@prisma-next/sql-contract-emitter 0.3.0-pr.99.2 → 0.3.0-pr.99.3

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.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACV,4BAA4B,EAC5B,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,eAAe,EAEf,UAAU,EACV,aAAa,EAGd,MAAM,iCAAiC,CAAC;AAyBzC,eAAO,MAAM,mBAAmB;;iCAGZ,UAAU,QAAQ,iBAAiB,KAAG,IAAI;qCA6BtC,UAAU,KAAG,IAAI;yCAyJjC,UAAU,oBACI,aAAa,CAAC,eAAe,CAAC,wBAC1B,aAAa,CAAC,eAAe,CAAC,YAC1C,4BAA4B,KACrC,MAAM;4CA8DoB,UAAU,KAAG,MAAM;IAyDhD;;;OAGG;+CAC6B,UAAU,CAAC,OAAO,CAAC,KAAG,MAAM;IAkB5D;;;OAGG;kDACgC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM;IAcnE;;OAEG;qCACmB,OAAO,KAAG,MAAM;0CA4B5B,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,WAC1C,UAAU,2BACM,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,KACpD,MAAM;IAgET;;;;OAIG;0CAEO,aAAa,WACZ,UAAU,0BACK,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,aACrD,iBAAiB,KAC3B,MAAM;gDAqBwB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAG,MAAM;4CAkEnE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,WAC1C,UAAU,cACP,MAAM,kBACF,MAAM,KACrB,MAAM;CAsDD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACV,4BAA4B,EAC5B,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EACV,eAAe,EAEf,UAAU,EACV,aAAa,EAGd,MAAM,iCAAiC,CAAC;AAyBzC,eAAO,MAAM,mBAAmB;;iCAGZ,UAAU,QAAQ,iBAAiB,KAAG,IAAI;qCA6BtC,UAAU,KAAG,IAAI;yCAyJjC,UAAU,oBACI,aAAa,CAAC,eAAe,CAAC,wBAC1B,aAAa,CAAC,eAAe,CAAC,YAC1C,4BAA4B,KACrC,MAAM;4CAyEoB,UAAU,KAAG,MAAM;IAyDhD;;;OAGG;+CAC6B,UAAU,CAAC,OAAO,CAAC,KAAG,MAAM;IAkB5D;;;OAGG;kDACgC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM;IAcnE;;OAEG;qCACmB,OAAO,KAAG,MAAM;0CA4B5B,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,WAC1C,UAAU,2BACM,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,KACpD,MAAM;IAgET;;;;OAIG;0CAEO,aAAa,WACZ,UAAU,0BACK,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,aACrD,iBAAiB,KAC3B,MAAM;gDAqBwB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAG,MAAM;4CAkEnE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,GAAG,SAAS,WAC1C,UAAU,cACP,MAAM,kBACF,MAAM,KACrB,MAAM;CAsDD,CAAC"}
package/dist/index.js CHANGED
@@ -172,12 +172,12 @@ var sqlTargetFamilyHook = {
172
172
  if (parameterizedTypeImports) {
173
173
  allImports.push(...parameterizedTypeImports);
174
174
  }
175
- const seenImports = /* @__PURE__ */ new Set();
175
+ const seenImportKeys = /* @__PURE__ */ new Set();
176
176
  const uniqueImports = [];
177
177
  for (const imp of allImports) {
178
178
  const key = `${imp.package}::${imp.named}`;
179
- if (!seenImports.has(key)) {
180
- seenImports.add(key);
179
+ if (!seenImportKeys.has(key)) {
180
+ seenImportKeys.add(key);
181
181
  uniqueImports.push(imp);
182
182
  }
183
183
  }
@@ -192,27 +192,27 @@ var sqlTargetFamilyHook = {
192
192
  const relationsType = this.generateRelationsType(ir.relations);
193
193
  const mappingsType = this.generateMappingsType(models, storage, codecTypes, operationTypes);
194
194
  return `// \u26A0\uFE0F GENERATED FILE - DO NOT EDIT
195
- // This file is automatically generated by 'prisma-next contract emit'.
196
- // To regenerate, run: prisma-next contract emit
197
- ${importLines.join("\n")}
195
+ // This file is automatically generated by 'prisma-next contract emit'.
196
+ // To regenerate, run: prisma-next contract emit
197
+ ${importLines.join("\n")}
198
198
 
199
- import type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';
199
+ import type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';
200
200
 
201
- export type CodecTypes = ${codecTypes || "Record<string, never>"};
202
- export type LaneCodecTypes = CodecTypes;
203
- export type OperationTypes = ${operationTypes || "Record<string, never>"};
201
+ export type CodecTypes = ${codecTypes || "Record<string, never>"};
202
+ export type LaneCodecTypes = CodecTypes;
203
+ export type OperationTypes = ${operationTypes || "Record<string, never>"};
204
204
 
205
- export type Contract = SqlContract<
205
+ export type Contract = SqlContract<
206
206
  ${storageType},
207
207
  ${modelsType},
208
208
  ${relationsType},
209
209
  ${mappingsType}
210
- >;
210
+ >;
211
211
 
212
- export type Tables = Contract['storage']['tables'];
213
- export type Models = Contract['models'];
214
- export type Relations = Contract['relations'];
215
- `;
212
+ export type Tables = Contract['storage']['tables'];
213
+ export type Models = Contract['models'];
214
+ export type Relations = Contract['relations'];
215
+ `;
216
216
  },
217
217
  generateStorageType(storage) {
218
218
  const tables = [];
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ContractIR } from '@prisma-next/contract/ir';\nimport type {\n GenerateContractTypesOptions,\n TypeRenderContext,\n TypeRenderEntry,\n TypesImportSpec,\n ValidationContext,\n} from '@prisma-next/contract/types';\nimport type {\n ModelDefinition,\n ModelField,\n SqlStorage,\n StorageColumn,\n StorageTable,\n StorageTypeInstance,\n} from '@prisma-next/sql-contract/types';\nimport { assertDefined } from '@prisma-next/utils/assertions';\n\n/**\n * Resolves the typeParams for a column, either from inline typeParams or from typeRef.\n * Returns undefined if no typeParams are available.\n */\nfunction resolveColumnTypeParams(\n column: StorageColumn,\n storage: SqlStorage,\n): Record<string, unknown> | undefined {\n // Inline typeParams take precedence\n if (column.typeParams && Object.keys(column.typeParams).length > 0) {\n return column.typeParams;\n }\n // Check typeRef\n if (column.typeRef && storage.types) {\n const typeInstance = storage.types[column.typeRef] as StorageTypeInstance | undefined;\n if (typeInstance?.typeParams) {\n return typeInstance.typeParams;\n }\n }\n return undefined;\n}\n\nexport const sqlTargetFamilyHook = {\n id: 'sql',\n\n validateTypes(ir: ContractIR, _ctx: ValidationContext): void {\n const storage = ir.storage as SqlStorage | undefined;\n if (!storage || !storage.tables) {\n return;\n }\n\n // Validate codec ID format (ns/name@version). Adapter-provided codecs are available regardless of contract.extensionPacks (which is for framework extensions); TypeScript prevents invalid usage and runtime validates availability.\n\n const typeIdRegex = /^([^/]+)\\/([^@]+)@(\\d+)$/;\n\n for (const [tableName, tableUnknown] of Object.entries(storage.tables)) {\n const table = tableUnknown as StorageTable;\n for (const [colName, colUnknown] of Object.entries(table.columns)) {\n const col = colUnknown as { codecId?: string };\n const codecId = col.codecId;\n if (!codecId) {\n throw new Error(`Column \"${colName}\" in table \"${tableName}\" is missing codecId`);\n }\n\n const match = codecId.match(typeIdRegex);\n if (!match || !match[1]) {\n throw new Error(\n `Column \"${colName}\" in table \"${tableName}\" has invalid codec ID format \"${codecId}\". Expected format: ns/name@version`,\n );\n }\n }\n }\n },\n\n validateStructure(ir: ContractIR): void {\n if (ir.targetFamily !== 'sql') {\n throw new Error(`Expected targetFamily \"sql\", got \"${ir.targetFamily}\"`);\n }\n\n const storage = ir.storage as SqlStorage | undefined;\n if (!storage || !storage.tables) {\n throw new Error('SQL contract must have storage.tables');\n }\n\n const models = ir.models as Record<string, ModelDefinition> | undefined;\n const tableNames = new Set(Object.keys(storage.tables));\n\n if (models) {\n for (const [modelName, modelUnknown] of Object.entries(models)) {\n const model = modelUnknown as ModelDefinition;\n if (!model.storage?.table) {\n throw new Error(`Model \"${modelName}\" is missing storage.table`);\n }\n\n const tableName = model.storage.table;\n if (!tableNames.has(tableName)) {\n throw new Error(`Model \"${modelName}\" references non-existent table \"${tableName}\"`);\n }\n\n const table: StorageTable | undefined = storage.tables[tableName];\n assertDefined(table, `Model \"${modelName}\" references non-existent table \"${tableName}\"`);\n\n if (!table.primaryKey) {\n throw new Error(`Model \"${modelName}\" table \"${tableName}\" is missing a primary key`);\n }\n\n const columnNames = new Set(Object.keys(table.columns));\n if (!model.fields || Object.keys(model.fields).length === 0) {\n throw new Error(`Model \"${modelName}\" is missing fields`);\n }\n\n for (const [fieldName, fieldUnknown] of Object.entries(model.fields)) {\n const field = fieldUnknown as ModelField;\n if (!field.column) {\n throw new Error(`Model \"${modelName}\" field \"${fieldName}\" is missing column property`);\n }\n\n if (!columnNames.has(field.column)) {\n throw new Error(\n `Model \"${modelName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${tableName}\"`,\n );\n }\n }\n\n if (!model.relations || typeof model.relations !== 'object') {\n throw new Error(\n `Model \"${modelName}\" is missing required field \"relations\" (must be an object)`,\n );\n }\n }\n }\n\n for (const [tableName, tableUnknown] of Object.entries(storage.tables)) {\n const table = tableUnknown as StorageTable;\n const columnNames = new Set(Object.keys(table.columns));\n\n // Column structure (nullable, nativeType, codecId) and table arrays (uniques, indexes, foreignKeys)\n // are validated by Arktype schema validation - no need to re-check here.\n // We only validate logical consistency (foreign key references, model references, etc.)\n\n if (!Array.isArray(table.uniques)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"uniques\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.indexes)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"indexes\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.foreignKeys)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"foreignKeys\" (must be an array)`,\n );\n }\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const unique of table.uniques) {\n for (const colName of unique.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const index of table.indexes) {\n for (const colName of index.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" index references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n );\n }\n }\n\n if (!tableNames.has(fk.references.table)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.references.table}\"`,\n );\n }\n\n // Table existence guaranteed by Set.has() check above\n const referencedTable: StorageTable | undefined = storage.tables[fk.references.table];\n assertDefined(\n referencedTable,\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.references.table}\"`,\n );\n\n const referencedColumnNames = new Set(Object.keys(referencedTable.columns));\n for (const colName of fk.references.columns) {\n if (!referencedColumnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.references.table}\"`,\n );\n }\n }\n\n if (fk.columns.length !== fk.references.columns.length) {\n throw new Error(\n `Table \"${tableName}\" foreignKey column count (${fk.columns.length}) does not match referenced column count (${fk.references.columns.length})`,\n );\n }\n }\n }\n },\n\n generateContractTypes(\n ir: ContractIR,\n codecTypeImports: ReadonlyArray<TypesImportSpec>,\n operationTypeImports: ReadonlyArray<TypesImportSpec>,\n options?: GenerateContractTypesOptions,\n ): string {\n const parameterizedRenderers = options?.parameterizedRenderers;\n const parameterizedTypeImports = options?.parameterizedTypeImports;\n const storage = ir.storage as SqlStorage;\n const models = ir.models as Record<string, ModelDefinition>;\n\n // Collect imports from codec types, operation types, and parameterized type imports\n const allImports = [...codecTypeImports, ...operationTypeImports];\n if (parameterizedTypeImports) {\n allImports.push(...parameterizedTypeImports);\n }\n\n // Deduplicate imports by package+named. When duplicates occur, the first occurrence\n // (and its alias) is kept; later duplicates with different aliases are silently ignored.\n const seenImports = new Set<string>();\n const uniqueImports: TypesImportSpec[] = [];\n for (const imp of allImports) {\n const key = `${imp.package}::${imp.named}`;\n if (!seenImports.has(key)) {\n seenImports.add(key);\n uniqueImports.push(imp);\n }\n }\n\n const importLines = uniqueImports.map((imp) => {\n // Simplify import when named === alias (e.g., `import type { Vector }` instead of `{ Vector as Vector }`)\n const importClause = imp.named === imp.alias ? imp.named : `${imp.named} as ${imp.alias}`;\n return `import type { ${importClause} } from '${imp.package}';`;\n });\n\n const codecTypes = codecTypeImports.map((imp) => imp.alias).join(' & ');\n const operationTypes = operationTypeImports.map((imp) => imp.alias).join(' & ');\n\n const storageType = this.generateStorageType(storage);\n const modelsType = this.generateModelsType(models, storage, parameterizedRenderers);\n const relationsType = this.generateRelationsType(ir.relations);\n const mappingsType = this.generateMappingsType(models, storage, codecTypes, operationTypes);\n\n return `// ⚠️ GENERATED FILE - DO NOT EDIT\n// This file is automatically generated by 'prisma-next contract emit'.\n// To regenerate, run: prisma-next contract emit\n${importLines.join('\\n')}\n\nimport type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';\n\nexport type CodecTypes = ${codecTypes || 'Record<string, never>'};\nexport type LaneCodecTypes = CodecTypes;\nexport type OperationTypes = ${operationTypes || 'Record<string, never>'};\n\nexport type Contract = SqlContract<\n ${storageType},\n ${modelsType},\n ${relationsType},\n ${mappingsType}\n>;\n\nexport type Tables = Contract['storage']['tables'];\nexport type Models = Contract['models'];\nexport type Relations = Contract['relations'];\n`;\n },\n\n generateStorageType(storage: SqlStorage): string {\n const tables: string[] = [];\n for (const [tableName, table] of Object.entries(storage.tables)) {\n const columns: string[] = [];\n for (const [colName, col] of Object.entries(table.columns)) {\n const nullable = col.nullable ? 'true' : 'false';\n const nativeType = `'${col.nativeType}'`;\n const codecId = `'${col.codecId}'`;\n columns.push(\n `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable} }`,\n );\n }\n\n const tableParts: string[] = [`columns: { ${columns.join('; ')} }`];\n\n if (table.primaryKey) {\n const pkCols = table.primaryKey.columns.map((c) => `'${c}'`).join(', ');\n const pkName = table.primaryKey.name ? `; readonly name: '${table.primaryKey.name}'` : '';\n tableParts.push(`primaryKey: { readonly columns: readonly [${pkCols}]${pkName} }`);\n }\n\n const uniques = table.uniques\n .map((u) => {\n const cols = u.columns.map((c: string) => `'${c}'`).join(', ');\n const name = u.name ? `; readonly name: '${u.name}'` : '';\n return `{ readonly columns: readonly [${cols}]${name} }`;\n })\n .join(', ');\n tableParts.push(`uniques: readonly [${uniques}]`);\n\n const indexes = table.indexes\n .map((i) => {\n const cols = i.columns.map((c: string) => `'${c}'`).join(', ');\n const name = i.name ? `; readonly name: '${i.name}'` : '';\n return `{ readonly columns: readonly [${cols}]${name} }`;\n })\n .join(', ');\n tableParts.push(`indexes: readonly [${indexes}]`);\n\n const fks = table.foreignKeys\n .map((fk) => {\n const cols = fk.columns.map((c: string) => `'${c}'`).join(', ');\n const refCols = fk.references.columns.map((c: string) => `'${c}'`).join(', ');\n const name = fk.name ? `; readonly name: '${fk.name}'` : '';\n return `{ readonly columns: readonly [${cols}]; readonly references: { readonly table: '${fk.references.table}'; readonly columns: readonly [${refCols}] }${name} }`;\n })\n .join(', ');\n tableParts.push(`foreignKeys: readonly [${fks}]`);\n\n tables.push(`readonly ${tableName}: { ${tableParts.join('; ')} }`);\n }\n\n const typesType = this.generateStorageTypesType(storage.types);\n\n return `{ readonly tables: { ${tables.join('; ')} }; readonly types: ${typesType} }`;\n },\n\n /**\n * Generates the TypeScript type for storage.types with literal types.\n * This preserves type params as literal values for precise typing.\n */\n generateStorageTypesType(types: SqlStorage['types']): string {\n if (!types || Object.keys(types).length === 0) {\n return 'Record<string, never>';\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n const codecId = `'${typeInstance.codecId}'`;\n const nativeType = `'${typeInstance.nativeType}'`;\n const typeParamsStr = this.serializeTypeParamsLiteral(typeInstance.typeParams);\n typeEntries.push(\n `readonly ${typeName}: { readonly codecId: ${codecId}; readonly nativeType: ${nativeType}; readonly typeParams: ${typeParamsStr} }`,\n );\n }\n\n return `{ ${typeEntries.join('; ')} }`;\n },\n\n /**\n * Serializes a typeParams object to a TypeScript literal type.\n * Converts { length: 1536 } to \"{ readonly length: 1536 }\".\n */\n serializeTypeParamsLiteral(params: Record<string, unknown>): string {\n if (!params || Object.keys(params).length === 0) {\n return 'Record<string, never>';\n }\n\n const entries: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n const serialized = this.serializeValue(value);\n entries.push(`readonly ${key}: ${serialized}`);\n }\n\n return `{ ${entries.join('; ')} }`;\n },\n\n /**\n * Serializes a value to a TypeScript literal type expression.\n */\n serializeValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (typeof value === 'string') {\n return `'${value}'`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (Array.isArray(value)) {\n const items = value.map((v) => this.serializeValue(v)).join(', ');\n return `readonly [${items}]`;\n }\n if (typeof value === 'object') {\n const entries: string[] = [];\n for (const [k, v] of Object.entries(value)) {\n entries.push(`readonly ${k}: ${this.serializeValue(v)}`);\n }\n return `{ ${entries.join('; ')} }`;\n }\n return 'unknown';\n },\n\n generateModelsType(\n models: Record<string, ModelDefinition> | undefined,\n storage: SqlStorage,\n parameterizedRenderers?: Map<string, TypeRenderEntry>,\n ): string {\n if (!models) {\n return 'Record<string, never>';\n }\n\n const renderCtx: TypeRenderContext = { codecTypesName: 'CodecTypes' };\n\n const modelTypes: string[] = [];\n for (const [modelName, model] of Object.entries(models)) {\n const fields: string[] = [];\n const tableName = model.storage.table;\n const table = storage.tables[tableName];\n\n if (table) {\n for (const [fieldName, field] of Object.entries(model.fields)) {\n const column = table.columns[field.column];\n if (!column) {\n fields.push(`readonly ${fieldName}: { readonly column: '${field.column}' }`);\n continue;\n }\n\n const jsType = this.generateColumnType(\n column,\n storage,\n parameterizedRenderers,\n renderCtx,\n );\n fields.push(`readonly ${fieldName}: ${jsType}`);\n }\n } else {\n for (const [fieldName, field] of Object.entries(model.fields)) {\n fields.push(`readonly ${fieldName}: { readonly column: '${field.column}' }`);\n }\n }\n\n const relations: string[] = [];\n for (const [relName, rel] of Object.entries(model.relations)) {\n if (typeof rel === 'object' && rel !== null && 'on' in rel) {\n const on = rel.on as { parentCols?: string[]; childCols?: string[] };\n if (on.parentCols && on.childCols) {\n const parentCols = on.parentCols.map((c) => `'${c}'`).join(', ');\n const childCols = on.childCols.map((c) => `'${c}'`).join(', ');\n relations.push(\n `readonly ${relName}: { readonly on: { readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] } }`,\n );\n }\n }\n }\n\n const modelParts: string[] = [\n `storage: { readonly table: '${tableName}' }`,\n `fields: { ${fields.join('; ')} }`,\n ];\n\n if (relations.length > 0) {\n modelParts.push(`relations: { ${relations.join('; ')} }`);\n }\n\n modelTypes.push(`readonly ${modelName}: { ${modelParts.join('; ')} }`);\n }\n\n return `{ ${modelTypes.join('; ')} }`;\n },\n\n /**\n * Generates the TypeScript type expression for a column.\n * Uses parameterized renderer if the column has typeParams and a matching renderer exists,\n * otherwise falls back to CodecTypes[codecId]['output'].\n */\n generateColumnType(\n column: StorageColumn,\n storage: SqlStorage,\n parameterizedRenderers: Map<string, TypeRenderEntry> | undefined,\n renderCtx: TypeRenderContext,\n ): string {\n const typeParams = resolveColumnTypeParams(column, storage);\n const nullable = column.nullable ?? false;\n let baseType: string;\n\n if (typeParams && parameterizedRenderers) {\n const renderer = parameterizedRenderers.get(column.codecId);\n if (renderer) {\n baseType = renderer.render(typeParams, renderCtx);\n } else {\n // No renderer for this codecId, fall back to standard lookup\n baseType = `CodecTypes['${column.codecId}']['output']`;\n }\n } else {\n // No typeParams, use standard codec lookup\n baseType = `CodecTypes['${column.codecId}']['output']`;\n }\n\n return nullable ? `${baseType} | null` : baseType;\n },\n\n generateRelationsType(relations: Record<string, unknown> | undefined): string {\n if (!relations || Object.keys(relations).length === 0) {\n return 'Record<string, never>';\n }\n\n const tableEntries: string[] = [];\n for (const [tableName, relsValue] of Object.entries(relations)) {\n if (typeof relsValue !== 'object' || relsValue === null) {\n continue;\n }\n const rels = relsValue as Record<string, unknown>;\n const relationEntries: string[] = [];\n for (const [relName, relValue] of Object.entries(rels)) {\n if (typeof relValue !== 'object' || relValue === null) {\n relationEntries.push(`readonly ${relName}: unknown`);\n continue;\n }\n const { to, cardinality, on, through } = relValue as {\n readonly to?: string;\n readonly cardinality?: string;\n readonly on?: {\n readonly parentCols?: readonly string[];\n readonly childCols?: readonly string[];\n };\n readonly through?: {\n readonly table: string;\n readonly parentCols: readonly string[];\n readonly childCols: readonly string[];\n };\n };\n\n const parts: string[] = [];\n if (to) {\n parts.push(`readonly to: '${to}'`);\n }\n if (cardinality) {\n parts.push(`readonly cardinality: '${cardinality}'`);\n }\n if (on?.parentCols && on.childCols) {\n const parentCols = on.parentCols.map((c) => `'${c}'`).join(', ');\n const childCols = on.childCols.map((c) => `'${c}'`).join(', ');\n parts.push(\n `readonly on: { readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] }`,\n );\n }\n if (through) {\n const parentCols = through.parentCols.map((c) => `'${c}'`).join(', ');\n const childCols = through.childCols.map((c) => `'${c}'`).join(', ');\n parts.push(\n `readonly through: { readonly table: '${through.table}'; readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] }`,\n );\n }\n\n relationEntries.push(\n parts.length > 0\n ? `readonly ${relName}: { ${parts.join('; ')} }`\n : `readonly ${relName}: unknown`,\n );\n }\n tableEntries.push(`readonly ${tableName}: { ${relationEntries.join('; ')} }`);\n }\n\n return `{ ${tableEntries.join('; ')} }`;\n },\n\n generateMappingsType(\n models: Record<string, ModelDefinition> | undefined,\n storage: SqlStorage,\n codecTypes: string,\n operationTypes: string,\n ): string {\n if (!models) {\n return `SqlMappings & { readonly codecTypes: ${codecTypes || 'Record<string, never>'}; readonly operationTypes: ${operationTypes || 'Record<string, never>'}; }`;\n }\n\n const modelToTable: string[] = [];\n const tableToModel: string[] = [];\n const fieldToColumn: string[] = [];\n const columnToField: string[] = [];\n\n for (const [modelName, model] of Object.entries(models)) {\n const tableName = model.storage.table;\n modelToTable.push(`readonly ${modelName}: '${tableName}'`);\n tableToModel.push(`readonly ${tableName}: '${modelName}'`);\n\n const fieldMap: string[] = [];\n for (const [fieldName, field] of Object.entries(model.fields)) {\n fieldMap.push(`readonly ${fieldName}: '${field.column}'`);\n }\n\n if (fieldMap.length > 0) {\n fieldToColumn.push(`readonly ${modelName}: { ${fieldMap.join('; ')} }`);\n }\n\n if (storage.tables[tableName]) {\n const colMap: string[] = [];\n for (const [fieldName, field] of Object.entries(model.fields)) {\n colMap.push(`readonly ${field.column}: '${fieldName}'`);\n }\n\n if (colMap.length > 0) {\n columnToField.push(`readonly ${tableName}: { ${colMap.join('; ')} }`);\n }\n }\n }\n\n const parts: string[] = [];\n if (modelToTable.length > 0) {\n parts.push(`modelToTable: { ${modelToTable.join('; ')} }`);\n }\n if (tableToModel.length > 0) {\n parts.push(`tableToModel: { ${tableToModel.join('; ')} }`);\n }\n if (fieldToColumn.length > 0) {\n parts.push(`fieldToColumn: { ${fieldToColumn.join('; ')} }`);\n }\n if (columnToField.length > 0) {\n parts.push(`columnToField: { ${columnToField.join('; ')} }`);\n }\n parts.push(`codecTypes: ${codecTypes || 'Record<string, never>'}`);\n parts.push(`operationTypes: ${operationTypes || 'Record<string, never>'}`);\n\n return `{ ${parts.join('; ')} }`;\n },\n} as const;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { ContractIR } from '@prisma-next/contract/ir';\nimport type {\n GenerateContractTypesOptions,\n TypeRenderContext,\n TypeRenderEntry,\n TypesImportSpec,\n ValidationContext,\n} from '@prisma-next/contract/types';\nimport type {\n ModelDefinition,\n ModelField,\n SqlStorage,\n StorageColumn,\n StorageTable,\n StorageTypeInstance,\n} from '@prisma-next/sql-contract/types';\nimport { assertDefined } from '@prisma-next/utils/assertions';\n\n/**\n * Resolves the typeParams for a column, either from inline typeParams or from typeRef.\n * Returns undefined if no typeParams are available.\n */\nfunction resolveColumnTypeParams(\n column: StorageColumn,\n storage: SqlStorage,\n): Record<string, unknown> | undefined {\n // Inline typeParams take precedence\n if (column.typeParams && Object.keys(column.typeParams).length > 0) {\n return column.typeParams;\n }\n // Check typeRef\n if (column.typeRef && storage.types) {\n const typeInstance = storage.types[column.typeRef] as StorageTypeInstance | undefined;\n if (typeInstance?.typeParams) {\n return typeInstance.typeParams;\n }\n }\n return undefined;\n}\n\nexport const sqlTargetFamilyHook = {\n id: 'sql',\n\n validateTypes(ir: ContractIR, _ctx: ValidationContext): void {\n const storage = ir.storage as SqlStorage | undefined;\n if (!storage || !storage.tables) {\n return;\n }\n\n // Validate codec ID format (ns/name@version). Adapter-provided codecs are available regardless of contract.extensionPacks (which is for framework extensions); TypeScript prevents invalid usage and runtime validates availability.\n\n const typeIdRegex = /^([^/]+)\\/([^@]+)@(\\d+)$/;\n\n for (const [tableName, tableUnknown] of Object.entries(storage.tables)) {\n const table = tableUnknown as StorageTable;\n for (const [colName, colUnknown] of Object.entries(table.columns)) {\n const col = colUnknown as { codecId?: string };\n const codecId = col.codecId;\n if (!codecId) {\n throw new Error(`Column \"${colName}\" in table \"${tableName}\" is missing codecId`);\n }\n\n const match = codecId.match(typeIdRegex);\n if (!match || !match[1]) {\n throw new Error(\n `Column \"${colName}\" in table \"${tableName}\" has invalid codec ID format \"${codecId}\". Expected format: ns/name@version`,\n );\n }\n }\n }\n },\n\n validateStructure(ir: ContractIR): void {\n if (ir.targetFamily !== 'sql') {\n throw new Error(`Expected targetFamily \"sql\", got \"${ir.targetFamily}\"`);\n }\n\n const storage = ir.storage as SqlStorage | undefined;\n if (!storage || !storage.tables) {\n throw new Error('SQL contract must have storage.tables');\n }\n\n const models = ir.models as Record<string, ModelDefinition> | undefined;\n const tableNames = new Set(Object.keys(storage.tables));\n\n if (models) {\n for (const [modelName, modelUnknown] of Object.entries(models)) {\n const model = modelUnknown as ModelDefinition;\n if (!model.storage?.table) {\n throw new Error(`Model \"${modelName}\" is missing storage.table`);\n }\n\n const tableName = model.storage.table;\n if (!tableNames.has(tableName)) {\n throw new Error(`Model \"${modelName}\" references non-existent table \"${tableName}\"`);\n }\n\n const table: StorageTable | undefined = storage.tables[tableName];\n assertDefined(table, `Model \"${modelName}\" references non-existent table \"${tableName}\"`);\n\n if (!table.primaryKey) {\n throw new Error(`Model \"${modelName}\" table \"${tableName}\" is missing a primary key`);\n }\n\n const columnNames = new Set(Object.keys(table.columns));\n if (!model.fields || Object.keys(model.fields).length === 0) {\n throw new Error(`Model \"${modelName}\" is missing fields`);\n }\n\n for (const [fieldName, fieldUnknown] of Object.entries(model.fields)) {\n const field = fieldUnknown as ModelField;\n if (!field.column) {\n throw new Error(`Model \"${modelName}\" field \"${fieldName}\" is missing column property`);\n }\n\n if (!columnNames.has(field.column)) {\n throw new Error(\n `Model \"${modelName}\" field \"${fieldName}\" references non-existent column \"${field.column}\" in table \"${tableName}\"`,\n );\n }\n }\n\n if (!model.relations || typeof model.relations !== 'object') {\n throw new Error(\n `Model \"${modelName}\" is missing required field \"relations\" (must be an object)`,\n );\n }\n }\n }\n\n for (const [tableName, tableUnknown] of Object.entries(storage.tables)) {\n const table = tableUnknown as StorageTable;\n const columnNames = new Set(Object.keys(table.columns));\n\n // Column structure (nullable, nativeType, codecId) and table arrays (uniques, indexes, foreignKeys)\n // are validated by Arktype schema validation - no need to re-check here.\n // We only validate logical consistency (foreign key references, model references, etc.)\n\n if (!Array.isArray(table.uniques)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"uniques\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.indexes)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"indexes\" (must be an array)`,\n );\n }\n if (!Array.isArray(table.foreignKeys)) {\n throw new Error(\n `Table \"${tableName}\" is missing required field \"foreignKeys\" (must be an array)`,\n );\n }\n\n if (table.primaryKey) {\n for (const colName of table.primaryKey.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" primaryKey references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const unique of table.uniques) {\n for (const colName of unique.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" unique constraint references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const index of table.indexes) {\n for (const colName of index.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" index references non-existent column \"${colName}\"`,\n );\n }\n }\n }\n\n for (const fk of table.foreignKeys) {\n for (const colName of fk.columns) {\n if (!columnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\"`,\n );\n }\n }\n\n if (!tableNames.has(fk.references.table)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.references.table}\"`,\n );\n }\n\n // Table existence guaranteed by Set.has() check above\n const referencedTable: StorageTable | undefined = storage.tables[fk.references.table];\n assertDefined(\n referencedTable,\n `Table \"${tableName}\" foreignKey references non-existent table \"${fk.references.table}\"`,\n );\n\n const referencedColumnNames = new Set(Object.keys(referencedTable.columns));\n for (const colName of fk.references.columns) {\n if (!referencedColumnNames.has(colName)) {\n throw new Error(\n `Table \"${tableName}\" foreignKey references non-existent column \"${colName}\" in table \"${fk.references.table}\"`,\n );\n }\n }\n\n if (fk.columns.length !== fk.references.columns.length) {\n throw new Error(\n `Table \"${tableName}\" foreignKey column count (${fk.columns.length}) does not match referenced column count (${fk.references.columns.length})`,\n );\n }\n }\n }\n },\n\n generateContractTypes(\n ir: ContractIR,\n codecTypeImports: ReadonlyArray<TypesImportSpec>,\n operationTypeImports: ReadonlyArray<TypesImportSpec>,\n options?: GenerateContractTypesOptions,\n ): string {\n const parameterizedRenderers = options?.parameterizedRenderers;\n const parameterizedTypeImports = options?.parameterizedTypeImports;\n const storage = ir.storage as SqlStorage;\n const models = ir.models as Record<string, ModelDefinition>;\n\n // Collect all type imports from three sources:\n // 1. Codec type imports (from adapters, targets, and extensions)\n // 2. Operation type imports (from adapters, targets, and extensions)\n // 3. Parameterized type imports (for parameterized codec renderers, may contain duplicates)\n const allImports: TypesImportSpec[] = [...codecTypeImports, ...operationTypeImports];\n\n if (parameterizedTypeImports) {\n allImports.push(...parameterizedTypeImports);\n }\n\n // Deduplicate imports by package+named to avoid duplicate import statements.\n // Strategy: When the same package::named appears multiple times, keep the first\n // occurrence (and its alias); later duplicates with different aliases are silently ignored.\n //\n // Note: uniqueImports must be an array (not a Set) because:\n // - We need to preserve the full TypesImportSpec objects (package, named, alias)\n // - We need to preserve insertion order (first occurrence wins)\n // - seenImportKeys is a Set used only for O(1) duplicate detection\n const seenImportKeys = new Set<string>();\n const uniqueImports: TypesImportSpec[] = [];\n for (const imp of allImports) {\n const key = `${imp.package}::${imp.named}`;\n if (!seenImportKeys.has(key)) {\n seenImportKeys.add(key);\n uniqueImports.push(imp);\n }\n }\n\n // Generate import statements, omitting redundant \"as Alias\" when named === alias\n const importLines = uniqueImports.map((imp) => {\n // Simplify import when named === alias (e.g., `import type { Vector }` instead of `{ Vector as Vector }`)\n const importClause = imp.named === imp.alias ? imp.named : `${imp.named} as ${imp.alias}`;\n return `import type { ${importClause} } from '${imp.package}';`;\n });\n\n const codecTypes = codecTypeImports.map((imp) => imp.alias).join(' & ');\n const operationTypes = operationTypeImports.map((imp) => imp.alias).join(' & ');\n\n const storageType = this.generateStorageType(storage);\n const modelsType = this.generateModelsType(models, storage, parameterizedRenderers);\n const relationsType = this.generateRelationsType(ir.relations);\n const mappingsType = this.generateMappingsType(models, storage, codecTypes, operationTypes);\n\n return `// ⚠️ GENERATED FILE - DO NOT EDIT\n // This file is automatically generated by 'prisma-next contract emit'.\n // To regenerate, run: prisma-next contract emit\n ${importLines.join('\\n')}\n\n import type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';\n\n export type CodecTypes = ${codecTypes || 'Record<string, never>'};\n export type LaneCodecTypes = CodecTypes;\n export type OperationTypes = ${operationTypes || 'Record<string, never>'};\n\n export type Contract = SqlContract<\n ${storageType},\n ${modelsType},\n ${relationsType},\n ${mappingsType}\n >;\n\n export type Tables = Contract['storage']['tables'];\n export type Models = Contract['models'];\n export type Relations = Contract['relations'];\n `;\n },\n\n generateStorageType(storage: SqlStorage): string {\n const tables: string[] = [];\n for (const [tableName, table] of Object.entries(storage.tables)) {\n const columns: string[] = [];\n for (const [colName, col] of Object.entries(table.columns)) {\n const nullable = col.nullable ? 'true' : 'false';\n const nativeType = `'${col.nativeType}'`;\n const codecId = `'${col.codecId}'`;\n columns.push(\n `readonly ${colName}: { readonly nativeType: ${nativeType}; readonly codecId: ${codecId}; readonly nullable: ${nullable} }`,\n );\n }\n\n const tableParts: string[] = [`columns: { ${columns.join('; ')} }`];\n\n if (table.primaryKey) {\n const pkCols = table.primaryKey.columns.map((c) => `'${c}'`).join(', ');\n const pkName = table.primaryKey.name ? `; readonly name: '${table.primaryKey.name}'` : '';\n tableParts.push(`primaryKey: { readonly columns: readonly [${pkCols}]${pkName} }`);\n }\n\n const uniques = table.uniques\n .map((u) => {\n const cols = u.columns.map((c: string) => `'${c}'`).join(', ');\n const name = u.name ? `; readonly name: '${u.name}'` : '';\n return `{ readonly columns: readonly [${cols}]${name} }`;\n })\n .join(', ');\n tableParts.push(`uniques: readonly [${uniques}]`);\n\n const indexes = table.indexes\n .map((i) => {\n const cols = i.columns.map((c: string) => `'${c}'`).join(', ');\n const name = i.name ? `; readonly name: '${i.name}'` : '';\n return `{ readonly columns: readonly [${cols}]${name} }`;\n })\n .join(', ');\n tableParts.push(`indexes: readonly [${indexes}]`);\n\n const fks = table.foreignKeys\n .map((fk) => {\n const cols = fk.columns.map((c: string) => `'${c}'`).join(', ');\n const refCols = fk.references.columns.map((c: string) => `'${c}'`).join(', ');\n const name = fk.name ? `; readonly name: '${fk.name}'` : '';\n return `{ readonly columns: readonly [${cols}]; readonly references: { readonly table: '${fk.references.table}'; readonly columns: readonly [${refCols}] }${name} }`;\n })\n .join(', ');\n tableParts.push(`foreignKeys: readonly [${fks}]`);\n\n tables.push(`readonly ${tableName}: { ${tableParts.join('; ')} }`);\n }\n\n const typesType = this.generateStorageTypesType(storage.types);\n\n return `{ readonly tables: { ${tables.join('; ')} }; readonly types: ${typesType} }`;\n },\n\n /**\n * Generates the TypeScript type for storage.types with literal types.\n * This preserves type params as literal values for precise typing.\n */\n generateStorageTypesType(types: SqlStorage['types']): string {\n if (!types || Object.keys(types).length === 0) {\n return 'Record<string, never>';\n }\n\n const typeEntries: string[] = [];\n for (const [typeName, typeInstance] of Object.entries(types)) {\n const codecId = `'${typeInstance.codecId}'`;\n const nativeType = `'${typeInstance.nativeType}'`;\n const typeParamsStr = this.serializeTypeParamsLiteral(typeInstance.typeParams);\n typeEntries.push(\n `readonly ${typeName}: { readonly codecId: ${codecId}; readonly nativeType: ${nativeType}; readonly typeParams: ${typeParamsStr} }`,\n );\n }\n\n return `{ ${typeEntries.join('; ')} }`;\n },\n\n /**\n * Serializes a typeParams object to a TypeScript literal type.\n * Converts { length: 1536 } to \"{ readonly length: 1536 }\".\n */\n serializeTypeParamsLiteral(params: Record<string, unknown>): string {\n if (!params || Object.keys(params).length === 0) {\n return 'Record<string, never>';\n }\n\n const entries: string[] = [];\n for (const [key, value] of Object.entries(params)) {\n const serialized = this.serializeValue(value);\n entries.push(`readonly ${key}: ${serialized}`);\n }\n\n return `{ ${entries.join('; ')} }`;\n },\n\n /**\n * Serializes a value to a TypeScript literal type expression.\n */\n serializeValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (typeof value === 'string') {\n return `'${value}'`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (Array.isArray(value)) {\n const items = value.map((v) => this.serializeValue(v)).join(', ');\n return `readonly [${items}]`;\n }\n if (typeof value === 'object') {\n const entries: string[] = [];\n for (const [k, v] of Object.entries(value)) {\n entries.push(`readonly ${k}: ${this.serializeValue(v)}`);\n }\n return `{ ${entries.join('; ')} }`;\n }\n return 'unknown';\n },\n\n generateModelsType(\n models: Record<string, ModelDefinition> | undefined,\n storage: SqlStorage,\n parameterizedRenderers?: Map<string, TypeRenderEntry>,\n ): string {\n if (!models) {\n return 'Record<string, never>';\n }\n\n const renderCtx: TypeRenderContext = { codecTypesName: 'CodecTypes' };\n\n const modelTypes: string[] = [];\n for (const [modelName, model] of Object.entries(models)) {\n const fields: string[] = [];\n const tableName = model.storage.table;\n const table = storage.tables[tableName];\n\n if (table) {\n for (const [fieldName, field] of Object.entries(model.fields)) {\n const column = table.columns[field.column];\n if (!column) {\n fields.push(`readonly ${fieldName}: { readonly column: '${field.column}' }`);\n continue;\n }\n\n const jsType = this.generateColumnType(\n column,\n storage,\n parameterizedRenderers,\n renderCtx,\n );\n fields.push(`readonly ${fieldName}: ${jsType}`);\n }\n } else {\n for (const [fieldName, field] of Object.entries(model.fields)) {\n fields.push(`readonly ${fieldName}: { readonly column: '${field.column}' }`);\n }\n }\n\n const relations: string[] = [];\n for (const [relName, rel] of Object.entries(model.relations)) {\n if (typeof rel === 'object' && rel !== null && 'on' in rel) {\n const on = rel.on as { parentCols?: string[]; childCols?: string[] };\n if (on.parentCols && on.childCols) {\n const parentCols = on.parentCols.map((c) => `'${c}'`).join(', ');\n const childCols = on.childCols.map((c) => `'${c}'`).join(', ');\n relations.push(\n `readonly ${relName}: { readonly on: { readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] } }`,\n );\n }\n }\n }\n\n const modelParts: string[] = [\n `storage: { readonly table: '${tableName}' }`,\n `fields: { ${fields.join('; ')} }`,\n ];\n\n if (relations.length > 0) {\n modelParts.push(`relations: { ${relations.join('; ')} }`);\n }\n\n modelTypes.push(`readonly ${modelName}: { ${modelParts.join('; ')} }`);\n }\n\n return `{ ${modelTypes.join('; ')} }`;\n },\n\n /**\n * Generates the TypeScript type expression for a column.\n * Uses parameterized renderer if the column has typeParams and a matching renderer exists,\n * otherwise falls back to CodecTypes[codecId]['output'].\n */\n generateColumnType(\n column: StorageColumn,\n storage: SqlStorage,\n parameterizedRenderers: Map<string, TypeRenderEntry> | undefined,\n renderCtx: TypeRenderContext,\n ): string {\n const typeParams = resolveColumnTypeParams(column, storage);\n const nullable = column.nullable ?? false;\n let baseType: string;\n\n if (typeParams && parameterizedRenderers) {\n const renderer = parameterizedRenderers.get(column.codecId);\n if (renderer) {\n baseType = renderer.render(typeParams, renderCtx);\n } else {\n // No renderer for this codecId, fall back to standard lookup\n baseType = `CodecTypes['${column.codecId}']['output']`;\n }\n } else {\n // No typeParams, use standard codec lookup\n baseType = `CodecTypes['${column.codecId}']['output']`;\n }\n\n return nullable ? `${baseType} | null` : baseType;\n },\n\n generateRelationsType(relations: Record<string, unknown> | undefined): string {\n if (!relations || Object.keys(relations).length === 0) {\n return 'Record<string, never>';\n }\n\n const tableEntries: string[] = [];\n for (const [tableName, relsValue] of Object.entries(relations)) {\n if (typeof relsValue !== 'object' || relsValue === null) {\n continue;\n }\n const rels = relsValue as Record<string, unknown>;\n const relationEntries: string[] = [];\n for (const [relName, relValue] of Object.entries(rels)) {\n if (typeof relValue !== 'object' || relValue === null) {\n relationEntries.push(`readonly ${relName}: unknown`);\n continue;\n }\n const { to, cardinality, on, through } = relValue as {\n readonly to?: string;\n readonly cardinality?: string;\n readonly on?: {\n readonly parentCols?: readonly string[];\n readonly childCols?: readonly string[];\n };\n readonly through?: {\n readonly table: string;\n readonly parentCols: readonly string[];\n readonly childCols: readonly string[];\n };\n };\n\n const parts: string[] = [];\n if (to) {\n parts.push(`readonly to: '${to}'`);\n }\n if (cardinality) {\n parts.push(`readonly cardinality: '${cardinality}'`);\n }\n if (on?.parentCols && on.childCols) {\n const parentCols = on.parentCols.map((c) => `'${c}'`).join(', ');\n const childCols = on.childCols.map((c) => `'${c}'`).join(', ');\n parts.push(\n `readonly on: { readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] }`,\n );\n }\n if (through) {\n const parentCols = through.parentCols.map((c) => `'${c}'`).join(', ');\n const childCols = through.childCols.map((c) => `'${c}'`).join(', ');\n parts.push(\n `readonly through: { readonly table: '${through.table}'; readonly parentCols: readonly [${parentCols}]; readonly childCols: readonly [${childCols}] }`,\n );\n }\n\n relationEntries.push(\n parts.length > 0\n ? `readonly ${relName}: { ${parts.join('; ')} }`\n : `readonly ${relName}: unknown`,\n );\n }\n tableEntries.push(`readonly ${tableName}: { ${relationEntries.join('; ')} }`);\n }\n\n return `{ ${tableEntries.join('; ')} }`;\n },\n\n generateMappingsType(\n models: Record<string, ModelDefinition> | undefined,\n storage: SqlStorage,\n codecTypes: string,\n operationTypes: string,\n ): string {\n if (!models) {\n return `SqlMappings & { readonly codecTypes: ${codecTypes || 'Record<string, never>'}; readonly operationTypes: ${operationTypes || 'Record<string, never>'}; }`;\n }\n\n const modelToTable: string[] = [];\n const tableToModel: string[] = [];\n const fieldToColumn: string[] = [];\n const columnToField: string[] = [];\n\n for (const [modelName, model] of Object.entries(models)) {\n const tableName = model.storage.table;\n modelToTable.push(`readonly ${modelName}: '${tableName}'`);\n tableToModel.push(`readonly ${tableName}: '${modelName}'`);\n\n const fieldMap: string[] = [];\n for (const [fieldName, field] of Object.entries(model.fields)) {\n fieldMap.push(`readonly ${fieldName}: '${field.column}'`);\n }\n\n if (fieldMap.length > 0) {\n fieldToColumn.push(`readonly ${modelName}: { ${fieldMap.join('; ')} }`);\n }\n\n if (storage.tables[tableName]) {\n const colMap: string[] = [];\n for (const [fieldName, field] of Object.entries(model.fields)) {\n colMap.push(`readonly ${field.column}: '${fieldName}'`);\n }\n\n if (colMap.length > 0) {\n columnToField.push(`readonly ${tableName}: { ${colMap.join('; ')} }`);\n }\n }\n }\n\n const parts: string[] = [];\n if (modelToTable.length > 0) {\n parts.push(`modelToTable: { ${modelToTable.join('; ')} }`);\n }\n if (tableToModel.length > 0) {\n parts.push(`tableToModel: { ${tableToModel.join('; ')} }`);\n }\n if (fieldToColumn.length > 0) {\n parts.push(`fieldToColumn: { ${fieldToColumn.join('; ')} }`);\n }\n if (columnToField.length > 0) {\n parts.push(`columnToField: { ${columnToField.join('; ')} }`);\n }\n parts.push(`codecTypes: ${codecTypes || 'Record<string, never>'}`);\n parts.push(`operationTypes: ${operationTypes || 'Record<string, never>'}`);\n\n return `{ ${parts.join('; ')} }`;\n },\n} as const;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@prisma-next/sql-contract-emitter",
3
- "version": "0.3.0-pr.99.2",
3
+ "version": "0.3.0-pr.99.3",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "SQL emitter hook for Prisma Next",
7
7
  "dependencies": {
8
- "@prisma-next/contract": "0.3.0-pr.99.2",
9
- "@prisma-next/emitter": "0.3.0-pr.99.2",
10
- "@prisma-next/sql-contract": "0.3.0-pr.99.2",
11
- "@prisma-next/utils": "0.3.0-pr.99.2"
8
+ "@prisma-next/contract": "0.3.0-pr.99.3",
9
+ "@prisma-next/emitter": "0.3.0-pr.99.3",
10
+ "@prisma-next/sql-contract": "0.3.0-pr.99.3",
11
+ "@prisma-next/utils": "0.3.0-pr.99.3"
12
12
  },
13
13
  "devDependencies": {
14
14
  "tsup": "8.5.1",
15
15
  "typescript": "5.9.3",
16
16
  "vitest": "4.0.16",
17
- "@prisma-next/test-utils": "0.0.1",
18
- "@prisma-next/tsconfig": "0.0.0"
17
+ "@prisma-next/tsconfig": "0.0.0",
18
+ "@prisma-next/test-utils": "0.0.1"
19
19
  },
20
20
  "files": [
21
21
  "dist",
package/src/index.ts CHANGED
@@ -233,24 +233,35 @@ export const sqlTargetFamilyHook = {
233
233
  const storage = ir.storage as SqlStorage;
234
234
  const models = ir.models as Record<string, ModelDefinition>;
235
235
 
236
- // Collect imports from codec types, operation types, and parameterized type imports
237
- const allImports = [...codecTypeImports, ...operationTypeImports];
236
+ // Collect all type imports from three sources:
237
+ // 1. Codec type imports (from adapters, targets, and extensions)
238
+ // 2. Operation type imports (from adapters, targets, and extensions)
239
+ // 3. Parameterized type imports (for parameterized codec renderers, may contain duplicates)
240
+ const allImports: TypesImportSpec[] = [...codecTypeImports, ...operationTypeImports];
241
+
238
242
  if (parameterizedTypeImports) {
239
243
  allImports.push(...parameterizedTypeImports);
240
244
  }
241
245
 
242
- // Deduplicate imports by package+named. When duplicates occur, the first occurrence
243
- // (and its alias) is kept; later duplicates with different aliases are silently ignored.
244
- const seenImports = new Set<string>();
246
+ // Deduplicate imports by package+named to avoid duplicate import statements.
247
+ // Strategy: When the same package::named appears multiple times, keep the first
248
+ // occurrence (and its alias); later duplicates with different aliases are silently ignored.
249
+ //
250
+ // Note: uniqueImports must be an array (not a Set) because:
251
+ // - We need to preserve the full TypesImportSpec objects (package, named, alias)
252
+ // - We need to preserve insertion order (first occurrence wins)
253
+ // - seenImportKeys is a Set used only for O(1) duplicate detection
254
+ const seenImportKeys = new Set<string>();
245
255
  const uniqueImports: TypesImportSpec[] = [];
246
256
  for (const imp of allImports) {
247
257
  const key = `${imp.package}::${imp.named}`;
248
- if (!seenImports.has(key)) {
249
- seenImports.add(key);
258
+ if (!seenImportKeys.has(key)) {
259
+ seenImportKeys.add(key);
250
260
  uniqueImports.push(imp);
251
261
  }
252
262
  }
253
263
 
264
+ // Generate import statements, omitting redundant "as Alias" when named === alias
254
265
  const importLines = uniqueImports.map((imp) => {
255
266
  // Simplify import when named === alias (e.g., `import type { Vector }` instead of `{ Vector as Vector }`)
256
267
  const importClause = imp.named === imp.alias ? imp.named : `${imp.named} as ${imp.alias}`;
@@ -266,27 +277,27 @@ export const sqlTargetFamilyHook = {
266
277
  const mappingsType = this.generateMappingsType(models, storage, codecTypes, operationTypes);
267
278
 
268
279
  return `// ⚠️ GENERATED FILE - DO NOT EDIT
269
- // This file is automatically generated by 'prisma-next contract emit'.
270
- // To regenerate, run: prisma-next contract emit
271
- ${importLines.join('\n')}
280
+ // This file is automatically generated by 'prisma-next contract emit'.
281
+ // To regenerate, run: prisma-next contract emit
282
+ ${importLines.join('\n')}
272
283
 
273
- import type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';
284
+ import type { SqlContract, SqlStorage, SqlMappings, ModelDefinition } from '@prisma-next/sql-contract/types';
274
285
 
275
- export type CodecTypes = ${codecTypes || 'Record<string, never>'};
276
- export type LaneCodecTypes = CodecTypes;
277
- export type OperationTypes = ${operationTypes || 'Record<string, never>'};
286
+ export type CodecTypes = ${codecTypes || 'Record<string, never>'};
287
+ export type LaneCodecTypes = CodecTypes;
288
+ export type OperationTypes = ${operationTypes || 'Record<string, never>'};
278
289
 
279
- export type Contract = SqlContract<
290
+ export type Contract = SqlContract<
280
291
  ${storageType},
281
292
  ${modelsType},
282
293
  ${relationsType},
283
294
  ${mappingsType}
284
- >;
295
+ >;
285
296
 
286
- export type Tables = Contract['storage']['tables'];
287
- export type Models = Contract['models'];
288
- export type Relations = Contract['relations'];
289
- `;
297
+ export type Tables = Contract['storage']['tables'];
298
+ export type Models = Contract['models'];
299
+ export type Relations = Contract['relations'];
300
+ `;
290
301
  },
291
302
 
292
303
  generateStorageType(storage: SqlStorage): string {