graphql-jerky 1.0.1 → 1.0.2

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.
@@ -12,6 +12,7 @@ import 'just-pascal-case';
12
12
  import 'url';
13
13
  import 'typescript';
14
14
  import 'glob';
15
+ import 'picomatch';
15
16
  import 'just-zip-it';
16
17
 
17
18
  program
package/build/lib.cjs CHANGED
@@ -10,6 +10,7 @@ var url = require('url');
10
10
  var fs = require('fs/promises');
11
11
  var ts = require('typescript');
12
12
  var glob = require('glob');
13
+ var pm = require('picomatch');
13
14
  var zip = require('just-zip-it');
14
15
 
15
16
  async function parseSource(filepath) {
@@ -419,7 +420,7 @@ class GeneratorContext {
419
420
  // NOTE: Resolver functions on interface definitions are not used by the default graphql-js
420
421
  // executor implementation, but nonetheless accessible by a potential alternate implementation.
421
422
  resolveFn && jen.prop("resolve", jen.parens(resolveFn).as.any),
422
- subscriber && jen.prop("subscribe", renderSymbolReference(this._pkgs, subscriber)),
423
+ subscriber && jen.prop("subscribe", jen.parens(renderSymbolReference(this._pkgs, subscriber)).as.any),
423
424
  ]));
424
425
  }
425
426
  _renderFieldsThunk(type, inputFieldDirectives, noresolver) {
@@ -501,7 +502,7 @@ class GeneratorContext {
501
502
  }
502
503
  _renderGraphQLObjectTypeDefinition(type, { inputFieldDirectives }) {
503
504
  const typeInterfaces = type.getInterfaces();
504
- return jen.new.add(this._gql("GraphQLObjectType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives)), ...truthify([
505
+ return jen.new.add(this._gql("GraphQLObjectType")).call(jen.obj(jen.prop("name", jen.lit(type.name)), jen.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, type.name === "Subscription")), ...truthify([
505
506
  type.description && jen.prop("description", jen.lit(type.description)),
506
507
  typeInterfaces.length && jen.prop("interfaces", jen.arrow().arr(
507
508
  // do not sort interfaces, the declaration order may be important
@@ -880,6 +881,41 @@ function generate(schema, outfile, options = {}) {
880
881
  return createGenerator(schema, options).generate(outfile);
881
882
  }
882
883
 
884
+ function createMatcher(pattern) {
885
+ if (!pattern) {
886
+ return () => false;
887
+ }
888
+ if (typeof pattern === "function") {
889
+ return pattern;
890
+ }
891
+ if (pattern instanceof RegExp) {
892
+ return (s) => pattern.test(s);
893
+ }
894
+ if (typeof pattern === "string") {
895
+ return pm(pattern);
896
+ }
897
+ let matchers = [];
898
+ let globs = [];
899
+ for (const p of Array.isArray(pattern) ? pattern : [pattern]) {
900
+ if (typeof p === "string") {
901
+ globs.push(p);
902
+ }
903
+ else if (typeof p === "function") {
904
+ matchers.push(p);
905
+ }
906
+ else if (p instanceof RegExp) {
907
+ matchers.push(RegExp.prototype.test.bind(p));
908
+ }
909
+ else {
910
+ throw new TypeError(`Invalid pattern: ${p}`);
911
+ }
912
+ }
913
+ if (globs.length) {
914
+ matchers.push(pm(globs));
915
+ }
916
+ return (s) => matchers.some((m) => m(s));
917
+ }
918
+
883
919
  async function parseResolverFile(path) {
884
920
  return Object.fromEntries(Object.entries((await parseModule(path)).exports)
885
921
  .flatMap(([name, { declaration }]) => {
@@ -897,11 +933,12 @@ async function parseResolverFile(path) {
897
933
  return [];
898
934
  }));
899
935
  }
900
- async function parseTypeResolvers(typeName, glob$1) {
936
+ async function parseTypeResolvers(typeName, glob$1, ignore) {
937
+ const shouldIgnore = createMatcher(ignore);
901
938
  const result = {};
902
939
  for await (const entry of glob.globIterate(glob$1, { withFileTypes: true })) {
903
940
  const fullpath = entry.fullpath();
904
- if (entry.isFile() && entry.name.endsWith(".ts")) {
941
+ if (!shouldIgnore(fullpath) && entry.isFile() && entry.name.endsWith(".ts")) {
905
942
  for (const [name, reference] of Object.entries(await parseResolverFile(fullpath))) {
906
943
  let realName = name;
907
944
  if (realName === "default") {
@@ -916,7 +953,7 @@ async function parseTypeResolvers(typeName, glob$1) {
916
953
  }
917
954
  return result;
918
955
  }
919
- async function parse$2(dirpath) {
956
+ async function parse$2(dirpath, ignore) {
920
957
  const dir = await fs.stat(dirpath);
921
958
  if (!dir.isDirectory()) {
922
959
  throw new Error(`Expected ${dirpath} to be a directory`);
@@ -925,14 +962,15 @@ async function parse$2(dirpath) {
925
962
  dirpath += "/";
926
963
  }
927
964
  const out = {};
965
+ const shouldIgnore = createMatcher(ignore);
928
966
  for await (const name of await fs.readdir(dirpath)) {
929
967
  const file = path.join(dirpath, name);
930
968
  const entry = await fs.stat(file);
931
969
  if (entry.isDirectory()) {
932
- out[name] = await parseTypeResolvers(name, file + "/*.ts");
970
+ out[name] = await parseTypeResolvers(name, file + "/*.ts", shouldIgnore);
933
971
  }
934
972
  else if (entry.isFile() && name.endsWith(".ts")) {
935
- out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file);
973
+ out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file, shouldIgnore);
936
974
  }
937
975
  }
938
976
  return out;
@@ -1517,9 +1555,13 @@ async function* findSchemaFiles(glob$1) {
1517
1555
  }
1518
1556
  }
1519
1557
  }
1520
- async function parse(glob) {
1558
+ async function parse(glob, ignore) {
1559
+ const shouldIgnore = createMatcher(ignore);
1521
1560
  const documentNodes = [];
1522
1561
  for await (const entry of findSchemaFiles(glob)) {
1562
+ if (shouldIgnore(entry)) {
1563
+ continue;
1564
+ }
1523
1565
  documentNodes.push(graphql.parse(new graphql.Source(await fs.readFile(entry, "utf-8"), entry)));
1524
1566
  }
1525
1567
  if (!documentNodes.length) {
package/build/lib.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import ts from 'typescript';
2
2
  import { GraphQLSchema } from 'graphql';
3
3
 
4
+ type MatchPattern = string | RegExp | ((s: string) => boolean) | Array<string | RegExp | ((s: string) => boolean)>;
5
+
4
6
  interface SymbolReference {
5
7
  module?: string;
6
8
  symbol: string;
@@ -8,8 +10,8 @@ interface SymbolReference {
8
10
  property?: string;
9
11
  }
10
12
 
11
- declare function parseTypeResolvers(typeName: string, glob: string | string[]): Promise<Record<string, SymbolReference>>;
12
- declare function parse$2(dirpath: string): Promise<Record<string, Record<string, SymbolReference>>>;
13
+ declare function parseTypeResolvers(typeName: string, glob: string | string[], ignore?: MatchPattern): Promise<Record<string, SymbolReference>>;
14
+ declare function parse$2(dirpath: string, ignore?: MatchPattern): Promise<Record<string, Record<string, SymbolReference>>>;
13
15
 
14
16
  type FunctionDeclaration = ts.MethodDeclaration | ts.FunctionExpression | ts.ArrowFunction;
15
17
  interface ScalarFnsInfo {
@@ -46,6 +48,6 @@ declare function generateSchema(schema: GraphQLSchema, outfile: string, options?
46
48
  declare function generateTypes(schema: GraphQLSchema, outfile: string, options?: GenerateOptions): string;
47
49
  declare function generate(schema: GraphQLSchema, outfile: string, options?: GenerateOptions): string;
48
50
 
49
- declare function parse(glob: string | string[]): Promise<GraphQLSchema>;
51
+ declare function parse(glob: string | string[], ignore?: MatchPattern): Promise<GraphQLSchema>;
50
52
 
51
53
  export { createGenerator, generate, generateSchema, generateTypes, parse$2 as parseResolvers, parse$1 as parseScalars, parse as parseSchema, parseTypeResolvers };
package/build/lib.mjs CHANGED
@@ -8,6 +8,7 @@ import { pathToFileURL, fileURLToPath } from 'url';
8
8
  import fs from 'fs/promises';
9
9
  import ts, { getLineAndCharacterOfPosition } from 'typescript';
10
10
  import { globIterate } from 'glob';
11
+ import pm from 'picomatch';
11
12
  import zip from 'just-zip-it';
12
13
 
13
14
  async function parseSource(filepath) {
@@ -417,7 +418,7 @@ class GeneratorContext {
417
418
  // NOTE: Resolver functions on interface definitions are not used by the default graphql-js
418
419
  // executor implementation, but nonetheless accessible by a potential alternate implementation.
419
420
  resolveFn && jen$1.prop("resolve", jen$1.parens(resolveFn).as.any),
420
- subscriber && jen$1.prop("subscribe", renderSymbolReference(this._pkgs, subscriber)),
421
+ subscriber && jen$1.prop("subscribe", jen$1.parens(renderSymbolReference(this._pkgs, subscriber)).as.any),
421
422
  ]));
422
423
  }
423
424
  _renderFieldsThunk(type, inputFieldDirectives, noresolver) {
@@ -499,7 +500,7 @@ class GeneratorContext {
499
500
  }
500
501
  _renderGraphQLObjectTypeDefinition(type, { inputFieldDirectives }) {
501
502
  const typeInterfaces = type.getInterfaces();
502
- return jen$1.new.add(this._gql("GraphQLObjectType")).call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives)), ...truthify([
503
+ return jen$1.new.add(this._gql("GraphQLObjectType")).call(jen$1.obj(jen$1.prop("name", jen$1.lit(type.name)), jen$1.prop("fields", this._renderFieldsThunk(type, inputFieldDirectives, type.name === "Subscription")), ...truthify([
503
504
  type.description && jen$1.prop("description", jen$1.lit(type.description)),
504
505
  typeInterfaces.length && jen$1.prop("interfaces", jen$1.arrow().arr(
505
506
  // do not sort interfaces, the declaration order may be important
@@ -878,6 +879,41 @@ function generate(schema, outfile, options = {}) {
878
879
  return createGenerator(schema, options).generate(outfile);
879
880
  }
880
881
 
882
+ function createMatcher(pattern) {
883
+ if (!pattern) {
884
+ return () => false;
885
+ }
886
+ if (typeof pattern === "function") {
887
+ return pattern;
888
+ }
889
+ if (pattern instanceof RegExp) {
890
+ return (s) => pattern.test(s);
891
+ }
892
+ if (typeof pattern === "string") {
893
+ return pm(pattern);
894
+ }
895
+ let matchers = [];
896
+ let globs = [];
897
+ for (const p of Array.isArray(pattern) ? pattern : [pattern]) {
898
+ if (typeof p === "string") {
899
+ globs.push(p);
900
+ }
901
+ else if (typeof p === "function") {
902
+ matchers.push(p);
903
+ }
904
+ else if (p instanceof RegExp) {
905
+ matchers.push(RegExp.prototype.test.bind(p));
906
+ }
907
+ else {
908
+ throw new TypeError(`Invalid pattern: ${p}`);
909
+ }
910
+ }
911
+ if (globs.length) {
912
+ matchers.push(pm(globs));
913
+ }
914
+ return (s) => matchers.some((m) => m(s));
915
+ }
916
+
881
917
  async function parseResolverFile(path) {
882
918
  return Object.fromEntries(Object.entries((await parseModule(path)).exports)
883
919
  .flatMap(([name, { declaration }]) => {
@@ -895,11 +931,12 @@ async function parseResolverFile(path) {
895
931
  return [];
896
932
  }));
897
933
  }
898
- async function parseTypeResolvers(typeName, glob) {
934
+ async function parseTypeResolvers(typeName, glob, ignore) {
935
+ const shouldIgnore = createMatcher(ignore);
899
936
  const result = {};
900
937
  for await (const entry of globIterate(glob, { withFileTypes: true })) {
901
938
  const fullpath = entry.fullpath();
902
- if (entry.isFile() && entry.name.endsWith(".ts")) {
939
+ if (!shouldIgnore(fullpath) && entry.isFile() && entry.name.endsWith(".ts")) {
903
940
  for (const [name, reference] of Object.entries(await parseResolverFile(fullpath))) {
904
941
  let realName = name;
905
942
  if (realName === "default") {
@@ -914,7 +951,7 @@ async function parseTypeResolvers(typeName, glob) {
914
951
  }
915
952
  return result;
916
953
  }
917
- async function parse$2(dirpath) {
954
+ async function parse$2(dirpath, ignore) {
918
955
  const dir = await fs.stat(dirpath);
919
956
  if (!dir.isDirectory()) {
920
957
  throw new Error(`Expected ${dirpath} to be a directory`);
@@ -923,14 +960,15 @@ async function parse$2(dirpath) {
923
960
  dirpath += "/";
924
961
  }
925
962
  const out = {};
963
+ const shouldIgnore = createMatcher(ignore);
926
964
  for await (const name of await fs.readdir(dirpath)) {
927
965
  const file = join(dirpath, name);
928
966
  const entry = await fs.stat(file);
929
967
  if (entry.isDirectory()) {
930
- out[name] = await parseTypeResolvers(name, file + "/*.ts");
968
+ out[name] = await parseTypeResolvers(name, file + "/*.ts", shouldIgnore);
931
969
  }
932
970
  else if (entry.isFile() && name.endsWith(".ts")) {
933
- out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file);
971
+ out[name.slice(0, -3)] = await parseTypeResolvers(name.slice(0, -3), file, shouldIgnore);
934
972
  }
935
973
  }
936
974
  return out;
@@ -1515,9 +1553,13 @@ async function* findSchemaFiles(glob) {
1515
1553
  }
1516
1554
  }
1517
1555
  }
1518
- async function parse(glob) {
1556
+ async function parse(glob, ignore) {
1557
+ const shouldIgnore = createMatcher(ignore);
1519
1558
  const documentNodes = [];
1520
1559
  for await (const entry of findSchemaFiles(glob)) {
1560
+ if (shouldIgnore(entry)) {
1561
+ continue;
1562
+ }
1521
1563
  documentNodes.push(parse$3(new Source(await fs.readFile(entry, "utf-8"), entry)));
1522
1564
  }
1523
1565
  if (!documentNodes.length) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphql-jerky",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Jerky is a schema-first static graphql schema lightweight code generator.",
5
5
  "type": "module",
6
6
  "bin": "./build/bin/jerky.cjs",
@@ -19,11 +19,13 @@
19
19
  "just-partition": "^2.2.0",
20
20
  "just-pascal-case": "^3.2.0",
21
21
  "just-zip-it": "^3.2.0",
22
+ "picomatch": "^2.3.1",
22
23
  "typescript": "^5.1.3"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@rollup/plugin-typescript": "^11.1.1",
26
27
  "@types/node": "^20.3.1",
28
+ "@types/picomatch": "^2.3.0",
27
29
  "rollup": "^3.25.1",
28
30
  "rollup-plugin-dts": "^5.3.0",
29
31
  "tslib": "^2.5.3"