@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,131 @@
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.ListOfAllDomainsOfDb = exports.ApiByNameQuery = exports.ApiQuery = void 0;
7
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
+ // DO NOT CHANGE TO domainBySubdomainAndDomain(domain: $domain, subdomain: $subdomain)
9
+ // condition is the way to handle since it will pass in null properly
10
+ // e.g. subdomain.domain or domain both work
11
+ exports.ApiQuery = (0, graphql_tag_1.default) `
12
+ query ApiRoot($domain: String!, $subdomain: String) {
13
+ domains(condition: { domain: $domain, subdomain: $subdomain }) {
14
+ nodes {
15
+ api {
16
+ databaseId
17
+ dbname
18
+ roleName
19
+ anonRole
20
+ isPublic
21
+ schemaNamesFromExt: apiExtensions {
22
+ nodes {
23
+ schemaName
24
+ }
25
+ }
26
+ schemaNames: schemataByApiSchemaApiIdAndSchemaId {
27
+ nodes {
28
+ schemaName
29
+ }
30
+ }
31
+ rlsModule {
32
+ privateSchema {
33
+ schemaName
34
+ }
35
+ authenticateStrict
36
+ authenticate
37
+ currentRole
38
+ currentRoleId
39
+ }
40
+ database {
41
+ sites {
42
+ nodes {
43
+ domains {
44
+ nodes {
45
+ subdomain
46
+ domain
47
+ }
48
+ }
49
+ }
50
+ }
51
+ } # for now keep this for patches
52
+ apiModules {
53
+ nodes {
54
+ name
55
+ data
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ }
62
+ `;
63
+ exports.ApiByNameQuery = (0, graphql_tag_1.default) `
64
+ query ApiByName($name: String!, $databaseId: UUID!) {
65
+ api: apiByDatabaseIdAndName(name: $name, databaseId: $databaseId) {
66
+ databaseId
67
+ dbname
68
+ roleName
69
+ anonRole
70
+ isPublic
71
+ schemaNamesFromExt: apiExtensions {
72
+ nodes {
73
+ schemaName
74
+ }
75
+ }
76
+ schemaNames: schemataByApiSchemaApiIdAndSchemaId {
77
+ nodes {
78
+ schemaName
79
+ }
80
+ }
81
+ rlsModule {
82
+ privateSchema {
83
+ schemaName
84
+ }
85
+ authenticate
86
+ authenticateStrict
87
+ currentRole
88
+ currentRoleId
89
+ }
90
+ database {
91
+ sites {
92
+ nodes {
93
+ domains {
94
+ nodes {
95
+ subdomain
96
+ domain
97
+ }
98
+ }
99
+ }
100
+ }
101
+ } # for now keep this for patches
102
+ apiModules {
103
+ nodes {
104
+ name
105
+ data
106
+ }
107
+ }
108
+ }
109
+ }
110
+ `;
111
+ exports.ListOfAllDomainsOfDb = (0, graphql_tag_1.default) `
112
+ query ListApisByDatabaseId {
113
+ apis {
114
+ nodes {
115
+ id
116
+ databaseId
117
+ name
118
+ dbname
119
+ roleName
120
+ anonRole
121
+ isPublic
122
+ domains {
123
+ nodes {
124
+ domain
125
+ subdomain
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ `;
@@ -0,0 +1,4 @@
1
+ import { ConstructiveOptions } from '@constructive-io/graphql-types';
2
+ import { RequestHandler } from 'express';
3
+ import './types';
4
+ export declare const graphile: (opts: ConstructiveOptions) => RequestHandler;
@@ -0,0 +1,91 @@
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.graphile = void 0;
7
+ const graphile_cache_1 = require("graphile-cache");
8
+ const graphile_settings_1 = require("graphile-settings");
9
+ const pg_cache_1 = require("pg-cache");
10
+ const postgraphile_1 = require("postgraphile");
11
+ require("./types"); // for Request type
12
+ const PublicKeySignature_1 = __importDefault(require("../plugins/PublicKeySignature"));
13
+ const graphile = (opts) => {
14
+ return async (req, res, next) => {
15
+ try {
16
+ const api = req.api;
17
+ if (!api) {
18
+ return res.status(500).send('Missing API info');
19
+ }
20
+ const key = req.svc_key;
21
+ if (!key) {
22
+ return res.status(500).send('Missing service cache key');
23
+ }
24
+ const { dbname, anonRole, roleName, schema } = api;
25
+ if (graphile_cache_1.graphileCache.has(key)) {
26
+ const { handler } = graphile_cache_1.graphileCache.get(key);
27
+ return handler(req, res, next);
28
+ }
29
+ const options = (0, graphile_settings_1.getGraphileSettings)({
30
+ ...opts,
31
+ graphile: {
32
+ ...opts.graphile,
33
+ schema: schema,
34
+ },
35
+ });
36
+ const pubkey_challenge = api.apiModules.find((mod) => mod.name === 'pubkey_challenge');
37
+ if (pubkey_challenge && pubkey_challenge.data) {
38
+ options.appendPlugins.push((0, PublicKeySignature_1.default)(pubkey_challenge.data));
39
+ }
40
+ options.appendPlugins = options.appendPlugins ?? [];
41
+ options.appendPlugins.push(...opts.graphile.appendPlugins);
42
+ options.pgSettings = async function pgSettings(request) {
43
+ const gqlReq = request;
44
+ const context = {
45
+ [`jwt.claims.database_id`]: gqlReq.databaseId,
46
+ [`jwt.claims.ip_address`]: gqlReq.clientIp,
47
+ };
48
+ if (gqlReq.get('origin')) {
49
+ context['jwt.claims.origin'] = gqlReq.get('origin');
50
+ }
51
+ if (gqlReq.get('User-Agent')) {
52
+ context['jwt.claims.user_agent'] = gqlReq.get('User-Agent');
53
+ }
54
+ if (gqlReq?.token?.user_id) {
55
+ return {
56
+ role: roleName,
57
+ [`jwt.claims.token_id`]: gqlReq.token.id,
58
+ [`jwt.claims.user_id`]: gqlReq.token.user_id,
59
+ ...context,
60
+ };
61
+ }
62
+ return { role: anonRole, ...context };
63
+ };
64
+ options.graphqlRoute = '/graphql';
65
+ options.graphiqlRoute = '/graphiql';
66
+ options.graphileBuildOptions = {
67
+ ...options.graphileBuildOptions,
68
+ ...opts.graphile.graphileBuildOptions,
69
+ };
70
+ const graphileOpts = {
71
+ ...options,
72
+ ...opts.graphile.overrideSettings,
73
+ };
74
+ const pgPool = (0, pg_cache_1.getPgPool)({
75
+ ...opts.pg,
76
+ database: dbname,
77
+ });
78
+ const handler = (0, postgraphile_1.postgraphile)(pgPool, schema, graphileOpts);
79
+ graphile_cache_1.graphileCache.set(key, {
80
+ pgPool,
81
+ pgPoolKey: dbname,
82
+ handler,
83
+ });
84
+ return handler(req, res, next);
85
+ }
86
+ catch (e) {
87
+ return res.status(500).send(e.message);
88
+ }
89
+ };
90
+ };
91
+ exports.graphile = graphile;
@@ -0,0 +1,33 @@
1
+ import { ApiModule } from "../types";
2
+ export type ConstructiveAPIToken = {
3
+ id: string;
4
+ user_id: string;
5
+ [key: string]: any;
6
+ };
7
+ declare global {
8
+ namespace Express {
9
+ interface Request {
10
+ api?: {
11
+ dbname: string;
12
+ anonRole: string;
13
+ roleName: string;
14
+ schema: string[];
15
+ apiModules: ApiModule[];
16
+ rlsModule?: {
17
+ authenticate?: string;
18
+ authenticateStrict?: string;
19
+ privateSchema: {
20
+ schemaName: string;
21
+ };
22
+ };
23
+ domains?: string[];
24
+ databaseId?: string;
25
+ isPublic?: boolean;
26
+ };
27
+ svc_key?: string;
28
+ clientIp?: string;
29
+ databaseId?: string;
30
+ token?: ConstructiveAPIToken;
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "@constructive-io/graphql-server",
3
+ "version": "2.10.5",
4
+ "author": "Constructive <developers@constructive.io>",
5
+ "description": "Constructive GraphQL Server",
6
+ "main": "index.js",
7
+ "module": "esm/index.js",
8
+ "types": "index.d.ts",
9
+ "homepage": "https://github.com/constructive-io/constructive",
10
+ "license": "MIT",
11
+ "publishConfig": {
12
+ "access": "public",
13
+ "directory": "dist"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/constructive-io/constructive"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/constructive-io/constructive/issues"
21
+ },
22
+ "scripts": {
23
+ "clean": "makage clean",
24
+ "prepack": "npm run build",
25
+ "build": "makage build",
26
+ "build:dev": "makage build --dev",
27
+ "dev": "ts-node src/run.ts",
28
+ "dev:watch": "nodemon --watch src --ext ts --exec ts-node src/run.ts",
29
+ "lint": "eslint . --fix",
30
+ "test": "jest --passWithNoTests",
31
+ "test:watch": "jest --watch",
32
+ "bucket:create": "ts-node src/scripts/create-bucket.ts"
33
+ },
34
+ "keywords": [
35
+ "server",
36
+ "graphql",
37
+ "express",
38
+ "constructive",
39
+ "backend"
40
+ ],
41
+ "dependencies": {
42
+ "@constructive-io/graphql-env": "^2.8.4",
43
+ "@constructive-io/graphql-types": "^2.12.4",
44
+ "@constructive-io/s3-utils": "^2.3.5",
45
+ "@constructive-io/upload-names": "^2.3.3",
46
+ "@constructive-io/url-domains": "^2.3.4",
47
+ "@graphile-contrib/pg-many-to-many": "^1.0.2",
48
+ "@pgpmjs/logger": "^1.3.4",
49
+ "@pgpmjs/server-utils": "^2.8.6",
50
+ "@pgpmjs/types": "^2.12.4",
51
+ "cors": "^2.8.5",
52
+ "dotenv": "^17.2.3",
53
+ "express": "^5.1.0",
54
+ "graphile-build": "^4.14.1",
55
+ "graphile-cache": "^1.6.6",
56
+ "graphile-i18n": "^0.2.10",
57
+ "graphile-meta-schema": "^0.3.10",
58
+ "graphile-plugin-connection-filter": "^2.4.10",
59
+ "graphile-plugin-connection-filter-postgis": "^1.1.10",
60
+ "graphile-plugin-fulltext-filter": "^2.1.10",
61
+ "graphile-query": "^2.4.5",
62
+ "graphile-search-plugin": "^0.2.10",
63
+ "graphile-settings": "^2.9.5",
64
+ "graphile-simple-inflector": "^0.2.10",
65
+ "graphile-utils": "^4.14.1",
66
+ "graphql": "15.10.1",
67
+ "graphql-tag": "2.12.6",
68
+ "graphql-upload": "^13.0.0",
69
+ "lru-cache": "^11.2.4",
70
+ "pg": "^8.16.3",
71
+ "pg-cache": "^1.6.6",
72
+ "pg-query-context": "^2.3.4",
73
+ "postgraphile": "^4.14.1",
74
+ "request-ip": "^3.3.0"
75
+ },
76
+ "devDependencies": {
77
+ "@aws-sdk/client-s3": "^3.952.0",
78
+ "@types/cors": "^2.8.17",
79
+ "@types/express": "^5.0.6",
80
+ "@types/graphql-upload": "^8.0.12",
81
+ "@types/pg": "^8.16.0",
82
+ "@types/request-ip": "^0.0.41",
83
+ "makage": "^0.1.8",
84
+ "nodemon": "^3.1.10",
85
+ "ts-node": "^10.9.2"
86
+ },
87
+ "gitHead": "22cfe32e994e26a6490e04e28bab26d1e7e6345c"
88
+ }
@@ -0,0 +1,11 @@
1
+ import type { Plugin } from 'graphile-build';
2
+ export interface PublicKeyChallengeConfig {
3
+ schema: string;
4
+ crypto_network: string;
5
+ sign_up_with_key: string;
6
+ sign_in_request_challenge: string;
7
+ sign_in_record_failure: string;
8
+ sign_in_with_challenge: string;
9
+ }
10
+ export declare const PublicKeySignature: (pubkey_challenge: PublicKeyChallengeConfig) => Plugin;
11
+ export default PublicKeySignature;
@@ -0,0 +1,121 @@
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.PublicKeySignature = void 0;
7
+ const graphile_utils_1 = require("graphile-utils");
8
+ const pg_query_context_1 = __importDefault(require("pg-query-context"));
9
+ const PublicKeySignature = (pubkey_challenge) => {
10
+ const { schema, crypto_network, sign_up_with_key, sign_in_request_challenge, sign_in_record_failure, sign_in_with_challenge } = pubkey_challenge;
11
+ return (0, graphile_utils_1.makeExtendSchemaPlugin)(() => ({
12
+ typeDefs: (0, graphile_utils_1.gql) `
13
+ input CreateUserAccountWithPublicKeyInput {
14
+ publicKey: String!
15
+ }
16
+
17
+ input GetMessageForSigningInput {
18
+ publicKey: String!
19
+ }
20
+
21
+ input VerifyMessageForSigningInput {
22
+ publicKey: String!
23
+ message: String!
24
+ signature: String!
25
+ }
26
+
27
+ type createUserAccountWithPublicKeyPayload {
28
+ message: String!
29
+ }
30
+
31
+ type getMessageForSigningPayload {
32
+ message: String!
33
+ }
34
+
35
+ type verifyMessageForSigningPayload {
36
+ access_token: String!
37
+ access_token_expires_at: Datetime!
38
+ }
39
+
40
+ extend type Mutation {
41
+ createUserAccountWithPublicKey(
42
+ input: CreateUserAccountWithPublicKeyInput
43
+ ): createUserAccountWithPublicKeyPayload
44
+
45
+ getMessageForSigning(
46
+ input: GetMessageForSigningInput
47
+ ): getMessageForSigningPayload
48
+
49
+ verifyMessageForSigning(
50
+ input: VerifyMessageForSigningInput
51
+ ): verifyMessageForSigningPayload
52
+ }
53
+ `,
54
+ resolvers: {
55
+ Mutation: {
56
+ async createUserAccountWithPublicKey(_parent, args, context) {
57
+ const { pgClient } = context;
58
+ const { publicKey } = args.input;
59
+ await (0, pg_query_context_1.default)({
60
+ client: pgClient,
61
+ context: { role: 'anonymous' },
62
+ query: `SELECT * FROM "${schema}".${sign_up_with_key}($1)`,
63
+ variables: [publicKey]
64
+ });
65
+ const { rows: [{ [sign_in_request_challenge]: message }] } = await (0, pg_query_context_1.default)({
66
+ client: pgClient,
67
+ context: { role: 'anonymous' },
68
+ query: `SELECT * FROM "${schema}".${sign_in_request_challenge}($1)`,
69
+ variables: [publicKey]
70
+ });
71
+ return { message };
72
+ },
73
+ async getMessageForSigning(_parent, args, context) {
74
+ const { pgClient } = context;
75
+ const { publicKey } = args.input;
76
+ const { rows: [{ [sign_in_request_challenge]: message }] } = await (0, pg_query_context_1.default)({
77
+ client: pgClient,
78
+ context: { role: 'anonymous' },
79
+ query: `SELECT * FROM "${schema}".${sign_in_request_challenge}($1)`,
80
+ variables: [publicKey]
81
+ });
82
+ if (!message)
83
+ throw new Error('NO_ACCOUNT_EXISTS');
84
+ return { message };
85
+ },
86
+ async verifyMessageForSigning(_parent, args, context) {
87
+ const { pgClient } = context;
88
+ const { publicKey, message, signature } = args.input;
89
+ // const network = Networks[crypto_network];
90
+ const network = 'btc';
91
+ // const result = verifyMessage(message, publicKey, signature, network);
92
+ // TODO implement using interchainJS?
93
+ const result = false;
94
+ if (!result) {
95
+ await (0, pg_query_context_1.default)({
96
+ client: pgClient,
97
+ context: { role: 'anonymous' },
98
+ query: `SELECT * FROM "${schema}".${sign_in_record_failure}($1)`,
99
+ variables: [publicKey]
100
+ });
101
+ throw new Error('BAD_SIGNIN');
102
+ }
103
+ const { rows: [token] } = await (0, pg_query_context_1.default)({
104
+ client: pgClient,
105
+ context: { role: 'anonymous' },
106
+ query: `SELECT * FROM "${schema}".${sign_in_with_challenge}($1, $2)`,
107
+ variables: [publicKey, message]
108
+ });
109
+ if (!token?.access_token)
110
+ throw new Error('BAD_SIGNIN');
111
+ return {
112
+ access_token: token.access_token,
113
+ access_token_expires_at: token.access_token_expires_at
114
+ };
115
+ }
116
+ }
117
+ }
118
+ }));
119
+ };
120
+ exports.PublicKeySignature = PublicKeySignature;
121
+ exports.default = exports.PublicKeySignature;
package/run.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/run.js ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const graphql_env_1 = require("@constructive-io/graphql-env");
5
+ const server_1 = require("./server");
6
+ (0, server_1.GraphQLServer)((0, graphql_env_1.getEnvOptions)({
7
+ pg: {
8
+ database: process.env.PGDATABASE,
9
+ },
10
+ }));
package/schema.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { PostGraphileOptions } from 'postgraphile';
2
+ export type BuildSchemaOptions = {
3
+ database?: string;
4
+ schemas: string[];
5
+ graphile?: Partial<PostGraphileOptions>;
6
+ };
7
+ export declare function buildSchemaSDL(opts: BuildSchemaOptions): Promise<string>;
8
+ export declare function fetchEndpointSchemaSDL(endpoint: string, opts?: {
9
+ headerHost?: string;
10
+ headers?: Record<string, string>;
11
+ auth?: string;
12
+ }): Promise<string>;
package/schema.js ADDED
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildSchemaSDL = buildSchemaSDL;
37
+ exports.fetchEndpointSchemaSDL = fetchEndpointSchemaSDL;
38
+ const graphql_1 = require("graphql");
39
+ const graphile_settings_1 = require("graphile-settings");
40
+ const pg_cache_1 = require("pg-cache");
41
+ const postgraphile_1 = require("postgraphile");
42
+ const http = __importStar(require("node:http"));
43
+ const https = __importStar(require("node:https"));
44
+ // Build GraphQL Schema SDL directly from Postgres using PostGraphile, without HTTP.
45
+ async function buildSchemaSDL(opts) {
46
+ const database = opts.database ?? 'constructive';
47
+ const schemas = Array.isArray(opts.schemas) ? opts.schemas : [];
48
+ const settings = (0, graphile_settings_1.getGraphileSettings)({
49
+ graphile: {
50
+ schema: schemas,
51
+ ...(opts.graphile ?? {})
52
+ }
53
+ });
54
+ const pgPool = (0, pg_cache_1.getPgPool)({ database });
55
+ const schema = await (0, postgraphile_1.createPostGraphileSchema)(pgPool, schemas, settings);
56
+ return (0, graphql_1.printSchema)(schema);
57
+ }
58
+ // Fetch GraphQL Schema SDL from a running GraphQL endpoint via introspection.
59
+ // This centralizes GraphQL client usage in the server package to avoid duplicating deps in the CLI.
60
+ async function fetchEndpointSchemaSDL(endpoint, opts) {
61
+ const url = new URL(endpoint);
62
+ const requestUrl = url;
63
+ const introspectionQuery = (0, graphql_1.getIntrospectionQuery)({ descriptions: true });
64
+ const postData = JSON.stringify({
65
+ query: introspectionQuery,
66
+ variables: null,
67
+ operationName: 'IntrospectionQuery',
68
+ });
69
+ const headers = {
70
+ 'Content-Type': 'application/json',
71
+ 'Content-Length': String(Buffer.byteLength(postData)),
72
+ };
73
+ if (opts?.headerHost) {
74
+ headers['Host'] = opts.headerHost;
75
+ }
76
+ if (opts?.auth) {
77
+ headers['Authorization'] = opts.auth;
78
+ }
79
+ if (opts?.headers) {
80
+ for (const [key, value] of Object.entries(opts.headers)) {
81
+ headers[key] = value;
82
+ }
83
+ }
84
+ const isHttps = requestUrl.protocol === 'https:';
85
+ const lib = isHttps ? https : http;
86
+ const responseData = await new Promise((resolve, reject) => {
87
+ const req = lib.request({
88
+ hostname: requestUrl.hostname,
89
+ port: (requestUrl.port ? Number(requestUrl.port) : (isHttps ? 443 : 80)),
90
+ path: requestUrl.pathname,
91
+ method: 'POST',
92
+ headers,
93
+ }, (res) => {
94
+ let data = '';
95
+ res.on('data', (chunk) => { data += chunk; });
96
+ res.on('end', () => {
97
+ if (res.statusCode && res.statusCode >= 400) {
98
+ reject(new Error(`HTTP ${res.statusCode} – ${data}`));
99
+ return;
100
+ }
101
+ resolve(data);
102
+ });
103
+ });
104
+ req.on('error', (err) => reject(err));
105
+ req.write(postData);
106
+ req.end();
107
+ });
108
+ let json;
109
+ try {
110
+ json = JSON.parse(responseData);
111
+ }
112
+ catch (e) {
113
+ throw new Error(`Failed to parse response: ${responseData}`);
114
+ }
115
+ if (json.errors) {
116
+ throw new Error('Introspection returned errors');
117
+ }
118
+ if (!json.data) {
119
+ throw new Error('No data in introspection response');
120
+ }
121
+ const schema = (0, graphql_1.buildClientSchema)(json.data);
122
+ return (0, graphql_1.printSchema)(schema);
123
+ }
@@ -0,0 +1 @@
1
+ import 'dotenv/config';
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ // Minimal script to create a bucket in MinIO using @constructive-io/s3-utils
3
+ // Avoid strict type coupling between different @aws-sdk/client-s3 versions
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ // Loads graphql/server/.env by default when running via ts-node from this workspace
6
+ require("dotenv/config");
7
+ const client_s3_1 = require("@aws-sdk/client-s3");
8
+ const s3_utils_1 = require("@constructive-io/s3-utils");
9
+ const BUCKET = process.env.BUCKET_NAME || 'test-bucket';
10
+ const REGION = process.env.AWS_REGION || 'us-east-1';
11
+ const ACCESS_KEY = process.env.AWS_ACCESS_KEY || process.env.AWS_ACCESS_KEY_ID || 'minioadmin';
12
+ const SECRET_KEY = process.env.AWS_SECRET_KEY ||
13
+ process.env.AWS_SECRET_ACCESS_KEY ||
14
+ 'minioadmin';
15
+ const ENDPOINT = process.env.MINIO_ENDPOINT || 'http://localhost:9000';
16
+ (async () => {
17
+ try {
18
+ const client = new client_s3_1.S3Client({
19
+ region: REGION,
20
+ credentials: { accessKeyId: ACCESS_KEY, secretAccessKey: SECRET_KEY },
21
+ endpoint: ENDPOINT,
22
+ forcePathStyle: true,
23
+ });
24
+ // Hint downstream to apply MinIO policies
25
+ process.env.IS_MINIO = 'true';
26
+ const res = await (0, s3_utils_1.createS3Bucket)(client, BUCKET);
27
+ console.log(`[create-bucket] ${BUCKET}:`, res);
28
+ client.destroy();
29
+ }
30
+ catch (e) {
31
+ console.error('[create-bucket] error', e);
32
+ process.exitCode = 1;
33
+ }
34
+ })();