introspectron 0.2.12 → 2.0.3

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/gql.js ADDED
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseGraphQuery = void 0;
4
+ // @ts-nocheck
5
+ const parseGraphQuery = (introQuery) => {
6
+ const types = introQuery.__schema.types;
7
+ const HASH = types.reduce((m, v) => {
8
+ m[v.name] = v;
9
+ return m;
10
+ }, {});
11
+ const queriesRoot = types.find((t) => t.name === 'Query');
12
+ const mutationsRoot = types.find((t) => t.name === 'Mutation');
13
+ const getInputForQueries = (input, context = {}) => {
14
+ if (input.kind === 'NON_NULL') {
15
+ context.isNotNull = true;
16
+ return getInputForQueries(input.ofType, context);
17
+ }
18
+ if (input.kind === 'LIST') {
19
+ context.isArray = true;
20
+ if (context.isNotNull) {
21
+ context.isArrayNotNull = true;
22
+ delete context.isNotNull;
23
+ }
24
+ return getInputForQueries(input.ofType, context);
25
+ }
26
+ if (input.kind === 'INPUT_OBJECT') {
27
+ if (input.name && HASH.hasOwnProperty(input.name)) {
28
+ const schema = HASH[input.name];
29
+ context.properties = schema.inputFields
30
+ .map((field) => {
31
+ return {
32
+ name: field.name,
33
+ type: field.type
34
+ };
35
+ })
36
+ .reduce((m3, v) => {
37
+ m3[v.name] = v;
38
+ return m3;
39
+ }, {});
40
+ }
41
+ }
42
+ else if (input.kind === 'OBJECT') {
43
+ if (input.name && HASH.hasOwnProperty(input.name)) {
44
+ const schema = HASH[input.name];
45
+ context.properties = schema.fields
46
+ .map((field) => {
47
+ return {
48
+ name: field.name,
49
+ type: field.type
50
+ };
51
+ })
52
+ .reduce((m3, v) => {
53
+ m3[v.name] = v;
54
+ return m3;
55
+ }, {});
56
+ }
57
+ }
58
+ else {
59
+ context.type = input.name;
60
+ }
61
+ return context;
62
+ };
63
+ const getInputForMutations = (input, context = {}) => {
64
+ if (input.kind === 'NON_NULL') {
65
+ context.isNotNull = true;
66
+ return getInputForMutations(input.ofType, context);
67
+ }
68
+ if (input.kind === 'LIST') {
69
+ context.isArray = true;
70
+ if (context.isNotNull) {
71
+ context.isArrayNotNull = true;
72
+ delete context.isNotNull;
73
+ }
74
+ return getInputForMutations(input.ofType, context);
75
+ }
76
+ if (input.kind === 'INPUT_OBJECT') {
77
+ if (input.name && HASH.hasOwnProperty(input.name)) {
78
+ const schema = HASH[input.name];
79
+ context.properties = schema.inputFields
80
+ .map((field) => {
81
+ return getInputForMutations(field.type, { name: field.name });
82
+ })
83
+ .reduce((m3, v) => {
84
+ m3[v.name] = v;
85
+ return m3;
86
+ }, {});
87
+ }
88
+ }
89
+ else if (input.kind === 'OBJECT') {
90
+ if (input.name && HASH.hasOwnProperty(input.name)) {
91
+ const schema = HASH[input.name];
92
+ context.properties = schema.fields
93
+ .map((field) => {
94
+ return {
95
+ name: field.name,
96
+ type: field.type
97
+ };
98
+ })
99
+ .reduce((m3, v) => {
100
+ m3[v.name] = v;
101
+ return m3;
102
+ }, {});
103
+ }
104
+ }
105
+ else {
106
+ context.type = input.name;
107
+ }
108
+ return context;
109
+ };
110
+ const mutations = mutationsRoot.fields.reduce((m, mutation) => {
111
+ let mutationType = 'other';
112
+ if (/^Create/.test(mutation.type.name)) {
113
+ mutationType = 'create';
114
+ }
115
+ else if (/^Update/.test(mutation.type.name)) {
116
+ mutationType = 'patch';
117
+ }
118
+ else if (/^Delete/.test(mutation.type.name)) {
119
+ mutationType = 'delete';
120
+ }
121
+ const props = mutation.args.reduce((m2, arg) => {
122
+ const type = arg.type?.ofType?.name;
123
+ const isNotNull = arg.type?.kind === 'NON_NULL';
124
+ if (type && HASH.hasOwnProperty(type)) {
125
+ const schema = HASH[type];
126
+ const fields = schema.inputFields.filter((a) => a.name !== 'clientMutationId');
127
+ const properties = fields
128
+ .map((a) => getInputForMutations(a.type, { name: a.name }))
129
+ .reduce((m3, v) => {
130
+ m3[v.name] = v;
131
+ return m3;
132
+ }, {});
133
+ m2[arg.name] = {
134
+ isNotNull,
135
+ type,
136
+ properties
137
+ };
138
+ }
139
+ else {
140
+ console.warn('whats wrong with ' + arg);
141
+ }
142
+ return m2;
143
+ }, {});
144
+ const getModelTypes = (type) => {
145
+ return type.fields
146
+ .filter((t) => t.type.kind === 'OBJECT')
147
+ .filter((t) => t.type.name !== 'Query')
148
+ .map((f) => ({ name: f.name, type: f.type }));
149
+ };
150
+ const models = getModelTypes(HASH[mutation.type.name]);
151
+ if (models.length > 0) {
152
+ // TODO this is probably brittle
153
+ const model = models[0].type.name;
154
+ m[mutation.name] = {
155
+ qtype: 'mutation',
156
+ mutationType,
157
+ model,
158
+ properties: props,
159
+ output: mutation.type
160
+ };
161
+ }
162
+ else {
163
+ // no return args, probably void functions
164
+ let t;
165
+ let outputFields = [];
166
+ if (mutation.type.kind === 'OBJECT') {
167
+ t = HASH[mutation.type.name];
168
+ outputFields = t.fields
169
+ .map((f) => ({ name: f.name, type: f.type }))
170
+ .filter((f) => f.name !== 'clientMutationId')
171
+ .filter((f) => f.type.name !== 'Query');
172
+ }
173
+ m[mutation.name] = {
174
+ qtype: 'mutation',
175
+ mutationType,
176
+ properties: props,
177
+ output: mutation.type,
178
+ outputs: outputFields
179
+ };
180
+ }
181
+ return m;
182
+ }, {});
183
+ // expect(mts).toMatchSnapshot();
184
+ const parseConnectionQuery = (query, nesting) => {
185
+ const objectType = getObjectType(query.type);
186
+ const Connection = HASH[objectType];
187
+ const nodes = Connection.fields.find((f) => f.name === 'nodes');
188
+ const edges = Connection.fields.find((f) => f.name === 'edges');
189
+ const model = getObjectType(nodes.type);
190
+ const context = { HASH, parseConnectionQuery, parseSingleQuery };
191
+ if (nesting === 0) {
192
+ return {
193
+ qtype: 'getMany',
194
+ model,
195
+ selection: parseSelectionScalar(context, model)
196
+ };
197
+ }
198
+ return {
199
+ qtype: 'getMany',
200
+ model,
201
+ selection: parseSelectionObject(context, model, 1)
202
+ };
203
+ };
204
+ const parseSingleQuery = (query, nesting) => {
205
+ const model = getObjectType(query.type);
206
+ const context = { HASH, parseConnectionQuery, parseSingleQuery };
207
+ if (nesting === 0) {
208
+ return {
209
+ qtype: 'getOne',
210
+ model,
211
+ properties: query.args.reduce((m2, v) => {
212
+ m2[v.name] = getInputForQueries(v.type);
213
+ return m2;
214
+ }, {}),
215
+ selection: parseSelectionScalar(context, model)
216
+ };
217
+ }
218
+ return {
219
+ model,
220
+ qtype: 'getOne',
221
+ properties: query.args.reduce((m2, v) => {
222
+ m2[v.name] = getInputForQueries(v.type);
223
+ return m2;
224
+ }, {}),
225
+ selection: parseSelectionObject(context, model, 1)
226
+ };
227
+ };
228
+ const queries = queriesRoot.fields.reduce((m, query) => {
229
+ // m[query.name] = getInputForQueries(query.type);
230
+ if (query.type.kind === 'OBJECT') {
231
+ if (isConnectionQuery(query)) {
232
+ m[query.name] = parseConnectionQuery(query, 1);
233
+ }
234
+ else {
235
+ m[query.name] = parseSingleQuery(query, 1);
236
+ }
237
+ }
238
+ return m;
239
+ }, {});
240
+ return {
241
+ queries,
242
+ mutations
243
+ };
244
+ };
245
+ exports.parseGraphQuery = parseGraphQuery;
246
+ // Parse selections for both scalar and object fields
247
+ function parseSelectionObject(context, model, nesting) {
248
+ const { HASH, parseConnectionQuery, parseSingleQuery } = context;
249
+ throwIfInvalidContext(context);
250
+ const selectionFields = HASH[model].fields.filter((f) => !isPureObjectType(f.type));
251
+ const selection = selectionFields.map((f) => {
252
+ if (f.type.ofType?.kind === 'OBJECT') {
253
+ if (isConnectionQuery(f)) {
254
+ return { name: f.name, ...parseConnectionQuery(f, nesting - 1) };
255
+ }
256
+ else {
257
+ return { name: f.name, ...parseSingleQuery(f, nesting - 1) };
258
+ }
259
+ }
260
+ return f.name;
261
+ });
262
+ return selection;
263
+ }
264
+ // Parse selections for scalar types only, ignore all field selections
265
+ // that have more nesting selection level
266
+ function parseSelectionScalar(context, model) {
267
+ const { HASH } = context;
268
+ throwIfInvalidContext(context);
269
+ const selectionFields = HASH[model].fields.filter((f) => !isPureObjectType(f.type) && !isConnectionQuery(f));
270
+ const selection = selectionFields.map((f) => f.name);
271
+ return selection;
272
+ }
273
+ function isConnectionQuery(query) {
274
+ const objectType = getObjectType(query.type);
275
+ const fields = query.args.map((a) => a.name);
276
+ return (/Connection$/.test(objectType) &&
277
+ fields.includes('condition') &&
278
+ fields.includes('filter'));
279
+ }
280
+ /**
281
+ * Check is a type is pure object type
282
+ * pure object type is different from custom types in the sense that
283
+ * it does not inherit from any type, custom types inherit from a parent type
284
+ * @param {Object} typeObj
285
+ * @returns {boolean}
286
+ */
287
+ function isPureObjectType(typeObj) {
288
+ return typeObj.kind === 'OBJECT' && typeObj.name == null;
289
+ }
290
+ function getObjectType(type) {
291
+ if (type.kind === 'OBJECT')
292
+ return type.name;
293
+ if (type.ofType)
294
+ return getObjectType(type.ofType);
295
+ }
296
+ function throwIfInvalidContext(context) {
297
+ const { HASH, parseConnectionQuery, parseSingleQuery } = context;
298
+ if (!HASH || !parseConnectionQuery || !parseSingleQuery) {
299
+ throw new Error('parseSelection: context missing');
300
+ }
301
+ }
@@ -2,4 +2,4 @@ export * from './introspect';
2
2
  export * from './process';
3
3
  export * from './query';
4
4
  export * from './gql';
5
- export * from './introspectGql';
5
+ export * from './introspectGql';
package/index.js ADDED
@@ -0,0 +1,22 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // @ts-nocheck
18
+ __exportStar(require("./introspect"), exports);
19
+ __exportStar(require("./process"), exports);
20
+ __exportStar(require("./query"), exports);
21
+ __exportStar(require("./gql"), exports);
22
+ __exportStar(require("./introspectGql"), exports);
@@ -0,0 +1,16 @@
1
+ export declare const introspect: (pgClient: any, { schemas, includeExtensions, pgEnableTags, pgThrowOnMissingSchema }?: {
2
+ schemas: any;
3
+ includeExtensions?: boolean;
4
+ pgEnableTags?: boolean;
5
+ pgThrowOnMissingSchema?: boolean;
6
+ }) => Promise<Readonly<{
7
+ __pgVersion: number;
8
+ namespace: any[];
9
+ class: any[];
10
+ attribute: any[];
11
+ type: any[];
12
+ constraint: any[];
13
+ procedure: any[];
14
+ extension: any[];
15
+ index: any[];
16
+ }>>;
package/introspect.js ADDED
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.introspect = void 0;
4
+ // @ts-nocheck
5
+ const query_1 = require("./query");
6
+ const utils_1 = require("./utils");
7
+ const introspect = async (pgClient, { schemas, includeExtensions = false, pgEnableTags = true, pgThrowOnMissingSchema = true } = {}) => {
8
+ const versionResult = await pgClient.query('show server_version_num;');
9
+ const serverVersionNum = parseInt(versionResult.rows[0].server_version_num, 10);
10
+ const introspectionQuery = (0, query_1.makeIntrospectionQuery)(serverVersionNum, {
11
+ pgLegacyFunctionsOnly: false,
12
+ pgIgnoreRBAC: true
13
+ });
14
+ const { rows } = await pgClient.query(introspectionQuery, [
15
+ schemas,
16
+ includeExtensions
17
+ ]);
18
+ const result = {
19
+ __pgVersion: serverVersionNum,
20
+ namespace: [],
21
+ class: [],
22
+ attribute: [],
23
+ type: [],
24
+ constraint: [],
25
+ procedure: [],
26
+ extension: [],
27
+ index: []
28
+ };
29
+ for (const { object } of rows) {
30
+ result[object.kind].push(object);
31
+ }
32
+ // Parse tags from comments
33
+ [
34
+ 'namespace',
35
+ 'class',
36
+ 'attribute',
37
+ 'type',
38
+ 'constraint',
39
+ 'procedure',
40
+ 'extension',
41
+ 'index'
42
+ ].forEach((kind) => {
43
+ result[kind].forEach((object) => {
44
+ // Keep a copy of the raw comment
45
+ object.comment = object.description;
46
+ if (pgEnableTags && object.description) {
47
+ const parsed = (0, utils_1.parseTags)(object.description);
48
+ object.tags = parsed.tags;
49
+ object.description = parsed.text;
50
+ }
51
+ else {
52
+ object.tags = {};
53
+ }
54
+ });
55
+ });
56
+ const extensionConfigurationClassIds = result.extension.flatMap((e) => e.configurationClassIds);
57
+ result.class.forEach((klass) => {
58
+ klass.isExtensionConfigurationTable =
59
+ extensionConfigurationClassIds.indexOf(klass.id) >= 0;
60
+ });
61
+ [
62
+ 'namespace',
63
+ 'class',
64
+ 'attribute',
65
+ 'type',
66
+ 'constraint',
67
+ 'procedure',
68
+ 'extension',
69
+ 'index'
70
+ ].forEach((k) => {
71
+ result[k].forEach(Object.freeze);
72
+ });
73
+ const knownSchemas = result.namespace.map((n) => n.name);
74
+ const missingSchemas = schemas.filter((s) => knownSchemas.indexOf(s) < 0);
75
+ if (missingSchemas.length) {
76
+ const errorMessage = `You requested to use schema '${schemas.join("', '")}'; however we couldn't find some of those! Missing schemas are: '${missingSchemas.join("', '")}'`;
77
+ if (pgThrowOnMissingSchema) {
78
+ throw new Error(errorMessage);
79
+ }
80
+ else {
81
+ console.warn('⚠️ WARNING⚠️ ' + errorMessage); // eslint-disable-line no-console
82
+ }
83
+ }
84
+ // return result;
85
+ return Object.freeze(result);
86
+ };
87
+ exports.introspect = introspect;
88
+ // export const processIntrospection = async (pgClient, introspectionResultsByKind) => {
89
+ // }
@@ -0,0 +1 @@
1
+ export declare const IntrospectionQuery: import("graphql/language/ast").DocumentNode;
@@ -0,0 +1,105 @@
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.IntrospectionQuery = void 0;
7
+ const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
+ exports.IntrospectionQuery = (0, graphql_tag_1.default) `
9
+ query IntrospectionQuery {
10
+ __schema {
11
+ queryType {
12
+ name
13
+ }
14
+ mutationType {
15
+ name
16
+ }
17
+ subscriptionType {
18
+ name
19
+ }
20
+ types {
21
+ ...FullType
22
+ }
23
+ directives {
24
+ name
25
+ description
26
+ locations
27
+ args {
28
+ ...InputValue
29
+ }
30
+ }
31
+ }
32
+ }
33
+ fragment FullType on __Type {
34
+ kind
35
+ name
36
+ description
37
+ fields(includeDeprecated: true) {
38
+ name
39
+ description
40
+ args {
41
+ ...InputValue
42
+ }
43
+ type {
44
+ ...TypeRef
45
+ }
46
+ isDeprecated
47
+ deprecationReason
48
+ }
49
+ inputFields {
50
+ ...InputValue
51
+ }
52
+ interfaces {
53
+ ...TypeRef
54
+ }
55
+ enumValues(includeDeprecated: true) {
56
+ name
57
+ description
58
+ isDeprecated
59
+ deprecationReason
60
+ }
61
+ possibleTypes {
62
+ ...TypeRef
63
+ }
64
+ }
65
+ fragment InputValue on __InputValue {
66
+ name
67
+ description
68
+ type {
69
+ ...TypeRef
70
+ }
71
+ defaultValue
72
+ }
73
+ fragment TypeRef on __Type {
74
+ kind
75
+ name
76
+ ofType {
77
+ kind
78
+ name
79
+ ofType {
80
+ kind
81
+ name
82
+ ofType {
83
+ kind
84
+ name
85
+ ofType {
86
+ kind
87
+ name
88
+ ofType {
89
+ kind
90
+ name
91
+ ofType {
92
+ kind
93
+ name
94
+ ofType {
95
+ kind
96
+ name
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ `;
package/package.json CHANGED
@@ -1,71 +1,36 @@
1
1
  {
2
2
  "name": "introspectron",
3
- "version": "0.2.12",
3
+ "version": "2.0.3",
4
4
  "description": "introspect your Postgres database and generate an SDK",
5
5
  "author": "Dan Lynch <pyramation@gmail.com>",
6
- "homepage": "https://github.com/launchql/launchql-gen/tree/master/packages/introspectron#readme",
6
+ "main": "index.js",
7
+ "module": "esm/index.js",
8
+ "types": "index.d.ts",
9
+ "homepage": "https://github.com/launchql/launchql",
7
10
  "license": "SEE LICENSE IN LICENSE",
8
- "main": "main/index.js",
9
- "module": "module/index.js",
10
- "directories": {
11
- "lib": "src",
12
- "test": "__tests__"
13
- },
14
- "files": [
15
- "main",
16
- "module"
17
- ],
18
11
  "publishConfig": {
19
- "access": "public"
12
+ "access": "public",
13
+ "directory": "dist"
20
14
  },
21
15
  "repository": {
22
16
  "type": "git",
23
- "url": "https://github.com/launchql/launchql-gen"
17
+ "url": "https://github.com/launchql/launchql"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/launchql/launchql/issues"
24
21
  },
25
22
  "scripts": {
26
- "build:main": "BABEL_ENV=production babel src --out-dir main --delete-dir-on-start",
27
- "build:module": "MODULE=true babel src --out-dir module --delete-dir-on-start",
28
- "build": "npm run build:module && npm run build:main",
29
- "clean": "rimraf node_modules main module",
30
- "debug": "node --inspect-brk ../../node_modules/jest/bin/jest.js --runInBand ./__tests__",
23
+ "copy": "copyfiles -f ../../LICENSE README.md package.json dist",
24
+ "clean": "rimraf dist/**",
31
25
  "prepare": "npm run build",
32
- "lint": "eslint src --fix",
26
+ "build": "npm run clean; tsc; tsc -p tsconfig.esm.json; npm run copy",
27
+ "build:dev": "npm run clean; tsc --declarationMap; tsc -p tsconfig.esm.json; npm run copy",
28
+ "lint": "eslint . --fix",
33
29
  "test": "jest",
34
- "test:watch": "jest --watch",
35
- "test:debug": "node --inspect node_modules/.bin/jest --runInBand"
36
- },
37
- "bugs": {
38
- "url": "https://github.com/launchql/launchql-gen/issues"
39
- },
40
- "devDependencies": {
41
- "@babel/cli": "7.8.4",
42
- "@babel/core": "7.8.4",
43
- "@babel/plugin-proposal-class-properties": "7.8.3",
44
- "@babel/plugin-proposal-export-default-from": "7.8.3",
45
- "@babel/plugin-proposal-object-rest-spread": "7.9.6",
46
- "@babel/plugin-transform-runtime": "7.9.6",
47
- "@babel/preset-env": "7.13.0",
48
- "@babel/preset-react": "7.9.4",
49
- "babel-core": "7.0.0-bridge.0",
50
- "babel-eslint": "10.0.3",
51
- "babel-plugin-macros": "2.8.0",
52
- "eslint": "^6.8.0",
53
- "eslint-config-prettier": "^6.10.0",
54
- "eslint-config-react-app": "5.2.0",
55
- "eslint-plugin-prettier": "^3.1.2",
56
- "eslint-plugin-react": "^7.18.3",
57
- "eslint-plugin-react-hooks": "4.0.0",
58
- "jest": "^25.1.0",
59
- "json-stringify-safe": "5.0.1",
60
- "pg": "8.3.3",
61
- "prettier": "^1.19.1",
62
- "regenerator-runtime": "^0.13.2",
63
- "rimraf": "^3.0.2"
30
+ "test:watch": "jest --watch"
64
31
  },
65
32
  "dependencies": {
66
- "@babel/runtime": "^7.4.2",
67
- "graphql-tag": "2.11.0",
68
- "lodash": "4.17.20"
33
+ "graphql-tag": "2.12.5"
69
34
  },
70
- "gitHead": "9a2a378c93c58d4602c148fd324427e01a91f473"
35
+ "gitHead": "546607b8de61b57f332562bfd8418cd5fac63a6a"
71
36
  }
package/process.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const introspectionResultsFromRaw: (rawResults: any, pgAugmentIntrospectionResults: any) => any;