@constructive-io/graphql-codegen 2.22.1 → 2.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/codegen/barrel.d.ts +5 -1
- package/cli/codegen/barrel.js +13 -11
- package/cli/codegen/index.d.ts +3 -3
- package/cli/codegen/index.js +15 -9
- package/cli/codegen/orm/client-generator.js +3 -2
- package/cli/codegen/orm/custom-ops-generator.js +17 -4
- package/cli/codegen/orm/input-types-generator.js +129 -18
- package/cli/codegen/orm/model-generator.js +2 -1
- package/cli/codegen/orm/query-builder.d.ts +1 -1
- package/cli/codegen/orm/query-builder.js +2 -2
- package/cli/codegen/schema-types-generator.js +5 -5
- package/cli/codegen/utils.d.ts +6 -1
- package/cli/codegen/utils.js +23 -8
- package/cli/commands/generate-orm.d.ts +5 -3
- package/cli/commands/generate-orm.js +65 -84
- package/cli/commands/generate.d.ts +2 -0
- package/cli/commands/generate.js +66 -87
- package/cli/commands/shared.d.ts +74 -0
- package/cli/commands/shared.js +88 -0
- package/cli/index.js +75 -45
- package/cli/introspect/index.d.ts +8 -5
- package/cli/introspect/index.js +19 -7
- package/cli/introspect/infer-tables.d.ts +51 -0
- package/cli/introspect/infer-tables.js +550 -0
- package/cli/introspect/source/endpoint.d.ts +34 -0
- package/cli/introspect/source/endpoint.js +35 -0
- package/cli/introspect/source/file.d.ts +20 -0
- package/cli/introspect/source/file.js +103 -0
- package/cli/introspect/source/index.d.ts +48 -0
- package/cli/introspect/source/index.js +72 -0
- package/cli/introspect/source/types.d.ts +58 -0
- package/cli/introspect/source/types.js +27 -0
- package/cli/introspect/transform.d.ts +5 -6
- package/cli/introspect/transform.js +0 -173
- package/cli/watch/cache.d.ts +3 -4
- package/cli/watch/cache.js +6 -10
- package/cli/watch/poller.d.ts +1 -2
- package/cli/watch/poller.js +27 -45
- package/cli/watch/types.d.ts +0 -3
- package/core/ast.js +4 -4
- package/core/query-builder.js +12 -12
- package/esm/cli/codegen/barrel.d.ts +5 -1
- package/esm/cli/codegen/barrel.js +13 -11
- package/esm/cli/codegen/index.d.ts +3 -3
- package/esm/cli/codegen/index.js +18 -12
- package/esm/cli/codegen/orm/client-generator.js +3 -2
- package/esm/cli/codegen/orm/custom-ops-generator.js +18 -5
- package/esm/cli/codegen/orm/input-types-generator.js +130 -19
- package/esm/cli/codegen/orm/model-generator.js +3 -2
- package/esm/cli/codegen/orm/query-builder.d.ts +1 -1
- package/esm/cli/codegen/orm/query-builder.js +2 -2
- package/esm/cli/codegen/schema-types-generator.js +6 -6
- package/esm/cli/codegen/utils.d.ts +6 -1
- package/esm/cli/codegen/utils.js +22 -8
- package/esm/cli/commands/generate-orm.d.ts +5 -3
- package/esm/cli/commands/generate-orm.js +65 -84
- package/esm/cli/commands/generate.d.ts +2 -0
- package/esm/cli/commands/generate.js +66 -87
- package/esm/cli/commands/shared.d.ts +74 -0
- package/esm/cli/commands/shared.js +84 -0
- package/esm/cli/index.js +76 -46
- package/esm/cli/introspect/index.d.ts +8 -5
- package/esm/cli/introspect/index.js +10 -3
- package/esm/cli/introspect/infer-tables.d.ts +51 -0
- package/esm/cli/introspect/infer-tables.js +547 -0
- package/esm/cli/introspect/source/endpoint.d.ts +34 -0
- package/esm/cli/introspect/source/endpoint.js +31 -0
- package/esm/cli/introspect/source/file.d.ts +20 -0
- package/esm/cli/introspect/source/file.js +66 -0
- package/esm/cli/introspect/source/index.d.ts +48 -0
- package/esm/cli/introspect/source/index.js +54 -0
- package/esm/cli/introspect/source/types.d.ts +58 -0
- package/esm/cli/introspect/source/types.js +23 -0
- package/esm/cli/introspect/transform.d.ts +5 -6
- package/esm/cli/introspect/transform.js +0 -172
- package/esm/cli/watch/cache.d.ts +3 -4
- package/esm/cli/watch/cache.js +7 -11
- package/esm/cli/watch/poller.d.ts +1 -2
- package/esm/cli/watch/poller.js +28 -46
- package/esm/cli/watch/types.d.ts +0 -3
- package/esm/core/ast.js +4 -4
- package/esm/core/query-builder.js +12 -12
- package/esm/generators/mutations.js +3 -3
- package/esm/generators/select.js +7 -7
- package/esm/types/config.d.ts +21 -5
- package/esm/types/config.js +2 -1
- package/generators/mutations.js +3 -3
- package/generators/select.js +7 -7
- package/package.json +5 -3
- package/types/config.d.ts +21 -5
- package/types/config.js +2 -1
- package/cli/introspect/fetch-meta.d.ts +0 -31
- package/cli/introspect/fetch-meta.js +0 -108
- package/cli/introspect/meta-query.d.ts +0 -111
- package/cli/introspect/meta-query.js +0 -191
- package/esm/cli/introspect/fetch-meta.d.ts +0 -31
- package/esm/cli/introspect/fetch-meta.js +0 -104
- package/esm/cli/introspect/meta-query.d.ts +0 -111
- package/esm/cli/introspect/meta-query.js +0 -188
package/esm/core/ast.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from 'gql-ast';
|
|
2
|
-
import
|
|
2
|
+
import { camelize, singularize } from 'inflekt';
|
|
3
3
|
import { getCustomAst } from './custom-ast';
|
|
4
4
|
const NON_MUTABLE_PROPS = ['createdAt', 'createdBy', 'updatedAt', 'updatedBy'];
|
|
5
5
|
const objectToArray = (obj) => Object.keys(obj).map((k) => ({
|
|
@@ -279,7 +279,7 @@ export const createOne = ({ mutationName, operationName, mutation, selection, })
|
|
|
279
279
|
if (!mutation.properties?.input?.properties) {
|
|
280
280
|
throw new Error(`No input field for mutation: ${mutationName}`);
|
|
281
281
|
}
|
|
282
|
-
const modelName =
|
|
282
|
+
const modelName = camelize([singularize(mutation.model)].join('_'), true);
|
|
283
283
|
const inputProperties = mutation.properties.input
|
|
284
284
|
.properties;
|
|
285
285
|
const modelProperties = inputProperties[modelName];
|
|
@@ -324,7 +324,7 @@ export const patchOne = ({ mutationName, operationName, mutation, selection, })
|
|
|
324
324
|
if (!mutation.properties?.input?.properties) {
|
|
325
325
|
throw new Error(`No input field for mutation: ${mutationName}`);
|
|
326
326
|
}
|
|
327
|
-
const modelName =
|
|
327
|
+
const modelName = camelize([singularize(mutation.model)].join('_'), true);
|
|
328
328
|
const inputProperties = mutation.properties.input
|
|
329
329
|
.properties;
|
|
330
330
|
const patchProperties = inputProperties['patch'];
|
|
@@ -376,7 +376,7 @@ export const deleteOne = ({ mutationName, operationName, mutation, }) => {
|
|
|
376
376
|
if (!mutation.properties?.input?.properties) {
|
|
377
377
|
throw new Error(`No input field for mutation: ${mutationName}`);
|
|
378
378
|
}
|
|
379
|
-
const modelName =
|
|
379
|
+
const modelName = camelize([singularize(mutation.model)].join('_'), true);
|
|
380
380
|
const inputProperties = mutation.properties.input
|
|
381
381
|
.properties;
|
|
382
382
|
const deleteAttrs = objectToArray(inputProperties);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { print as gqlPrint } from 'graphql';
|
|
2
|
-
import
|
|
2
|
+
import { camelize, underscore, pluralize } from 'inflekt';
|
|
3
3
|
import { createOne, deleteOne, getAll, getCount, getMany, getOne, patchOne, } from './ast';
|
|
4
4
|
import { validateMetaObject } from './meta-object';
|
|
5
5
|
export * as MetaObject from './meta-object';
|
|
@@ -88,13 +88,13 @@ export class QueryBuilder {
|
|
|
88
88
|
const getInputName = (mutationType) => {
|
|
89
89
|
switch (mutationType) {
|
|
90
90
|
case 'delete': {
|
|
91
|
-
return `Delete${
|
|
91
|
+
return `Delete${camelize(this._model)}Input`;
|
|
92
92
|
}
|
|
93
93
|
case 'create': {
|
|
94
|
-
return `Create${
|
|
94
|
+
return `Create${camelize(this._model)}Input`;
|
|
95
95
|
}
|
|
96
96
|
case 'patch': {
|
|
97
|
-
return `Update${
|
|
97
|
+
return `Update${camelize(this._model)}Input`;
|
|
98
98
|
}
|
|
99
99
|
default:
|
|
100
100
|
throw new Error('Unhandled mutation type' + mutationType);
|
|
@@ -123,7 +123,7 @@ export class QueryBuilder {
|
|
|
123
123
|
getMany({ select } = {}) {
|
|
124
124
|
this._op = 'getMany';
|
|
125
125
|
this._key = this._findQuery();
|
|
126
|
-
this.queryName(
|
|
126
|
+
this.queryName(camelize(['get', underscore(this._key), 'query'].join('_'), true));
|
|
127
127
|
const defn = this._introspection[this._key];
|
|
128
128
|
this.select(select);
|
|
129
129
|
this._ast = getMany({
|
|
@@ -138,7 +138,7 @@ export class QueryBuilder {
|
|
|
138
138
|
all({ select } = {}) {
|
|
139
139
|
this._op = 'getMany';
|
|
140
140
|
this._key = this._findQuery();
|
|
141
|
-
this.queryName(
|
|
141
|
+
this.queryName(camelize(['get', underscore(this._key), 'query', 'all'].join('_'), true));
|
|
142
142
|
const defn = this._introspection[this._key];
|
|
143
143
|
this.select(select);
|
|
144
144
|
this._ast = getAll({
|
|
@@ -152,7 +152,7 @@ export class QueryBuilder {
|
|
|
152
152
|
count() {
|
|
153
153
|
this._op = 'getMany';
|
|
154
154
|
this._key = this._findQuery();
|
|
155
|
-
this.queryName(
|
|
155
|
+
this.queryName(camelize(['get', underscore(this._key), 'count', 'query'].join('_'), true));
|
|
156
156
|
const defn = this._introspection[this._key];
|
|
157
157
|
this._ast = getCount({
|
|
158
158
|
queryName: this._queryName,
|
|
@@ -164,7 +164,7 @@ export class QueryBuilder {
|
|
|
164
164
|
getOne({ select } = {}) {
|
|
165
165
|
this._op = 'getOne';
|
|
166
166
|
this._key = this._findQuery();
|
|
167
|
-
this.queryName(
|
|
167
|
+
this.queryName(camelize(['get', underscore(this._key), 'query'].join('_'), true));
|
|
168
168
|
const defn = this._introspection[this._key];
|
|
169
169
|
this.select(select);
|
|
170
170
|
this._ast = getOne({
|
|
@@ -180,7 +180,7 @@ export class QueryBuilder {
|
|
|
180
180
|
this._op = 'mutation';
|
|
181
181
|
this._mutation = 'create';
|
|
182
182
|
this._key = this._findMutation();
|
|
183
|
-
this.queryName(
|
|
183
|
+
this.queryName(camelize([underscore(this._key), 'mutation'].join('_'), true));
|
|
184
184
|
const defn = this._introspection[this._key];
|
|
185
185
|
this.select(select);
|
|
186
186
|
this._ast = createOne({
|
|
@@ -195,7 +195,7 @@ export class QueryBuilder {
|
|
|
195
195
|
this._op = 'mutation';
|
|
196
196
|
this._mutation = 'delete';
|
|
197
197
|
this._key = this._findMutation();
|
|
198
|
-
this.queryName(
|
|
198
|
+
this.queryName(camelize([underscore(this._key), 'mutation'].join('_'), true));
|
|
199
199
|
const defn = this._introspection[this._key];
|
|
200
200
|
this.select(select);
|
|
201
201
|
this._ast = deleteOne({
|
|
@@ -209,7 +209,7 @@ export class QueryBuilder {
|
|
|
209
209
|
this._op = 'mutation';
|
|
210
210
|
this._mutation = 'patch';
|
|
211
211
|
this._key = this._findMutation();
|
|
212
|
-
this.queryName(
|
|
212
|
+
this.queryName(camelize([underscore(this._key), 'mutation'].join('_'), true));
|
|
213
213
|
const defn = this._introspection[this._key];
|
|
214
214
|
this.select(select);
|
|
215
215
|
this._ast = patchOne({
|
|
@@ -371,5 +371,5 @@ function isRelationalField(fieldName, modelMeta) {
|
|
|
371
371
|
// Get getMany op name from model
|
|
372
372
|
// ie. UserSetting => userSettings
|
|
373
373
|
function modelNameToGetMany(model) {
|
|
374
|
-
return
|
|
374
|
+
return camelize(pluralize(underscore(model)), true);
|
|
375
375
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as t from 'gql-ast';
|
|
6
6
|
import { print } from 'graphql';
|
|
7
|
-
import
|
|
7
|
+
import { camelize } from 'inflekt';
|
|
8
8
|
import { TypedDocumentString } from '../client/typed-document';
|
|
9
9
|
import { getCustomAstForCleanField, requiresSubfieldSelection, } from '../core/custom-ast';
|
|
10
10
|
import { isRelationalField } from './field-selector';
|
|
@@ -32,7 +32,7 @@ function generateFieldSelections(table) {
|
|
|
32
32
|
*/
|
|
33
33
|
export function buildPostGraphileCreate(table, _allTables, _options = {}) {
|
|
34
34
|
const mutationName = `create${table.name}`;
|
|
35
|
-
const singularName =
|
|
35
|
+
const singularName = camelize(table.name, true);
|
|
36
36
|
// Create the variable definition for $input
|
|
37
37
|
const variableDefinitions = [
|
|
38
38
|
t.variableDefinition({
|
|
@@ -91,7 +91,7 @@ export function buildPostGraphileCreate(table, _allTables, _options = {}) {
|
|
|
91
91
|
*/
|
|
92
92
|
export function buildPostGraphileUpdate(table, _allTables, _options = {}) {
|
|
93
93
|
const mutationName = `update${table.name}`;
|
|
94
|
-
const singularName =
|
|
94
|
+
const singularName = camelize(table.name, true);
|
|
95
95
|
// Create the variable definition for $input
|
|
96
96
|
const variableDefinitions = [
|
|
97
97
|
t.variableDefinition({
|
package/esm/generators/select.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import * as t from 'gql-ast';
|
|
6
6
|
import { print } from 'graphql';
|
|
7
|
-
import
|
|
7
|
+
import { camelize, pluralize } from 'inflekt';
|
|
8
8
|
import { TypedDocumentString } from '../client/typed-document';
|
|
9
9
|
import { getCustomAstForCleanField, requiresSubfieldSelection, } from '../core/custom-ast';
|
|
10
10
|
import { QueryBuilder } from '../core/query-builder';
|
|
@@ -16,9 +16,9 @@ import { convertToSelectionOptions, isRelationalField } from './field-selector';
|
|
|
16
16
|
*/
|
|
17
17
|
export function toCamelCasePlural(tableName) {
|
|
18
18
|
// First convert to camelCase (lowercase first letter)
|
|
19
|
-
const camelCase =
|
|
19
|
+
const camelCase = camelize(tableName, true);
|
|
20
20
|
// Then pluralize properly
|
|
21
|
-
return
|
|
21
|
+
return pluralize(camelCase);
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
24
24
|
* Generate the PostGraphile OrderBy enum type name for a table
|
|
@@ -101,7 +101,7 @@ export function generateIntrospectionSchema(tables) {
|
|
|
101
101
|
properties: convertFieldsToProperties(table.fields),
|
|
102
102
|
};
|
|
103
103
|
// Add getOne query (by ID)
|
|
104
|
-
const singularName =
|
|
104
|
+
const singularName = camelize(modelName, true);
|
|
105
105
|
schema[singularName] = {
|
|
106
106
|
qtype: 'getOne',
|
|
107
107
|
model: modelName,
|
|
@@ -122,8 +122,8 @@ export function generateIntrospectionSchema(tables) {
|
|
|
122
122
|
isArray: false,
|
|
123
123
|
isArrayNotNull: false,
|
|
124
124
|
properties: {
|
|
125
|
-
[
|
|
126
|
-
name:
|
|
125
|
+
[camelize(modelName, true)]: {
|
|
126
|
+
name: camelize(modelName, true),
|
|
127
127
|
type: `${modelName}Input`,
|
|
128
128
|
isNotNull: true,
|
|
129
129
|
isArray: false,
|
|
@@ -549,7 +549,7 @@ function findRelatedTable(relationField, table, allTables) {
|
|
|
549
549
|
* Generate FindOne query AST directly from CleanTable
|
|
550
550
|
*/
|
|
551
551
|
function generateFindOneQueryAST(table) {
|
|
552
|
-
const singularName =
|
|
552
|
+
const singularName = camelize(table.name, true);
|
|
553
553
|
// Generate field selections (include all non-relational fields, including complex types)
|
|
554
554
|
const fieldSelections = table.fields
|
|
555
555
|
.filter((field) => !isRelationalField(field.name, table))
|
package/esm/types/config.d.ts
CHANGED
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export interface GraphQLSDKConfig {
|
|
8
8
|
/**
|
|
9
|
-
* GraphQL endpoint URL
|
|
9
|
+
* GraphQL endpoint URL for live introspection
|
|
10
|
+
* Either endpoint or schema must be provided
|
|
10
11
|
*/
|
|
11
|
-
endpoint
|
|
12
|
+
endpoint?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Path to GraphQL schema file (.graphql) for file-based generation
|
|
15
|
+
* Either endpoint or schema must be provided
|
|
16
|
+
*/
|
|
17
|
+
schema?: string;
|
|
12
18
|
/**
|
|
13
19
|
* Headers to include in introspection requests
|
|
14
20
|
*/
|
|
@@ -19,7 +25,7 @@ export interface GraphQLSDKConfig {
|
|
|
19
25
|
*/
|
|
20
26
|
output?: string;
|
|
21
27
|
/**
|
|
22
|
-
* Table filtering options (for table-based CRUD operations
|
|
28
|
+
* Table filtering options (for table-based CRUD operations)
|
|
23
29
|
*/
|
|
24
30
|
tables?: {
|
|
25
31
|
/** Tables to include (glob patterns supported) */
|
|
@@ -154,8 +160,17 @@ export interface ResolvedWatchConfig {
|
|
|
154
160
|
/**
|
|
155
161
|
* Resolved configuration with defaults applied
|
|
156
162
|
*/
|
|
157
|
-
export interface ResolvedConfig
|
|
163
|
+
export interface ResolvedConfig {
|
|
164
|
+
/**
|
|
165
|
+
* GraphQL endpoint URL (empty string if using schema file)
|
|
166
|
+
*/
|
|
167
|
+
endpoint: string;
|
|
168
|
+
/**
|
|
169
|
+
* Path to GraphQL schema file (null if using endpoint)
|
|
170
|
+
*/
|
|
171
|
+
schema: string | null;
|
|
158
172
|
headers: Record<string, string>;
|
|
173
|
+
output: string;
|
|
159
174
|
tables: {
|
|
160
175
|
include: string[];
|
|
161
176
|
exclude: string[];
|
|
@@ -168,6 +183,7 @@ export interface ResolvedConfig extends Required<Omit<GraphQLSDKConfig, 'headers
|
|
|
168
183
|
include: string[];
|
|
169
184
|
exclude: string[];
|
|
170
185
|
};
|
|
186
|
+
excludeFields: string[];
|
|
171
187
|
hooks: {
|
|
172
188
|
queries: boolean;
|
|
173
189
|
mutations: boolean;
|
|
@@ -196,7 +212,7 @@ export declare const DEFAULT_WATCH_CONFIG: ResolvedWatchConfig;
|
|
|
196
212
|
/**
|
|
197
213
|
* Default configuration values
|
|
198
214
|
*/
|
|
199
|
-
export declare const DEFAULT_CONFIG: Omit<ResolvedConfig, 'endpoint'>;
|
|
215
|
+
export declare const DEFAULT_CONFIG: Omit<ResolvedConfig, 'endpoint' | 'schema'>;
|
|
200
216
|
/**
|
|
201
217
|
* Default ORM configuration values
|
|
202
218
|
*/
|
package/esm/types/config.js
CHANGED
|
@@ -65,7 +65,8 @@ export function defineConfig(config) {
|
|
|
65
65
|
*/
|
|
66
66
|
export function resolveConfig(config) {
|
|
67
67
|
return {
|
|
68
|
-
endpoint: config.endpoint,
|
|
68
|
+
endpoint: config.endpoint ?? '',
|
|
69
|
+
schema: config.schema ?? null,
|
|
69
70
|
headers: config.headers ?? DEFAULT_CONFIG.headers,
|
|
70
71
|
output: config.output ?? DEFAULT_CONFIG.output,
|
|
71
72
|
tables: {
|
package/generators/mutations.js
CHANGED
|
@@ -42,7 +42,7 @@ exports.buildPostGraphileDelete = buildPostGraphileDelete;
|
|
|
42
42
|
*/
|
|
43
43
|
const t = __importStar(require("gql-ast"));
|
|
44
44
|
const graphql_1 = require("graphql");
|
|
45
|
-
const
|
|
45
|
+
const inflekt_1 = require("inflekt");
|
|
46
46
|
const typed_document_1 = require("../client/typed-document");
|
|
47
47
|
const custom_ast_1 = require("../core/custom-ast");
|
|
48
48
|
const field_selector_1 = require("./field-selector");
|
|
@@ -70,7 +70,7 @@ function generateFieldSelections(table) {
|
|
|
70
70
|
*/
|
|
71
71
|
function buildPostGraphileCreate(table, _allTables, _options = {}) {
|
|
72
72
|
const mutationName = `create${table.name}`;
|
|
73
|
-
const singularName =
|
|
73
|
+
const singularName = (0, inflekt_1.camelize)(table.name, true);
|
|
74
74
|
// Create the variable definition for $input
|
|
75
75
|
const variableDefinitions = [
|
|
76
76
|
t.variableDefinition({
|
|
@@ -129,7 +129,7 @@ function buildPostGraphileCreate(table, _allTables, _options = {}) {
|
|
|
129
129
|
*/
|
|
130
130
|
function buildPostGraphileUpdate(table, _allTables, _options = {}) {
|
|
131
131
|
const mutationName = `update${table.name}`;
|
|
132
|
-
const singularName =
|
|
132
|
+
const singularName = (0, inflekt_1.camelize)(table.name, true);
|
|
133
133
|
// Create the variable definition for $input
|
|
134
134
|
const variableDefinitions = [
|
|
135
135
|
t.variableDefinition({
|
package/generators/select.js
CHANGED
|
@@ -47,7 +47,7 @@ exports.buildCount = buildCount;
|
|
|
47
47
|
*/
|
|
48
48
|
const t = __importStar(require("gql-ast"));
|
|
49
49
|
const graphql_1 = require("graphql");
|
|
50
|
-
const
|
|
50
|
+
const inflekt_1 = require("inflekt");
|
|
51
51
|
const typed_document_1 = require("../client/typed-document");
|
|
52
52
|
const custom_ast_1 = require("../core/custom-ast");
|
|
53
53
|
const query_builder_1 = require("../core/query-builder");
|
|
@@ -59,9 +59,9 @@ const field_selector_1 = require("./field-selector");
|
|
|
59
59
|
*/
|
|
60
60
|
function toCamelCasePlural(tableName) {
|
|
61
61
|
// First convert to camelCase (lowercase first letter)
|
|
62
|
-
const camelCase =
|
|
62
|
+
const camelCase = (0, inflekt_1.camelize)(tableName, true);
|
|
63
63
|
// Then pluralize properly
|
|
64
|
-
return
|
|
64
|
+
return (0, inflekt_1.pluralize)(camelCase);
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* Generate the PostGraphile OrderBy enum type name for a table
|
|
@@ -144,7 +144,7 @@ function generateIntrospectionSchema(tables) {
|
|
|
144
144
|
properties: convertFieldsToProperties(table.fields),
|
|
145
145
|
};
|
|
146
146
|
// Add getOne query (by ID)
|
|
147
|
-
const singularName =
|
|
147
|
+
const singularName = (0, inflekt_1.camelize)(modelName, true);
|
|
148
148
|
schema[singularName] = {
|
|
149
149
|
qtype: 'getOne',
|
|
150
150
|
model: modelName,
|
|
@@ -165,8 +165,8 @@ function generateIntrospectionSchema(tables) {
|
|
|
165
165
|
isArray: false,
|
|
166
166
|
isArrayNotNull: false,
|
|
167
167
|
properties: {
|
|
168
|
-
[
|
|
169
|
-
name:
|
|
168
|
+
[(0, inflekt_1.camelize)(modelName, true)]: {
|
|
169
|
+
name: (0, inflekt_1.camelize)(modelName, true),
|
|
170
170
|
type: `${modelName}Input`,
|
|
171
171
|
isNotNull: true,
|
|
172
172
|
isArray: false,
|
|
@@ -592,7 +592,7 @@ function findRelatedTable(relationField, table, allTables) {
|
|
|
592
592
|
* Generate FindOne query AST directly from CleanTable
|
|
593
593
|
*/
|
|
594
594
|
function generateFindOneQueryAST(table) {
|
|
595
|
-
const singularName =
|
|
595
|
+
const singularName = (0, inflekt_1.camelize)(table.name, true);
|
|
596
596
|
// Generate field selections (include all non-relational fields, including complex types)
|
|
597
597
|
const fieldSelections = table.fields
|
|
598
598
|
.filter((field) => !(0, field_selector_1.isRelationalField)(field.name, table))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/graphql-codegen",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.1",
|
|
4
4
|
"description": "CLI-based GraphQL SDK generator for PostGraphile endpoints with React Query hooks",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
"test:watch": "jest --watch",
|
|
44
44
|
"example:codegen:sdk": "node dist/cli/index.js generate --endpoint http://api.localhost:3000/graphql --output examples/output/generated-sdk",
|
|
45
45
|
"example:codegen:orm": "node dist/cli/index.js generate-orm --endpoint http://api.localhost:3000/graphql --output examples/output/generated-orm",
|
|
46
|
+
"example:codegen:sdk:schema": "node dist/cli/index.js generate --schema examples/example.schema.graphql --output examples/output/generated-sdk-schema",
|
|
47
|
+
"example:codegen:orm:schema": "node dist/cli/index.js generate-orm --schema examples/example.schema.graphql --output examples/output/generated-orm-schema",
|
|
46
48
|
"example:sdk": "tsx examples/react-query-sdk.ts",
|
|
47
49
|
"example:orm": "tsx examples/orm-sdk.ts"
|
|
48
50
|
},
|
|
@@ -51,7 +53,7 @@
|
|
|
51
53
|
"commander": "^12.1.0",
|
|
52
54
|
"gql-ast": "^2.4.6",
|
|
53
55
|
"graphql": "15.10.1",
|
|
54
|
-
"
|
|
56
|
+
"inflekt": "^0.1.2",
|
|
55
57
|
"jiti": "^2.6.1",
|
|
56
58
|
"prettier": "^3.7.4",
|
|
57
59
|
"ts-morph": "^27.0.2"
|
|
@@ -79,5 +81,5 @@
|
|
|
79
81
|
"tsx": "^4.21.0",
|
|
80
82
|
"typescript": "^5.9.3"
|
|
81
83
|
},
|
|
82
|
-
"gitHead": "
|
|
84
|
+
"gitHead": "22c89cfc6f67879e77ca47f652c31c80828665f5"
|
|
83
85
|
}
|
package/types/config.d.ts
CHANGED
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export interface GraphQLSDKConfig {
|
|
8
8
|
/**
|
|
9
|
-
* GraphQL endpoint URL
|
|
9
|
+
* GraphQL endpoint URL for live introspection
|
|
10
|
+
* Either endpoint or schema must be provided
|
|
10
11
|
*/
|
|
11
|
-
endpoint
|
|
12
|
+
endpoint?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Path to GraphQL schema file (.graphql) for file-based generation
|
|
15
|
+
* Either endpoint or schema must be provided
|
|
16
|
+
*/
|
|
17
|
+
schema?: string;
|
|
12
18
|
/**
|
|
13
19
|
* Headers to include in introspection requests
|
|
14
20
|
*/
|
|
@@ -19,7 +25,7 @@ export interface GraphQLSDKConfig {
|
|
|
19
25
|
*/
|
|
20
26
|
output?: string;
|
|
21
27
|
/**
|
|
22
|
-
* Table filtering options (for table-based CRUD operations
|
|
28
|
+
* Table filtering options (for table-based CRUD operations)
|
|
23
29
|
*/
|
|
24
30
|
tables?: {
|
|
25
31
|
/** Tables to include (glob patterns supported) */
|
|
@@ -154,8 +160,17 @@ export interface ResolvedWatchConfig {
|
|
|
154
160
|
/**
|
|
155
161
|
* Resolved configuration with defaults applied
|
|
156
162
|
*/
|
|
157
|
-
export interface ResolvedConfig
|
|
163
|
+
export interface ResolvedConfig {
|
|
164
|
+
/**
|
|
165
|
+
* GraphQL endpoint URL (empty string if using schema file)
|
|
166
|
+
*/
|
|
167
|
+
endpoint: string;
|
|
168
|
+
/**
|
|
169
|
+
* Path to GraphQL schema file (null if using endpoint)
|
|
170
|
+
*/
|
|
171
|
+
schema: string | null;
|
|
158
172
|
headers: Record<string, string>;
|
|
173
|
+
output: string;
|
|
159
174
|
tables: {
|
|
160
175
|
include: string[];
|
|
161
176
|
exclude: string[];
|
|
@@ -168,6 +183,7 @@ export interface ResolvedConfig extends Required<Omit<GraphQLSDKConfig, 'headers
|
|
|
168
183
|
include: string[];
|
|
169
184
|
exclude: string[];
|
|
170
185
|
};
|
|
186
|
+
excludeFields: string[];
|
|
171
187
|
hooks: {
|
|
172
188
|
queries: boolean;
|
|
173
189
|
mutations: boolean;
|
|
@@ -196,7 +212,7 @@ export declare const DEFAULT_WATCH_CONFIG: ResolvedWatchConfig;
|
|
|
196
212
|
/**
|
|
197
213
|
* Default configuration values
|
|
198
214
|
*/
|
|
199
|
-
export declare const DEFAULT_CONFIG: Omit<ResolvedConfig, 'endpoint'>;
|
|
215
|
+
export declare const DEFAULT_CONFIG: Omit<ResolvedConfig, 'endpoint' | 'schema'>;
|
|
200
216
|
/**
|
|
201
217
|
* Default ORM configuration values
|
|
202
218
|
*/
|
package/types/config.js
CHANGED
|
@@ -70,7 +70,8 @@ function defineConfig(config) {
|
|
|
70
70
|
*/
|
|
71
71
|
function resolveConfig(config) {
|
|
72
72
|
return {
|
|
73
|
-
endpoint: config.endpoint,
|
|
73
|
+
endpoint: config.endpoint ?? '',
|
|
74
|
+
schema: config.schema ?? null,
|
|
74
75
|
headers: config.headers ?? exports.DEFAULT_CONFIG.headers,
|
|
75
76
|
output: config.output ?? exports.DEFAULT_CONFIG.output,
|
|
76
77
|
tables: {
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Fetch _meta query from a PostGraphile endpoint
|
|
3
|
-
*/
|
|
4
|
-
import { type MetaQueryResponse } from './meta-query';
|
|
5
|
-
export interface FetchMetaOptions {
|
|
6
|
-
/** GraphQL endpoint URL */
|
|
7
|
-
endpoint: string;
|
|
8
|
-
/** Optional authorization header value (e.g., "Bearer token") */
|
|
9
|
-
authorization?: string;
|
|
10
|
-
/** Optional additional headers */
|
|
11
|
-
headers?: Record<string, string>;
|
|
12
|
-
/** Request timeout in milliseconds (default: 30000) */
|
|
13
|
-
timeout?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface FetchMetaResult {
|
|
16
|
-
success: boolean;
|
|
17
|
-
data?: MetaQueryResponse;
|
|
18
|
-
error?: string;
|
|
19
|
-
statusCode?: number;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Fetch the _meta query from a PostGraphile endpoint
|
|
23
|
-
*/
|
|
24
|
-
export declare function fetchMeta(options: FetchMetaOptions): Promise<FetchMetaResult>;
|
|
25
|
-
/**
|
|
26
|
-
* Validate that an endpoint URL is valid
|
|
27
|
-
*/
|
|
28
|
-
export declare function validateEndpoint(endpoint: string): {
|
|
29
|
-
valid: boolean;
|
|
30
|
-
error?: string;
|
|
31
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchMeta = fetchMeta;
|
|
4
|
-
exports.validateEndpoint = validateEndpoint;
|
|
5
|
-
/**
|
|
6
|
-
* Fetch _meta query from a PostGraphile endpoint
|
|
7
|
-
*/
|
|
8
|
-
const meta_query_1 = require("./meta-query");
|
|
9
|
-
/**
|
|
10
|
-
* Fetch the _meta query from a PostGraphile endpoint
|
|
11
|
-
*/
|
|
12
|
-
async function fetchMeta(options) {
|
|
13
|
-
const { endpoint, authorization, headers = {}, timeout = 30000 } = options;
|
|
14
|
-
// Build headers
|
|
15
|
-
const requestHeaders = {
|
|
16
|
-
'Content-Type': 'application/json',
|
|
17
|
-
Accept: 'application/json',
|
|
18
|
-
...headers,
|
|
19
|
-
};
|
|
20
|
-
if (authorization) {
|
|
21
|
-
requestHeaders['Authorization'] = authorization;
|
|
22
|
-
}
|
|
23
|
-
// Create abort controller for timeout
|
|
24
|
-
const controller = new AbortController();
|
|
25
|
-
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
26
|
-
try {
|
|
27
|
-
const response = await fetch(endpoint, {
|
|
28
|
-
method: 'POST',
|
|
29
|
-
headers: requestHeaders,
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
query: meta_query_1.META_QUERY,
|
|
32
|
-
variables: {},
|
|
33
|
-
}),
|
|
34
|
-
signal: controller.signal,
|
|
35
|
-
});
|
|
36
|
-
clearTimeout(timeoutId);
|
|
37
|
-
if (!response.ok) {
|
|
38
|
-
return {
|
|
39
|
-
success: false,
|
|
40
|
-
error: `HTTP ${response.status}: ${response.statusText}`,
|
|
41
|
-
statusCode: response.status,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
const json = (await response.json());
|
|
45
|
-
// Check for GraphQL errors
|
|
46
|
-
if (json.errors && json.errors.length > 0) {
|
|
47
|
-
const errorMessages = json.errors.map((e) => e.message).join('; ');
|
|
48
|
-
return {
|
|
49
|
-
success: false,
|
|
50
|
-
error: `GraphQL errors: ${errorMessages}`,
|
|
51
|
-
statusCode: response.status,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
// Check if _meta is present
|
|
55
|
-
if (!json.data?._meta) {
|
|
56
|
-
return {
|
|
57
|
-
success: false,
|
|
58
|
-
error: 'No _meta field in response. Make sure the endpoint has the PostGraphile meta plugin installed.',
|
|
59
|
-
statusCode: response.status,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
success: true,
|
|
64
|
-
data: json.data,
|
|
65
|
-
statusCode: response.status,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
catch (err) {
|
|
69
|
-
clearTimeout(timeoutId);
|
|
70
|
-
if (err instanceof Error) {
|
|
71
|
-
if (err.name === 'AbortError') {
|
|
72
|
-
return {
|
|
73
|
-
success: false,
|
|
74
|
-
error: `Request timeout after ${timeout}ms`,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
success: false,
|
|
79
|
-
error: err.message,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
success: false,
|
|
84
|
-
error: 'Unknown error occurred',
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Validate that an endpoint URL is valid
|
|
90
|
-
*/
|
|
91
|
-
function validateEndpoint(endpoint) {
|
|
92
|
-
try {
|
|
93
|
-
const url = new URL(endpoint);
|
|
94
|
-
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
95
|
-
return {
|
|
96
|
-
valid: false,
|
|
97
|
-
error: 'Endpoint must use http or https protocol',
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
return { valid: true };
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
return {
|
|
104
|
-
valid: false,
|
|
105
|
-
error: 'Invalid URL format',
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|