Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] #301: render data model schema #303

Merged
merged 8 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@iroha2:registry=https://nexus.iroha.tech/repository/npm-group/
16 changes: 15 additions & 1 deletion .vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ function getNav(): DefaultTheme.NavItem[] {
link: '/',
activeMatch: '^/$|^/guide/',
},
{
text: 'Schema',
link: '/data-model-schema/',
activeMatch: '^/data-model-schema/',
},
]
}

function getGuideSidebar(): DefaultTheme.SidebarGroup[] {
function getGuideSidebar(): DefaultTheme.SidebarItem[] {
return [
{
text: 'Getting started',
Expand Down Expand Up @@ -370,6 +375,15 @@ export default defineConfig({

sidebar: {
'/guide/': getGuideSidebar(),
'/data-model-schema': [
{
text: 'Channel',
items: ['stable', 'lts', 'dev'].map((channel) => ({
link: `/data-model-schema/${channel}`,
text: `iroha2-${channel}`,
})),
},
],
'/': getGuideSidebar(),
},
nav: getNav(),
Expand Down
24 changes: 24 additions & 0 deletions etc/meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* hyperledger/iroha#iroha2-stable
*/
export const IROHA_REV_STABLE = 'c4af68c4f7959b154eb5380aa93c894e2e63fe4e'

/**
* hyperledger/iroha#iroha2-dev
*/
export const IROHA_REV_DEV = '726f5eabf65a79ea618b4fce62a09cee7a5b13d1'

/**
* hyperledger/iroha#iroha2-lts
*/
export const IROHA_REV_LTS = '6e75248b84c73bf0415e1718024c75f406b5d354'

/**
* hyperledger/iroha-javascript#iroha2
*/
export const IROHA_JS_REV = 'd59fc767ddf0d1a66f5c6914a9be1560f614d791'

/**
* hyperledger/iroha-java#iroha2-dev
*/
export const IROHA_JAVA_REV_DEV = 'e176225f935cc7f976d17384191ef0c0043ca0f6'
159 changes: 159 additions & 0 deletions etc/render-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// FIXME fix the package, then update imports and dependencies
// https://github.com/hyperledger/iroha-javascript/issues/155
import type { RustTypeDefinitionVariant } from '@iroha2/data-model-schema/src/transform/types'
import { match, P } from 'ts-pattern'
// https://github.com/vuejs/vitepress/blob/b16340acbd3c60fee023daadb0ec5a0292060a1e/src/node/markdown/markdown.ts#L13
import { slugify } from '@mdit-vue/shared'

export type Segment = Exclude<RustTypeDefinitionVariant, { TupleStruct: unknown }>

export type Schema = Record<string, Segment>

function segmentHeading(content: string) {
return `## ${code(content)}`
}

function segmentPropNameOnly(prop: string) {
return `**${prop}:**`
}

function segmentProp(name: string, content: string) {
return `${segmentPropNameOnly(name)} ${content}`
}

function segmentType(type: string) {
return segmentProp('Type', type)
}

function joinDouble(...lines: string[]): string {
return lines.join('\n\n')
}

function tyMdLink(ty: string) {
return match(ty)
.with(
P.when((x: string): x is `u${number}` => /^u\d+$/.test(x)),
'bool',
'Bool',
'String',
(x) => `${code(x)}`,
)
.otherwise((ty) => `[${code(ty)}](#${slugify(ty)})`)
}

function code(content: string) {
return `\`${content}\``
}

function table(
cols: (string | { title: string; align?: 'left' | 'right' | 'center' })[],
rows: string[][],
options: { indent: string },
): string {
const { titles, aligns } = cols
.map<[string, string]>((x) =>
typeof x === 'string'
? [x, '---']
: [
x.title,
match(x.align)
.with('left', () => ':--')
.with('center', () => ':-:')
.with('right', () => '--:')
.with(undefined, () => '---')
.exhaustive(),
],
)
.reduce<{ titles: string[]; aligns: string[] }>(
(acc, [title, align]) => {
acc.titles.push(title)
acc.aligns.push(align)
return acc
},
{ titles: [], aligns: [] },
)

return [titles, aligns, ...rows].map((row) => `${options.indent}| ${row.join(' | ')} |`).join('\n')
}

function predicateNotFalse<T>(value: false | T): value is T {
return Boolean(value)
}

function renderSegment(segment: Segment, segmentName: string): string {
const heading = segmentHeading(segmentName)

const body = match<Segment, string>(segment)
.with({ Struct: P.select() }, ({ declarations }) =>
joinDouble(
segmentType('Struct'),
segmentPropNameOnly('Declarations'),
table(
[
{ title: 'Field name', align: 'right' },
{ title: 'Field value', align: 'left' },
],
declarations.map((x) => [code(x.name), tyMdLink(x.ty)]),
{ indent: ' ' },
),
),
)
.with({ Enum: P.select() }, ({ variants }) =>
joinDouble(
segmentType('Enum'),
segmentPropNameOnly('Variants'),
table(
[{ title: 'Variant name', align: 'right' }, { title: 'Variant value', align: 'left' }, 'Discriminant'],
variants.map((x) => [code(x.name), x.ty ? tyMdLink(x.ty) : `&mdash;`, String(x.discriminant)]),
{ indent: ' ' },
),
),
)
.with({ Tuple: P.select() }, ({ types }) =>
joinDouble(segmentType('Tuple'), segmentProp('Values', `(` + types.map((ty) => tyMdLink(ty)).join(', ') + `)`)),
)
.with({ Map: P.select() }, ({ key, value, sorted_by_key }) =>
joinDouble(
...[
segmentType('Map'),
segmentProp('Key', tyMdLink(key)),
segmentProp('Value', tyMdLink(value)),
sorted_by_key && segmentProp('Sorted by key', 'Yes'),
].filter(predicateNotFalse),
),
)
.with({ Vec: P.select() }, ({ ty, sorted }) =>
joinDouble(
...[
//
segmentType('Vec'),
segmentProp('Value', tyMdLink(ty)),
sorted && segmentProp('Sorted', 'Yes'),
].filter(predicateNotFalse),
),
)
.with({ Int: P.select() }, (str) => joinDouble(segmentType('Int'), segmentProp('Kind', str)))
.with({ FixedPoint: P.select() }, ({ base, decimal_places }) =>
joinDouble(
segmentType('Fixed Point'),
segmentProp('Base', code(base)),
segmentProp('Decimal places', String(decimal_places)),
),
)
.with({ Array: P.select() }, ({ ty, len }) =>
joinDouble(segmentType('Array'), segmentProp('Length', String(len)), segmentProp('Value', tyMdLink(ty))),
)
.with({ Option: P.select() }, (ty) => joinDouble(segmentType('Option'), segmentProp('Some', tyMdLink(ty))))
.with(P.string, (alias) => joinDouble(segmentType('Alias'), segmentProp('To', tyMdLink(alias))))
.exhaustive()

return joinDouble(heading, body)
}

/**
* Returns Markdown
*/
export function renderSchema(schema: Schema): string {
const entries = Object.entries(schema)
return joinDouble(...entries.map(([name, segment]) => renderSegment(segment, name)))
}
29 changes: 9 additions & 20 deletions etc/snippet_sources.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
import type { SnippetSourceDefinition } from './types'
import { rewriteMdLinks } from './util'

/**
* hyperledger/iroha#iroha2-stable
*/
const IROHA_REV_STABLE = 'c4af68c4f7959b154eb5380aa93c894e2e63fe4e'

/**
* hyperledger/iroha#iroha2-dev
*/
const IROHA_REV_DEV = '726f5eabf65a79ea618b4fce62a09cee7a5b13d1'

/**
* hyperledger/iroha-javascript#iroha2
*/
const IROHA_JS_REV = 'd59fc767ddf0d1a66f5c6914a9be1560f614d791'

/**
* hyperledger/iroha-java#iroha2-dev
*/
const IROHA_JAVA_REV_DEV = 'e176225f935cc7f976d17384191ef0c0043ca0f6'
import { IROHA_JAVA_REV_DEV, IROHA_REV_STABLE, IROHA_JS_REV, IROHA_REV_DEV, IROHA_REV_LTS } from './meta'

// *****

Expand Down Expand Up @@ -133,6 +114,14 @@ export default [
// remove the title header (`# ...`)
.then((x) => x.replace(/# .+\n/m, '')),
},
...(['dev', 'lts', 'stable'] as const).map<SnippetSourceDefinition>((channel) => {
const revision = ({ dev: IROHA_REV_DEV, lts: IROHA_REV_LTS, stable: IROHA_REV_STABLE } as const)[channel]

return {
src: `https://raw.githubusercontent.com/hyperledger/iroha/${revision}/docs/source/references/schema.json`,
filename: `data-model-schema.${channel}.json`,
}
}),
{
src: './src/example_code/lorem.rs',
},
Expand Down
33 changes: 19 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,38 @@
"cli": "tsx etc/cli"
},
"devDependencies": {
"@iroha2/data-model-schema": "^5.0.0",
"@mdit-vue/shared": "^0.12.0",
"@scale-codec/definition-compiler": "^4.0.1",
"@types/debug": "^4.1.7",
"@types/markdown-it": "^12.2.3",
"@types/node": "^18.14.2",
"@types/yargs": "^17.0.17",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.53.0",
"@types/node": "^18.15.11",
"@types/yargs": "^17.0.24",
"@typescript-eslint/eslint-plugin": "^5.57.0",
"@typescript-eslint/parser": "^5.57.0",
"case": "^1.6.3",
"chalk": "^4",
"del": "^7.0.0",
"eslint": "^8.35.0",
"eslint-plugin-vue": "^9.9.0",
"eslint": "^8.37.0",
"eslint-plugin-vue": "^9.10.0",
"log-update": "^5.0.1",
"make-dir": "^3.1.0",
"markdown-it": "^13.0.1",
"markdown-it-footnote": "^3.0.3",
"node-fetch": "^3.3.0",
"prettier": "^2.8.4",
"prettier": "^2.8.7",
"prettier-eslint": "^15.0.1",
"prettier-eslint-cli": "^7.1.0",
"sass": "^1.56.1",
"ts-pattern": "^4.0.6",
"tsx": "^3.12.1",
"typescript": "4.9.5",
"vite": "^4.1.4",
"vite-plugin-pwa": "^0.14.4",
"ts-pattern": "^4.2.2",
"tsx": "^3.12.6",
"typescript": "5.0.3",
"vite": "^4.2.1",
"vite-plugin-pwa": "^0.14.7",
"vite-plugin-windicss": "^1.8.10",
"vite-svg-loader": "^4.0.0",
"vitepress": "1.0.0-alpha.48",
"vitest": "^0.29.1",
"vitepress": "1.0.0-alpha.64",
"vitest": "^0.29.8",
"windicss": "^3.5.6",
"yargs": "^17.6.2"
},
Expand Down