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.
@@ -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 (typeof thing === "function") {
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?.name ?? thingConstructor?.displayName ?? null;
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("Attempted to export GraphQLSchema directly from `_convertToAST`; this is currently unsupported.");
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
- let hasUnsafeKeys = false;
578
- Object.entries(thing).forEach(([key, value]) => {
579
- const tKey = identifierOrLiteral(key);
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 = isExportedFromFactory(thing)
663
- ? factoryAst(file, thing, locationHint, nameHint)
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
- if (isExportedFromFactory(fn)) {
713
- return factoryAst(file, fn, locationHint, nameHint);
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 result = (0, parser_1.parseExpression)(funcString, {
785
- sourceType: "module",
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 result;
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 result = (0, parser_1.parseExpression)(modifiedDefinition, {
815
- sourceType: "module",
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 result;
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: t.booleanLiteral(process.env.ENABLE_DEFER_STREAM === "1"),
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: convertToIdentifierViaAST(file, type.serialize, `${type.name}Serialize`, `${type.name}.serialize`),
956
- parseValue: convertToIdentifierViaAST(file, type.parseValue, `${type.name}ParseValue`, `${type.name}.parseValue`),
957
- parseLiteral: convertToIdentifierViaAST(file, type.parseLiteral, `${type.name}ParseLiteral`, `${type.name}.parseLiteral`),
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
- exports.exportSchemaAsString = exportSchemaAsString;
1040
- async function exportSchema(schema, toPath, options = {}) {
1041
- const { code } = await exportSchemaAsString(schema, options);
1042
- const HEADER = `/* eslint-disable graphile-export/export-instances, graphile-export/export-methods, graphile-export/exhaustive-deps */\n`;
1043
- const toFormat = HEADER + code;
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
- await (0, promises_1.writeFile)(toPath, formatted);
1216
+ return formatted;
1052
1217
  }
1053
1218
  else {
1054
- await (0, promises_1.writeFile)(toPath, toFormat);
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