@constructive-io/graphql-codegen 4.14.0 → 4.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,19 +1,5 @@
1
1
  import type { CleanTable, TypeRegistry } from '../../../types/schema';
2
2
  import type { GeneratedFile } from './executor-generator';
3
- /**
4
- * Get the set of field names that have defaults in the create input type.
5
- * Looks up the CreateXInput -> inner input type (e.g. DatabaseInput) in the
6
- * TypeRegistry and checks each field's defaultValue from introspection.
7
- */
8
- /**
9
- * Resolve the inner input type from a CreateXInput or UpdateXInput type.
10
- * The CreateXInput has an inner field (e.g. "database" of type DatabaseInput)
11
- * that contains the actual field definitions.
12
- */
13
- export declare function resolveInnerInputType(inputTypeName: string, typeRegistry: TypeRegistry): {
14
- name: string;
15
- fields: Set<string>;
16
- } | null;
17
3
  export declare function getFieldsWithDefaults(table: CleanTable, typeRegistry?: TypeRegistry): Set<string>;
18
4
  export interface TableCommandOptions {
19
5
  targetName?: string;
@@ -33,7 +33,6 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.resolveInnerInputType = resolveInnerInputType;
37
36
  exports.getFieldsWithDefaults = getFieldsWithDefaults;
38
37
  exports.generateTableCommand = generateTableCommand;
39
38
  const t = __importStar(require("@babel/types"));
@@ -150,8 +149,8 @@ function buildFieldSchemaObject(table) {
150
149
  return t.objectProperty(t.identifier(f.name), t.stringLiteral(schemaType));
151
150
  }));
152
151
  }
153
- function buildSelectObject(table) {
154
- const fields = (0, utils_1.getScalarFields)(table);
152
+ function buildSelectObject(table, typeRegistry) {
153
+ const fields = (0, utils_1.getSelectableScalarFields)(table, typeRegistry);
155
154
  return t.objectExpression(fields.map((f) => t.objectProperty(t.identifier(f.name), t.booleanLiteral(true))));
156
155
  }
157
156
  function buildJsonLog(expr) {
@@ -202,9 +201,9 @@ function buildSubcommandSwitch(subcommands, handlerPrefix, usageVarName) {
202
201
  ]));
203
202
  return t.switchStatement(t.identifier('subcommand'), cases);
204
203
  }
205
- function buildListHandler(table, targetName) {
204
+ function buildListHandler(table, targetName, typeRegistry) {
206
205
  const { singularName } = (0, utils_1.getTableNames)(table);
207
- const selectObj = buildSelectObject(table);
206
+ const selectObj = buildSelectObject(table, typeRegistry);
208
207
  const tryBody = [
209
208
  buildGetClientStatement(targetName),
210
209
  t.variableDeclaration('const', [
@@ -222,11 +221,11 @@ function buildListHandler(table, targetName) {
222
221
  t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Failed to list records.')),
223
222
  ]), false, true);
224
223
  }
225
- function buildGetHandler(table, targetName) {
224
+ function buildGetHandler(table, targetName, typeRegistry) {
226
225
  const { singularName } = (0, utils_1.getTableNames)(table);
227
226
  const pkFields = (0, utils_1.getPrimaryKeyInfo)(table);
228
227
  const pk = pkFields[0];
229
- const selectObj = buildSelectObject(table);
228
+ const selectObj = buildSelectObject(table, typeRegistry);
230
229
  const promptQuestion = t.objectExpression([
231
230
  t.objectProperty(t.identifier('type'), t.stringLiteral('text')),
232
231
  t.objectProperty(t.identifier('name'), t.stringLiteral(pk.name)),
@@ -258,40 +257,12 @@ function buildGetHandler(table, targetName) {
258
257
  t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Record not found.')),
259
258
  ]), false, true);
260
259
  }
261
- /**
262
- * Get the set of field names that have defaults in the create input type.
263
- * Looks up the CreateXInput -> inner input type (e.g. DatabaseInput) in the
264
- * TypeRegistry and checks each field's defaultValue from introspection.
265
- */
266
- /**
267
- * Resolve the inner input type from a CreateXInput or UpdateXInput type.
268
- * The CreateXInput has an inner field (e.g. "database" of type DatabaseInput)
269
- * that contains the actual field definitions.
270
- */
271
- function resolveInnerInputType(inputTypeName, typeRegistry) {
272
- const inputType = typeRegistry.get(inputTypeName);
273
- if (!inputType?.inputFields)
274
- return null;
275
- for (const inputField of inputType.inputFields) {
276
- const innerTypeName = inputField.type.name
277
- || inputField.type.ofType?.name
278
- || inputField.type.ofType?.ofType?.name;
279
- if (!innerTypeName)
280
- continue;
281
- const innerType = typeRegistry.get(innerTypeName);
282
- if (!innerType?.inputFields)
283
- continue;
284
- const fields = new Set(innerType.inputFields.map((f) => f.name));
285
- return { name: innerTypeName, fields };
286
- }
287
- return null;
288
- }
289
260
  function getFieldsWithDefaults(table, typeRegistry) {
290
261
  const fieldsWithDefaults = new Set();
291
262
  if (!typeRegistry)
292
263
  return fieldsWithDefaults;
293
264
  const createInputTypeName = (0, utils_1.getCreateInputTypeName)(table);
294
- const resolved = resolveInnerInputType(createInputTypeName, typeRegistry);
265
+ const resolved = (0, utils_1.resolveInnerInputType)(createInputTypeName, typeRegistry);
295
266
  if (!resolved)
296
267
  return fieldsWithDefaults;
297
268
  const innerType = typeRegistry.get(resolved.name);
@@ -307,18 +278,6 @@ function getFieldsWithDefaults(table, typeRegistry) {
307
278
  }
308
279
  return fieldsWithDefaults;
309
280
  }
310
- /**
311
- * Get the set of field names that actually exist in the create/update input type.
312
- * Fields not in this set (e.g. computed fields like searchTsvRank, hashUuid)
313
- * should be excluded from the data object in create/update handlers.
314
- */
315
- function getWritableFieldNames(table, typeRegistry) {
316
- if (!typeRegistry)
317
- return null;
318
- const createInputTypeName = (0, utils_1.getCreateInputTypeName)(table);
319
- const resolved = resolveInnerInputType(createInputTypeName, typeRegistry);
320
- return resolved?.fields ?? null;
321
- }
322
281
  function buildMutationHandler(table, operation, targetName, typeRegistry, ormTypes) {
323
282
  const { singularName } = (0, utils_1.getTableNames)(table);
324
283
  const pkFields = (0, utils_1.getPrimaryKeyInfo)(table);
@@ -326,7 +285,7 @@ function buildMutationHandler(table, operation, targetName, typeRegistry, ormTyp
326
285
  // Get the set of writable field names from the type registry
327
286
  // This filters out computed fields (e.g. searchTsvRank, hashUuid) that exist
328
287
  // on the entity type but not on the create/update input type.
329
- const writableFields = getWritableFieldNames(table, typeRegistry);
288
+ const writableFields = (0, utils_1.getWritableFieldNames)(table, typeRegistry);
330
289
  // Get fields that have defaults from introspection (for create operations)
331
290
  const fieldsWithDefaults = getFieldsWithDefaults(table, typeRegistry);
332
291
  // For create: include fields that are in the create input type.
@@ -379,7 +338,7 @@ function buildMutationHandler(table, operation, targetName, typeRegistry, ormTyp
379
338
  ? t.objectExpression([
380
339
  t.objectProperty(t.identifier(pk.name), t.booleanLiteral(true)),
381
340
  ])
382
- : buildSelectObject(table);
341
+ : buildSelectObject(table, typeRegistry);
383
342
  let ormArgs;
384
343
  // Build data properties without individual type assertions.
385
344
  // Instead, we build a plain object from cleanedData and cast the entire
@@ -587,9 +546,9 @@ function generateTableCommand(table, options) {
587
546
  ]), false, true));
588
547
  const tn = options?.targetName;
589
548
  const ormTypes = { createInputTypeName, patchTypeName, innerFieldName };
590
- statements.push(buildListHandler(table, tn));
549
+ statements.push(buildListHandler(table, tn, options?.typeRegistry));
591
550
  if (hasGet)
592
- statements.push(buildGetHandler(table, tn));
551
+ statements.push(buildGetHandler(table, tn, options?.typeRegistry));
593
552
  statements.push(buildMutationHandler(table, 'create', tn, options?.typeRegistry, ormTypes));
594
553
  if (hasUpdate)
595
554
  statements.push(buildMutationHandler(table, 'update', tn, options?.typeRegistry, ormTypes));
@@ -1,4 +1,4 @@
1
- import type { CleanField, CleanFieldType, CleanTable } from '../../types/schema';
1
+ import type { CleanField, CleanFieldType, CleanTable, TypeRegistry } from '../../types/schema';
2
2
  /** Lowercase first character */
3
3
  export declare function lcFirst(str: string): string;
4
4
  /** Uppercase first character */
@@ -148,6 +148,31 @@ export declare function isRelationField(fieldName: string, table: CleanTable): b
148
148
  * Get only scalar fields (non-relation fields)
149
149
  */
150
150
  export declare function getScalarFields(table: CleanTable): CleanField[];
151
+ /**
152
+ * Resolve the inner input type from a CreateXInput.
153
+ * PostGraphile create inputs wrap the actual field definitions in an inner type
154
+ * (e.g. CreateUserInput -> { user: UserInput }) — this resolves that inner type
155
+ * and returns the set of field names it contains.
156
+ */
157
+ export declare function resolveInnerInputType(inputTypeName: string, typeRegistry: TypeRegistry): {
158
+ name: string;
159
+ fields: Set<string>;
160
+ } | null;
161
+ /**
162
+ * Get the set of field names that actually exist in the create input type.
163
+ * Fields not in this set (e.g. computed fields like searchTsvRank, hashUuid)
164
+ * are plugin-added computed fields that don't correspond to real database columns.
165
+ * Returns null when no typeRegistry is provided (caller should treat as "no filtering").
166
+ */
167
+ export declare function getWritableFieldNames(table: CleanTable, typeRegistry?: TypeRegistry): Set<string> | null;
168
+ /**
169
+ * Get scalar fields that represent actual database columns (not computed/plugin-added).
170
+ * When a TypeRegistry is provided, filters out fields that don't exist in the
171
+ * create input type — these are computed fields added by plugins (e.g. search scores,
172
+ * hash UUIDs) that aren't real columns and shouldn't appear in default selections.
173
+ * Without a TypeRegistry, falls back to all scalar fields.
174
+ */
175
+ export declare function getSelectableScalarFields(table: CleanTable, typeRegistry?: TypeRegistry): CleanField[];
151
176
  /**
152
177
  * Primary key field information
153
178
  */
@@ -33,6 +33,9 @@ exports.fieldTypeToTs = fieldTypeToTs;
33
33
  exports.getScalarFilterType = getScalarFilterType;
34
34
  exports.isRelationField = isRelationField;
35
35
  exports.getScalarFields = getScalarFields;
36
+ exports.resolveInnerInputType = resolveInnerInputType;
37
+ exports.getWritableFieldNames = getWritableFieldNames;
38
+ exports.getSelectableScalarFields = getSelectableScalarFields;
36
39
  exports.getPrimaryKeyInfo = getPrimaryKeyInfo;
37
40
  exports.getPrimaryKeyFields = getPrimaryKeyFields;
38
41
  exports.hasValidPrimaryKey = hasValidPrimaryKey;
@@ -303,6 +306,54 @@ function isRelationField(fieldName, table) {
303
306
  function getScalarFields(table) {
304
307
  return table.fields.filter((f) => !isRelationField(f.name, table));
305
308
  }
309
+ /**
310
+ * Resolve the inner input type from a CreateXInput.
311
+ * PostGraphile create inputs wrap the actual field definitions in an inner type
312
+ * (e.g. CreateUserInput -> { user: UserInput }) — this resolves that inner type
313
+ * and returns the set of field names it contains.
314
+ */
315
+ function resolveInnerInputType(inputTypeName, typeRegistry) {
316
+ const inputType = typeRegistry.get(inputTypeName);
317
+ if (!inputType?.inputFields)
318
+ return null;
319
+ for (const inputField of inputType.inputFields) {
320
+ const innerTypeName = inputField.type.name
321
+ || inputField.type.ofType?.name
322
+ || inputField.type.ofType?.ofType?.name;
323
+ if (!innerTypeName)
324
+ continue;
325
+ const innerType = typeRegistry.get(innerTypeName);
326
+ if (!innerType?.inputFields)
327
+ continue;
328
+ const fields = new Set(innerType.inputFields.map((f) => f.name));
329
+ return { name: innerTypeName, fields };
330
+ }
331
+ return null;
332
+ }
333
+ /**
334
+ * Get the set of field names that actually exist in the create input type.
335
+ * Fields not in this set (e.g. computed fields like searchTsvRank, hashUuid)
336
+ * are plugin-added computed fields that don't correspond to real database columns.
337
+ * Returns null when no typeRegistry is provided (caller should treat as "no filtering").
338
+ */
339
+ function getWritableFieldNames(table, typeRegistry) {
340
+ if (!typeRegistry)
341
+ return null;
342
+ const createInputTypeName = getCreateInputTypeName(table);
343
+ const resolved = resolveInnerInputType(createInputTypeName, typeRegistry);
344
+ return resolved?.fields ?? null;
345
+ }
346
+ /**
347
+ * Get scalar fields that represent actual database columns (not computed/plugin-added).
348
+ * When a TypeRegistry is provided, filters out fields that don't exist in the
349
+ * create input type — these are computed fields added by plugins (e.g. search scores,
350
+ * hash UUIDs) that aren't real columns and shouldn't appear in default selections.
351
+ * Without a TypeRegistry, falls back to all scalar fields.
352
+ */
353
+ function getSelectableScalarFields(table, typeRegistry) {
354
+ const writableFields = getWritableFieldNames(table, typeRegistry);
355
+ return getScalarFields(table).filter((f) => writableFields === null || writableFields.has(f.name));
356
+ }
306
357
  /**
307
358
  * Get primary key field information from table constraints
308
359
  * Returns array to support composite primary keys
@@ -1,19 +1,5 @@
1
1
  import type { CleanTable, TypeRegistry } from '../../../types/schema';
2
2
  import type { GeneratedFile } from './executor-generator';
3
- /**
4
- * Get the set of field names that have defaults in the create input type.
5
- * Looks up the CreateXInput -> inner input type (e.g. DatabaseInput) in the
6
- * TypeRegistry and checks each field's defaultValue from introspection.
7
- */
8
- /**
9
- * Resolve the inner input type from a CreateXInput or UpdateXInput type.
10
- * The CreateXInput has an inner field (e.g. "database" of type DatabaseInput)
11
- * that contains the actual field definitions.
12
- */
13
- export declare function resolveInnerInputType(inputTypeName: string, typeRegistry: TypeRegistry): {
14
- name: string;
15
- fields: Set<string>;
16
- } | null;
17
3
  export declare function getFieldsWithDefaults(table: CleanTable, typeRegistry?: TypeRegistry): Set<string>;
18
4
  export interface TableCommandOptions {
19
5
  targetName?: string;
@@ -1,7 +1,7 @@
1
1
  import * as t from '@babel/types';
2
2
  import { toKebabCase } from 'komoji';
3
3
  import { generateCode } from '../babel-ast';
4
- import { getGeneratedFileHeader, getPrimaryKeyInfo, getScalarFields, getTableNames, ucFirst, lcFirst, getCreateInputTypeName, getPatchTypeName, } from '../utils';
4
+ import { getGeneratedFileHeader, getPrimaryKeyInfo, getScalarFields, getSelectableScalarFields, getTableNames, getWritableFieldNames, resolveInnerInputType, ucFirst, lcFirst, getCreateInputTypeName, getPatchTypeName, } from '../utils';
5
5
  function createImportDeclaration(moduleSpecifier, namedImports, typeOnly = false) {
6
6
  const specifiers = namedImports.map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
7
7
  const decl = t.importDeclaration(specifiers, t.stringLiteral(moduleSpecifier));
@@ -112,8 +112,8 @@ function buildFieldSchemaObject(table) {
112
112
  return t.objectProperty(t.identifier(f.name), t.stringLiteral(schemaType));
113
113
  }));
114
114
  }
115
- function buildSelectObject(table) {
116
- const fields = getScalarFields(table);
115
+ function buildSelectObject(table, typeRegistry) {
116
+ const fields = getSelectableScalarFields(table, typeRegistry);
117
117
  return t.objectExpression(fields.map((f) => t.objectProperty(t.identifier(f.name), t.booleanLiteral(true))));
118
118
  }
119
119
  function buildJsonLog(expr) {
@@ -164,9 +164,9 @@ function buildSubcommandSwitch(subcommands, handlerPrefix, usageVarName) {
164
164
  ]));
165
165
  return t.switchStatement(t.identifier('subcommand'), cases);
166
166
  }
167
- function buildListHandler(table, targetName) {
167
+ function buildListHandler(table, targetName, typeRegistry) {
168
168
  const { singularName } = getTableNames(table);
169
- const selectObj = buildSelectObject(table);
169
+ const selectObj = buildSelectObject(table, typeRegistry);
170
170
  const tryBody = [
171
171
  buildGetClientStatement(targetName),
172
172
  t.variableDeclaration('const', [
@@ -184,11 +184,11 @@ function buildListHandler(table, targetName) {
184
184
  t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Failed to list records.')),
185
185
  ]), false, true);
186
186
  }
187
- function buildGetHandler(table, targetName) {
187
+ function buildGetHandler(table, targetName, typeRegistry) {
188
188
  const { singularName } = getTableNames(table);
189
189
  const pkFields = getPrimaryKeyInfo(table);
190
190
  const pk = pkFields[0];
191
- const selectObj = buildSelectObject(table);
191
+ const selectObj = buildSelectObject(table, typeRegistry);
192
192
  const promptQuestion = t.objectExpression([
193
193
  t.objectProperty(t.identifier('type'), t.stringLiteral('text')),
194
194
  t.objectProperty(t.identifier('name'), t.stringLiteral(pk.name)),
@@ -220,34 +220,6 @@ function buildGetHandler(table, targetName) {
220
220
  t.tryStatement(t.blockStatement(tryBody), buildErrorCatch('Record not found.')),
221
221
  ]), false, true);
222
222
  }
223
- /**
224
- * Get the set of field names that have defaults in the create input type.
225
- * Looks up the CreateXInput -> inner input type (e.g. DatabaseInput) in the
226
- * TypeRegistry and checks each field's defaultValue from introspection.
227
- */
228
- /**
229
- * Resolve the inner input type from a CreateXInput or UpdateXInput type.
230
- * The CreateXInput has an inner field (e.g. "database" of type DatabaseInput)
231
- * that contains the actual field definitions.
232
- */
233
- export function resolveInnerInputType(inputTypeName, typeRegistry) {
234
- const inputType = typeRegistry.get(inputTypeName);
235
- if (!inputType?.inputFields)
236
- return null;
237
- for (const inputField of inputType.inputFields) {
238
- const innerTypeName = inputField.type.name
239
- || inputField.type.ofType?.name
240
- || inputField.type.ofType?.ofType?.name;
241
- if (!innerTypeName)
242
- continue;
243
- const innerType = typeRegistry.get(innerTypeName);
244
- if (!innerType?.inputFields)
245
- continue;
246
- const fields = new Set(innerType.inputFields.map((f) => f.name));
247
- return { name: innerTypeName, fields };
248
- }
249
- return null;
250
- }
251
223
  export function getFieldsWithDefaults(table, typeRegistry) {
252
224
  const fieldsWithDefaults = new Set();
253
225
  if (!typeRegistry)
@@ -269,18 +241,6 @@ export function getFieldsWithDefaults(table, typeRegistry) {
269
241
  }
270
242
  return fieldsWithDefaults;
271
243
  }
272
- /**
273
- * Get the set of field names that actually exist in the create/update input type.
274
- * Fields not in this set (e.g. computed fields like searchTsvRank, hashUuid)
275
- * should be excluded from the data object in create/update handlers.
276
- */
277
- function getWritableFieldNames(table, typeRegistry) {
278
- if (!typeRegistry)
279
- return null;
280
- const createInputTypeName = getCreateInputTypeName(table);
281
- const resolved = resolveInnerInputType(createInputTypeName, typeRegistry);
282
- return resolved?.fields ?? null;
283
- }
284
244
  function buildMutationHandler(table, operation, targetName, typeRegistry, ormTypes) {
285
245
  const { singularName } = getTableNames(table);
286
246
  const pkFields = getPrimaryKeyInfo(table);
@@ -341,7 +301,7 @@ function buildMutationHandler(table, operation, targetName, typeRegistry, ormTyp
341
301
  ? t.objectExpression([
342
302
  t.objectProperty(t.identifier(pk.name), t.booleanLiteral(true)),
343
303
  ])
344
- : buildSelectObject(table);
304
+ : buildSelectObject(table, typeRegistry);
345
305
  let ormArgs;
346
306
  // Build data properties without individual type assertions.
347
307
  // Instead, we build a plain object from cleanedData and cast the entire
@@ -549,9 +509,9 @@ export function generateTableCommand(table, options) {
549
509
  ]), false, true));
550
510
  const tn = options?.targetName;
551
511
  const ormTypes = { createInputTypeName, patchTypeName, innerFieldName };
552
- statements.push(buildListHandler(table, tn));
512
+ statements.push(buildListHandler(table, tn, options?.typeRegistry));
553
513
  if (hasGet)
554
- statements.push(buildGetHandler(table, tn));
514
+ statements.push(buildGetHandler(table, tn, options?.typeRegistry));
555
515
  statements.push(buildMutationHandler(table, 'create', tn, options?.typeRegistry, ormTypes));
556
516
  if (hasUpdate)
557
517
  statements.push(buildMutationHandler(table, 'update', tn, options?.typeRegistry, ormTypes));
@@ -1,4 +1,4 @@
1
- import type { CleanField, CleanFieldType, CleanTable } from '../../types/schema';
1
+ import type { CleanField, CleanFieldType, CleanTable, TypeRegistry } from '../../types/schema';
2
2
  /** Lowercase first character */
3
3
  export declare function lcFirst(str: string): string;
4
4
  /** Uppercase first character */
@@ -148,6 +148,31 @@ export declare function isRelationField(fieldName: string, table: CleanTable): b
148
148
  * Get only scalar fields (non-relation fields)
149
149
  */
150
150
  export declare function getScalarFields(table: CleanTable): CleanField[];
151
+ /**
152
+ * Resolve the inner input type from a CreateXInput.
153
+ * PostGraphile create inputs wrap the actual field definitions in an inner type
154
+ * (e.g. CreateUserInput -> { user: UserInput }) — this resolves that inner type
155
+ * and returns the set of field names it contains.
156
+ */
157
+ export declare function resolveInnerInputType(inputTypeName: string, typeRegistry: TypeRegistry): {
158
+ name: string;
159
+ fields: Set<string>;
160
+ } | null;
161
+ /**
162
+ * Get the set of field names that actually exist in the create input type.
163
+ * Fields not in this set (e.g. computed fields like searchTsvRank, hashUuid)
164
+ * are plugin-added computed fields that don't correspond to real database columns.
165
+ * Returns null when no typeRegistry is provided (caller should treat as "no filtering").
166
+ */
167
+ export declare function getWritableFieldNames(table: CleanTable, typeRegistry?: TypeRegistry): Set<string> | null;
168
+ /**
169
+ * Get scalar fields that represent actual database columns (not computed/plugin-added).
170
+ * When a TypeRegistry is provided, filters out fields that don't exist in the
171
+ * create input type — these are computed fields added by plugins (e.g. search scores,
172
+ * hash UUIDs) that aren't real columns and shouldn't appear in default selections.
173
+ * Without a TypeRegistry, falls back to all scalar fields.
174
+ */
175
+ export declare function getSelectableScalarFields(table: CleanTable, typeRegistry?: TypeRegistry): CleanField[];
151
176
  /**
152
177
  * Primary key field information
153
178
  */
@@ -261,6 +261,54 @@ export function isRelationField(fieldName, table) {
261
261
  export function getScalarFields(table) {
262
262
  return table.fields.filter((f) => !isRelationField(f.name, table));
263
263
  }
264
+ /**
265
+ * Resolve the inner input type from a CreateXInput.
266
+ * PostGraphile create inputs wrap the actual field definitions in an inner type
267
+ * (e.g. CreateUserInput -> { user: UserInput }) — this resolves that inner type
268
+ * and returns the set of field names it contains.
269
+ */
270
+ export function resolveInnerInputType(inputTypeName, typeRegistry) {
271
+ const inputType = typeRegistry.get(inputTypeName);
272
+ if (!inputType?.inputFields)
273
+ return null;
274
+ for (const inputField of inputType.inputFields) {
275
+ const innerTypeName = inputField.type.name
276
+ || inputField.type.ofType?.name
277
+ || inputField.type.ofType?.ofType?.name;
278
+ if (!innerTypeName)
279
+ continue;
280
+ const innerType = typeRegistry.get(innerTypeName);
281
+ if (!innerType?.inputFields)
282
+ continue;
283
+ const fields = new Set(innerType.inputFields.map((f) => f.name));
284
+ return { name: innerTypeName, fields };
285
+ }
286
+ return null;
287
+ }
288
+ /**
289
+ * Get the set of field names that actually exist in the create input type.
290
+ * Fields not in this set (e.g. computed fields like searchTsvRank, hashUuid)
291
+ * are plugin-added computed fields that don't correspond to real database columns.
292
+ * Returns null when no typeRegistry is provided (caller should treat as "no filtering").
293
+ */
294
+ export function getWritableFieldNames(table, typeRegistry) {
295
+ if (!typeRegistry)
296
+ return null;
297
+ const createInputTypeName = getCreateInputTypeName(table);
298
+ const resolved = resolveInnerInputType(createInputTypeName, typeRegistry);
299
+ return resolved?.fields ?? null;
300
+ }
301
+ /**
302
+ * Get scalar fields that represent actual database columns (not computed/plugin-added).
303
+ * When a TypeRegistry is provided, filters out fields that don't exist in the
304
+ * create input type — these are computed fields added by plugins (e.g. search scores,
305
+ * hash UUIDs) that aren't real columns and shouldn't appear in default selections.
306
+ * Without a TypeRegistry, falls back to all scalar fields.
307
+ */
308
+ export function getSelectableScalarFields(table, typeRegistry) {
309
+ const writableFields = getWritableFieldNames(table, typeRegistry);
310
+ return getScalarFields(table).filter((f) => writableFields === null || writableFields.has(f.name));
311
+ }
264
312
  /**
265
313
  * Get primary key field information from table constraints
266
314
  * Returns array to support composite primary keys
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-codegen",
3
- "version": "4.14.0",
3
+ "version": "4.14.1",
4
4
  "description": "GraphQL SDK generator for Constructive databases with React Query hooks",
5
5
  "keywords": [
6
6
  "graphql",
@@ -101,5 +101,5 @@
101
101
  "tsx": "^4.21.0",
102
102
  "typescript": "^5.9.3"
103
103
  },
104
- "gitHead": "1ade5f10df8e38a5f87bbd2e2f7ec2ba97267079"
104
+ "gitHead": "64ef59e5114d52bc897c7e9ef92d35ca6525f12f"
105
105
  }