@gqloom/core 0.4.0 → 0.6.0

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/README.md CHANGED
@@ -8,24 +8,24 @@ The design of GQLoom is inspired by [tRPC](https://trpc.io/), [TypeGraphQL](http
8
8
 
9
9
  ## Features
10
10
 
11
- - 🚀 GraphQL: flexible and efficient, reducing redundant data transfers;
12
- - 🔒 Robust type safety: enjoy intelligent hints at development time to detect potential problems at compile time;
13
- - 🔋 Ready to go: middleware, contexts, subscriptions, federated graphs are ready to go;
14
- - 🔮 No extra magic: no decorators, no metadata and reflection, no code generation, you just need JavaScript/TypeScript;
15
- - 🧩 Familiar schema libraries: use the schema libraries you already know (Zod, Yup, Valibot) to build GraphQL Schema and validate inputs;
16
- - 🧑‍💻 Develop happily: highly readable and semantic APIs designed to keep your code tidy;
11
+ * 🚀 GraphQL: flexible and efficient, reducing redundant data transfers;
12
+ * 🔒 Robust type safety: enjoy intelligent hints at development time to detect potential problems at compile time;
13
+ * 🔋 Ready to go: middleware, contexts, subscriptions, federated graphs are ready to go;
14
+ * 🔮 No extra magic: no decorators, no metadata and reflection, no code generation, you just need JavaScript/TypeScript;
15
+ * 🧩 Familiar schema libraries: use the schema libraries you already know (Zod, Yup, Valibot) to build GraphQL Schema and validate inputs;
16
+ * 🧑‍💻 Develop happily: highly readable and semantic APIs designed to keep your code tidy;
17
17
 
18
18
  ## Hello World
19
19
 
20
20
  ```ts
21
- import { resolver, query, weave } from "@gqloom/valibot"
21
+ import { resolver, query, ValibotWeaver } from "@gqloom/valibot"
22
22
  import * as v from "valibot"
23
23
 
24
- const HelloResolver = resolver({
24
+ const helloResolver = resolver({
25
25
  hello: query(v.string(), () => "world"),
26
26
  })
27
27
 
28
- export const schema = weave(HelloResolver)
28
+ export const schema = ValibotWeaver.weave(helloResolver)
29
29
  ```
30
30
 
31
31
  Read [Introduction](https://gqloom.dev/guide/introduction.html) to learn more about GQLoom.
package/dist/index.cjs CHANGED
@@ -21,10 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  ContextMemoization: () => ContextMemoization,
24
+ GraphQLSchemaLoom: () => GraphQLSchemaLoom,
24
25
  LoomObjectType: () => LoomObjectType,
26
+ OPERATION_OBJECT_NAMES: () => OPERATION_OBJECT_NAMES,
25
27
  ResolverOptionsMap: () => ResolverOptionsMap,
26
28
  SYMBOLS: () => symbols_exports,
27
- SchemaWeaver: () => SchemaWeaver,
28
29
  applyMiddlewares: () => applyMiddlewares,
29
30
  baseResolver: () => baseResolver,
30
31
  collectName: () => collectName,
@@ -67,6 +68,7 @@ __export(src_exports, {
67
68
  onlyMemoization: () => onlyMemoization,
68
69
  parseInputValue: () => parseInputValue,
69
70
  parseSilk: () => parseSilk,
71
+ pascalCase: () => pascalCase,
70
72
  provideWeaverContext: () => provideWeaverContext,
71
73
  query: () => query,
72
74
  resolver: () => resolver,
@@ -227,7 +229,9 @@ function collectName(name, schema) {
227
229
  }
228
230
 
229
231
  // src/resolver/silk.ts
230
- function silk(type, validate = (value) => ({ value: value ?? void 0 })) {
232
+ function silk(type, validate = (value) => ({
233
+ value: value ?? void 0
234
+ })) {
231
235
  return {
232
236
  [GET_GRAPHQL_TYPE]: typeof type === "function" ? type : () => type,
233
237
  "~standard": {
@@ -332,13 +336,17 @@ function getFieldOptions({
332
336
  }
333
337
 
334
338
  // src/utils/middleware.ts
335
- function applyMiddlewares(middlewares, resolveFunction, payload) {
339
+ function applyMiddlewares(middlewares, resolveFunction, options) {
336
340
  const next = (index) => {
337
341
  if (index >= middlewares.length) {
338
342
  return resolveFunction();
339
343
  }
340
344
  const middleware = middlewares[index];
341
- return middleware(() => next(index + 1), payload);
345
+ const callableOptions = Object.assign(() => next(index + 1), {
346
+ ...options,
347
+ next: () => next(index + 1)
348
+ });
349
+ return middleware(callableOptions);
342
350
  };
343
351
  return next(0);
344
352
  }
@@ -491,6 +499,13 @@ function deepMerge(...objects) {
491
499
  return result;
492
500
  }
493
501
 
502
+ // src/utils/string.ts
503
+ function pascalCase(str) {
504
+ return str.split(/[\s-_]+/).map(
505
+ (word, index) => index === 0 ? word.charAt(0).toUpperCase() + word.slice(1) : word.charAt(0).toUpperCase() + word.slice(1)
506
+ ).join("");
507
+ }
508
+
494
509
  // src/utils/error.ts
495
510
  function markErrorLocation(error, ...locations) {
496
511
  if (error instanceof Error) {
@@ -790,31 +805,38 @@ var import_graphql5 = require("graphql");
790
805
 
791
806
  // src/schema/input.ts
792
807
  var import_graphql4 = require("graphql");
793
- function inputToArgs(input) {
808
+ function inputToArgs(input, options) {
794
809
  if (input === void 0) return void 0;
795
810
  if (isSilk(input)) {
796
811
  let inputType = getGraphQLType(input);
797
812
  if ((0, import_graphql4.isNonNullType)(inputType)) inputType = inputType.ofType;
798
813
  if ((0, import_graphql4.isObjectType)(inputType)) {
799
- return mapValue(
800
- inputType.toConfig().fields,
801
- (it) => toInputFieldConfig(it)
802
- );
814
+ return mapValue(inputType.toConfig().fields, (it, key) => {
815
+ let fieldName;
816
+ if (options?.fieldName) {
817
+ fieldName = `${pascalCase(options.fieldName)}${pascalCase(key)}`;
818
+ }
819
+ return toInputFieldConfig(it, { fieldName });
820
+ });
803
821
  }
804
822
  throw new Error(`Cannot convert ${inputType.toString()} to input type`);
805
823
  }
806
824
  const args = {};
807
825
  Object.entries(input).forEach(([name, field2]) => {
808
826
  tryIn(() => {
827
+ let fieldName;
828
+ if (options?.fieldName) {
829
+ fieldName = `${pascalCase(options.fieldName)}${pascalCase(name)}`;
830
+ }
809
831
  args[name] = {
810
832
  ...field2,
811
- type: ensureInputType(field2)
833
+ type: ensureInputType(field2, { fieldName })
812
834
  };
813
835
  }, name);
814
836
  });
815
837
  return args;
816
838
  }
817
- function ensureInputType(silkOrType) {
839
+ function ensureInputType(silkOrType, options) {
818
840
  const gqlType = (() => {
819
841
  if (isSilk(silkOrType)) {
820
842
  return getGraphQLType(silkOrType);
@@ -824,48 +846,56 @@ function ensureInputType(silkOrType) {
824
846
  if ((0, import_graphql4.isUnionType)(gqlType))
825
847
  throw new Error(`Cannot convert union type ${gqlType.name} to input type`);
826
848
  if ((0, import_graphql4.isNonNullType)(gqlType)) {
827
- return new import_graphql4.GraphQLNonNull(ensureInputType(gqlType.ofType));
849
+ return new import_graphql4.GraphQLNonNull(ensureInputType(gqlType.ofType, options));
828
850
  }
829
851
  if ((0, import_graphql4.isListType)(gqlType)) {
830
- return new import_graphql4.GraphQLList(ensureInputType(gqlType.ofType));
852
+ return new import_graphql4.GraphQLList(ensureInputType(gqlType.ofType, options));
831
853
  }
832
854
  if ((0, import_graphql4.isObjectType)(gqlType) || (0, import_graphql4.isInterfaceType)(gqlType))
833
- return ensureInputObjectType(gqlType);
855
+ return ensureInputObjectType(gqlType, options);
834
856
  return gqlType;
835
857
  }
836
- function ensureInputObjectType(object) {
858
+ function ensureInputObjectType(object, options) {
837
859
  if ((0, import_graphql4.isInputObjectType)(object)) return object;
838
860
  const existing = weaverContext.inputMap?.get(object);
839
861
  if (existing != null) return existing;
840
- const {
841
- astNode: _,
842
- extensionASTNodes: __,
843
- fields,
844
- ...config
845
- } = object.toConfig();
846
- const getInputObjectName = weaverContext.getConfig("gqloom.core.schema")?.getInputObjectName ?? ((name) => name);
862
+ const { astNode, extensionASTNodes, fields, ...config } = object.toConfig();
863
+ let name = object.name;
864
+ if (name === LoomObjectType.AUTO_ALIASING) {
865
+ name = `${pascalCase(options?.fieldName ?? "")}Input`;
866
+ }
867
+ const getInputObjectName = weaverContext.getConfig("gqloom.core.schema")?.getInputObjectName ?? ((n) => n);
868
+ name = getInputObjectName(name);
847
869
  const input = new import_graphql4.GraphQLInputObjectType({
848
870
  ...config,
849
- name: getInputObjectName(object.name),
871
+ name,
850
872
  fields: provideWeaverContext.inherit(
851
- () => mapValue(fields, (it) => toInputFieldConfig(it))
873
+ () => mapValue(
874
+ fields,
875
+ (it, key) => toInputFieldConfig(it, {
876
+ fieldName: inputFieldName(name) + pascalCase(key)
877
+ })
878
+ )
852
879
  )
853
880
  });
854
881
  weaverContext.inputMap?.set(object, input);
855
882
  return input;
856
883
  }
857
- function toInputFieldConfig({
858
- astNode: _,
859
- resolve: _1,
860
- ...config
861
- }) {
862
- return { ...config, type: ensureInputType(config.type) };
884
+ function toInputFieldConfig({ astNode, resolve, ...config }, options) {
885
+ return { ...config, type: ensureInputType(config.type, options) };
886
+ }
887
+ function inputFieldName(name) {
888
+ while (name.endsWith("Input")) {
889
+ name = name.slice(0, -"Input".length);
890
+ }
891
+ return name;
863
892
  }
864
893
 
865
894
  // src/schema/object.ts
866
- var LoomObjectType = class extends import_graphql5.GraphQLObjectType {
895
+ var LoomObjectType = class _LoomObjectType extends import_graphql5.GraphQLObjectType {
867
896
  extraFields = /* @__PURE__ */ new Map();
868
897
  hiddenFields = /* @__PURE__ */ new Set();
898
+ static AUTO_ALIASING = "__gqloom_auto_aliasing";
869
899
  weaverContext;
870
900
  resolverOptions;
871
901
  constructor(objectOrGetter, options = {}) {
@@ -882,6 +912,28 @@ var LoomObjectType = class extends import_graphql5.GraphQLObjectType {
882
912
  super(config);
883
913
  this.resolverOptions = options.resolverOptions;
884
914
  this.weaverContext = options.weaverContext ?? initWeaverContext();
915
+ if (this.name !== _LoomObjectType.AUTO_ALIASING) {
916
+ this.hasExplicitName = true;
917
+ }
918
+ }
919
+ hasExplicitName;
920
+ _aliases = [];
921
+ get aliases() {
922
+ return this._aliases;
923
+ }
924
+ addAlias(name) {
925
+ if (this.hasExplicitName) return;
926
+ this._aliases.push(name);
927
+ this.renameByAliases();
928
+ }
929
+ renameByAliases() {
930
+ let name;
931
+ for (const alias of this.aliases) {
932
+ if (name === void 0 || alias.length < name.length) {
933
+ name = alias;
934
+ }
935
+ }
936
+ if (name) this.name = name;
885
937
  }
886
938
  hideField(name) {
887
939
  this.hiddenFields.add(name);
@@ -899,8 +951,8 @@ var LoomObjectType = class extends import_graphql5.GraphQLObjectType {
899
951
  extraFieldMap;
900
952
  getFields() {
901
953
  const fieldsBySuper = super.getFields();
902
- Object.values(fieldsBySuper).forEach(
903
- (field2) => field2.type = this.getCacheType(field2.type)
954
+ Object.entries(fieldsBySuper).forEach(
955
+ ([fieldName, field2]) => field2.type = this.getCacheType(field2.type, fieldName)
904
956
  );
905
957
  const extraFields = provideWeaverContext(
906
958
  () => defineFieldMap(this.mapToFieldConfig(this.extraFields)),
@@ -921,17 +973,22 @@ var LoomObjectType = class extends import_graphql5.GraphQLObjectType {
921
973
  mapToFieldConfig(map) {
922
974
  const record = {};
923
975
  for (const [name, field2] of map.entries()) {
924
- record[name] = this.toFieldConfig(field2);
976
+ record[name] = this.toFieldConfig(field2, name);
925
977
  }
926
978
  return record;
927
979
  }
928
- toFieldConfig(field2) {
980
+ toFieldConfig(field2, fieldName) {
929
981
  try {
930
- const outputType = this.getCacheType(getGraphQLType(field2.output));
982
+ const outputType = this.getCacheType(
983
+ getGraphQLType(field2.output),
984
+ fieldName
985
+ );
931
986
  return {
932
987
  ...extract(field2),
933
988
  type: outputType,
934
- args: inputToArgs(field2.input),
989
+ args: inputToArgs(field2.input, {
990
+ fieldName: fieldName ? parentName(this.name) + fieldName : void 0
991
+ }),
935
992
  ...this.provideForResolve(field2),
936
993
  ...this.provideForSubscribe(field2)
937
994
  };
@@ -964,8 +1021,8 @@ var LoomObjectType = class extends import_graphql5.GraphQLObjectType {
964
1021
  )
965
1022
  };
966
1023
  }
967
- getCacheType(gqlType) {
968
- return getCacheType(gqlType, this.options);
1024
+ getCacheType(gqlType, fieldName) {
1025
+ return getCacheType(gqlType, { ...this.options, fieldName, parent: this });
969
1026
  }
970
1027
  get options() {
971
1028
  const { resolverOptions, weaverContext: weaverContext2 } = this;
@@ -1011,6 +1068,11 @@ function defineArguments(args) {
1011
1068
  astNode: argConfig.astNode
1012
1069
  }));
1013
1070
  }
1071
+ var OPERATION_OBJECT_NAMES = /* @__PURE__ */ new Set([
1072
+ "Query",
1073
+ "Mutation",
1074
+ "Subscription"
1075
+ ]);
1014
1076
  function getCacheType(gqlType, options = {}) {
1015
1077
  const context = options.weaverContext ?? weaverContext;
1016
1078
  if (gqlType instanceof LoomObjectType) return gqlType;
@@ -1019,6 +1081,11 @@ function getCacheType(gqlType, options = {}) {
1019
1081
  if (gqlObject != null) return gqlObject;
1020
1082
  const loomObject = new LoomObjectType(gqlType, options);
1021
1083
  context.loomObjectMap?.set(gqlType, loomObject);
1084
+ if (options.fieldName && options.parent) {
1085
+ loomObject.addAlias(
1086
+ parentName(options.parent.name) + pascalCase(options.fieldName)
1087
+ );
1088
+ }
1022
1089
  return loomObject;
1023
1090
  } else if ((0, import_graphql5.isListType)(gqlType)) {
1024
1091
  return new import_graphql5.GraphQLList(getCacheType(gqlType.ofType, options));
@@ -1039,8 +1106,12 @@ function getCacheType(gqlType, options = {}) {
1039
1106
  }
1040
1107
  return gqlType;
1041
1108
  }
1109
+ function parentName(name) {
1110
+ if (OPERATION_OBJECT_NAMES.has(name)) name = "";
1111
+ return name;
1112
+ }
1042
1113
 
1043
- // src/schema/schema-vendor-weaver.ts
1114
+ // src/schema/schema-weaver.ts
1044
1115
  function isSchemaVendorWeaver(some) {
1045
1116
  if (typeof some !== "object" && typeof some !== "function") return false;
1046
1117
  if (!("getGraphQLType" in some) || typeof some.getGraphQLType !== "function")
@@ -1049,9 +1120,9 @@ function isSchemaVendorWeaver(some) {
1049
1120
  return true;
1050
1121
  }
1051
1122
 
1052
- // src/schema/schema-weaver.ts
1123
+ // src/schema/schema-loom.ts
1053
1124
  var import_graphql6 = require("graphql");
1054
- var SchemaWeaver = class _SchemaWeaver {
1125
+ var GraphQLSchemaLoom = class _GraphQLSchemaLoom {
1055
1126
  query;
1056
1127
  mutation;
1057
1128
  subscription;
@@ -1073,7 +1144,7 @@ var SchemaWeaver = class _SchemaWeaver {
1073
1144
  if (query2 != null) this.query = query2;
1074
1145
  if (mutation2 != null) this.mutation = mutation2;
1075
1146
  if (subscription2 != null) this.subscription = subscription2;
1076
- if (types != null) this.types = types.slice();
1147
+ this.types = new Set(types ?? []);
1077
1148
  this.context = context ?? initWeaverContext();
1078
1149
  }
1079
1150
  use(...middlewares) {
@@ -1107,8 +1178,7 @@ var SchemaWeaver = class _SchemaWeaver {
1107
1178
  `${gqlType2?.name ?? gqlType2.toString()} is not a named type`
1108
1179
  );
1109
1180
  }, this.context);
1110
- this.types ??= [];
1111
- this.types.push(gqlType);
1181
+ this.types.add(gqlType);
1112
1182
  return this;
1113
1183
  }
1114
1184
  setConfig(config) {
@@ -1134,16 +1204,17 @@ var SchemaWeaver = class _SchemaWeaver {
1134
1204
  if (parent == null) return void 0;
1135
1205
  let gqlType = getGraphQLType(parent);
1136
1206
  if ((0, import_graphql6.isNonNullType)(gqlType)) gqlType = gqlType.ofType;
1137
- if ((0, import_graphql6.isObjectType)(gqlType)) {
1138
- const existing = this.context.loomObjectMap.get(gqlType);
1139
- if (existing != null) return existing;
1140
- const extraObject = new LoomObjectType(gqlType, this.fieldOptions);
1141
- this.context.loomObjectMap.set(gqlType, extraObject);
1142
- return extraObject;
1207
+ if (!(0, import_graphql6.isObjectType)(gqlType)) {
1208
+ throw new Error(
1209
+ `${gqlType?.name ?? gqlType.toString()} is not an object type`
1210
+ );
1143
1211
  }
1144
- throw new Error(
1145
- `${gqlType?.name ?? gqlType.toString()} is not an object type`
1146
- );
1212
+ const existing = this.context.loomObjectMap.get(gqlType);
1213
+ if (existing != null) return existing;
1214
+ const extraObject = new LoomObjectType(gqlType, this.fieldOptions);
1215
+ this.context.loomObjectMap.set(gqlType, extraObject);
1216
+ this.types.add(extraObject);
1217
+ return extraObject;
1147
1218
  })();
1148
1219
  if (resolverOptions?.extensions && parentObject)
1149
1220
  parentObject.mergeExtensions(resolverOptions.extensions);
@@ -1218,12 +1289,12 @@ var SchemaWeaver = class _SchemaWeaver {
1218
1289
  }
1219
1290
  /**
1220
1291
  * Weave a GraphQL Schema from resolvers
1221
- * @param inputs Resolvers, Global Middlewares or WeaverConfigs
1222
- * @returns GraphQ LSchema
1292
+ * @param inputs Resolvers, Global Middlewares, WeaverConfigs Or SchemaWeaver
1293
+ * @returns GraphQL Schema
1223
1294
  */
1224
1295
  static weave(...inputs) {
1225
- const { context, configs, middlewares, resolvers, silks, weavers } = _SchemaWeaver.optionsFrom(...inputs);
1226
- const weaver = new _SchemaWeaver({}, context);
1296
+ const { context, configs, middlewares, resolvers, silks, weavers } = _GraphQLSchemaLoom.optionsFrom(...inputs);
1297
+ const weaver = new _GraphQLSchemaLoom({}, context);
1227
1298
  configs.forEach((it) => weaver.setConfig(it));
1228
1299
  weavers.forEach((it) => weaver.addVendor(it));
1229
1300
  middlewares.forEach((it) => weaver.use(it));
@@ -1232,7 +1303,7 @@ var SchemaWeaver = class _SchemaWeaver {
1232
1303
  return weaver.weaveGraphQLSchema();
1233
1304
  }
1234
1305
  };
1235
- var weave = SchemaWeaver.weave;
1306
+ var weave = GraphQLSchemaLoom.weave;
1236
1307
 
1237
1308
  // src/schema/interface.ts
1238
1309
  var import_graphql7 = require("graphql");
@@ -1262,10 +1333,11 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1262
1333
  // Annotate the CommonJS export names for ESM import in node:
1263
1334
  0 && (module.exports = {
1264
1335
  ContextMemoization,
1336
+ GraphQLSchemaLoom,
1265
1337
  LoomObjectType,
1338
+ OPERATION_OBJECT_NAMES,
1266
1339
  ResolverOptionsMap,
1267
1340
  SYMBOLS,
1268
- SchemaWeaver,
1269
1341
  applyMiddlewares,
1270
1342
  baseResolver,
1271
1343
  collectName,
@@ -1308,6 +1380,7 @@ function ensureInterfaceType(gqlType, interfaceConfig) {
1308
1380
  onlyMemoization,
1309
1381
  parseInputValue,
1310
1382
  parseSilk,
1383
+ pascalCase,
1311
1384
  provideWeaverContext,
1312
1385
  query,
1313
1386
  resolver,