@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.
- package/LICENSE +23 -0
- package/README.md +89 -0
- package/errors/404-message.d.ts +2 -0
- package/errors/404-message.js +232 -0
- package/errors/404.d.ts +2 -0
- package/errors/404.js +218 -0
- package/errors/50x.d.ts +2 -0
- package/errors/50x.js +216 -0
- package/esm/errors/404-message.js +230 -0
- package/esm/errors/404.js +216 -0
- package/esm/errors/50x.js +214 -0
- package/esm/index.js +2 -0
- package/esm/middleware/api.js +337 -0
- package/esm/middleware/auth.js +68 -0
- package/esm/middleware/cors.js +63 -0
- package/esm/middleware/flush.js +49 -0
- package/esm/middleware/gql.js +125 -0
- package/esm/middleware/graphile.js +84 -0
- package/esm/middleware/types.js +1 -0
- package/esm/plugins/PublicKeySignature.js +114 -0
- package/esm/run.js +8 -0
- package/esm/schema.js +86 -0
- package/esm/scripts/create-bucket.js +32 -0
- package/esm/server.js +95 -0
- package/esm/types.js +1 -0
- package/index.d.ts +2 -0
- package/index.js +18 -0
- package/middleware/api.d.ts +6 -0
- package/middleware/api.js +346 -0
- package/middleware/auth.d.ts +4 -0
- package/middleware/auth.js +75 -0
- package/middleware/cors.d.ts +14 -0
- package/middleware/cors.js +70 -0
- package/middleware/flush.d.ts +5 -0
- package/middleware/flush.js +54 -0
- package/middleware/gql.d.ts +6 -0
- package/middleware/gql.js +131 -0
- package/middleware/graphile.d.ts +4 -0
- package/middleware/graphile.js +91 -0
- package/middleware/types.d.ts +33 -0
- package/middleware/types.js +2 -0
- package/package.json +88 -0
- package/plugins/PublicKeySignature.d.ts +11 -0
- package/plugins/PublicKeySignature.js +121 -0
- package/run.d.ts +2 -0
- package/run.js +10 -0
- package/schema.d.ts +12 -0
- package/schema.js +123 -0
- package/scripts/create-bucket.d.ts +1 -0
- package/scripts/create-bucket.js +34 -0
- package/server.d.ts +17 -0
- package/server.js +102 -0
- package/types.d.ts +85 -0
- 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,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
|
+
}
|
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
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
|
+
})();
|