graphile-settings 5.1.1 → 5.2.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.
- package/esm/plugins/custom-inflector.js +164 -11
- package/package.json +9 -9
- package/plugins/custom-inflector.js +164 -11
|
@@ -66,10 +66,85 @@ function arraysMatch(array1, array2, comparator = (v1, v2) => v1 === v2) {
|
|
|
66
66
|
}
|
|
67
67
|
return true;
|
|
68
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Handle @listSuffix smart tag for per-table control of Connection/List suffix.
|
|
71
|
+
* When @listSuffix is "omit", connections get a "Connection" suffix and lists are bare.
|
|
72
|
+
* When @listSuffix is "include" (or absent), default behavior applies.
|
|
73
|
+
*/
|
|
74
|
+
let globalPgOmitListSuffix = null;
|
|
75
|
+
function overrideListSuffix(listSuffix, cb) {
|
|
76
|
+
if (listSuffix == null) {
|
|
77
|
+
return cb();
|
|
78
|
+
}
|
|
79
|
+
if (listSuffix !== 'include' && listSuffix !== 'omit') {
|
|
80
|
+
throw new Error(`Unrecognized @listSuffix value "${String(listSuffix)}". Must be "omit" or "include".`);
|
|
81
|
+
}
|
|
82
|
+
const old = globalPgOmitListSuffix;
|
|
83
|
+
try {
|
|
84
|
+
globalPgOmitListSuffix = listSuffix === 'omit';
|
|
85
|
+
return cb();
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
globalPgOmitListSuffix = old;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
69
91
|
export const InflektPlugin = {
|
|
70
92
|
name: 'InflektPlugin',
|
|
71
93
|
version: '1.0.0',
|
|
72
94
|
inflection: {
|
|
95
|
+
add: {
|
|
96
|
+
/**
|
|
97
|
+
* Pluralize ensuring the result differs from the singular.
|
|
98
|
+
* Registered as an inflection method so other plugins can call this.distinctPluralize().
|
|
99
|
+
*/
|
|
100
|
+
distinctPluralize(_preset, str) {
|
|
101
|
+
return distinctPluralize(str);
|
|
102
|
+
},
|
|
103
|
+
/**
|
|
104
|
+
* Extract base name from FK attribute names (e.g. "author_id" -> "author").
|
|
105
|
+
* Registered so other plugins can call this._getBaseName().
|
|
106
|
+
*/
|
|
107
|
+
_getBaseName(_preset, attributeName) {
|
|
108
|
+
return getBaseName(attributeName);
|
|
109
|
+
},
|
|
110
|
+
/**
|
|
111
|
+
* Check if a base name matches another name when singularized.
|
|
112
|
+
* Registered so other plugins can call this._baseNameMatches().
|
|
113
|
+
*/
|
|
114
|
+
_baseNameMatches(_preset, baseName, otherName) {
|
|
115
|
+
return baseNameMatches(baseName, otherName);
|
|
116
|
+
},
|
|
117
|
+
/**
|
|
118
|
+
* Get the opposite name for a relation base name (e.g. "parent" -> "child").
|
|
119
|
+
* Registered so other plugins can call this._getOppositeBaseName().
|
|
120
|
+
*/
|
|
121
|
+
_getOppositeBaseName(_preset, baseName) {
|
|
122
|
+
return getOppositeBaseName(baseName);
|
|
123
|
+
},
|
|
124
|
+
/**
|
|
125
|
+
* Extract base name from composite FK keys.
|
|
126
|
+
* Handles single-key (delegates to getBaseName) and multi-key
|
|
127
|
+
* (joins base names with hyphens) FK relations.
|
|
128
|
+
*/
|
|
129
|
+
_getBaseNameFromKeys(preset, detailedKeys) {
|
|
130
|
+
if (detailedKeys.length === 1) {
|
|
131
|
+
const key = detailedKeys[0];
|
|
132
|
+
const attributeName = this._attributeName({
|
|
133
|
+
...key,
|
|
134
|
+
skipRowId: true,
|
|
135
|
+
});
|
|
136
|
+
return getBaseName(attributeName);
|
|
137
|
+
}
|
|
138
|
+
if (preset.schema?.pgSimplifyMultikeyRelations) {
|
|
139
|
+
const attributeNames = detailedKeys.map((key) => this._attributeName({ ...key, skipRowId: true }));
|
|
140
|
+
const baseNames = attributeNames.map((attr) => getBaseName(attr));
|
|
141
|
+
if (baseNames.every((n) => n)) {
|
|
142
|
+
return baseNames.join('-');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
},
|
|
147
|
+
},
|
|
73
148
|
replace: {
|
|
74
149
|
/**
|
|
75
150
|
* Remove schema prefixes from all schemas.
|
|
@@ -168,22 +243,97 @@ export const InflektPlugin = {
|
|
|
168
243
|
singularize(_previous, _preset, str) {
|
|
169
244
|
return singularizeLast(str);
|
|
170
245
|
},
|
|
246
|
+
/**
|
|
247
|
+
* Connection field suffix — respects @listSuffix smart tag.
|
|
248
|
+
* When pgOmitListSuffix is true, connections get "Connection" suffix.
|
|
249
|
+
*/
|
|
250
|
+
connectionField(_prev, options, baseName) {
|
|
251
|
+
return (globalPgOmitListSuffix ?? options.schema?.pgOmitListSuffix)
|
|
252
|
+
? baseName + 'Connection'
|
|
253
|
+
: baseName;
|
|
254
|
+
},
|
|
255
|
+
/**
|
|
256
|
+
* List field suffix — respects @listSuffix smart tag.
|
|
257
|
+
* When pgOmitListSuffix is true, lists are bare (no suffix).
|
|
258
|
+
*/
|
|
259
|
+
listField(_prev, options, baseName) {
|
|
260
|
+
return (globalPgOmitListSuffix ?? options.schema?.pgOmitListSuffix)
|
|
261
|
+
? baseName
|
|
262
|
+
: baseName + 'List';
|
|
263
|
+
},
|
|
171
264
|
/**
|
|
172
265
|
* Simplify root query connection fields (allUsers -> users)
|
|
266
|
+
* Supports @listSuffix smart tag per-table.
|
|
173
267
|
*/
|
|
174
268
|
allRowsConnection(_previous, _options, resource) {
|
|
175
|
-
const
|
|
176
|
-
return
|
|
269
|
+
const listSuffix = resource.extensions?.tags?.listSuffix;
|
|
270
|
+
return overrideListSuffix(listSuffix, () => {
|
|
271
|
+
const resourceName = this._singularizedResourceName(resource);
|
|
272
|
+
return this.connectionField(toCamelCase(distinctPluralize(resourceName)));
|
|
273
|
+
});
|
|
177
274
|
},
|
|
178
275
|
/**
|
|
179
|
-
* Simplify root query list fields
|
|
276
|
+
* Simplify root query list fields.
|
|
277
|
+
* Supports @listSuffix smart tag per-table.
|
|
180
278
|
*/
|
|
181
279
|
allRowsList(_previous, _options, resource) {
|
|
182
|
-
const
|
|
183
|
-
return
|
|
280
|
+
const listSuffix = resource.extensions?.tags?.listSuffix;
|
|
281
|
+
return overrideListSuffix(listSuffix, () => {
|
|
282
|
+
const resourceName = this._singularizedResourceName(resource);
|
|
283
|
+
return this.listField(toCamelCase(distinctPluralize(resourceName)));
|
|
284
|
+
});
|
|
285
|
+
},
|
|
286
|
+
/**
|
|
287
|
+
* @listSuffix passthrough for many-relation connection fields
|
|
288
|
+
*/
|
|
289
|
+
manyRelationConnection(previous, _options, details) {
|
|
290
|
+
const { registry, codec, relationName } = details;
|
|
291
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
292
|
+
const listSuffix = (relation?.extensions?.tags?.listSuffix ??
|
|
293
|
+
relation?.remoteResource?.extensions?.tags?.listSuffix);
|
|
294
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
295
|
+
},
|
|
296
|
+
/**
|
|
297
|
+
* @listSuffix passthrough for many-relation list fields
|
|
298
|
+
*/
|
|
299
|
+
manyRelationList(previous, _options, details) {
|
|
300
|
+
const { registry, codec, relationName } = details;
|
|
301
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
302
|
+
const listSuffix = (relation?.extensions?.tags?.listSuffix ??
|
|
303
|
+
relation?.remoteResource?.extensions?.tags?.listSuffix);
|
|
304
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
305
|
+
},
|
|
306
|
+
/**
|
|
307
|
+
* @listSuffix passthrough for custom query connection fields
|
|
308
|
+
*/
|
|
309
|
+
customQueryConnectionField(previous, _options, details) {
|
|
310
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
311
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
312
|
+
},
|
|
313
|
+
/**
|
|
314
|
+
* @listSuffix passthrough for custom query list fields
|
|
315
|
+
*/
|
|
316
|
+
customQueryListField(previous, _options, details) {
|
|
317
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
318
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
319
|
+
},
|
|
320
|
+
/**
|
|
321
|
+
* @listSuffix passthrough for computed attribute connection fields
|
|
322
|
+
*/
|
|
323
|
+
computedAttributeConnectionField(previous, _options, details) {
|
|
324
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
325
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
326
|
+
},
|
|
327
|
+
/**
|
|
328
|
+
* @listSuffix passthrough for computed attribute list fields
|
|
329
|
+
*/
|
|
330
|
+
computedAttributeListField(previous, _options, details) {
|
|
331
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
332
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
184
333
|
},
|
|
185
334
|
/**
|
|
186
|
-
* Simplify single relation field names (userByAuthorId -> author)
|
|
335
|
+
* Simplify single relation field names (userByAuthorId -> author).
|
|
336
|
+
* Uses _getBaseNameFromKeys for composite FK support.
|
|
187
337
|
*/
|
|
188
338
|
singleRelation(previous, _options, details) {
|
|
189
339
|
const { registry, codec, relationName } = details;
|
|
@@ -194,7 +344,10 @@ export const InflektPlugin = {
|
|
|
194
344
|
if (typeof relation.extensions?.tags?.fieldName === 'string') {
|
|
195
345
|
return relation.extensions.tags.fieldName;
|
|
196
346
|
}
|
|
197
|
-
|
|
347
|
+
const detailedKeys = relation.localAttributes.map((attributeName) => ({
|
|
348
|
+
codec,
|
|
349
|
+
attributeName,
|
|
350
|
+
}));
|
|
198
351
|
if (relation.localAttributes.length === 1) {
|
|
199
352
|
const attributeName = relation.localAttributes[0];
|
|
200
353
|
const baseName = getBaseName(attributeName);
|
|
@@ -211,7 +364,8 @@ export const InflektPlugin = {
|
|
|
211
364
|
return previous(details);
|
|
212
365
|
},
|
|
213
366
|
/**
|
|
214
|
-
* Simplify backwards single relation field names
|
|
367
|
+
* Simplify backwards single relation field names.
|
|
368
|
+
* Uses _getBaseNameFromKeys for composite FK support.
|
|
215
369
|
*/
|
|
216
370
|
singleRelationBackwards(previous, _options, details) {
|
|
217
371
|
const { registry, codec, relationName } = details;
|
|
@@ -225,7 +379,6 @@ export const InflektPlugin = {
|
|
|
225
379
|
if (typeof relation.extensions?.tags?.foreignFieldName === 'string') {
|
|
226
380
|
return relation.extensions.tags.foreignFieldName;
|
|
227
381
|
}
|
|
228
|
-
// Try to extract base name from the remote attribute
|
|
229
382
|
if (relation.remoteAttributes.length === 1) {
|
|
230
383
|
const attributeName = relation.remoteAttributes[0];
|
|
231
384
|
const baseName = getBaseName(attributeName);
|
|
@@ -242,7 +395,8 @@ export const InflektPlugin = {
|
|
|
242
395
|
return previous(details);
|
|
243
396
|
},
|
|
244
397
|
/**
|
|
245
|
-
* Simplify many relation field names (postsByAuthorId -> posts)
|
|
398
|
+
* Simplify many relation field names (postsByAuthorId -> posts).
|
|
399
|
+
* Uses _getBaseNameFromKeys for composite FK support.
|
|
246
400
|
*/
|
|
247
401
|
_manyRelation(previous, _options, details) {
|
|
248
402
|
const { registry, codec, relationName } = details;
|
|
@@ -254,7 +408,6 @@ export const InflektPlugin = {
|
|
|
254
408
|
if (typeof baseOverride === 'string') {
|
|
255
409
|
return baseOverride;
|
|
256
410
|
}
|
|
257
|
-
// Try to extract base name from the remote attribute
|
|
258
411
|
if (relation.remoteAttributes.length === 1) {
|
|
259
412
|
const attributeName = relation.remoteAttributes[0];
|
|
260
413
|
const baseName = getBaseName(attributeName);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphile-settings",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "graphile settings",
|
|
6
6
|
"main": "index.js",
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
"graphile-bucket-provisioner-plugin": "0.11.0",
|
|
50
50
|
"graphile-build": "5.0.0",
|
|
51
51
|
"graphile-build-pg": "5.0.0",
|
|
52
|
-
"graphile-bulk-mutations": "^0.3.
|
|
52
|
+
"graphile-bulk-mutations": "^0.3.1",
|
|
53
53
|
"graphile-config": "1.0.0",
|
|
54
|
-
"graphile-connection-filter": "^1.10.
|
|
55
|
-
"graphile-ltree": "^1.7.
|
|
56
|
-
"graphile-pg-aggregates": "^1.3.
|
|
57
|
-
"graphile-postgis": "^2.16.
|
|
54
|
+
"graphile-connection-filter": "^1.10.1",
|
|
55
|
+
"graphile-ltree": "^1.7.1",
|
|
56
|
+
"graphile-pg-aggregates": "^1.3.1",
|
|
57
|
+
"graphile-postgis": "^2.16.1",
|
|
58
58
|
"graphile-presigned-url-plugin": "^0.19.0",
|
|
59
59
|
"graphile-realtime-subscriptions": "^0.7.0",
|
|
60
|
-
"graphile-search": "^1.12.
|
|
60
|
+
"graphile-search": "^1.12.1",
|
|
61
61
|
"graphile-sql-expression-validator": "^2.13.0",
|
|
62
62
|
"graphile-upload-plugin": "^2.11.0",
|
|
63
63
|
"graphile-utils": "5.0.0",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"@types/express": "^5.0.6",
|
|
77
77
|
"@types/pg": "^8.18.0",
|
|
78
78
|
"@types/request-ip": "^0.0.41",
|
|
79
|
-
"graphile-test": "^4.15.
|
|
79
|
+
"graphile-test": "^4.15.1",
|
|
80
80
|
"makage": "^0.3.0",
|
|
81
81
|
"nodemon": "^3.1.14",
|
|
82
82
|
"ts-node": "^10.9.2"
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"constructive",
|
|
89
89
|
"graphql"
|
|
90
90
|
],
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "62282a9e2b4a72a68c6c3c6a8729e3a0a42a54b2"
|
|
92
92
|
}
|
|
@@ -69,10 +69,85 @@ function arraysMatch(array1, array2, comparator = (v1, v2) => v1 === v2) {
|
|
|
69
69
|
}
|
|
70
70
|
return true;
|
|
71
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle @listSuffix smart tag for per-table control of Connection/List suffix.
|
|
74
|
+
* When @listSuffix is "omit", connections get a "Connection" suffix and lists are bare.
|
|
75
|
+
* When @listSuffix is "include" (or absent), default behavior applies.
|
|
76
|
+
*/
|
|
77
|
+
let globalPgOmitListSuffix = null;
|
|
78
|
+
function overrideListSuffix(listSuffix, cb) {
|
|
79
|
+
if (listSuffix == null) {
|
|
80
|
+
return cb();
|
|
81
|
+
}
|
|
82
|
+
if (listSuffix !== 'include' && listSuffix !== 'omit') {
|
|
83
|
+
throw new Error(`Unrecognized @listSuffix value "${String(listSuffix)}". Must be "omit" or "include".`);
|
|
84
|
+
}
|
|
85
|
+
const old = globalPgOmitListSuffix;
|
|
86
|
+
try {
|
|
87
|
+
globalPgOmitListSuffix = listSuffix === 'omit';
|
|
88
|
+
return cb();
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
globalPgOmitListSuffix = old;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
72
94
|
exports.InflektPlugin = {
|
|
73
95
|
name: 'InflektPlugin',
|
|
74
96
|
version: '1.0.0',
|
|
75
97
|
inflection: {
|
|
98
|
+
add: {
|
|
99
|
+
/**
|
|
100
|
+
* Pluralize ensuring the result differs from the singular.
|
|
101
|
+
* Registered as an inflection method so other plugins can call this.distinctPluralize().
|
|
102
|
+
*/
|
|
103
|
+
distinctPluralize(_preset, str) {
|
|
104
|
+
return (0, inflekt_1.distinctPluralize)(str);
|
|
105
|
+
},
|
|
106
|
+
/**
|
|
107
|
+
* Extract base name from FK attribute names (e.g. "author_id" -> "author").
|
|
108
|
+
* Registered so other plugins can call this._getBaseName().
|
|
109
|
+
*/
|
|
110
|
+
_getBaseName(_preset, attributeName) {
|
|
111
|
+
return getBaseName(attributeName);
|
|
112
|
+
},
|
|
113
|
+
/**
|
|
114
|
+
* Check if a base name matches another name when singularized.
|
|
115
|
+
* Registered so other plugins can call this._baseNameMatches().
|
|
116
|
+
*/
|
|
117
|
+
_baseNameMatches(_preset, baseName, otherName) {
|
|
118
|
+
return baseNameMatches(baseName, otherName);
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Get the opposite name for a relation base name (e.g. "parent" -> "child").
|
|
122
|
+
* Registered so other plugins can call this._getOppositeBaseName().
|
|
123
|
+
*/
|
|
124
|
+
_getOppositeBaseName(_preset, baseName) {
|
|
125
|
+
return getOppositeBaseName(baseName);
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Extract base name from composite FK keys.
|
|
129
|
+
* Handles single-key (delegates to getBaseName) and multi-key
|
|
130
|
+
* (joins base names with hyphens) FK relations.
|
|
131
|
+
*/
|
|
132
|
+
_getBaseNameFromKeys(preset, detailedKeys) {
|
|
133
|
+
if (detailedKeys.length === 1) {
|
|
134
|
+
const key = detailedKeys[0];
|
|
135
|
+
const attributeName = this._attributeName({
|
|
136
|
+
...key,
|
|
137
|
+
skipRowId: true,
|
|
138
|
+
});
|
|
139
|
+
return getBaseName(attributeName);
|
|
140
|
+
}
|
|
141
|
+
if (preset.schema?.pgSimplifyMultikeyRelations) {
|
|
142
|
+
const attributeNames = detailedKeys.map((key) => this._attributeName({ ...key, skipRowId: true }));
|
|
143
|
+
const baseNames = attributeNames.map((attr) => getBaseName(attr));
|
|
144
|
+
if (baseNames.every((n) => n)) {
|
|
145
|
+
return baseNames.join('-');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
},
|
|
150
|
+
},
|
|
76
151
|
replace: {
|
|
77
152
|
/**
|
|
78
153
|
* Remove schema prefixes from all schemas.
|
|
@@ -171,22 +246,97 @@ exports.InflektPlugin = {
|
|
|
171
246
|
singularize(_previous, _preset, str) {
|
|
172
247
|
return (0, inflekt_1.singularizeLast)(str);
|
|
173
248
|
},
|
|
249
|
+
/**
|
|
250
|
+
* Connection field suffix — respects @listSuffix smart tag.
|
|
251
|
+
* When pgOmitListSuffix is true, connections get "Connection" suffix.
|
|
252
|
+
*/
|
|
253
|
+
connectionField(_prev, options, baseName) {
|
|
254
|
+
return (globalPgOmitListSuffix ?? options.schema?.pgOmitListSuffix)
|
|
255
|
+
? baseName + 'Connection'
|
|
256
|
+
: baseName;
|
|
257
|
+
},
|
|
258
|
+
/**
|
|
259
|
+
* List field suffix — respects @listSuffix smart tag.
|
|
260
|
+
* When pgOmitListSuffix is true, lists are bare (no suffix).
|
|
261
|
+
*/
|
|
262
|
+
listField(_prev, options, baseName) {
|
|
263
|
+
return (globalPgOmitListSuffix ?? options.schema?.pgOmitListSuffix)
|
|
264
|
+
? baseName
|
|
265
|
+
: baseName + 'List';
|
|
266
|
+
},
|
|
174
267
|
/**
|
|
175
268
|
* Simplify root query connection fields (allUsers -> users)
|
|
269
|
+
* Supports @listSuffix smart tag per-table.
|
|
176
270
|
*/
|
|
177
271
|
allRowsConnection(_previous, _options, resource) {
|
|
178
|
-
const
|
|
179
|
-
return (
|
|
272
|
+
const listSuffix = resource.extensions?.tags?.listSuffix;
|
|
273
|
+
return overrideListSuffix(listSuffix, () => {
|
|
274
|
+
const resourceName = this._singularizedResourceName(resource);
|
|
275
|
+
return this.connectionField((0, inflekt_1.toCamelCase)((0, inflekt_1.distinctPluralize)(resourceName)));
|
|
276
|
+
});
|
|
180
277
|
},
|
|
181
278
|
/**
|
|
182
|
-
* Simplify root query list fields
|
|
279
|
+
* Simplify root query list fields.
|
|
280
|
+
* Supports @listSuffix smart tag per-table.
|
|
183
281
|
*/
|
|
184
282
|
allRowsList(_previous, _options, resource) {
|
|
185
|
-
const
|
|
186
|
-
return (
|
|
283
|
+
const listSuffix = resource.extensions?.tags?.listSuffix;
|
|
284
|
+
return overrideListSuffix(listSuffix, () => {
|
|
285
|
+
const resourceName = this._singularizedResourceName(resource);
|
|
286
|
+
return this.listField((0, inflekt_1.toCamelCase)((0, inflekt_1.distinctPluralize)(resourceName)));
|
|
287
|
+
});
|
|
288
|
+
},
|
|
289
|
+
/**
|
|
290
|
+
* @listSuffix passthrough for many-relation connection fields
|
|
291
|
+
*/
|
|
292
|
+
manyRelationConnection(previous, _options, details) {
|
|
293
|
+
const { registry, codec, relationName } = details;
|
|
294
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
295
|
+
const listSuffix = (relation?.extensions?.tags?.listSuffix ??
|
|
296
|
+
relation?.remoteResource?.extensions?.tags?.listSuffix);
|
|
297
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
298
|
+
},
|
|
299
|
+
/**
|
|
300
|
+
* @listSuffix passthrough for many-relation list fields
|
|
301
|
+
*/
|
|
302
|
+
manyRelationList(previous, _options, details) {
|
|
303
|
+
const { registry, codec, relationName } = details;
|
|
304
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
305
|
+
const listSuffix = (relation?.extensions?.tags?.listSuffix ??
|
|
306
|
+
relation?.remoteResource?.extensions?.tags?.listSuffix);
|
|
307
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
308
|
+
},
|
|
309
|
+
/**
|
|
310
|
+
* @listSuffix passthrough for custom query connection fields
|
|
311
|
+
*/
|
|
312
|
+
customQueryConnectionField(previous, _options, details) {
|
|
313
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
314
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
315
|
+
},
|
|
316
|
+
/**
|
|
317
|
+
* @listSuffix passthrough for custom query list fields
|
|
318
|
+
*/
|
|
319
|
+
customQueryListField(previous, _options, details) {
|
|
320
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
321
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
322
|
+
},
|
|
323
|
+
/**
|
|
324
|
+
* @listSuffix passthrough for computed attribute connection fields
|
|
325
|
+
*/
|
|
326
|
+
computedAttributeConnectionField(previous, _options, details) {
|
|
327
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
328
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
329
|
+
},
|
|
330
|
+
/**
|
|
331
|
+
* @listSuffix passthrough for computed attribute list fields
|
|
332
|
+
*/
|
|
333
|
+
computedAttributeListField(previous, _options, details) {
|
|
334
|
+
const listSuffix = details.resource?.extensions?.tags?.listSuffix;
|
|
335
|
+
return overrideListSuffix(listSuffix, () => previous(details));
|
|
187
336
|
},
|
|
188
337
|
/**
|
|
189
|
-
* Simplify single relation field names (userByAuthorId -> author)
|
|
338
|
+
* Simplify single relation field names (userByAuthorId -> author).
|
|
339
|
+
* Uses _getBaseNameFromKeys for composite FK support.
|
|
190
340
|
*/
|
|
191
341
|
singleRelation(previous, _options, details) {
|
|
192
342
|
const { registry, codec, relationName } = details;
|
|
@@ -197,7 +347,10 @@ exports.InflektPlugin = {
|
|
|
197
347
|
if (typeof relation.extensions?.tags?.fieldName === 'string') {
|
|
198
348
|
return relation.extensions.tags.fieldName;
|
|
199
349
|
}
|
|
200
|
-
|
|
350
|
+
const detailedKeys = relation.localAttributes.map((attributeName) => ({
|
|
351
|
+
codec,
|
|
352
|
+
attributeName,
|
|
353
|
+
}));
|
|
201
354
|
if (relation.localAttributes.length === 1) {
|
|
202
355
|
const attributeName = relation.localAttributes[0];
|
|
203
356
|
const baseName = getBaseName(attributeName);
|
|
@@ -214,7 +367,8 @@ exports.InflektPlugin = {
|
|
|
214
367
|
return previous(details);
|
|
215
368
|
},
|
|
216
369
|
/**
|
|
217
|
-
* Simplify backwards single relation field names
|
|
370
|
+
* Simplify backwards single relation field names.
|
|
371
|
+
* Uses _getBaseNameFromKeys for composite FK support.
|
|
218
372
|
*/
|
|
219
373
|
singleRelationBackwards(previous, _options, details) {
|
|
220
374
|
const { registry, codec, relationName } = details;
|
|
@@ -228,7 +382,6 @@ exports.InflektPlugin = {
|
|
|
228
382
|
if (typeof relation.extensions?.tags?.foreignFieldName === 'string') {
|
|
229
383
|
return relation.extensions.tags.foreignFieldName;
|
|
230
384
|
}
|
|
231
|
-
// Try to extract base name from the remote attribute
|
|
232
385
|
if (relation.remoteAttributes.length === 1) {
|
|
233
386
|
const attributeName = relation.remoteAttributes[0];
|
|
234
387
|
const baseName = getBaseName(attributeName);
|
|
@@ -245,7 +398,8 @@ exports.InflektPlugin = {
|
|
|
245
398
|
return previous(details);
|
|
246
399
|
},
|
|
247
400
|
/**
|
|
248
|
-
* Simplify many relation field names (postsByAuthorId -> posts)
|
|
401
|
+
* Simplify many relation field names (postsByAuthorId -> posts).
|
|
402
|
+
* Uses _getBaseNameFromKeys for composite FK support.
|
|
249
403
|
*/
|
|
250
404
|
_manyRelation(previous, _options, details) {
|
|
251
405
|
const { registry, codec, relationName } = details;
|
|
@@ -257,7 +411,6 @@ exports.InflektPlugin = {
|
|
|
257
411
|
if (typeof baseOverride === 'string') {
|
|
258
412
|
return baseOverride;
|
|
259
413
|
}
|
|
260
|
-
// Try to extract base name from the remote attribute
|
|
261
414
|
if (relation.remoteAttributes.length === 1) {
|
|
262
415
|
const attributeName = relation.remoteAttributes[0];
|
|
263
416
|
const baseName = getBaseName(attributeName);
|