@constructive-io/graphql-server 2.10.5

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.
Files changed (54) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +89 -0
  3. package/errors/404-message.d.ts +2 -0
  4. package/errors/404-message.js +232 -0
  5. package/errors/404.d.ts +2 -0
  6. package/errors/404.js +218 -0
  7. package/errors/50x.d.ts +2 -0
  8. package/errors/50x.js +216 -0
  9. package/esm/errors/404-message.js +230 -0
  10. package/esm/errors/404.js +216 -0
  11. package/esm/errors/50x.js +214 -0
  12. package/esm/index.js +2 -0
  13. package/esm/middleware/api.js +337 -0
  14. package/esm/middleware/auth.js +68 -0
  15. package/esm/middleware/cors.js +63 -0
  16. package/esm/middleware/flush.js +49 -0
  17. package/esm/middleware/gql.js +125 -0
  18. package/esm/middleware/graphile.js +84 -0
  19. package/esm/middleware/types.js +1 -0
  20. package/esm/plugins/PublicKeySignature.js +114 -0
  21. package/esm/run.js +8 -0
  22. package/esm/schema.js +86 -0
  23. package/esm/scripts/create-bucket.js +32 -0
  24. package/esm/server.js +95 -0
  25. package/esm/types.js +1 -0
  26. package/index.d.ts +2 -0
  27. package/index.js +18 -0
  28. package/middleware/api.d.ts +6 -0
  29. package/middleware/api.js +346 -0
  30. package/middleware/auth.d.ts +4 -0
  31. package/middleware/auth.js +75 -0
  32. package/middleware/cors.d.ts +14 -0
  33. package/middleware/cors.js +70 -0
  34. package/middleware/flush.d.ts +5 -0
  35. package/middleware/flush.js +54 -0
  36. package/middleware/gql.d.ts +6 -0
  37. package/middleware/gql.js +131 -0
  38. package/middleware/graphile.d.ts +4 -0
  39. package/middleware/graphile.js +91 -0
  40. package/middleware/types.d.ts +33 -0
  41. package/middleware/types.js +2 -0
  42. package/package.json +88 -0
  43. package/plugins/PublicKeySignature.d.ts +11 -0
  44. package/plugins/PublicKeySignature.js +121 -0
  45. package/run.d.ts +2 -0
  46. package/run.js +10 -0
  47. package/schema.d.ts +12 -0
  48. package/schema.js +123 -0
  49. package/scripts/create-bucket.d.ts +1 -0
  50. package/scripts/create-bucket.js +34 -0
  51. package/server.d.ts +17 -0
  52. package/server.js +102 -0
  53. package/types.d.ts +85 -0
  54. package/types.js +2 -0
@@ -0,0 +1,346 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getApiConfig = exports.createApiMiddleware = exports.getSubdomain = void 0;
7
+ const graphql_env_1 = require("@constructive-io/graphql-env");
8
+ const server_utils_1 = require("@pgpmjs/server-utils");
9
+ const graphile_query_1 = require("graphile-query");
10
+ const graphile_settings_1 = require("graphile-settings");
11
+ const pg_cache_1 = require("pg-cache");
12
+ const _50x_1 = __importDefault(require("../errors/50x"));
13
+ const _404_message_1 = __importDefault(require("../errors/404-message"));
14
+ const gql_1 = require("./gql");
15
+ require("./types"); // for Request type
16
+ const transformServiceToApi = (svc) => {
17
+ const api = svc.data.api;
18
+ const schemaNames = api.schemaNamesFromExt?.nodes?.map((n) => n.schemaName) || [];
19
+ const additionalSchemas = api.schemaNames?.nodes?.map((n) => n.schemaName) || [];
20
+ let domains = [];
21
+ if (api.database?.sites?.nodes) {
22
+ domains = api.database.sites.nodes.reduce((acc, site) => {
23
+ if (site.domains?.nodes && site.domains.nodes.length) {
24
+ const siteUrls = site.domains.nodes.map((domain) => {
25
+ const hostname = domain.subdomain
26
+ ? `${domain.subdomain}.${domain.domain}`
27
+ : domain.domain;
28
+ const protocol = domain.domain === 'localhost' ? 'http://' : 'https://';
29
+ return protocol + hostname;
30
+ });
31
+ return [...acc, ...siteUrls];
32
+ }
33
+ return acc;
34
+ }, []);
35
+ }
36
+ return {
37
+ dbname: api.dbname,
38
+ anonRole: api.anonRole,
39
+ roleName: api.roleName,
40
+ schema: [...schemaNames, ...additionalSchemas],
41
+ apiModules: api.apiModules?.nodes?.map((node) => ({
42
+ name: node.name,
43
+ data: node.data,
44
+ })) || [],
45
+ rlsModule: api.rlsModule,
46
+ domains,
47
+ databaseId: api.databaseId,
48
+ isPublic: api.isPublic,
49
+ };
50
+ };
51
+ const getPortFromRequest = (req) => {
52
+ const host = req.headers.host;
53
+ if (!host)
54
+ return null;
55
+ const parts = host.split(':');
56
+ return parts.length === 2 ? `:${parts[1]}` : null;
57
+ };
58
+ const getSubdomain = (reqDomains) => {
59
+ const names = reqDomains.filter((name) => !['www'].includes(name));
60
+ return !names.length ? null : names.join('.');
61
+ };
62
+ exports.getSubdomain = getSubdomain;
63
+ const createApiMiddleware = (opts) => {
64
+ return async (req, res, next) => {
65
+ if (opts.api?.enableMetaApi === false) {
66
+ const schemas = opts.api.exposedSchemas;
67
+ const anonRole = opts.api.anonRole;
68
+ const roleName = opts.api.roleName;
69
+ const databaseId = opts.api.defaultDatabaseId;
70
+ const api = {
71
+ dbname: opts.pg?.database ?? '',
72
+ anonRole,
73
+ roleName,
74
+ schema: schemas,
75
+ apiModules: [],
76
+ domains: [],
77
+ databaseId,
78
+ isPublic: false,
79
+ };
80
+ req.api = api;
81
+ req.databaseId = databaseId;
82
+ return next();
83
+ }
84
+ try {
85
+ const svc = await (0, exports.getApiConfig)(opts, req);
86
+ if (svc?.errorHtml) {
87
+ res
88
+ .status(404)
89
+ .send((0, _404_message_1.default)('API not found', svc.errorHtml));
90
+ return;
91
+ }
92
+ else if (!svc) {
93
+ res
94
+ .status(404)
95
+ .send((0, _404_message_1.default)('API service not found for the given domain/subdomain.'));
96
+ return;
97
+ }
98
+ const api = transformServiceToApi(svc);
99
+ req.api = api;
100
+ req.databaseId = api.databaseId;
101
+ next();
102
+ }
103
+ catch (e) {
104
+ if (e.code === 'NO_VALID_SCHEMAS') {
105
+ res.status(404).send((0, _404_message_1.default)(e.message));
106
+ }
107
+ else if (e.message.match(/does not exist/)) {
108
+ res
109
+ .status(404)
110
+ .send((0, _404_message_1.default)("The resource you're looking for does not exist."));
111
+ }
112
+ else {
113
+ console.error(e);
114
+ res.status(500).send(_50x_1.default);
115
+ }
116
+ }
117
+ };
118
+ };
119
+ exports.createApiMiddleware = createApiMiddleware;
120
+ const getHardCodedSchemata = ({ opts, schemata, databaseId, key, }) => {
121
+ const svc = {
122
+ data: {
123
+ api: {
124
+ databaseId,
125
+ isPublic: false,
126
+ dbname: opts.pg.database,
127
+ anonRole: 'administrator',
128
+ roleName: 'administrator',
129
+ schemaNamesFromExt: {
130
+ nodes: schemata
131
+ .split(',')
132
+ .map((schema) => schema.trim())
133
+ .map((schemaName) => ({ schemaName })),
134
+ },
135
+ schemaNames: { nodes: [] },
136
+ apiModules: [],
137
+ },
138
+ },
139
+ };
140
+ server_utils_1.svcCache.set(key, svc);
141
+ return svc;
142
+ };
143
+ const getMetaSchema = ({ opts, key, databaseId, }) => {
144
+ const apiOpts = opts.api || {};
145
+ const schemata = apiOpts.metaSchemas || [];
146
+ const svc = {
147
+ data: {
148
+ api: {
149
+ databaseId,
150
+ isPublic: false,
151
+ dbname: opts.pg.database,
152
+ anonRole: 'administrator',
153
+ roleName: 'administrator',
154
+ schemaNamesFromExt: {
155
+ nodes: schemata.map((schemaName) => ({ schemaName })),
156
+ },
157
+ schemaNames: { nodes: [] },
158
+ apiModules: [],
159
+ },
160
+ },
161
+ };
162
+ server_utils_1.svcCache.set(key, svc);
163
+ return svc;
164
+ };
165
+ const queryServiceByDomainAndSubdomain = async ({ opts, key, client, domain, subdomain, }) => {
166
+ const result = await client.query({
167
+ role: 'administrator',
168
+ query: gql_1.ApiQuery,
169
+ variables: { domain, subdomain },
170
+ });
171
+ if (result.errors?.length) {
172
+ console.error(result.errors);
173
+ return null;
174
+ }
175
+ const nodes = result?.data?.domains?.nodes;
176
+ if (nodes?.length) {
177
+ const data = nodes[0];
178
+ const apiPublic = opts.api?.isPublic;
179
+ if (!data.api || data.api.isPublic !== apiPublic)
180
+ return null;
181
+ const svc = { data };
182
+ server_utils_1.svcCache.set(key, svc);
183
+ return svc;
184
+ }
185
+ return null;
186
+ };
187
+ const queryServiceByApiName = async ({ opts, key, client, databaseId, name, }) => {
188
+ const result = await client.query({
189
+ role: 'administrator',
190
+ query: gql_1.ApiByNameQuery,
191
+ variables: { databaseId, name },
192
+ });
193
+ if (result.errors?.length) {
194
+ console.error(result.errors);
195
+ return null;
196
+ }
197
+ const data = result?.data;
198
+ const apiPublic = opts.api?.isPublic;
199
+ if (data?.api && data.api.isPublic === apiPublic) {
200
+ const svc = { data };
201
+ server_utils_1.svcCache.set(key, svc);
202
+ return svc;
203
+ }
204
+ return null;
205
+ };
206
+ const getSvcKey = (opts, req) => {
207
+ const domain = req.urlDomains.domain;
208
+ const key = req.urlDomains.subdomains
209
+ .filter((name) => !['www'].includes(name))
210
+ .concat(domain)
211
+ .join('.');
212
+ const apiPublic = opts.api?.isPublic;
213
+ if (apiPublic === false) {
214
+ if (req.get('X-Api-Name')) {
215
+ return 'api:' + req.get('X-Database-Id') + ':' + req.get('X-Api-Name');
216
+ }
217
+ if (req.get('X-Schemata')) {
218
+ return ('schemata:' + req.get('X-Database-Id') + ':' + req.get('X-Schemata'));
219
+ }
220
+ if (req.get('X-Meta-Schema')) {
221
+ return 'metaschema:api:' + req.get('X-Database-Id');
222
+ }
223
+ }
224
+ return key;
225
+ };
226
+ const validateSchemata = async (pool, schemata) => {
227
+ const result = await pool.query(`SELECT schema_name FROM information_schema.schemata WHERE schema_name = ANY($1::text[])`, [schemata]);
228
+ return result.rows.map((row) => row.schema_name);
229
+ };
230
+ const getApiConfig = async (opts, req) => {
231
+ const rootPgPool = (0, pg_cache_1.getPgPool)(opts.pg);
232
+ // @ts-ignore
233
+ const subdomain = (0, exports.getSubdomain)(req.urlDomains.subdomains);
234
+ const domain = req.urlDomains.domain;
235
+ const key = getSvcKey(opts, req);
236
+ req.svc_key = key;
237
+ let svc;
238
+ if (server_utils_1.svcCache.has(key)) {
239
+ svc = server_utils_1.svcCache.get(key);
240
+ }
241
+ else {
242
+ const apiOpts = opts.api || {};
243
+ const allSchemata = apiOpts.metaSchemas || [];
244
+ const validatedSchemata = await validateSchemata(rootPgPool, allSchemata);
245
+ if (validatedSchemata.length === 0) {
246
+ const message = `No valid schemas found for domain: ${domain}, subdomain: ${subdomain}`;
247
+ const error = new Error(message);
248
+ error.code = 'NO_VALID_SCHEMAS';
249
+ throw error;
250
+ }
251
+ const settings = (0, graphile_settings_1.getGraphileSettings)({
252
+ graphile: {
253
+ schema: validatedSchemata,
254
+ },
255
+ });
256
+ // @ts-ignore
257
+ const schema = await (0, graphile_query_1.getSchema)(rootPgPool, settings);
258
+ // @ts-ignore
259
+ const client = new graphile_query_1.GraphileQuery({ schema, pool: rootPgPool, settings });
260
+ const apiPublic = opts.api?.isPublic;
261
+ if (apiPublic === false) {
262
+ if (req.get('X-Schemata')) {
263
+ svc = getHardCodedSchemata({
264
+ opts,
265
+ key,
266
+ schemata: req.get('X-Schemata'),
267
+ databaseId: req.get('X-Database-Id'),
268
+ });
269
+ }
270
+ else if (req.get('X-Api-Name')) {
271
+ svc = await queryServiceByApiName({
272
+ opts,
273
+ key,
274
+ client,
275
+ name: req.get('X-Api-Name'),
276
+ databaseId: req.get('X-Database-Id'),
277
+ });
278
+ }
279
+ else if (req.get('X-Meta-Schema')) {
280
+ svc = getMetaSchema({
281
+ opts,
282
+ key,
283
+ databaseId: req.get('X-Database-Id'),
284
+ });
285
+ }
286
+ else {
287
+ svc = await queryServiceByDomainAndSubdomain({
288
+ opts,
289
+ key,
290
+ client,
291
+ domain,
292
+ subdomain,
293
+ });
294
+ }
295
+ }
296
+ else {
297
+ svc = await queryServiceByDomainAndSubdomain({
298
+ opts,
299
+ key,
300
+ client,
301
+ domain,
302
+ subdomain,
303
+ });
304
+ if (!svc) {
305
+ if ((0, graphql_env_1.getNodeEnv)() === 'development') {
306
+ // TODO ONLY DO THIS IN DEV MODE
307
+ const fallbackResult = await client.query({
308
+ role: 'administrator',
309
+ // @ts-ignore
310
+ query: gql_1.ListOfAllDomainsOfDb,
311
+ // variables: { databaseId }
312
+ });
313
+ if (!fallbackResult.errors?.length &&
314
+ fallbackResult.data?.apis?.nodes?.length) {
315
+ const port = getPortFromRequest(req);
316
+ const allDomains = fallbackResult.data.apis.nodes.flatMap((api) => api.domains.nodes.map((d) => ({
317
+ domain: d.domain,
318
+ subdomain: d.subdomain,
319
+ href: d.subdomain
320
+ ? `http://${d.subdomain}.${d.domain}${port}/graphiql`
321
+ : `http://${d.domain}${port}/graphiql`,
322
+ })));
323
+ const linksHtml = allDomains.length
324
+ ? `<ul class="mt-4 pl-5 list-disc space-y-1">` +
325
+ allDomains
326
+ .map((d) => `<li><a href="${d.href}" class="text-brand hover:underline">${d.href}</a></li>`)
327
+ .join('') +
328
+ `</ul>`
329
+ : `<p class="text-gray-600">No APIs are currently registered for this database.</p>`;
330
+ const errorHtml = `
331
+ <p class="text-sm text-gray-700">Try some of these:</p>
332
+ <div class="mt-4">
333
+ ${linksHtml}
334
+ </div>
335
+ `.trim();
336
+ return {
337
+ errorHtml,
338
+ };
339
+ }
340
+ }
341
+ }
342
+ }
343
+ }
344
+ return svc;
345
+ };
346
+ exports.getApiConfig = getApiConfig;
@@ -0,0 +1,4 @@
1
+ import { PgpmOptions } from '@pgpmjs/types';
2
+ import { RequestHandler } from 'express';
3
+ import './types';
4
+ export declare const createAuthenticateMiddleware: (opts: PgpmOptions) => RequestHandler;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createAuthenticateMiddleware = void 0;
7
+ const pg_cache_1 = require("pg-cache");
8
+ const pg_query_context_1 = __importDefault(require("pg-query-context"));
9
+ require("./types"); // for Request type
10
+ const createAuthenticateMiddleware = (opts) => {
11
+ return async (req, res, next) => {
12
+ const api = req.api;
13
+ if (!api) {
14
+ res.status(500).send('Missing API info');
15
+ return;
16
+ }
17
+ const pool = (0, pg_cache_1.getPgPool)({
18
+ ...opts.pg,
19
+ database: api.dbname,
20
+ });
21
+ const rlsModule = api.rlsModule;
22
+ if (!rlsModule)
23
+ return next();
24
+ const authFn = opts.server.strictAuth
25
+ ? rlsModule.authenticateStrict
26
+ : rlsModule.authenticate;
27
+ if (authFn && rlsModule.privateSchema.schemaName) {
28
+ const { authorization = '' } = req.headers;
29
+ const [authType, authToken] = authorization.split(' ');
30
+ let token = {};
31
+ if (authType?.toLowerCase() === 'bearer' && authToken) {
32
+ const context = {
33
+ 'jwt.claims.ip_address': req.clientIp,
34
+ };
35
+ if (req.get('origin')) {
36
+ context['jwt.claims.origin'] = req.get('origin');
37
+ }
38
+ if (req.get('User-Agent')) {
39
+ context['jwt.claims.user_agent'] = req.get('User-Agent');
40
+ }
41
+ try {
42
+ const result = await (0, pg_query_context_1.default)({
43
+ client: pool,
44
+ context,
45
+ query: `SELECT * FROM "${rlsModule.privateSchema.schemaName}"."${authFn}"($1)`,
46
+ variables: [authToken],
47
+ });
48
+ if (result?.rowCount === 0) {
49
+ res.status(200).json({
50
+ errors: [{ extensions: { code: 'UNAUTHENTICATED' } }],
51
+ });
52
+ return;
53
+ }
54
+ token = result.rows[0];
55
+ }
56
+ catch (e) {
57
+ res.status(200).json({
58
+ errors: [
59
+ {
60
+ extensions: {
61
+ code: 'BAD_TOKEN_DEFINITION',
62
+ message: e.message,
63
+ },
64
+ },
65
+ ],
66
+ });
67
+ return;
68
+ }
69
+ }
70
+ req.token = token;
71
+ }
72
+ next();
73
+ };
74
+ };
75
+ exports.createAuthenticateMiddleware = createAuthenticateMiddleware;
@@ -0,0 +1,14 @@
1
+ import type { RequestHandler } from 'express';
2
+ import './types';
3
+ /**
4
+ * Unified CORS middleware for Constructive API
5
+ *
6
+ * Feature parity + compatibility:
7
+ * - Respects a global fallback origin (e.g. from env/CLI) for quick overrides.
8
+ * - Preserves multi-tenant, per-API CORS via meta schema ('cors' module + domains).
9
+ * - Always allows localhost to ease development.
10
+ *
11
+ * Usage:
12
+ * app.use(cors(fallbackOrigin));
13
+ */
14
+ export declare const cors: (fallbackOrigin?: string) => RequestHandler;
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cors = void 0;
7
+ const url_domains_1 = require("@constructive-io/url-domains");
8
+ const cors_1 = __importDefault(require("cors"));
9
+ require("./types"); // for Request type
10
+ /**
11
+ * Unified CORS middleware for Constructive API
12
+ *
13
+ * Feature parity + compatibility:
14
+ * - Respects a global fallback origin (e.g. from env/CLI) for quick overrides.
15
+ * - Preserves multi-tenant, per-API CORS via meta schema ('cors' module + domains).
16
+ * - Always allows localhost to ease development.
17
+ *
18
+ * Usage:
19
+ * app.use(cors(fallbackOrigin));
20
+ */
21
+ const cors = (fallbackOrigin) => {
22
+ // Use the cors library's dynamic origin function to decide per request
23
+ const dynamicOrigin = (origin, callback, req) => {
24
+ // 1) Global fallback (fast path)
25
+ if (fallbackOrigin && fallbackOrigin.trim().length) {
26
+ if (fallbackOrigin.trim() === '*') {
27
+ // Reflect whatever Origin the caller sent
28
+ return callback(null, true);
29
+ }
30
+ if (origin && origin.trim() === fallbackOrigin.trim()) {
31
+ return callback(null, true);
32
+ }
33
+ // If a strict fallback origin is provided and does not match,
34
+ // continue to per-API checks below (do not immediately deny).
35
+ }
36
+ // 2) Per-API allowlist sourced from req.api (if available)
37
+ // createApiMiddleware runs before this in server.ts, so req.api should be set
38
+ const api = req.api;
39
+ if (api) {
40
+ const corsModules = (api.apiModules || []).filter((m) => m.name === 'cors');
41
+ const siteUrls = api.domains || [];
42
+ const listOfDomains = corsModules.reduce((m, mod) => [...mod.data.urls, ...m], siteUrls);
43
+ if (origin && listOfDomains.includes(origin)) {
44
+ return callback(null, true);
45
+ }
46
+ }
47
+ // 3) Localhost is always allowed
48
+ if (origin) {
49
+ try {
50
+ const parsed = (0, url_domains_1.parseUrl)(new URL(origin));
51
+ if (parsed.domain === 'localhost') {
52
+ return callback(null, true);
53
+ }
54
+ }
55
+ catch {
56
+ // ignore invalid origin
57
+ }
58
+ }
59
+ // Default: not allowed
60
+ return callback(null, false);
61
+ };
62
+ // Wrap in the cors plugin with our dynamic origin resolver
63
+ const handler = (req, res, next) => (0, cors_1.default)({
64
+ origin: (reqOrigin, cb) => dynamicOrigin(reqOrigin, cb, req),
65
+ credentials: true,
66
+ optionsSuccessStatus: 200,
67
+ })(req, res, next);
68
+ return handler;
69
+ };
70
+ exports.cors = cors;
@@ -0,0 +1,5 @@
1
+ import { ConstructiveOptions } from '@constructive-io/graphql-types';
2
+ import { NextFunction, Request, Response } from 'express';
3
+ import './types';
4
+ export declare const flush: (req: Request, res: Response, next: NextFunction) => Promise<void>;
5
+ export declare const flushService: (opts: ConstructiveOptions, databaseId: string) => Promise<void>;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flushService = exports.flush = void 0;
4
+ const logger_1 = require("@pgpmjs/logger");
5
+ const server_utils_1 = require("@pgpmjs/server-utils");
6
+ const graphile_cache_1 = require("graphile-cache");
7
+ const pg_cache_1 = require("pg-cache");
8
+ require("./types"); // for Request type
9
+ const log = new logger_1.Logger('flush');
10
+ const flush = async (req, res, next) => {
11
+ if (req.url === '/flush') {
12
+ // TODO: check bearer for a flush / special key
13
+ graphile_cache_1.graphileCache.delete(req.svc_key);
14
+ server_utils_1.svcCache.delete(req.svc_key);
15
+ res.status(200).send('OK');
16
+ return;
17
+ }
18
+ return next();
19
+ };
20
+ exports.flush = flush;
21
+ const flushService = async (opts, databaseId) => {
22
+ const pgPool = (0, pg_cache_1.getPgPool)(opts.pg);
23
+ log.info('flushing db ' + databaseId);
24
+ const api = new RegExp(`^api:${databaseId}:.*`);
25
+ const schemata = new RegExp(`^schemata:${databaseId}:.*`);
26
+ const meta = new RegExp(`^metaschema:api:${databaseId}`);
27
+ if (!opts.api.isPublic) {
28
+ graphile_cache_1.graphileCache.forEach((_, k) => {
29
+ if (api.test(k) || schemata.test(k) || meta.test(k)) {
30
+ graphile_cache_1.graphileCache.delete(k);
31
+ server_utils_1.svcCache.delete(k);
32
+ }
33
+ });
34
+ }
35
+ const svc = await pgPool.query(`SELECT *
36
+ FROM meta_public.domains
37
+ WHERE database_id = $1`, [databaseId]);
38
+ if (svc.rowCount === 0)
39
+ return;
40
+ for (const row of svc.rows) {
41
+ let key;
42
+ if (row.domain && !row.subdomain) {
43
+ key = row.domain;
44
+ }
45
+ else if (row.domain && row.subdomain) {
46
+ key = `${row.subdomain}.${row.domain}`;
47
+ }
48
+ if (key) {
49
+ graphile_cache_1.graphileCache.delete(key);
50
+ server_utils_1.svcCache.delete(key);
51
+ }
52
+ }
53
+ };
54
+ exports.flushService = flushService;
@@ -0,0 +1,6 @@
1
+ import gql from 'graphql-tag';
2
+ type GraphQLDocument = ReturnType<typeof gql>;
3
+ export declare const ApiQuery: GraphQLDocument;
4
+ export declare const ApiByNameQuery: GraphQLDocument;
5
+ export declare const ListOfAllDomainsOfDb: GraphQLDocument;
6
+ export {};