@constructive-io/graphql-query 3.2.4 → 3.3.0
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 +411 -65
- package/ast.d.ts +4 -4
- package/ast.js +24 -9
- package/client/error.d.ts +95 -0
- package/client/error.js +277 -0
- package/client/execute.d.ts +57 -0
- package/client/execute.js +124 -0
- package/client/index.d.ts +8 -0
- package/client/index.js +20 -0
- package/client/typed-document.d.ts +31 -0
- package/client/typed-document.js +44 -0
- package/custom-ast.d.ts +22 -8
- package/custom-ast.js +16 -1
- package/esm/ast.js +22 -7
- package/esm/client/error.js +271 -0
- package/esm/client/execute.js +120 -0
- package/esm/client/index.js +8 -0
- package/esm/client/typed-document.js +40 -0
- package/esm/custom-ast.js +16 -1
- package/esm/generators/field-selector.js +381 -0
- package/esm/generators/index.js +13 -0
- package/esm/generators/mutations.js +200 -0
- package/esm/generators/naming-helpers.js +154 -0
- package/esm/generators/select.js +661 -0
- package/esm/index.js +30 -0
- package/esm/introspect/index.js +9 -0
- package/esm/introspect/infer-tables.js +697 -0
- package/esm/introspect/schema-query.js +120 -0
- package/esm/introspect/transform-schema.js +271 -0
- package/esm/introspect/transform.js +38 -0
- package/esm/meta-object/convert.js +3 -0
- package/esm/meta-object/format.json +11 -41
- package/esm/meta-object/validate.js +20 -4
- package/esm/query-builder.js +14 -18
- package/esm/types/index.js +18 -0
- package/esm/types/introspection.js +54 -0
- package/esm/types/mutation.js +4 -0
- package/esm/types/query.js +4 -0
- package/esm/types/schema.js +5 -0
- package/esm/types/selection.js +4 -0
- package/esm/utils.js +69 -0
- package/generators/field-selector.d.ts +30 -0
- package/generators/field-selector.js +387 -0
- package/generators/index.d.ts +9 -0
- package/generators/index.js +42 -0
- package/generators/mutations.d.ts +30 -0
- package/generators/mutations.js +238 -0
- package/generators/naming-helpers.d.ts +48 -0
- package/generators/naming-helpers.js +169 -0
- package/generators/select.d.ts +39 -0
- package/generators/select.js +705 -0
- package/index.d.ts +19 -0
- package/index.js +34 -1
- package/introspect/index.d.ts +9 -0
- package/introspect/index.js +25 -0
- package/introspect/infer-tables.d.ts +42 -0
- package/introspect/infer-tables.js +700 -0
- package/introspect/schema-query.d.ts +20 -0
- package/introspect/schema-query.js +123 -0
- package/introspect/transform-schema.d.ts +86 -0
- package/introspect/transform-schema.js +281 -0
- package/introspect/transform.d.ts +20 -0
- package/introspect/transform.js +43 -0
- package/meta-object/convert.d.ts +3 -0
- package/meta-object/convert.js +3 -0
- package/meta-object/format.json +11 -41
- package/meta-object/validate.d.ts +8 -3
- package/meta-object/validate.js +20 -4
- package/package.json +4 -3
- package/query-builder.d.ts +11 -12
- package/query-builder.js +25 -29
- package/{types.d.ts → types/core.d.ts} +25 -18
- package/types/index.d.ts +12 -0
- package/types/index.js +34 -0
- package/types/introspection.d.ts +121 -0
- package/types/introspection.js +62 -0
- package/types/mutation.d.ts +45 -0
- package/types/mutation.js +5 -0
- package/types/query.d.ts +91 -0
- package/types/query.js +5 -0
- package/types/schema.d.ts +265 -0
- package/types/schema.js +6 -0
- package/types/selection.d.ts +43 -0
- package/types/selection.js +5 -0
- package/utils.d.ts +17 -0
- package/utils.js +72 -0
- /package/esm/{types.js → types/core.js} +0 -0
- /package/{types.js → types/core.js} +0 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.buildPostGraphileCreate = buildPostGraphileCreate;
|
|
37
|
+
exports.buildPostGraphileUpdate = buildPostGraphileUpdate;
|
|
38
|
+
exports.buildPostGraphileDelete = buildPostGraphileDelete;
|
|
39
|
+
/**
|
|
40
|
+
* Mutation generators for CREATE, UPDATE, and DELETE operations
|
|
41
|
+
* Uses AST-based approach for PostGraphile-compatible mutations
|
|
42
|
+
*/
|
|
43
|
+
const t = __importStar(require("gql-ast"));
|
|
44
|
+
const graphql_1 = require("graphql");
|
|
45
|
+
const typed_document_1 = require("../client/typed-document");
|
|
46
|
+
const custom_ast_1 = require("../custom-ast");
|
|
47
|
+
const field_selector_1 = require("./field-selector");
|
|
48
|
+
const naming_helpers_1 = require("./naming-helpers");
|
|
49
|
+
/**
|
|
50
|
+
* Generate field selections for PostGraphile mutations using custom AST logic
|
|
51
|
+
* This handles both scalar fields and complex types that require subfield selections
|
|
52
|
+
*/
|
|
53
|
+
function generateFieldSelections(table) {
|
|
54
|
+
return table.fields
|
|
55
|
+
.filter((field) => !(0, field_selector_1.isRelationalField)(field.name, table)) // Exclude relational fields
|
|
56
|
+
.map((field) => {
|
|
57
|
+
if ((0, custom_ast_1.requiresSubfieldSelection)(field)) {
|
|
58
|
+
// Use custom AST generation for complex types
|
|
59
|
+
return (0, custom_ast_1.getCustomAstForCleanField)(field);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Use simple field selection for scalar types
|
|
63
|
+
return t.field({ name: field.name });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Build PostGraphile-style CREATE mutation
|
|
69
|
+
* PostGraphile expects: mutation { createTableName(input: { tableName: TableNameInput! }) { tableName { ... } } }
|
|
70
|
+
*/
|
|
71
|
+
function buildPostGraphileCreate(table, _allTables, _options = {}) {
|
|
72
|
+
const mutationName = (0, naming_helpers_1.toCreateMutationName)(table.name, table);
|
|
73
|
+
const singularName = (0, naming_helpers_1.toCamelCaseSingular)(table.name, table);
|
|
74
|
+
const inputTypeName = (0, naming_helpers_1.toCreateInputTypeName)(table.name, table);
|
|
75
|
+
// Create the variable definition for $input
|
|
76
|
+
const variableDefinitions = [
|
|
77
|
+
t.variableDefinition({
|
|
78
|
+
variable: t.variable({ name: 'input' }),
|
|
79
|
+
type: t.nonNullType({
|
|
80
|
+
type: t.namedType({ type: inputTypeName }),
|
|
81
|
+
}),
|
|
82
|
+
}),
|
|
83
|
+
];
|
|
84
|
+
// Create the mutation arguments
|
|
85
|
+
const mutationArgs = [
|
|
86
|
+
t.argument({
|
|
87
|
+
name: 'input',
|
|
88
|
+
value: t.variable({ name: 'input' }),
|
|
89
|
+
}),
|
|
90
|
+
];
|
|
91
|
+
// Get the field selections for the return value using custom AST logic
|
|
92
|
+
const fieldSelections = generateFieldSelections(table);
|
|
93
|
+
// Build the mutation AST
|
|
94
|
+
const ast = t.document({
|
|
95
|
+
definitions: [
|
|
96
|
+
t.operationDefinition({
|
|
97
|
+
operation: graphql_1.OperationTypeNode.MUTATION,
|
|
98
|
+
name: `${mutationName}Mutation`,
|
|
99
|
+
variableDefinitions,
|
|
100
|
+
selectionSet: t.selectionSet({
|
|
101
|
+
selections: [
|
|
102
|
+
t.field({
|
|
103
|
+
name: mutationName,
|
|
104
|
+
args: mutationArgs,
|
|
105
|
+
selectionSet: t.selectionSet({
|
|
106
|
+
selections: [
|
|
107
|
+
t.field({
|
|
108
|
+
name: singularName,
|
|
109
|
+
selectionSet: t.selectionSet({
|
|
110
|
+
selections: fieldSelections,
|
|
111
|
+
}),
|
|
112
|
+
}),
|
|
113
|
+
],
|
|
114
|
+
}),
|
|
115
|
+
}),
|
|
116
|
+
],
|
|
117
|
+
}),
|
|
118
|
+
}),
|
|
119
|
+
],
|
|
120
|
+
});
|
|
121
|
+
// Print the AST to get the query string
|
|
122
|
+
const queryString = (0, graphql_1.print)(ast);
|
|
123
|
+
return new typed_document_1.TypedDocumentString(queryString, {
|
|
124
|
+
__ast: ast,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Build PostGraphile-style UPDATE mutation
|
|
129
|
+
* PostGraphile expects: mutation { updateTableName(input: { id: UUID!, patch: TableNamePatch! }) { tableName { ... } } }
|
|
130
|
+
*/
|
|
131
|
+
function buildPostGraphileUpdate(table, _allTables, _options = {}) {
|
|
132
|
+
const mutationName = (0, naming_helpers_1.toUpdateMutationName)(table.name, table);
|
|
133
|
+
const singularName = (0, naming_helpers_1.toCamelCaseSingular)(table.name, table);
|
|
134
|
+
const inputTypeName = (0, naming_helpers_1.toUpdateInputTypeName)(table.name);
|
|
135
|
+
// Create the variable definition for $input
|
|
136
|
+
const variableDefinitions = [
|
|
137
|
+
t.variableDefinition({
|
|
138
|
+
variable: t.variable({ name: 'input' }),
|
|
139
|
+
type: t.nonNullType({
|
|
140
|
+
type: t.namedType({ type: inputTypeName }),
|
|
141
|
+
}),
|
|
142
|
+
}),
|
|
143
|
+
];
|
|
144
|
+
// Create the mutation arguments
|
|
145
|
+
const mutationArgs = [
|
|
146
|
+
t.argument({
|
|
147
|
+
name: 'input',
|
|
148
|
+
value: t.variable({ name: 'input' }),
|
|
149
|
+
}),
|
|
150
|
+
];
|
|
151
|
+
// Get the field selections for the return value using custom AST logic
|
|
152
|
+
const fieldSelections = generateFieldSelections(table);
|
|
153
|
+
// Build the mutation AST
|
|
154
|
+
const ast = t.document({
|
|
155
|
+
definitions: [
|
|
156
|
+
t.operationDefinition({
|
|
157
|
+
operation: graphql_1.OperationTypeNode.MUTATION,
|
|
158
|
+
name: `${mutationName}Mutation`,
|
|
159
|
+
variableDefinitions,
|
|
160
|
+
selectionSet: t.selectionSet({
|
|
161
|
+
selections: [
|
|
162
|
+
t.field({
|
|
163
|
+
name: mutationName,
|
|
164
|
+
args: mutationArgs,
|
|
165
|
+
selectionSet: t.selectionSet({
|
|
166
|
+
selections: [
|
|
167
|
+
t.field({
|
|
168
|
+
name: singularName,
|
|
169
|
+
selectionSet: t.selectionSet({
|
|
170
|
+
selections: fieldSelections,
|
|
171
|
+
}),
|
|
172
|
+
}),
|
|
173
|
+
],
|
|
174
|
+
}),
|
|
175
|
+
}),
|
|
176
|
+
],
|
|
177
|
+
}),
|
|
178
|
+
}),
|
|
179
|
+
],
|
|
180
|
+
});
|
|
181
|
+
// Print the AST to get the query string
|
|
182
|
+
const queryString = (0, graphql_1.print)(ast);
|
|
183
|
+
return new typed_document_1.TypedDocumentString(queryString, {
|
|
184
|
+
__ast: ast,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Build PostGraphile-style DELETE mutation
|
|
189
|
+
* PostGraphile expects: mutation { deleteTableName(input: { id: UUID! }) { clientMutationId } }
|
|
190
|
+
*/
|
|
191
|
+
function buildPostGraphileDelete(table, _allTables, _options = {}) {
|
|
192
|
+
const mutationName = (0, naming_helpers_1.toDeleteMutationName)(table.name, table);
|
|
193
|
+
const inputTypeName = (0, naming_helpers_1.toDeleteInputTypeName)(table.name);
|
|
194
|
+
// Create the variable definition for $input
|
|
195
|
+
const variableDefinitions = [
|
|
196
|
+
t.variableDefinition({
|
|
197
|
+
variable: t.variable({ name: 'input' }),
|
|
198
|
+
type: t.nonNullType({
|
|
199
|
+
type: t.namedType({ type: inputTypeName }),
|
|
200
|
+
}),
|
|
201
|
+
}),
|
|
202
|
+
];
|
|
203
|
+
// Create the mutation arguments
|
|
204
|
+
const mutationArgs = [
|
|
205
|
+
t.argument({
|
|
206
|
+
name: 'input',
|
|
207
|
+
value: t.variable({ name: 'input' }),
|
|
208
|
+
}),
|
|
209
|
+
];
|
|
210
|
+
// PostGraphile delete mutations typically return clientMutationId
|
|
211
|
+
const fieldSelections = [t.field({ name: 'clientMutationId' })];
|
|
212
|
+
// Build the mutation AST
|
|
213
|
+
const ast = t.document({
|
|
214
|
+
definitions: [
|
|
215
|
+
t.operationDefinition({
|
|
216
|
+
operation: graphql_1.OperationTypeNode.MUTATION,
|
|
217
|
+
name: `${mutationName}Mutation`,
|
|
218
|
+
variableDefinitions,
|
|
219
|
+
selectionSet: t.selectionSet({
|
|
220
|
+
selections: [
|
|
221
|
+
t.field({
|
|
222
|
+
name: mutationName,
|
|
223
|
+
args: mutationArgs,
|
|
224
|
+
selectionSet: t.selectionSet({
|
|
225
|
+
selections: fieldSelections,
|
|
226
|
+
}),
|
|
227
|
+
}),
|
|
228
|
+
],
|
|
229
|
+
}),
|
|
230
|
+
}),
|
|
231
|
+
],
|
|
232
|
+
});
|
|
233
|
+
// Print the AST to get the query string
|
|
234
|
+
const queryString = (0, graphql_1.print)(ast);
|
|
235
|
+
return new typed_document_1.TypedDocumentString(queryString, {
|
|
236
|
+
__ast: ast,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { CleanTable } from '../types/schema';
|
|
2
|
+
/**
|
|
3
|
+
* Safely normalise a server-provided inflection value.
|
|
4
|
+
* Returns `null` for null, undefined, or whitespace-only strings.
|
|
5
|
+
*/
|
|
6
|
+
export declare function normalizeInflectionValue(value: string | null | undefined): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Convert PascalCase table name to camelCase plural for GraphQL queries.
|
|
9
|
+
* Prefers server-provided `table.query.all` / `table.inflection.allRows`
|
|
10
|
+
* when available, with guards against naive pluralisation drift and
|
|
11
|
+
* missing camelCase boundaries.
|
|
12
|
+
*
|
|
13
|
+
* Example: "ActionGoal" -> "actionGoals", "User" -> "users", "Person" -> "people"
|
|
14
|
+
*/
|
|
15
|
+
export declare function toCamelCasePlural(tableName: string, table?: CleanTable | null): string;
|
|
16
|
+
/**
|
|
17
|
+
* Convert PascalCase table name to camelCase singular field name.
|
|
18
|
+
* Prefers server-provided names when available.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toCamelCaseSingular(tableName: string, table?: CleanTable | null): string;
|
|
21
|
+
export declare function toCreateMutationName(tableName: string, table?: CleanTable | null): string;
|
|
22
|
+
export declare function toUpdateMutationName(tableName: string, table?: CleanTable | null): string;
|
|
23
|
+
export declare function toDeleteMutationName(tableName: string, table?: CleanTable | null): string;
|
|
24
|
+
export declare function toCreateInputTypeName(tableName: string, table?: CleanTable | null): string;
|
|
25
|
+
export declare function toUpdateInputTypeName(tableName: string): string;
|
|
26
|
+
export declare function toDeleteInputTypeName(tableName: string): string;
|
|
27
|
+
export declare function toFilterTypeName(tableName: string, table?: CleanTable | null): string;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve PostGraphile patch field name.
|
|
30
|
+
* In v5 this is typically entity-specific: e.g. "userPatch", "contactPatch".
|
|
31
|
+
* Prefers the value discovered from the schema (`table.query.patchFieldName`
|
|
32
|
+
* or `table.inflection.patchField`), falls back to `${singularName}Patch`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function toPatchFieldName(tableName: string, table?: CleanTable | null): string;
|
|
35
|
+
/**
|
|
36
|
+
* Convert camelCase field name to SCREAMING_SNAKE_CASE for PostGraphile
|
|
37
|
+
* orderBy enums.
|
|
38
|
+
*
|
|
39
|
+
* "displayName" -> "DISPLAY_NAME_ASC"
|
|
40
|
+
* "createdAt" -> "CREATED_AT_DESC"
|
|
41
|
+
* "id" -> "ID_ASC"
|
|
42
|
+
*/
|
|
43
|
+
export declare function toOrderByEnumValue(fieldName: string, direction: 'asc' | 'desc'): string;
|
|
44
|
+
/**
|
|
45
|
+
* Generate the PostGraphile OrderBy enum type name for a table.
|
|
46
|
+
* Prefers server-provided `table.inflection.orderByType` when available.
|
|
47
|
+
*/
|
|
48
|
+
export declare function toOrderByTypeName(tableName: string, table?: CleanTable | null): string;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.normalizeInflectionValue = normalizeInflectionValue;
|
|
4
|
+
exports.toCamelCasePlural = toCamelCasePlural;
|
|
5
|
+
exports.toCamelCaseSingular = toCamelCaseSingular;
|
|
6
|
+
exports.toCreateMutationName = toCreateMutationName;
|
|
7
|
+
exports.toUpdateMutationName = toUpdateMutationName;
|
|
8
|
+
exports.toDeleteMutationName = toDeleteMutationName;
|
|
9
|
+
exports.toCreateInputTypeName = toCreateInputTypeName;
|
|
10
|
+
exports.toUpdateInputTypeName = toUpdateInputTypeName;
|
|
11
|
+
exports.toDeleteInputTypeName = toDeleteInputTypeName;
|
|
12
|
+
exports.toFilterTypeName = toFilterTypeName;
|
|
13
|
+
exports.toPatchFieldName = toPatchFieldName;
|
|
14
|
+
exports.toOrderByEnumValue = toOrderByEnumValue;
|
|
15
|
+
exports.toOrderByTypeName = toOrderByTypeName;
|
|
16
|
+
/**
|
|
17
|
+
* Server-aware naming helpers for GraphQL query/mutation generation.
|
|
18
|
+
*
|
|
19
|
+
* These functions prefer names already discovered from the GraphQL schema
|
|
20
|
+
* (stored on `table.query` and `table.inflection` by `infer-tables.ts`)
|
|
21
|
+
* and fall back to local inflection when introspection data is unavailable.
|
|
22
|
+
*
|
|
23
|
+
* Back-ported from Dashboard's `packages/data/src/query-generator.ts`.
|
|
24
|
+
*/
|
|
25
|
+
const inflekt_1 = require("inflekt");
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Internal helpers
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Safely normalise a server-provided inflection value.
|
|
31
|
+
* Returns `null` for null, undefined, or whitespace-only strings.
|
|
32
|
+
*/
|
|
33
|
+
function normalizeInflectionValue(value) {
|
|
34
|
+
if (typeof value !== 'string')
|
|
35
|
+
return null;
|
|
36
|
+
const trimmed = value.trim();
|
|
37
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Plural / Singular
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* Convert PascalCase table name to camelCase plural for GraphQL queries.
|
|
44
|
+
* Prefers server-provided `table.query.all` / `table.inflection.allRows`
|
|
45
|
+
* when available, with guards against naive pluralisation drift and
|
|
46
|
+
* missing camelCase boundaries.
|
|
47
|
+
*
|
|
48
|
+
* Example: "ActionGoal" -> "actionGoals", "User" -> "users", "Person" -> "people"
|
|
49
|
+
*/
|
|
50
|
+
function toCamelCasePlural(tableName, table) {
|
|
51
|
+
const singular = (0, inflekt_1.camelize)(tableName, true);
|
|
52
|
+
const inflectedPlural = (0, inflekt_1.pluralize)(singular);
|
|
53
|
+
const serverPluralCandidates = [
|
|
54
|
+
table?.query?.all,
|
|
55
|
+
table?.inflection?.allRows,
|
|
56
|
+
];
|
|
57
|
+
for (const candidateRaw of serverPluralCandidates) {
|
|
58
|
+
const candidate = normalizeInflectionValue(candidateRaw);
|
|
59
|
+
if (!candidate)
|
|
60
|
+
continue;
|
|
61
|
+
// Guard against known fallback drift:
|
|
62
|
+
// 1. Naive pluralisation: "activitys" instead of "activities"
|
|
63
|
+
const isNaivePlural = candidate === `${singular}s` && candidate !== inflectedPlural;
|
|
64
|
+
// 2. Missing camelCase boundaries: "deliveryzones" instead of "deliveryZones"
|
|
65
|
+
const isMiscased = candidate !== inflectedPlural &&
|
|
66
|
+
candidate.toLowerCase() === inflectedPlural.toLowerCase();
|
|
67
|
+
if (isNaivePlural || isMiscased)
|
|
68
|
+
continue;
|
|
69
|
+
return candidate;
|
|
70
|
+
}
|
|
71
|
+
return inflectedPlural;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Convert PascalCase table name to camelCase singular field name.
|
|
75
|
+
* Prefers server-provided names when available.
|
|
76
|
+
*/
|
|
77
|
+
function toCamelCaseSingular(tableName, table) {
|
|
78
|
+
const localSingular = (0, inflekt_1.camelize)(tableName, true);
|
|
79
|
+
for (const candidateRaw of [
|
|
80
|
+
table?.query?.one,
|
|
81
|
+
table?.inflection?.tableFieldName,
|
|
82
|
+
]) {
|
|
83
|
+
const candidate = normalizeInflectionValue(candidateRaw);
|
|
84
|
+
if (!candidate)
|
|
85
|
+
continue;
|
|
86
|
+
// Reject miscased versions: "deliveryzone" vs "deliveryZone"
|
|
87
|
+
if (candidate !== localSingular &&
|
|
88
|
+
candidate.toLowerCase() === localSingular.toLowerCase())
|
|
89
|
+
continue;
|
|
90
|
+
return candidate;
|
|
91
|
+
}
|
|
92
|
+
return localSingular;
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// Mutation names
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
function toCreateMutationName(tableName, table) {
|
|
98
|
+
return (normalizeInflectionValue(table?.query?.create) ?? `create${tableName}`);
|
|
99
|
+
}
|
|
100
|
+
function toUpdateMutationName(tableName, table) {
|
|
101
|
+
return (normalizeInflectionValue(table?.query?.update) ?? `update${tableName}`);
|
|
102
|
+
}
|
|
103
|
+
function toDeleteMutationName(tableName, table) {
|
|
104
|
+
return (normalizeInflectionValue(table?.query?.delete) ?? `delete${tableName}`);
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Input / type names
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
function toCreateInputTypeName(tableName, table) {
|
|
110
|
+
return (normalizeInflectionValue(table?.inflection?.createInputType) ??
|
|
111
|
+
`Create${tableName}Input`);
|
|
112
|
+
}
|
|
113
|
+
function toUpdateInputTypeName(tableName) {
|
|
114
|
+
return `Update${tableName}Input`;
|
|
115
|
+
}
|
|
116
|
+
function toDeleteInputTypeName(tableName) {
|
|
117
|
+
return `Delete${tableName}Input`;
|
|
118
|
+
}
|
|
119
|
+
function toFilterTypeName(tableName, table) {
|
|
120
|
+
return (normalizeInflectionValue(table?.inflection?.filterType) ??
|
|
121
|
+
`${tableName}Filter`);
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Patch field name
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Resolve PostGraphile patch field name.
|
|
128
|
+
* In v5 this is typically entity-specific: e.g. "userPatch", "contactPatch".
|
|
129
|
+
* Prefers the value discovered from the schema (`table.query.patchFieldName`
|
|
130
|
+
* or `table.inflection.patchField`), falls back to `${singularName}Patch`.
|
|
131
|
+
*/
|
|
132
|
+
function toPatchFieldName(tableName, table) {
|
|
133
|
+
// First check the patch field name discovered from UpdateXxxInput
|
|
134
|
+
const introspectedPatch = normalizeInflectionValue(table?.query?.patchFieldName);
|
|
135
|
+
if (introspectedPatch)
|
|
136
|
+
return introspectedPatch;
|
|
137
|
+
// Then check the inflection table
|
|
138
|
+
const explicitPatchField = normalizeInflectionValue(table?.inflection?.patchField);
|
|
139
|
+
if (explicitPatchField)
|
|
140
|
+
return explicitPatchField;
|
|
141
|
+
return `${toCamelCaseSingular(tableName, table)}Patch`;
|
|
142
|
+
}
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
// OrderBy helpers
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
/**
|
|
147
|
+
* Convert camelCase field name to SCREAMING_SNAKE_CASE for PostGraphile
|
|
148
|
+
* orderBy enums.
|
|
149
|
+
*
|
|
150
|
+
* "displayName" -> "DISPLAY_NAME_ASC"
|
|
151
|
+
* "createdAt" -> "CREATED_AT_DESC"
|
|
152
|
+
* "id" -> "ID_ASC"
|
|
153
|
+
*/
|
|
154
|
+
function toOrderByEnumValue(fieldName, direction) {
|
|
155
|
+
const screaming = fieldName
|
|
156
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
157
|
+
.toUpperCase();
|
|
158
|
+
return `${screaming}_${direction.toUpperCase()}`;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Generate the PostGraphile OrderBy enum type name for a table.
|
|
162
|
+
* Prefers server-provided `table.inflection.orderByType` when available.
|
|
163
|
+
*/
|
|
164
|
+
function toOrderByTypeName(tableName, table) {
|
|
165
|
+
if (table?.inflection?.orderByType)
|
|
166
|
+
return table.inflection.orderByType;
|
|
167
|
+
const plural = toCamelCasePlural(tableName, table);
|
|
168
|
+
return `${plural.charAt(0).toUpperCase() + plural.slice(1)}OrderBy`;
|
|
169
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { TypedDocumentString } from '../client/typed-document';
|
|
2
|
+
import { QueryBuilder } from '../query-builder';
|
|
3
|
+
import type { MetaObject, QueryIntrospectionSchema } from '../types';
|
|
4
|
+
import type { QueryOptions } from '../types/query';
|
|
5
|
+
import type { CleanTable } from '../types/schema';
|
|
6
|
+
export { toCamelCasePlural, toOrderByTypeName } from './naming-helpers';
|
|
7
|
+
/**
|
|
8
|
+
* Convert CleanTable to MetaObject format for QueryBuilder
|
|
9
|
+
*/
|
|
10
|
+
export declare function cleanTableToMetaObject(tables: CleanTable[]): MetaObject;
|
|
11
|
+
/**
|
|
12
|
+
* Generate basic IntrospectionSchema from CleanTable array
|
|
13
|
+
* This creates a minimal schema for AST generation
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateIntrospectionSchema(tables: CleanTable[]): QueryIntrospectionSchema;
|
|
16
|
+
/**
|
|
17
|
+
* Create AST-based query builder for a table
|
|
18
|
+
*/
|
|
19
|
+
export declare function createASTQueryBuilder(tables: CleanTable[]): QueryBuilder;
|
|
20
|
+
/**
|
|
21
|
+
* Build a SELECT query for a table with optional filtering, sorting, and pagination
|
|
22
|
+
* Uses direct AST generation without intermediate conversions
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildSelect(table: CleanTable, allTables: readonly CleanTable[], options?: QueryOptions): TypedDocumentString<Record<string, unknown>, QueryOptions>;
|
|
25
|
+
/**
|
|
26
|
+
* Build a single row query by primary key or unique field
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildFindOne(table: CleanTable, _pkField?: string): TypedDocumentString<Record<string, unknown>, Record<string, unknown>>;
|
|
29
|
+
/**
|
|
30
|
+
* Build a count query for a table
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildCount(table: CleanTable): TypedDocumentString<{
|
|
33
|
+
[key: string]: {
|
|
34
|
+
totalCount: number;
|
|
35
|
+
};
|
|
36
|
+
}, {
|
|
37
|
+
condition?: Record<string, unknown>;
|
|
38
|
+
filter?: Record<string, unknown>;
|
|
39
|
+
}>;
|