graphile-export 0.0.2-beta.2 → 0.0.2-beta.21
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/CHANGELOG.md +284 -0
- package/README.md +5 -2
- package/dist/exportSchema.d.ts +4 -1
- package/dist/exportSchema.d.ts.map +1 -1
- package/dist/exportSchema.js +273 -100
- package/dist/exportSchema.js.map +1 -1
- package/dist/helpers.d.ts +1 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -1
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/optimize/index.d.ts +1 -1
- package/dist/optimize/index.d.ts.map +1 -1
- package/dist/optimize/index.js +69 -25
- package/dist/optimize/index.js.map +1 -1
- package/dist/reservedWords.d.ts +2 -0
- package/dist/reservedWords.d.ts.map +1 -0
- package/dist/reservedWords.js +100 -0
- package/dist/reservedWords.js.map +1 -0
- package/dist/wellKnown.d.ts +0 -19
- package/dist/wellKnown.d.ts.map +1 -1
- package/dist/wellKnown.js +15 -13
- package/dist/wellKnown.js.map +1 -1
- package/package.json +23 -19
package/dist/exportSchema.js
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exportSchema = exports.exportSchemaAsString = exports.objectNullPrototype = exports.isNotNullish = exports.canRepresentAsIdentifier = void 0;
|
|
3
|
+
exports.exportSchema = exports.exportValueAsString = exports.exportSchemaAsString = exports.objectNullPrototype = exports.isNotNullish = exports.canRepresentAsIdentifier = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const promises_1 = require("node:fs/promises");
|
|
6
|
+
const node_util_1 = require("node:util");
|
|
5
7
|
const generator_1 = tslib_1.__importDefault(require("@babel/generator"));
|
|
6
8
|
const parser_1 = require("@babel/parser");
|
|
7
9
|
const template_1 = tslib_1.__importDefault(require("@babel/template"));
|
|
10
|
+
const traverse_1 = tslib_1.__importDefault(require("@babel/traverse"));
|
|
8
11
|
const t = tslib_1.__importStar(require("@babel/types"));
|
|
9
12
|
const graphql_1 = require("grafast/graphql");
|
|
10
|
-
const promises_1 = require("node:fs/promises");
|
|
11
|
-
const node_util_1 = require("node:util");
|
|
12
13
|
const index_js_1 = require("./optimize/index.js");
|
|
14
|
+
const reservedWords_js_1 = require("./reservedWords.js");
|
|
13
15
|
const wellKnown_js_1 = require("./wellKnown.js");
|
|
14
16
|
// Cannot import sql because it's optional
|
|
15
17
|
// import { sql } from "pg-sql2";
|
|
@@ -48,6 +50,14 @@ function identifierOrLiteral(key) {
|
|
|
48
50
|
return t.stringLiteral(key);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
function literal(key) {
|
|
54
|
+
if (typeof key === "number") {
|
|
55
|
+
return t.numericLiteral(key);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
return t.stringLiteral(key);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
51
61
|
function locationHintToIdentifierName(locationHint) {
|
|
52
62
|
let result = locationHint;
|
|
53
63
|
result = result.replace(/[[.]/g, "__").replace(/\]/g, "");
|
|
@@ -59,7 +69,10 @@ function locationHintToIdentifierName(locationHint) {
|
|
|
59
69
|
return result;
|
|
60
70
|
}
|
|
61
71
|
function getNameForThing(thing, locationHint, baseNameHint) {
|
|
62
|
-
if (
|
|
72
|
+
if (thing.$exporter$name) {
|
|
73
|
+
return thing.$exporter$name;
|
|
74
|
+
}
|
|
75
|
+
else if (typeof thing === "function") {
|
|
63
76
|
if (baseNameHint) {
|
|
64
77
|
return baseNameHint;
|
|
65
78
|
}
|
|
@@ -71,7 +84,10 @@ function getNameForThing(thing, locationHint, baseNameHint) {
|
|
|
71
84
|
}
|
|
72
85
|
else {
|
|
73
86
|
const thingConstructor = thing.constructor;
|
|
74
|
-
const thingConstructorNameRaw = thingConstructor
|
|
87
|
+
const thingConstructorNameRaw = thingConstructor?.$exporter$name ??
|
|
88
|
+
thingConstructor?.name ??
|
|
89
|
+
thingConstructor?.displayName ??
|
|
90
|
+
null;
|
|
75
91
|
const thingConstructorName = ["Array", "Object", "Set", "Map"].includes(thingConstructorNameRaw)
|
|
76
92
|
? null
|
|
77
93
|
: thingConstructorNameRaw;
|
|
@@ -120,54 +136,60 @@ const BUILTINS = ["Int", "Float", "Boolean", "ID", "String"];
|
|
|
120
136
|
function isBuiltinType(type) {
|
|
121
137
|
return type.name.startsWith("__") || BUILTINS.includes(type.name);
|
|
122
138
|
}
|
|
139
|
+
const RESERVED_VARIABLES = {
|
|
140
|
+
// Reserved variables
|
|
141
|
+
AbortController: true,
|
|
142
|
+
Array: true,
|
|
143
|
+
Buffer: true,
|
|
144
|
+
DOMException: true,
|
|
145
|
+
Error: true,
|
|
146
|
+
Event: true,
|
|
147
|
+
EventTarget: true,
|
|
148
|
+
JSON: true,
|
|
149
|
+
Math: true,
|
|
150
|
+
MessageChannel: true,
|
|
151
|
+
MessageEvent: true,
|
|
152
|
+
MessagePort: true,
|
|
153
|
+
Object: true,
|
|
154
|
+
TextDecoder: true,
|
|
155
|
+
TextEncoder: true,
|
|
156
|
+
URL: true,
|
|
157
|
+
URLSearchParams: true,
|
|
158
|
+
WebAssembly: true,
|
|
159
|
+
__dirname: true,
|
|
160
|
+
__filename: true,
|
|
161
|
+
atob: true,
|
|
162
|
+
btoa: true,
|
|
163
|
+
clearImmediate: true,
|
|
164
|
+
clearInterval: true,
|
|
165
|
+
clearTimeout: true,
|
|
166
|
+
console: true,
|
|
167
|
+
exports: true,
|
|
168
|
+
global: true,
|
|
169
|
+
module: true,
|
|
170
|
+
performance: true,
|
|
171
|
+
process: true,
|
|
172
|
+
queueMicrotask: true,
|
|
173
|
+
require: true,
|
|
174
|
+
setImmediate: true,
|
|
175
|
+
setInterval: true,
|
|
176
|
+
setTimeout: true,
|
|
177
|
+
structuredClone: true,
|
|
178
|
+
};
|
|
179
|
+
for (const reservedWord of reservedWords_js_1.reservedWords) {
|
|
180
|
+
RESERVED_VARIABLES[reservedWord] = true;
|
|
181
|
+
}
|
|
182
|
+
Object.freeze(RESERVED_VARIABLES);
|
|
123
183
|
class CodegenFile {
|
|
124
184
|
constructor(options) {
|
|
125
185
|
this.options = options;
|
|
126
|
-
this._variables = Object.assign(Object.create(null),
|
|
127
|
-
// Reserved variables
|
|
128
|
-
AbortController: true,
|
|
129
|
-
Array: true,
|
|
130
|
-
Buffer: true,
|
|
131
|
-
DOMException: true,
|
|
132
|
-
Error: true,
|
|
133
|
-
Event: true,
|
|
134
|
-
EventTarget: true,
|
|
135
|
-
JSON: true,
|
|
136
|
-
Math: true,
|
|
137
|
-
MessageChannel: true,
|
|
138
|
-
MessageEvent: true,
|
|
139
|
-
MessagePort: true,
|
|
140
|
-
Object: true,
|
|
141
|
-
TextDecoder: true,
|
|
142
|
-
TextEncoder: true,
|
|
143
|
-
URL: true,
|
|
144
|
-
URLSearchParams: true,
|
|
145
|
-
WebAssembly: true,
|
|
146
|
-
__dirname: true,
|
|
147
|
-
__filename: true,
|
|
148
|
-
atob: true,
|
|
149
|
-
btoa: true,
|
|
150
|
-
clearImmediate: true,
|
|
151
|
-
clearInterval: true,
|
|
152
|
-
clearTimeout: true,
|
|
153
|
-
console: true,
|
|
154
|
-
exports: true,
|
|
155
|
-
global: true,
|
|
156
|
-
module: true,
|
|
157
|
-
performance: true,
|
|
158
|
-
process: true,
|
|
159
|
-
queueMicrotask: true,
|
|
160
|
-
require: true,
|
|
161
|
-
setImmediate: true,
|
|
162
|
-
setInterval: true,
|
|
163
|
-
setTimeout: true,
|
|
164
|
-
structuredClone: true,
|
|
165
|
-
});
|
|
186
|
+
this._variables = Object.assign(Object.create(null), RESERVED_VARIABLES);
|
|
166
187
|
this._imports = Object.create(null);
|
|
167
188
|
this._types = Object.create(null);
|
|
168
189
|
this._directives = Object.create(null);
|
|
169
190
|
this._statements = [];
|
|
170
191
|
this._values = new Map();
|
|
192
|
+
this._funcToAstCache = new Map();
|
|
171
193
|
}
|
|
172
194
|
addStatements(statements) {
|
|
173
195
|
if (Array.isArray(statements)) {
|
|
@@ -566,22 +588,20 @@ function _convertToAST(file, thing, locationHint, nameHint, depth, reference) {
|
|
|
566
588
|
return func(file, thing, locationHint, nameHint);
|
|
567
589
|
}
|
|
568
590
|
else if ((0, graphql_1.isSchema)(thing)) {
|
|
569
|
-
throw new Error(
|
|
591
|
+
throw new Error(`Attempted to export GraphQLSchema directly from \`_convertToAST\` (at ${locationHint}); this is currently unsupported.`);
|
|
570
592
|
}
|
|
571
593
|
else if (typeof thing === "object" && thing != null) {
|
|
572
594
|
const prototype = Object.getPrototypeOf(thing);
|
|
573
595
|
if (prototype !== null && prototype !== Object.prototype) {
|
|
574
|
-
throw new Error(`Attempting to export an instance of a class; you should wrap this definition in EXPORTABLE! (Class: ${thing.constructor})`);
|
|
596
|
+
throw new Error(`Attempting to export an instance of a class (at ${locationHint}); you should wrap this definition in EXPORTABLE! (Class: ${thing.constructor})`);
|
|
575
597
|
}
|
|
576
598
|
const propertyPairs = [];
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
599
|
+
const entries = Object.entries(thing);
|
|
600
|
+
const hasUnsafeKeys = entries.some(([key]) => !canBeRegularObjectKey(key));
|
|
601
|
+
entries.forEach(([key, value]) => {
|
|
602
|
+
const tKey = hasUnsafeKeys ? literal(key) : identifierOrLiteral(key);
|
|
580
603
|
const subvalue = handleSubvalue(value, tKey, key);
|
|
581
604
|
propertyPairs.push([tKey, subvalue]);
|
|
582
|
-
if (!canBeRegularObjectKey(key)) {
|
|
583
|
-
hasUnsafeKeys = true;
|
|
584
|
-
}
|
|
585
605
|
});
|
|
586
606
|
if (prototype === null) {
|
|
587
607
|
if (hasUnsafeKeys) {
|
|
@@ -603,7 +623,7 @@ function _convertToAST(file, thing, locationHint, nameHint, depth, reference) {
|
|
|
603
623
|
}
|
|
604
624
|
else {
|
|
605
625
|
if (hasUnsafeKeys) {
|
|
606
|
-
throw new Error(`Unexportable key found on non-null-prototype object`);
|
|
626
|
+
throw new Error(`Unexportable key found on non-null-prototype object (at ${locationHint})`);
|
|
607
627
|
}
|
|
608
628
|
else {
|
|
609
629
|
const obj = t.objectExpression(propertyPairs.map(([key, val]) => t.objectProperty(key, val)));
|
|
@@ -650,6 +670,21 @@ const getExistingIdentifier = (file, thing) => {
|
|
|
650
670
|
return file.declareType(thing);
|
|
651
671
|
}
|
|
652
672
|
};
|
|
673
|
+
function importWellKnownOrFactory(file, value, locationHint, nameHint) {
|
|
674
|
+
if (isImportable(value)) {
|
|
675
|
+
return file.import(value.$$export.moduleName, value.$$export.exportName);
|
|
676
|
+
}
|
|
677
|
+
else if ((0, wellKnown_js_1.wellKnown)(file.options, value)) {
|
|
678
|
+
const { moduleName, exportName } = (0, wellKnown_js_1.wellKnown)(file.options, value);
|
|
679
|
+
return file.import(moduleName, exportName);
|
|
680
|
+
}
|
|
681
|
+
else if (isExportedFromFactory(value)) {
|
|
682
|
+
return factoryAst(file, value, locationHint, nameHint);
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
return undefined;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
653
688
|
function convertToIdentifierViaAST(file, thing, baseNameHint, locationHint, depth = 0) {
|
|
654
689
|
const existingIdentifier = getExistingIdentifier(file, thing);
|
|
655
690
|
if (existingIdentifier) {
|
|
@@ -659,9 +694,8 @@ function convertToIdentifierViaAST(file, thing, baseNameHint, locationHint, dept
|
|
|
659
694
|
const nameHint = getNameForThing(thing, locationHint, baseNameHint);
|
|
660
695
|
const variableIdentifier = file.makeVariable(nameHint || "value");
|
|
661
696
|
file._values.set(thing, variableIdentifier);
|
|
662
|
-
const ast =
|
|
663
|
-
|
|
664
|
-
: _convertToAST(file, thing, locationHint, nameHint, depth, variableIdentifier);
|
|
697
|
+
const ast = importWellKnownOrFactory(file, thing, locationHint, nameHint) ??
|
|
698
|
+
_convertToAST(file, thing, locationHint, nameHint, depth, variableIdentifier);
|
|
665
699
|
if (ast.type === "Identifier") {
|
|
666
700
|
console.warn(`graphile-export error: AST returned an identifier '${ast.name}'; this could cause an infinite loop.`);
|
|
667
701
|
}
|
|
@@ -709,24 +743,13 @@ function func(file, fn, locationHint, nameHint) {
|
|
|
709
743
|
// scope; e.g.:
|
|
710
744
|
//
|
|
711
745
|
// `(() => { const foo = 1, bar = 2; return /*>*/() => {return foo+bar}/*<*/})();`
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
}
|
|
715
|
-
else if ((0, wellKnown_js_1.wellKnown)(file.options, fn)) {
|
|
716
|
-
const { moduleName, exportName } = (0, wellKnown_js_1.wellKnown)(file.options, fn);
|
|
717
|
-
return file.import(moduleName, exportName);
|
|
718
|
-
}
|
|
719
|
-
else if (isImportable(fn)) {
|
|
720
|
-
return file.import(fn.$$export.moduleName, fn.$$export.exportName);
|
|
721
|
-
}
|
|
722
|
-
else {
|
|
723
|
-
return funcToAst(fn, locationHint, nameHint);
|
|
724
|
-
}
|
|
746
|
+
return (importWellKnownOrFactory(file, fn, locationHint, nameHint) ??
|
|
747
|
+
funcToAst(file, fn, locationHint, nameHint).ast);
|
|
725
748
|
}
|
|
726
749
|
const shouldOptimizeFactoryCalls = true;
|
|
727
750
|
function factoryAst(file, fn, locationHint, nameHint) {
|
|
728
751
|
const factory = fn.$exporter$factory;
|
|
729
|
-
const funcAST = funcToAst(factory, locationHint, nameHint);
|
|
752
|
+
const { functionWithoutOwnAttributesAST: funcAST } = funcToAst(file, factory, locationHint, nameHint);
|
|
730
753
|
const depArgs = fn.$exporter$args.map((arg, i) => {
|
|
731
754
|
if (typeof arg === "string") {
|
|
732
755
|
return t.stringLiteral(arg);
|
|
@@ -778,13 +801,79 @@ function factoryAst(file, fn, locationHint, nameHint) {
|
|
|
778
801
|
return t.callExpression(funcAST, depArgs);
|
|
779
802
|
}
|
|
780
803
|
}
|
|
781
|
-
function funcToAst(fn, locationHint, _nameHint) {
|
|
804
|
+
function funcToAst(file, fn, locationHint, _nameHint) {
|
|
805
|
+
if (file._funcToAstCache.has(fn)) {
|
|
806
|
+
return file._funcToAstCache.get(fn);
|
|
807
|
+
}
|
|
808
|
+
const path = _funcToAst(fn, locationHint, _nameHint);
|
|
809
|
+
const externalReferences = new Set();
|
|
810
|
+
const localBindings = path.scope.bindings;
|
|
811
|
+
path.traverse({
|
|
812
|
+
Identifier(path) {
|
|
813
|
+
if (t.isReferenced(path.node, path.parent) && // Is a variable reference
|
|
814
|
+
!path.scope.hasBinding(path.node.name) && // Not defined in local scope
|
|
815
|
+
!localBindings[path.node.name] // Not a parameter of the function
|
|
816
|
+
) {
|
|
817
|
+
externalReferences.add(path.node.name);
|
|
818
|
+
}
|
|
819
|
+
},
|
|
820
|
+
});
|
|
821
|
+
// Remove global things they're allowed to reference
|
|
822
|
+
externalReferences.delete("Buffer");
|
|
823
|
+
externalReferences.delete("console");
|
|
824
|
+
externalReferences.delete("process");
|
|
825
|
+
externalReferences.delete("setTimeout");
|
|
826
|
+
externalReferences.delete("setInterval");
|
|
827
|
+
if (externalReferences.size > 0) {
|
|
828
|
+
throw new Error(`The function being exported as ${locationHint} references external variables: \`${[
|
|
829
|
+
...externalReferences,
|
|
830
|
+
].join("`, `")}\`. Please ensure this function is wrapped in \`EXPORTABLE(() => ...)\`. Fn:\n${fn}`);
|
|
831
|
+
}
|
|
832
|
+
const fnExpression = path.node;
|
|
833
|
+
const ownProps = Object.entries(fn);
|
|
834
|
+
const result = (() => {
|
|
835
|
+
if (ownProps.length > 0) {
|
|
836
|
+
// Need to assign things to it
|
|
837
|
+
const properties = ownProps.map(([key, value]) => {
|
|
838
|
+
return t.objectProperty(identifierOrLiteral(key), convertToIdentifierViaAST(file, value, `${locationHint}.${key}`, `${locationHint}['${key}']`));
|
|
839
|
+
});
|
|
840
|
+
return {
|
|
841
|
+
functionWithoutOwnAttributesAST: fnExpression,
|
|
842
|
+
ast: t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("assign")), [fnExpression, t.objectExpression(properties)]),
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
else {
|
|
846
|
+
return {
|
|
847
|
+
functionWithoutOwnAttributesAST: fnExpression,
|
|
848
|
+
ast: fnExpression,
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
})();
|
|
852
|
+
file._funcToAstCache.set(fn, result);
|
|
853
|
+
return result;
|
|
854
|
+
}
|
|
855
|
+
function parseExpressionViaDoc(funcString) {
|
|
856
|
+
const doc = (0, parser_1.parse)(`const f = ${funcString}`, {
|
|
857
|
+
sourceType: "module",
|
|
858
|
+
plugins: ["typescript"],
|
|
859
|
+
});
|
|
860
|
+
let result = null;
|
|
861
|
+
(0, traverse_1.default)(doc, {
|
|
862
|
+
VariableDeclaration(path) {
|
|
863
|
+
result = path.get("declarations.0.init");
|
|
864
|
+
path.stop();
|
|
865
|
+
},
|
|
866
|
+
});
|
|
867
|
+
if (!result) {
|
|
868
|
+
throw new Error(`graphile-export internal error - failed to find the variable declaration (?!!)`);
|
|
869
|
+
}
|
|
870
|
+
return result;
|
|
871
|
+
}
|
|
872
|
+
function _funcToAst(fn, locationHint, _nameHint) {
|
|
782
873
|
const funcString = fn.toString().trim();
|
|
783
874
|
try {
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
plugins: ["typescript"],
|
|
787
|
-
});
|
|
875
|
+
const path = parseExpressionViaDoc(funcString);
|
|
876
|
+
const result = path.node;
|
|
788
877
|
if (result.type !== "FunctionExpression" &&
|
|
789
878
|
result.type !== "ArrowFunctionExpression") {
|
|
790
879
|
if (result.type === "ClassExpression") {
|
|
@@ -793,7 +882,7 @@ Object.defineProperty(${result.id?.name ?? "MyClass"}, '$$export', { value: { mo
|
|
|
793
882
|
}
|
|
794
883
|
throw new Error(`Expected FunctionExpression or ArrowFunctionExpression but saw ${result.type}`);
|
|
795
884
|
}
|
|
796
|
-
return
|
|
885
|
+
return path;
|
|
797
886
|
}
|
|
798
887
|
catch (e) {
|
|
799
888
|
if (e.retry === false) {
|
|
@@ -811,15 +900,13 @@ Object.defineProperty(${result.id?.name ?? "MyClass"}, '$$export', { value: { mo
|
|
|
811
900
|
const modifiedDefinition = funcString.startsWith("async ")
|
|
812
901
|
? "async function " + funcString.slice(6)
|
|
813
902
|
: "function " + funcString;
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
plugins: ["typescript"],
|
|
817
|
-
});
|
|
903
|
+
const path = parseExpressionViaDoc(modifiedDefinition);
|
|
904
|
+
const result = path.node;
|
|
818
905
|
if (result.type !== "FunctionExpression" &&
|
|
819
906
|
result.type !== "ArrowFunctionExpression") {
|
|
820
907
|
throw new Error(`Expected FunctionExpression or ArrowFunctionExpression but saw ${result.type}`);
|
|
821
908
|
}
|
|
822
|
-
return
|
|
909
|
+
return path;
|
|
823
910
|
}
|
|
824
911
|
catch {
|
|
825
912
|
throw new Error(`Function export error at ${locationHint} - failed to process function definition '${trimDef(fn.toString())}'\n ${String(e.stack ?? e)
|
|
@@ -848,14 +935,9 @@ function exportSchemaGraphQLJS({ config, customTypes, customDirectives, file, })
|
|
|
848
935
|
? t.arrayExpression(customDirectives.map((directive) => file.declareDirective(directive)))
|
|
849
936
|
: null,
|
|
850
937
|
extensions: extensions(file, config.extensions, "schema.extensions", "schema.extensions"),
|
|
851
|
-
enableDeferStream:
|
|
852
|
-
/*
|
|
853
|
-
// TODO: use the below once https://github.com/graphql/graphql-js/pull/3450 is fixed:
|
|
854
|
-
enableDeferStream:
|
|
855
|
-
config.enableDeferStream != null
|
|
938
|
+
enableDeferStream: config.enableDeferStream != null
|
|
856
939
|
? t.booleanLiteral(config.enableDeferStream)
|
|
857
940
|
: null,
|
|
858
|
-
*/
|
|
859
941
|
assumeValid: null, // TODO: t.booleanLiteral(true),
|
|
860
942
|
}));
|
|
861
943
|
}
|
|
@@ -931,6 +1013,9 @@ function exportSchemaTypeDefs({ schema, customTypes, file, }) {
|
|
|
931
1013
|
}
|
|
932
1014
|
else if (type instanceof graphql_1.GraphQLInputObjectType) {
|
|
933
1015
|
const typeProperties = [];
|
|
1016
|
+
if (type.extensions?.grafast?.inputPlan) {
|
|
1017
|
+
typeProperties.push(t.objectProperty(identifierOrLiteral("__inputPlan"), convertToIdentifierViaAST(file, type.extensions?.grafast.inputPlan, `${type.name}.inputPlan`, `${type.name}.extensions.grafast.inputPlan`)));
|
|
1018
|
+
}
|
|
934
1019
|
for (const [fieldName, field] of Object.entries(type.toConfig().fields)) {
|
|
935
1020
|
typeProperties.push(t.objectProperty(identifierOrLiteral(fieldName), convertToIdentifierViaAST(file, field.extensions?.grafast, `${type.name}.${fieldName}`, `${type.name}.fields[${fieldName}].extensions.grafast`)));
|
|
936
1021
|
}
|
|
@@ -950,11 +1035,20 @@ function exportSchemaTypeDefs({ schema, customTypes, file, }) {
|
|
|
950
1035
|
const planAST = config.extensions.grafast?.plan
|
|
951
1036
|
? convertToIdentifierViaAST(file, config.extensions?.grafast?.plan, `${type.name}Plan`, `${type.name}.extensions.grafast.plan`)
|
|
952
1037
|
: null;
|
|
953
|
-
if (planAST
|
|
1038
|
+
if (planAST ||
|
|
1039
|
+
type.serialize !== graphql_1.GraphQLScalarType.prototype.serialize ||
|
|
1040
|
+
type.parseValue !== graphql_1.GraphQLScalarType.prototype.parseValue ||
|
|
1041
|
+
type.parseLiteral !== graphql_1.GraphQLScalarType.prototype.parseLiteral) {
|
|
954
1042
|
plansProperties.push(t.objectProperty(identifierOrLiteral(type.name), t.objectExpression(objectToObjectProperties({
|
|
955
|
-
serialize:
|
|
956
|
-
|
|
957
|
-
|
|
1043
|
+
serialize: type.serialize !== graphql_1.GraphQLScalarType.prototype.serialize
|
|
1044
|
+
? convertToIdentifierViaAST(file, type.serialize, `${type.name}Serialize`, `${type.name}.serialize`)
|
|
1045
|
+
: null,
|
|
1046
|
+
parseValue: type.parseValue !== graphql_1.GraphQLScalarType.prototype.parseValue
|
|
1047
|
+
? convertToIdentifierViaAST(file, type.parseValue, `${type.name}ParseValue`, `${type.name}.parseValue`)
|
|
1048
|
+
: null,
|
|
1049
|
+
parseLiteral: type.parseLiteral !== graphql_1.GraphQLScalarType.prototype.parseLiteral
|
|
1050
|
+
? convertToIdentifierViaAST(file, type.parseLiteral, `${type.name}ParseLiteral`, `${type.name}.parseLiteral`)
|
|
1051
|
+
: null,
|
|
958
1052
|
plan: planAST,
|
|
959
1053
|
}))));
|
|
960
1054
|
}
|
|
@@ -1016,6 +1110,11 @@ async function exportSchemaAsString(schema, options) {
|
|
|
1016
1110
|
"defer",
|
|
1017
1111
|
"stream",
|
|
1018
1112
|
].includes(d.name));
|
|
1113
|
+
if (process.env.ENABLE_DEFER_STREAM === "1" ||
|
|
1114
|
+
config.directives.some((d) => d.name === "defer" || d.name === "skip")) {
|
|
1115
|
+
// Ref: https://github.com/graphql/graphql-js/pull/3450
|
|
1116
|
+
config.enableDeferStream = true;
|
|
1117
|
+
}
|
|
1019
1118
|
const file = new CodegenFile(options);
|
|
1020
1119
|
const schemaExportDetails = {
|
|
1021
1120
|
schema,
|
|
@@ -1031,28 +1130,102 @@ async function exportSchemaAsString(schema, options) {
|
|
|
1031
1130
|
else {
|
|
1032
1131
|
exportSchemaGraphQLJS(schemaExportDetails);
|
|
1033
1132
|
}
|
|
1133
|
+
return exportFile(file);
|
|
1134
|
+
}
|
|
1135
|
+
exports.exportSchemaAsString = exportSchemaAsString;
|
|
1136
|
+
function exportFile(file) {
|
|
1034
1137
|
const ast = file.toAST();
|
|
1035
1138
|
const optimizedAst = (0, index_js_1.optimize)(ast);
|
|
1036
1139
|
const { code } = reallyGenerate(optimizedAst, {});
|
|
1037
1140
|
return { code };
|
|
1038
1141
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
const
|
|
1042
|
-
const
|
|
1043
|
-
const
|
|
1142
|
+
async function exportValueAsString(name, value, options) {
|
|
1143
|
+
const file = new CodegenFile(options);
|
|
1144
|
+
const exportName = file.makeVariable(name);
|
|
1145
|
+
const valueAST = convertToIdentifierViaAST(file, value, name, name);
|
|
1146
|
+
file.addStatements(t.exportNamedDeclaration(t.variableDeclaration("const", [
|
|
1147
|
+
t.variableDeclarator(exportName, valueAST),
|
|
1148
|
+
])));
|
|
1149
|
+
return exportFile(file);
|
|
1150
|
+
}
|
|
1151
|
+
exports.exportValueAsString = exportValueAsString;
|
|
1152
|
+
async function loadESLint() {
|
|
1153
|
+
try {
|
|
1154
|
+
return await import("eslint");
|
|
1155
|
+
}
|
|
1156
|
+
catch (e) {
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
async function lint(code, rawFilePath) {
|
|
1161
|
+
const eslintModule = await loadESLint();
|
|
1162
|
+
if (eslintModule == null) {
|
|
1163
|
+
console.warn(`graphile-export could not find 'eslint' so disabling additional checks`);
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
const filePath = typeof rawFilePath === "string" ? rawFilePath : rawFilePath.pathname;
|
|
1167
|
+
const { ESLint } = eslintModule;
|
|
1168
|
+
const eslint = new ESLint({
|
|
1169
|
+
useEslintrc: false,
|
|
1170
|
+
reportUnusedDisableDirectives: "off",
|
|
1171
|
+
allowInlineConfig: false,
|
|
1172
|
+
overrideConfig: {
|
|
1173
|
+
reportUnusedDisableDirectives: false,
|
|
1174
|
+
parserOptions: {
|
|
1175
|
+
ecmaVersion: 2020,
|
|
1176
|
+
sourceType: "module",
|
|
1177
|
+
},
|
|
1178
|
+
rules: {
|
|
1179
|
+
"no-use-before-define": [
|
|
1180
|
+
"error",
|
|
1181
|
+
{
|
|
1182
|
+
functions: false,
|
|
1183
|
+
classes: false,
|
|
1184
|
+
// We often have cyclic dependencies between types, this is handled via callbacks, so we don't care about that.
|
|
1185
|
+
variables: false,
|
|
1186
|
+
allowNamedExports: false,
|
|
1187
|
+
},
|
|
1188
|
+
],
|
|
1189
|
+
},
|
|
1190
|
+
},
|
|
1191
|
+
});
|
|
1192
|
+
const results = await eslint.lintText(code, {
|
|
1193
|
+
warnIgnored: true,
|
|
1194
|
+
// DO NOT PASS THE `filePath`; it can result in the file being ignored!
|
|
1195
|
+
});
|
|
1196
|
+
if (results.length !== 1) {
|
|
1197
|
+
console.dir({ filePath, results });
|
|
1198
|
+
throw new Error(`Expected ESLint results to have exactly one entry`);
|
|
1199
|
+
}
|
|
1200
|
+
const [result] = results;
|
|
1201
|
+
if (result.warningCount > 0 || result.errorCount > 0) {
|
|
1202
|
+
console.log(`ESLint found problems in the export; this likely indicates some issue with \`EXPORTABLE\` calls`);
|
|
1203
|
+
const formatter = await eslint.loadFormatter("stylish");
|
|
1204
|
+
const output = formatter.format(results);
|
|
1205
|
+
console.log(output);
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
async function format(toFormat, toPath, options) {
|
|
1044
1209
|
if (options.prettier) {
|
|
1045
1210
|
const prettier = await import("prettier");
|
|
1046
1211
|
const config = await prettier.resolveConfig(toPath.toString());
|
|
1047
|
-
const formatted = prettier.format(toFormat, {
|
|
1212
|
+
const formatted = await prettier.format(toFormat, {
|
|
1048
1213
|
parser: "babel",
|
|
1049
1214
|
...(config ?? {}),
|
|
1050
1215
|
});
|
|
1051
|
-
|
|
1216
|
+
return formatted;
|
|
1052
1217
|
}
|
|
1053
1218
|
else {
|
|
1054
|
-
|
|
1219
|
+
return toFormat;
|
|
1055
1220
|
}
|
|
1056
1221
|
}
|
|
1222
|
+
const HEADER = `/* eslint-disable graphile-export/export-instances, graphile-export/export-methods, graphile-export/exhaustive-deps */\n`;
|
|
1223
|
+
async function exportSchema(schema, toPath, options = {}) {
|
|
1224
|
+
const { code } = await exportSchemaAsString(schema, options);
|
|
1225
|
+
const toFormat = HEADER + code;
|
|
1226
|
+
const formatted = await format(toFormat, toPath, options);
|
|
1227
|
+
await (0, promises_1.writeFile)(toPath, formatted);
|
|
1228
|
+
await lint(formatted, toPath);
|
|
1229
|
+
}
|
|
1057
1230
|
exports.exportSchema = exportSchema;
|
|
1058
1231
|
//# sourceMappingURL=exportSchema.js.map
|