@constructive-io/graphql-codegen 2.18.0 → 2.20.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 +1818 -113
- package/__tests__/codegen/input-types-generator.test.d.ts +1 -0
- package/__tests__/codegen/input-types-generator.test.js +635 -0
- package/cli/codegen/barrel.d.ts +27 -0
- package/cli/codegen/barrel.js +163 -0
- package/cli/codegen/client.d.ts +4 -0
- package/cli/codegen/client.js +170 -0
- package/cli/codegen/custom-mutations.d.ts +38 -0
- package/cli/codegen/custom-mutations.js +149 -0
- package/cli/codegen/custom-queries.d.ts +38 -0
- package/cli/codegen/custom-queries.js +358 -0
- package/cli/codegen/filters.d.ts +27 -0
- package/cli/codegen/filters.js +357 -0
- package/cli/codegen/gql-ast.d.ts +41 -0
- package/cli/codegen/gql-ast.js +329 -0
- package/cli/codegen/index.d.ts +71 -0
- package/cli/codegen/index.js +147 -0
- package/cli/codegen/mutations.d.ts +30 -0
- package/cli/codegen/mutations.js +410 -0
- package/cli/codegen/orm/barrel.d.ts +18 -0
- package/cli/codegen/orm/barrel.js +48 -0
- package/cli/codegen/orm/client-generator.d.ts +45 -0
- package/cli/codegen/orm/client-generator.js +646 -0
- package/cli/codegen/orm/custom-ops-generator.d.ts +30 -0
- package/cli/codegen/orm/custom-ops-generator.js +350 -0
- package/cli/codegen/orm/index.d.ts +38 -0
- package/cli/codegen/orm/index.js +88 -0
- package/cli/codegen/orm/input-types-generator.d.ts +21 -0
- package/cli/codegen/orm/input-types-generator.js +705 -0
- package/cli/codegen/orm/input-types-generator.test.d.ts +1 -0
- package/cli/codegen/orm/input-types-generator.test.js +75 -0
- package/cli/codegen/orm/model-generator.d.ts +32 -0
- package/cli/codegen/orm/model-generator.js +264 -0
- package/cli/codegen/orm/query-builder.d.ts +161 -0
- package/cli/codegen/orm/query-builder.js +366 -0
- package/cli/codegen/orm/select-types.d.ts +169 -0
- package/cli/codegen/orm/select-types.js +16 -0
- package/cli/codegen/orm/select-types.test.d.ts +11 -0
- package/cli/codegen/orm/select-types.test.js +22 -0
- package/cli/codegen/queries.d.ts +25 -0
- package/cli/codegen/queries.js +438 -0
- package/cli/codegen/scalars.d.ts +12 -0
- package/cli/codegen/scalars.js +71 -0
- package/cli/codegen/schema-gql-ast.d.ts +51 -0
- package/cli/codegen/schema-gql-ast.js +385 -0
- package/cli/codegen/ts-ast.d.ts +122 -0
- package/cli/codegen/ts-ast.js +280 -0
- package/cli/codegen/type-resolver.d.ts +96 -0
- package/cli/codegen/type-resolver.js +246 -0
- package/cli/codegen/types.d.ts +12 -0
- package/cli/codegen/types.js +69 -0
- package/cli/codegen/utils.d.ts +163 -0
- package/cli/codegen/utils.js +326 -0
- package/cli/commands/generate-orm.d.ts +37 -0
- package/cli/commands/generate-orm.js +195 -0
- package/cli/commands/generate.d.ts +39 -0
- package/cli/commands/generate.js +299 -0
- package/cli/commands/index.d.ts +7 -0
- package/cli/commands/index.js +12 -0
- package/cli/commands/init.d.ts +35 -0
- package/cli/commands/init.js +176 -0
- package/cli/index.d.ts +4 -0
- package/cli/index.js +291 -0
- package/cli/introspect/fetch-meta.d.ts +31 -0
- package/cli/introspect/fetch-meta.js +108 -0
- package/cli/introspect/fetch-schema.d.ts +21 -0
- package/cli/introspect/fetch-schema.js +86 -0
- package/cli/introspect/index.d.ts +8 -0
- package/cli/introspect/index.js +16 -0
- package/cli/introspect/meta-query.d.ts +111 -0
- package/cli/introspect/meta-query.js +191 -0
- package/cli/introspect/schema-query.d.ts +20 -0
- package/cli/introspect/schema-query.js +123 -0
- package/cli/introspect/transform-schema.d.ts +74 -0
- package/cli/introspect/transform-schema.js +269 -0
- package/cli/introspect/transform-schema.test.d.ts +1 -0
- package/cli/introspect/transform-schema.test.js +67 -0
- package/cli/introspect/transform.d.ts +21 -0
- package/cli/introspect/transform.js +216 -0
- package/cli/watch/cache.d.ts +45 -0
- package/cli/watch/cache.js +111 -0
- package/cli/watch/debounce.d.ts +19 -0
- package/cli/watch/debounce.js +89 -0
- package/cli/watch/hash.d.ts +17 -0
- package/cli/watch/hash.js +48 -0
- package/cli/watch/index.d.ts +10 -0
- package/cli/watch/index.js +22 -0
- package/cli/watch/orchestrator.d.ts +63 -0
- package/cli/watch/orchestrator.js +228 -0
- package/cli/watch/poller.d.ts +65 -0
- package/cli/watch/poller.js +203 -0
- package/cli/watch/types.d.ts +67 -0
- package/cli/watch/types.js +5 -0
- package/client/error.d.ts +95 -0
- package/client/error.js +255 -0
- package/client/execute.d.ts +57 -0
- package/client/execute.js +124 -0
- package/client/index.d.ts +6 -0
- package/client/index.js +18 -0
- package/client/typed-document.d.ts +31 -0
- package/client/typed-document.js +44 -0
- package/core/ast.d.ts +10 -0
- package/core/ast.js +593 -0
- package/core/custom-ast.d.ts +35 -0
- package/core/custom-ast.js +204 -0
- package/core/index.d.ts +8 -0
- package/core/index.js +33 -0
- package/core/meta-object/convert.d.ts +65 -0
- package/core/meta-object/convert.js +63 -0
- package/core/meta-object/format.json +93 -0
- package/core/meta-object/index.d.ts +2 -0
- package/core/meta-object/index.js +18 -0
- package/core/meta-object/validate.d.ts +9 -0
- package/core/meta-object/validate.js +34 -0
- package/core/query-builder.d.ts +46 -0
- package/core/query-builder.js +412 -0
- package/core/types.d.ts +139 -0
- package/core/types.js +28 -0
- package/esm/__tests__/codegen/input-types-generator.test.d.ts +1 -0
- package/esm/__tests__/codegen/input-types-generator.test.js +633 -0
- package/esm/cli/codegen/barrel.d.ts +27 -0
- package/esm/cli/codegen/barrel.js +156 -0
- package/esm/cli/codegen/client.d.ts +4 -0
- package/esm/cli/codegen/client.js +167 -0
- package/esm/cli/codegen/custom-mutations.d.ts +38 -0
- package/esm/cli/codegen/custom-mutations.js +145 -0
- package/esm/cli/codegen/custom-queries.d.ts +38 -0
- package/esm/cli/codegen/custom-queries.js +354 -0
- package/esm/cli/codegen/filters.d.ts +27 -0
- package/esm/cli/codegen/filters.js +351 -0
- package/esm/cli/codegen/gql-ast.d.ts +41 -0
- package/esm/cli/codegen/gql-ast.js +288 -0
- package/esm/cli/codegen/index.d.ts +71 -0
- package/esm/cli/codegen/index.js +124 -0
- package/esm/cli/codegen/mutations.d.ts +30 -0
- package/esm/cli/codegen/mutations.js +404 -0
- package/esm/cli/codegen/orm/barrel.d.ts +18 -0
- package/esm/cli/codegen/orm/barrel.js +44 -0
- package/esm/cli/codegen/orm/client-generator.d.ts +45 -0
- package/esm/cli/codegen/orm/client-generator.js +640 -0
- package/esm/cli/codegen/orm/custom-ops-generator.d.ts +30 -0
- package/esm/cli/codegen/orm/custom-ops-generator.js +346 -0
- package/esm/cli/codegen/orm/index.d.ts +38 -0
- package/esm/cli/codegen/orm/index.js +75 -0
- package/esm/cli/codegen/orm/input-types-generator.d.ts +21 -0
- package/esm/cli/codegen/orm/input-types-generator.js +700 -0
- package/esm/cli/codegen/orm/input-types-generator.test.d.ts +1 -0
- package/esm/cli/codegen/orm/input-types-generator.test.js +73 -0
- package/esm/cli/codegen/orm/model-generator.d.ts +32 -0
- package/esm/cli/codegen/orm/model-generator.js +260 -0
- package/esm/cli/codegen/orm/query-builder.d.ts +161 -0
- package/esm/cli/codegen/orm/query-builder.js +353 -0
- package/esm/cli/codegen/orm/select-types.d.ts +169 -0
- package/esm/cli/codegen/orm/select-types.js +15 -0
- package/esm/cli/codegen/orm/select-types.test.d.ts +11 -0
- package/esm/cli/codegen/orm/select-types.test.js +21 -0
- package/esm/cli/codegen/queries.d.ts +25 -0
- package/esm/cli/codegen/queries.js +433 -0
- package/esm/cli/codegen/scalars.d.ts +12 -0
- package/esm/cli/codegen/scalars.js +66 -0
- package/esm/cli/codegen/schema-gql-ast.d.ts +51 -0
- package/esm/cli/codegen/schema-gql-ast.js +343 -0
- package/esm/cli/codegen/ts-ast.d.ts +122 -0
- package/esm/cli/codegen/ts-ast.js +260 -0
- package/esm/cli/codegen/type-resolver.d.ts +96 -0
- package/esm/cli/codegen/type-resolver.js +224 -0
- package/esm/cli/codegen/types.d.ts +12 -0
- package/esm/cli/codegen/types.js +65 -0
- package/esm/cli/codegen/utils.d.ts +163 -0
- package/esm/cli/codegen/utils.js +288 -0
- package/esm/cli/commands/generate-orm.d.ts +37 -0
- package/esm/cli/commands/generate-orm.js +192 -0
- package/esm/cli/commands/generate.d.ts +39 -0
- package/esm/cli/commands/generate.js +262 -0
- package/esm/cli/commands/index.d.ts +7 -0
- package/esm/cli/commands/index.js +5 -0
- package/esm/cli/commands/init.d.ts +35 -0
- package/esm/cli/commands/init.js +138 -0
- package/esm/cli/index.d.ts +4 -0
- package/esm/cli/index.js +256 -0
- package/esm/cli/introspect/fetch-meta.d.ts +31 -0
- package/esm/cli/introspect/fetch-meta.js +104 -0
- package/esm/cli/introspect/fetch-schema.d.ts +21 -0
- package/esm/cli/introspect/fetch-schema.js +83 -0
- package/esm/cli/introspect/index.d.ts +8 -0
- package/esm/cli/introspect/index.js +6 -0
- package/esm/cli/introspect/meta-query.d.ts +111 -0
- package/esm/cli/introspect/meta-query.js +188 -0
- package/esm/cli/introspect/schema-query.d.ts +20 -0
- package/esm/cli/introspect/schema-query.js +120 -0
- package/esm/cli/introspect/transform-schema.d.ts +74 -0
- package/esm/cli/introspect/transform-schema.js +259 -0
- package/esm/cli/introspect/transform-schema.test.d.ts +1 -0
- package/esm/cli/introspect/transform-schema.test.js +65 -0
- package/esm/cli/introspect/transform.d.ts +21 -0
- package/esm/cli/introspect/transform.js +210 -0
- package/esm/cli/watch/cache.d.ts +45 -0
- package/esm/cli/watch/cache.js +73 -0
- package/esm/cli/watch/debounce.d.ts +19 -0
- package/esm/cli/watch/debounce.js +85 -0
- package/esm/cli/watch/hash.d.ts +17 -0
- package/esm/cli/watch/hash.js +43 -0
- package/esm/cli/watch/index.d.ts +10 -0
- package/esm/cli/watch/index.js +8 -0
- package/esm/cli/watch/orchestrator.d.ts +63 -0
- package/esm/cli/watch/orchestrator.js +223 -0
- package/esm/cli/watch/poller.d.ts +65 -0
- package/esm/cli/watch/poller.js +198 -0
- package/esm/cli/watch/types.d.ts +67 -0
- package/esm/cli/watch/types.js +4 -0
- package/esm/client/error.d.ts +95 -0
- package/esm/client/error.js +249 -0
- package/esm/client/execute.d.ts +57 -0
- package/esm/client/execute.js +120 -0
- package/esm/client/index.d.ts +6 -0
- package/esm/client/index.js +6 -0
- package/esm/client/typed-document.d.ts +31 -0
- package/esm/client/typed-document.js +40 -0
- package/esm/core/ast.d.ts +10 -0
- package/esm/core/ast.js +549 -0
- package/esm/core/custom-ast.d.ts +35 -0
- package/esm/core/custom-ast.js +161 -0
- package/esm/core/index.d.ts +8 -0
- package/esm/core/index.js +12 -0
- package/esm/core/meta-object/convert.d.ts +65 -0
- package/esm/core/meta-object/convert.js +60 -0
- package/esm/core/meta-object/format.json +93 -0
- package/esm/core/meta-object/index.d.ts +2 -0
- package/esm/core/meta-object/index.js +2 -0
- package/esm/core/meta-object/validate.d.ts +9 -0
- package/esm/core/meta-object/validate.js +28 -0
- package/esm/core/query-builder.d.ts +46 -0
- package/esm/core/query-builder.js +375 -0
- package/esm/core/types.d.ts +139 -0
- package/esm/core/types.js +24 -0
- package/esm/generators/field-selector.d.ts +30 -0
- package/esm/generators/field-selector.js +355 -0
- package/esm/generators/index.d.ts +6 -0
- package/esm/generators/index.js +9 -0
- package/esm/generators/mutations.d.ts +31 -0
- package/esm/generators/mutations.js +197 -0
- package/esm/generators/select.d.ts +50 -0
- package/esm/generators/select.js +636 -0
- package/esm/index.d.ts +12 -0
- package/esm/index.js +17 -3
- package/esm/react/index.d.ts +5 -0
- package/esm/react/index.js +6 -0
- package/esm/types/config.d.ts +199 -0
- package/esm/types/config.js +106 -0
- package/esm/types/index.d.ts +9 -0
- package/esm/types/index.js +4 -0
- package/esm/types/introspection.d.ts +121 -0
- package/esm/types/introspection.js +54 -0
- package/esm/types/mutation.d.ts +45 -0
- package/esm/types/mutation.js +4 -0
- package/esm/types/query.d.ts +82 -0
- package/esm/types/query.js +4 -0
- package/esm/types/schema.d.ts +253 -0
- package/esm/types/schema.js +5 -0
- package/esm/types/selection.d.ts +43 -0
- package/esm/types/selection.js +4 -0
- package/esm/utils/index.d.ts +4 -0
- package/esm/utils/index.js +4 -0
- package/generators/field-selector.d.ts +30 -0
- package/generators/field-selector.js +361 -0
- package/generators/index.d.ts +6 -0
- package/generators/index.js +27 -0
- package/generators/mutations.d.ts +31 -0
- package/generators/mutations.js +235 -0
- package/generators/select.d.ts +50 -0
- package/generators/select.js +679 -0
- package/index.d.ts +12 -3
- package/index.js +19 -3
- package/package.json +59 -38
- package/react/index.d.ts +5 -0
- package/react/index.js +9 -0
- package/types/config.d.ts +199 -0
- package/types/config.js +111 -0
- package/types/index.d.ts +9 -0
- package/types/index.js +10 -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 +82 -0
- package/types/query.js +5 -0
- package/types/schema.d.ts +253 -0
- package/types/schema.js +6 -0
- package/types/selection.d.ts +43 -0
- package/types/selection.js +5 -0
- package/utils/index.d.ts +4 -0
- package/utils/index.js +7 -0
- package/codegen.d.ts +0 -13
- package/codegen.js +0 -293
- package/esm/codegen.js +0 -253
- package/esm/gql.js +0 -939
- package/esm/options.js +0 -27
- package/gql.d.ts +0 -188
- package/gql.js +0 -992
- package/options.d.ts +0 -45
- package/options.js +0 -31
|
@@ -0,0 +1,353 @@
|
|
|
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
|
+
/**
|
|
11
|
+
* Internal client state
|
|
12
|
+
*/
|
|
13
|
+
export class OrmClient {
|
|
14
|
+
endpoint;
|
|
15
|
+
headers;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.endpoint = config.endpoint;
|
|
18
|
+
this.headers = config.headers ?? {};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Execute a GraphQL query/mutation
|
|
22
|
+
*/
|
|
23
|
+
async execute(document, variables) {
|
|
24
|
+
const response = await fetch(this.endpoint, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'application/json',
|
|
28
|
+
Accept: 'application/json',
|
|
29
|
+
...this.headers,
|
|
30
|
+
},
|
|
31
|
+
body: JSON.stringify({
|
|
32
|
+
query: document,
|
|
33
|
+
variables: variables ?? {},
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
return {
|
|
38
|
+
data: null,
|
|
39
|
+
errors: [
|
|
40
|
+
{
|
|
41
|
+
message: `HTTP ${response.status}: ${response.statusText}`,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const json = (await response.json());
|
|
47
|
+
return {
|
|
48
|
+
data: json.data ?? null,
|
|
49
|
+
errors: json.errors,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Update headers (e.g., for auth token refresh)
|
|
54
|
+
*/
|
|
55
|
+
setHeaders(headers) {
|
|
56
|
+
this.headers = { ...this.headers, ...headers };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get current endpoint
|
|
60
|
+
*/
|
|
61
|
+
getEndpoint() {
|
|
62
|
+
return this.endpoint;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Query builder that holds the query configuration and executes it
|
|
67
|
+
*
|
|
68
|
+
* Usage:
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const result = await new QueryBuilder(config).execute();
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export class QueryBuilder {
|
|
74
|
+
config;
|
|
75
|
+
constructor(config) {
|
|
76
|
+
this.config = config;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Execute the query and return the result
|
|
80
|
+
*/
|
|
81
|
+
async execute() {
|
|
82
|
+
return this.config.client.execute(this.config.document, this.config.variables);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the GraphQL document (useful for debugging)
|
|
86
|
+
*/
|
|
87
|
+
toGraphQL() {
|
|
88
|
+
return this.config.document;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the variables (useful for debugging)
|
|
92
|
+
*/
|
|
93
|
+
getVariables() {
|
|
94
|
+
return this.config.variables;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ============================================================================
|
|
98
|
+
// GraphQL Document Builders (Runtime)
|
|
99
|
+
// ============================================================================
|
|
100
|
+
/**
|
|
101
|
+
* Build field selections from a select object
|
|
102
|
+
*
|
|
103
|
+
* Converts:
|
|
104
|
+
* { id: true, name: true, posts: { select: { title: true } } }
|
|
105
|
+
*
|
|
106
|
+
* To:
|
|
107
|
+
* id
|
|
108
|
+
* name
|
|
109
|
+
* posts {
|
|
110
|
+
* nodes { title }
|
|
111
|
+
* totalCount
|
|
112
|
+
* pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
|
|
113
|
+
* }
|
|
114
|
+
*/
|
|
115
|
+
export function buildSelections(select, fieldMeta) {
|
|
116
|
+
if (!select) {
|
|
117
|
+
return '';
|
|
118
|
+
}
|
|
119
|
+
const fields = [];
|
|
120
|
+
for (const [key, value] of Object.entries(select)) {
|
|
121
|
+
if (value === false || value === undefined) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (value === true) {
|
|
125
|
+
fields.push(key);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// Nested select
|
|
129
|
+
if (typeof value === 'object' && value !== null) {
|
|
130
|
+
const nested = value;
|
|
131
|
+
const meta = fieldMeta?.[key];
|
|
132
|
+
const isConnection = meta?.isConnection ?? true; // Default to connection for relations
|
|
133
|
+
if (nested.select) {
|
|
134
|
+
const nestedSelections = buildSelections(nested.select);
|
|
135
|
+
// Build arguments for the relation field
|
|
136
|
+
const args = [];
|
|
137
|
+
if (nested.first !== undefined) {
|
|
138
|
+
args.push(`first: ${nested.first}`);
|
|
139
|
+
}
|
|
140
|
+
if (nested.filter) {
|
|
141
|
+
args.push(`filter: ${JSON.stringify(nested.filter)}`);
|
|
142
|
+
}
|
|
143
|
+
if (nested.orderBy && nested.orderBy.length > 0) {
|
|
144
|
+
args.push(`orderBy: [${nested.orderBy.join(', ')}]`);
|
|
145
|
+
}
|
|
146
|
+
const argsStr = args.length > 0 ? `(${args.join(', ')})` : '';
|
|
147
|
+
if (isConnection) {
|
|
148
|
+
// Connection type - include nodes, totalCount, pageInfo
|
|
149
|
+
fields.push(`${key}${argsStr} {
|
|
150
|
+
nodes { ${nestedSelections} }
|
|
151
|
+
totalCount
|
|
152
|
+
pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
|
|
153
|
+
}`);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
// Direct relation (not a connection)
|
|
157
|
+
fields.push(`${key}${argsStr} { ${nestedSelections} }`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return fields.join('\n ');
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Build a findMany query document
|
|
166
|
+
*/
|
|
167
|
+
export function buildFindManyDocument(operationName, queryField, select, args, filterTypeName) {
|
|
168
|
+
const selections = select ? buildSelections(select) : 'id';
|
|
169
|
+
// Build variable definitions and query arguments
|
|
170
|
+
const varDefs = [];
|
|
171
|
+
const queryArgs = [];
|
|
172
|
+
const variables = {};
|
|
173
|
+
if (args.where) {
|
|
174
|
+
varDefs.push(`$where: ${filterTypeName}`);
|
|
175
|
+
queryArgs.push('filter: $where');
|
|
176
|
+
variables.where = args.where;
|
|
177
|
+
}
|
|
178
|
+
if (args.orderBy && args.orderBy.length > 0) {
|
|
179
|
+
varDefs.push(`$orderBy: [${operationName}OrderBy!]`);
|
|
180
|
+
queryArgs.push('orderBy: $orderBy');
|
|
181
|
+
variables.orderBy = args.orderBy;
|
|
182
|
+
}
|
|
183
|
+
if (args.first !== undefined) {
|
|
184
|
+
varDefs.push('$first: Int');
|
|
185
|
+
queryArgs.push('first: $first');
|
|
186
|
+
variables.first = args.first;
|
|
187
|
+
}
|
|
188
|
+
if (args.last !== undefined) {
|
|
189
|
+
varDefs.push('$last: Int');
|
|
190
|
+
queryArgs.push('last: $last');
|
|
191
|
+
variables.last = args.last;
|
|
192
|
+
}
|
|
193
|
+
if (args.after) {
|
|
194
|
+
varDefs.push('$after: Cursor');
|
|
195
|
+
queryArgs.push('after: $after');
|
|
196
|
+
variables.after = args.after;
|
|
197
|
+
}
|
|
198
|
+
if (args.before) {
|
|
199
|
+
varDefs.push('$before: Cursor');
|
|
200
|
+
queryArgs.push('before: $before');
|
|
201
|
+
variables.before = args.before;
|
|
202
|
+
}
|
|
203
|
+
if (args.offset !== undefined) {
|
|
204
|
+
varDefs.push('$offset: Int');
|
|
205
|
+
queryArgs.push('offset: $offset');
|
|
206
|
+
variables.offset = args.offset;
|
|
207
|
+
}
|
|
208
|
+
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
209
|
+
const queryArgsStr = queryArgs.length > 0 ? `(${queryArgs.join(', ')})` : '';
|
|
210
|
+
const document = `query ${operationName}Query${varDefsStr} {
|
|
211
|
+
${queryField}${queryArgsStr} {
|
|
212
|
+
nodes {
|
|
213
|
+
${selections}
|
|
214
|
+
}
|
|
215
|
+
totalCount
|
|
216
|
+
pageInfo {
|
|
217
|
+
hasNextPage
|
|
218
|
+
hasPreviousPage
|
|
219
|
+
startCursor
|
|
220
|
+
endCursor
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}`;
|
|
224
|
+
return { document, variables };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Build a findFirst query document
|
|
228
|
+
*/
|
|
229
|
+
export function buildFindFirstDocument(operationName, queryField, select, args, filterTypeName) {
|
|
230
|
+
const selections = select ? buildSelections(select) : 'id';
|
|
231
|
+
const varDefs = [];
|
|
232
|
+
const queryArgs = [];
|
|
233
|
+
const variables = {};
|
|
234
|
+
if (args.where) {
|
|
235
|
+
varDefs.push(`$where: ${filterTypeName}`);
|
|
236
|
+
queryArgs.push('filter: $where');
|
|
237
|
+
variables.where = args.where;
|
|
238
|
+
}
|
|
239
|
+
// findFirst uses the list query with first: 1
|
|
240
|
+
varDefs.push('$first: Int');
|
|
241
|
+
queryArgs.push('first: $first');
|
|
242
|
+
variables.first = 1;
|
|
243
|
+
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
244
|
+
const queryArgsStr = queryArgs.length > 0 ? `(${queryArgs.join(', ')})` : '';
|
|
245
|
+
const document = `query ${operationName}Query${varDefsStr} {
|
|
246
|
+
${queryField}${queryArgsStr} {
|
|
247
|
+
nodes {
|
|
248
|
+
${selections}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}`;
|
|
252
|
+
return { document, variables };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Build a create mutation document
|
|
256
|
+
*/
|
|
257
|
+
export function buildCreateDocument(operationName, mutationField, entityField, select, data, inputTypeName) {
|
|
258
|
+
const selections = select ? buildSelections(select) : 'id';
|
|
259
|
+
const document = `mutation ${operationName}Mutation($input: ${inputTypeName}!) {
|
|
260
|
+
${mutationField}(input: $input) {
|
|
261
|
+
${entityField} {
|
|
262
|
+
${selections}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}`;
|
|
266
|
+
return {
|
|
267
|
+
document,
|
|
268
|
+
variables: {
|
|
269
|
+
input: {
|
|
270
|
+
[entityField]: data,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Build an update mutation document
|
|
277
|
+
*/
|
|
278
|
+
export function buildUpdateDocument(operationName, mutationField, entityField, select, where, data, inputTypeName) {
|
|
279
|
+
const selections = select ? buildSelections(select) : 'id';
|
|
280
|
+
// PostGraphile update uses nodeId or primary key in input
|
|
281
|
+
const document = `mutation ${operationName}Mutation($input: ${inputTypeName}!) {
|
|
282
|
+
${mutationField}(input: $input) {
|
|
283
|
+
${entityField} {
|
|
284
|
+
${selections}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}`;
|
|
288
|
+
return {
|
|
289
|
+
document,
|
|
290
|
+
variables: {
|
|
291
|
+
input: {
|
|
292
|
+
id: where.id, // Assumes id-based where clause
|
|
293
|
+
patch: data,
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Build a delete mutation document
|
|
300
|
+
*/
|
|
301
|
+
export function buildDeleteDocument(operationName, mutationField, entityField, where, inputTypeName) {
|
|
302
|
+
const document = `mutation ${operationName}Mutation($input: ${inputTypeName}!) {
|
|
303
|
+
${mutationField}(input: $input) {
|
|
304
|
+
${entityField} {
|
|
305
|
+
id
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}`;
|
|
309
|
+
return {
|
|
310
|
+
document,
|
|
311
|
+
variables: {
|
|
312
|
+
input: {
|
|
313
|
+
id: where.id,
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Build a custom query document
|
|
320
|
+
*/
|
|
321
|
+
export function buildCustomQueryDocument(operationName, queryField, select, args, variableDefinitions) {
|
|
322
|
+
const selections = select ? buildSelections(select) : '';
|
|
323
|
+
const varDefs = variableDefinitions.map((v) => `$${v.name}: ${v.type}`);
|
|
324
|
+
const queryArgs = variableDefinitions.map((v) => `${v.name}: $${v.name}`);
|
|
325
|
+
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
326
|
+
const queryArgsStr = queryArgs.length > 0 ? `(${queryArgs.join(', ')})` : '';
|
|
327
|
+
const selectionsBlock = selections ? ` {\n ${selections}\n }` : '';
|
|
328
|
+
const document = `query ${operationName}Query${varDefsStr} {
|
|
329
|
+
${queryField}${queryArgsStr}${selectionsBlock}
|
|
330
|
+
}`;
|
|
331
|
+
return {
|
|
332
|
+
document,
|
|
333
|
+
variables: args ?? {},
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Build a custom mutation document
|
|
338
|
+
*/
|
|
339
|
+
export function buildCustomMutationDocument(operationName, mutationField, select, args, variableDefinitions) {
|
|
340
|
+
const selections = select ? buildSelections(select) : '';
|
|
341
|
+
const varDefs = variableDefinitions.map((v) => `$${v.name}: ${v.type}`);
|
|
342
|
+
const mutationArgs = variableDefinitions.map((v) => `${v.name}: $${v.name}`);
|
|
343
|
+
const varDefsStr = varDefs.length > 0 ? `(${varDefs.join(', ')})` : '';
|
|
344
|
+
const mutationArgsStr = mutationArgs.length > 0 ? `(${mutationArgs.join(', ')})` : '';
|
|
345
|
+
const selectionsBlock = selections ? ` {\n ${selections}\n }` : '';
|
|
346
|
+
const document = `mutation ${operationName}Mutation${varDefsStr} {
|
|
347
|
+
${mutationField}${mutationArgsStr}${selectionsBlock}
|
|
348
|
+
}`;
|
|
349
|
+
return {
|
|
350
|
+
document,
|
|
351
|
+
variables: args ?? {},
|
|
352
|
+
};
|
|
353
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript utility types for ORM select inference
|
|
3
|
+
*
|
|
4
|
+
* These types enable Prisma-like type inference where the return type
|
|
5
|
+
* is automatically derived from the `select` object passed to queries.
|
|
6
|
+
*
|
|
7
|
+
* Example:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const user = await db.user.findFirst({
|
|
10
|
+
* select: { id: true, name: true }
|
|
11
|
+
* }).execute();
|
|
12
|
+
* // user type is { id: string; name: string } | null
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Extracts the element type from an array or connection type
|
|
17
|
+
*/
|
|
18
|
+
export type ElementType<T> = T extends (infer E)[] ? E : T extends {
|
|
19
|
+
nodes: (infer E)[];
|
|
20
|
+
} ? E : T;
|
|
21
|
+
/**
|
|
22
|
+
* Checks if a type is a connection type (has nodes array)
|
|
23
|
+
*/
|
|
24
|
+
export type IsConnection<T> = T extends {
|
|
25
|
+
nodes: unknown[];
|
|
26
|
+
totalCount: number;
|
|
27
|
+
} ? true : false;
|
|
28
|
+
/**
|
|
29
|
+
* Base select type - maps fields to boolean or nested select config
|
|
30
|
+
* This is generated per-entity
|
|
31
|
+
*/
|
|
32
|
+
export type SelectConfig<TFields extends string> = {
|
|
33
|
+
[K in TFields]?: boolean | NestedSelectConfig;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Nested select configuration for relations
|
|
37
|
+
*/
|
|
38
|
+
export interface NestedSelectConfig {
|
|
39
|
+
select?: Record<string, boolean | NestedSelectConfig>;
|
|
40
|
+
first?: number;
|
|
41
|
+
last?: number;
|
|
42
|
+
after?: string;
|
|
43
|
+
before?: string;
|
|
44
|
+
filter?: Record<string, unknown>;
|
|
45
|
+
orderBy?: string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Infers the result type from a select configuration
|
|
49
|
+
*
|
|
50
|
+
* Rules:
|
|
51
|
+
* - If field is `true`, include the field with its original type
|
|
52
|
+
* - If field is `false` or not present, exclude the field
|
|
53
|
+
* - If field is an object with `select`, recursively apply inference
|
|
54
|
+
* - For connection types, preserve the connection structure
|
|
55
|
+
*/
|
|
56
|
+
export type InferSelectResult<TEntity, TSelect> = TSelect extends undefined ? TEntity : {
|
|
57
|
+
[K in keyof TSelect as TSelect[K] extends false | undefined ? never : K]: TSelect[K] extends true ? K extends keyof TEntity ? TEntity[K] : never : TSelect[K] extends {
|
|
58
|
+
select: infer NestedSelect;
|
|
59
|
+
} ? K extends keyof TEntity ? NonNullable<TEntity[K]> extends ConnectionResult<infer NodeType> ? ConnectionResult<InferSelectResult<NodeType, NestedSelect>> : InferSelectResult<NonNullable<TEntity[K]>, NestedSelect> | (null extends TEntity[K] ? null : never) : never : K extends keyof TEntity ? TEntity[K] : never;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Makes all properties in the result optional for partial selects
|
|
63
|
+
* Used when select is not provided (returns all fields)
|
|
64
|
+
*/
|
|
65
|
+
export type PartialEntity<T> = {
|
|
66
|
+
[K in keyof T]?: T[K];
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Result wrapper that matches GraphQL response structure
|
|
70
|
+
*/
|
|
71
|
+
export interface QueryResult<T> {
|
|
72
|
+
data: T | null;
|
|
73
|
+
errors?: GraphQLError[];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* GraphQL error type
|
|
77
|
+
*/
|
|
78
|
+
export interface GraphQLError {
|
|
79
|
+
message: string;
|
|
80
|
+
locations?: {
|
|
81
|
+
line: number;
|
|
82
|
+
column: number;
|
|
83
|
+
}[];
|
|
84
|
+
path?: (string | number)[];
|
|
85
|
+
extensions?: Record<string, unknown>;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Connection result type for list queries
|
|
89
|
+
*/
|
|
90
|
+
export interface ConnectionResult<T> {
|
|
91
|
+
nodes: T[];
|
|
92
|
+
totalCount: number;
|
|
93
|
+
pageInfo: PageInfo;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* PageInfo type from GraphQL connections
|
|
97
|
+
*/
|
|
98
|
+
export interface PageInfo {
|
|
99
|
+
hasNextPage: boolean;
|
|
100
|
+
hasPreviousPage: boolean;
|
|
101
|
+
startCursor?: string | null;
|
|
102
|
+
endCursor?: string | null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Arguments for findMany operations
|
|
106
|
+
*/
|
|
107
|
+
export interface FindManyArgs<TSelect, TWhere, TOrderBy> {
|
|
108
|
+
select?: TSelect;
|
|
109
|
+
where?: TWhere;
|
|
110
|
+
orderBy?: TOrderBy[];
|
|
111
|
+
first?: number;
|
|
112
|
+
last?: number;
|
|
113
|
+
after?: string;
|
|
114
|
+
before?: string;
|
|
115
|
+
offset?: number;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Arguments for findFirst/findUnique operations
|
|
119
|
+
*/
|
|
120
|
+
export interface FindFirstArgs<TSelect, TWhere> {
|
|
121
|
+
select?: TSelect;
|
|
122
|
+
where?: TWhere;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Arguments for create operations
|
|
126
|
+
*/
|
|
127
|
+
export interface CreateArgs<TSelect, TData> {
|
|
128
|
+
data: TData;
|
|
129
|
+
select?: TSelect;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Arguments for update operations
|
|
133
|
+
*/
|
|
134
|
+
export interface UpdateArgs<TSelect, TWhere, TData> {
|
|
135
|
+
where: TWhere;
|
|
136
|
+
data: TData;
|
|
137
|
+
select?: TSelect;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Arguments for delete operations
|
|
141
|
+
*/
|
|
142
|
+
export interface DeleteArgs<TWhere> {
|
|
143
|
+
where: TWhere;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Helper type to get the final result type from a query
|
|
147
|
+
* Handles the case where select is optional
|
|
148
|
+
*/
|
|
149
|
+
export type ResolveSelectResult<TEntity, TSelect> = TSelect extends undefined ? TEntity : InferSelectResult<TEntity, NonNullable<TSelect>>;
|
|
150
|
+
/**
|
|
151
|
+
* Type for operation that returns a single entity or null
|
|
152
|
+
*/
|
|
153
|
+
export type SingleResult<TEntity, TSelect> = QueryResult<{
|
|
154
|
+
[K: string]: ResolveSelectResult<TEntity, TSelect> | null;
|
|
155
|
+
}>;
|
|
156
|
+
/**
|
|
157
|
+
* Type for operation that returns a connection
|
|
158
|
+
*/
|
|
159
|
+
export type ConnectionQueryResult<TEntity, TSelect> = QueryResult<{
|
|
160
|
+
[K: string]: ConnectionResult<ResolveSelectResult<TEntity, TSelect>>;
|
|
161
|
+
}>;
|
|
162
|
+
/**
|
|
163
|
+
* Type for mutation that returns a payload with the entity
|
|
164
|
+
*/
|
|
165
|
+
export type MutationResult<TEntity, TSelect, TPayloadKey extends string> = QueryResult<{
|
|
166
|
+
[K in TPayloadKey]: {
|
|
167
|
+
[EntityKey: string]: ResolveSelectResult<TEntity, TSelect>;
|
|
168
|
+
};
|
|
169
|
+
}>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript utility types for ORM select inference
|
|
3
|
+
*
|
|
4
|
+
* These types enable Prisma-like type inference where the return type
|
|
5
|
+
* is automatically derived from the `select` object passed to queries.
|
|
6
|
+
*
|
|
7
|
+
* Example:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const user = await db.user.findFirst({
|
|
10
|
+
* select: { id: true, name: true }
|
|
11
|
+
* }).execute();
|
|
12
|
+
* // user type is { id: string; name: string } | null
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-level tests for select-types.ts
|
|
3
|
+
*
|
|
4
|
+
* These tests verify the compile-time type inference behavior.
|
|
5
|
+
* The TypeScript compiler validates these types during build.
|
|
6
|
+
*
|
|
7
|
+
* Note: Type-only tests using expectTypeOf have been removed as they
|
|
8
|
+
* are not compatible with Jest. The TypeScript compiler validates
|
|
9
|
+
* these types at compile time via the type assertions below.
|
|
10
|
+
*/
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-level tests for select-types.ts
|
|
3
|
+
*
|
|
4
|
+
* These tests verify the compile-time type inference behavior.
|
|
5
|
+
* The TypeScript compiler validates these types during build.
|
|
6
|
+
*
|
|
7
|
+
* Note: Type-only tests using expectTypeOf have been removed as they
|
|
8
|
+
* are not compatible with Jest. The TypeScript compiler validates
|
|
9
|
+
* these types at compile time via the type assertions below.
|
|
10
|
+
*/
|
|
11
|
+
// Compile-time type check: verify the inferred type matches expected structure
|
|
12
|
+
const _typeCheck = {};
|
|
13
|
+
const _excludedTypeCheck = {};
|
|
14
|
+
// Dummy test to satisfy Jest
|
|
15
|
+
describe('InferSelectResult', () => {
|
|
16
|
+
it('type assertions compile correctly', () => {
|
|
17
|
+
// If this file compiles, the type tests pass
|
|
18
|
+
expect(true).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query hook generators using AST-based code generation
|
|
3
|
+
*
|
|
4
|
+
* Output structure:
|
|
5
|
+
* queries/
|
|
6
|
+
* useCarsQuery.ts - List query hook
|
|
7
|
+
* useCarQuery.ts - Single item query hook
|
|
8
|
+
*/
|
|
9
|
+
import type { CleanTable } from '../../types/schema';
|
|
10
|
+
export interface GeneratedQueryFile {
|
|
11
|
+
fileName: string;
|
|
12
|
+
content: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate list query hook file content using AST
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateListQueryHook(table: CleanTable): GeneratedQueryFile;
|
|
18
|
+
/**
|
|
19
|
+
* Generate single item query hook file content using AST
|
|
20
|
+
*/
|
|
21
|
+
export declare function generateSingleQueryHook(table: CleanTable): GeneratedQueryFile;
|
|
22
|
+
/**
|
|
23
|
+
* Generate all query hook files for all tables
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateAllQueryHooks(tables: CleanTable[]): GeneratedQueryFile[];
|