graphile-settings 3.1.1 → 4.0.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/README.md +170 -85
- package/esm/index.d.ts +37 -0
- package/esm/index.js +54 -103
- package/esm/plugins/conflict-detector.d.ts +7 -0
- package/esm/plugins/conflict-detector.js +67 -0
- package/esm/plugins/custom-inflector.d.ts +9 -0
- package/esm/plugins/custom-inflector.js +382 -0
- package/esm/plugins/enable-all-filter-columns.d.ts +60 -0
- package/esm/plugins/enable-all-filter-columns.js +85 -0
- package/esm/plugins/index.d.ts +19 -0
- package/esm/plugins/index.js +26 -0
- package/esm/plugins/inflector-logger.d.ts +7 -0
- package/esm/plugins/inflector-logger.js +215 -0
- package/esm/plugins/many-to-many-preset.d.ts +62 -0
- package/esm/plugins/many-to-many-preset.js +86 -0
- package/esm/plugins/meta-schema/cache.d.ts +4 -0
- package/esm/plugins/meta-schema/cache.js +7 -0
- package/esm/plugins/meta-schema/constraint-meta-builders.d.ts +13 -0
- package/esm/plugins/meta-schema/constraint-meta-builders.js +51 -0
- package/esm/plugins/meta-schema/graphql-meta-field.d.ts +4 -0
- package/esm/plugins/meta-schema/graphql-meta-field.js +201 -0
- package/esm/plugins/meta-schema/inflection-utils.d.ts +4 -0
- package/esm/plugins/meta-schema/inflection-utils.js +20 -0
- package/esm/plugins/meta-schema/name-meta-builders.d.ts +4 -0
- package/esm/plugins/meta-schema/name-meta-builders.js +38 -0
- package/esm/plugins/meta-schema/plugin.d.ts +2 -0
- package/esm/plugins/meta-schema/plugin.js +23 -0
- package/esm/plugins/meta-schema/relation-meta-builders.d.ts +8 -0
- package/esm/plugins/meta-schema/relation-meta-builders.js +115 -0
- package/esm/plugins/meta-schema/table-meta-builder.d.ts +2 -0
- package/esm/plugins/meta-schema/table-meta-builder.js +69 -0
- package/esm/plugins/meta-schema/table-meta-context.d.ts +13 -0
- package/esm/plugins/meta-schema/table-meta-context.js +11 -0
- package/esm/plugins/meta-schema/table-resource-utils.d.ts +12 -0
- package/esm/plugins/meta-schema/table-resource-utils.js +50 -0
- package/esm/plugins/meta-schema/type-mappings.d.ts +3 -0
- package/esm/plugins/meta-schema/type-mappings.js +75 -0
- package/esm/plugins/meta-schema/types.d.ts +206 -0
- package/esm/plugins/meta-schema/types.js +1 -0
- package/esm/plugins/meta-schema.d.ts +19 -0
- package/esm/plugins/meta-schema.js +20 -0
- package/esm/plugins/minimal-preset.d.ts +7 -0
- package/esm/plugins/minimal-preset.js +42 -0
- package/esm/plugins/pg-type-mappings.d.ts +41 -0
- package/esm/plugins/pg-type-mappings.js +122 -0
- package/esm/plugins/primary-key-only.d.ts +96 -0
- package/esm/plugins/primary-key-only.js +143 -0
- package/esm/presets/constructive-preset.d.ts +40 -0
- package/esm/presets/constructive-preset.js +137 -0
- package/esm/presets/index.d.ts +7 -0
- package/esm/presets/index.js +7 -0
- package/index.d.ts +37 -3
- package/index.js +56 -129
- package/package.json +16 -22
- package/plugins/conflict-detector.d.ts +7 -0
- package/plugins/conflict-detector.js +70 -0
- package/plugins/custom-inflector.d.ts +9 -0
- package/plugins/custom-inflector.js +385 -0
- package/plugins/enable-all-filter-columns.d.ts +60 -0
- package/plugins/enable-all-filter-columns.js +88 -0
- package/plugins/index.d.ts +19 -0
- package/plugins/index.js +56 -0
- package/plugins/inflector-logger.d.ts +7 -0
- package/plugins/inflector-logger.js +218 -0
- package/plugins/many-to-many-preset.d.ts +62 -0
- package/plugins/many-to-many-preset.js +89 -0
- package/plugins/meta-schema/cache.d.ts +4 -0
- package/plugins/meta-schema/cache.js +12 -0
- package/plugins/meta-schema/constraint-meta-builders.d.ts +13 -0
- package/plugins/meta-schema/constraint-meta-builders.js +58 -0
- package/plugins/meta-schema/graphql-meta-field.d.ts +4 -0
- package/plugins/meta-schema/graphql-meta-field.js +204 -0
- package/plugins/meta-schema/inflection-utils.d.ts +4 -0
- package/plugins/meta-schema/inflection-utils.js +25 -0
- package/plugins/meta-schema/name-meta-builders.d.ts +4 -0
- package/plugins/meta-schema/name-meta-builders.js +43 -0
- package/plugins/meta-schema/plugin.d.ts +2 -0
- package/plugins/meta-schema/plugin.js +26 -0
- package/plugins/meta-schema/relation-meta-builders.d.ts +8 -0
- package/plugins/meta-schema/relation-meta-builders.js +120 -0
- package/plugins/meta-schema/table-meta-builder.d.ts +2 -0
- package/plugins/meta-schema/table-meta-builder.js +72 -0
- package/plugins/meta-schema/table-meta-context.d.ts +13 -0
- package/plugins/meta-schema/table-meta-context.js +15 -0
- package/plugins/meta-schema/table-resource-utils.d.ts +12 -0
- package/plugins/meta-schema/table-resource-utils.js +60 -0
- package/plugins/meta-schema/type-mappings.d.ts +3 -0
- package/plugins/meta-schema/type-mappings.js +79 -0
- package/plugins/meta-schema/types.d.ts +206 -0
- package/plugins/meta-schema/types.js +2 -0
- package/plugins/meta-schema.d.ts +19 -0
- package/plugins/meta-schema.js +20 -0
- package/plugins/minimal-preset.d.ts +7 -0
- package/plugins/minimal-preset.js +45 -0
- package/plugins/pg-type-mappings.d.ts +41 -0
- package/plugins/pg-type-mappings.js +128 -0
- package/plugins/primary-key-only.d.ts +96 -0
- package/plugins/primary-key-only.js +147 -0
- package/presets/constructive-preset.d.ts +40 -0
- package/presets/constructive-preset.js +140 -0
- package/presets/index.d.ts +7 -0
- package/presets/index.js +11 -0
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CustomInflectorPreset = exports.CustomInflectorPlugin = exports.InflektPreset = exports.InflektPlugin = void 0;
|
|
4
|
+
const inflekt_1 = require("inflekt");
|
|
5
|
+
/**
|
|
6
|
+
* Custom inflector plugin for Constructive using the inflekt library.
|
|
7
|
+
*
|
|
8
|
+
* This plugin provides inflection rules based on the inflekt package from dev-utils.
|
|
9
|
+
* It gives us full control over naming conventions and handles Latin plural suffixes
|
|
10
|
+
* correctly (e.g., "schemata" -> "schema" instead of "schematum").
|
|
11
|
+
*
|
|
12
|
+
* Key features:
|
|
13
|
+
* - Uses inflekt for pluralization/singularization with PostGraphile-compatible Latin handling
|
|
14
|
+
* - Simplifies field names (allUsers -> users, postsByAuthorId -> posts)
|
|
15
|
+
* - Customizable opposite name mappings for relations
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Custom opposite name mappings for relations.
|
|
19
|
+
* For example, if you have a `parent_id` column, this determines
|
|
20
|
+
* what the reverse relation should be called.
|
|
21
|
+
*
|
|
22
|
+
* Add your own mappings here as needed.
|
|
23
|
+
*/
|
|
24
|
+
const CUSTOM_OPPOSITES = {
|
|
25
|
+
parent: 'child',
|
|
26
|
+
child: 'parent',
|
|
27
|
+
author: 'authored',
|
|
28
|
+
editor: 'edited',
|
|
29
|
+
reviewer: 'reviewed',
|
|
30
|
+
owner: 'owned',
|
|
31
|
+
creator: 'created',
|
|
32
|
+
updater: 'updated',
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Extract base name from attribute names like "author_id" -> "author"
|
|
36
|
+
*/
|
|
37
|
+
function getBaseName(attributeName) {
|
|
38
|
+
const matches = attributeName.match(/^(.+?)(_row_id|_id|_uuid|_fk|_pk|RowId|Id|Uuid|UUID|Fk|Pk)$/);
|
|
39
|
+
if (matches) {
|
|
40
|
+
return matches[1];
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if a base name matches another name (singularized)
|
|
46
|
+
*/
|
|
47
|
+
function baseNameMatches(baseName, otherName) {
|
|
48
|
+
const singularizedName = (0, inflekt_1.singularize)(otherName);
|
|
49
|
+
return (0, inflekt_1.camelize)(baseName, true) === (0, inflekt_1.camelize)(singularizedName, true);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Get the opposite name for a relation base name
|
|
53
|
+
*/
|
|
54
|
+
function getOppositeBaseName(baseName) {
|
|
55
|
+
return CUSTOM_OPPOSITES[baseName] || null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Returns true if array1 and array2 have the same length and values
|
|
59
|
+
*/
|
|
60
|
+
function arraysMatch(array1, array2, comparator = (v1, v2) => v1 === v2) {
|
|
61
|
+
if (array1 === array2)
|
|
62
|
+
return true;
|
|
63
|
+
const l = array1.length;
|
|
64
|
+
if (l !== array2.length)
|
|
65
|
+
return false;
|
|
66
|
+
for (let i = 0; i < l; i++) {
|
|
67
|
+
if (!comparator(array1[i], array2[i]))
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
exports.InflektPlugin = {
|
|
73
|
+
name: 'InflektPlugin',
|
|
74
|
+
version: '1.0.0',
|
|
75
|
+
inflection: {
|
|
76
|
+
replace: {
|
|
77
|
+
/**
|
|
78
|
+
* Remove schema prefixes from all schemas.
|
|
79
|
+
*
|
|
80
|
+
* WHY THIS EXISTS:
|
|
81
|
+
* PostGraphile v5's default `_schemaPrefix` inflector only removes the prefix
|
|
82
|
+
* for the FIRST schema in the pgServices.schemas array. All other schemas get
|
|
83
|
+
* prefixed with their schema name (e.g., "services_public_api" -> "servicesPublicApi").
|
|
84
|
+
*
|
|
85
|
+
* This is problematic for multi-schema setups where you want clean, consistent
|
|
86
|
+
* naming across all schemas.
|
|
87
|
+
*
|
|
88
|
+
* SOURCE CODE REFERENCE:
|
|
89
|
+
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgTablesPlugin.ts#L261-L271
|
|
90
|
+
*
|
|
91
|
+
* The relevant v5 code:
|
|
92
|
+
* ```typescript
|
|
93
|
+
* _schemaPrefix(options, { pgNamespace, serviceName }) {
|
|
94
|
+
* const pgService = options.pgServices?.find((db) => db.name === serviceName);
|
|
95
|
+
* const databasePrefix = serviceName === "main" ? "" : `${serviceName}_`;
|
|
96
|
+
* const schemaPrefix =
|
|
97
|
+
* pgNamespace.nspname === pgService?.schemas?.[0] // <-- Only first schema!
|
|
98
|
+
* ? ""
|
|
99
|
+
* : `${pgNamespace.nspname}_`;
|
|
100
|
+
* return `${databasePrefix}${schemaPrefix}`;
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* OUR FIX:
|
|
105
|
+
* We override this to always return an empty string, giving clean names for
|
|
106
|
+
* all schemas. Use the ConflictDetectorPlugin to detect naming conflicts.
|
|
107
|
+
*
|
|
108
|
+
* WARNING: This may cause naming conflicts if you have tables with the
|
|
109
|
+
* same name in different schemas. Use @name smart tags to disambiguate.
|
|
110
|
+
*/
|
|
111
|
+
_schemaPrefix(_previous, _options, _details) {
|
|
112
|
+
return '';
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* Keep `id` columns as `id` instead of renaming to `rowId`.
|
|
116
|
+
*
|
|
117
|
+
* WHY THIS EXISTS:
|
|
118
|
+
* PostGraphile v5's default `_attributeName` inflector renames any column
|
|
119
|
+
* named "id" to "row_id" to avoid conflicts with the Relay Global Object
|
|
120
|
+
* Identification spec's `id` field. Since we don't use Relay/Node (we use
|
|
121
|
+
* UUIDs), there's no conflict to avoid.
|
|
122
|
+
*
|
|
123
|
+
* NOTE: Disabling NodePlugin does NOT fix this! The renaming happens in
|
|
124
|
+
* PgAttributesPlugin which is a core plugin we need for basic column
|
|
125
|
+
* functionality.
|
|
126
|
+
*
|
|
127
|
+
* SOURCE CODE REFERENCE:
|
|
128
|
+
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgAttributesPlugin.ts#L289-L298
|
|
129
|
+
*
|
|
130
|
+
* The relevant v5 code:
|
|
131
|
+
* ```typescript
|
|
132
|
+
* _attributeName(options, { attributeName, codec, skipRowId }) {
|
|
133
|
+
* const attribute = codec.attributes[attributeName];
|
|
134
|
+
* const name = attribute.extensions?.tags?.name || attributeName;
|
|
135
|
+
* // Avoid conflict with 'id' field used for Relay.
|
|
136
|
+
* const nonconflictName =
|
|
137
|
+
* !skipRowId && name.toLowerCase() === "id" && !codec.isAnonymous
|
|
138
|
+
* ? "row_id" // <-- This renames id to row_id!
|
|
139
|
+
* : name;
|
|
140
|
+
* return this.coerceToGraphQLName(nonconflictName);
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* OUR FIX:
|
|
145
|
+
* We override this to always use the original attribute name, never
|
|
146
|
+
* renaming `id` to `row_id`. Since we use UUIDs and don't use Relay,
|
|
147
|
+
* there's no naming conflict.
|
|
148
|
+
*/
|
|
149
|
+
_attributeName(_previous, _options, details) {
|
|
150
|
+
const attribute = details.codec.attributes[details.attributeName];
|
|
151
|
+
const name = attribute?.extensions?.tags?.name || details.attributeName;
|
|
152
|
+
return this.coerceToGraphQLName(name);
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Fix capitalized plurals (e.g., "Table1S" -> "Table1s")
|
|
156
|
+
*/
|
|
157
|
+
camelCase(previous, _preset, str) {
|
|
158
|
+
const original = previous(str);
|
|
159
|
+
return (0, inflekt_1.fixCapitalisedPlural)(original);
|
|
160
|
+
},
|
|
161
|
+
upperCamelCase(previous, _preset, str) {
|
|
162
|
+
const original = previous(str);
|
|
163
|
+
return (0, inflekt_1.fixCapitalisedPlural)(original);
|
|
164
|
+
},
|
|
165
|
+
/**
|
|
166
|
+
* Use inflekt's singularize/pluralize which only changes the last word
|
|
167
|
+
*/
|
|
168
|
+
pluralize(_previous, _preset, str) {
|
|
169
|
+
return (0, inflekt_1.pluralizeLast)(str);
|
|
170
|
+
},
|
|
171
|
+
singularize(_previous, _preset, str) {
|
|
172
|
+
return (0, inflekt_1.singularizeLast)(str);
|
|
173
|
+
},
|
|
174
|
+
/**
|
|
175
|
+
* Simplify root query connection fields (allUsers -> users)
|
|
176
|
+
*/
|
|
177
|
+
allRowsConnection(_previous, _options, resource) {
|
|
178
|
+
const resourceName = this._singularizedResourceName(resource);
|
|
179
|
+
return (0, inflekt_1.camelize)((0, inflekt_1.distinctPluralize)(resourceName), true);
|
|
180
|
+
},
|
|
181
|
+
/**
|
|
182
|
+
* Simplify root query list fields
|
|
183
|
+
*/
|
|
184
|
+
allRowsList(_previous, _options, resource) {
|
|
185
|
+
const resourceName = this._singularizedResourceName(resource);
|
|
186
|
+
return (0, inflekt_1.camelize)((0, inflekt_1.distinctPluralize)(resourceName), true) + 'List';
|
|
187
|
+
},
|
|
188
|
+
/**
|
|
189
|
+
* Simplify single relation field names (userByAuthorId -> author)
|
|
190
|
+
*/
|
|
191
|
+
singleRelation(previous, _options, details) {
|
|
192
|
+
const { registry, codec, relationName } = details;
|
|
193
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
194
|
+
if (typeof relation.extensions?.tags?.fieldName === 'string') {
|
|
195
|
+
return relation.extensions.tags.fieldName;
|
|
196
|
+
}
|
|
197
|
+
// Try to extract base name from the local attribute
|
|
198
|
+
if (relation.localAttributes.length === 1) {
|
|
199
|
+
const attributeName = relation.localAttributes[0];
|
|
200
|
+
const baseName = getBaseName(attributeName);
|
|
201
|
+
if (baseName) {
|
|
202
|
+
return (0, inflekt_1.camelize)(baseName, true);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Fall back to the remote resource name
|
|
206
|
+
const foreignPk = relation.remoteResource.uniques.find((u) => u.isPrimary);
|
|
207
|
+
if (foreignPk &&
|
|
208
|
+
arraysMatch(foreignPk.attributes, relation.remoteAttributes)) {
|
|
209
|
+
return (0, inflekt_1.camelize)(this._singularizedCodecName(relation.remoteResource.codec), true);
|
|
210
|
+
}
|
|
211
|
+
return previous(details);
|
|
212
|
+
},
|
|
213
|
+
/**
|
|
214
|
+
* Simplify backwards single relation field names
|
|
215
|
+
*/
|
|
216
|
+
singleRelationBackwards(previous, _options, details) {
|
|
217
|
+
const { registry, codec, relationName } = details;
|
|
218
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
219
|
+
if (typeof relation.extensions?.tags?.foreignSingleFieldName === 'string') {
|
|
220
|
+
return relation.extensions.tags.foreignSingleFieldName;
|
|
221
|
+
}
|
|
222
|
+
if (typeof relation.extensions?.tags?.foreignFieldName === 'string') {
|
|
223
|
+
return relation.extensions.tags.foreignFieldName;
|
|
224
|
+
}
|
|
225
|
+
// Try to extract base name from the remote attribute
|
|
226
|
+
if (relation.remoteAttributes.length === 1) {
|
|
227
|
+
const attributeName = relation.remoteAttributes[0];
|
|
228
|
+
const baseName = getBaseName(attributeName);
|
|
229
|
+
if (baseName) {
|
|
230
|
+
const oppositeBaseName = getOppositeBaseName(baseName);
|
|
231
|
+
if (oppositeBaseName) {
|
|
232
|
+
return (0, inflekt_1.camelize)(`${oppositeBaseName}_${this._singularizedCodecName(relation.remoteResource.codec)}`, true);
|
|
233
|
+
}
|
|
234
|
+
if (baseNameMatches(baseName, codec.name)) {
|
|
235
|
+
return (0, inflekt_1.camelize)(this._singularizedCodecName(relation.remoteResource.codec), true);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return previous(details);
|
|
240
|
+
},
|
|
241
|
+
/**
|
|
242
|
+
* Simplify many relation field names (postsByAuthorId -> posts)
|
|
243
|
+
*/
|
|
244
|
+
_manyRelation(previous, _options, details) {
|
|
245
|
+
const { registry, codec, relationName } = details;
|
|
246
|
+
const relation = registry.pgRelations[codec.name]?.[relationName];
|
|
247
|
+
const baseOverride = relation.extensions?.tags.foreignFieldName;
|
|
248
|
+
if (typeof baseOverride === 'string') {
|
|
249
|
+
return baseOverride;
|
|
250
|
+
}
|
|
251
|
+
// Try to extract base name from the remote attribute
|
|
252
|
+
if (relation.remoteAttributes.length === 1) {
|
|
253
|
+
const attributeName = relation.remoteAttributes[0];
|
|
254
|
+
const baseName = getBaseName(attributeName);
|
|
255
|
+
if (baseName) {
|
|
256
|
+
const oppositeBaseName = getOppositeBaseName(baseName);
|
|
257
|
+
if (oppositeBaseName) {
|
|
258
|
+
return (0, inflekt_1.camelize)(`${oppositeBaseName}_${(0, inflekt_1.distinctPluralize)(this._singularizedCodecName(relation.remoteResource.codec))}`, true);
|
|
259
|
+
}
|
|
260
|
+
if (baseNameMatches(baseName, codec.name)) {
|
|
261
|
+
return (0, inflekt_1.camelize)((0, inflekt_1.distinctPluralize)(this._singularizedCodecName(relation.remoteResource.codec)), true);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
// Fall back to pluralized remote resource name
|
|
266
|
+
const pk = relation.remoteResource.uniques.find((u) => u.isPrimary);
|
|
267
|
+
if (pk && arraysMatch(pk.attributes, relation.remoteAttributes)) {
|
|
268
|
+
return (0, inflekt_1.camelize)((0, inflekt_1.distinctPluralize)(this._singularizedCodecName(relation.remoteResource.codec)), true);
|
|
269
|
+
}
|
|
270
|
+
return previous(details);
|
|
271
|
+
},
|
|
272
|
+
/**
|
|
273
|
+
* Simplify many-to-many relation field names with conflict detection.
|
|
274
|
+
*
|
|
275
|
+
* Default pg-many-to-many naming: tagsByPostTagPostIdAndTagId
|
|
276
|
+
* Our simplified naming: tags
|
|
277
|
+
*
|
|
278
|
+
* Falls back to verbose naming if:
|
|
279
|
+
* - Smart tag override exists (manyToManyFieldName)
|
|
280
|
+
* - There's a direct relation to the same target table (would conflict)
|
|
281
|
+
* - There are multiple many-to-many relations to the same target table
|
|
282
|
+
*/
|
|
283
|
+
_manyToManyRelation(previous, _options, details) {
|
|
284
|
+
const { leftTable, rightTable, junctionTable, rightRelationName } = details;
|
|
285
|
+
const junctionRightRelation = junctionTable.getRelation(rightRelationName);
|
|
286
|
+
const baseOverride = junctionRightRelation.extensions?.tags?.manyToManyFieldName;
|
|
287
|
+
if (typeof baseOverride === 'string') {
|
|
288
|
+
return baseOverride;
|
|
289
|
+
}
|
|
290
|
+
const simpleName = (0, inflekt_1.camelize)((0, inflekt_1.distinctPluralize)(this._singularizedCodecName(rightTable.codec)), true);
|
|
291
|
+
const leftRelations = leftTable.getRelations();
|
|
292
|
+
let hasDirectRelation = false;
|
|
293
|
+
let manyToManyCount = 0;
|
|
294
|
+
for (const [_relName, rel] of Object.entries(leftRelations)) {
|
|
295
|
+
if (rel.remoteResource?.codec?.name === rightTable.codec.name) {
|
|
296
|
+
if (!rel.isReferencee) {
|
|
297
|
+
hasDirectRelation = true;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (rel.isReferencee &&
|
|
301
|
+
rel.remoteResource?.codec?.name !== rightTable.codec.name) {
|
|
302
|
+
const junctionRelations = rel.remoteResource?.getRelations?.() || {};
|
|
303
|
+
for (const [_jRelName, jRel] of Object.entries(junctionRelations)) {
|
|
304
|
+
if (!jRel.isReferencee &&
|
|
305
|
+
jRel.remoteResource?.codec?.name === rightTable.codec.name) {
|
|
306
|
+
manyToManyCount++;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (hasDirectRelation || manyToManyCount > 1) {
|
|
312
|
+
return previous(details);
|
|
313
|
+
}
|
|
314
|
+
return simpleName;
|
|
315
|
+
},
|
|
316
|
+
/**
|
|
317
|
+
* Shorten primary key lookups (userById -> user)
|
|
318
|
+
*/
|
|
319
|
+
rowByUnique(previous, _options, details) {
|
|
320
|
+
const { unique, resource } = details;
|
|
321
|
+
if (typeof unique.extensions?.tags?.fieldName === 'string') {
|
|
322
|
+
return unique.extensions?.tags?.fieldName;
|
|
323
|
+
}
|
|
324
|
+
if (unique.isPrimary) {
|
|
325
|
+
return (0, inflekt_1.camelize)(this._singularizedCodecName(resource.codec), true);
|
|
326
|
+
}
|
|
327
|
+
return previous(details);
|
|
328
|
+
},
|
|
329
|
+
/**
|
|
330
|
+
* Shorten update mutation names
|
|
331
|
+
*/
|
|
332
|
+
updateByKeysField(previous, _options, details) {
|
|
333
|
+
const { resource, unique } = details;
|
|
334
|
+
if (typeof unique.extensions?.tags.updateFieldName === 'string') {
|
|
335
|
+
return unique.extensions.tags.updateFieldName;
|
|
336
|
+
}
|
|
337
|
+
if (unique.isPrimary) {
|
|
338
|
+
return (0, inflekt_1.camelize)(`update_${this._singularizedCodecName(resource.codec)}`, true);
|
|
339
|
+
}
|
|
340
|
+
return previous(details);
|
|
341
|
+
},
|
|
342
|
+
/**
|
|
343
|
+
* Shorten delete mutation names
|
|
344
|
+
*/
|
|
345
|
+
deleteByKeysField(previous, _options, details) {
|
|
346
|
+
const { resource, unique } = details;
|
|
347
|
+
if (typeof unique.extensions?.tags.deleteFieldName === 'string') {
|
|
348
|
+
return unique.extensions.tags.deleteFieldName;
|
|
349
|
+
}
|
|
350
|
+
if (unique.isPrimary) {
|
|
351
|
+
return (0, inflekt_1.camelize)(`delete_${this._singularizedCodecName(resource.codec)}`, true);
|
|
352
|
+
}
|
|
353
|
+
return previous(details);
|
|
354
|
+
},
|
|
355
|
+
/**
|
|
356
|
+
* Uppercase enum values to match GraphQL CONSTANT_CASE convention.
|
|
357
|
+
*
|
|
358
|
+
* WHY THIS EXISTS:
|
|
359
|
+
* In PostGraphile v4, custom PostgreSQL enum values (e.g., 'app', 'core', 'module')
|
|
360
|
+
* were automatically uppercased to CONSTANT_CASE ('APP', 'CORE', 'MODULE').
|
|
361
|
+
* In PostGraphile v5, the default `enumValue` inflector preserves the original
|
|
362
|
+
* PostgreSQL casing via `coerceToGraphQLName(value)`, resulting in lowercase
|
|
363
|
+
* enum values in the GraphQL schema.
|
|
364
|
+
*
|
|
365
|
+
* OUR FIX:
|
|
366
|
+
* We call the previous inflector to retain all special character handling
|
|
367
|
+
* (asterisks, symbols, etc.), then uppercase the result to restore v4 behavior.
|
|
368
|
+
*/
|
|
369
|
+
enumValue(previous, _options, value, codec) {
|
|
370
|
+
const result = previous(value, codec);
|
|
371
|
+
return result.toUpperCase();
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* Preset that includes the inflekt-based inflector plugin.
|
|
378
|
+
* Use this in your main preset's `extends` array.
|
|
379
|
+
*/
|
|
380
|
+
exports.InflektPreset = {
|
|
381
|
+
plugins: [exports.InflektPlugin],
|
|
382
|
+
};
|
|
383
|
+
// Re-export for backwards compatibility
|
|
384
|
+
exports.CustomInflectorPlugin = exports.InflektPlugin;
|
|
385
|
+
exports.CustomInflectorPreset = exports.InflektPreset;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { GraphileConfig } from 'graphile-config';
|
|
2
|
+
/**
|
|
3
|
+
* EnableAllFilterColumnsPlugin - Enables filtering on ALL columns, not just indexed ones.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS:
|
|
6
|
+
* PostGraphile v5's `PgIndexBehaviorsPlugin` restricts filtering to only indexed columns
|
|
7
|
+
* by default. This is a performance optimization - filtering on non-indexed columns can
|
|
8
|
+
* cause slow table scans. However, for development and flexibility, we want to allow
|
|
9
|
+
* filtering on all columns and let developers/DBAs decide which columns need indexes.
|
|
10
|
+
*
|
|
11
|
+
* SOURCE CODE REFERENCE:
|
|
12
|
+
* PgIndexBehaviorsPlugin marks non-indexed columns with `extensions.isIndexed = false`
|
|
13
|
+
* and then adds `-filterBy` behavior to remove them from filters:
|
|
14
|
+
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgIndexBehaviorsPlugin.ts
|
|
15
|
+
*
|
|
16
|
+
* The relevant v5 code (from PgIndexBehaviorsPlugin):
|
|
17
|
+
* ```typescript
|
|
18
|
+
* entityBehavior: {
|
|
19
|
+
* pgCodecAttribute: {
|
|
20
|
+
* inferred: {
|
|
21
|
+
* after: ["inferred"],
|
|
22
|
+
* provides: ["postInferred"],
|
|
23
|
+
* callback(behavior, [codec, attributeName]) {
|
|
24
|
+
* const newBehavior = [behavior];
|
|
25
|
+
* const attr = codec.attributes[attributeName];
|
|
26
|
+
* if (attr.extensions?.isIndexed === false) {
|
|
27
|
+
* newBehavior.push("-filterBy", "-orderBy"); // <-- This removes filterBy!
|
|
28
|
+
* }
|
|
29
|
+
* return newBehavior;
|
|
30
|
+
* },
|
|
31
|
+
* },
|
|
32
|
+
* },
|
|
33
|
+
* },
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* OUR FIX:
|
|
37
|
+
* We add a behavior callback that runs AFTER PgIndexBehaviorsPlugin's "postInferred" phase
|
|
38
|
+
* and adds `+attribute:filterBy` back to ALL columns, regardless of index status.
|
|
39
|
+
*
|
|
40
|
+
* This means:
|
|
41
|
+
* - All columns will appear in the connection filter's filter argument
|
|
42
|
+
* - Developers can filter by any column
|
|
43
|
+
* - It's the developer's/DBA's responsibility to add indexes for frequently filtered columns
|
|
44
|
+
*
|
|
45
|
+
* PERFORMANCE WARNING:
|
|
46
|
+
* Filtering on non-indexed columns can cause full table scans, which may be slow on large
|
|
47
|
+
* tables. Monitor your query performance and add indexes as needed. You can check which
|
|
48
|
+
* columns are indexed by querying pg_indexes or using EXPLAIN ANALYZE on your queries.
|
|
49
|
+
*
|
|
50
|
+
* To identify non-indexed columns being filtered, you can:
|
|
51
|
+
* 1. Enable slow query logging in PostgreSQL (log_min_duration_statement)
|
|
52
|
+
* 2. Use EXPLAIN ANALYZE on queries to see if they're doing sequential scans
|
|
53
|
+
* 3. Check pg_stat_user_tables for seq_scan counts
|
|
54
|
+
*/
|
|
55
|
+
export declare const EnableAllFilterColumnsPlugin: GraphileConfig.Plugin;
|
|
56
|
+
/**
|
|
57
|
+
* Preset that includes the EnableAllFilterColumnsPlugin.
|
|
58
|
+
* Add this to your main preset's `extends` array.
|
|
59
|
+
*/
|
|
60
|
+
export declare const EnableAllFilterColumnsPreset: GraphileConfig.Preset;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EnableAllFilterColumnsPreset = exports.EnableAllFilterColumnsPlugin = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* EnableAllFilterColumnsPlugin - Enables filtering on ALL columns, not just indexed ones.
|
|
6
|
+
*
|
|
7
|
+
* WHY THIS EXISTS:
|
|
8
|
+
* PostGraphile v5's `PgIndexBehaviorsPlugin` restricts filtering to only indexed columns
|
|
9
|
+
* by default. This is a performance optimization - filtering on non-indexed columns can
|
|
10
|
+
* cause slow table scans. However, for development and flexibility, we want to allow
|
|
11
|
+
* filtering on all columns and let developers/DBAs decide which columns need indexes.
|
|
12
|
+
*
|
|
13
|
+
* SOURCE CODE REFERENCE:
|
|
14
|
+
* PgIndexBehaviorsPlugin marks non-indexed columns with `extensions.isIndexed = false`
|
|
15
|
+
* and then adds `-filterBy` behavior to remove them from filters:
|
|
16
|
+
* https://github.com/graphile/crystal/blob/924b2515c6bd30e5905ac1419a25244b40c8bb4d/graphile-build/graphile-build-pg/src/plugins/PgIndexBehaviorsPlugin.ts
|
|
17
|
+
*
|
|
18
|
+
* The relevant v5 code (from PgIndexBehaviorsPlugin):
|
|
19
|
+
* ```typescript
|
|
20
|
+
* entityBehavior: {
|
|
21
|
+
* pgCodecAttribute: {
|
|
22
|
+
* inferred: {
|
|
23
|
+
* after: ["inferred"],
|
|
24
|
+
* provides: ["postInferred"],
|
|
25
|
+
* callback(behavior, [codec, attributeName]) {
|
|
26
|
+
* const newBehavior = [behavior];
|
|
27
|
+
* const attr = codec.attributes[attributeName];
|
|
28
|
+
* if (attr.extensions?.isIndexed === false) {
|
|
29
|
+
* newBehavior.push("-filterBy", "-orderBy"); // <-- This removes filterBy!
|
|
30
|
+
* }
|
|
31
|
+
* return newBehavior;
|
|
32
|
+
* },
|
|
33
|
+
* },
|
|
34
|
+
* },
|
|
35
|
+
* },
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* OUR FIX:
|
|
39
|
+
* We add a behavior callback that runs AFTER PgIndexBehaviorsPlugin's "postInferred" phase
|
|
40
|
+
* and adds `+attribute:filterBy` back to ALL columns, regardless of index status.
|
|
41
|
+
*
|
|
42
|
+
* This means:
|
|
43
|
+
* - All columns will appear in the connection filter's filter argument
|
|
44
|
+
* - Developers can filter by any column
|
|
45
|
+
* - It's the developer's/DBA's responsibility to add indexes for frequently filtered columns
|
|
46
|
+
*
|
|
47
|
+
* PERFORMANCE WARNING:
|
|
48
|
+
* Filtering on non-indexed columns can cause full table scans, which may be slow on large
|
|
49
|
+
* tables. Monitor your query performance and add indexes as needed. You can check which
|
|
50
|
+
* columns are indexed by querying pg_indexes or using EXPLAIN ANALYZE on your queries.
|
|
51
|
+
*
|
|
52
|
+
* To identify non-indexed columns being filtered, you can:
|
|
53
|
+
* 1. Enable slow query logging in PostgreSQL (log_min_duration_statement)
|
|
54
|
+
* 2. Use EXPLAIN ANALYZE on queries to see if they're doing sequential scans
|
|
55
|
+
* 3. Check pg_stat_user_tables for seq_scan counts
|
|
56
|
+
*/
|
|
57
|
+
exports.EnableAllFilterColumnsPlugin = {
|
|
58
|
+
name: 'EnableAllFilterColumnsPlugin',
|
|
59
|
+
version: '1.0.0',
|
|
60
|
+
description: 'Enables filtering on all columns, not just indexed ones',
|
|
61
|
+
schema: {
|
|
62
|
+
entityBehavior: {
|
|
63
|
+
pgCodecAttribute: {
|
|
64
|
+
/**
|
|
65
|
+
* This callback runs in the "inferred" phase AFTER PgIndexBehaviorsPlugin's
|
|
66
|
+
* "postInferred" phase. It adds `filterBy` back to ALL columns, overriding
|
|
67
|
+
* the `-filterBy` that PgIndexBehaviorsPlugin adds to non-indexed columns.
|
|
68
|
+
*/
|
|
69
|
+
inferred: {
|
|
70
|
+
after: ['postInferred'],
|
|
71
|
+
provides: ['enableAllFilters'],
|
|
72
|
+
callback(behavior) {
|
|
73
|
+
// Add filterBy to override any -filterBy from PgIndexBehaviorsPlugin
|
|
74
|
+
// The behavior system will resolve conflicts, with later additions winning
|
|
75
|
+
return [behavior, 'filterBy'];
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Preset that includes the EnableAllFilterColumnsPlugin.
|
|
84
|
+
* Add this to your main preset's `extends` array.
|
|
85
|
+
*/
|
|
86
|
+
exports.EnableAllFilterColumnsPreset = {
|
|
87
|
+
plugins: [exports.EnableAllFilterColumnsPlugin],
|
|
88
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostGraphile v5 Plugins
|
|
3
|
+
*
|
|
4
|
+
* This module exports all custom plugins for PostGraphile v5.
|
|
5
|
+
* Each plugin can be used individually or combined via the presets.
|
|
6
|
+
*/
|
|
7
|
+
export { MinimalPreset } from './minimal-preset';
|
|
8
|
+
export { InflektPlugin, InflektPreset, CustomInflectorPlugin, CustomInflectorPreset, } from './custom-inflector';
|
|
9
|
+
export { ConflictDetectorPlugin, ConflictDetectorPreset, } from './conflict-detector';
|
|
10
|
+
export { InflectorLoggerPlugin, InflectorLoggerPreset, } from './inflector-logger';
|
|
11
|
+
export { EnableAllFilterColumnsPlugin, EnableAllFilterColumnsPreset, } from './enable-all-filter-columns';
|
|
12
|
+
export { ManyToManyOptInPlugin, ManyToManyOptInPreset, } from './many-to-many-preset';
|
|
13
|
+
export { createUniqueLookupPlugin, PrimaryKeyOnlyPlugin, NoUniqueLookupPlugin, PrimaryKeyOnlyPreset, NoUniqueLookupPreset, } from './primary-key-only';
|
|
14
|
+
export type { UniqueLookupOptions } from './primary-key-only';
|
|
15
|
+
export { MetaSchemaPlugin, MetaSchemaPreset, } from './meta-schema';
|
|
16
|
+
export { PgTypeMappingsPlugin, PgTypeMappingsPreset, } from './pg-type-mappings';
|
|
17
|
+
export type { TypeMapping } from './pg-type-mappings';
|
|
18
|
+
export { PgSearchPlugin, PgSearchPreset, createPgSearchPlugin, TsvectorCodecPlugin, TsvectorCodecPreset, } from 'graphile-search-plugin';
|
|
19
|
+
export type { PgSearchPluginOptions } from 'graphile-search-plugin';
|
package/plugins/index.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PostGraphile v5 Plugins
|
|
4
|
+
*
|
|
5
|
+
* This module exports all custom plugins for PostGraphile v5.
|
|
6
|
+
* Each plugin can be used individually or combined via the presets.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.TsvectorCodecPreset = exports.TsvectorCodecPlugin = exports.createPgSearchPlugin = exports.PgSearchPreset = exports.PgSearchPlugin = exports.PgTypeMappingsPreset = exports.PgTypeMappingsPlugin = exports.MetaSchemaPreset = exports.MetaSchemaPlugin = exports.NoUniqueLookupPreset = exports.PrimaryKeyOnlyPreset = exports.NoUniqueLookupPlugin = exports.PrimaryKeyOnlyPlugin = exports.createUniqueLookupPlugin = exports.ManyToManyOptInPreset = exports.ManyToManyOptInPlugin = exports.EnableAllFilterColumnsPreset = exports.EnableAllFilterColumnsPlugin = exports.InflectorLoggerPreset = exports.InflectorLoggerPlugin = exports.ConflictDetectorPreset = exports.ConflictDetectorPlugin = exports.CustomInflectorPreset = exports.CustomInflectorPlugin = exports.InflektPreset = exports.InflektPlugin = exports.MinimalPreset = void 0;
|
|
10
|
+
// Minimal preset - PostGraphile without Node/Relay features
|
|
11
|
+
var minimal_preset_1 = require("./minimal-preset");
|
|
12
|
+
Object.defineProperty(exports, "MinimalPreset", { enumerable: true, get: function () { return minimal_preset_1.MinimalPreset; } });
|
|
13
|
+
// Custom inflector using inflekt library
|
|
14
|
+
var custom_inflector_1 = require("./custom-inflector");
|
|
15
|
+
Object.defineProperty(exports, "InflektPlugin", { enumerable: true, get: function () { return custom_inflector_1.InflektPlugin; } });
|
|
16
|
+
Object.defineProperty(exports, "InflektPreset", { enumerable: true, get: function () { return custom_inflector_1.InflektPreset; } });
|
|
17
|
+
Object.defineProperty(exports, "CustomInflectorPlugin", { enumerable: true, get: function () { return custom_inflector_1.CustomInflectorPlugin; } });
|
|
18
|
+
Object.defineProperty(exports, "CustomInflectorPreset", { enumerable: true, get: function () { return custom_inflector_1.CustomInflectorPreset; } });
|
|
19
|
+
// Conflict detector for multi-schema setups
|
|
20
|
+
var conflict_detector_1 = require("./conflict-detector");
|
|
21
|
+
Object.defineProperty(exports, "ConflictDetectorPlugin", { enumerable: true, get: function () { return conflict_detector_1.ConflictDetectorPlugin; } });
|
|
22
|
+
Object.defineProperty(exports, "ConflictDetectorPreset", { enumerable: true, get: function () { return conflict_detector_1.ConflictDetectorPreset; } });
|
|
23
|
+
// Inflector logger for debugging
|
|
24
|
+
var inflector_logger_1 = require("./inflector-logger");
|
|
25
|
+
Object.defineProperty(exports, "InflectorLoggerPlugin", { enumerable: true, get: function () { return inflector_logger_1.InflectorLoggerPlugin; } });
|
|
26
|
+
Object.defineProperty(exports, "InflectorLoggerPreset", { enumerable: true, get: function () { return inflector_logger_1.InflectorLoggerPreset; } });
|
|
27
|
+
// Enable filtering on all columns (not just indexed)
|
|
28
|
+
var enable_all_filter_columns_1 = require("./enable-all-filter-columns");
|
|
29
|
+
Object.defineProperty(exports, "EnableAllFilterColumnsPlugin", { enumerable: true, get: function () { return enable_all_filter_columns_1.EnableAllFilterColumnsPlugin; } });
|
|
30
|
+
Object.defineProperty(exports, "EnableAllFilterColumnsPreset", { enumerable: true, get: function () { return enable_all_filter_columns_1.EnableAllFilterColumnsPreset; } });
|
|
31
|
+
// Many-to-many with opt-in behavior
|
|
32
|
+
var many_to_many_preset_1 = require("./many-to-many-preset");
|
|
33
|
+
Object.defineProperty(exports, "ManyToManyOptInPlugin", { enumerable: true, get: function () { return many_to_many_preset_1.ManyToManyOptInPlugin; } });
|
|
34
|
+
Object.defineProperty(exports, "ManyToManyOptInPreset", { enumerable: true, get: function () { return many_to_many_preset_1.ManyToManyOptInPreset; } });
|
|
35
|
+
// Primary key only lookups (disable non-PK unique constraints)
|
|
36
|
+
var primary_key_only_1 = require("./primary-key-only");
|
|
37
|
+
Object.defineProperty(exports, "createUniqueLookupPlugin", { enumerable: true, get: function () { return primary_key_only_1.createUniqueLookupPlugin; } });
|
|
38
|
+
Object.defineProperty(exports, "PrimaryKeyOnlyPlugin", { enumerable: true, get: function () { return primary_key_only_1.PrimaryKeyOnlyPlugin; } });
|
|
39
|
+
Object.defineProperty(exports, "NoUniqueLookupPlugin", { enumerable: true, get: function () { return primary_key_only_1.NoUniqueLookupPlugin; } });
|
|
40
|
+
Object.defineProperty(exports, "PrimaryKeyOnlyPreset", { enumerable: true, get: function () { return primary_key_only_1.PrimaryKeyOnlyPreset; } });
|
|
41
|
+
Object.defineProperty(exports, "NoUniqueLookupPreset", { enumerable: true, get: function () { return primary_key_only_1.NoUniqueLookupPreset; } });
|
|
42
|
+
// Meta schema plugin for introspection (tables, fields, indexes, constraints)
|
|
43
|
+
var meta_schema_1 = require("./meta-schema");
|
|
44
|
+
Object.defineProperty(exports, "MetaSchemaPlugin", { enumerable: true, get: function () { return meta_schema_1.MetaSchemaPlugin; } });
|
|
45
|
+
Object.defineProperty(exports, "MetaSchemaPreset", { enumerable: true, get: function () { return meta_schema_1.MetaSchemaPreset; } });
|
|
46
|
+
// PG type mappings for custom PostgreSQL types (email, url, etc.)
|
|
47
|
+
var pg_type_mappings_1 = require("./pg-type-mappings");
|
|
48
|
+
Object.defineProperty(exports, "PgTypeMappingsPlugin", { enumerable: true, get: function () { return pg_type_mappings_1.PgTypeMappingsPlugin; } });
|
|
49
|
+
Object.defineProperty(exports, "PgTypeMappingsPreset", { enumerable: true, get: function () { return pg_type_mappings_1.PgTypeMappingsPreset; } });
|
|
50
|
+
// Search plugin for tsvector full-text search conditions (includes TsvectorCodec)
|
|
51
|
+
var graphile_search_plugin_1 = require("graphile-search-plugin");
|
|
52
|
+
Object.defineProperty(exports, "PgSearchPlugin", { enumerable: true, get: function () { return graphile_search_plugin_1.PgSearchPlugin; } });
|
|
53
|
+
Object.defineProperty(exports, "PgSearchPreset", { enumerable: true, get: function () { return graphile_search_plugin_1.PgSearchPreset; } });
|
|
54
|
+
Object.defineProperty(exports, "createPgSearchPlugin", { enumerable: true, get: function () { return graphile_search_plugin_1.createPgSearchPlugin; } });
|
|
55
|
+
Object.defineProperty(exports, "TsvectorCodecPlugin", { enumerable: true, get: function () { return graphile_search_plugin_1.TsvectorCodecPlugin; } });
|
|
56
|
+
Object.defineProperty(exports, "TsvectorCodecPreset", { enumerable: true, get: function () { return graphile_search_plugin_1.TsvectorCodecPreset; } });
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GraphileConfig } from 'graphile-config';
|
|
2
|
+
export declare const InflectorLoggerPlugin: GraphileConfig.Plugin;
|
|
3
|
+
/**
|
|
4
|
+
* Preset that includes the inflector logger plugin.
|
|
5
|
+
* Use this in your main preset's `extends` array.
|
|
6
|
+
*/
|
|
7
|
+
export declare const InflectorLoggerPreset: GraphileConfig.Preset;
|