Skip to content

Commit a4d7028

Browse files
committed
fix(codegen): preserve db.pgpm when merging CLI args with file config
fix(graphile-settings): resolve function/table resource name collisions - Add functionResourceName override to InflektPlugin to restore schema prefixes for functions while keeping clean names for tables - Filter ConflictDetectorPlugin by configured pgServices.schemas to prevent false-positive warnings from unrelated schemas - Deep-merge db config in codegen CLI to preserve file config db fields - Use filterDefined in buildDbConfig to strip undefined values
1 parent db546ec commit a4d7028

4 files changed

Lines changed: 62 additions & 6 deletions

File tree

graphile/graphile-settings/src/plugins/conflict-detector.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ export const ConflictDetectorPlugin: GraphileConfig.Plugin = {
2929
// Track codecs by their GraphQL name to detect conflicts
3030
const codecsByName = new Map<string, CodecInfo[]>();
3131

32+
// Get configured schemas from pgServices to only check relevant codecs
33+
const configuredSchemas = new Set<string>();
34+
const pgServices = (build as any).resolvedPreset?.pgServices ?? [];
35+
36+
for (const service of pgServices) {
37+
for (const schema of service.schemas ?? ['public']) {
38+
configuredSchemas.add(schema);
39+
}
40+
}
41+
3242
// Iterate through all codecs to find tables
3343
for (const codec of Object.values(build.input.pgRegistry.pgCodecs)) {
3444
// Skip non-table codecs (those without attributes or anonymous ones)
@@ -41,6 +51,11 @@ export const ConflictDetectorPlugin: GraphileConfig.Plugin = {
4151
const schemaName = pgExtensions?.schemaName || 'unknown';
4252
const tableName = codec.name;
4353

54+
// Skip codecs from schemas not in the configured list
55+
if (configuredSchemas.size > 0 && !configuredSchemas.has(schemaName)) {
56+
continue;
57+
}
58+
4459
// Get the GraphQL name that would be generated
4560
const graphqlName = build.inflection.tableType(codec);
4661

graphile/graphile-settings/src/plugins/custom-inflector.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,39 @@ export const InflektPlugin: GraphileConfig.Plugin = {
129129
return '';
130130
},
131131

132+
/**
133+
* Restore PostGraphile's default schema prefix logic for functions.
134+
*
135+
* Our _schemaPrefix override returns '' for all schemas to give clean
136+
* table names. However, this strips prefixes from functions too, causing
137+
* resource naming collisions when a function and table share the same
138+
* base name across schemas (e.g., actions_public.table_grant() collides
139+
* with metaschema_public.table_grant table).
140+
*
141+
* Fix: bypass our _schemaPrefix override for functions and use
142+
* PostGraphile's default prefix logic instead.
143+
*/
144+
functionResourceName(_previous, options: any, details: any) {
145+
const { serviceName, pgProc } = details;
146+
const { tags } = pgProc.getTagsAndDescription();
147+
148+
if (typeof tags.name === 'string') {
149+
return tags.name;
150+
}
151+
152+
const pgNamespace = pgProc.getNamespace();
153+
154+
if (!pgNamespace) {
155+
return pgProc.proname;
156+
}
157+
158+
const pgService = (options.pgServices ?? []).find((db: any) => db.name === serviceName);
159+
const primarySchema = pgService?.schemas?.[0] ?? 'public';
160+
const databasePrefix = serviceName === 'main' ? '' : `${serviceName}_`;
161+
const schemaPrefix = pgNamespace.nspname === primarySchema ? '' : `${pgNamespace.nspname}_`;
162+
return `${databasePrefix}${schemaPrefix}${pgProc.proname}`;
163+
},
164+
132165
/**
133166
* Keep `id` columns as `id` instead of renaming to `rowId`.
134167
*

graphql/codegen/src/cli/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,11 @@ export const commands = async (
114114
let hasError = false;
115115
for (const name of names) {
116116
console.log(`\n[${name}]`);
117-
const result = await generate({
118-
...targets[name],
119-
...cliOptions,
120-
} as GraphQLSDKConfigTarget);
117+
const targetConfig = { ...targets[name], ...cliOptions } as GraphQLSDKConfigTarget;
118+
if (targets[name].db && targetConfig.db) {
119+
targetConfig.db = { ...targets[name].db, ...targetConfig.db };
120+
}
121+
const result = await generate(targetConfig);
121122
printResult(result);
122123
if (!result.success) hasError = true;
123124
}

graphql/codegen/src/cli/shared.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,10 @@ export function buildDbConfig(
202202
): Record<string, unknown> {
203203
const { schemas, apiNames, ...rest } = options;
204204
if (schemas || apiNames) {
205-
return { ...rest, db: { schemas, apiNames } };
205+
return {
206+
...rest,
207+
db: filterDefined({ schemas, apiNames } as Record<string, unknown>),
208+
};
206209
}
207210
return rest;
208211
}
@@ -259,5 +262,9 @@ export function buildGenerateOptions(
259262
const camelized = camelizeArgv(answers);
260263
const normalized = normalizeCodegenListOptions(camelized);
261264
const withDb = buildDbConfig(normalized);
262-
return { ...fileConfig, ...withDb } as GraphQLSDKConfigTarget;
265+
const merged = { ...fileConfig, ...withDb } as GraphQLSDKConfigTarget;
266+
if (fileConfig.db && merged.db) {
267+
merged.db = { ...fileConfig.db, ...merged.db };
268+
}
269+
return merged;
263270
}

0 commit comments

Comments
 (0)