@eide/uniformgen 0.1.4 → 0.1.6

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":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAgEA,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyX9D"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAoEA,UAAU,WAAW;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAiZ9D"}
@@ -15,7 +15,7 @@ import { generateAdminHooksReact, generateAdminHooksRemix, generateAdminHooksInd
15
15
  // Phase 13: Platform resolve generators
16
16
  import { generatePlatformResolveReact, generatePlatformResolveRemix, generatePlatformResolveIndexReact, generatePlatformResolveIndexRemix, } from '../generators/resolve/index.js';
17
17
  // Phase 13: CMS layer generators
18
- import { getRoutableModels, generateCmsTypes, generateResolveRouteReact as generateCmsRouteReact, generateResolveRouteRemix as generateCmsRouteRemix, generateCmsIndexReact, generateCmsIndexRemix, } from '../generators/cms/index.js';
18
+ import { getRoutableModels, generateCmsTypes, generateResolveRouteReact as generateCmsRouteReact, generateResolveRouteRemix as generateCmsRouteRemix, generateEntityRoutesReact, generateEntityRoutesRemix, generateResolveEntitiesReact, generateResolveEntitiesRemix, generateCmsIndexReact, generateCmsIndexRemix, } from '../generators/cms/index.js';
19
19
  import { generateModelFilters, generateFiltersIndex, } from '../generators/filters/index.js';
20
20
  // Workflow generators
21
21
  import { generateWorkflowTypes, generateWorkflowTypesIndex, } from '../generators/types/workflows.js';
@@ -69,10 +69,21 @@ export async function sync(options) {
69
69
  if (entityModels.length > 0) {
70
70
  const modelsDir = join(config.output.types, 'models');
71
71
  for (const model of entityModels) {
72
- files.push({
73
- path: join(modelsDir, `${model.key}.ts`),
74
- content: generateEntityModelTypes(model, entityModels),
75
- });
72
+ try {
73
+ files.push({
74
+ path: join(modelsDir, `${model.key}.ts`),
75
+ content: generateEntityModelTypes(model, entityModels),
76
+ });
77
+ }
78
+ catch (error) {
79
+ console.error(chalk.red(`\nError generating types for model: ${model.key}`));
80
+ console.error(chalk.gray(` Model name: ${model.name}`));
81
+ console.error(chalk.gray(` Fields: ${model.fields?.length ?? 0}`));
82
+ if (model.fields?.length > 0) {
83
+ console.error(chalk.gray(` Field keys: ${model.fields.map(f => f.key).join(', ')}`));
84
+ }
85
+ throw error;
86
+ }
76
87
  }
77
88
  files.push({
78
89
  path: join(modelsDir, 'index.ts'),
@@ -174,6 +185,8 @@ export async function sync(options) {
174
185
  console.log(`Generating ${framework} CMS hooks for ${routableModels.length} routable models...`);
175
186
  const cmsDir = join(hooksDir, 'cms');
176
187
  const generateCmsRoute = framework === 'react' ? generateCmsRouteReact : generateCmsRouteRemix;
188
+ const generateEntityRoutes = framework === 'react' ? generateEntityRoutesReact : generateEntityRoutesRemix;
189
+ const generateResolveEntities = framework === 'react' ? generateResolveEntitiesReact : generateResolveEntitiesRemix;
177
190
  const generateCmsIndex = framework === 'react' ? generateCmsIndexReact : generateCmsIndexRemix;
178
191
  // Generate CMS types
179
192
  files.push({
@@ -185,6 +198,16 @@ export async function sync(options) {
185
198
  path: join(cmsDir, 'route.ts'),
186
199
  content: generateCmsRoute(routableModels),
187
200
  });
201
+ // Generate entity routes lookup hook/function
202
+ files.push({
203
+ path: join(cmsDir, 'entity-routes.ts'),
204
+ content: generateEntityRoutes(routableModels),
205
+ });
206
+ // Generate batch entity resolution hook/function
207
+ files.push({
208
+ path: join(cmsDir, 'resolve-entities.ts'),
209
+ content: generateResolveEntities(routableModels),
210
+ });
188
211
  // Generate CMS index
189
212
  files.push({
190
213
  path: join(cmsDir, 'index.ts'),
@@ -1 +1 @@
1
- {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/generators/admin/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAIlE;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,WAAW,EAAE,GACxB,MAAM,CA0VR;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,WAAW,EAAE,GACxB,MAAM,CAkJR"}
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/generators/admin/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAIlE;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,WAAW,EAAE,GACxB,MAAM,CA4VR;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,WAAW,EAAE,GACxB,MAAM,CAmJR"}
@@ -22,12 +22,14 @@ export function generateAdminQueriesReact(model, _allModels) {
22
22
  const pluralName = model.pluralName
23
23
  ? toCamelCase(model.pluralName.replace(/\s+/g, ''))
24
24
  : `${camelName}s`;
25
+ // Use model.name with fallback for JSDoc comments
26
+ const displayName = model.name ?? model.key;
25
27
  const lines = [];
26
28
  // File header
27
29
  lines.push(`/**`);
28
- lines.push(` * ${model.name} - Admin Query Hooks`);
30
+ lines.push(` * ${displayName} - Admin Query Hooks`);
29
31
  lines.push(` *`);
30
- lines.push(` * React hooks for querying ${model.name} records in admin UIs.`);
32
+ lines.push(` * React hooks for querying ${displayName} records in admin UIs.`);
31
33
  lines.push(` *`);
32
34
  lines.push(` * @generated by UniformGen - DO NOT EDIT MANUALLY`);
33
35
  lines.push(` */`);
@@ -52,7 +54,7 @@ export function generateAdminQueriesReact(model, _allModels) {
52
54
  lines.push(`} from './types/${model.key}.js';`);
53
55
  lines.push('');
54
56
  // List result interface
55
- lines.push(`/** List result for ${model.name} records */`);
57
+ lines.push(`/** List result for ${displayName} records */`);
56
58
  lines.push(`export interface ${typeName}ListResult {`);
57
59
  lines.push(` items: ${typeName}Record[];`);
58
60
  lines.push(` total: number;`);
@@ -231,7 +233,7 @@ export function generateAdminQueriesReact(model, _allModels) {
231
233
  lines.push('');
232
234
  // use{Model}Records hook
233
235
  lines.push(`/**`);
234
- lines.push(` * List ${model.name} records with optional filtering`);
236
+ lines.push(` * List ${displayName} records with optional filtering`);
235
237
  lines.push(` *`);
236
238
  lines.push(` * @example`);
237
239
  lines.push(` * const { ${pluralName}, loading } = use${typeName}Records({`);
@@ -281,7 +283,7 @@ export function generateAdminQueriesReact(model, _allModels) {
281
283
  lines.push('');
282
284
  // use{Model}Record hook
283
285
  lines.push(`/**`);
284
- lines.push(` * Get a single ${model.name} record with all variants`);
286
+ lines.push(` * Get a single ${displayName} record with all variants`);
285
287
  lines.push(` *`);
286
288
  lines.push(` * @example`);
287
289
  lines.push(` * const { ${camelName}, loading } = use${typeName}Record('record-id');`);
@@ -309,7 +311,7 @@ export function generateAdminQueriesReact(model, _allModels) {
309
311
  lines.push('');
310
312
  // use{Model}Versions hook
311
313
  lines.push(`/**`);
312
- lines.push(` * Get version history for a ${model.name} variant`);
314
+ lines.push(` * Get version history for a ${displayName} variant`);
313
315
  lines.push(` *`);
314
316
  lines.push(` * @example`);
315
317
  lines.push(` * const { versions, loading } = use${typeName}Versions('variant-id', { limit: 10 });`);
@@ -349,12 +351,13 @@ export function generateAdminQueriesRemix(model, _allModels) {
349
351
  return '';
350
352
  }
351
353
  const typeName = toPascalCase(model.key);
354
+ const displayName = model.name ?? model.key;
352
355
  const lines = [];
353
356
  // File header
354
357
  lines.push(`/**`);
355
- lines.push(` * ${model.name} - Admin Query Functions`);
358
+ lines.push(` * ${displayName} - Admin Query Functions`);
356
359
  lines.push(` *`);
357
- lines.push(` * Server-side functions for querying ${model.name} records.`);
360
+ lines.push(` * Server-side functions for querying ${displayName} records.`);
358
361
  lines.push(` * Use in Remix loaders or Hydrogen server functions.`);
359
362
  lines.push(` *`);
360
363
  lines.push(` * @generated by UniformGen - DO NOT EDIT MANUALLY`);
@@ -384,7 +387,7 @@ export function generateAdminQueriesRemix(model, _allModels) {
384
387
  lines.push(`}`);
385
388
  lines.push('');
386
389
  // List result interface
387
- lines.push(`/** List result for ${model.name} records */`);
390
+ lines.push(`/** List result for ${displayName} records */`);
388
391
  lines.push(`export interface ${typeName}ListResult {`);
389
392
  lines.push(` items: ${typeName}Record[];`);
390
393
  lines.push(` total: number;`);
@@ -438,7 +441,7 @@ export function generateAdminQueriesRemix(model, _allModels) {
438
441
  lines.push(`// ============================================================================`);
439
442
  lines.push('');
440
443
  lines.push(`/**`);
441
- lines.push(` * List ${model.name} records`);
444
+ lines.push(` * List ${displayName} records`);
442
445
  lines.push(` */`);
443
446
  lines.push(`export async function list${typeName}Records(`);
444
447
  lines.push(` client: GraphQLClient,`);
@@ -454,7 +457,7 @@ export function generateAdminQueriesRemix(model, _allModels) {
454
457
  lines.push(`}`);
455
458
  lines.push('');
456
459
  lines.push(`/**`);
457
- lines.push(` * Get a single ${model.name} record with variants`);
460
+ lines.push(` * Get a single ${displayName} record with variants`);
458
461
  lines.push(` */`);
459
462
  lines.push(`export async function get${typeName}Record(client: GraphQLClient, id: string): Promise<${typeName}RecordWithVariants | null> {`);
460
463
  lines.push(` const result = await client.request<{ entityRecord: any }>(GET_${typeName.toUpperCase()}_RECORD, { id });`);
@@ -462,7 +465,7 @@ export function generateAdminQueriesRemix(model, _allModels) {
462
465
  lines.push(`}`);
463
466
  lines.push('');
464
467
  lines.push(`/**`);
465
- lines.push(` * Get version history for a ${model.name} variant`);
468
+ lines.push(` * Get version history for a ${displayName} variant`);
466
469
  lines.push(` */`);
467
470
  lines.push(`export async function get${typeName}Versions(`);
468
471
  lines.push(` client: GraphQLClient,`);
@@ -492,7 +492,7 @@ export interface GetEntitiesRoutesResult {
492
492
  /**
493
493
  * GraphQL query for single entity routes
494
494
  */
495
- const GET_ENTITY_ROUTES_QUERY = gql\\\`
495
+ const GET_ENTITY_ROUTES_QUERY = gql\`
496
496
  query GetEntityRoutes($input: GetEntityRoutesInput!) {
497
497
  getEntityRoutes(input: $input) {
498
498
  naturalKey
@@ -521,12 +521,12 @@ const GET_ENTITY_ROUTES_QUERY = gql\\\`
521
521
  }
522
522
  }
523
523
  }
524
- \\\`;
524
+ \`;
525
525
 
526
526
  /**
527
527
  * GraphQL query for batch entity routes
528
528
  */
529
- const GET_ENTITIES_ROUTES_QUERY = gql\\\`
529
+ const GET_ENTITIES_ROUTES_QUERY = gql\`
530
530
  query GetEntitiesRoutes($input: GetEntitiesRoutesInput!) {
531
531
  getEntitiesRoutes(input: $input) {
532
532
  results {
@@ -545,7 +545,7 @@ const GET_ENTITIES_ROUTES_QUERY = gql\\\`
545
545
  notFound
546
546
  }
547
547
  }
548
- \\\`;
548
+ \`;
549
549
 
550
550
  /**
551
551
  * Get routes for a single entity by natural key
@@ -647,7 +647,7 @@ export function useGetEntitiesRoutes(
647
647
  /**
648
648
  * List of model keys that support route resolution
649
649
  */
650
- export const ROUTABLE_MODELS = [\${modelKeys.map(k => \\\`'\${k}'\\\`).join(', ')}] as const;
650
+ export const ROUTABLE_MODELS = [\${modelKeys.map(k => \`'\${k}'\`).join(', ')}] as const;
651
651
 
652
652
  /**
653
653
  * Type for routable model keys
@@ -752,7 +752,7 @@ const GET_ENTITY_ROUTES_QUERY = \\\`
752
752
  }
753
753
  }
754
754
  }
755
- \\\`;
755
+ \`;
756
756
 
757
757
  /**
758
758
  * GraphQL query for batch entity routes
@@ -776,7 +776,7 @@ const GET_ENTITIES_ROUTES_QUERY = \\\`
776
776
  notFound
777
777
  }
778
778
  }
779
- \\\`;
779
+ \`;
780
780
 
781
781
  /**
782
782
  * Get routes for a single entity by natural key
@@ -873,7 +873,7 @@ export async function getEntitiesRoutes(
873
873
  /**
874
874
  * List of model keys that support route resolution
875
875
  */
876
- export const ROUTABLE_MODELS = [\${modelKeys.map(k => \\\`'\${k}'\\\`).join(', ')}] as const;
876
+ export const ROUTABLE_MODELS = [\${modelKeys.map(k => \`'\${k}'\`).join(', ')}] as const;
877
877
 
878
878
  /**
879
879
  * Type for routable model keys
@@ -965,7 +965,7 @@ export interface ResolveEntitiesResult {
965
965
  /**
966
966
  * GraphQL query for batch entity resolution
967
967
  */
968
- const RESOLVE_ENTITIES_QUERY = gql\\\`
968
+ const RESOLVE_ENTITIES_QUERY = gql\`
969
969
  query ResolveEntities($input: ResolveEntitiesInput!) {
970
970
  resolveEntities(input: $input) {
971
971
  results {
@@ -1041,7 +1041,7 @@ const RESOLVE_ENTITIES_QUERY = gql\\\`
1041
1041
  }
1042
1042
  }
1043
1043
  }
1044
- \\\`;
1044
+ \`;
1045
1045
 
1046
1046
  /**
1047
1047
  * Resolve full content for multiple entities by natural key
@@ -1109,7 +1109,7 @@ export function useResolveEntities(
1109
1109
  /**
1110
1110
  * List of model keys that support content resolution
1111
1111
  */
1112
- export const ROUTABLE_MODELS = [\${modelKeys.map(k => \\\`'\${k}'\\\`).join(', ')}] as const;
1112
+ export const ROUTABLE_MODELS = [\${modelKeys.map(k => \`'\${k}'\`).join(', ')}] as const;
1113
1113
 
1114
1114
  /**
1115
1115
  * Type for routable model keys
@@ -1279,7 +1279,7 @@ const RESOLVE_ENTITIES_QUERY = \\\`
1279
1279
  }
1280
1280
  }
1281
1281
  }
1282
- \\\`;
1282
+ \`;
1283
1283
 
1284
1284
  /**
1285
1285
  * Resolve full content for multiple entities by natural key
@@ -1354,7 +1354,7 @@ export async function resolveEntities(
1354
1354
  /**
1355
1355
  * List of model keys that support content resolution
1356
1356
  */
1357
- export const ROUTABLE_MODELS = [\${modelKeys.map(k => \\\`'\${k}'\\\`).join(', ')}] as const;
1357
+ export const ROUTABLE_MODELS = [\${modelKeys.map(k => \`'\${k}'\`).join(', ')}] as const;
1358
1358
 
1359
1359
  /**
1360
1360
  * Type for routable model keys
@@ -1 +1 @@
1
- {"version":3,"file":"entity-models.d.ts","sourceRoot":"","sources":["../../../src/generators/documents/entity-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAGlE;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAkFvE"}
1
+ {"version":3,"file":"entity-models.d.ts","sourceRoot":"","sources":["../../../src/generators/documents/entity-models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAGlE;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAmFvE"}
@@ -8,7 +8,8 @@ export function generateEntityModelDocuments(model) {
8
8
  const pluralName = model.pluralName
9
9
  ? toPascalCase(model.pluralName.replace(/\s+/g, ''))
10
10
  : `${typeName}s`;
11
- return `# Generated GraphQL operations for ${model.name}
11
+ const displayName = model.name ?? model.key;
12
+ return `# Generated GraphQL operations for ${displayName}
12
13
  # @generated by UniformGen - DO NOT EDIT MANUALLY
13
14
 
14
15
  fragment ${typeName}Fields on EntityRecord {
@@ -1 +1 @@
1
- {"version":3,"file":"field-mapping.d.ts","sourceRoot":"","sources":["../../src/utils/field-mapping.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,aA+BhC,CAAC;AAEH;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CA2G1D,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,EACtC,IAAI,GAAE,QAAQ,GAAG,OAAkB,GAClC,MAAM,CAgDR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,GAC7C,GAAG,CAAC,MAAM,CAAC,CAmBb;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,GAC7C,GAAG,CAAC,MAAM,CAAC,CAmBb;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAUtD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CA4EjE"}
1
+ {"version":3,"file":"field-mapping.d.ts","sourceRoot":"","sources":["../../src/utils/field-mapping.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,aA+BhC,CAAC;AAEH;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CA2G1D,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,EACtC,IAAI,GAAE,QAAQ,GAAG,OAAkB,GAClC,MAAM,CAsDR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,GAC7C,GAAG,CAAC,MAAM,CAAC,CAmBb;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,GAC7C,GAAG,CAAC,MAAM,CAAC,CAmBb;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIhD;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWtD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,GAAG,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAqFjE"}
@@ -151,6 +151,11 @@ export const FIELD_TYPE_MAPPING = {
151
151
  * Get TypeScript type for a field
152
152
  */
153
153
  export function getFieldType(field, mode = 'output') {
154
+ // Defensive null check
155
+ if (!field?.type) {
156
+ console.warn(`Field has no type, defaulting to 'unknown'`);
157
+ return 'unknown';
158
+ }
154
159
  const mapping = FIELD_TYPE_MAPPING[field.type];
155
160
  // If not a primitive type, it's an inline schema reference
156
161
  if (!mapping) {
@@ -238,12 +243,16 @@ export function getInlineSchemaReferences(fields) {
238
243
  * Convert field ID to camelCase
239
244
  */
240
245
  export function toCamelCase(str) {
246
+ if (!str)
247
+ return 'unknown';
241
248
  return str.replace(/[-_]([a-z])/g, (_, letter) => letter.toUpperCase());
242
249
  }
243
250
  /**
244
251
  * Convert field ID to PascalCase
245
252
  */
246
253
  export function toPascalCase(str) {
254
+ if (!str)
255
+ return 'Unknown';
247
256
  const camel = toCamelCase(str);
248
257
  return camel.charAt(0).toUpperCase() + camel.slice(1);
249
258
  }
@@ -253,6 +262,8 @@ export function toPascalCase(str) {
253
262
  * Prefixes with underscore if name starts with a number.
254
263
  */
255
264
  export function sanitizeFieldName(name) {
265
+ if (!name)
266
+ return '_unknown';
256
267
  // Replace all non-alphanumeric and non-underscore characters with underscores
257
268
  let sanitized = name.replace(/[^a-zA-Z0-9_]/g, '_');
258
269
  // If starts with a number, prefix with underscore
@@ -267,10 +278,13 @@ export function sanitizeFieldName(name) {
267
278
  */
268
279
  export function generateFieldDef(field) {
269
280
  const parts = [];
270
- // Required properties
271
- parts.push(`key: '${field.key}'`);
272
- parts.push(`type: '${field.type}'`);
273
- parts.push(`label: '${field.label.replace(/'/g, "\\'")}'`);
281
+ // Required properties (with defensive null checks)
282
+ const fieldKey = field.key ?? 'unknown';
283
+ const fieldType = field.type ?? 'text';
284
+ const fieldLabel = field.label ?? field.key ?? 'Unknown';
285
+ parts.push(`key: '${fieldKey}'`);
286
+ parts.push(`type: '${fieldType}'`);
287
+ parts.push(`label: '${fieldLabel.replace(/'/g, "\\'")}'`);
274
288
  // Optional properties
275
289
  if (field.required) {
276
290
  parts.push('required: true');
@@ -301,7 +315,12 @@ export function generateFieldDef(field) {
301
315
  if ((field.type === 'select' || field.type === 'multiselect') && field.options?.options) {
302
316
  const options = field.options.options;
303
317
  const optionsStr = options
304
- .map((o) => `{ label: '${o.label.replace(/'/g, "\\'")}', value: '${o.value.replace(/'/g, "\\'")}' }`)
318
+ .filter((o) => o.value !== undefined) // Skip options without values
319
+ .map((o) => {
320
+ const label = (o.label ?? o.value ?? '').replace(/'/g, "\\'");
321
+ const value = (o.value ?? '').replace(/'/g, "\\'");
322
+ return `{ label: '${label}', value: '${value}' }`;
323
+ })
305
324
  .join(', ');
306
325
  parts.push(`options: [${optionsStr}]`);
307
326
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eide/uniformgen",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Type-safe code generator for Foir - generates TypeScript types and GraphQL operations from your project schemas",
5
5
  "type": "module",
6
6
  "publishConfig": {