diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 3eff258..0e6943b 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -21,7 +21,7 @@ export default async () => { const autogenerated = [generateRpcDocs, generateWebClientDocs] await Promise.all(autogenerated.map(fn => fn())) - return withPwa(defineConfig({ + return defineConfig({ base: baseUrl, title: pkg.title, srcExclude: ['**/README.md'], @@ -128,53 +128,53 @@ export default async () => { ['meta', { name: 'twitter:creator', content: '@nimiq' }], ['meta', { name: 'twitter:title', content: pkg.title }], ], - pwa: { - mode: env.DEPLOYMENT_ENV !== 'production' ? 'development' : 'production', - disable: env.DEPLOYMENT_ENV === 'development', - scope: baseUrl, - registerType: 'autoUpdate', - injectRegister: 'script-defer', - includeAssets: [`${baseUrl}favicons/favicon.svg`], - manifest: { - name: pkg.title, - short_name: pkg.title, - theme_color: '#ffffff', - icons: [ - { - src: `${baseUrl}favicons/nimiq-hexagon-192.png`, - sizes: '192x192', - type: 'image/png', - }, - { - src: `${baseUrl}favicons/nimiq-hexagon-512.png`, - sizes: '512x512', - type: 'image/png', - }, - { - src: `${baseUrl}favicons/nimiq-hexagon-512.png`, - sizes: '512x512', - type: 'image/png', - purpose: 'any maskable', - }, - ], - }, - workbox: { - globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'], - }, - experimental: { - includeAllowlist: true, - }, - devOptions: { - enabled: env.DEPLOYMENT_ENV === 'production', - type: 'module', - suppressWarnings: true, - navigateFallback: '/', - }, - }, + // pwa: { + // mode: env.DEPLOYMENT_ENV !== 'production' ? 'development' : 'production', + // disable: env.DEPLOYMENT_ENV !== 'production', + // scope: baseUrl, + // registerType: 'autoUpdate', + // injectRegister: 'script-defer', + // includeAssets: [`${baseUrl}favicons/favicon.svg`], + // manifest: { + // name: pkg.title, + // short_name: pkg.title, + // theme_color: '#ffffff', + // icons: [ + // { + // src: `${baseUrl}favicons/nimiq-hexagon-192.png`, + // sizes: '192x192', + // type: 'image/png', + // }, + // { + // src: `${baseUrl}favicons/nimiq-hexagon-512.png`, + // sizes: '512x512', + // type: 'image/png', + // }, + // { + // src: `${baseUrl}favicons/nimiq-hexagon-512.png`, + // sizes: '512x512', + // type: 'image/png', + // purpose: 'any maskable', + // }, + // ], + // }, + // workbox: { + // globPatterns: ['**/*.{css,js,html,svg,png,ico,txt,woff2}'], + // }, + // experimental: { + // includeAllowlist: true, + // }, + // devOptions: { + // enabled: env.DEPLOYMENT_ENV === 'production', + // type: 'module', + // suppressWarnings: true, + // navigateFallback: '/', + // }, + // }, sitemap: { hostname: 'https://onmax.github.io', }, - })) + }) } diff --git a/.vitepress/scripts/rpc-docs.ts b/.vitepress/scripts/rpc-docs.ts index 6b11bc0..8ea6703 100644 --- a/.vitepress/scripts/rpc-docs.ts +++ b/.vitepress/scripts/rpc-docs.ts @@ -36,12 +36,13 @@ export async function generateRpcDocs() { // Build folder const buildFolder = join(__dirname, '../../build/rpc-docs') // Read package version of generated docs, if already built - const versionFile = join(buildFolder, '/_version') + const methodFile = join(buildFolder, '/method.md') - if (existsSync(versionFile)) { - const generatedVersion = readFileSync(versionFile, 'utf-8') - - // Skip build if package version and generated version match + if (existsSync(methodFile)) { + const re = /## Version: (\.*)/ + const content = readFileSync(methodFile, 'utf-8') + const generatedVersion = re.exec(content)?.[1] + consola.info(`RPC specification docs ${packageVersion} already generated`) if (packageVersion === generatedVersion) { consola.info(`RPC specification docs ${packageVersion} already generated`) return @@ -56,91 +57,173 @@ export async function generateRpcDocs() { methodsMd.push(addHeader('h2', `Version: ${spec.info.version}`)) methodsMd.push(`[Download RPC definition](https://github.com/nimiq/core-rs-albatross/releases/latest)`) + // - passphrase*: `String` + // Returns: [ReturnAccount](#returnaccount) + const template = ` +
+
+ +### {{ methodName }} + +Parameters{.label .text-12 .text-neutral-800} + +{{ parameters }} + +Returns{.label .text-12 .text-neutral-800} + +{{ returns }} + +
+ +
+ +::: code-group + +\`\`\`JavaScript +const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: '{"jsonrpc":"2.0","method":"{{ methodName }}","params":[{{ parametersValues }}],"id":1}' +}; + +fetch('http://127.0.0.1:8648', options) + .then(response => response.json()) + .then(response => console.log(response)) + .catch(err => console.error(err)); +\`\`\` + +\`\`\`Shell +curl --request POST \n + --url http://127.0.0.1:8648 \n + --header 'Content-Type: application/json' \n + --data '{ + "jsonrpc": "2.0", + "method": "{{ methodName }}", + "params": [{{ parametersValues }}], + "id": 1 + }' +\`\`\` +::: + +
+
+`.trim() + + function paramToValue(param: any) { + switch (param.schema.type) { + case 'string': return `"${param.name}"` + case 'number': return '0' + case 'boolean': return 'false' + default: return '""' + } + } + methodsMd.push(addHeader('h2', 'Methods')) for (const method of spec.methods) { - methodsMd.push(addHeader('h3', method.name)) - - // Method parameters - methodsMd.push(addParagraph('Parameters:')) - if (method.params.length === 0) - methodsMd.push(addParagraph('*None*')) - else - methodsMd.push(methodParamsToTable(method)) - - // Method result - if ('$ref' in method.result.schema) { - const ref = method.result.schema.$ref.split('/').pop() - methodsMd.push(addParagraph(`Returns: [${ref}](#${ref.toLowerCase()})`)) + const parameters = method.params.map(param => `- ${param.name}${param.required ? '*' : ''}: \`${param.schema.type}\``).join('\n') + + const parametersValues = method.params.map(paramToValue).join(', ') + + let resultProperties = '' + const returnsObject = '$ref' in method.result.schema + if (returnsObject) { + const { /* title, description, */ required, properties } = spec.components.schemas[method.result.schema.$ref.split('/').at(-1)] + resultProperties = Object.values(properties).map(({ title, type }) => `- ${title}${required.includes(title) ? '*' : ''}: \`${type}\``).join('\n') } else { - if (method.result.schema.type !== 'array') { - methodsMd.push(addParagraph(`Returns: ${firstCharToUpper(method.result.schema.type)}`)) - } - else { - if ('$ref' in method.result.schema.items) { - const ref = method.result.schema.items.$ref.split('/').pop() - methodsMd.push(addParagraph(`Returns: Array< [${ref}](#${ref.toLowerCase()}) >`)) - } - else { - methodsMd.push(addParagraph(`Returns: Array< ${firstCharToUpper(method.result.schema.items.type)} >`)) - } - } + resultProperties = `- \`${method.result.schema.type}\`` } + const tmp = template + .replaceAll('{{ methodName }}', method.name) + .replaceAll('{{ parameters }}', parameters) + .replaceAll('{{ parametersValues }}', parametersValues) + .replaceAll('{{ returns }}', resultProperties) + + methodsMd.push(tmp) } + // Method parameters + // methodsMd.push(addParagraph('Parameters{.subline .text-neutral-800 .text-12}')) + // if (method.params.length === 0) + // methodsMd.push(addParagraph('*None*')) + // else + // methodsMd.push(methodParamsToTable(method)) + + // Method result + // if ('$ref' in method.result.schema) { + // const ref = method.result.schema.$ref.split('/').pop() + // methodsMd.push(addParagraph(`Returns: [${ref}](#${ref.toLowerCase()})`)) + // } + // else { + // if (method.result.schema.type !== 'array') { + // methodsMd.push(addParagraph(`Returns: ${firstCharToUpper(method.result.schema.type)} `)) + // } + // else { + // if ('$ref' in method.result.schema.items) { + // const ref = method.result.schema.items.$ref.split('/').pop() + // methodsMd.push(addParagraph(`Returns: Array < [${ref}](#${ref.toLowerCase()}) > `)) + // } + // else { + // methodsMd.push(addParagraph(`Returns: Array < ${firstCharToUpper(method.result.schema.items.type)} > `)) + // } + // } + // } + // Schemas section - const schemasMd = [] - schemasMd.push(addHeader('h2', 'Schemas')) - for (const schema of Object.values(spec.components.schemas)) { - schemasMd.push(addHeader('h3', (schema as any).title)) - schemasMd.push(schemaPropertiesToTable(schema)) - } + // const schemasMd = [] + // schemasMd.push(addHeader('h2', 'Schemas')) + // for (const schema of Object.values(spec.components.schemas)) { + // schemasMd.push(addHeader('h3', (schema as any).title)) + // schemasMd.push(schemaPropertiesToTable(schema)) + // } // Verify that destination folder exists if (!existsSync(buildFolder)) mkdirSync(buildFolder) writeFileSync(join(__dirname, '../../build/rpc-docs/methods.md'), json2md(methodsMd)) - writeFileSync(join(__dirname, '../../build/rpc-docs/schemas.md'), json2md(schemasMd)) + // writeFileSync(join(__dirname, '../../build/rpc-docs/schemas.md'), json2md(schemasMd)) } function addHeader(size: string, text: string) { return { [size]: text } } -function addParagraph(text: string) { - return { p: text } -} - -function firstCharToUpper(string: string) { - return string.charAt(0).toUpperCase() + string.slice(1) -} - -function schemaPropertiesToTable(schema: any) { - const table = { table: { headers: ['Name', 'Type', 'Required'], rows: [] } } - const requiredProps = Object.entries(schema.required).map(prop => prop[1]) - - Object.entries(schema.properties) - .map(obj => obj[1]) - .forEach((prop: any) => { - // Check if we are dealing with a type or a reference to a schema - let type: string - if (!prop.type && prop.$ref) { - const ref = prop.$ref.split('/').pop() - type = `[${ref}](#${ref.toLowerCase()})` - } - else { type = prop.type } - - const isPropRequired = requiredProps.find(reqProp => reqProp === prop.title) - table.table.rows.push([prop.title, firstCharToUpper(type), isPropRequired ? 'Yes' : 'No']) - }) - return table -} - -function methodParamsToTable(method: any) { - const table = { table: { headers: ['Name', 'Type', 'Required'], rows: [] } } - method.params.forEach((param: any) => { - table.table.rows.push([param.name, firstCharToUpper(param.schema.type), param.required ? 'Yes' : 'No']) - }) - return table -} +// function addParagraph(text: string) { +// return { p: text } +// } + +// function firstCharToUpper(string: string) { +// return string.charAt(0).toUpperCase() + string.slice(1) +// } + +// function schemaPropertiesToTable(schema: any) { +// const table = { table: { headers: ['Name', 'Type', 'Required'], rows: [] } } +// const requiredProps = Object.entries(schema.required).map(prop => prop[1]) + +// Object.entries(schema.properties) +// .map(obj => obj[1]) +// .forEach((prop: any) => { +// // Check if we are dealing with a type or a reference to a schema +// let type: string +// if (!prop.type && prop.$ref) { +// const ref = prop.$ref.split('/').pop() +// type = `[${ref}](#${ref.toLowerCase()})` +// } +// else { type = prop.type } + +// const isPropRequired = requiredProps.find(reqProp => reqProp === prop.title) +// table.table.rows.push([prop.title, firstCharToUpper(type), isPropRequired ? 'Yes' : 'No']) +// }) +// return table +// } + +// function methodParamsToTable(method: any) { +// const table = { table: { headers: ['Name', 'Type', 'Required'], rows: [] } } +// method.params.forEach((param: any) => { +// table.table.rows.push([param.name, firstCharToUpper(param.schema.type), param.required ? 'Yes' : 'No']) +// }) +// return table +// } diff --git a/.vitepress/theme/MainLayout.vue b/.vitepress/theme/MainLayout.vue index 3c78124..0575c2a 100644 --- a/.vitepress/theme/MainLayout.vue +++ b/.vitepress/theme/MainLayout.vue @@ -1,10 +1,10 @@