@prisma-next/ts-render 0.5.0-dev.9 → 0.5.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/json-to-ts-source.ts","../src/ts-expression.ts","../src/render-imports.ts"],"sourcesContent":[],"mappings":";;AAiBA;AACA;AAUA;;;;ACjBA;AAeA;;;;ACDA;;;;KFRY,SAAA,+CAAwD,cAAc;KACtE,UAAA;0BAAuC;;;;;;;;;;iBAUnC,cAAA;;;;AAXhB;AACA;AAUA;;;;ACjBA;AAeA;;;UAfiB,iBAAA;ECcD,SAAA,eAAa,EAAA,MAAwB;;;wBDV7B,SAAS;;;;;;;;;;uBAWX,YAAA;;0CAEoB;;;;ADX1C;AACA;AAUA;;;;ACjBA;AAeA;;;;ACDA;;;;;;;;;;;;iBAAgB,aAAA,wBAAqC"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/json-to-ts-source.ts","../src/ts-expression.ts","../src/render-imports.ts"],"mappings":";;AAiBA;;;;;AACA;;;;;AAUA;;;;;KAXY,SAAA,+CAAwD,SAAA,KAAc,UAAA;AAAA,KACtE,UAAA;EAAA,UAAyB,GAAA,WAAc,SAAA;AAAA;;;;;;;;;iBAUnC,cAAA,CAAe,KAAA;;;;AAX/B;;;;;AACA;;;;;UCPiB,iBAAA;EAAA,SACN,eAAA;EAAA,SACA,MAAA;EAAA,SACA,IAAA;EAAA,SACA,UAAA,GAAa,QAAA,CAAS,MAAA;AAAA;;;AAJjC;;;;;;uBAesB,YAAA;EAAA,SACX,gBAAA,CAAA;EAAA,SACA,kBAAA,CAAA,YAA+B,iBAAA;AAAA;;;ADX1C;;;;;AACA;;;;;AAUA;;;;;;;;ACjBA;;;;;ADMA,iBEQgB,aAAA,CAAc,YAAA,WAAuB,iBAAA"}
package/dist/index.mjs CHANGED
@@ -33,7 +33,6 @@ function renderKey(key) {
33
33
  if (key === "__proto__") return JSON.stringify(key);
34
34
  return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
35
35
  }
36
-
37
36
  //#endregion
38
37
  //#region src/render-imports.ts
39
38
  /**
@@ -129,7 +128,6 @@ function buildAttributesClause(attrs) {
129
128
  if (entries.length === 0) return "";
130
129
  return ` with { ${entries.join(", ")} }`;
131
130
  }
132
-
133
131
  //#endregion
134
132
  //#region src/ts-expression.ts
135
133
  /**
@@ -141,7 +139,7 @@ function buildAttributesClause(attrs) {
141
139
  * deduplicated import block.
142
140
  */
143
141
  var TsExpression = class {};
144
-
145
142
  //#endregion
146
143
  export { TsExpression, jsonToTsSource, renderImports };
144
+
147
145
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/json-to-ts-source.ts","../src/render-imports.ts","../src/ts-expression.ts"],"sourcesContent":["/**\n * Pure JSON-to-TypeScript-source printer.\n *\n * This module is the second stage of the codec → TS pipeline:\n *\n * jsValue → codec.encodeJson → JsonValue → jsonToTsSource → TS source text\n *\n * Stage 1 (`codec.encodeJson`) is a codec responsibility — date serialization,\n * opaque domain types (vector, bigint, uuid), JSON canonicalization. Stage 2\n * (this module) is a pure JSON-to-TS printer that must never grow type-specific\n * branches.\n *\n * To render a non-JSON JS value (Date, Vector, BigInt, Buffer, …), encode it\n * through the relevant codec's `encodeJson` first. Adding special cases to\n * this file is not the answer — that's what codecs are for.\n */\n\nexport type JsonValue = string | number | boolean | null | readonly JsonValue[] | JsonObject;\nexport type JsonObject = { readonly [key: string]: JsonValue | undefined };\n\n/**\n * Render a JSON-compatible value as a TypeScript source-text literal.\n *\n * Accepts `unknown` for ergonomics with structural types (e.g. `ColumnSpec`,\n * `ForeignKeySpec`) whose fields are all JSON-compatible but whose interfaces\n * lack the index signature TypeScript requires for `JsonObject` assignability.\n * Non-JSON values (Date, Symbol, Function, etc.) throw at runtime.\n */\nexport function jsonToTsSource(value: unknown): string {\n if (value === undefined) return 'undefined';\n if (value === null) return 'null';\n if (typeof value === 'string') return JSON.stringify(value);\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const items = value.map((v: unknown) => jsonToTsSource(v));\n const singleLine = `[${items.join(', ')}]`;\n if (singleLine.length <= 80) return singleLine;\n return `[\\n${items.map((i) => ` ${i}`).join(',\\n')},\\n]`;\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value).filter(([, v]) => v !== undefined);\n if (entries.length === 0) return '{}';\n const items = entries.map(([k, v]) => `${renderKey(k)}: ${jsonToTsSource(v)}`);\n const singleLine = `{ ${items.join(', ')} }`;\n if (singleLine.length <= 80) return singleLine;\n return `{\\n${items.map((i) => ` ${i}`).join(',\\n')},\\n}`;\n }\n throw new Error(`jsonToTsSource: unsupported value type \"${typeof value}\"`);\n}\n\nfunction renderKey(key: string): string {\n if (key === '__proto__') return JSON.stringify(key);\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);\n}\n","import type { ImportRequirement } from './ts-expression';\n\n/**\n * Render an aggregated `import` block from a flat list of\n * `ImportRequirement`s. Each target's migration renderer collects\n * requirements polymorphically from its call nodes and pipes them here.\n *\n * The emitter invariants:\n *\n * - **One line per module specifier.** Named imports are aggregated and\n * emitted sorted alphabetically; a single default symbol is combined\n * onto the same line when attributes agree (`import def, { a, b } from \"m\";`).\n * - **At most one default symbol per module.** Two conflicting default\n * symbols on the same specifier throw — the user's renderer can't\n * guess which one they meant.\n * - **Attribute unanimity per module.** All requirements for the same\n * module specifier must carry the same (or no) `attributes` map.\n * Divergent attribute maps throw — they can't collapse to one line\n * and there's no user-resolvable recovery at this layer.\n * - **Deterministic ordering.** Modules are emitted sorted by specifier;\n * within a module, named symbols are emitted sorted alphabetically.\n *\n * Returns a string containing one import line per module, joined by `\\n`\n * (no trailing newline). An empty requirement list returns `\"\"`.\n */\nexport function renderImports(requirements: readonly ImportRequirement[]): string {\n const byModule = aggregateByModule(requirements);\n const entries = [...byModule.entries()].sort(([a], [b]) => a.localeCompare(b));\n return entries\n .map(([moduleSpecifier, group]) => renderModuleImport(moduleSpecifier, group))\n .join('\\n');\n}\n\ninterface ModuleImportGroup {\n readonly named: Set<string>;\n defaultSymbol: string | null;\n attributes: Readonly<Record<string, string>> | null;\n attributesSet: boolean;\n}\n\nfunction aggregateByModule(\n requirements: readonly ImportRequirement[],\n): Map<string, ModuleImportGroup> {\n const byModule = new Map<string, ModuleImportGroup>();\n for (const req of requirements) {\n let group = byModule.get(req.moduleSpecifier);\n if (!group) {\n group = { named: new Set(), defaultSymbol: null, attributes: null, attributesSet: false };\n byModule.set(req.moduleSpecifier, group);\n }\n mergeRequirementIntoGroup(req, group);\n }\n return byModule;\n}\n\nfunction mergeRequirementIntoGroup(req: ImportRequirement, group: ModuleImportGroup): void {\n const kind = req.kind ?? 'named';\n if (kind === 'default') {\n if (group.defaultSymbol !== null && group.defaultSymbol !== req.symbol) {\n throw new Error(\n `Conflicting default imports for module \"${req.moduleSpecifier}\": ` +\n `\"${group.defaultSymbol}\" and \"${req.symbol}\". Only one default symbol is allowed per module.`,\n );\n }\n group.defaultSymbol = req.symbol;\n } else {\n group.named.add(req.symbol);\n }\n mergeAttributes(req, group);\n}\n\nfunction mergeAttributes(req: ImportRequirement, group: ModuleImportGroup): void {\n const incoming = req.attributes ?? null;\n if (!group.attributesSet) {\n group.attributes = incoming;\n group.attributesSet = true;\n return;\n }\n if (!attributesEqual(group.attributes, incoming)) {\n throw new Error(\n `Conflicting import attributes for module \"${req.moduleSpecifier}\": ` +\n `${stringifyAttributes(group.attributes)} vs ${stringifyAttributes(incoming)}.`,\n );\n }\n}\n\nfunction attributesEqual(\n a: Readonly<Record<string, string>> | null,\n b: Readonly<Record<string, string>> | null,\n): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n const aKeys = Object.keys(a).sort();\n const bKeys = Object.keys(b).sort();\n if (aKeys.length !== bKeys.length) return false;\n for (let i = 0; i < aKeys.length; i++) {\n const key = aKeys[i];\n if (key !== bKeys[i]) return false;\n if (a[key as string] !== b[key as string]) return false;\n }\n return true;\n}\n\nfunction stringifyAttributes(attrs: Readonly<Record<string, string>> | null): string {\n if (attrs === null) return '(none)';\n const entries = Object.entries(attrs)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}: ${JSON.stringify(v)}`);\n return `{ ${entries.join(', ')} }`;\n}\n\nfunction renderModuleImport(moduleSpecifier: string, group: ModuleImportGroup): string {\n const clause = buildImportClause(group);\n const attrs = buildAttributesClause(group.attributes);\n return `import ${clause} from '${moduleSpecifier}'${attrs};`;\n}\n\nfunction buildImportClause(group: ModuleImportGroup): string {\n const named = [...group.named].sort();\n const hasNamed = named.length > 0;\n const hasDefault = group.defaultSymbol !== null;\n if (hasDefault && hasNamed) {\n return `${group.defaultSymbol}, { ${named.join(', ')} }`;\n }\n if (hasDefault) {\n return group.defaultSymbol as string;\n }\n return `{ ${named.join(', ')} }`;\n}\n\nfunction buildAttributesClause(attrs: Readonly<Record<string, string>> | null): string {\n if (attrs === null) return '';\n const entries = Object.entries(attrs)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}: ${JSON.stringify(v)}`);\n if (entries.length === 0) return '';\n return ` with { ${entries.join(', ')} }`;\n}\n","/**\n * Declarative contribution to the `import` block of a rendered TypeScript\n * source file. Each node in an IR declares which symbols it needs from which\n * modules; the top-level renderer deduplicates across nodes and emits one\n * `import { a, b, c } from \"…\"` line per module.\n *\n * `kind` defaults to `\"named\"` (e.g. `import { a } from \"m\"`). Setting it to\n * `\"default\"` emits `import a from \"m\"`. `attributes`, if provided, emits an\n * import attributes clause (`with { type: \"json\" }`) verbatim — required for\n * JSON module imports in the rendered scaffolds.\n */\nexport interface ImportRequirement {\n readonly moduleSpecifier: string;\n readonly symbol: string;\n readonly kind?: 'named' | 'default';\n readonly attributes?: Readonly<Record<string, string>>;\n}\n\n/**\n * Abstract base class for any IR node that can be emitted as a TypeScript\n * expression and declare its own import requirements.\n *\n * A top-level renderer walks an array of these polymorphically, concatenates\n * `renderTypeScript()` results, and aggregates `importRequirements()` into a\n * deduplicated import block.\n */\nexport abstract class TsExpression {\n abstract renderTypeScript(): string;\n abstract importRequirements(): readonly ImportRequirement[];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/json-to-ts-source.ts","../src/render-imports.ts","../src/ts-expression.ts"],"sourcesContent":["/**\n * Pure JSON-to-TypeScript-source printer.\n *\n * This module is the second stage of the codec → TS pipeline:\n *\n * jsValue → codec.encodeJson → JsonValue → jsonToTsSource → TS source text\n *\n * Stage 1 (`codec.encodeJson`) is a codec responsibility — date serialization,\n * opaque domain types (vector, bigint, uuid), JSON canonicalization. Stage 2\n * (this module) is a pure JSON-to-TS printer that must never grow type-specific\n * branches.\n *\n * To render a non-JSON JS value (Date, Vector, BigInt, Buffer, …), encode it\n * through the relevant codec's `encodeJson` first. Adding special cases to\n * this file is not the answer — that's what codecs are for.\n */\n\nexport type JsonValue = string | number | boolean | null | readonly JsonValue[] | JsonObject;\nexport type JsonObject = { readonly [key: string]: JsonValue | undefined };\n\n/**\n * Render a JSON-compatible value as a TypeScript source-text literal.\n *\n * Accepts `unknown` for ergonomics with structural types (e.g. `ColumnSpec`,\n * `ForeignKeySpec`) whose fields are all JSON-compatible but whose interfaces\n * lack the index signature TypeScript requires for `JsonObject` assignability.\n * Non-JSON values (Date, Symbol, Function, etc.) throw at runtime.\n */\nexport function jsonToTsSource(value: unknown): string {\n if (value === undefined) return 'undefined';\n if (value === null) return 'null';\n if (typeof value === 'string') return JSON.stringify(value);\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (Array.isArray(value)) {\n if (value.length === 0) return '[]';\n const items = value.map((v: unknown) => jsonToTsSource(v));\n const singleLine = `[${items.join(', ')}]`;\n if (singleLine.length <= 80) return singleLine;\n return `[\\n${items.map((i) => ` ${i}`).join(',\\n')},\\n]`;\n }\n if (typeof value === 'object') {\n const entries = Object.entries(value).filter(([, v]) => v !== undefined);\n if (entries.length === 0) return '{}';\n const items = entries.map(([k, v]) => `${renderKey(k)}: ${jsonToTsSource(v)}`);\n const singleLine = `{ ${items.join(', ')} }`;\n if (singleLine.length <= 80) return singleLine;\n return `{\\n${items.map((i) => ` ${i}`).join(',\\n')},\\n}`;\n }\n throw new Error(`jsonToTsSource: unsupported value type \"${typeof value}\"`);\n}\n\nfunction renderKey(key: string): string {\n if (key === '__proto__') return JSON.stringify(key);\n return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : JSON.stringify(key);\n}\n","import type { ImportRequirement } from './ts-expression';\n\n/**\n * Render an aggregated `import` block from a flat list of\n * `ImportRequirement`s. Each target's migration renderer collects\n * requirements polymorphically from its call nodes and pipes them here.\n *\n * The emitter invariants:\n *\n * - **One line per module specifier.** Named imports are aggregated and\n * emitted sorted alphabetically; a single default symbol is combined\n * onto the same line when attributes agree (`import def, { a, b } from \"m\";`).\n * - **At most one default symbol per module.** Two conflicting default\n * symbols on the same specifier throw — the user's renderer can't\n * guess which one they meant.\n * - **Attribute unanimity per module.** All requirements for the same\n * module specifier must carry the same (or no) `attributes` map.\n * Divergent attribute maps throw — they can't collapse to one line\n * and there's no user-resolvable recovery at this layer.\n * - **Deterministic ordering.** Modules are emitted sorted by specifier;\n * within a module, named symbols are emitted sorted alphabetically.\n *\n * Returns a string containing one import line per module, joined by `\\n`\n * (no trailing newline). An empty requirement list returns `\"\"`.\n */\nexport function renderImports(requirements: readonly ImportRequirement[]): string {\n const byModule = aggregateByModule(requirements);\n const entries = [...byModule.entries()].sort(([a], [b]) => a.localeCompare(b));\n return entries\n .map(([moduleSpecifier, group]) => renderModuleImport(moduleSpecifier, group))\n .join('\\n');\n}\n\ninterface ModuleImportGroup {\n readonly named: Set<string>;\n defaultSymbol: string | null;\n attributes: Readonly<Record<string, string>> | null;\n attributesSet: boolean;\n}\n\nfunction aggregateByModule(\n requirements: readonly ImportRequirement[],\n): Map<string, ModuleImportGroup> {\n const byModule = new Map<string, ModuleImportGroup>();\n for (const req of requirements) {\n let group = byModule.get(req.moduleSpecifier);\n if (!group) {\n group = { named: new Set(), defaultSymbol: null, attributes: null, attributesSet: false };\n byModule.set(req.moduleSpecifier, group);\n }\n mergeRequirementIntoGroup(req, group);\n }\n return byModule;\n}\n\nfunction mergeRequirementIntoGroup(req: ImportRequirement, group: ModuleImportGroup): void {\n const kind = req.kind ?? 'named';\n if (kind === 'default') {\n if (group.defaultSymbol !== null && group.defaultSymbol !== req.symbol) {\n throw new Error(\n `Conflicting default imports for module \"${req.moduleSpecifier}\": ` +\n `\"${group.defaultSymbol}\" and \"${req.symbol}\". Only one default symbol is allowed per module.`,\n );\n }\n group.defaultSymbol = req.symbol;\n } else {\n group.named.add(req.symbol);\n }\n mergeAttributes(req, group);\n}\n\nfunction mergeAttributes(req: ImportRequirement, group: ModuleImportGroup): void {\n const incoming = req.attributes ?? null;\n if (!group.attributesSet) {\n group.attributes = incoming;\n group.attributesSet = true;\n return;\n }\n if (!attributesEqual(group.attributes, incoming)) {\n throw new Error(\n `Conflicting import attributes for module \"${req.moduleSpecifier}\": ` +\n `${stringifyAttributes(group.attributes)} vs ${stringifyAttributes(incoming)}.`,\n );\n }\n}\n\nfunction attributesEqual(\n a: Readonly<Record<string, string>> | null,\n b: Readonly<Record<string, string>> | null,\n): boolean {\n if (a === b) return true;\n if (a === null || b === null) return false;\n const aKeys = Object.keys(a).sort();\n const bKeys = Object.keys(b).sort();\n if (aKeys.length !== bKeys.length) return false;\n for (let i = 0; i < aKeys.length; i++) {\n const key = aKeys[i];\n if (key !== bKeys[i]) return false;\n if (a[key as string] !== b[key as string]) return false;\n }\n return true;\n}\n\nfunction stringifyAttributes(attrs: Readonly<Record<string, string>> | null): string {\n if (attrs === null) return '(none)';\n const entries = Object.entries(attrs)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}: ${JSON.stringify(v)}`);\n return `{ ${entries.join(', ')} }`;\n}\n\nfunction renderModuleImport(moduleSpecifier: string, group: ModuleImportGroup): string {\n const clause = buildImportClause(group);\n const attrs = buildAttributesClause(group.attributes);\n return `import ${clause} from '${moduleSpecifier}'${attrs};`;\n}\n\nfunction buildImportClause(group: ModuleImportGroup): string {\n const named = [...group.named].sort();\n const hasNamed = named.length > 0;\n const hasDefault = group.defaultSymbol !== null;\n if (hasDefault && hasNamed) {\n return `${group.defaultSymbol}, { ${named.join(', ')} }`;\n }\n if (hasDefault) {\n return group.defaultSymbol as string;\n }\n return `{ ${named.join(', ')} }`;\n}\n\nfunction buildAttributesClause(attrs: Readonly<Record<string, string>> | null): string {\n if (attrs === null) return '';\n const entries = Object.entries(attrs)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}: ${JSON.stringify(v)}`);\n if (entries.length === 0) return '';\n return ` with { ${entries.join(', ')} }`;\n}\n","/**\n * Declarative contribution to the `import` block of a rendered TypeScript\n * source file. Each node in an IR declares which symbols it needs from which\n * modules; the top-level renderer deduplicates across nodes and emits one\n * `import { a, b, c } from \"…\"` line per module.\n *\n * `kind` defaults to `\"named\"` (e.g. `import { a } from \"m\"`). Setting it to\n * `\"default\"` emits `import a from \"m\"`. `attributes`, if provided, emits an\n * import attributes clause (`with { type: \"json\" }`) verbatim — required for\n * JSON module imports in the rendered scaffolds.\n */\nexport interface ImportRequirement {\n readonly moduleSpecifier: string;\n readonly symbol: string;\n readonly kind?: 'named' | 'default';\n readonly attributes?: Readonly<Record<string, string>>;\n}\n\n/**\n * Abstract base class for any IR node that can be emitted as a TypeScript\n * expression and declare its own import requirements.\n *\n * A top-level renderer walks an array of these polymorphically, concatenates\n * `renderTypeScript()` results, and aggregates `importRequirements()` into a\n * deduplicated import block.\n */\nexport abstract class TsExpression {\n abstract renderTypeScript(): string;\n abstract importRequirements(): readonly ImportRequirement[];\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,14 +1,15 @@
1
1
  {
2
2
  "name": "@prisma-next/ts-render",
3
- "version": "0.5.0-dev.9",
3
+ "version": "0.5.1",
4
+ "license": "Apache-2.0",
4
5
  "type": "module",
5
6
  "sideEffects": false,
6
7
  "description": "TypeScript source-text rendering utilities: JSON-to-TS literal printer and abstract expression base class",
7
8
  "dependencies": {},
8
9
  "devDependencies": {
9
- "tsdown": "0.18.4",
10
+ "tsdown": "0.22.0",
10
11
  "typescript": "5.9.3",
11
- "vitest": "4.0.17",
12
+ "vitest": "4.1.5",
12
13
  "@prisma-next/tsconfig": "0.0.0",
13
14
  "@prisma-next/tsdown": "0.0.0"
14
15
  },