@constructive-io/graphql-server 3.1.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errors/404-message.js +1 -1
- package/errors/api-errors.d.ts +200 -0
- package/errors/api-errors.js +276 -0
- package/esm/errors/404-message.js +1 -1
- package/esm/errors/api-errors.js +261 -0
- package/esm/index.js +2 -0
- package/esm/middleware/api.js +355 -277
- package/esm/middleware/auth.js +25 -7
- package/esm/middleware/error-handler.js +86 -0
- package/esm/middleware/favicon.js +12 -0
- package/esm/middleware/graphile.js +149 -64
- package/esm/options.js +232 -0
- package/esm/schema.js +24 -11
- package/esm/server.js +41 -5
- package/index.d.ts +1 -0
- package/index.js +2 -0
- package/middleware/api.d.ts +3 -15
- package/middleware/api.js +359 -283
- package/middleware/auth.js +25 -7
- package/middleware/error-handler.d.ts +4 -0
- package/middleware/error-handler.js +94 -0
- package/middleware/favicon.d.ts +2 -0
- package/middleware/favicon.js +16 -0
- package/middleware/graphile.d.ts +14 -0
- package/middleware/graphile.js +149 -64
- package/options.d.ts +131 -0
- package/options.js +244 -0
- package/package.json +23 -24
- package/schema.d.ts +2 -2
- package/schema.js +23 -10
- package/server.d.ts +24 -2
- package/server.js +39 -3
- package/codegen/orm/client.d.ts +0 -55
- package/codegen/orm/client.js +0 -75
- package/codegen/orm/index.d.ts +0 -36
- package/codegen/orm/index.js +0 -59
- package/codegen/orm/input-types.d.ts +0 -20140
- package/codegen/orm/input-types.js +0 -2
- package/codegen/orm/models/api.d.ts +0 -42
- package/codegen/orm/models/api.js +0 -76
- package/codegen/orm/models/domain.d.ts +0 -42
- package/codegen/orm/models/domain.js +0 -76
- package/codegen/orm/models/index.d.ts +0 -7
- package/codegen/orm/models/index.js +0 -12
- package/codegen/orm/mutation/index.d.ts +0 -7
- package/codegen/orm/mutation/index.js +0 -7
- package/codegen/orm/query/index.d.ts +0 -20
- package/codegen/orm/query/index.js +0 -24
- package/codegen/orm/query-builder.d.ts +0 -81
- package/codegen/orm/query-builder.js +0 -496
- package/codegen/orm/select-types.d.ts +0 -83
- package/codegen/orm/select-types.js +0 -7
- package/codegen/orm/types.d.ts +0 -6
- package/codegen/orm/types.js +0 -23
- package/esm/codegen/orm/client.js +0 -70
- package/esm/codegen/orm/index.js +0 -39
- package/esm/codegen/orm/input-types.js +0 -1
- package/esm/codegen/orm/models/api.js +0 -72
- package/esm/codegen/orm/models/domain.js +0 -72
- package/esm/codegen/orm/models/index.js +0 -7
- package/esm/codegen/orm/mutation/index.js +0 -4
- package/esm/codegen/orm/query/index.js +0 -21
- package/esm/codegen/orm/query-builder.js +0 -452
- package/esm/codegen/orm/select-types.js +0 -6
- package/esm/codegen/orm/types.js +0 -7
- package/esm/middleware/gql.js +0 -116
- package/esm/plugins/PublicKeySignature.js +0 -114
- package/esm/scripts/codegen-schema.js +0 -71
- package/esm/scripts/create-bucket.js +0 -40
- package/middleware/gql.d.ts +0 -164
- package/middleware/gql.js +0 -121
- package/plugins/PublicKeySignature.d.ts +0 -11
- package/plugins/PublicKeySignature.js +0 -121
- package/scripts/codegen-schema.d.ts +0 -1
- package/scripts/codegen-schema.js +0 -76
- package/scripts/create-bucket.d.ts +0 -1
- package/scripts/create-bucket.js +0 -42
package/options.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* GraphQL Server Options - Configuration utilities
|
|
4
|
+
*
|
|
5
|
+
* This module provides type-safe configuration utilities for the GraphQL server.
|
|
6
|
+
* It includes type guards for runtime validation and utility functions for
|
|
7
|
+
* configuration normalization.
|
|
8
|
+
*
|
|
9
|
+
* The main configuration type is `ConstructiveOptions` from @constructive-io/graphql-types.
|
|
10
|
+
*
|
|
11
|
+
* @module options
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.serverDefaults = void 0;
|
|
18
|
+
exports.isConstructiveOptions = isConstructiveOptions;
|
|
19
|
+
exports.hasPgConfig = hasPgConfig;
|
|
20
|
+
exports.hasServerConfig = hasServerConfig;
|
|
21
|
+
exports.hasApiConfig = hasApiConfig;
|
|
22
|
+
exports.isLegacyOptions = isLegacyOptions;
|
|
23
|
+
exports.normalizeServerOptions = normalizeServerOptions;
|
|
24
|
+
const deepmerge_1 = __importDefault(require("deepmerge"));
|
|
25
|
+
const graphql_types_1 = require("@constructive-io/graphql-types");
|
|
26
|
+
// ============================================
|
|
27
|
+
// Default Configuration
|
|
28
|
+
// ============================================
|
|
29
|
+
/**
|
|
30
|
+
* Default configuration values for GraphQL server
|
|
31
|
+
*
|
|
32
|
+
* Provides sensible defaults for all currently active fields.
|
|
33
|
+
*/
|
|
34
|
+
exports.serverDefaults = {
|
|
35
|
+
pg: {
|
|
36
|
+
host: 'localhost',
|
|
37
|
+
port: 5432,
|
|
38
|
+
user: 'postgres',
|
|
39
|
+
password: 'password',
|
|
40
|
+
database: 'postgres'
|
|
41
|
+
},
|
|
42
|
+
server: {
|
|
43
|
+
host: 'localhost',
|
|
44
|
+
port: 3000,
|
|
45
|
+
trustProxy: false,
|
|
46
|
+
strictAuth: false
|
|
47
|
+
},
|
|
48
|
+
api: graphql_types_1.apiDefaults,
|
|
49
|
+
graphile: graphql_types_1.graphileDefaults,
|
|
50
|
+
features: graphql_types_1.graphileFeatureDefaults
|
|
51
|
+
};
|
|
52
|
+
// ============================================
|
|
53
|
+
// Type Guards
|
|
54
|
+
// ============================================
|
|
55
|
+
/**
|
|
56
|
+
* List of all recognized fields in ConstructiveOptions
|
|
57
|
+
*/
|
|
58
|
+
const RECOGNIZED_FIELDS = [
|
|
59
|
+
'pg',
|
|
60
|
+
'server',
|
|
61
|
+
'api',
|
|
62
|
+
'graphile',
|
|
63
|
+
'features',
|
|
64
|
+
'db',
|
|
65
|
+
'cdn',
|
|
66
|
+
'deployment',
|
|
67
|
+
'migrations',
|
|
68
|
+
'jobs'
|
|
69
|
+
];
|
|
70
|
+
/**
|
|
71
|
+
* Type guard to validate if an unknown value is a valid ConstructiveOptions object
|
|
72
|
+
*
|
|
73
|
+
* Validates that:
|
|
74
|
+
* 1. The value is a non-null object
|
|
75
|
+
* 2. Contains at least one recognized field from the interface
|
|
76
|
+
* 3. All recognized fields that exist have object values (not primitives)
|
|
77
|
+
*
|
|
78
|
+
* @param opts - Unknown value to validate
|
|
79
|
+
* @returns True if opts is a valid ConstructiveOptions object
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* if (isConstructiveOptions(unknownConfig)) {
|
|
84
|
+
* // TypeScript knows unknownConfig is ConstructiveOptions
|
|
85
|
+
* const { pg, server } = unknownConfig;
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
function isConstructiveOptions(opts) {
|
|
90
|
+
if (opts === null || opts === undefined) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
if (typeof opts !== 'object') {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const obj = opts;
|
|
97
|
+
// Check for at least one recognized field from the interface
|
|
98
|
+
const hasRecognizedField = RECOGNIZED_FIELDS.some((field) => field in obj);
|
|
99
|
+
if (!hasRecognizedField) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
// Validate that recognized fields have object values (not primitives)
|
|
103
|
+
for (const field of RECOGNIZED_FIELDS) {
|
|
104
|
+
if (field in obj && obj[field] !== undefined && obj[field] !== null) {
|
|
105
|
+
if (typeof obj[field] !== 'object') {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Type guard to check if an object has PostgreSQL configuration
|
|
114
|
+
*
|
|
115
|
+
* @param opts - Unknown value to check
|
|
116
|
+
* @returns True if opts has a defined pg property
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* if (hasPgConfig(config)) {
|
|
121
|
+
* console.log(config.pg.host);
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
function hasPgConfig(opts) {
|
|
126
|
+
if (opts === null || opts === undefined || typeof opts !== 'object') {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return 'pg' in opts && opts.pg !== undefined;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Type guard to check if an object has HTTP server configuration
|
|
133
|
+
*
|
|
134
|
+
* @param opts - Unknown value to check
|
|
135
|
+
* @returns True if opts has a defined server property
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* if (hasServerConfig(config)) {
|
|
140
|
+
* console.log(config.server.port);
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
function hasServerConfig(opts) {
|
|
145
|
+
if (opts === null || opts === undefined || typeof opts !== 'object') {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return 'server' in opts && opts.server !== undefined;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Type guard to check if an object has API configuration
|
|
152
|
+
*
|
|
153
|
+
* @param opts - Unknown value to check
|
|
154
|
+
* @returns True if opts has a defined api property
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* if (hasApiConfig(config)) {
|
|
159
|
+
* console.log(config.api.exposedSchemas);
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
function hasApiConfig(opts) {
|
|
164
|
+
if (opts === null || opts === undefined || typeof opts !== 'object') {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
return 'api' in opts && opts.api !== undefined;
|
|
168
|
+
}
|
|
169
|
+
// ============================================
|
|
170
|
+
// Internal Utilities
|
|
171
|
+
// ============================================
|
|
172
|
+
/**
|
|
173
|
+
* Array merge strategy that replaces arrays (source wins over target).
|
|
174
|
+
* This ensures that when a user specifies an array value, it replaces
|
|
175
|
+
* the default rather than merging/concatenating.
|
|
176
|
+
*
|
|
177
|
+
* @internal
|
|
178
|
+
*/
|
|
179
|
+
const replaceArrays = (_target, source) => source;
|
|
180
|
+
// ============================================
|
|
181
|
+
// Utility Functions
|
|
182
|
+
// ============================================
|
|
183
|
+
/**
|
|
184
|
+
* Legacy field names that indicate old configuration format
|
|
185
|
+
*/
|
|
186
|
+
const LEGACY_FIELDS = [
|
|
187
|
+
'schemas', // Old array-style schema config (should be graphile.schema)
|
|
188
|
+
'pgConfig', // Old naming (should be pg)
|
|
189
|
+
'serverPort', // Flat config (should be server.port)
|
|
190
|
+
'serverHost', // Flat config (should be server.host)
|
|
191
|
+
'dbConfig', // Old naming (should be db)
|
|
192
|
+
'postgraphile', // Old Graphile v4 naming (should be graphile)
|
|
193
|
+
'pgPool', // Direct pool config (deprecated)
|
|
194
|
+
'jwtSecret', // Flat JWT config (should be in api or auth)
|
|
195
|
+
'watchPg' // Old PostGraphile v4 option
|
|
196
|
+
];
|
|
197
|
+
/**
|
|
198
|
+
* Detects if the given options object uses a deprecated/legacy format
|
|
199
|
+
*
|
|
200
|
+
* Checks for presence of legacy field names that indicate the configuration
|
|
201
|
+
* needs to be migrated to ConstructiveOptions format.
|
|
202
|
+
*
|
|
203
|
+
* @param opts - Unknown value to check
|
|
204
|
+
* @returns True if legacy configuration patterns are detected
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```typescript
|
|
208
|
+
* if (isLegacyOptions(config)) {
|
|
209
|
+
* console.warn('Detected legacy configuration format. Please migrate to ConstructiveOptions.');
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
function isLegacyOptions(opts) {
|
|
214
|
+
if (opts === null || opts === undefined || typeof opts !== 'object') {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
const obj = opts;
|
|
218
|
+
return LEGACY_FIELDS.some((field) => field in obj);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Normalizes input to a ConstructiveOptions object with defaults applied
|
|
222
|
+
*
|
|
223
|
+
* Accepts ConstructiveOptions and returns a fully normalized object
|
|
224
|
+
* with default values applied via deep merge. User-provided values override defaults.
|
|
225
|
+
*
|
|
226
|
+
* @param opts - ConstructiveOptions to normalize
|
|
227
|
+
* @returns ConstructiveOptions with defaults filled in
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* // Partial config - missing fields filled from defaults
|
|
232
|
+
* const normalized = normalizeServerOptions({
|
|
233
|
+
* pg: { database: 'myapp' }
|
|
234
|
+
* });
|
|
235
|
+
*
|
|
236
|
+
* // normalized.pg.host === 'localhost' (from default)
|
|
237
|
+
* // normalized.pg.database === 'myapp' (from user config)
|
|
238
|
+
* // normalized.server.port === 3000 (from default)
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
function normalizeServerOptions(opts) {
|
|
242
|
+
// Deep merge with defaults - user options override defaults
|
|
243
|
+
return (0, deepmerge_1.default)(exports.serverDefaults, opts, { arrayMerge: replaceArrays });
|
|
244
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/graphql-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Constructive GraphQL Server",
|
|
6
6
|
"main": "index.js",
|
|
@@ -42,38 +42,37 @@
|
|
|
42
42
|
"backend"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@constructive-io/graphql-env": "^
|
|
46
|
-
"@constructive-io/graphql-types": "^
|
|
45
|
+
"@constructive-io/graphql-env": "^3.0.0",
|
|
46
|
+
"@constructive-io/graphql-types": "^3.0.0",
|
|
47
47
|
"@constructive-io/s3-utils": "^2.6.0",
|
|
48
48
|
"@constructive-io/upload-names": "^2.5.0",
|
|
49
49
|
"@constructive-io/url-domains": "^2.5.0",
|
|
50
|
-
"@graphile-contrib/pg-many-to-many": "
|
|
50
|
+
"@graphile-contrib/pg-many-to-many": "2.0.0-rc.1",
|
|
51
|
+
"@graphile/simplify-inflection": "8.0.0-rc.3",
|
|
51
52
|
"@pgpmjs/logger": "^2.1.0",
|
|
52
53
|
"@pgpmjs/server-utils": "^3.1.0",
|
|
53
54
|
"@pgpmjs/types": "^2.16.0",
|
|
54
55
|
"cors": "^2.8.5",
|
|
56
|
+
"deepmerge": "^4.3.1",
|
|
55
57
|
"express": "^5.2.1",
|
|
56
|
-
"gql-ast": "^
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"graphile-
|
|
60
|
-
"graphile-
|
|
61
|
-
"graphile-
|
|
62
|
-
"graphile-
|
|
63
|
-
"graphile-
|
|
64
|
-
"
|
|
65
|
-
"graphile-search-plugin": "^1.1.1",
|
|
66
|
-
"graphile-settings": "^3.1.1",
|
|
67
|
-
"graphile-simple-inflector": "^1.1.1",
|
|
68
|
-
"graphile-utils": "^4.14.1",
|
|
69
|
-
"graphql": "15.10.1",
|
|
70
|
-
"graphql-tag": "2.12.6",
|
|
58
|
+
"gql-ast": "^3.0.0",
|
|
59
|
+
"grafast": "^1.0.0-rc.4",
|
|
60
|
+
"grafserv": "^1.0.0-rc.4",
|
|
61
|
+
"graphile-build": "^5.0.0-rc.3",
|
|
62
|
+
"graphile-build-pg": "^5.0.0-rc.3",
|
|
63
|
+
"graphile-cache": "^3.0.0",
|
|
64
|
+
"graphile-config": "1.0.0-rc.3",
|
|
65
|
+
"graphile-settings": "^4.0.1",
|
|
66
|
+
"graphql": "^16.9.0",
|
|
71
67
|
"graphql-upload": "^13.0.0",
|
|
72
68
|
"lru-cache": "^11.2.4",
|
|
73
69
|
"pg": "^8.17.1",
|
|
74
|
-
"pg-cache": "^
|
|
70
|
+
"pg-cache": "^3.0.0",
|
|
71
|
+
"pg-env": "^1.4.0",
|
|
75
72
|
"pg-query-context": "^2.5.0",
|
|
76
|
-
"
|
|
73
|
+
"pg-sql2": "^5.0.0-rc.3",
|
|
74
|
+
"postgraphile": "^5.0.0-rc.4",
|
|
75
|
+
"postgraphile-plugin-connection-filter": "^3.0.0-rc.1",
|
|
77
76
|
"request-ip": "^3.3.0"
|
|
78
77
|
},
|
|
79
78
|
"devDependencies": {
|
|
@@ -83,11 +82,11 @@
|
|
|
83
82
|
"@types/graphql-upload": "^8.0.12",
|
|
84
83
|
"@types/pg": "^8.16.0",
|
|
85
84
|
"@types/request-ip": "^0.0.41",
|
|
86
|
-
"graphile-test": "
|
|
87
|
-
"makage": "^0.1.
|
|
85
|
+
"graphile-test": "4.0.0",
|
|
86
|
+
"makage": "^0.1.10",
|
|
88
87
|
"nodemon": "^3.1.10",
|
|
89
88
|
"rimraf": "^6.1.2",
|
|
90
89
|
"ts-node": "^10.9.2"
|
|
91
90
|
},
|
|
92
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "c05d6bd3dfa36690aefe21079042666dfae801a1"
|
|
93
92
|
}
|
package/schema.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { GraphileConfig } from 'graphile-config';
|
|
2
2
|
export type BuildSchemaOptions = {
|
|
3
3
|
database?: string;
|
|
4
4
|
schemas: string[];
|
|
5
|
-
graphile?: Partial<
|
|
5
|
+
graphile?: Partial<GraphileConfig.Preset>;
|
|
6
6
|
};
|
|
7
7
|
export declare function buildSchemaSDL(opts: BuildSchemaOptions): Promise<string>;
|
|
8
8
|
export declare function fetchEndpointSchemaSDL(endpoint: string, opts?: {
|
package/schema.js
CHANGED
|
@@ -37,22 +37,35 @@ exports.buildSchemaSDL = buildSchemaSDL;
|
|
|
37
37
|
exports.fetchEndpointSchemaSDL = fetchEndpointSchemaSDL;
|
|
38
38
|
const graphql_1 = require("graphql");
|
|
39
39
|
const graphile_settings_1 = require("graphile-settings");
|
|
40
|
+
const graphile_build_1 = require("graphile-build");
|
|
40
41
|
const pg_cache_1 = require("pg-cache");
|
|
41
|
-
const postgraphile_1 = require("postgraphile");
|
|
42
42
|
const http = __importStar(require("node:http"));
|
|
43
43
|
const https = __importStar(require("node:https"));
|
|
44
|
-
// Build GraphQL Schema SDL directly from Postgres using PostGraphile, without HTTP.
|
|
44
|
+
// Build GraphQL Schema SDL directly from Postgres using PostGraphile v5, without HTTP.
|
|
45
45
|
async function buildSchemaSDL(opts) {
|
|
46
46
|
const database = opts.database ?? 'constructive';
|
|
47
47
|
const schemas = Array.isArray(opts.schemas) ? opts.schemas : [];
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
// Get pool config for connection string
|
|
49
|
+
const pool = (0, pg_cache_1.getPgPool)({ database });
|
|
50
|
+
const poolConfig = pool.options || {};
|
|
51
|
+
const connectionString = `postgres://${poolConfig.user || 'postgres'}:${poolConfig.password || ''}@${poolConfig.host || 'localhost'}:${poolConfig.port || 5432}/${database}`;
|
|
52
|
+
// Build v5 preset
|
|
53
|
+
const preset = {
|
|
54
|
+
extends: [
|
|
55
|
+
graphile_settings_1.ConstructivePreset,
|
|
56
|
+
...(opts.graphile?.extends ?? []),
|
|
57
|
+
],
|
|
58
|
+
...(opts.graphile?.disablePlugins && { disablePlugins: opts.graphile.disablePlugins }),
|
|
59
|
+
...(opts.graphile?.plugins && { plugins: opts.graphile.plugins }),
|
|
60
|
+
...(opts.graphile?.schema && { schema: opts.graphile.schema }),
|
|
61
|
+
pgServices: [
|
|
62
|
+
(0, graphile_settings_1.makePgService)({
|
|
63
|
+
connectionString,
|
|
64
|
+
schemas,
|
|
65
|
+
}),
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
const { schema } = await (0, graphile_build_1.makeSchema)(preset);
|
|
56
69
|
return (0, graphql_1.printSchema)(schema);
|
|
57
70
|
}
|
|
58
71
|
// Fetch GraphQL Schema SDL from a running GraphQL endpoint via introspection.
|
package/server.d.ts
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
|
+
import type { ConstructiveOptions } from '@constructive-io/graphql-types';
|
|
1
2
|
import { PgpmOptions } from '@pgpmjs/types';
|
|
2
3
|
import type { Server as HttpServer } from 'http';
|
|
3
4
|
import { Pool, PoolClient } from 'pg';
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Creates and starts a GraphQL server instance
|
|
7
|
+
*
|
|
8
|
+
* Accepts ConstructiveOptions or PgpmOptions.
|
|
9
|
+
* Options are normalized using normalizeServerOptions to apply defaults.
|
|
10
|
+
*
|
|
11
|
+
* @param rawOpts - Server configuration options
|
|
12
|
+
* @returns void (server runs until shutdown)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // Using ConstructiveOptions (recommended)
|
|
17
|
+
* GraphQLServer({
|
|
18
|
+
* pg: { database: 'myapp' },
|
|
19
|
+
* server: { port: 4000 }
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Using PgpmOptions (backward compatible)
|
|
23
|
+
* GraphQLServer(pgpmOptions);
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const GraphQLServer: (rawOpts?: ConstructiveOptions | PgpmOptions) => void;
|
|
5
27
|
declare class Server {
|
|
6
28
|
private app;
|
|
7
29
|
private opts;
|
|
@@ -10,7 +32,7 @@ declare class Server {
|
|
|
10
32
|
private shuttingDown;
|
|
11
33
|
private closed;
|
|
12
34
|
private httpServer;
|
|
13
|
-
constructor(opts:
|
|
35
|
+
constructor(opts: ConstructiveOptions);
|
|
14
36
|
listen(): HttpServer;
|
|
15
37
|
flush(databaseId: string): Promise<void>;
|
|
16
38
|
getPool(): Pool;
|
package/server.js
CHANGED
|
@@ -18,12 +18,40 @@ const request_ip_1 = __importDefault(require("request-ip"));
|
|
|
18
18
|
const api_1 = require("./middleware/api");
|
|
19
19
|
const auth_1 = require("./middleware/auth");
|
|
20
20
|
const cors_1 = require("./middleware/cors");
|
|
21
|
+
const error_handler_1 = require("./middleware/error-handler");
|
|
22
|
+
const favicon_1 = require("./middleware/favicon");
|
|
21
23
|
const flush_1 = require("./middleware/flush");
|
|
22
24
|
const graphile_1 = require("./middleware/graphile");
|
|
25
|
+
const options_1 = require("./options");
|
|
23
26
|
const log = new logger_1.Logger('server');
|
|
24
27
|
const isDev = () => (0, graphql_env_1.getNodeEnv)() === 'development';
|
|
28
|
+
/**
|
|
29
|
+
* Creates and starts a GraphQL server instance
|
|
30
|
+
*
|
|
31
|
+
* Accepts ConstructiveOptions or PgpmOptions.
|
|
32
|
+
* Options are normalized using normalizeServerOptions to apply defaults.
|
|
33
|
+
*
|
|
34
|
+
* @param rawOpts - Server configuration options
|
|
35
|
+
* @returns void (server runs until shutdown)
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // Using ConstructiveOptions (recommended)
|
|
40
|
+
* GraphQLServer({
|
|
41
|
+
* pg: { database: 'myapp' },
|
|
42
|
+
* server: { port: 4000 }
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* // Using PgpmOptions (backward compatible)
|
|
46
|
+
* GraphQLServer(pgpmOptions);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
25
49
|
const GraphQLServer = (rawOpts = {}) => {
|
|
26
|
-
|
|
50
|
+
// Normalize options to ConstructiveOptions with defaults applied
|
|
51
|
+
const normalizedOpts = (0, options_1.normalizeServerOptions)(rawOpts);
|
|
52
|
+
// Apply environment variable overrides via getEnvOptions
|
|
53
|
+
// Cast to PgpmOptions for backward compatibility with getEnvOptions
|
|
54
|
+
const envOptions = (0, graphql_env_1.getEnvOptions)(normalizedOpts);
|
|
27
55
|
const app = new Server(envOptions);
|
|
28
56
|
app.addEventListener();
|
|
29
57
|
app.listen();
|
|
@@ -78,6 +106,7 @@ class Server {
|
|
|
78
106
|
roleName: apiOpts.roleName
|
|
79
107
|
});
|
|
80
108
|
(0, server_utils_1.healthz)(app);
|
|
109
|
+
app.use(favicon_1.favicon);
|
|
81
110
|
(0, server_utils_1.trustProxy)(app, effectiveOpts.server.trustProxy);
|
|
82
111
|
// Warn if a global CORS override is set in production
|
|
83
112
|
const fallbackOrigin = effectiveOpts.server?.origin?.trim();
|
|
@@ -99,6 +128,9 @@ class Server {
|
|
|
99
128
|
app.use(authenticate);
|
|
100
129
|
app.use((0, graphile_1.graphile)(effectiveOpts));
|
|
101
130
|
app.use(flush_1.flush);
|
|
131
|
+
// Error handling - MUST be LAST
|
|
132
|
+
app.use(error_handler_1.notFoundHandler); // Catches unmatched routes (404)
|
|
133
|
+
app.use(error_handler_1.errorHandler); // Catches all thrown errors
|
|
102
134
|
this.app = app;
|
|
103
135
|
}
|
|
104
136
|
listen() {
|
|
@@ -199,9 +231,13 @@ class Server {
|
|
|
199
231
|
static async closeCaches(opts = {}) {
|
|
200
232
|
const { closePools = false } = opts;
|
|
201
233
|
server_utils_1.svcCache.clear();
|
|
202
|
-
|
|
234
|
+
// Use closeAllCaches to properly await async disposal of PostGraphile instances
|
|
235
|
+
// before closing pg pools - this ensures all connections are released
|
|
203
236
|
if (closePools) {
|
|
204
|
-
await
|
|
237
|
+
await (0, graphile_cache_1.closeAllCaches)();
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
graphile_cache_1.graphileCache.clear();
|
|
205
241
|
}
|
|
206
242
|
}
|
|
207
243
|
log(text) {
|
package/codegen/orm/client.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ORM Client - Runtime GraphQL executor
|
|
3
|
-
* @generated by @constructive-io/graphql-codegen
|
|
4
|
-
* DO NOT EDIT - changes will be overwritten
|
|
5
|
-
*/
|
|
6
|
-
export interface OrmClientConfig {
|
|
7
|
-
endpoint: string;
|
|
8
|
-
headers?: Record<string, string>;
|
|
9
|
-
}
|
|
10
|
-
export interface GraphQLError {
|
|
11
|
-
message: string;
|
|
12
|
-
locations?: {
|
|
13
|
-
line: number;
|
|
14
|
-
column: number;
|
|
15
|
-
}[];
|
|
16
|
-
path?: (string | number)[];
|
|
17
|
-
extensions?: Record<string, unknown>;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Error thrown when GraphQL request fails
|
|
21
|
-
*/
|
|
22
|
-
export declare class GraphQLRequestError extends Error {
|
|
23
|
-
readonly errors: GraphQLError[];
|
|
24
|
-
readonly data: unknown;
|
|
25
|
-
constructor(errors: GraphQLError[], data?: unknown);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Discriminated union for query results
|
|
29
|
-
* Use .ok to check success, or use .unwrap() to get data or throw
|
|
30
|
-
*/
|
|
31
|
-
export type QueryResult<T> = {
|
|
32
|
-
ok: true;
|
|
33
|
-
data: T;
|
|
34
|
-
errors: undefined;
|
|
35
|
-
} | {
|
|
36
|
-
ok: false;
|
|
37
|
-
data: null;
|
|
38
|
-
errors: GraphQLError[];
|
|
39
|
-
};
|
|
40
|
-
/**
|
|
41
|
-
* Legacy QueryResult type for backwards compatibility
|
|
42
|
-
* @deprecated Use QueryResult discriminated union instead
|
|
43
|
-
*/
|
|
44
|
-
export interface LegacyQueryResult<T> {
|
|
45
|
-
data: T | null;
|
|
46
|
-
errors?: GraphQLError[];
|
|
47
|
-
}
|
|
48
|
-
export declare class OrmClient {
|
|
49
|
-
private endpoint;
|
|
50
|
-
private headers;
|
|
51
|
-
constructor(config: OrmClientConfig);
|
|
52
|
-
execute<T>(document: string, variables?: Record<string, unknown>): Promise<QueryResult<T>>;
|
|
53
|
-
setHeaders(headers: Record<string, string>): void;
|
|
54
|
-
getEndpoint(): string;
|
|
55
|
-
}
|
package/codegen/orm/client.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* ORM Client - Runtime GraphQL executor
|
|
4
|
-
* @generated by @constructive-io/graphql-codegen
|
|
5
|
-
* DO NOT EDIT - changes will be overwritten
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.OrmClient = exports.GraphQLRequestError = void 0;
|
|
9
|
-
/**
|
|
10
|
-
* Error thrown when GraphQL request fails
|
|
11
|
-
*/
|
|
12
|
-
class GraphQLRequestError extends Error {
|
|
13
|
-
errors;
|
|
14
|
-
data;
|
|
15
|
-
constructor(errors, data = null) {
|
|
16
|
-
const messages = errors.map((e) => e.message).join('; ');
|
|
17
|
-
super(`GraphQL Error: ${messages}`);
|
|
18
|
-
this.errors = errors;
|
|
19
|
-
this.data = data;
|
|
20
|
-
this.name = 'GraphQLRequestError';
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.GraphQLRequestError = GraphQLRequestError;
|
|
24
|
-
class OrmClient {
|
|
25
|
-
endpoint;
|
|
26
|
-
headers;
|
|
27
|
-
constructor(config) {
|
|
28
|
-
this.endpoint = config.endpoint;
|
|
29
|
-
this.headers = config.headers ?? {};
|
|
30
|
-
}
|
|
31
|
-
async execute(document, variables) {
|
|
32
|
-
const response = await fetch(this.endpoint, {
|
|
33
|
-
method: 'POST',
|
|
34
|
-
headers: {
|
|
35
|
-
'Content-Type': 'application/json',
|
|
36
|
-
Accept: 'application/json',
|
|
37
|
-
...this.headers,
|
|
38
|
-
},
|
|
39
|
-
body: JSON.stringify({
|
|
40
|
-
query: document,
|
|
41
|
-
variables: variables ?? {},
|
|
42
|
-
}),
|
|
43
|
-
});
|
|
44
|
-
if (!response.ok) {
|
|
45
|
-
return {
|
|
46
|
-
ok: false,
|
|
47
|
-
data: null,
|
|
48
|
-
errors: [
|
|
49
|
-
{ message: `HTTP ${response.status}: ${response.statusText}` },
|
|
50
|
-
],
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const json = (await response.json());
|
|
54
|
-
// Return discriminated union based on presence of errors
|
|
55
|
-
if (json.errors && json.errors.length > 0) {
|
|
56
|
-
return {
|
|
57
|
-
ok: false,
|
|
58
|
-
data: null,
|
|
59
|
-
errors: json.errors,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
ok: true,
|
|
64
|
-
data: json.data,
|
|
65
|
-
errors: undefined,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
setHeaders(headers) {
|
|
69
|
-
this.headers = { ...this.headers, ...headers };
|
|
70
|
-
}
|
|
71
|
-
getEndpoint() {
|
|
72
|
-
return this.endpoint;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
exports.OrmClient = OrmClient;
|
package/codegen/orm/index.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { OrmClientConfig } from './client';
|
|
2
|
-
import { ApiModel } from './models/api';
|
|
3
|
-
import { DomainModel } from './models/domain';
|
|
4
|
-
export type { OrmClientConfig, QueryResult, GraphQLError } from './client';
|
|
5
|
-
export { GraphQLRequestError } from './client';
|
|
6
|
-
export { QueryBuilder } from './query-builder';
|
|
7
|
-
export * from './select-types';
|
|
8
|
-
/**
|
|
9
|
-
* Create an ORM client instance
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```typescript
|
|
13
|
-
* const db = createClient({
|
|
14
|
-
* endpoint: 'https://api.example.com/graphql',
|
|
15
|
-
* headers: { Authorization: 'Bearer token' },
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* // Query apis
|
|
19
|
-
* const apis = await db.api.findMany({
|
|
20
|
-
* select: { id: true, name: true },
|
|
21
|
-
* first: 10,
|
|
22
|
-
* }).execute();
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare function createClient(config: OrmClientConfig): {
|
|
26
|
-
api: ApiModel;
|
|
27
|
-
domain: DomainModel;
|
|
28
|
-
query: {
|
|
29
|
-
apiByDatabaseIdAndName: <const S extends import("./input-types").ApiSelect>(args: import("./query").ApiByDatabaseIdAndNameVariables, options?: {
|
|
30
|
-
select?: import("./select-types").DeepExact<S, import("./input-types").ApiSelect>;
|
|
31
|
-
}) => import("./query-builder").QueryBuilder<{
|
|
32
|
-
apiByDatabaseIdAndName: import("./select-types").InferSelectResult<import("./input-types").Api, S>;
|
|
33
|
-
}>;
|
|
34
|
-
};
|
|
35
|
-
mutation: {};
|
|
36
|
-
};
|