@constructive-io/graphql-codegen 2.24.0 → 2.26.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 +403 -279
- package/cli/codegen/babel-ast.d.ts +7 -0
- package/cli/codegen/babel-ast.js +15 -0
- package/cli/codegen/barrel.js +43 -14
- package/cli/codegen/custom-mutations.js +4 -4
- package/cli/codegen/custom-queries.js +12 -22
- package/cli/codegen/gql-ast.js +22 -1
- package/cli/codegen/index.js +1 -0
- package/cli/codegen/mutations.d.ts +2 -0
- package/cli/codegen/mutations.js +26 -13
- package/cli/codegen/orm/client-generator.js +475 -136
- package/cli/codegen/orm/custom-ops-generator.js +8 -3
- package/cli/codegen/orm/input-types-generator.js +22 -0
- package/cli/codegen/orm/model-generator.js +18 -5
- package/cli/codegen/orm/select-types.d.ts +33 -0
- package/cli/codegen/queries.d.ts +1 -1
- package/cli/codegen/queries.js +112 -35
- package/cli/codegen/utils.d.ts +6 -0
- package/cli/codegen/utils.js +19 -0
- package/cli/commands/generate-orm.d.ts +14 -0
- package/cli/commands/generate-orm.js +160 -44
- package/cli/commands/generate.d.ts +22 -0
- package/cli/commands/generate.js +195 -55
- package/cli/commands/init.js +29 -9
- package/cli/index.js +133 -28
- package/cli/watch/orchestrator.d.ts +4 -0
- package/cli/watch/orchestrator.js +4 -0
- package/esm/cli/codegen/babel-ast.d.ts +7 -0
- package/esm/cli/codegen/babel-ast.js +14 -0
- package/esm/cli/codegen/barrel.js +44 -15
- package/esm/cli/codegen/custom-mutations.js +5 -5
- package/esm/cli/codegen/custom-queries.js +13 -23
- package/esm/cli/codegen/gql-ast.js +23 -2
- package/esm/cli/codegen/index.js +1 -0
- package/esm/cli/codegen/mutations.d.ts +2 -0
- package/esm/cli/codegen/mutations.js +27 -14
- package/esm/cli/codegen/orm/client-generator.js +475 -136
- package/esm/cli/codegen/orm/custom-ops-generator.js +8 -3
- package/esm/cli/codegen/orm/input-types-generator.js +22 -0
- package/esm/cli/codegen/orm/model-generator.js +18 -5
- package/esm/cli/codegen/orm/select-types.d.ts +33 -0
- package/esm/cli/codegen/queries.d.ts +1 -1
- package/esm/cli/codegen/queries.js +114 -37
- package/esm/cli/codegen/utils.d.ts +6 -0
- package/esm/cli/codegen/utils.js +18 -0
- package/esm/cli/commands/generate-orm.d.ts +14 -0
- package/esm/cli/commands/generate-orm.js +161 -45
- package/esm/cli/commands/generate.d.ts +22 -0
- package/esm/cli/commands/generate.js +195 -56
- package/esm/cli/commands/init.js +29 -9
- package/esm/cli/index.js +134 -29
- package/esm/cli/watch/orchestrator.d.ts +4 -0
- package/esm/cli/watch/orchestrator.js +5 -1
- package/esm/types/config.d.ts +39 -2
- package/esm/types/config.js +88 -4
- package/esm/types/index.d.ts +2 -2
- package/esm/types/index.js +1 -1
- package/package.json +10 -7
- package/types/config.d.ts +39 -2
- package/types/config.js +91 -4
- package/types/index.d.ts +2 -2
- package/types/index.js +2 -1
- package/cli/codegen/orm/query-builder.d.ts +0 -161
- package/cli/codegen/orm/query-builder.js +0 -366
- package/esm/cli/codegen/orm/query-builder.d.ts +0 -161
- package/esm/cli/codegen/orm/query-builder.js +0 -353
package/types/config.js
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.DEFAULT_ORM_CONFIG = exports.DEFAULT_CONFIG = exports.DEFAULT_QUERY_KEY_CONFIG = exports.DEFAULT_WATCH_CONFIG = void 0;
|
|
7
7
|
exports.defineConfig = defineConfig;
|
|
8
|
+
exports.isMultiConfig = isMultiConfig;
|
|
9
|
+
exports.mergeConfig = mergeConfig;
|
|
8
10
|
exports.resolveConfig = resolveConfig;
|
|
11
|
+
exports.resolveConfigTargets = resolveConfigTargets;
|
|
9
12
|
/**
|
|
10
13
|
* Default watch configuration values
|
|
11
14
|
*/
|
|
@@ -76,10 +79,80 @@ exports.DEFAULT_ORM_CONFIG = {
|
|
|
76
79
|
function defineConfig(config) {
|
|
77
80
|
return config;
|
|
78
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Type guard for multi-target configs
|
|
84
|
+
*/
|
|
85
|
+
function isMultiConfig(config) {
|
|
86
|
+
const targets = config.targets;
|
|
87
|
+
return typeof targets === 'object' && targets !== null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Merge two target configs (defaults + overrides)
|
|
91
|
+
*/
|
|
92
|
+
function mergeConfig(base, overrides) {
|
|
93
|
+
const headers = base.headers || overrides.headers
|
|
94
|
+
? { ...(base.headers ?? {}), ...(overrides.headers ?? {}) }
|
|
95
|
+
: undefined;
|
|
96
|
+
const tables = base.tables || overrides.tables
|
|
97
|
+
? { ...(base.tables ?? {}), ...(overrides.tables ?? {}) }
|
|
98
|
+
: undefined;
|
|
99
|
+
const queries = base.queries || overrides.queries
|
|
100
|
+
? { ...(base.queries ?? {}), ...(overrides.queries ?? {}) }
|
|
101
|
+
: undefined;
|
|
102
|
+
const mutations = base.mutations || overrides.mutations
|
|
103
|
+
? { ...(base.mutations ?? {}), ...(overrides.mutations ?? {}) }
|
|
104
|
+
: undefined;
|
|
105
|
+
const hooks = base.hooks || overrides.hooks
|
|
106
|
+
? { ...(base.hooks ?? {}), ...(overrides.hooks ?? {}) }
|
|
107
|
+
: undefined;
|
|
108
|
+
const postgraphile = base.postgraphile || overrides.postgraphile
|
|
109
|
+
? { ...(base.postgraphile ?? {}), ...(overrides.postgraphile ?? {}) }
|
|
110
|
+
: undefined;
|
|
111
|
+
const codegen = base.codegen || overrides.codegen
|
|
112
|
+
? { ...(base.codegen ?? {}), ...(overrides.codegen ?? {}) }
|
|
113
|
+
: undefined;
|
|
114
|
+
const orm = base.orm || overrides.orm
|
|
115
|
+
? { ...(base.orm ?? {}), ...(overrides.orm ?? {}) }
|
|
116
|
+
: undefined;
|
|
117
|
+
const reactQuery = base.reactQuery || overrides.reactQuery
|
|
118
|
+
? { ...(base.reactQuery ?? {}), ...(overrides.reactQuery ?? {}) }
|
|
119
|
+
: undefined;
|
|
120
|
+
const queryKeys = base.queryKeys || overrides.queryKeys
|
|
121
|
+
? {
|
|
122
|
+
...(base.queryKeys ?? {}),
|
|
123
|
+
...(overrides.queryKeys ?? {}),
|
|
124
|
+
relationships: {
|
|
125
|
+
...(base.queryKeys?.relationships ?? {}),
|
|
126
|
+
...(overrides.queryKeys?.relationships ?? {}),
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
: undefined;
|
|
130
|
+
const watch = base.watch || overrides.watch
|
|
131
|
+
? { ...(base.watch ?? {}), ...(overrides.watch ?? {}) }
|
|
132
|
+
: undefined;
|
|
133
|
+
return {
|
|
134
|
+
...base,
|
|
135
|
+
...overrides,
|
|
136
|
+
headers,
|
|
137
|
+
tables,
|
|
138
|
+
queries,
|
|
139
|
+
mutations,
|
|
140
|
+
hooks,
|
|
141
|
+
postgraphile,
|
|
142
|
+
codegen,
|
|
143
|
+
orm,
|
|
144
|
+
reactQuery,
|
|
145
|
+
queryKeys,
|
|
146
|
+
watch,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
79
149
|
/**
|
|
80
150
|
* Resolve configuration by applying defaults
|
|
81
151
|
*/
|
|
82
152
|
function resolveConfig(config) {
|
|
153
|
+
if (isMultiConfig(config)) {
|
|
154
|
+
throw new Error('Multi-target config cannot be resolved with resolveConfig(). Use resolveConfigTargets().');
|
|
155
|
+
}
|
|
83
156
|
return {
|
|
84
157
|
endpoint: config.endpoint ?? '',
|
|
85
158
|
schema: config.schema ?? null,
|
|
@@ -121,10 +194,14 @@ function resolveConfig(config) {
|
|
|
121
194
|
},
|
|
122
195
|
queryKeys: {
|
|
123
196
|
style: config.queryKeys?.style ?? exports.DEFAULT_QUERY_KEY_CONFIG.style,
|
|
124
|
-
relationships: config.queryKeys?.relationships ??
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
197
|
+
relationships: config.queryKeys?.relationships ??
|
|
198
|
+
exports.DEFAULT_QUERY_KEY_CONFIG.relationships,
|
|
199
|
+
generateScopedKeys: config.queryKeys?.generateScopedKeys ??
|
|
200
|
+
exports.DEFAULT_QUERY_KEY_CONFIG.generateScopedKeys,
|
|
201
|
+
generateCascadeHelpers: config.queryKeys?.generateCascadeHelpers ??
|
|
202
|
+
exports.DEFAULT_QUERY_KEY_CONFIG.generateCascadeHelpers,
|
|
203
|
+
generateMutationKeys: config.queryKeys?.generateMutationKeys ??
|
|
204
|
+
exports.DEFAULT_QUERY_KEY_CONFIG.generateMutationKeys,
|
|
128
205
|
},
|
|
129
206
|
watch: {
|
|
130
207
|
pollInterval: config.watch?.pollInterval ?? exports.DEFAULT_WATCH_CONFIG.pollInterval,
|
|
@@ -134,3 +211,13 @@ function resolveConfig(config) {
|
|
|
134
211
|
},
|
|
135
212
|
};
|
|
136
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Resolve all targets in a multi-target config
|
|
216
|
+
*/
|
|
217
|
+
function resolveConfigTargets(config) {
|
|
218
|
+
const defaults = config.defaults ?? {};
|
|
219
|
+
return Object.entries(config.targets).map(([name, target]) => ({
|
|
220
|
+
name,
|
|
221
|
+
config: resolveConfig(mergeConfig(defaults, target)),
|
|
222
|
+
}));
|
|
223
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export type { CleanTable, CleanField, CleanFieldType, CleanRelations, CleanBelon
|
|
|
5
5
|
export type { PageInfo, ConnectionResult, QueryOptions, OrderByItem, FilterOperator, FieldFilter, RelationalFilter, Filter, } from './query';
|
|
6
6
|
export type { MutationOptions, CreateInput, UpdateInput, DeleteInput, MutationResult, } from './mutation';
|
|
7
7
|
export type { SimpleFieldSelection, FieldSelectionPreset, FieldSelection, SelectionOptions, } from './selection';
|
|
8
|
-
export type { GraphQLSDKConfig, ResolvedConfig, } from './config';
|
|
9
|
-
export { defineConfig, resolveConfig, DEFAULT_CONFIG } from './config';
|
|
8
|
+
export type { GraphQLSDKConfig, GraphQLSDKConfigTarget, GraphQLSDKMultiConfig, ResolvedConfig, ResolvedTargetConfig, } from './config';
|
|
9
|
+
export { defineConfig, resolveConfig, resolveConfigTargets, DEFAULT_CONFIG, } from './config';
|
package/types/index.js
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* Type exports for @constructive-io/graphql-codegen
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.DEFAULT_CONFIG = exports.resolveConfig = exports.defineConfig = void 0;
|
|
6
|
+
exports.DEFAULT_CONFIG = exports.resolveConfigTargets = exports.resolveConfig = exports.defineConfig = void 0;
|
|
7
7
|
var config_1 = require("./config");
|
|
8
8
|
Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return config_1.defineConfig; } });
|
|
9
9
|
Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return config_1.resolveConfig; } });
|
|
10
|
+
Object.defineProperty(exports, "resolveConfigTargets", { enumerable: true, get: function () { return config_1.resolveConfigTargets; } });
|
|
10
11
|
Object.defineProperty(exports, "DEFAULT_CONFIG", { enumerable: true, get: function () { return config_1.DEFAULT_CONFIG; } });
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime query builder for ORM client
|
|
3
|
-
*
|
|
4
|
-
* This module provides the runtime functionality that builds GraphQL
|
|
5
|
-
* queries/mutations from the fluent API calls and executes them.
|
|
6
|
-
*
|
|
7
|
-
* This file will be copied to the generated output (not generated via AST)
|
|
8
|
-
* since it's runtime code that doesn't change based on schema.
|
|
9
|
-
*/
|
|
10
|
-
import type { QueryResult } from './select-types';
|
|
11
|
-
/**
|
|
12
|
-
* ORM client configuration
|
|
13
|
-
*/
|
|
14
|
-
export interface OrmClientConfig {
|
|
15
|
-
endpoint: string;
|
|
16
|
-
headers?: Record<string, string>;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Internal client state
|
|
20
|
-
*/
|
|
21
|
-
export declare class OrmClient {
|
|
22
|
-
private endpoint;
|
|
23
|
-
private headers;
|
|
24
|
-
constructor(config: OrmClientConfig);
|
|
25
|
-
/**
|
|
26
|
-
* Execute a GraphQL query/mutation
|
|
27
|
-
*/
|
|
28
|
-
execute<T>(document: string, variables?: Record<string, unknown>): Promise<QueryResult<T>>;
|
|
29
|
-
/**
|
|
30
|
-
* Update headers (e.g., for auth token refresh)
|
|
31
|
-
*/
|
|
32
|
-
setHeaders(headers: Record<string, string>): void;
|
|
33
|
-
/**
|
|
34
|
-
* Get current endpoint
|
|
35
|
-
*/
|
|
36
|
-
getEndpoint(): string;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Configuration for building a query
|
|
40
|
-
*/
|
|
41
|
-
export interface QueryBuilderConfig {
|
|
42
|
-
client: OrmClient;
|
|
43
|
-
operation: 'query' | 'mutation';
|
|
44
|
-
operationName: string;
|
|
45
|
-
fieldName: string;
|
|
46
|
-
document: string;
|
|
47
|
-
variables?: Record<string, unknown>;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Query builder that holds the query configuration and executes it
|
|
51
|
-
*
|
|
52
|
-
* Usage:
|
|
53
|
-
* ```typescript
|
|
54
|
-
* const result = await new QueryBuilder(config).execute();
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
export declare class QueryBuilder<TResult> {
|
|
58
|
-
private config;
|
|
59
|
-
constructor(config: QueryBuilderConfig);
|
|
60
|
-
/**
|
|
61
|
-
* Execute the query and return the result
|
|
62
|
-
*/
|
|
63
|
-
execute(): Promise<QueryResult<TResult>>;
|
|
64
|
-
/**
|
|
65
|
-
* Get the GraphQL document (useful for debugging)
|
|
66
|
-
*/
|
|
67
|
-
toGraphQL(): string;
|
|
68
|
-
/**
|
|
69
|
-
* Get the variables (useful for debugging)
|
|
70
|
-
*/
|
|
71
|
-
getVariables(): Record<string, unknown> | undefined;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Build field selections from a select object
|
|
75
|
-
*
|
|
76
|
-
* Converts:
|
|
77
|
-
* { id: true, name: true, posts: { select: { title: true } } }
|
|
78
|
-
*
|
|
79
|
-
* To:
|
|
80
|
-
* id
|
|
81
|
-
* name
|
|
82
|
-
* posts {
|
|
83
|
-
* nodes { title }
|
|
84
|
-
* totalCount
|
|
85
|
-
* pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
|
|
86
|
-
* }
|
|
87
|
-
*/
|
|
88
|
-
export declare function buildSelections(select: Record<string, unknown> | undefined, fieldMeta?: Record<string, FieldMeta>): string;
|
|
89
|
-
/**
|
|
90
|
-
* Field metadata for determining connection vs direct relation
|
|
91
|
-
*/
|
|
92
|
-
export interface FieldMeta {
|
|
93
|
-
isConnection: boolean;
|
|
94
|
-
isNullable: boolean;
|
|
95
|
-
typeName: string;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Build a findMany query document
|
|
99
|
-
*/
|
|
100
|
-
export declare function buildFindManyDocument(operationName: string, queryField: string, select: Record<string, unknown> | undefined, args: {
|
|
101
|
-
where?: Record<string, unknown>;
|
|
102
|
-
orderBy?: string[];
|
|
103
|
-
first?: number;
|
|
104
|
-
last?: number;
|
|
105
|
-
after?: string;
|
|
106
|
-
before?: string;
|
|
107
|
-
offset?: number;
|
|
108
|
-
}, filterTypeName: string, orderByTypeName: string): {
|
|
109
|
-
document: string;
|
|
110
|
-
variables: Record<string, unknown>;
|
|
111
|
-
};
|
|
112
|
-
/**
|
|
113
|
-
* Build a findFirst query document
|
|
114
|
-
*/
|
|
115
|
-
export declare function buildFindFirstDocument(operationName: string, queryField: string, select: Record<string, unknown> | undefined, args: {
|
|
116
|
-
where?: Record<string, unknown>;
|
|
117
|
-
}, filterTypeName: string): {
|
|
118
|
-
document: string;
|
|
119
|
-
variables: Record<string, unknown>;
|
|
120
|
-
};
|
|
121
|
-
/**
|
|
122
|
-
* Build a create mutation document
|
|
123
|
-
*/
|
|
124
|
-
export declare function buildCreateDocument(operationName: string, mutationField: string, entityField: string, select: Record<string, unknown> | undefined, data: Record<string, unknown>, inputTypeName: string): {
|
|
125
|
-
document: string;
|
|
126
|
-
variables: Record<string, unknown>;
|
|
127
|
-
};
|
|
128
|
-
/**
|
|
129
|
-
* Build an update mutation document
|
|
130
|
-
*/
|
|
131
|
-
export declare function buildUpdateDocument(operationName: string, mutationField: string, entityField: string, select: Record<string, unknown> | undefined, where: Record<string, unknown>, data: Record<string, unknown>, inputTypeName: string): {
|
|
132
|
-
document: string;
|
|
133
|
-
variables: Record<string, unknown>;
|
|
134
|
-
};
|
|
135
|
-
/**
|
|
136
|
-
* Build a delete mutation document
|
|
137
|
-
*/
|
|
138
|
-
export declare function buildDeleteDocument(operationName: string, mutationField: string, entityField: string, where: Record<string, unknown>, inputTypeName: string): {
|
|
139
|
-
document: string;
|
|
140
|
-
variables: Record<string, unknown>;
|
|
141
|
-
};
|
|
142
|
-
/**
|
|
143
|
-
* Build a custom query document
|
|
144
|
-
*/
|
|
145
|
-
export declare function buildCustomQueryDocument(operationName: string, queryField: string, select: Record<string, unknown> | undefined, args: Record<string, unknown> | undefined, variableDefinitions: Array<{
|
|
146
|
-
name: string;
|
|
147
|
-
type: string;
|
|
148
|
-
}>): {
|
|
149
|
-
document: string;
|
|
150
|
-
variables: Record<string, unknown>;
|
|
151
|
-
};
|
|
152
|
-
/**
|
|
153
|
-
* Build a custom mutation document
|
|
154
|
-
*/
|
|
155
|
-
export declare function buildCustomMutationDocument(operationName: string, mutationField: string, select: Record<string, unknown> | undefined, args: Record<string, unknown> | undefined, variableDefinitions: Array<{
|
|
156
|
-
name: string;
|
|
157
|
-
type: string;
|
|
158
|
-
}>): {
|
|
159
|
-
document: string;
|
|
160
|
-
variables: Record<string, unknown>;
|
|
161
|
-
};
|
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Runtime query builder for ORM client
|
|
4
|
-
*
|
|
5
|
-
* This module provides the runtime functionality that builds GraphQL
|
|
6
|
-
* queries/mutations from the fluent API calls and executes them.
|
|
7
|
-
*
|
|
8
|
-
* This file will be copied to the generated output (not generated via AST)
|
|
9
|
-
* since it's runtime code that doesn't change based on schema.
|
|
10
|
-
*/
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.QueryBuilder = exports.OrmClient = void 0;
|
|
13
|
-
exports.buildSelections = buildSelections;
|
|
14
|
-
exports.buildFindManyDocument = buildFindManyDocument;
|
|
15
|
-
exports.buildFindFirstDocument = buildFindFirstDocument;
|
|
16
|
-
exports.buildCreateDocument = buildCreateDocument;
|
|
17
|
-
exports.buildUpdateDocument = buildUpdateDocument;
|
|
18
|
-
exports.buildDeleteDocument = buildDeleteDocument;
|
|
19
|
-
exports.buildCustomQueryDocument = buildCustomQueryDocument;
|
|
20
|
-
exports.buildCustomMutationDocument = buildCustomMutationDocument;
|
|
21
|
-
/**
|
|
22
|
-
* Internal client state
|
|
23
|
-
*/
|
|
24
|
-
class OrmClient {
|
|
25
|
-
endpoint;
|
|
26
|
-
headers;
|
|
27
|
-
constructor(config) {
|
|
28
|
-
this.endpoint = config.endpoint;
|
|
29
|
-
this.headers = config.headers ?? {};
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Execute a GraphQL query/mutation
|
|
33
|
-
*/
|
|
34
|
-
async execute(document, variables) {
|
|
35
|
-
const response = await fetch(this.endpoint, {
|
|
36
|
-
method: 'POST',
|
|
37
|
-
headers: {
|
|
38
|
-
'Content-Type': 'application/json',
|
|
39
|
-
Accept: 'application/json',
|
|
40
|
-
...this.headers,
|
|
41
|
-
},
|
|
42
|
-
body: JSON.stringify({
|
|
43
|
-
query: document,
|
|
44
|
-
variables: variables ?? {},
|
|
45
|
-
}),
|
|
46
|
-
});
|
|
47
|
-
if (!response.ok) {
|
|
48
|
-
return {
|
|
49
|
-
data: null,
|
|
50
|
-
errors: [
|
|
51
|
-
{
|
|
52
|
-
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const json = (await response.json());
|
|
58
|
-
return {
|
|
59
|
-
data: json.data ?? null,
|
|
60
|
-
errors: json.errors,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Update headers (e.g., for auth token refresh)
|
|
65
|
-
*/
|
|
66
|
-
setHeaders(headers) {
|
|
67
|
-
this.headers = { ...this.headers, ...headers };
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Get current endpoint
|
|
71
|
-
*/
|
|
72
|
-
getEndpoint() {
|
|
73
|
-
return this.endpoint;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
exports.OrmClient = OrmClient;
|
|
77
|
-
/**
|
|
78
|
-
* Query builder that holds the query configuration and executes it
|
|
79
|
-
*
|
|
80
|
-
* Usage:
|
|
81
|
-
* ```typescript
|
|
82
|
-
* const result = await new QueryBuilder(config).execute();
|
|
83
|
-
* ```
|
|
84
|
-
*/
|
|
85
|
-
class QueryBuilder {
|
|
86
|
-
config;
|
|
87
|
-
constructor(config) {
|
|
88
|
-
this.config = config;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Execute the query and return the result
|
|
92
|
-
*/
|
|
93
|
-
async execute() {
|
|
94
|
-
return this.config.client.execute(this.config.document, this.config.variables);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Get the GraphQL document (useful for debugging)
|
|
98
|
-
*/
|
|
99
|
-
toGraphQL() {
|
|
100
|
-
return this.config.document;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Get the variables (useful for debugging)
|
|
104
|
-
*/
|
|
105
|
-
getVariables() {
|
|
106
|
-
return this.config.variables;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
exports.QueryBuilder = QueryBuilder;
|
|
110
|
-
// ============================================================================
|
|
111
|
-
// GraphQL Document Builders (Runtime)
|
|
112
|
-
// ============================================================================
|
|
113
|
-
/**
|
|
114
|
-
* Build field selections from a select object
|
|
115
|
-
*
|
|
116
|
-
* Converts:
|
|
117
|
-
* { id: true, name: true, posts: { select: { title: true } } }
|
|
118
|
-
*
|
|
119
|
-
* To:
|
|
120
|
-
* id
|
|
121
|
-
* name
|
|
122
|
-
* posts {
|
|
123
|
-
* nodes { title }
|
|
124
|
-
* totalCount
|
|
125
|
-
* pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
|
|
126
|
-
* }
|
|
127
|
-
*/
|
|
128
|
-
function buildSelections(select, fieldMeta) {
|
|
129
|
-
if (!select) {
|
|
130
|
-
return '';
|
|
131
|
-
}
|
|
132
|
-
const fields = [];
|
|
133
|
-
for (const [key, value] of Object.entries(select)) {
|
|
134
|
-
if (value === false || value === undefined) {
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
if (value === true) {
|
|
138
|
-
fields.push(key);
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
// Nested select
|
|
142
|
-
if (typeof value === 'object' && value !== null) {
|
|
143
|
-
const nested = value;
|
|
144
|
-
const meta = fieldMeta?.[key];
|
|
145
|
-
const isConnection = meta?.isConnection ?? true; // Default to connection for relations
|
|
146
|
-
if (nested.select) {
|
|
147
|
-
const nestedSelections = buildSelections(nested.select);
|
|
148
|
-
// Build arguments for the relation field
|
|
149
|
-
const args = [];
|
|
150
|
-
if (nested.first !== undefined) {
|
|
151
|
-
args.push(`first: ${nested.first}`);
|
|
152
|
-
}
|
|
153
|
-
if (nested.filter) {
|
|
154
|
-
args.push(`filter: ${JSON.stringify(nested.filter)}`);
|
|
155
|
-
}
|
|
156
|
-
if (nested.orderBy && nested.orderBy.length > 0) {
|
|
157
|
-
args.push(`orderBy: [${nested.orderBy.join(', ')}]`);
|
|
158
|
-
}
|
|
159
|
-
const argsStr = args.length > 0 ? `(${args.join(', ')})` : '';
|
|
160
|
-
if (isConnection) {
|
|
161
|
-
// Connection type - include nodes, totalCount, pageInfo
|
|
162
|
-
fields.push(`${key}${argsStr} {
|
|
163
|
-
nodes { ${nestedSelections} }
|
|
164
|
-
totalCount
|
|
165
|
-
pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
|
|
166
|
-
}`);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
// Direct relation (not a connection)
|
|
170
|
-
fields.push(`${key}${argsStr} { ${nestedSelections} }`);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return fields.join('\n ');
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Build a findMany query document
|
|
179
|
-
*/
|
|
180
|
-
function buildFindManyDocument(operationName, queryField, select, args, filterTypeName, orderByTypeName) {
|
|
181
|
-
const selections = select ? buildSelections(select) : 'id';
|
|
182
|
-
// Build variable definitions and query arguments
|
|
183
|
-
const varDefs = [];
|
|
184
|
-
const queryArgs = [];
|
|
185
|
-
const variables = {};
|
|
186
|
-
if (args.where) {
|
|
187
|
-
varDefs.push(`$where: ${filterTypeName}`);
|
|
188
|
-
queryArgs.push('filter: $where');
|
|
189
|
-
variables.where = args.where;
|
|
190
|
-
}
|
|
191
|
-
if (args.orderBy && args.orderBy.length > 0) {
|
|
192
|
-
varDefs.push(`$orderBy: [${orderByTypeName}!]`);
|
|
193
|
-
queryArgs.push('orderBy: $orderBy');
|
|
194
|
-
variables.orderBy = args.orderBy;
|
|
195
|
-
}
|
|
196
|
-
if (args.first !== undefined) {
|
|
197
|
-
varDefs.push('$first: Int');
|
|
198
|
-
queryArgs.push('first: $first');
|
|
199
|
-
variables.first = args.first;
|
|
200
|
-
}
|
|
201
|
-
if (args.last !== undefined) {
|
|
202
|
-
varDefs.push('$last: Int');
|
|
203
|
-
queryArgs.push('last: $last');
|
|
204
|
-
variables.last = args.last;
|
|
205
|
-
}
|
|
206
|
-
if (args.after) {
|
|
207
|
-
varDefs.push('$after: Cursor');
|
|
208
|
-
queryArgs.push('after: $after');
|
|
209
|
-
variables.after = args.after;
|
|
210
|
-
}
|
|
211
|
-
if (args.before) {
|
|
212
|
-
varDefs.push('$before: Cursor');
|
|
213
|
-
queryArgs.push('before: $before');
|
|
214
|
-
variables.before = args.before;
|
|
215
|
-
}
|
|
216
|
-
if (args.offset !== undefined) {
|
|
217
|
-
varDefs.push('$offset: Int');
|
|
218
|
-
queryArgs.push('offset: $offset');
|
|
219
|
-
variables.offset = args.offset;
|
|
220
|
-
}
|
|
221
|
-
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
222
|
-
const queryArgsStr = queryArgs.length > 0 ? `(${queryArgs.join(', ')})` : '';
|
|
223
|
-
const document = `query ${operationName}Query${varDefsStr} {
|
|
224
|
-
${queryField}${queryArgsStr} {
|
|
225
|
-
nodes {
|
|
226
|
-
${selections}
|
|
227
|
-
}
|
|
228
|
-
totalCount
|
|
229
|
-
pageInfo {
|
|
230
|
-
hasNextPage
|
|
231
|
-
hasPreviousPage
|
|
232
|
-
startCursor
|
|
233
|
-
endCursor
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}`;
|
|
237
|
-
return { document, variables };
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Build a findFirst query document
|
|
241
|
-
*/
|
|
242
|
-
function buildFindFirstDocument(operationName, queryField, select, args, filterTypeName) {
|
|
243
|
-
const selections = select ? buildSelections(select) : 'id';
|
|
244
|
-
const varDefs = [];
|
|
245
|
-
const queryArgs = [];
|
|
246
|
-
const variables = {};
|
|
247
|
-
if (args.where) {
|
|
248
|
-
varDefs.push(`$where: ${filterTypeName}`);
|
|
249
|
-
queryArgs.push('filter: $where');
|
|
250
|
-
variables.where = args.where;
|
|
251
|
-
}
|
|
252
|
-
// findFirst uses the list query with first: 1
|
|
253
|
-
varDefs.push('$first: Int');
|
|
254
|
-
queryArgs.push('first: $first');
|
|
255
|
-
variables.first = 1;
|
|
256
|
-
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
257
|
-
const queryArgsStr = queryArgs.length > 0 ? `(${queryArgs.join(', ')})` : '';
|
|
258
|
-
const document = `query ${operationName}Query${varDefsStr} {
|
|
259
|
-
${queryField}${queryArgsStr} {
|
|
260
|
-
nodes {
|
|
261
|
-
${selections}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
}`;
|
|
265
|
-
return { document, variables };
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Build a create mutation document
|
|
269
|
-
*/
|
|
270
|
-
function buildCreateDocument(operationName, mutationField, entityField, select, data, inputTypeName) {
|
|
271
|
-
const selections = select ? buildSelections(select) : 'id';
|
|
272
|
-
const document = `mutation ${operationName}Mutation($input: ${inputTypeName}!) {
|
|
273
|
-
${mutationField}(input: $input) {
|
|
274
|
-
${entityField} {
|
|
275
|
-
${selections}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}`;
|
|
279
|
-
return {
|
|
280
|
-
document,
|
|
281
|
-
variables: {
|
|
282
|
-
input: {
|
|
283
|
-
[entityField]: data,
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Build an update mutation document
|
|
290
|
-
*/
|
|
291
|
-
function buildUpdateDocument(operationName, mutationField, entityField, select, where, data, inputTypeName) {
|
|
292
|
-
const selections = select ? buildSelections(select) : 'id';
|
|
293
|
-
// PostGraphile update uses nodeId or primary key in input
|
|
294
|
-
const document = `mutation ${operationName}Mutation($input: ${inputTypeName}!) {
|
|
295
|
-
${mutationField}(input: $input) {
|
|
296
|
-
${entityField} {
|
|
297
|
-
${selections}
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}`;
|
|
301
|
-
return {
|
|
302
|
-
document,
|
|
303
|
-
variables: {
|
|
304
|
-
input: {
|
|
305
|
-
id: where.id, // Assumes id-based where clause
|
|
306
|
-
patch: data,
|
|
307
|
-
},
|
|
308
|
-
},
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Build a delete mutation document
|
|
313
|
-
*/
|
|
314
|
-
function buildDeleteDocument(operationName, mutationField, entityField, where, inputTypeName) {
|
|
315
|
-
const document = `mutation ${operationName}Mutation($input: ${inputTypeName}!) {
|
|
316
|
-
${mutationField}(input: $input) {
|
|
317
|
-
${entityField} {
|
|
318
|
-
id
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}`;
|
|
322
|
-
return {
|
|
323
|
-
document,
|
|
324
|
-
variables: {
|
|
325
|
-
input: {
|
|
326
|
-
id: where.id,
|
|
327
|
-
},
|
|
328
|
-
},
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* Build a custom query document
|
|
333
|
-
*/
|
|
334
|
-
function buildCustomQueryDocument(operationName, queryField, select, args, variableDefinitions) {
|
|
335
|
-
const selections = select ? buildSelections(select) : '';
|
|
336
|
-
const varDefs = variableDefinitions.map((v) => `$${v.name}: ${v.type}`);
|
|
337
|
-
const queryArgs = variableDefinitions.map((v) => `${v.name}: $${v.name}`);
|
|
338
|
-
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
339
|
-
const queryArgsStr = queryArgs.length > 0 ? `(${queryArgs.join(', ')})` : '';
|
|
340
|
-
const selectionsBlock = selections ? ` {\n ${selections}\n }` : '';
|
|
341
|
-
const document = `query ${operationName}Query${varDefsStr} {
|
|
342
|
-
${queryField}${queryArgsStr}${selectionsBlock}
|
|
343
|
-
}`;
|
|
344
|
-
return {
|
|
345
|
-
document,
|
|
346
|
-
variables: args ?? {},
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
|
-
* Build a custom mutation document
|
|
351
|
-
*/
|
|
352
|
-
function buildCustomMutationDocument(operationName, mutationField, select, args, variableDefinitions) {
|
|
353
|
-
const selections = select ? buildSelections(select) : '';
|
|
354
|
-
const varDefs = variableDefinitions.map((v) => `$${v.name}: ${v.type}`);
|
|
355
|
-
const mutationArgs = variableDefinitions.map((v) => `${v.name}: $${v.name}`);
|
|
356
|
-
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
357
|
-
const mutationArgsStr = mutationArgs.length > 0 ? `(${mutationArgs.join(', ')})` : '';
|
|
358
|
-
const selectionsBlock = selections ? ` {\n ${selections}\n }` : '';
|
|
359
|
-
const document = `mutation ${operationName}Mutation${varDefsStr} {
|
|
360
|
-
${mutationField}${mutationArgsStr}${selectionsBlock}
|
|
361
|
-
}`;
|
|
362
|
-
return {
|
|
363
|
-
document,
|
|
364
|
-
variables: args ?? {},
|
|
365
|
-
};
|
|
366
|
-
}
|