@danielhritcu/zenstack-custom 1.1.0 → 1.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.
@@ -1,5 +1,5 @@
1
- import { a as DerivedModelDescriptor, E as ExtendedSchema, G as GlobalConfig, b as ModelConfig, c as ModelsOutput, M as ManyRelation, O as OneRelation, T as ThroughPath, f as ThroughRelation, A as AnyRelation, e as SearchProfile, D as DerivedField } from '../config-1Cdfs72F.cjs';
2
- export { S as SchemaConfig, d as SearchField, Z as ZenConfig, g as defineConfig } from '../config-1Cdfs72F.cjs';
1
+ import { a as DerivedModelDescriptor, E as ExtendedSchema, G as GlobalConfig, b as ModelConfig, c as ModelsOutput, M as ManyRelation, O as OneRelation, T as ThroughPath, f as ThroughRelation, A as AnyRelation, e as SearchProfile, D as DerivedField } from '../config-CRQer7hw.cjs';
2
+ export { S as SchemaConfig, d as SearchField, Z as ZenConfig, g as defineConfig } from '../config-CRQer7hw.cjs';
3
3
  import { PgTable, PgColumn, getTableConfig } from 'drizzle-orm/pg-core';
4
4
 
5
5
  declare function derived<TBase extends PgTable, const TWhere extends Record<string, unknown>>(base: TBase, opts: {
@@ -36,6 +36,7 @@ interface ModelOptions {
36
36
  defaultWhere?: Record<string, unknown>;
37
37
  derived?: Record<string, DerivedField>;
38
38
  validate?: Record<string, unknown>;
39
+ branded?: Record<string, true>;
39
40
  }
40
41
  declare function model(table: PgTable, opts: ModelOptions): ModelConfig;
41
42
  declare function defineModels(extendedSchema: {
@@ -74,7 +75,7 @@ type ThroughRelationPath = {
74
75
  [key: string]: true | ThroughRelationPath;
75
76
  };
76
77
 
77
- interface FKRelationInfo {
78
+ interface FKRelationInfo$1 {
78
79
  targetExportName: string;
79
80
  fields: string[];
80
81
  references: string[];
@@ -91,7 +92,7 @@ interface LegacyConfig {
91
92
  modelScopes: Record<string, Record<string, unknown>>;
92
93
  derivedFields: Record<string, Record<string, DerivedField>>;
93
94
  validationSchemas: Record<string, Record<string, unknown>>;
94
- fkRelations: Record<string, Record<string, FKRelationInfo>>;
95
+ fkRelations: Record<string, Record<string, FKRelationInfo$1>>;
95
96
  }
96
97
  declare function adaptToLegacyConfig(output: ModelsOutput): LegacyConfig;
97
98
 
@@ -205,11 +206,29 @@ declare function discoverViews(allViews: Record<string, unknown>): ViewInfo[];
205
206
  declare function extractFKs(table: PgTable): FKInfo[];
206
207
 
207
208
  type RelationTargets = Record<string, Record<string, string>>;
208
- declare function buildRelations(tables: TableInfo[], relationTargets?: RelationTargets, filteredRelations?: FilteredRelationsConfig, throughRelations?: ThroughRelationsConfig, fkRelations?: Record<string, Record<string, FKRelationInfo>>): {
209
+ declare function buildRelations(tables: TableInfo[], relationTargets?: RelationTargets, filteredRelations?: FilteredRelationsConfig, throughRelations?: ThroughRelationsConfig, fkRelations?: Record<string, Record<string, FKRelationInfo$1>>): {
209
210
  modelRelations: Map<string, RelationField[]>;
210
211
  inverseRelations: Map<string, RelationField[]>;
211
212
  };
212
213
 
214
+ interface FKRelationInfo {
215
+ targetExportName: string;
216
+ fields: string[];
217
+ references: string[];
218
+ relationName: string | null;
219
+ }
220
+
221
+ /**
222
+ * Branding context passed to namespace-emitting functions so they can
223
+ * produce branded ID types for UUID primary-key / foreign-key columns and
224
+ * for user-declared `branded` fields in the model config.
225
+ */
226
+ interface BrandingInfo {
227
+ /** Map of modelName -> { relName -> FKRelationInfo } */
228
+ fkRelations: Record<string, Record<string, FKRelationInfo>>;
229
+ /** Map of modelName -> { fieldName -> true } for custom branded fields */
230
+ brandedFields: Record<string, Record<string, true>>;
231
+ }
213
232
  declare function emitEnumBlock(info: EnumInfo): string;
214
233
  declare function emitFieldBlock(field: FieldInfo): string;
215
234
  declare function emitRelationField(rel: RelationField, opposite: string): string;
@@ -225,15 +244,16 @@ interface EmitSchemaOptions {
225
244
  views?: ViewInfo[];
226
245
  }
227
246
  declare function emitSchemaTs({ tables, enumMap, modelRelations, inverseRelations, searchDefaults, modelScopes, typeDefs, fieldToTypeDef, views, }: EmitSchemaOptions): string;
228
- declare function emitModelsTs(tables: TableInfo[], typedJsonFields?: TypedJsonFieldInfo[]): string;
247
+ declare function emitModelsTs(tables: TableInfo[], typedJsonFields?: TypedJsonFieldInfo[], branding?: BrandingInfo): string;
229
248
  declare function emitViewsTs(views: ViewInfo[], typedJsonFields?: TypedJsonFieldInfo[]): string;
230
249
  declare function emitInputTs(tables: TableInfo[]): string;
231
- declare function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields, }: {
250
+ declare function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields, branding, }: {
232
251
  tables: TableInfo[];
233
252
  views: ViewInfo[];
234
253
  enumMap: Map<string, EnumInfo>;
235
254
  typeDefs: Map<string, TypeDefInfo>;
236
255
  typedJsonFields: TypedJsonFieldInfo[];
256
+ branding?: BrandingInfo;
237
257
  }): string;
238
258
  declare function emitCompatTs({ tables, views, enumMap, typedJsonFields, }: {
239
259
  tables: TableInfo[];
@@ -262,4 +282,4 @@ declare function esc(s: string): string;
262
282
  declare function getDrizzleTableName(table: unknown): string;
263
283
  declare function writeFileIfChanged(filePath: string, content: string): boolean;
264
284
 
265
- export { APP_SLUG_JS, APP_SLUG_SQL, type ComputedFieldDeclaration, type ComputedFieldInfo, type ComputedFieldsConfig, DerivedField, type DerivedModelDeclaration, DerivedModelDescriptor, type DerivedModelsConfig, type EmitSchemaOptions, type EnumInfo, ExtendedSchema, type FKInfo, type FKRelationInfo, type FieldInfo, type FilteredRelationDeclaration, type FilteredRelationsConfig, GENERATED_FILE_BANNER, GlobalConfig, ManyRelation, ModelConfig, ModelsOutput, OneRelation, type RelationField, type ResolvedRelationTargets, type SearchDefaultDeclaration, type SearchDefaultsConfig, SearchProfile, type TableInfo, ThroughPath, ThroughRelation, type ThroughRelationDeclaration, type ThroughRelationPath, type ThroughRelationsConfig, type TypeDefField, type TypeDefInfo, type TypeDefMapping, type TypedJsonArtifacts, type TypedJsonFieldInfo, type ViewInfo, adaptToLegacyConfig, assertNoTypedColumnOverrides, buildRelations, buildTypeDefs, capitalize, defineModels, derived, discoverEnums, discoverTables, discoverViews, emitCompatTs, emitEnumBlock, emitEnumsTs, emitFieldBlock, emitGeneratedFileBanner, emitIndexTs, emitInputTs, emitJsonNamespaceBlock, emitJsonRawNamespaceBlock, emitJsonRawTs, emitJsonTs, emitModelsTs, emitOrmTypesTs, emitRelationField, emitSchemaTs, emitTypeDefsBlock, emitViewsTs, esc, extend, extractFKs, getDrizzleTableName, many, mapColumn, model, one, through, toPascalCase, uncapitalize, writeFileIfChanged };
285
+ export { APP_SLUG_JS, APP_SLUG_SQL, type BrandingInfo, type ComputedFieldDeclaration, type ComputedFieldInfo, type ComputedFieldsConfig, DerivedField, type DerivedModelDeclaration, DerivedModelDescriptor, type DerivedModelsConfig, type EmitSchemaOptions, type EnumInfo, ExtendedSchema, type FKInfo, type FKRelationInfo$1 as FKRelationInfo, type FieldInfo, type FilteredRelationDeclaration, type FilteredRelationsConfig, GENERATED_FILE_BANNER, GlobalConfig, ManyRelation, ModelConfig, ModelsOutput, OneRelation, type RelationField, type ResolvedRelationTargets, type SearchDefaultDeclaration, type SearchDefaultsConfig, SearchProfile, type TableInfo, ThroughPath, ThroughRelation, type ThroughRelationDeclaration, type ThroughRelationPath, type ThroughRelationsConfig, type TypeDefField, type TypeDefInfo, type TypeDefMapping, type TypedJsonArtifacts, type TypedJsonFieldInfo, type ViewInfo, adaptToLegacyConfig, assertNoTypedColumnOverrides, buildRelations, buildTypeDefs, capitalize, defineModels, derived, discoverEnums, discoverTables, discoverViews, emitCompatTs, emitEnumBlock, emitEnumsTs, emitFieldBlock, emitGeneratedFileBanner, emitIndexTs, emitInputTs, emitJsonNamespaceBlock, emitJsonRawNamespaceBlock, emitJsonRawTs, emitJsonTs, emitModelsTs, emitOrmTypesTs, emitRelationField, emitSchemaTs, emitTypeDefsBlock, emitViewsTs, esc, extend, extractFKs, getDrizzleTableName, many, mapColumn, model, one, through, toPascalCase, uncapitalize, writeFileIfChanged };
@@ -1,5 +1,5 @@
1
- import { a as DerivedModelDescriptor, E as ExtendedSchema, G as GlobalConfig, b as ModelConfig, c as ModelsOutput, M as ManyRelation, O as OneRelation, T as ThroughPath, f as ThroughRelation, A as AnyRelation, e as SearchProfile, D as DerivedField } from '../config-1Cdfs72F.js';
2
- export { S as SchemaConfig, d as SearchField, Z as ZenConfig, g as defineConfig } from '../config-1Cdfs72F.js';
1
+ import { a as DerivedModelDescriptor, E as ExtendedSchema, G as GlobalConfig, b as ModelConfig, c as ModelsOutput, M as ManyRelation, O as OneRelation, T as ThroughPath, f as ThroughRelation, A as AnyRelation, e as SearchProfile, D as DerivedField } from '../config-CRQer7hw.js';
2
+ export { S as SchemaConfig, d as SearchField, Z as ZenConfig, g as defineConfig } from '../config-CRQer7hw.js';
3
3
  import { PgTable, PgColumn, getTableConfig } from 'drizzle-orm/pg-core';
4
4
 
5
5
  declare function derived<TBase extends PgTable, const TWhere extends Record<string, unknown>>(base: TBase, opts: {
@@ -36,6 +36,7 @@ interface ModelOptions {
36
36
  defaultWhere?: Record<string, unknown>;
37
37
  derived?: Record<string, DerivedField>;
38
38
  validate?: Record<string, unknown>;
39
+ branded?: Record<string, true>;
39
40
  }
40
41
  declare function model(table: PgTable, opts: ModelOptions): ModelConfig;
41
42
  declare function defineModels(extendedSchema: {
@@ -74,7 +75,7 @@ type ThroughRelationPath = {
74
75
  [key: string]: true | ThroughRelationPath;
75
76
  };
76
77
 
77
- interface FKRelationInfo {
78
+ interface FKRelationInfo$1 {
78
79
  targetExportName: string;
79
80
  fields: string[];
80
81
  references: string[];
@@ -91,7 +92,7 @@ interface LegacyConfig {
91
92
  modelScopes: Record<string, Record<string, unknown>>;
92
93
  derivedFields: Record<string, Record<string, DerivedField>>;
93
94
  validationSchemas: Record<string, Record<string, unknown>>;
94
- fkRelations: Record<string, Record<string, FKRelationInfo>>;
95
+ fkRelations: Record<string, Record<string, FKRelationInfo$1>>;
95
96
  }
96
97
  declare function adaptToLegacyConfig(output: ModelsOutput): LegacyConfig;
97
98
 
@@ -205,11 +206,29 @@ declare function discoverViews(allViews: Record<string, unknown>): ViewInfo[];
205
206
  declare function extractFKs(table: PgTable): FKInfo[];
206
207
 
207
208
  type RelationTargets = Record<string, Record<string, string>>;
208
- declare function buildRelations(tables: TableInfo[], relationTargets?: RelationTargets, filteredRelations?: FilteredRelationsConfig, throughRelations?: ThroughRelationsConfig, fkRelations?: Record<string, Record<string, FKRelationInfo>>): {
209
+ declare function buildRelations(tables: TableInfo[], relationTargets?: RelationTargets, filteredRelations?: FilteredRelationsConfig, throughRelations?: ThroughRelationsConfig, fkRelations?: Record<string, Record<string, FKRelationInfo$1>>): {
209
210
  modelRelations: Map<string, RelationField[]>;
210
211
  inverseRelations: Map<string, RelationField[]>;
211
212
  };
212
213
 
214
+ interface FKRelationInfo {
215
+ targetExportName: string;
216
+ fields: string[];
217
+ references: string[];
218
+ relationName: string | null;
219
+ }
220
+
221
+ /**
222
+ * Branding context passed to namespace-emitting functions so they can
223
+ * produce branded ID types for UUID primary-key / foreign-key columns and
224
+ * for user-declared `branded` fields in the model config.
225
+ */
226
+ interface BrandingInfo {
227
+ /** Map of modelName -> { relName -> FKRelationInfo } */
228
+ fkRelations: Record<string, Record<string, FKRelationInfo>>;
229
+ /** Map of modelName -> { fieldName -> true } for custom branded fields */
230
+ brandedFields: Record<string, Record<string, true>>;
231
+ }
213
232
  declare function emitEnumBlock(info: EnumInfo): string;
214
233
  declare function emitFieldBlock(field: FieldInfo): string;
215
234
  declare function emitRelationField(rel: RelationField, opposite: string): string;
@@ -225,15 +244,16 @@ interface EmitSchemaOptions {
225
244
  views?: ViewInfo[];
226
245
  }
227
246
  declare function emitSchemaTs({ tables, enumMap, modelRelations, inverseRelations, searchDefaults, modelScopes, typeDefs, fieldToTypeDef, views, }: EmitSchemaOptions): string;
228
- declare function emitModelsTs(tables: TableInfo[], typedJsonFields?: TypedJsonFieldInfo[]): string;
247
+ declare function emitModelsTs(tables: TableInfo[], typedJsonFields?: TypedJsonFieldInfo[], branding?: BrandingInfo): string;
229
248
  declare function emitViewsTs(views: ViewInfo[], typedJsonFields?: TypedJsonFieldInfo[]): string;
230
249
  declare function emitInputTs(tables: TableInfo[]): string;
231
- declare function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields, }: {
250
+ declare function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields, branding, }: {
232
251
  tables: TableInfo[];
233
252
  views: ViewInfo[];
234
253
  enumMap: Map<string, EnumInfo>;
235
254
  typeDefs: Map<string, TypeDefInfo>;
236
255
  typedJsonFields: TypedJsonFieldInfo[];
256
+ branding?: BrandingInfo;
237
257
  }): string;
238
258
  declare function emitCompatTs({ tables, views, enumMap, typedJsonFields, }: {
239
259
  tables: TableInfo[];
@@ -262,4 +282,4 @@ declare function esc(s: string): string;
262
282
  declare function getDrizzleTableName(table: unknown): string;
263
283
  declare function writeFileIfChanged(filePath: string, content: string): boolean;
264
284
 
265
- export { APP_SLUG_JS, APP_SLUG_SQL, type ComputedFieldDeclaration, type ComputedFieldInfo, type ComputedFieldsConfig, DerivedField, type DerivedModelDeclaration, DerivedModelDescriptor, type DerivedModelsConfig, type EmitSchemaOptions, type EnumInfo, ExtendedSchema, type FKInfo, type FKRelationInfo, type FieldInfo, type FilteredRelationDeclaration, type FilteredRelationsConfig, GENERATED_FILE_BANNER, GlobalConfig, ManyRelation, ModelConfig, ModelsOutput, OneRelation, type RelationField, type ResolvedRelationTargets, type SearchDefaultDeclaration, type SearchDefaultsConfig, SearchProfile, type TableInfo, ThroughPath, ThroughRelation, type ThroughRelationDeclaration, type ThroughRelationPath, type ThroughRelationsConfig, type TypeDefField, type TypeDefInfo, type TypeDefMapping, type TypedJsonArtifacts, type TypedJsonFieldInfo, type ViewInfo, adaptToLegacyConfig, assertNoTypedColumnOverrides, buildRelations, buildTypeDefs, capitalize, defineModels, derived, discoverEnums, discoverTables, discoverViews, emitCompatTs, emitEnumBlock, emitEnumsTs, emitFieldBlock, emitGeneratedFileBanner, emitIndexTs, emitInputTs, emitJsonNamespaceBlock, emitJsonRawNamespaceBlock, emitJsonRawTs, emitJsonTs, emitModelsTs, emitOrmTypesTs, emitRelationField, emitSchemaTs, emitTypeDefsBlock, emitViewsTs, esc, extend, extractFKs, getDrizzleTableName, many, mapColumn, model, one, through, toPascalCase, uncapitalize, writeFileIfChanged };
285
+ export { APP_SLUG_JS, APP_SLUG_SQL, type BrandingInfo, type ComputedFieldDeclaration, type ComputedFieldInfo, type ComputedFieldsConfig, DerivedField, type DerivedModelDeclaration, DerivedModelDescriptor, type DerivedModelsConfig, type EmitSchemaOptions, type EnumInfo, ExtendedSchema, type FKInfo, type FKRelationInfo$1 as FKRelationInfo, type FieldInfo, type FilteredRelationDeclaration, type FilteredRelationsConfig, GENERATED_FILE_BANNER, GlobalConfig, ManyRelation, ModelConfig, ModelsOutput, OneRelation, type RelationField, type ResolvedRelationTargets, type SearchDefaultDeclaration, type SearchDefaultsConfig, SearchProfile, type TableInfo, ThroughPath, ThroughRelation, type ThroughRelationDeclaration, type ThroughRelationPath, type ThroughRelationsConfig, type TypeDefField, type TypeDefInfo, type TypeDefMapping, type TypedJsonArtifacts, type TypedJsonFieldInfo, type ViewInfo, adaptToLegacyConfig, assertNoTypedColumnOverrides, buildRelations, buildTypeDefs, capitalize, defineModels, derived, discoverEnums, discoverTables, discoverViews, emitCompatTs, emitEnumBlock, emitEnumsTs, emitFieldBlock, emitGeneratedFileBanner, emitIndexTs, emitInputTs, emitJsonNamespaceBlock, emitJsonRawNamespaceBlock, emitJsonRawTs, emitJsonTs, emitModelsTs, emitOrmTypesTs, emitRelationField, emitSchemaTs, emitTypeDefsBlock, emitViewsTs, esc, extend, extractFKs, getDrizzleTableName, many, mapColumn, model, one, through, toPascalCase, uncapitalize, writeFileIfChanged };
@@ -138,7 +138,8 @@ function model(table, opts) {
138
138
  search: opts.search,
139
139
  defaultWhere: opts.defaultWhere,
140
140
  derived: opts.derived,
141
- validate: opts.validate
141
+ validate: opts.validate,
142
+ branded: opts.branded
142
143
  };
143
144
  }
144
145
  __name(model, "model");
@@ -1690,6 +1691,32 @@ __name(sortTypedJsonFields, "sortTypedJsonFields");
1690
1691
 
1691
1692
  // src/codegen/emit.ts
1692
1693
  var DB_ATTR_RE = /@db\.(\w+)(?:\((\d+)\))?/;
1694
+ function isUuidField(t, fieldName) {
1695
+ const col = t.table[fieldName];
1696
+ if (!col) return false;
1697
+ return col.columnType === "PgUUID";
1698
+ }
1699
+ __name(isUuidField, "isUuidField");
1700
+ function isPkField(t, fieldName) {
1701
+ const col = t.table[fieldName];
1702
+ if (!col) return false;
1703
+ if (col.primary) return true;
1704
+ const sqlName = col.name;
1705
+ return t.cfg.primaryKeys.some((pk) => pk.columns.some((c) => c.name === sqlName));
1706
+ }
1707
+ __name(isPkField, "isPkField");
1708
+ function findFkTarget(t, fieldName, fkRelations) {
1709
+ const modelFks = fkRelations[t.modelName];
1710
+ if (!modelFks) return null;
1711
+ for (const fkInfo of Object.values(modelFks)) {
1712
+ const idx = fkInfo.fields.indexOf(fieldName);
1713
+ if (idx >= 0) {
1714
+ return fkInfo.targetExportName;
1715
+ }
1716
+ }
1717
+ return null;
1718
+ }
1719
+ __name(findFkTarget, "findFkTarget");
1693
1720
  function buildDerivedEnumName(modelName, fieldName) {
1694
1721
  return `${toPascalCase(modelName)}${toPascalCase(fieldName)}`;
1695
1722
  }
@@ -2185,8 +2212,9 @@ function emitSchemaTs({ tables, enumMap, modelRelations, inverseRelations, searc
2185
2212
  return out.join("\n");
2186
2213
  }
2187
2214
  __name(emitSchemaTs, "emitSchemaTs");
2188
- function emitModelsTs(tables, typedJsonFields = []) {
2215
+ function emitModelsTs(tables, typedJsonFields = [], branding) {
2189
2216
  const jsonFieldAliases = createJsonFieldAliasMap(typedJsonFields);
2217
+ const hasBranding = branding && (Object.keys(branding.brandedFields).length > 0 || tables.some((t) => getEntityFieldNames(t).some((f) => isUuidField(t, f) && isPkField(t, f))));
2190
2218
  const out = [
2191
2219
  ...emitGeneratedFileBanner()
2192
2220
  ];
@@ -2194,6 +2222,10 @@ function emitModelsTs(tables, typedJsonFields = []) {
2194
2222
  out.push('import type * as $ from "@zenstackhq/orm";');
2195
2223
  out.push('import type * as Json from "./json";');
2196
2224
  out.push('import { type SchemaType as Schema } from "./schema";');
2225
+ if (hasBranding) {
2226
+ out.push("");
2227
+ out.push("declare const __brand: unique symbol;");
2228
+ }
2197
2229
  out.push("");
2198
2230
  for (const t of tables) {
2199
2231
  out.push(`export interface ${t.typeName} extends $.ModelResult<Schema, ${esc(t.modelName)}> {}`);
@@ -2204,7 +2236,12 @@ function emitModelsTs(tables, typedJsonFields = []) {
2204
2236
  if (jsonAlias) {
2205
2237
  out.push(` export interface ${exportName} extends Json.${jsonAlias} {}`);
2206
2238
  } else {
2207
- out.push(` export type ${exportName} = ${t.typeName}[${esc(fieldName)}];`);
2239
+ const brandedLine = branding ? emitBrandedFieldLine(t, fieldName, exportName, branding, " ") : null;
2240
+ if (brandedLine) {
2241
+ out.push(...brandedLine);
2242
+ } else {
2243
+ out.push(` export type ${exportName} = ${t.typeName}[${esc(fieldName)}];`);
2244
+ }
2208
2245
  }
2209
2246
  }
2210
2247
  out.push("}");
@@ -2213,6 +2250,33 @@ function emitModelsTs(tables, typedJsonFields = []) {
2213
2250
  return out.join("\n");
2214
2251
  }
2215
2252
  __name(emitModelsTs, "emitModelsTs");
2253
+ function emitBrandedFieldLine(t, fieldName, exportName, branding, indent) {
2254
+ const customBranded = branding.brandedFields[t.modelName]?.[fieldName];
2255
+ if (isUuidField(t, fieldName) && isPkField(t, fieldName)) {
2256
+ const brand = `${t.modelName}.${fieldName}`;
2257
+ return [
2258
+ `${indent}export type ${exportName} = string & { [__brand]: '${brand}' };`,
2259
+ `${indent}export const ${exportName} = (id: string): ${exportName} => id as ${exportName};`
2260
+ ];
2261
+ }
2262
+ if (isUuidField(t, fieldName)) {
2263
+ const targetExportName = findFkTarget(t, fieldName, branding.fkRelations);
2264
+ if (targetExportName) {
2265
+ return [
2266
+ `${indent}export type ${exportName} = ${targetExportName}.Id;`
2267
+ ];
2268
+ }
2269
+ }
2270
+ if (customBranded) {
2271
+ const brand = `${t.modelName}.${fieldName}`;
2272
+ return [
2273
+ `${indent}export type ${exportName} = string & { [__brand]: '${brand}' };`,
2274
+ `${indent}export const ${exportName} = (id: string): ${exportName} => id as ${exportName};`
2275
+ ];
2276
+ }
2277
+ return null;
2278
+ }
2279
+ __name(emitBrandedFieldLine, "emitBrandedFieldLine");
2216
2280
  function emitViewsTs(views, typedJsonFields = []) {
2217
2281
  const jsonFieldAliases = createJsonFieldAliasMap(typedJsonFields);
2218
2282
  const out = [
@@ -2278,12 +2342,13 @@ function emitInputTs(tables) {
2278
2342
  return out.join("\n");
2279
2343
  }
2280
2344
  __name(emitInputTs, "emitInputTs");
2281
- function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields }) {
2345
+ function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields, branding }) {
2282
2346
  const allEnums = new Map([
2283
2347
  ...enumMap,
2284
2348
  ...collectDerivedEnums(tables, enumMap)
2285
2349
  ]);
2286
2350
  const jsonFieldAliases = createJsonFieldAliasMap(typedJsonFields);
2351
+ const hasBranding = branding && (Object.keys(branding.brandedFields).length > 0 || tables.some((t) => getEntityFieldNames(t).some((f) => isUuidField(t, f) && isPkField(t, f))));
2287
2352
  const out = [
2288
2353
  ...emitGeneratedFileBanner()
2289
2354
  ];
@@ -2291,6 +2356,10 @@ function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields }) {
2291
2356
  out.push('import type * as $ from "@zenstackhq/orm";');
2292
2357
  out.push('import type * as RawJson from "../../supabase/schema/types";');
2293
2358
  out.push('import { type SchemaType as Schema } from "./schema";');
2359
+ if (hasBranding) {
2360
+ out.push("");
2361
+ out.push("declare const __brand: unique symbol;");
2362
+ }
2294
2363
  out.push("");
2295
2364
  out.push("export namespace Json {");
2296
2365
  out.push(...emitJsonNamespaceBlock(typeDefs, typedJsonFields, " "));
@@ -2305,7 +2374,7 @@ function emitIndexTs({ tables, views, enumMap, typeDefs, typedJsonFields }) {
2305
2374
  out.push("");
2306
2375
  out.push("export namespace Table {");
2307
2376
  for (const table of tables) {
2308
- out.push(...emitEntityNamespaceBlock(table, table.modelName, jsonFieldAliases, " "));
2377
+ out.push(...emitEntityNamespaceBlock(table, table.modelName, jsonFieldAliases, " ", branding));
2309
2378
  out.push("");
2310
2379
  }
2311
2380
  out.push("}");
@@ -2464,7 +2533,7 @@ function createJsonFieldAliasMap(typedJsonFields) {
2464
2533
  ]));
2465
2534
  }
2466
2535
  __name(createJsonFieldAliasMap, "createJsonFieldAliasMap");
2467
- function emitEntityNamespaceBlock(entity, modelName, jsonFieldAliases, indent = "") {
2536
+ function emitEntityNamespaceBlock(entity, modelName, jsonFieldAliases, indent = "", branding) {
2468
2537
  const out = [];
2469
2538
  out.push(`${indent}export interface ${entity.typeName} extends $.ModelResult<Schema, ${esc(modelName)}> {}`);
2470
2539
  out.push(`${indent}export namespace ${entity.typeName} {`);
@@ -2474,7 +2543,13 @@ function emitEntityNamespaceBlock(entity, modelName, jsonFieldAliases, indent =
2474
2543
  if (jsonAlias) {
2475
2544
  out.push(`${indent} export interface ${exportName} extends Json.${jsonAlias} {}`);
2476
2545
  } else {
2477
- out.push(`${indent} export type ${exportName} = ${entity.typeName}[${esc(fieldName)}];`);
2546
+ const isTable = "table" in entity;
2547
+ const brandedLine = isTable && branding ? emitBrandedFieldLine(entity, fieldName, exportName, branding, `${indent} `) : null;
2548
+ if (brandedLine) {
2549
+ out.push(...brandedLine);
2550
+ } else {
2551
+ out.push(`${indent} export type ${exportName} = ${entity.typeName}[${esc(fieldName)}];`);
2552
+ }
2478
2553
  }
2479
2554
  }
2480
2555
  out.push(`${indent}}`);