@constructive-io/graphql-server 5.0.4 → 5.1.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/esm/middleware/api.js +49 -157
- package/esm/middleware/flush.js +4 -10
- package/esm/middleware/graphile.js +24 -23
- package/esm/middleware/routing.js +9 -10
- package/esm/server.js +16 -15
- package/middleware/api.d.ts +1 -1
- package/middleware/api.js +49 -157
- package/middleware/flush.d.ts +1 -1
- package/middleware/flush.js +4 -10
- package/middleware/graphile.d.ts +1 -1
- package/middleware/graphile.js +24 -23
- package/middleware/routing.d.ts +5 -6
- package/middleware/routing.js +9 -10
- package/package.json +14 -14
- package/server.js +15 -14
package/middleware/routing.d.ts
CHANGED
|
@@ -23,14 +23,13 @@ export interface ResolvedRoute {
|
|
|
23
23
|
* Resolve a hostname through the compiled scoped-routing plane (host-only:
|
|
24
24
|
* path/method routing belongs to Traefik/Ingress, not the server).
|
|
25
25
|
* Returns null when there is no match (route_binding_id IS NULL) or when the
|
|
26
|
-
* resolver is not installed in the target database —
|
|
27
|
-
*
|
|
26
|
+
* resolver is not installed in the target database — in both cases the caller
|
|
27
|
+
* treats it as a hard no-match (→ 404); there is no legacy fallback.
|
|
28
28
|
*/
|
|
29
29
|
export declare const resolveRoute: (pool: Pool, schema: string, host: string) => Promise<ResolvedRoute | null>;
|
|
30
30
|
/**
|
|
31
|
-
* Map a resolved api-target route onto the
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* caller falls back to the legacy lookup.
|
|
31
|
+
* Map a resolved api-target route onto the ApiStructure shape consumed by the
|
|
32
|
+
* rest of the middleware chain. Returns null when the route target is not an
|
|
33
|
+
* api surface or its resolved_config lacks the api essentials (→ 404).
|
|
35
34
|
*/
|
|
36
35
|
export declare const routeToApiStructure: (route: ResolvedRoute, opts: ApiOptions) => ApiStructure | null;
|
package/middleware/routing.js
CHANGED
|
@@ -9,8 +9,8 @@ const isValidSchemaName = (name) => /^[a-z_][a-z0-9_]*$/.test(name);
|
|
|
9
9
|
* Resolve a hostname through the compiled scoped-routing plane (host-only:
|
|
10
10
|
* path/method routing belongs to Traefik/Ingress, not the server).
|
|
11
11
|
* Returns null when there is no match (route_binding_id IS NULL) or when the
|
|
12
|
-
* resolver is not installed in the target database —
|
|
13
|
-
*
|
|
12
|
+
* resolver is not installed in the target database — in both cases the caller
|
|
13
|
+
* treats it as a hard no-match (→ 404); there is no legacy fallback.
|
|
14
14
|
*/
|
|
15
15
|
const resolveRoute = async (pool, schema, host) => {
|
|
16
16
|
if (!isValidSchemaName(schema)) {
|
|
@@ -29,9 +29,9 @@ const resolveRoute = async (pool, schema, host) => {
|
|
|
29
29
|
catch (error) {
|
|
30
30
|
const err = error;
|
|
31
31
|
// 42883 undefined_function / 3F000 invalid_schema_name: resolver not
|
|
32
|
-
// installed in this database — treat as no-match
|
|
32
|
+
// installed in this database — treat as a hard no-match.
|
|
33
33
|
if (err.code === '42883' || err.code === '3F000') {
|
|
34
|
-
log.debug(`[resolve-route] resolver not installed (${err.code});
|
|
34
|
+
log.debug(`[resolve-route] resolver not installed (${err.code}); no match`);
|
|
35
35
|
return null;
|
|
36
36
|
}
|
|
37
37
|
throw error;
|
|
@@ -39,10 +39,9 @@ const resolveRoute = async (pool, schema, host) => {
|
|
|
39
39
|
};
|
|
40
40
|
exports.resolveRoute = resolveRoute;
|
|
41
41
|
/**
|
|
42
|
-
* Map a resolved api-target route onto the
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* caller falls back to the legacy lookup.
|
|
42
|
+
* Map a resolved api-target route onto the ApiStructure shape consumed by the
|
|
43
|
+
* rest of the middleware chain. Returns null when the route target is not an
|
|
44
|
+
* api surface or its resolved_config lacks the api essentials (→ 404).
|
|
46
45
|
*/
|
|
47
46
|
const routeToApiStructure = (route, opts) => {
|
|
48
47
|
if (route.target_module !== 'apis' && route.target_module !== 'api') {
|
|
@@ -50,7 +49,7 @@ const routeToApiStructure = (route, opts) => {
|
|
|
50
49
|
}
|
|
51
50
|
const config = (route.resolved_config ?? {});
|
|
52
51
|
if (!config.dbname || !config.schemas?.length) {
|
|
53
|
-
log.debug('[resolve-route] api target missing dbname/schemas in resolved_config;
|
|
52
|
+
log.debug('[resolve-route] api target missing dbname/schemas in resolved_config; no match');
|
|
54
53
|
return null;
|
|
55
54
|
}
|
|
56
55
|
return {
|
|
@@ -62,7 +61,7 @@ const routeToApiStructure = (route, opts) => {
|
|
|
62
61
|
apiModules: [],
|
|
63
62
|
domains: [],
|
|
64
63
|
databaseId: config.database_id,
|
|
65
|
-
isPublic: config.is_public ?? (opts.api?.isPublic ?? false)
|
|
64
|
+
isPublic: config.is_public ?? (opts.api?.isPublic ?? false)
|
|
66
65
|
};
|
|
67
66
|
};
|
|
68
67
|
exports.routeToApiStructure = routeToApiStructure;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constructive-io/graphql-server",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "Constructive GraphQL Server",
|
|
6
6
|
"main": "index.js",
|
|
@@ -42,18 +42,18 @@
|
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@constructive-io/csrf": "^0.17.0",
|
|
45
|
-
"@constructive-io/express-context": "^0.
|
|
46
|
-
"@constructive-io/graphql-env": "^3.
|
|
47
|
-
"@constructive-io/graphql-types": "^3.
|
|
45
|
+
"@constructive-io/express-context": "^0.13.0",
|
|
46
|
+
"@constructive-io/graphql-env": "^3.17.0",
|
|
47
|
+
"@constructive-io/graphql-types": "^3.16.0",
|
|
48
48
|
"@constructive-io/query-builder": "^3.0.1",
|
|
49
49
|
"@constructive-io/s3-utils": "^2.20.0",
|
|
50
50
|
"@constructive-io/url-domains": "^2.19.0",
|
|
51
51
|
"@graphile-contrib/pg-many-to-many": "2.0.0-rc.2",
|
|
52
|
-
"@pgpmjs/env": "^2.
|
|
52
|
+
"@pgpmjs/env": "^2.29.0",
|
|
53
53
|
"@pgpmjs/logger": "^2.14.0",
|
|
54
|
-
"@pgpmjs/server-utils": "^3.15.
|
|
55
|
-
"@pgpmjs/types": "^2.
|
|
56
|
-
"agentic-server": "0.11.
|
|
54
|
+
"@pgpmjs/server-utils": "^3.15.4",
|
|
55
|
+
"@pgpmjs/types": "^2.36.0",
|
|
56
|
+
"agentic-server": "0.11.3",
|
|
57
57
|
"cors": "^2.8.6",
|
|
58
58
|
"deepmerge": "^4.3.1",
|
|
59
59
|
"express": "^5.2.1",
|
|
@@ -62,16 +62,16 @@
|
|
|
62
62
|
"grafserv": "1.0.0",
|
|
63
63
|
"graphile-build": "5.0.2",
|
|
64
64
|
"graphile-build-pg": "5.0.2",
|
|
65
|
-
"graphile-cache": "^4.0.
|
|
65
|
+
"graphile-cache": "^4.0.1",
|
|
66
66
|
"graphile-config": "1.0.1",
|
|
67
|
-
"graphile-function-bindings": "^1.0.
|
|
68
|
-
"graphile-settings": "^6.0.
|
|
67
|
+
"graphile-function-bindings": "^1.0.5",
|
|
68
|
+
"graphile-settings": "^6.0.5",
|
|
69
69
|
"graphile-utils": "5.0.1",
|
|
70
70
|
"graphql": "16.13.0",
|
|
71
71
|
"graphql-upload": "^13.0.0",
|
|
72
72
|
"lru-cache": "^11.2.7",
|
|
73
73
|
"pg": "^8.21.0",
|
|
74
|
-
"pg-cache": "^3.15.
|
|
74
|
+
"pg-cache": "^3.15.3",
|
|
75
75
|
"pg-env": "^1.18.1",
|
|
76
76
|
"pg-query-context": "^2.19.0",
|
|
77
77
|
"pg-sql2": "5.0.1",
|
|
@@ -87,10 +87,10 @@
|
|
|
87
87
|
"@types/pg": "^8.20.0",
|
|
88
88
|
"@types/request-ip": "^0.0.41",
|
|
89
89
|
"cookie-parser": "^1.4.7",
|
|
90
|
-
"graphile-test": "5.0.
|
|
90
|
+
"graphile-test": "5.0.5",
|
|
91
91
|
"makage": "^0.3.0",
|
|
92
92
|
"nodemon": "^3.1.14",
|
|
93
93
|
"ts-node": "^10.9.2"
|
|
94
94
|
},
|
|
95
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "39db6d576bce7bc1de8123849f237b1695779d88"
|
|
96
96
|
}
|
package/server.js
CHANGED
|
@@ -5,37 +5,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.Server = exports.GraphQLServer = void 0;
|
|
7
7
|
const csrf_1 = require("@constructive-io/csrf");
|
|
8
|
+
const express_context_1 = require("@constructive-io/express-context");
|
|
8
9
|
const graphql_env_1 = require("@constructive-io/graphql-env");
|
|
10
|
+
const url_domains_1 = require("@constructive-io/url-domains");
|
|
9
11
|
const logger_1 = require("@pgpmjs/logger");
|
|
10
12
|
const server_utils_1 = require("@pgpmjs/server-utils");
|
|
11
|
-
const
|
|
13
|
+
const agentic_server_1 = require("agentic-server");
|
|
12
14
|
const cookie_parser_1 = __importDefault(require("cookie-parser"));
|
|
13
15
|
const express_1 = __importDefault(require("express"));
|
|
14
|
-
const graphql_upload_1 = __importDefault(require("graphql-upload"));
|
|
15
16
|
const graphile_cache_1 = require("graphile-cache");
|
|
17
|
+
const graphql_upload_1 = __importDefault(require("graphql-upload"));
|
|
16
18
|
const pg_cache_1 = require("pg-cache");
|
|
17
19
|
const request_ip_1 = __importDefault(require("request-ip"));
|
|
18
20
|
const debug_db_snapshot_1 = require("./diagnostics/debug-db-snapshot");
|
|
21
|
+
const debug_sampler_1 = require("./diagnostics/debug-sampler");
|
|
19
22
|
const observability_1 = require("./diagnostics/observability");
|
|
20
23
|
const api_1 = require("./middleware/api");
|
|
21
24
|
const auth_1 = require("./middleware/auth");
|
|
25
|
+
// Auth cookie handling is done via AuthCookiePlugin in grafserv
|
|
26
|
+
const captcha_1 = require("./middleware/captcha");
|
|
27
|
+
const cookie_1 = require("./middleware/cookie");
|
|
22
28
|
const cors_1 = require("./middleware/cors");
|
|
23
29
|
const error_handler_1 = require("./middleware/error-handler");
|
|
24
30
|
const favicon_1 = require("./middleware/favicon");
|
|
25
|
-
const fn_1 = require("./middleware/fn");
|
|
26
31
|
const flush_1 = require("./middleware/flush");
|
|
32
|
+
const fn_1 = require("./middleware/fn");
|
|
27
33
|
const graphile_1 = require("./middleware/graphile");
|
|
28
34
|
const multipart_bridge_1 = require("./middleware/multipart-bridge");
|
|
29
35
|
const debug_db_1 = require("./middleware/observability/debug-db");
|
|
30
36
|
const debug_memory_1 = require("./middleware/observability/debug-memory");
|
|
31
37
|
const guard_1 = require("./middleware/observability/guard");
|
|
32
38
|
const request_logger_1 = require("./middleware/observability/request-logger");
|
|
33
|
-
// Auth cookie handling is done via AuthCookiePlugin in grafserv
|
|
34
|
-
const captcha_1 = require("./middleware/captcha");
|
|
35
|
-
const cookie_1 = require("./middleware/cookie");
|
|
36
|
-
const agentic_server_1 = require("agentic-server");
|
|
37
|
-
const express_context_1 = require("@constructive-io/express-context");
|
|
38
|
-
const debug_sampler_1 = require("./diagnostics/debug-sampler");
|
|
39
39
|
const log = new logger_1.Logger('server');
|
|
40
40
|
/**
|
|
41
41
|
* Creates and starts a GraphQL server instance
|
|
@@ -92,12 +92,13 @@ class Server {
|
|
|
92
92
|
serverHost: effectiveOpts.server?.host,
|
|
93
93
|
serverPort: effectiveOpts.server?.port,
|
|
94
94
|
apiIsPublic: apiOpts.isPublic,
|
|
95
|
-
|
|
95
|
+
enableScopedRouting: apiOpts.enableScopedRouting,
|
|
96
|
+
scopedRoutingSchema: apiOpts.scopedRoutingSchema,
|
|
96
97
|
metaSchemas: apiOpts.metaSchemas?.join(',') || 'default',
|
|
97
98
|
exposedSchemas: apiOpts.exposedSchemas?.join(',') || 'none',
|
|
98
99
|
anonRole: apiOpts.anonRole,
|
|
99
100
|
roleName: apiOpts.roleName,
|
|
100
|
-
observabilityEnabled
|
|
101
|
+
observabilityEnabled
|
|
101
102
|
});
|
|
102
103
|
if (observabilityRequested && !observabilityEnabled) {
|
|
103
104
|
const reasons = [];
|
|
@@ -136,7 +137,7 @@ class Server {
|
|
|
136
137
|
app.use((0, cors_1.cors)(fallbackOrigin));
|
|
137
138
|
app.use('/graphql', graphql_upload_1.default.graphqlUploadExpress({
|
|
138
139
|
maxFileSize: 10 * 1024 * 1024, // 10 MB
|
|
139
|
-
maxFiles: 10
|
|
140
|
+
maxFiles: 10
|
|
140
141
|
}));
|
|
141
142
|
// Rewrite Content-Type after graphql-upload so grafserv accepts the request
|
|
142
143
|
app.use('/graphql', multipart_bridge_1.multipartBridge);
|
|
@@ -154,8 +155,8 @@ class Server {
|
|
|
154
155
|
cookieOptions: {
|
|
155
156
|
httpOnly: false, // SPA clients need to read this via document.cookie
|
|
156
157
|
secure: process.env.NODE_ENV === 'production',
|
|
157
|
-
sameSite: 'lax'
|
|
158
|
-
}
|
|
158
|
+
sameSite: 'lax'
|
|
159
|
+
}
|
|
159
160
|
});
|
|
160
161
|
const csrfProtect = (req, res, next) => {
|
|
161
162
|
// Skip CSRF for Bearer token auth
|