joist-graphql-resolver-utils 2.3.0-next.7 → 2.3.0-next.71

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.
Files changed (129) hide show
  1. package/build/context.cjs +2 -0
  2. package/build/context.d.cts +7 -0
  3. package/build/context.d.cts.map +1 -0
  4. package/build/context.d.mts +7 -0
  5. package/build/context.d.mts.map +1 -0
  6. package/build/context.js +2 -3
  7. package/build/cursorPagination.cjs +104 -0
  8. package/build/cursorPagination.cjs.map +1 -0
  9. package/build/cursorPagination.d.cts +43 -0
  10. package/build/cursorPagination.d.cts.map +1 -0
  11. package/build/cursorPagination.d.mts +43 -0
  12. package/build/cursorPagination.d.mts.map +1 -0
  13. package/build/cursorPagination.js +88 -62
  14. package/build/cursorPagination.js.map +1 -1
  15. package/build/entityResolver.cjs +95 -0
  16. package/build/entityResolver.cjs.map +1 -0
  17. package/build/entityResolver.d.cts +23 -0
  18. package/build/entityResolver.d.cts.map +1 -0
  19. package/build/entityResolver.d.mts +23 -0
  20. package/build/entityResolver.d.mts.map +1 -0
  21. package/build/entityResolver.js +84 -135
  22. package/build/entityResolver.js.map +1 -1
  23. package/build/hint.cjs +50 -0
  24. package/build/hint.cjs.map +1 -0
  25. package/build/hint.d.cts +12 -0
  26. package/build/hint.d.cts.map +1 -0
  27. package/build/hint.d.mts +12 -0
  28. package/build/hint.d.mts.map +1 -0
  29. package/build/hint.js +36 -65
  30. package/build/hint.js.map +1 -1
  31. package/build/index.cjs +14 -0
  32. package/build/index.d.cts +6 -0
  33. package/build/index.d.mts +6 -0
  34. package/build/index.js +6 -17
  35. package/build/limitPagination.cjs +68 -0
  36. package/build/limitPagination.cjs.map +1 -0
  37. package/build/limitPagination.d.cts +34 -0
  38. package/build/limitPagination.d.cts.map +1 -0
  39. package/build/limitPagination.d.mts +34 -0
  40. package/build/limitPagination.d.mts.map +1 -0
  41. package/build/limitPagination.js +62 -52
  42. package/build/limitPagination.js.map +1 -1
  43. package/build/makeRunInputMutation.cjs +21 -0
  44. package/build/makeRunInputMutation.cjs.map +1 -0
  45. package/build/{makeRunInputMutation.d.ts → makeRunInputMutation.d.cts} +9 -7
  46. package/build/makeRunInputMutation.d.cts.map +1 -0
  47. package/build/makeRunInputMutation.d.mts +24 -0
  48. package/build/makeRunInputMutation.d.mts.map +1 -0
  49. package/build/makeRunInputMutation.js +16 -14
  50. package/build/makeRunInputMutation.js.map +1 -1
  51. package/build/makeRunObjectField.cjs +22 -0
  52. package/build/makeRunObjectField.cjs.map +1 -0
  53. package/build/{makeRunObjectField.d.ts → makeRunObjectField.d.cts} +7 -5
  54. package/build/makeRunObjectField.d.cts.map +1 -0
  55. package/build/makeRunObjectField.d.mts +16 -0
  56. package/build/makeRunObjectField.d.mts.map +1 -0
  57. package/build/makeRunObjectField.js +17 -16
  58. package/build/makeRunObjectField.js.map +1 -1
  59. package/build/makeRunObjectFields.cjs +24 -0
  60. package/build/makeRunObjectFields.cjs.map +1 -0
  61. package/build/{makeRunObjectFields.d.ts → makeRunObjectFields.d.cts} +8 -8
  62. package/build/makeRunObjectFields.d.cts.map +1 -0
  63. package/build/makeRunObjectFields.d.mts +15 -0
  64. package/build/makeRunObjectFields.d.mts.map +1 -0
  65. package/build/makeRunObjectFields.js +19 -19
  66. package/build/makeRunObjectFields.js.map +1 -1
  67. package/build/makeRunQuery.cjs +20 -0
  68. package/build/makeRunQuery.cjs.map +1 -0
  69. package/build/{makeRunQuery.d.ts → makeRunQuery.d.cts} +7 -5
  70. package/build/makeRunQuery.d.cts.map +1 -0
  71. package/build/makeRunQuery.d.mts +20 -0
  72. package/build/makeRunQuery.d.mts.map +1 -0
  73. package/build/makeRunQuery.js +15 -14
  74. package/build/makeRunQuery.js.map +1 -1
  75. package/build/paginationUtils.cjs +34 -0
  76. package/build/paginationUtils.cjs.map +1 -0
  77. package/build/paginationUtils.d.cts +17 -0
  78. package/build/paginationUtils.d.cts.map +1 -0
  79. package/build/paginationUtils.d.mts +17 -0
  80. package/build/paginationUtils.d.mts.map +1 -0
  81. package/build/paginationUtils.js +30 -4
  82. package/build/paginationUtils.js.map +1 -1
  83. package/build/saveEntity.cjs +24 -0
  84. package/build/saveEntity.cjs.map +1 -0
  85. package/build/saveEntity.d.cts +15 -0
  86. package/build/saveEntity.d.cts.map +1 -0
  87. package/build/saveEntity.d.mts +15 -0
  88. package/build/saveEntity.d.mts.map +1 -0
  89. package/build/saveEntity.js +15 -13
  90. package/build/saveEntity.js.map +1 -1
  91. package/build/tests.cjs +9 -0
  92. package/build/tests.d.cts +6 -0
  93. package/build/tests.d.mts +6 -0
  94. package/build/tests.js +5 -27
  95. package/build/typeUtils.cjs +2 -0
  96. package/build/typeUtils.d.cts +11 -0
  97. package/build/typeUtils.d.cts.map +1 -0
  98. package/build/typeUtils.d.mts +11 -0
  99. package/build/typeUtils.d.mts.map +1 -0
  100. package/build/typeUtils.js +2 -3
  101. package/package.json +74 -16
  102. package/build/context.d.ts +0 -4
  103. package/build/context.d.ts.map +0 -1
  104. package/build/context.js.map +0 -1
  105. package/build/cursorPagination.d.ts +0 -33
  106. package/build/cursorPagination.d.ts.map +0 -1
  107. package/build/entityResolver.d.ts +0 -25
  108. package/build/entityResolver.d.ts.map +0 -1
  109. package/build/hint.d.ts +0 -9
  110. package/build/hint.d.ts.map +0 -1
  111. package/build/index.d.ts +0 -6
  112. package/build/index.d.ts.map +0 -1
  113. package/build/index.js.map +0 -1
  114. package/build/limitPagination.d.ts +0 -28
  115. package/build/limitPagination.d.ts.map +0 -1
  116. package/build/makeRunInputMutation.d.ts.map +0 -1
  117. package/build/makeRunObjectField.d.ts.map +0 -1
  118. package/build/makeRunObjectFields.d.ts.map +0 -1
  119. package/build/makeRunQuery.d.ts.map +0 -1
  120. package/build/paginationUtils.d.ts +0 -7
  121. package/build/paginationUtils.d.ts.map +0 -1
  122. package/build/saveEntity.d.ts +0 -12
  123. package/build/saveEntity.d.ts.map +0 -1
  124. package/build/tests.d.ts +0 -6
  125. package/build/tests.d.ts.map +0 -1
  126. package/build/tests.js.map +0 -1
  127. package/build/typeUtils.d.ts +0 -10
  128. package/build/typeUtils.d.ts.map +0 -1
  129. package/build/typeUtils.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ import { Resolver } from "./context.mjs";
2
+ import { Collection, Entity, EntityMetadata, IdOf, MaybeAbstractEntityConstructor, Property, ReactiveGetter, ReadOnlyCollection, Reference } from "joist-core";
3
+ //#region src/entityResolver.d.ts
4
+ type GraphQLPrimitive = string | Date | boolean | number | bigint | null | undefined;
5
+ /**
6
+ * Maps properties like `Entity.firstName: string` to field resolver functions like `firstName(): Promise<string>`.
7
+ *
8
+ * Note that we don't necessarily know/care if `firstName` is in the `Entity` GraphQL type, we just map
9
+ * every field to a potential resolver, and then will let the `EntityResolvers` type-check effectively
10
+ * do the union of "what's defined on the ORM type vs. what's defined on the GraphQL type".
11
+ *
12
+ * Note this might require setting GraphQL options like `requireResolversToMatchSchema: ignore` to avoid
13
+ * the GraphQL infra complaining about the extra field resolvers that Joist creates for fields that
14
+ * are not technically mapped in your GraphQL schema.
15
+ */
16
+ type EntityResolver<T extends Entity> = { [P in keyof T]: P extends "id" ? Resolver<T, Record<string, any>, IdOf<T>> : T[P] extends GraphQLPrimitive | GraphQLPrimitive[] ? Resolver<T, Record<string, any>, T[P]> : T[P] extends Collection<any, infer U> ? Resolver<T, Record<string, any>, U[]> : T[P] extends ReadOnlyCollection<any, infer U> ? Resolver<T, Record<string, any>, U[]> : T[P] extends Reference<any, infer U, infer N> ? Resolver<T, Record<string, any>, U | N> : T[P] extends Property<any, infer V> ? Resolver<T, Record<string, any>, V> : T[P] extends ReactiveGetter<any, infer V> ? Resolver<T, Record<string, any>, V> : T[P] extends Promise<infer V> ? Resolver<T, Record<string, any>, V> : T[P] extends (() => Promise<infer V>) ? Resolver<T, Record<string, any>, V> : T[P] extends (() => infer V) ? Resolver<T, Record<string, any>, V> : Resolver<T, Record<string, any>, T[P]>; };
17
+ /**
18
+ * Creates field resolvers for each of the fields on our entity.
19
+ */
20
+ declare function entityResolver<T extends Entity, A extends Record<string, keyof T> = {}>(entity: MaybeAbstractEntityConstructor<T> | EntityMetadata<T>, aliases?: A): EntityResolver<T> & { [K in keyof A]: EntityResolver<T>[A[K]]; };
21
+ //#endregion
22
+ export { EntityResolver, entityResolver };
23
+ //# sourceMappingURL=entityResolver.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entityResolver.d.mts","names":[],"sources":["../src/entityResolver.ts"],"mappings":";;;KAwCK,4BAA4B;;;;;;;;;;;;KAarB,eAAe,UAAU,aAClC,WAAW,IAAI,iBACZ,SAAS,GAAG,qBAAqB,KAAK,MACtC,EAAE,WAAW,mBAAmB,qBAC9B,SAAS,GAAG,qBAAqB,EAAE,MACnC,EAAE,WAAW,sBAAsB,KACjC,SAAS,GAAG,qBAAqB,OACjC,EAAE,WAAW,8BAA8B,KACzC,SAAS,GAAG,qBAAqB,OACjC,EAAE,WAAW,qBAAqB,SAAS,KACzC,SAAS,GAAG,qBAAqB,IAAI,KACrC,EAAE,WAAW,oBAAoB,KAC/B,SAAS,GAAG,qBAAqB,KACjC,EAAE,WAAW,0BAA0B,KACrC,SAAS,GAAG,qBAAqB,KACjC,EAAE,WAAW,cAAc,KACzB,SAAS,GAAG,qBAAqB,KACjC,EAAE,kBAAiB,cAAc,MAC/B,SAAS,GAAG,qBAAqB,KACjC,EAAE,wBAAuB,KACvB,SAAS,GAAG,qBAAqB,KACjC,SAAS,GAAG,qBAAqB,EAAE;;;;iBAM3C,eAAe,UAAU,QAAQ,UAAU,qBAAqB,SAC9E,QAAQ,+BAA+B,KAAK,eAAe,IAC3D,UAAU,IACT,eAAe,QAAQ,WAAW,IAAI,eAAe,GAAG,EAAE"}
@@ -1,145 +1,94 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.entityResolver = entityResolver;
4
- const joist_core_1 = require("joist-core");
5
- const hint_1 = require("./hint");
1
+ import "./context.js";
2
+ import { convertInfoToLoadHint } from "./hint.js";
3
+ import "graphql/type";
4
+ import { getMetadata, getProperties, isAsyncProperty, isCollection, isLoadedAsyncProperty, isLoadedCollection, isLoadedLazyField, isLoadedProperty, isLoadedReadOnlyCollection, isLoadedReference, isManyToOneField, isOneToManyField, isProperty, isReactiveGetter, isReadOnlyCollection, isReference } from "joist-core";
5
+ //#region src/entityResolver.ts
6
6
  /**
7
- * Creates field resolvers for each of the fields on our entity.
8
- */
7
+ * Creates field resolvers for each of the fields on our entity.
8
+ */
9
9
  function entityResolver(entity, aliases) {
10
- const entityMetadata = (0, joist_core_1.getMetadata)(entity);
11
- const idResolver = (entityOrId) => {
12
- return typeof entityOrId === "string" ? entityOrId : entityOrId.id;
13
- };
14
- const primitiveResolvers = Object.values(entityMetadata.allFields)
15
- .filter((ormField) => !isPrimaryKeyField(ormField) && !isReferenceField(ormField) && !isCollectionField(ormField))
16
- .map((ormField) => {
17
- if ("derived" in ormField && ormField.derived === "async") {
18
- return [ormField.fieldName, (entity) => entity[ormField.fieldName].get];
19
- }
20
- else {
21
- // Currently, we only support primitives, i.e. strings/numbers/etc. and not collections.
22
- return [ormField.fieldName, (entity) => entity[ormField.fieldName]];
23
- }
24
- });
25
- const referenceResolvers = Object.values(entityMetadata.allFields)
26
- .filter((ormField) => isReferenceField(ormField))
27
- .map((ormField) => [
28
- ormField.fieldName,
29
- (entity, args, ctx, info) => {
30
- // Use the `info` to see if the query is only returning `{ id }` and if so avoid fetching the entity
31
- if ((ormField.kind === "m2o" || ormField.kind === "poly") && info?.fieldNodes.length === 1) {
32
- const selectionSet = info.fieldNodes[0].selectionSet;
33
- // We can't do this if the expected return type uses inheritance, as graphql wouldn't know how to map to a
34
- // resolver with just an id since there could be multiple implementations
35
- const hasAbstractType = (ormField.kind === "m2o" && ormField.otherMetadata().inheritanceType !== undefined) ||
36
- (ormField.kind === "poly" &&
37
- ormField.components.some((c) => c.otherMetadata().inheritanceType !== undefined));
38
- if (selectionSet && !hasAbstractType) {
39
- if (selectionSet.selections.length === 1 &&
40
- selectionSet.selections[0].kind === "Field" &&
41
- selectionSet.selections[0].name.value === "id") {
42
- // This is cheating and returning the "wrong root", but our `id` field resolvers
43
- // knows to look for it, to optimize this case and avoiding the unnecessary load
44
- return entity[ormField.fieldName].idMaybe;
45
- }
46
- }
47
- }
48
- const reference = entity[ormField.fieldName];
49
- if ((0, joist_core_1.isLoadedReference)(reference)) {
50
- return reference.get;
51
- }
52
- // We skip polys b/c they can't have load hints anyway
53
- if (info && ((0, joist_core_1.isManyToOneField)(ormField) || (0, joist_core_1.isOneToManyField)(ormField))) {
54
- // See if we can populate the collection from the GraphQL selection set
55
- const loadHint = (0, hint_1.convertInfoToLoadHint)(ormField.otherMetadata(), info);
56
- if (loadHint) {
57
- const parentHint = { [ormField.fieldName]: loadHint };
58
- return entity.em.populate(entity, parentHint).then(() => reference.get);
59
- }
60
- }
61
- return reference.load();
62
- },
63
- ]);
64
- const collectionResolvers = Object.values(entityMetadata.allFields)
65
- .filter((ormField) => isCollectionField(ormField))
66
- .map((ormField) => [
67
- ormField.fieldName,
68
- (entity, args, ctx, info) => {
69
- const field = ormField;
70
- const collection = entity[field.fieldName];
71
- if ((0, joist_core_1.isLoadedCollection)(collection)) {
72
- return collection.get;
73
- }
74
- if (info) {
75
- // See if we can populate the collection from the GraphQL selection set
76
- const loadHint = (0, hint_1.convertInfoToLoadHint)(field.otherMetadata(), info);
77
- if (loadHint) {
78
- const parentHint = { [field.fieldName]: loadHint };
79
- return entity.em.populate(entity, parentHint).then(() => collection.get);
80
- }
81
- }
82
- return collection.load();
83
- },
84
- ]);
85
- const ormResolvers = Object.fromEntries([...primitiveResolvers, ...referenceResolvers, ...collectionResolvers]);
86
- // Look for non-orm properties on the domain object's prototype
87
- // and on an instance of the domain object itself to get
88
- // non-prototype properties like CustomReferences
89
- const alreadyFoundKeys = Object.keys(ormResolvers);
90
- const customProperties = Object.keys((0, joist_core_1.getProperties)(entityMetadata)).filter((n) => !alreadyFoundKeys.includes(n));
91
- const customResolvers = customProperties.map((key) => [
92
- key,
93
- (entity) => {
94
- const property = entity[key];
95
- if (typeof property === "function") {
96
- // Support methods like `async name(): Promise<string>`
97
- return property.apply(entity);
98
- }
99
- else if ((0, joist_core_1.isReactiveGetter)(property)) {
100
- return property.get;
101
- }
102
- else if ((0, joist_core_1.isReference)(property) || (0, joist_core_1.isCollection)(property) || (0, joist_core_1.isProperty)(property)) {
103
- if ((0, joist_core_1.isLoadedReference)(property) || (0, joist_core_1.isLoadedCollection)(property) || (0, joist_core_1.isLoadedProperty)(property)) {
104
- return property.get;
105
- }
106
- // ...we need to know the `property.otherMetadata()` return type, which isn't available right now
107
- // const loadHint = convertInfoToLoadHint(getMetadata(entity), info);
108
- // if (loadHint) {
109
- // return entity.em.populate(entity, loadHint).then(() => (property as any).get);
110
- // }
111
- return property.load();
112
- }
113
- else if ((0, joist_core_1.isReadOnlyCollection)(property)) {
114
- if ((0, joist_core_1.isLoadedReadOnlyCollection)(property)) {
115
- return property.get;
116
- }
117
- return property.load();
118
- }
119
- else {
120
- return property;
121
- }
122
- },
123
- ]);
124
- let resolvers = {
125
- id: idResolver,
126
- ...ormResolvers,
127
- ...Object.fromEntries(customResolvers),
128
- };
129
- if (aliases) {
130
- Object.entries(aliases).forEach(([alias, field]) => {
131
- resolvers[alias] = resolvers[field];
132
- });
133
- }
134
- return resolvers;
10
+ const entityMetadata = getMetadata(entity);
11
+ const idResolver = (entityOrId) => {
12
+ return typeof entityOrId === "string" ? entityOrId : entityOrId.id;
13
+ };
14
+ const primitiveResolvers = Object.values(entityMetadata.allFields).filter((ormField) => !isPrimaryKeyField(ormField) && !isReferenceField(ormField) && !isCollectionField(ormField)).map((ormField) => {
15
+ if ("derived" in ormField && ormField.derived === "async") return [ormField.fieldName, (entity) => entity[ormField.fieldName].get];
16
+ else if ("lazy" in ormField && ormField.lazy) return [ormField.fieldName, (entity) => {
17
+ const lazyField = entity[ormField.fieldName];
18
+ return isLoadedLazyField(lazyField) ? lazyField.get : lazyField.load();
19
+ }];
20
+ else return [ormField.fieldName, (entity) => entity[ormField.fieldName]];
21
+ });
22
+ const referenceResolvers = Object.values(entityMetadata.allFields).filter((ormField) => isReferenceField(ormField)).map((ormField) => [ormField.fieldName, (entity, args, ctx, info) => {
23
+ if ((ormField.kind === "m2o" || ormField.kind === "poly") && info?.fieldNodes.length === 1) {
24
+ const selectionSet = info.fieldNodes[0].selectionSet;
25
+ const hasAbstractType = ormField.kind === "m2o" && ormField.otherMetadata().inheritanceType !== void 0 || ormField.kind === "poly" && ormField.components.some((c) => c.otherMetadata().inheritanceType !== void 0);
26
+ if (selectionSet && !hasAbstractType) {
27
+ if (selectionSet.selections.length === 1 && selectionSet.selections[0].kind === "Field" && selectionSet.selections[0].name.value === "id") return entity[ormField.fieldName].idMaybe;
28
+ }
29
+ }
30
+ const reference = entity[ormField.fieldName];
31
+ if (isLoadedReference(reference)) return reference.get;
32
+ if (info && (isManyToOneField(ormField) || isOneToManyField(ormField))) {
33
+ const loadHint = convertInfoToLoadHint(ormField.otherMetadata(), info);
34
+ if (loadHint) {
35
+ const parentHint = { [ormField.fieldName]: loadHint };
36
+ return entity.em.populate(entity, parentHint).then(() => reference.get);
37
+ }
38
+ }
39
+ return reference.load();
40
+ }]);
41
+ const collectionResolvers = Object.values(entityMetadata.allFields).filter((ormField) => isCollectionField(ormField)).map((ormField) => [ormField.fieldName, (entity, args, ctx, info) => {
42
+ const field = ormField;
43
+ const collection = entity[field.fieldName];
44
+ if (isLoadedCollection(collection)) return collection.get;
45
+ if (info) {
46
+ const loadHint = convertInfoToLoadHint(field.otherMetadata(), info);
47
+ if (loadHint) {
48
+ const parentHint = { [field.fieldName]: loadHint };
49
+ return entity.em.populate(entity, parentHint).then(() => collection.get);
50
+ }
51
+ }
52
+ return collection.load();
53
+ }]);
54
+ const ormResolvers = Object.fromEntries([
55
+ ...primitiveResolvers,
56
+ ...referenceResolvers,
57
+ ...collectionResolvers
58
+ ]);
59
+ const alreadyFoundKeys = Object.keys(ormResolvers);
60
+ const customResolvers = Object.keys(getProperties(entityMetadata)).filter((n) => !alreadyFoundKeys.includes(n)).map((key) => [key, (entity) => {
61
+ const property = entity[key];
62
+ if (typeof property === "function") return property.apply(entity);
63
+ else if (isReactiveGetter(property)) return property.get;
64
+ else if (isReference(property) || isCollection(property) || isProperty(property) || isAsyncProperty(property)) {
65
+ if (isLoadedReference(property) || isLoadedCollection(property) || isLoadedProperty(property) || isLoadedAsyncProperty(property)) return property.get;
66
+ return property.load();
67
+ } else if (isReadOnlyCollection(property)) {
68
+ if (isLoadedReadOnlyCollection(property)) return property.get;
69
+ return property.load();
70
+ } else return property;
71
+ }]);
72
+ let resolvers = {
73
+ id: idResolver,
74
+ ...ormResolvers,
75
+ ...Object.fromEntries(customResolvers)
76
+ };
77
+ if (aliases) Object.entries(aliases).forEach(([alias, field]) => {
78
+ resolvers[alias] = resolvers[field];
79
+ });
80
+ return resolvers;
135
81
  }
136
82
  function isReferenceField(ormField) {
137
- return ormField.kind === "m2o" || ormField.kind === "o2o" || ormField.kind === "poly";
83
+ return ormField.kind === "m2o" || ormField.kind === "o2o" || ormField.kind === "poly";
138
84
  }
139
85
  function isCollectionField(ormField) {
140
- return ormField.kind === "o2m" || ormField.kind === "m2m";
86
+ return ormField.kind === "o2m" || ormField.kind === "m2m";
141
87
  }
142
88
  function isPrimaryKeyField(ormField) {
143
- return ormField.kind === "primaryKey";
89
+ return ormField.kind === "primaryKey";
144
90
  }
91
+ //#endregion
92
+ export { entityResolver };
93
+
145
94
  //# sourceMappingURL=entityResolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entityResolver.js","sourceRoot":"","sources":["../src/entityResolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entityResolver.js","names":[],"sources":["../src/entityResolver.ts"],"sourcesContent":["import { type GraphQLResolveInfo } from \"graphql/type\";\nimport {\n type Collection,\n type Entity,\n type EntityMetadata,\n type Field,\n type IdOf,\n type LoadHint,\n type ManyToManyField,\n type ManyToOneField,\n type MaybeAbstractEntityConstructor,\n type OneToManyField,\n type OneToOneField,\n type PolymorphicField,\n type PrimaryKeyField,\n type Property,\n type ReactiveGetter,\n type ReadOnlyCollection,\n type Reference,\n getMetadata,\n getProperties,\n isAsyncProperty,\n isCollection,\n isLoadedAsyncProperty,\n isLoadedCollection,\n isLoadedLazyField,\n isLoadedProperty,\n isLoadedReadOnlyCollection,\n isLoadedReference,\n isManyToOneField,\n isOneToManyField,\n isProperty,\n isReactiveGetter,\n isReadOnlyCollection,\n isReference,\n} from \"joist-core\";\n\nimport { type Resolver } from \"./context.ts\";\nimport { convertInfoToLoadHint } from \"./hint.ts\";\n\ntype GraphQLPrimitive = string | Date | boolean | number | bigint | null | undefined;\n\n/**\n * Maps properties like `Entity.firstName: string` to field resolver functions like `firstName(): Promise<string>`.\n *\n * Note that we don't necessarily know/care if `firstName` is in the `Entity` GraphQL type, we just map\n * every field to a potential resolver, and then will let the `EntityResolvers` type-check effectively\n * do the union of \"what's defined on the ORM type vs. what's defined on the GraphQL type\".\n *\n * Note this might require setting GraphQL options like `requireResolversToMatchSchema: ignore` to avoid\n * the GraphQL infra complaining about the extra field resolvers that Joist creates for fields that\n * are not technically mapped in your GraphQL schema.\n */\nexport type EntityResolver<T extends Entity> = {\n [P in keyof T]: P extends \"id\"\n ? Resolver<T, Record<string, any>, IdOf<T>>\n : T[P] extends GraphQLPrimitive | GraphQLPrimitive[]\n ? Resolver<T, Record<string, any>, T[P]>\n : T[P] extends Collection<any, infer U>\n ? Resolver<T, Record<string, any>, U[]>\n : T[P] extends ReadOnlyCollection<any, infer U>\n ? Resolver<T, Record<string, any>, U[]>\n : T[P] extends Reference<any, infer U, infer N>\n ? Resolver<T, Record<string, any>, U | N>\n : T[P] extends Property<any, infer V>\n ? Resolver<T, Record<string, any>, V>\n : T[P] extends ReactiveGetter<any, infer V>\n ? Resolver<T, Record<string, any>, V>\n : T[P] extends Promise<infer V>\n ? Resolver<T, Record<string, any>, V>\n : T[P] extends () => Promise<infer V>\n ? Resolver<T, Record<string, any>, V>\n : T[P] extends () => infer V\n ? Resolver<T, Record<string, any>, V>\n : Resolver<T, Record<string, any>, T[P]>;\n};\n\n/**\n * Creates field resolvers for each of the fields on our entity.\n */\nexport function entityResolver<T extends Entity, A extends Record<string, keyof T> = {}>(\n entity: MaybeAbstractEntityConstructor<T> | EntityMetadata<T>,\n aliases?: A,\n): EntityResolver<T> & { [K in keyof A]: EntityResolver<T>[A[K]] } {\n const entityMetadata = getMetadata(entity as any);\n\n const idResolver = (entityOrId: T | string) => {\n return typeof entityOrId === \"string\" ? entityOrId : entityOrId.id;\n };\n\n const primitiveResolvers = Object.values(entityMetadata.allFields)\n .filter((ormField) => !isPrimaryKeyField(ormField) && !isReferenceField(ormField) && !isCollectionField(ormField))\n .map((ormField) => {\n if (\"derived\" in ormField && ormField.derived === \"async\") {\n return [ormField.fieldName, (entity: T) => (entity as any)[ormField.fieldName].get];\n } else if (\"lazy\" in ormField && ormField.lazy) {\n // `lazy` columns are excluded from the default SELECT and exposed as `LazyField`s, so put the\n // value on the wire by loading it on demand (or reading `.get` if already loaded/populated).\n return [\n ormField.fieldName,\n (entity: T) => {\n const lazyField = (entity as any)[ormField.fieldName];\n return isLoadedLazyField(lazyField) ? lazyField.get : lazyField.load();\n },\n ];\n } else {\n // Currently, we only support primitives, i.e. strings/numbers/etc. and not collections.\n return [ormField.fieldName, (entity: T) => (entity as any)[ormField.fieldName]];\n }\n });\n\n const referenceResolvers: [string, Resolver<any, any, any>][] = Object.values(entityMetadata.allFields)\n .filter((ormField) => isReferenceField(ormField))\n .map((ormField) => [\n ormField.fieldName,\n (entity: T, args, ctx, info: GraphQLResolveInfo | undefined) => {\n // Use the `info` to see if the query is only returning `{ id }` and if so avoid fetching the entity\n if ((ormField.kind === \"m2o\" || ormField.kind === \"poly\") && info?.fieldNodes.length === 1) {\n const selectionSet = info.fieldNodes[0].selectionSet;\n // We can't do this if the expected return type uses inheritance, as graphql wouldn't know how to map to a\n // resolver with just an id since there could be multiple implementations\n const hasAbstractType =\n (ormField.kind === \"m2o\" && ormField.otherMetadata().inheritanceType !== undefined) ||\n (ormField.kind === \"poly\" &&\n ormField.components.some((c) => c.otherMetadata().inheritanceType !== undefined));\n if (selectionSet && !hasAbstractType) {\n if (\n selectionSet.selections.length === 1 &&\n selectionSet.selections[0].kind === \"Field\" &&\n selectionSet.selections[0].name.value === \"id\"\n ) {\n // This is cheating and returning the \"wrong root\", but our `id` field resolvers\n // knows to look for it, to optimize this case and avoiding the unnecessary load\n return (entity as any)[ormField.fieldName].idMaybe;\n }\n }\n }\n const reference = (entity as any)[ormField.fieldName];\n if (isLoadedReference(reference)) {\n return reference.get;\n }\n // We skip polys b/c they can't have load hints anyway\n if (info && (isManyToOneField(ormField) || isOneToManyField(ormField))) {\n // See if we can populate the collection from the GraphQL selection set\n const loadHint = convertInfoToLoadHint(ormField.otherMetadata(), info);\n if (loadHint) {\n const parentHint = { [ormField.fieldName]: loadHint } as LoadHint<T>;\n return entity.em.populate(entity, parentHint).then(() => reference.get);\n }\n }\n return reference.load();\n },\n ]);\n\n const collectionResolvers: [string, Resolver<T, any, any>][] = Object.values(entityMetadata.allFields)\n .filter((ormField) => isCollectionField(ormField))\n .map((ormField) => [\n ormField.fieldName,\n (entity, args, ctx, info: GraphQLResolveInfo | undefined) => {\n const field = ormField as OneToManyField | ManyToManyField;\n const collection = (entity as any)[field.fieldName];\n if (isLoadedCollection(collection)) {\n return collection.get;\n }\n if (info) {\n // See if we can populate the collection from the GraphQL selection set\n const loadHint = convertInfoToLoadHint(field.otherMetadata(), info);\n if (loadHint) {\n const parentHint = { [field.fieldName]: loadHint } as LoadHint<T>;\n return entity.em.populate(entity, parentHint).then(() => collection.get);\n }\n }\n return collection.load();\n },\n ]);\n\n const ormResolvers = Object.fromEntries([...primitiveResolvers, ...referenceResolvers, ...collectionResolvers]);\n\n // Look for non-orm properties on the domain object's prototype\n // and on an instance of the domain object itself to get\n // non-prototype properties like CustomReferences\n const alreadyFoundKeys = Object.keys(ormResolvers);\n const customProperties = Object.keys(getProperties(entityMetadata)).filter((n) => !alreadyFoundKeys.includes(n));\n const customResolvers: [string, Resolver<T, any, any>][] = customProperties.map((key) => [\n key,\n (entity) => {\n const property = (entity as any)[key];\n if (typeof property === \"function\") {\n // Support methods like `async name(): Promise<string>`\n return (property as Function).apply(entity);\n } else if (isReactiveGetter(property)) {\n return property.get;\n } else if (isReference(property) || isCollection(property) || isProperty(property) || isAsyncProperty(property)) {\n if (\n isLoadedReference(property) ||\n isLoadedCollection(property) ||\n isLoadedProperty(property) ||\n isLoadedAsyncProperty(property)\n ) {\n return property.get;\n }\n // ...we need to know the `property.otherMetadata()` return type, which isn't available right now\n // const loadHint = convertInfoToLoadHint(getMetadata(entity), info);\n // if (loadHint) {\n // return entity.em.populate(entity, loadHint).then(() => (property as any).get);\n // }\n return property.load();\n } else if (isReadOnlyCollection(property)) {\n if (isLoadedReadOnlyCollection(property)) {\n return property.get;\n }\n return property.load();\n } else {\n return property;\n }\n },\n ]);\n\n let resolvers = {\n id: idResolver,\n ...ormResolvers,\n ...Object.fromEntries(customResolvers),\n } as any;\n\n if (aliases) {\n Object.entries(aliases).forEach(([alias, field]) => {\n resolvers[alias] = resolvers[field];\n });\n }\n\n return resolvers;\n}\n\nfunction isReferenceField(ormField: Field): ormField is ManyToOneField | OneToOneField | PolymorphicField {\n return ormField.kind === \"m2o\" || ormField.kind === \"o2o\" || ormField.kind === \"poly\";\n}\n\nfunction isCollectionField(ormField: Field): ormField is OneToManyField | ManyToManyField {\n return ormField.kind === \"o2m\" || ormField.kind === \"m2m\";\n}\n\nfunction isPrimaryKeyField(ormField: Field): ormField is PrimaryKeyField {\n return ormField.kind === \"primaryKey\";\n}\n"],"mappings":";;;;;;;;AAgFA,SAAgB,eACd,QACA,SACiE;CACjE,MAAM,iBAAiB,YAAY,MAAa;CAEhD,MAAM,cAAc,eAA2B;EAC7C,OAAO,OAAO,eAAe,WAAW,aAAa,WAAW;CAClE;CAEA,MAAM,qBAAqB,OAAO,OAAO,eAAe,SAAS,CAAC,CAC/D,QAAQ,aAAa,CAAC,kBAAkB,QAAQ,KAAK,CAAC,iBAAiB,QAAQ,KAAK,CAAC,kBAAkB,QAAQ,CAAC,CAAC,CACjH,KAAK,aAAa;EACjB,IAAI,aAAa,YAAY,SAAS,YAAY,SAChD,OAAO,CAAC,SAAS,YAAY,WAAe,OAAe,SAAS,UAAU,CAAC,GAAG;OAC7E,IAAI,UAAU,YAAY,SAAS,MAGxC,OAAO,CACL,SAAS,YACR,WAAc;GACb,MAAM,YAAa,OAAe,SAAS;GAC3C,OAAO,kBAAkB,SAAS,IAAI,UAAU,MAAM,UAAU,KAAK;EACvE,CACF;OAGA,OAAO,CAAC,SAAS,YAAY,WAAe,OAAe,SAAS,UAAU;CAElF,CAAC;CAEH,MAAM,qBAA0D,OAAO,OAAO,eAAe,SAAS,CAAC,CACpG,QAAQ,aAAa,iBAAiB,QAAQ,CAAC,CAAC,CAChD,KAAK,aAAa,CACjB,SAAS,YACR,QAAW,MAAM,KAAK,SAAyC;EAE9D,KAAK,SAAS,SAAS,SAAS,SAAS,SAAS,WAAW,MAAM,WAAW,WAAW,GAAG;GAC1F,MAAM,eAAe,KAAK,WAAW,EAAE,CAAC;GAGxC,MAAM,kBACH,SAAS,SAAS,SAAS,SAAS,cAAc,CAAC,CAAC,oBAAoB,KAAA,KACxE,SAAS,SAAS,UACjB,SAAS,WAAW,MAAM,MAAM,EAAE,cAAc,CAAC,CAAC,oBAAoB,KAAA,CAAS;GACnF,IAAI,gBAAgB,CAAC,iBAEjB;QAAA,aAAa,WAAW,WAAW,KACnC,aAAa,WAAW,EAAE,CAAC,SAAS,WACpC,aAAa,WAAW,EAAE,CAAC,KAAK,UAAU,MAI1C,OAAQ,OAAe,SAAS,UAAU,CAAC;GAAA;EAGjD;EACA,MAAM,YAAa,OAAe,SAAS;EAC3C,IAAI,kBAAkB,SAAS,GAC7B,OAAO,UAAU;EAGnB,IAAI,SAAS,iBAAiB,QAAQ,KAAK,iBAAiB,QAAQ,IAAI;GAEtE,MAAM,WAAW,sBAAsB,SAAS,cAAc,GAAG,IAAI;GACrE,IAAI,UAAU;IACZ,MAAM,aAAa,GAAG,SAAS,YAAY,SAAS;IACpD,OAAO,OAAO,GAAG,SAAS,QAAQ,UAAU,CAAC,CAAC,WAAW,UAAU,GAAG;GACxE;EACF;EACA,OAAO,UAAU,KAAK;CACxB,CACF,CAAC;CAEH,MAAM,sBAAyD,OAAO,OAAO,eAAe,SAAS,CAAC,CACnG,QAAQ,aAAa,kBAAkB,QAAQ,CAAC,CAAC,CACjD,KAAK,aAAa,CACjB,SAAS,YACR,QAAQ,MAAM,KAAK,SAAyC;EAC3D,MAAM,QAAQ;EACd,MAAM,aAAc,OAAe,MAAM;EACzC,IAAI,mBAAmB,UAAU,GAC/B,OAAO,WAAW;EAEpB,IAAI,MAAM;GAER,MAAM,WAAW,sBAAsB,MAAM,cAAc,GAAG,IAAI;GAClE,IAAI,UAAU;IACZ,MAAM,aAAa,GAAG,MAAM,YAAY,SAAS;IACjD,OAAO,OAAO,GAAG,SAAS,QAAQ,UAAU,CAAC,CAAC,WAAW,WAAW,GAAG;GACzE;EACF;EACA,OAAO,WAAW,KAAK;CACzB,CACF,CAAC;CAEH,MAAM,eAAe,OAAO,YAAY;EAAC,GAAG;EAAoB,GAAG;EAAoB,GAAG;CAAmB,CAAC;CAK9G,MAAM,mBAAmB,OAAO,KAAK,YAAY;CAEjD,MAAM,kBADmB,OAAO,KAAK,cAAc,cAAc,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,iBAAiB,SAAS,CAAC,CACpC,CAAC,CAAC,KAAK,QAAQ,CACvF,MACC,WAAW;EACV,MAAM,WAAY,OAAe;EACjC,IAAI,OAAO,aAAa,YAEtB,OAAQ,SAAsB,MAAM,MAAM;OACrC,IAAI,iBAAiB,QAAQ,GAClC,OAAO,SAAS;OACX,IAAI,YAAY,QAAQ,KAAK,aAAa,QAAQ,KAAK,WAAW,QAAQ,KAAK,gBAAgB,QAAQ,GAAG;GAC/G,IACE,kBAAkB,QAAQ,KAC1B,mBAAmB,QAAQ,KAC3B,iBAAiB,QAAQ,KACzB,sBAAsB,QAAQ,GAE9B,OAAO,SAAS;GAOlB,OAAO,SAAS,KAAK;EACvB,OAAO,IAAI,qBAAqB,QAAQ,GAAG;GACzC,IAAI,2BAA2B,QAAQ,GACrC,OAAO,SAAS;GAElB,OAAO,SAAS,KAAK;EACvB,OACE,OAAO;CAEX,CACF,CAAC;CAED,IAAI,YAAY;EACd,IAAI;EACJ,GAAG;EACH,GAAG,OAAO,YAAY,eAAe;CACvC;CAEA,IAAI,SACF,OAAO,QAAQ,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,WAAW;EAClD,UAAU,SAAS,UAAU;CAC/B,CAAC;CAGH,OAAO;AACT;AAEA,SAAS,iBAAiB,UAAgF;CACxG,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS,SAAS;AACjF;AAEA,SAAS,kBAAkB,UAA+D;CACxF,OAAO,SAAS,SAAS,SAAS,SAAS,SAAS;AACtD;AAEA,SAAS,kBAAkB,UAA8C;CACvE,OAAO,SAAS,SAAS;AAC3B"}
package/build/hint.cjs ADDED
@@ -0,0 +1,50 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let graphql_type = require("graphql/type");
3
+ require("joist-core");
4
+ require("graphql/language");
5
+ //#region src/hint.ts
6
+ /** Returns a load hint for the given `meta` entity at the `info` node.populate`. */
7
+ function convertInfoToLoadHint(meta, info) {
8
+ const objectType = convertToObjectType(info.returnType);
9
+ const { selectionSet, arguments: args } = info.fieldNodes[0];
10
+ const hasArgs = !!args && args.length > 0;
11
+ if (objectType && selectionSet && !hasArgs) {
12
+ const hint = selectionSetToObject(info, meta, objectType, selectionSet);
13
+ return Object.keys(hint).length === 0 ? void 0 : hint;
14
+ }
15
+ }
16
+ /** Converts a GraphQL selection set into a hint for `EntityManager.populate`. */
17
+ function selectionSetToObject(info, meta, gqlType, selectionSet) {
18
+ const result = {};
19
+ for (const selection of selectionSet.selections) if (selection.kind === "Field") {
20
+ if (selection.arguments && selection.arguments.length > 0) continue;
21
+ const fieldName = selection.name.value;
22
+ const field = gqlType.getFields()[fieldName];
23
+ if (field === void 0) continue;
24
+ const fieldType = convertToObjectType(field.type);
25
+ const ormField = meta.allFields[fieldName];
26
+ if (fieldType && selection.selectionSet && ormField && "otherMetadata" in ormField) result[fieldName] = selectionSetToObject(info, ormField.otherMetadata(), fieldType, selection.selectionSet);
27
+ } else if (selection.kind === "FragmentSpread") {
28
+ const fragmentName = selection.name.value;
29
+ const fragment = info.fragments[fragmentName];
30
+ const objectType = convertToObjectType(info.schema.getType(fragment.typeCondition.name.value));
31
+ if (objectType) deepMerge(result, selectionSetToObject(info, meta, objectType, fragment.selectionSet));
32
+ } else if (selection.kind === "InlineFragment" && selection.typeCondition) {
33
+ const objectType = convertToObjectType(info.schema.getType(selection.typeCondition.name.value));
34
+ if (objectType) deepMerge(result, selectionSetToObject(info, meta, objectType, selection.selectionSet));
35
+ }
36
+ return result;
37
+ }
38
+ function convertToObjectType(type) {
39
+ if (type instanceof graphql_type.GraphQLNonNull || type instanceof graphql_type.GraphQLList) return convertToObjectType(type.ofType);
40
+ else if ((0, graphql_type.isObjectType)(type)) return type;
41
+ }
42
+ function deepMerge(a, b) {
43
+ for (const [key, value] of Object.entries(b)) deepMerge(a[key] ??= {}, value);
44
+ }
45
+ //#endregion
46
+ exports.convertInfoToLoadHint = convertInfoToLoadHint;
47
+ exports.convertToObjectType = convertToObjectType;
48
+ exports.selectionSetToObject = selectionSetToObject;
49
+
50
+ //# sourceMappingURL=hint.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hint.cjs","names":["GraphQLNonNull","GraphQLList","isObjectType"],"sources":["../src/hint.ts"],"sourcesContent":["import { type SelectionSetNode } from \"graphql/language\";\nimport {\n GraphQLList,\n GraphQLNonNull,\n type GraphQLObjectType,\n type GraphQLOutputType,\n type GraphQLResolveInfo,\n isObjectType,\n} from \"graphql/type\";\nimport { type Entity, type EntityMetadata, type LoadHint } from \"joist-core\";\n\n/** Returns a load hint for the given `meta` entity at the `info` node.populate`. */\nexport function convertInfoToLoadHint<T extends Entity>(\n meta: EntityMetadata,\n info: GraphQLResolveInfo,\n): LoadHint<T> | undefined {\n // The return type of the current field resolver is the root type, i.e.\n // Author.books fieldResolver ==> objectType = Book, or\n // query.authors fieldResolver ==> objectType = Author\n const objectType = convertToObjectType(info.returnType);\n const { selectionSet, arguments: args } = info.fieldNodes[0];\n const hasArgs = !!args && args.length > 0;\n if (objectType && selectionSet && !hasArgs) {\n const hint = selectionSetToObject(info, meta, objectType, selectionSet);\n // Don't return an empty hint\n return Object.keys(hint).length === 0 ? undefined : hint;\n }\n return undefined;\n}\n\n/** Converts a GraphQL selection set into a hint for `EntityManager.populate`. */\nexport function selectionSetToObject(\n info: GraphQLResolveInfo,\n meta: EntityMetadata,\n gqlType: GraphQLObjectType,\n selectionSet: SelectionSetNode,\n): Record<string, any> {\n const result: Record<string, any> = {};\n for (const selection of selectionSet.selections) {\n if (selection.kind === \"Field\") {\n // If there are arguments, defer to the field resolver to apply them.\n if (selection.arguments && selection.arguments.length > 0) continue;\n const fieldName = selection.name.value;\n const field = gqlType.getFields()[fieldName];\n // This might be __typename, which is a meta field\n if (field === undefined) continue;\n const fieldType = convertToObjectType(field.type);\n const ormField = meta.allFields[fieldName];\n if (fieldType && selection.selectionSet && ormField && \"otherMetadata\" in ormField) {\n result[fieldName] = selectionSetToObject(info, ormField.otherMetadata(), fieldType, selection.selectionSet);\n }\n } else if (selection.kind === \"FragmentSpread\") {\n const fragmentName = selection.name.value;\n const fragment = info.fragments[fragmentName]!;\n const type = info.schema.getType(fragment.typeCondition.name.value)!;\n const objectType = convertToObjectType(type as any);\n if (objectType) {\n const other = selectionSetToObject(info, meta, objectType, fragment.selectionSet);\n deepMerge(result, other);\n }\n } else if (selection.kind === \"InlineFragment\" && selection.typeCondition) {\n const type = info.schema.getType(selection.typeCondition.name.value)!;\n const objectType = convertToObjectType(type as any);\n if (objectType) {\n const other = selectionSetToObject(info, meta, objectType, selection.selectionSet);\n deepMerge(result, other);\n }\n }\n }\n return result;\n}\n\nexport function convertToObjectType(type: GraphQLOutputType): GraphQLObjectType | undefined {\n if (type instanceof GraphQLNonNull || type instanceof GraphQLList) {\n return convertToObjectType(type.ofType);\n } else if (isObjectType(type)) {\n return type;\n }\n return undefined;\n}\n\nfunction deepMerge<T extends object>(a: T, b: T): void {\n for (const [key, value] of Object.entries(b)) {\n deepMerge(((a as any)[key] ??= {}), value);\n }\n}\n"],"mappings":";;;;;;AAYA,SAAgB,sBACd,MACA,MACyB;CAIzB,MAAM,aAAa,oBAAoB,KAAK,UAAU;CACtD,MAAM,EAAE,cAAc,WAAW,SAAS,KAAK,WAAW;CAC1D,MAAM,UAAU,CAAC,CAAC,QAAQ,KAAK,SAAS;CACxC,IAAI,cAAc,gBAAgB,CAAC,SAAS;EAC1C,MAAM,OAAO,qBAAqB,MAAM,MAAM,YAAY,YAAY;EAEtE,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,IAAI,KAAA,IAAY;CACtD;AAEF;;AAGA,SAAgB,qBACd,MACA,MACA,SACA,cACqB;CACrB,MAAM,SAA8B,CAAC;CACrC,KAAK,MAAM,aAAa,aAAa,YACnC,IAAI,UAAU,SAAS,SAAS;EAE9B,IAAI,UAAU,aAAa,UAAU,UAAU,SAAS,GAAG;EAC3D,MAAM,YAAY,UAAU,KAAK;EACjC,MAAM,QAAQ,QAAQ,UAAU,CAAC,CAAC;EAElC,IAAI,UAAU,KAAA,GAAW;EACzB,MAAM,YAAY,oBAAoB,MAAM,IAAI;EAChD,MAAM,WAAW,KAAK,UAAU;EAChC,IAAI,aAAa,UAAU,gBAAgB,YAAY,mBAAmB,UACxE,OAAO,aAAa,qBAAqB,MAAM,SAAS,cAAc,GAAG,WAAW,UAAU,YAAY;CAE9G,OAAO,IAAI,UAAU,SAAS,kBAAkB;EAC9C,MAAM,eAAe,UAAU,KAAK;EACpC,MAAM,WAAW,KAAK,UAAU;EAEhC,MAAM,aAAa,oBADN,KAAK,OAAO,QAAQ,SAAS,cAAc,KAAK,KACnB,CAAQ;EAClD,IAAI,YAEF,UAAU,QADI,qBAAqB,MAAM,MAAM,YAAY,SAAS,YAC9C,CAAC;CAE3B,OAAO,IAAI,UAAU,SAAS,oBAAoB,UAAU,eAAe;EAEzE,MAAM,aAAa,oBADN,KAAK,OAAO,QAAQ,UAAU,cAAc,KAAK,KACpB,CAAQ;EAClD,IAAI,YAEF,UAAU,QADI,qBAAqB,MAAM,MAAM,YAAY,UAAU,YAC/C,CAAC;CAE3B;CAEF,OAAO;AACT;AAEA,SAAgB,oBAAoB,MAAwD;CAC1F,IAAI,gBAAgBA,aAAAA,kBAAkB,gBAAgBC,aAAAA,aACpD,OAAO,oBAAoB,KAAK,MAAM;MACjC,KAAA,GAAIC,aAAAA,aAAAA,CAAa,IAAI,GAC1B,OAAO;AAGX;AAEA,SAAS,UAA4B,GAAM,GAAY;CACrD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,CAAC,GACzC,UAAW,EAAW,SAAS,CAAC,GAAI,KAAK;AAE7C"}
@@ -0,0 +1,12 @@
1
+ import { GraphQLObjectType, GraphQLOutputType, GraphQLResolveInfo } from "graphql/type";
2
+ import { Entity, EntityMetadata, LoadHint } from "joist-core";
3
+ import { SelectionSetNode } from "graphql/language";
4
+ //#region src/hint.d.ts
5
+ /** Returns a load hint for the given `meta` entity at the `info` node.populate`. */
6
+ declare function convertInfoToLoadHint<T extends Entity>(meta: EntityMetadata, info: GraphQLResolveInfo): LoadHint<T> | undefined;
7
+ /** Converts a GraphQL selection set into a hint for `EntityManager.populate`. */
8
+ declare function selectionSetToObject(info: GraphQLResolveInfo, meta: EntityMetadata, gqlType: GraphQLObjectType, selectionSet: SelectionSetNode): Record<string, any>;
9
+ declare function convertToObjectType(type: GraphQLOutputType): GraphQLObjectType | undefined;
10
+ //#endregion
11
+ export { convertInfoToLoadHint, convertToObjectType, selectionSetToObject };
12
+ //# sourceMappingURL=hint.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hint.d.cts","names":[],"sources":["../src/hint.ts"],"mappings":";;;;;iBAYgB,sBAAsB,UAAU,QAC9C,MAAM,gBACN,MAAM,qBACL,SAAS;;iBAgBI,qBACd,MAAM,oBACN,MAAM,gBACN,SAAS,mBACT,cAAc,mBACb;iBAoCa,oBAAoB,MAAM,oBAAoB"}
@@ -0,0 +1,12 @@
1
+ import { GraphQLObjectType, GraphQLOutputType, GraphQLResolveInfo } from "graphql/type";
2
+ import { Entity, EntityMetadata, LoadHint } from "joist-core";
3
+ import { SelectionSetNode } from "graphql/language";
4
+ //#region src/hint.d.ts
5
+ /** Returns a load hint for the given `meta` entity at the `info` node.populate`. */
6
+ declare function convertInfoToLoadHint<T extends Entity>(meta: EntityMetadata, info: GraphQLResolveInfo): LoadHint<T> | undefined;
7
+ /** Converts a GraphQL selection set into a hint for `EntityManager.populate`. */
8
+ declare function selectionSetToObject(info: GraphQLResolveInfo, meta: EntityMetadata, gqlType: GraphQLObjectType, selectionSet: SelectionSetNode): Record<string, any>;
9
+ declare function convertToObjectType(type: GraphQLOutputType): GraphQLObjectType | undefined;
10
+ //#endregion
11
+ export { convertInfoToLoadHint, convertToObjectType, selectionSetToObject };
12
+ //# sourceMappingURL=hint.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hint.d.mts","names":[],"sources":["../src/hint.ts"],"mappings":";;;;;iBAYgB,sBAAsB,UAAU,QAC9C,MAAM,gBACN,MAAM,qBACL,SAAS;;iBAgBI,qBACd,MAAM,oBACN,MAAM,gBACN,SAAS,mBACT,cAAc,mBACb;iBAoCa,oBAAoB,MAAM,oBAAoB"}
package/build/hint.js CHANGED
@@ -1,76 +1,47 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertInfoToLoadHint = convertInfoToLoadHint;
4
- exports.selectionSetToObject = selectionSetToObject;
5
- exports.convertToObjectType = convertToObjectType;
6
- const type_1 = require("graphql/type");
1
+ import { GraphQLList, GraphQLNonNull, isObjectType } from "graphql/type";
2
+ import "joist-core";
3
+ import "graphql/language";
4
+ //#region src/hint.ts
7
5
  /** Returns a load hint for the given `meta` entity at the `info` node.populate`. */
8
6
  function convertInfoToLoadHint(meta, info) {
9
- // The return type of the current field resolver is the root type, i.e.
10
- // Author.books fieldResolver ==> objectType = Book, or
11
- // query.authors fieldResolver ==> objectType = Author
12
- const objectType = convertToObjectType(info.returnType);
13
- const { selectionSet, arguments: args } = info.fieldNodes[0];
14
- const hasArgs = !!args && args.length > 0;
15
- if (objectType && selectionSet && !hasArgs) {
16
- const hint = selectionSetToObject(info, meta, objectType, selectionSet);
17
- // Don't return an empty hint
18
- return Object.keys(hint).length === 0 ? undefined : hint;
19
- }
20
- return undefined;
7
+ const objectType = convertToObjectType(info.returnType);
8
+ const { selectionSet, arguments: args } = info.fieldNodes[0];
9
+ const hasArgs = !!args && args.length > 0;
10
+ if (objectType && selectionSet && !hasArgs) {
11
+ const hint = selectionSetToObject(info, meta, objectType, selectionSet);
12
+ return Object.keys(hint).length === 0 ? void 0 : hint;
13
+ }
21
14
  }
22
15
  /** Converts a GraphQL selection set into a hint for `EntityManager.populate`. */
23
16
  function selectionSetToObject(info, meta, gqlType, selectionSet) {
24
- const result = {};
25
- for (const selection of selectionSet.selections) {
26
- if (selection.kind === "Field") {
27
- // If there are arguments, defer to the field resolver to apply them.
28
- if (selection.arguments && selection.arguments.length > 0)
29
- continue;
30
- const fieldName = selection.name.value;
31
- const field = gqlType.getFields()[fieldName];
32
- // This might be __typename, which is a meta field
33
- if (field === undefined)
34
- continue;
35
- const fieldType = convertToObjectType(field.type);
36
- const ormField = meta.allFields[fieldName];
37
- if (fieldType && selection.selectionSet && ormField && "otherMetadata" in ormField) {
38
- result[fieldName] = selectionSetToObject(info, ormField.otherMetadata(), fieldType, selection.selectionSet);
39
- }
40
- }
41
- else if (selection.kind === "FragmentSpread") {
42
- const fragmentName = selection.name.value;
43
- const fragment = info.fragments[fragmentName];
44
- const type = info.schema.getType(fragment.typeCondition.name.value);
45
- const objectType = convertToObjectType(type);
46
- if (objectType) {
47
- const other = selectionSetToObject(info, meta, objectType, fragment.selectionSet);
48
- deepMerge(result, other);
49
- }
50
- }
51
- else if (selection.kind === "InlineFragment" && selection.typeCondition) {
52
- const type = info.schema.getType(selection.typeCondition.name.value);
53
- const objectType = convertToObjectType(type);
54
- if (objectType) {
55
- const other = selectionSetToObject(info, meta, objectType, selection.selectionSet);
56
- deepMerge(result, other);
57
- }
58
- }
59
- }
60
- return result;
17
+ const result = {};
18
+ for (const selection of selectionSet.selections) if (selection.kind === "Field") {
19
+ if (selection.arguments && selection.arguments.length > 0) continue;
20
+ const fieldName = selection.name.value;
21
+ const field = gqlType.getFields()[fieldName];
22
+ if (field === void 0) continue;
23
+ const fieldType = convertToObjectType(field.type);
24
+ const ormField = meta.allFields[fieldName];
25
+ if (fieldType && selection.selectionSet && ormField && "otherMetadata" in ormField) result[fieldName] = selectionSetToObject(info, ormField.otherMetadata(), fieldType, selection.selectionSet);
26
+ } else if (selection.kind === "FragmentSpread") {
27
+ const fragmentName = selection.name.value;
28
+ const fragment = info.fragments[fragmentName];
29
+ const objectType = convertToObjectType(info.schema.getType(fragment.typeCondition.name.value));
30
+ if (objectType) deepMerge(result, selectionSetToObject(info, meta, objectType, fragment.selectionSet));
31
+ } else if (selection.kind === "InlineFragment" && selection.typeCondition) {
32
+ const objectType = convertToObjectType(info.schema.getType(selection.typeCondition.name.value));
33
+ if (objectType) deepMerge(result, selectionSetToObject(info, meta, objectType, selection.selectionSet));
34
+ }
35
+ return result;
61
36
  }
62
37
  function convertToObjectType(type) {
63
- if (type instanceof type_1.GraphQLNonNull || type instanceof type_1.GraphQLList) {
64
- return convertToObjectType(type.ofType);
65
- }
66
- else if ((0, type_1.isObjectType)(type)) {
67
- return type;
68
- }
69
- return undefined;
38
+ if (type instanceof GraphQLNonNull || type instanceof GraphQLList) return convertToObjectType(type.ofType);
39
+ else if (isObjectType(type)) return type;
70
40
  }
71
41
  function deepMerge(a, b) {
72
- for (const [key, value] of Object.entries(b)) {
73
- deepMerge((a[key] ??= {}), value);
74
- }
42
+ for (const [key, value] of Object.entries(b)) deepMerge(a[key] ??= {}, value);
75
43
  }
44
+ //#endregion
45
+ export { convertInfoToLoadHint, convertToObjectType, selectionSetToObject };
46
+
76
47
  //# sourceMappingURL=hint.js.map
package/build/hint.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"hint.js","sourceRoot":"","sources":["../src/hint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hint.js","names":[],"sources":["../src/hint.ts"],"sourcesContent":["import { type SelectionSetNode } from \"graphql/language\";\nimport {\n GraphQLList,\n GraphQLNonNull,\n type GraphQLObjectType,\n type GraphQLOutputType,\n type GraphQLResolveInfo,\n isObjectType,\n} from \"graphql/type\";\nimport { type Entity, type EntityMetadata, type LoadHint } from \"joist-core\";\n\n/** Returns a load hint for the given `meta` entity at the `info` node.populate`. */\nexport function convertInfoToLoadHint<T extends Entity>(\n meta: EntityMetadata,\n info: GraphQLResolveInfo,\n): LoadHint<T> | undefined {\n // The return type of the current field resolver is the root type, i.e.\n // Author.books fieldResolver ==> objectType = Book, or\n // query.authors fieldResolver ==> objectType = Author\n const objectType = convertToObjectType(info.returnType);\n const { selectionSet, arguments: args } = info.fieldNodes[0];\n const hasArgs = !!args && args.length > 0;\n if (objectType && selectionSet && !hasArgs) {\n const hint = selectionSetToObject(info, meta, objectType, selectionSet);\n // Don't return an empty hint\n return Object.keys(hint).length === 0 ? undefined : hint;\n }\n return undefined;\n}\n\n/** Converts a GraphQL selection set into a hint for `EntityManager.populate`. */\nexport function selectionSetToObject(\n info: GraphQLResolveInfo,\n meta: EntityMetadata,\n gqlType: GraphQLObjectType,\n selectionSet: SelectionSetNode,\n): Record<string, any> {\n const result: Record<string, any> = {};\n for (const selection of selectionSet.selections) {\n if (selection.kind === \"Field\") {\n // If there are arguments, defer to the field resolver to apply them.\n if (selection.arguments && selection.arguments.length > 0) continue;\n const fieldName = selection.name.value;\n const field = gqlType.getFields()[fieldName];\n // This might be __typename, which is a meta field\n if (field === undefined) continue;\n const fieldType = convertToObjectType(field.type);\n const ormField = meta.allFields[fieldName];\n if (fieldType && selection.selectionSet && ormField && \"otherMetadata\" in ormField) {\n result[fieldName] = selectionSetToObject(info, ormField.otherMetadata(), fieldType, selection.selectionSet);\n }\n } else if (selection.kind === \"FragmentSpread\") {\n const fragmentName = selection.name.value;\n const fragment = info.fragments[fragmentName]!;\n const type = info.schema.getType(fragment.typeCondition.name.value)!;\n const objectType = convertToObjectType(type as any);\n if (objectType) {\n const other = selectionSetToObject(info, meta, objectType, fragment.selectionSet);\n deepMerge(result, other);\n }\n } else if (selection.kind === \"InlineFragment\" && selection.typeCondition) {\n const type = info.schema.getType(selection.typeCondition.name.value)!;\n const objectType = convertToObjectType(type as any);\n if (objectType) {\n const other = selectionSetToObject(info, meta, objectType, selection.selectionSet);\n deepMerge(result, other);\n }\n }\n }\n return result;\n}\n\nexport function convertToObjectType(type: GraphQLOutputType): GraphQLObjectType | undefined {\n if (type instanceof GraphQLNonNull || type instanceof GraphQLList) {\n return convertToObjectType(type.ofType);\n } else if (isObjectType(type)) {\n return type;\n }\n return undefined;\n}\n\nfunction deepMerge<T extends object>(a: T, b: T): void {\n for (const [key, value] of Object.entries(b)) {\n deepMerge(((a as any)[key] ??= {}), value);\n }\n}\n"],"mappings":";;;;;AAYA,SAAgB,sBACd,MACA,MACyB;CAIzB,MAAM,aAAa,oBAAoB,KAAK,UAAU;CACtD,MAAM,EAAE,cAAc,WAAW,SAAS,KAAK,WAAW;CAC1D,MAAM,UAAU,CAAC,CAAC,QAAQ,KAAK,SAAS;CACxC,IAAI,cAAc,gBAAgB,CAAC,SAAS;EAC1C,MAAM,OAAO,qBAAqB,MAAM,MAAM,YAAY,YAAY;EAEtE,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,IAAI,KAAA,IAAY;CACtD;AAEF;;AAGA,SAAgB,qBACd,MACA,MACA,SACA,cACqB;CACrB,MAAM,SAA8B,CAAC;CACrC,KAAK,MAAM,aAAa,aAAa,YACnC,IAAI,UAAU,SAAS,SAAS;EAE9B,IAAI,UAAU,aAAa,UAAU,UAAU,SAAS,GAAG;EAC3D,MAAM,YAAY,UAAU,KAAK;EACjC,MAAM,QAAQ,QAAQ,UAAU,CAAC,CAAC;EAElC,IAAI,UAAU,KAAA,GAAW;EACzB,MAAM,YAAY,oBAAoB,MAAM,IAAI;EAChD,MAAM,WAAW,KAAK,UAAU;EAChC,IAAI,aAAa,UAAU,gBAAgB,YAAY,mBAAmB,UACxE,OAAO,aAAa,qBAAqB,MAAM,SAAS,cAAc,GAAG,WAAW,UAAU,YAAY;CAE9G,OAAO,IAAI,UAAU,SAAS,kBAAkB;EAC9C,MAAM,eAAe,UAAU,KAAK;EACpC,MAAM,WAAW,KAAK,UAAU;EAEhC,MAAM,aAAa,oBADN,KAAK,OAAO,QAAQ,SAAS,cAAc,KAAK,KACnB,CAAQ;EAClD,IAAI,YAEF,UAAU,QADI,qBAAqB,MAAM,MAAM,YAAY,SAAS,YAC9C,CAAC;CAE3B,OAAO,IAAI,UAAU,SAAS,oBAAoB,UAAU,eAAe;EAEzE,MAAM,aAAa,oBADN,KAAK,OAAO,QAAQ,UAAU,cAAc,KAAK,KACpB,CAAQ;EAClD,IAAI,YAEF,UAAU,QADI,qBAAqB,MAAM,MAAM,YAAY,UAAU,YAC/C,CAAC;CAE3B;CAEF,OAAO;AACT;AAEA,SAAgB,oBAAoB,MAAwD;CAC1F,IAAI,gBAAgB,kBAAkB,gBAAgB,aACpD,OAAO,oBAAoB,KAAK,MAAM;MACjC,IAAI,aAAa,IAAI,GAC1B,OAAO;AAGX;AAEA,SAAS,UAA4B,GAAM,GAAY;CACrD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,CAAC,GACzC,UAAW,EAAW,SAAS,CAAC,GAAI,KAAK;AAE7C"}
@@ -0,0 +1,14 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_cursorPagination = require("./cursorPagination.cjs");
3
+ const require_hint = require("./hint.cjs");
4
+ const require_entityResolver = require("./entityResolver.cjs");
5
+ const require_limitPagination = require("./limitPagination.cjs");
6
+ const require_saveEntity = require("./saveEntity.cjs");
7
+ exports.CursorPageInfo = require_cursorPagination.CursorPageInfo;
8
+ exports.LimitPageInfo = require_limitPagination.LimitPageInfo;
9
+ exports.convertInfoToLoadHint = require_hint.convertInfoToLoadHint;
10
+ exports.entityResolver = require_entityResolver.entityResolver;
11
+ exports.paginateCursor = require_cursorPagination.paginateCursor;
12
+ exports.paginateLimit = require_limitPagination.paginateLimit;
13
+ exports.saveEntities = require_saveEntity.saveEntities;
14
+ exports.saveEntity = require_saveEntity.saveEntity;
@@ -0,0 +1,6 @@
1
+ import { CursorPageInfo, paginateCursor } from "./cursorPagination.cjs";
2
+ import { entityResolver } from "./entityResolver.cjs";
3
+ import { convertInfoToLoadHint } from "./hint.cjs";
4
+ import { LimitPageInfo, paginateLimit } from "./limitPagination.cjs";
5
+ import { saveEntities, saveEntity } from "./saveEntity.cjs";
6
+ export { CursorPageInfo, LimitPageInfo, convertInfoToLoadHint, entityResolver, paginateCursor, paginateLimit, saveEntities, saveEntity };
@@ -0,0 +1,6 @@
1
+ import { CursorPageInfo, paginateCursor } from "./cursorPagination.mjs";
2
+ import { entityResolver } from "./entityResolver.mjs";
3
+ import { convertInfoToLoadHint } from "./hint.mjs";
4
+ import { LimitPageInfo, paginateLimit } from "./limitPagination.mjs";
5
+ import { saveEntities, saveEntity } from "./saveEntity.mjs";
6
+ export { CursorPageInfo, LimitPageInfo, convertInfoToLoadHint, entityResolver, paginateCursor, paginateLimit, saveEntities, saveEntity };