@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amritk/generate-examples",
3
- "version": "0.1.1",
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": "bun run build:code && bun run build:types",
37
- "build:code": "bun build ./src/index.ts --outdir=dist --target=node",
38
- "build:types": "tsc -p ."
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
- "bun": "./src/index.ts",
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.6.2"
52
+ "@amritk/helpers": "0.7.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "fast-check": ">=3"
@@ -1,10 +1,5 @@
1
- import { buildDynamicRefMap } from '@amritk/helpers/build-dynamic-ref-map'
2
- import { extractRefs } from '@amritk/helpers/extract-refs'
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
- * $ref references recursively, mirroring the generate-parsers pipeline.
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
- if (rootFilename !== 'index') {
66
- processedFilenames.add(rootFilename)
67
- files.push({ filename: `${rootFilename}.ts`, content: rootContent })
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
- const rootRefs = extractRefs(rootSchema)
71
- refsToProcess.push(...rootRefs)
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
- if (filename !== 'index' && !processedFilenames.has(filename)) {
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
  }