graphql-jerky 1.0.6 → 1.0.8

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.
@@ -2,9 +2,9 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- var path = require('path');
5
+ var fs = require('node:fs/promises');
6
+ var path = require('node:path');
6
7
  var commander = require('commander');
7
- var fs = require('fs/promises');
8
8
  var lib = require('../lib.cjs');
9
9
 
10
10
  commander.program
@@ -13,37 +13,43 @@ commander.program
13
13
  .description("Schema-first GraphQL typescript code generator")
14
14
  .argument("[schema]", "Path to schema file or directory.")
15
15
  .option("-o, --out <destination>", "Path to write schema_gen.ts.")
16
+ .option("-t", "Write types to a separate file.")
17
+ .option("--types-out <destination>", "Path to write types_gen.ts. Types will be written in types_gen.ts if omitted and -t is used.")
16
18
  .option("--graphql <module>", "graphql module import specifier.")
17
19
  .option("--scalars <module>", "scalars module import specifier.")
18
20
  .option("--resolvers <directory>", "resolvers directory path.")
19
21
  .option("--subscribers <module>", "subscriber module import specifier.")
20
22
  .option("--field-directives <module>", "field directives module import specifier.")
21
23
  .option("--input-directives <module>", "input directives module import specifier.")
24
+ .option("--include-ast-nodes", "Include ast nodes in graphql type objects")
25
+ .option("--include-subscription-resolvers", "Include subscription field resolvers in graphql type objects")
22
26
  .option("--ext <mode>", 'whether "keep", "replace", or "omit" the .ts extension in import statements.')
23
27
  .showHelpAfterError(true);
24
28
  commander.program.parse();
25
- const { out = "schema_gen.ts", graphql = "graphql", scalars, resolvers, subscribers, fieldDirectives, inputDirectives, ext = "omit", } = commander.program.opts();
29
+ const { out = "schema_gen.ts", typesOut, graphql = "graphql", scalars, resolvers, subscribers, fieldDirectives, inputDirectives, ext = "omit", t: splitTypesFile, includeAstNodes, includeSubscriptionResolvers: includeSubscriptionFieldResolvers, } = commander.program.opts();
26
30
  const [schema = "."] = commander.program.args;
27
- (async () => {
28
- let outfile = out;
29
- if (!outfile.pathname.endsWith("/")) {
31
+ async function normalizeOutfile(path, defaultFilename) {
32
+ if (!path.endsWith("/")) {
30
33
  // test if it's a directory
31
34
  try {
32
- const stat = await fs.stat(outfile);
35
+ const stat = await fs.stat(path);
33
36
  if (stat.isDirectory()) {
34
- outfile += "/";
37
+ path += "/";
35
38
  }
36
39
  }
37
40
  catch {
38
41
  // probably doesn't exist yet
39
42
  }
40
43
  }
41
- if (outfile.endsWith("/")) {
42
- outfile += "schema_gen.ts";
44
+ if (path.endsWith("/")) {
45
+ path += defaultFilename;
43
46
  }
44
- if (!outfile.endsWith(".ts")) {
45
- outfile += ".ts";
47
+ if (!path.endsWith(".ts")) {
48
+ path += ".ts";
46
49
  }
50
+ return path;
51
+ }
52
+ (async () => {
47
53
  switch (ext) {
48
54
  case "keep":
49
55
  case "replace":
@@ -52,7 +58,7 @@ const [schema = "."] = commander.program.args;
52
58
  default:
53
59
  throw new Error(`invalid mode for --ext: ${ext}`);
54
60
  }
55
- await fs.writeFile(outfile, lib.generate(await lib.parseSchema(path.resolve(schema)), outfile.pathname, {
61
+ const generator = lib.createGenerator(await lib.parseSchema(path.resolve(schema)), {
56
62
  scalarsInfo: scalars ? await lib.parseScalars(scalars) : undefined,
57
63
  fieldDirectivesInfo: fieldDirectives
58
64
  ? await lib.parseTypeResolvers("", fieldDirectives)
@@ -66,9 +72,22 @@ const [schema = "."] = commander.program.args;
66
72
  : undefined,
67
73
  graphqlModuleSpecifier: graphql,
68
74
  extMode: ext,
69
- }));
75
+ includeAstNodes,
76
+ includeSubscriptionFieldResolvers,
77
+ });
78
+ const outfile = await normalizeOutfile(out, "schema_gen.ts");
79
+ if (splitTypesFile || typesOut) {
80
+ const typesfile = await normalizeOutfile(typesOut ?? path.dirname(outfile), "types_gen.ts");
81
+ await Promise.all([
82
+ fs.writeFile(outfile, generator.generateSchema(outfile)),
83
+ fs.writeFile(typesfile, generator.generateTypes(typesfile)),
84
+ ]);
85
+ }
86
+ else {
87
+ await fs.writeFile(outfile, generator.generate(outfile));
88
+ }
70
89
  })().catch((err) => {
71
- console.error(err.message);
90
+ console.error(err.stack);
72
91
  console.log();
73
92
  if (process.argv.length === 2 ||
74
93
  (process.argv.length === 3 && process.argv[2] === "help")) {
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import path from 'path';
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
4
5
  import { program } from 'commander';
5
- import fs from 'fs/promises';
6
- import { generate, parseScalars as parse, parseTypeResolvers, parseResolvers as parse$1, parseSchema as parse$2 } from '../lib.mjs';
7
- import 'url';
6
+ import { createGenerator, parseScalars as parse, parseTypeResolvers, parseResolvers as parse$1, parseSchema as parse$2 } from '../lib.mjs';
7
+ import 'node:url';
8
8
  import 'graphql';
9
9
  import 'jennifer-js';
10
10
  import 'jennifer-js/format';
@@ -21,37 +21,43 @@ program
21
21
  .description("Schema-first GraphQL typescript code generator")
22
22
  .argument("[schema]", "Path to schema file or directory.")
23
23
  .option("-o, --out <destination>", "Path to write schema_gen.ts.")
24
+ .option("-t", "Write types to a separate file.")
25
+ .option("--types-out <destination>", "Path to write types_gen.ts. Types will be written in types_gen.ts if omitted and -t is used.")
24
26
  .option("--graphql <module>", "graphql module import specifier.")
25
27
  .option("--scalars <module>", "scalars module import specifier.")
26
28
  .option("--resolvers <directory>", "resolvers directory path.")
27
29
  .option("--subscribers <module>", "subscriber module import specifier.")
28
30
  .option("--field-directives <module>", "field directives module import specifier.")
29
31
  .option("--input-directives <module>", "input directives module import specifier.")
32
+ .option("--include-ast-nodes", "Include ast nodes in graphql type objects")
33
+ .option("--include-subscription-resolvers", "Include subscription field resolvers in graphql type objects")
30
34
  .option("--ext <mode>", 'whether "keep", "replace", or "omit" the .ts extension in import statements.')
31
35
  .showHelpAfterError(true);
32
36
  program.parse();
33
- const { out = "schema_gen.ts", graphql = "graphql", scalars, resolvers, subscribers, fieldDirectives, inputDirectives, ext = "omit", } = program.opts();
37
+ const { out = "schema_gen.ts", typesOut, graphql = "graphql", scalars, resolvers, subscribers, fieldDirectives, inputDirectives, ext = "omit", t: splitTypesFile, includeAstNodes, includeSubscriptionResolvers: includeSubscriptionFieldResolvers, } = program.opts();
34
38
  const [schema = "."] = program.args;
35
- (async () => {
36
- let outfile = out;
37
- if (!outfile.pathname.endsWith("/")) {
39
+ async function normalizeOutfile(path, defaultFilename) {
40
+ if (!path.endsWith("/")) {
38
41
  // test if it's a directory
39
42
  try {
40
- const stat = await fs.stat(outfile);
43
+ const stat = await fs.stat(path);
41
44
  if (stat.isDirectory()) {
42
- outfile += "/";
45
+ path += "/";
43
46
  }
44
47
  }
45
48
  catch {
46
49
  // probably doesn't exist yet
47
50
  }
48
51
  }
49
- if (outfile.endsWith("/")) {
50
- outfile += "schema_gen.ts";
52
+ if (path.endsWith("/")) {
53
+ path += defaultFilename;
51
54
  }
52
- if (!outfile.endsWith(".ts")) {
53
- outfile += ".ts";
55
+ if (!path.endsWith(".ts")) {
56
+ path += ".ts";
54
57
  }
58
+ return path;
59
+ }
60
+ (async () => {
55
61
  switch (ext) {
56
62
  case "keep":
57
63
  case "replace":
@@ -60,7 +66,7 @@ const [schema = "."] = program.args;
60
66
  default:
61
67
  throw new Error(`invalid mode for --ext: ${ext}`);
62
68
  }
63
- await fs.writeFile(outfile, generate(await parse$2(path.resolve(schema)), outfile.pathname, {
69
+ const generator = createGenerator(await parse$2(path.resolve(schema)), {
64
70
  scalarsInfo: scalars ? await parse(scalars) : undefined,
65
71
  fieldDirectivesInfo: fieldDirectives
66
72
  ? await parseTypeResolvers("", fieldDirectives)
@@ -74,9 +80,22 @@ const [schema = "."] = program.args;
74
80
  : undefined,
75
81
  graphqlModuleSpecifier: graphql,
76
82
  extMode: ext,
77
- }));
83
+ includeAstNodes,
84
+ includeSubscriptionFieldResolvers,
85
+ });
86
+ const outfile = await normalizeOutfile(out, "schema_gen.ts");
87
+ if (splitTypesFile || typesOut) {
88
+ const typesfile = await normalizeOutfile(typesOut ?? path.dirname(outfile), "types_gen.ts");
89
+ await Promise.all([
90
+ fs.writeFile(outfile, generator.generateSchema(outfile)),
91
+ fs.writeFile(typesfile, generator.generateTypes(typesfile)),
92
+ ]);
93
+ }
94
+ else {
95
+ await fs.writeFile(outfile, generator.generate(outfile));
96
+ }
78
97
  })().catch((err) => {
79
- console.error(err.message);
98
+ console.error(err.stack);
80
99
  console.log();
81
100
  if (process.argv.length === 2 ||
82
101
  (process.argv.length === 3 && process.argv[2] === "help")) {
package/build/lib.cjs CHANGED
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
- var path = require('path');
4
- var url = require('url');
3
+ var path = require('node:path');
4
+ var node_url = require('node:url');
5
5
  var graphql = require('graphql');
6
6
  var jen = require('jennifer-js');
7
7
  var format = require('jennifer-js/format');
8
8
  var partition = require('just-partition');
9
9
  var pascalCase = require('just-pascal-case');
10
- var fs = require('fs/promises');
10
+ var fs = require('node:fs/promises');
11
11
  var ts = require('typescript');
12
12
  var glob = require('glob');
13
13
  var pm = require('picomatch');
@@ -225,12 +225,12 @@ async function findExports(source, resolveModuleFn = resolveModule) {
225
225
  return exports;
226
226
  }
227
227
  async function parseModule(sourceOrPath) {
228
- const url$1 = typeof sourceOrPath === "string"
229
- ? url.pathToFileURL(path.resolve(sourceOrPath))
228
+ const url = typeof sourceOrPath === "string"
229
+ ? node_url.pathToFileURL(path.resolve(sourceOrPath))
230
230
  : new URL(sourceOrPath.fileName);
231
- const source = typeof sourceOrPath === "string" ? await parseSource(url$1) : sourceOrPath;
231
+ const source = typeof sourceOrPath === "string" ? await parseSource(url) : sourceOrPath;
232
232
  return {
233
- path: url$1,
233
+ path: url,
234
234
  exports: await findExports(source),
235
235
  source,
236
236
  };
@@ -305,7 +305,7 @@ function renderImports(base, imports, aliases, extMode = "omit") {
305
305
  return jen.statements(...imports.map(([pkg, symbols]) => {
306
306
  let mod = pkg;
307
307
  if (mod.startsWith("file:///")) {
308
- mod = url.fileURLToPath(mod);
308
+ mod = node_url.fileURLToPath(mod);
309
309
  }
310
310
  if (mod.startsWith("/")) {
311
311
  mod = path.relative(base, mod);
@@ -371,7 +371,8 @@ class GeneratorContext {
371
371
  this._graphqlModuleSpecifier = options.graphqlModuleSpecifier ?? "graphql";
372
372
  this._pkgs = new RequiredPackages();
373
373
  this._extMode = options.extMode ?? "omit";
374
- this._includeSubscriptionFieldResolvers = options.includeSubscriptionFieldResolvers ?? false;
374
+ this._includeSubscriptionFieldResolvers =
375
+ options.includeSubscriptionFieldResolvers ?? false;
375
376
  }
376
377
  _gql(name) {
377
378
  return jen.id(this._pkgs.addRequires(this._graphqlModuleSpecifier, name));
@@ -603,7 +604,8 @@ class GeneratorContext {
603
604
  const typeInterfaces = type.getInterfaces();
604
605
  return jen.new
605
606
  .add(this._gql("GraphQLObjectType"))
606
- .call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, !this._includeSubscriptionFieldResolvers && type.name === "Subscription")), ...truthify([
607
+ .call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, !this._includeSubscriptionFieldResolvers &&
608
+ type.name === "Subscription")), ...truthify([
607
609
  type.description &&
608
610
  jen.prop("description", jen.lit(type.description)),
609
611
  typeInterfaces.length &&
@@ -863,6 +865,27 @@ class GeneratorContext {
863
865
  .block(jen.return(jen.id("v").in.add(this._renderGraphQLTypeType(type)))),
864
866
  ];
865
867
  }
868
+ _getGraphQLTypeClass(type) {
869
+ if (type instanceof graphql.GraphQLObjectType) {
870
+ return "GraphQLObjectType";
871
+ }
872
+ if (type instanceof graphql.GraphQLScalarType) {
873
+ return "GraphQLScalarType";
874
+ }
875
+ if (type instanceof graphql.GraphQLInterfaceType) {
876
+ return "GraphQLInterfaceType";
877
+ }
878
+ if (type instanceof graphql.GraphQLUnionType) {
879
+ return "GraphQLUnionType";
880
+ }
881
+ if (type instanceof graphql.GraphQLInputObjectType) {
882
+ return "GraphQLInputObjectType";
883
+ }
884
+ if (type instanceof graphql.GraphQLEnumType) {
885
+ return "GraphQLEnumType";
886
+ }
887
+ throw new Error(`unhandled type: ${type.toString()}`);
888
+ }
866
889
  _getRenderDefintionFnForType(type) {
867
890
  if (type instanceof graphql.GraphQLObjectType) {
868
891
  return this._renderGraphQLObjectTypeDefinition.bind(this, type);
@@ -908,6 +931,8 @@ class GeneratorContext {
908
931
  _renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives, includeAstNodes) {
909
932
  return jen.const
910
933
  .add(this._renderGraphQLTypeIdentifier(type))
934
+ .op(":")
935
+ .id(this._getGraphQLTypeClass(type))
911
936
  .op("=")
912
937
  .add(this._getRenderDefintionFnForType(type)({
913
938
  implementors: interfaces[type.name],
package/build/lib.mjs CHANGED
@@ -1,11 +1,11 @@
1
- import path, { resolve, basename, extname, join } from 'path';
2
- import { pathToFileURL, fileURLToPath } from 'url';
1
+ import path, { resolve, basename, extname, join } from 'node:path';
2
+ import { pathToFileURL, fileURLToPath } from 'node:url';
3
3
  import { GraphQLNonNull, GraphQLList, GraphQLScalarType, GraphQLEnumType, GraphQLDirective, Kind, GraphQLObjectType, getNamedType, getNullableType, GraphQLInterfaceType, GraphQLUnionType, GraphQLInputObjectType, DirectiveLocation, GraphQLError, parse as parse$3, Source, buildASTSchema, validateSchema } from 'graphql';
4
4
  import jen$1, { jen } from 'jennifer-js';
5
5
  import format from 'jennifer-js/format';
6
6
  import partition from 'just-partition';
7
7
  import pascalCase from 'just-pascal-case';
8
- import fs from 'fs/promises';
8
+ import fs from 'node:fs/promises';
9
9
  import ts, { getLineAndCharacterOfPosition } from 'typescript';
10
10
  import { globIterate } from 'glob';
11
11
  import pm from 'picomatch';
@@ -369,7 +369,8 @@ class GeneratorContext {
369
369
  this._graphqlModuleSpecifier = options.graphqlModuleSpecifier ?? "graphql";
370
370
  this._pkgs = new RequiredPackages();
371
371
  this._extMode = options.extMode ?? "omit";
372
- this._includeSubscriptionFieldResolvers = options.includeSubscriptionFieldResolvers ?? false;
372
+ this._includeSubscriptionFieldResolvers =
373
+ options.includeSubscriptionFieldResolvers ?? false;
373
374
  }
374
375
  _gql(name) {
375
376
  return jen$1.id(this._pkgs.addRequires(this._graphqlModuleSpecifier, name));
@@ -601,7 +602,8 @@ class GeneratorContext {
601
602
  const typeInterfaces = type.getInterfaces();
602
603
  return jen$1.new
603
604
  .add(this._gql("GraphQLObjectType"))
604
- .call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, !this._includeSubscriptionFieldResolvers && type.name === "Subscription")), ...truthify([
605
+ .call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, includeAstNodes, !this._includeSubscriptionFieldResolvers &&
606
+ type.name === "Subscription")), ...truthify([
605
607
  type.description &&
606
608
  jen$1.prop("description", jen$1.lit(type.description)),
607
609
  typeInterfaces.length &&
@@ -861,6 +863,27 @@ class GeneratorContext {
861
863
  .block(jen$1.return(jen$1.id("v").in.add(this._renderGraphQLTypeType(type)))),
862
864
  ];
863
865
  }
866
+ _getGraphQLTypeClass(type) {
867
+ if (type instanceof GraphQLObjectType) {
868
+ return "GraphQLObjectType";
869
+ }
870
+ if (type instanceof GraphQLScalarType) {
871
+ return "GraphQLScalarType";
872
+ }
873
+ if (type instanceof GraphQLInterfaceType) {
874
+ return "GraphQLInterfaceType";
875
+ }
876
+ if (type instanceof GraphQLUnionType) {
877
+ return "GraphQLUnionType";
878
+ }
879
+ if (type instanceof GraphQLInputObjectType) {
880
+ return "GraphQLInputObjectType";
881
+ }
882
+ if (type instanceof GraphQLEnumType) {
883
+ return "GraphQLEnumType";
884
+ }
885
+ throw new Error(`unhandled type: ${type.toString()}`);
886
+ }
864
887
  _getRenderDefintionFnForType(type) {
865
888
  if (type instanceof GraphQLObjectType) {
866
889
  return this._renderGraphQLObjectTypeDefinition.bind(this, type);
@@ -906,6 +929,8 @@ class GeneratorContext {
906
929
  _renderGraphQLTypeDefinitions(type, interfaces, inputFieldDirectives, includeAstNodes) {
907
930
  return jen$1.const
908
931
  .add(this._renderGraphQLTypeIdentifier(type))
932
+ .op(":")
933
+ .id(this._getGraphQLTypeClass(type))
909
934
  .op("=")
910
935
  .add(this._getRenderDefintionFnForType(type)({
911
936
  implementors: interfaces[type.name],
package/package.json CHANGED
@@ -1,38 +1,38 @@
1
1
  {
2
- "name": "graphql-jerky",
3
- "version": "1.0.6",
4
- "description": "Jerky is a schema-first static graphql schema lightweight code generator.",
5
- "type": "module",
6
- "bin": "./build/bin/jerky.cjs",
7
- "types": "./build/lib.d.ts",
8
- "module": "./build/lib.mjs",
9
- "main": "./build/lib.cjs",
10
- "scripts": {
11
- "build": "rollup -c",
12
- "prepack": "npm run build"
13
- },
14
- "dependencies": {
15
- "commander": "^10.0.1",
16
- "glob": "^10.2.7",
17
- "graphql": "^16.6.0",
18
- "jennifer-js": "^1.0.0",
19
- "just-partition": "^2.2.0",
20
- "just-pascal-case": "^3.2.0",
21
- "just-zip-it": "^3.2.0",
22
- "picomatch": "^2.3.1",
23
- "typescript": "^5.1.3"
24
- },
25
- "devDependencies": {
26
- "@biomejs/biome": "^1.4.1",
27
- "@rollup/plugin-typescript": "^11.1.1",
28
- "@types/node": "^20.3.1",
29
- "@types/picomatch": "^2.3.0",
30
- "rollup": "^3.25.1",
31
- "rollup-plugin-dts": "^5.3.0",
32
- "tslib": "^2.5.3"
33
- },
34
- "files": [
35
- "build"
36
- ],
37
- "license": "MIT"
2
+ "name": "graphql-jerky",
3
+ "version": "1.0.8",
4
+ "description": "Jerky is a schema-first static graphql schema lightweight code generator.",
5
+ "type": "module",
6
+ "bin": "./build/bin/jerky.cjs",
7
+ "types": "./build/lib.d.ts",
8
+ "module": "./build/lib.mjs",
9
+ "main": "./build/lib.cjs",
10
+ "scripts": {
11
+ "build": "rollup -c",
12
+ "prepack": "npm run build"
13
+ },
14
+ "dependencies": {
15
+ "commander": "^10.0.1",
16
+ "glob": "^10.2.7",
17
+ "graphql": "^16.6.0",
18
+ "jennifer-js": "^1.0.0",
19
+ "just-partition": "^2.2.0",
20
+ "just-pascal-case": "^3.2.0",
21
+ "just-zip-it": "^3.2.0",
22
+ "picomatch": "^2.3.1",
23
+ "typescript": "^5.1.3"
24
+ },
25
+ "devDependencies": {
26
+ "@biomejs/biome": "^1.4.1",
27
+ "@rollup/plugin-typescript": "^11.1.1",
28
+ "@types/node": "^20.3.1",
29
+ "@types/picomatch": "^2.3.0",
30
+ "rollup": "^3.25.1",
31
+ "rollup-plugin-dts": "^5.3.0",
32
+ "tslib": "^2.5.3"
33
+ },
34
+ "files": [
35
+ "build"
36
+ ],
37
+ "license": "MIT"
38
38
  }