@amritk/generate-examples 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generators/build-schema.d.ts +3 -1
- package/dist/generators/build-schema.d.ts.map +1 -0
- package/dist/generators/build-schema.js +44 -0
- package/dist/generators/collect-example-imports.d.ts +1 -0
- package/dist/generators/collect-example-imports.d.ts.map +1 -0
- package/dist/generators/collect-example-imports.js +88 -0
- package/dist/generators/derive-example.d.ts +1 -0
- package/dist/generators/derive-example.d.ts.map +1 -0
- package/dist/generators/derive-example.js +137 -0
- package/dist/generators/generate-arbitrary.d.ts +1 -0
- package/dist/generators/generate-arbitrary.d.ts.map +1 -0
- package/dist/generators/generate-arbitrary.js +165 -0
- package/dist/generators/generate-files.d.ts +1 -0
- package/dist/generators/generate-files.d.ts.map +1 -0
- package/dist/generators/generate-files.js +41 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -1353
- package/package.json +6 -6
- package/src/generators/build-schema.ts +14 -79
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amritk/generate-examples",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Generate fast-check arbitraries and example values from JSON Schemas.",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -33,23 +33,23 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
|
-
"build": "
|
|
37
|
-
"
|
|
38
|
-
"
|
|
36
|
+
"build": "tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f",
|
|
37
|
+
"types:check": "tsgo -p . --noEmit",
|
|
38
|
+
"test": "NODE_ENV=production vitest run --root ../.. generate-examples"
|
|
39
39
|
},
|
|
40
40
|
"imports": {
|
|
41
41
|
"#generators/*": "./src/generators/*.ts"
|
|
42
42
|
},
|
|
43
43
|
"exports": {
|
|
44
44
|
".": {
|
|
45
|
-
"
|
|
45
|
+
"development": "./src/index.ts",
|
|
46
46
|
"default": "./dist/index.js",
|
|
47
47
|
"types": "./dist/index.d.ts"
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"json-schema-typed": "^8.0.1",
|
|
52
|
-
"@amritk/helpers": "0.
|
|
52
|
+
"@amritk/helpers": "0.7.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"fast-check": ">=3"
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { refToFilename } from '@amritk/helpers/ref-to-filename'
|
|
4
|
-
import { refToName } from '@amritk/helpers/ref-to-name'
|
|
5
|
-
import { resolveDynamicRefs } from '@amritk/helpers/resolve-dynamic-refs'
|
|
6
|
-
import { resolveRef } from '@amritk/helpers/resolve-ref'
|
|
7
|
-
import { upgradeDraft07Schema } from '@amritk/helpers/upgrade-draft07-schema'
|
|
1
|
+
import { generateIndexBarrel } from '@amritk/helpers/generate-index-barrel'
|
|
2
|
+
import { walkRefGraph } from '@amritk/helpers/walk-ref-graph'
|
|
8
3
|
import type { JSONSchema } from 'json-schema-typed/draft-2020-12'
|
|
9
4
|
|
|
10
5
|
import { generateExampleFile } from './generate-files'
|
|
@@ -19,7 +14,8 @@ export type GeneratedFile = {
|
|
|
19
14
|
|
|
20
15
|
/**
|
|
21
16
|
* Builds all TypeScript example files from a JSON Schema by traversing all
|
|
22
|
-
*
|
|
17
|
+
* `$ref` / `$dynamicRef` references recursively (via the shared
|
|
18
|
+
* `@amritk/helpers/walk-ref-graph` walker).
|
|
23
19
|
*
|
|
24
20
|
* Each generated file exports:
|
|
25
21
|
* - A TypeScript type definition
|
|
@@ -45,83 +41,22 @@ export const buildExampleSchema = async (
|
|
|
45
41
|
rootTypeName: string,
|
|
46
42
|
typeSuffix = '',
|
|
47
43
|
): Promise<GeneratedFile[]> => {
|
|
48
|
-
rootSchema = upgradeDraft07Schema(rootSchema as Record<string, unknown>) as JSONSchema
|
|
49
|
-
|
|
50
44
|
const files: GeneratedFile[] = []
|
|
51
|
-
const processedRefs = new Set<string>()
|
|
52
|
-
const processedFilenames = new Set<string>()
|
|
53
|
-
const refsToProcess: string[] = []
|
|
54
|
-
|
|
55
|
-
const dynamicRefMap = buildDynamicRefMap(rootSchema)
|
|
56
|
-
|
|
57
|
-
// Root schema
|
|
58
|
-
const processedRootSchema = resolveDynamicRefs(rootSchema, dynamicRefMap)
|
|
59
|
-
const rootContent = generateExampleFile(processedRootSchema, rootTypeName, {
|
|
60
|
-
rootSchema: rootSchema as Record<string, unknown>,
|
|
61
|
-
typeSuffix,
|
|
62
|
-
})
|
|
63
|
-
const rootFilename = rootTypeName.toLowerCase()
|
|
64
45
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
46
|
+
walkRefGraph(rootSchema, rootTypeName, { typeSuffix }, (node) => {
|
|
47
|
+
// `index` is reserved for the barrel below, so never let a definition of
|
|
48
|
+
// that name overwrite it.
|
|
49
|
+
if (node.filename === 'index') return
|
|
69
50
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
while (refsToProcess.length > 0) {
|
|
74
|
-
const ref = refsToProcess.shift()
|
|
75
|
-
if (!ref || processedRefs.has(ref)) continue
|
|
76
|
-
processedRefs.add(ref)
|
|
77
|
-
|
|
78
|
-
const resolvedSchema = resolveRef(ref, rootSchema as Record<string, unknown>)
|
|
79
|
-
if (!resolvedSchema) {
|
|
80
|
-
console.warn(`Warning: Could not resolve ref: ${ref}`)
|
|
81
|
-
continue
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const typeName = refToName(ref, typeSuffix)
|
|
85
|
-
const filename = refToFilename(ref)
|
|
86
|
-
const processedSchema = resolveDynamicRefs(resolvedSchema as JSONSchema, dynamicRefMap)
|
|
87
|
-
const content = generateExampleFile(processedSchema, typeName, {
|
|
88
|
-
selfRef: ref,
|
|
89
|
-
rootSchema: rootSchema as Record<string, unknown>,
|
|
51
|
+
const content = generateExampleFile(node.schema, node.typeName, {
|
|
52
|
+
rootSchema: node.rootSchema,
|
|
90
53
|
typeSuffix,
|
|
54
|
+
...(node.ref !== undefined ? { selfRef: node.ref } : {}),
|
|
91
55
|
})
|
|
56
|
+
files.push({ filename: `${node.filename}.ts`, content })
|
|
57
|
+
})
|
|
92
58
|
|
|
93
|
-
|
|
94
|
-
processedFilenames.add(filename)
|
|
95
|
-
files.push({ filename: `${filename}.ts`, content })
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
for (const nestedRef of extractRefs(resolvedSchema as JSONSchema)) {
|
|
99
|
-
if (!processedRefs.has(nestedRef)) refsToProcess.push(nestedRef)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Generate index.ts barrel
|
|
104
|
-
const TYPE_EXPORT_RE = /^export type (\w+)/gm
|
|
105
|
-
const CONST_EXPORT_RE = /^export const (\w+)/gm
|
|
106
|
-
|
|
107
|
-
const sortedFiles = [...files].sort((a, b) => a.filename.localeCompare(b.filename))
|
|
108
|
-
let indexContent = ''
|
|
109
|
-
|
|
110
|
-
for (const file of sortedFiles) {
|
|
111
|
-
const moduleName = file.filename.replace(/\.ts$/, '')
|
|
112
|
-
const typeNames: string[] = []
|
|
113
|
-
const constNames: string[] = []
|
|
114
|
-
|
|
115
|
-
for (const match of file.content.matchAll(TYPE_EXPORT_RE)) typeNames.push(match[1] as string)
|
|
116
|
-
for (const match of file.content.matchAll(CONST_EXPORT_RE)) constNames.push(match[1] as string)
|
|
117
|
-
|
|
118
|
-
if (typeNames.length === 0 && constNames.length === 0) continue
|
|
119
|
-
|
|
120
|
-
const typeExports = typeNames.map((n) => `type ${n}`)
|
|
121
|
-
indexContent += `export { ${[...typeExports, ...constNames].join(', ')} } from './${moduleName}';\n`
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
files.push({ filename: 'index.ts', content: indexContent })
|
|
59
|
+
files.push({ filename: 'index.ts', content: generateIndexBarrel(files) })
|
|
125
60
|
|
|
126
61
|
return files
|
|
127
62
|
}
|