grafast 0.1.1-beta.22 → 0.1.1-beta.24

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/dist/index.d.ts CHANGED
@@ -71,6 +71,22 @@ declare global {
71
71
  }
72
72
  interface InputObjectTypeExtensions {
73
73
  baked?: InputObjectTypeBakedResolver;
74
+ /**
75
+ * EXPERIMENTAL!
76
+ *
77
+ * Scope to pass to `.apply()` methods called by `applyInput()` step.
78
+ *
79
+ * IMPORTANT: the scope is only evaluated for the top-level named type
80
+ * that `applyInput()` is applied against, so any type that nests this
81
+ * (e.g. other input objects) needs to ensure they have an `applyScope()`
82
+ * that's compatible; similarly this `applyPlan()` needs to supply values
83
+ * that are compatible with all the descendant input objects, enums and
84
+ * scalars. For this reason we recommend that you return an object with a
85
+ * scoped key that you care about so it's easily merged.
86
+ *
87
+ * @experimental
88
+ */
89
+ applyScope?: () => Step;
74
90
  }
75
91
  interface InputFieldExtensions {
76
92
  apply?: InputObjectFieldApplyResolver<any>;
@@ -130,6 +146,20 @@ declare global {
130
146
  planType?($stepOrSpecifier: Step, info: PlanTypeInfo): AbstractTypePlanner;
131
147
  }
132
148
  interface EnumTypeExtensions {
149
+ /**
150
+ * EXPERIMENTAL!
151
+ *
152
+ * Scope to pass to `.apply()` methods called by `applyInput()` step.
153
+ *
154
+ * IMPORTANT: the scope is only evaluated for the top-level named type
155
+ * that `applyInput()` is applied against, so any type that nests this
156
+ * (e.g. input objects) needs to ensure they have an `applyScope()`
157
+ * that's compatible. For this reason we recommend that you return an
158
+ * object with a scoped key that you care about so it's easily merged.
159
+ *
160
+ * @experimental
161
+ */
162
+ applyScope?: () => Step;
133
163
  }
134
164
  interface EnumValueExtensions {
135
165
  /**
@@ -143,6 +173,20 @@ declare global {
143
173
  interface ScalarTypeExtensions {
144
174
  plan?: ScalarPlanResolver;
145
175
  inputPlan?: ScalarInputPlanResolver;
176
+ /**
177
+ * EXPERIMENTAL!
178
+ *
179
+ * Scope to pass to `.apply()` methods called by `applyInput()` step.
180
+ *
181
+ * IMPORTANT: the scope is only evaluated for the top-level named type
182
+ * that `applyInput()` is applied against, so any type that nests this
183
+ * (e.g. input objects) needs to ensure they have an `applyScope()`
184
+ * that's compatible. For this reason we recommend that you return an
185
+ * object with a scoped key that you care about so it's easily merged.
186
+ *
187
+ * @experimental
188
+ */
189
+ applyScope?: () => Step;
146
190
  /**
147
191
  * Set true if `serialize(serialize(foo)) === serialize(foo)` for all foo
148
192
  */
@@ -1,6 +1,6 @@
1
1
  import type EventEmitter from "eventemitter3";
2
2
  import type { Middleware } from "graphile-config";
3
- import type { ASTNode, ExecutionArgs, FragmentDefinitionNode, GraphQLArgs, GraphQLArgument, GraphQLArgumentConfig, GraphQLField, GraphQLFieldConfig, GraphQLInputField, GraphQLInputFieldConfig, GraphQLInputObjectType, GraphQLInputType, GraphQLInterfaceType, GraphQLObjectType, GraphQLOutputType, GraphQLScalarType, GraphQLSchema, GraphQLUnionType, OperationDefinitionNode, Source, ValueNode, VariableNode } from "graphql";
3
+ import type { ASTNode, ExecutionArgs, FragmentDefinitionNode, GraphQLArgs, GraphQLArgument, GraphQLArgumentConfig, GraphQLEnumValue, GraphQLField, GraphQLFieldConfig, GraphQLInputField, GraphQLInputFieldConfig, GraphQLInputObjectType, GraphQLInputType, GraphQLInterfaceType, GraphQLObjectType, GraphQLOutputType, GraphQLScalarType, GraphQLSchema, GraphQLUnionType, OperationDefinitionNode, Source, ValueNode, VariableNode } from "graphql";
4
4
  import type { ObjMap } from "graphql/jsutils/ObjMap.js";
5
5
  import type { $$streamMore, $$timeout, $$ts, ExecutionEntryFlags } from "./constants.js";
6
6
  import type { Constraint } from "./constraints.js";
@@ -158,11 +158,12 @@ export interface FieldInfo {
158
158
  * executions.
159
159
  */
160
160
  export type FieldPlanResolver<TParentStep extends Step = Step, TArgs extends BaseGraphQLArguments = any, TResultStep extends Step = Step> = ($parentPlan: TParentStep, args: FieldArgs<TArgs>, info: FieldInfo) => TResultStep | null;
161
- export type InputObjectFieldApplyResolver<TParent = any, TData = any> = (target: TParent, input: TData, // Don't use unknown here, otherwise users can't easily cast it
161
+ export type InputObjectFieldApplyResolver<TParent = any, TData = any, TScope = any> = (target: TParent, input: TData, // Don't use unknown here, otherwise users can't easily cast it
162
162
  info: {
163
163
  schema: GraphQLSchema;
164
164
  fieldName: string;
165
165
  field: GraphQLInputField;
166
+ scope: TScope;
166
167
  }) => any;
167
168
  export type InputObjectTypeBakedInfo = {
168
169
  schema: GraphQLSchema;
@@ -199,7 +200,10 @@ export type ScalarInputPlanResolver<TResultStep extends Step = Step> = ($inputVa
199
200
  *
200
201
  * @experimental
201
202
  */
202
- export type EnumValueApplyResolver<TParent = any> = (parent: TParent) => void;
203
+ export type EnumValueApplyResolver<TParent = any, TScope = any> = (parent: TParent, info: {
204
+ value: GraphQLEnumValue;
205
+ scope: TScope;
206
+ }) => void;
203
207
  /**
204
208
  * Basically GraphQLFieldConfig but with an easy to access `plan` method.
205
209
  */
@@ -13,13 +13,20 @@ export declare class ApplyInputStep<TParent extends object = any, TTarget extend
13
13
  isSyncAndSafe: boolean;
14
14
  allowMultipleOptimizations: boolean;
15
15
  valueDepId: 0;
16
- constructor(inputType: GraphQLInputType, $value: AnyInputStep, getTargetFromParent: ((parent: TParent, inputValue: any) => TTarget | undefined | (() => TTarget)) | undefined);
16
+ scopeDepId: 1 | null;
17
+ constructor(inputType: GraphQLInputType, $value: AnyInputStep, getTargetFromParent: ((parent: TParent, inputValue: any, info: {
18
+ scope: unknown;
19
+ }) => TTarget | undefined | (() => TTarget)) | undefined, $scope?: Step | null);
17
20
  deduplicate(peers: readonly ApplyInputStep[]): ApplyInputStep<any, any>[];
18
21
  optimize(): this | ConstantStep<(parent: TParent) => void>;
19
- unbatchedExecute(extra: UnbatchedExecutionExtra, value: any): (parentThing: TParent) => void;
22
+ unbatchedExecute(extra: UnbatchedExecutionExtra, value: any, scope: unknown): (parentThing: TParent) => void;
20
23
  }
21
- export declare function inputArgsApply<TArg extends object, TTarget extends object = TArg>(schema: GraphQLSchema, inputType: GraphQLInputType, parent: TArg, inputValue: unknown, getTargetFromParent: ((parent: TArg, inputValue: any) => TTarget | undefined | (() => TTarget)) | undefined): void;
22
- export declare function applyInput<TParent extends object = any, TTarget extends object = TParent>(inputType: GraphQLInputType, $value: AnyInputStep, getTargetFromParent?: (parent: TParent, inputValue: any) => TTarget | undefined): ConstantStep<(parent: TParent) => void> | ApplyInputStep<TParent, TTarget>;
24
+ export declare function inputArgsApply<TArg extends object, TTarget extends object = TArg>(schema: GraphQLSchema, inputType: GraphQLInputType, parent: TArg, inputValue: unknown, getTargetFromParent: ((parent: TArg, inputValue: any, info: {
25
+ scope: unknown;
26
+ }) => TTarget | undefined | (() => TTarget)) | undefined, scope: unknown): void;
27
+ export declare function applyInput<TParent extends object = any, TTarget extends object = TParent>(inputType: GraphQLInputType, $value: AnyInputStep, getTargetFromParent?: (parent: TParent, inputValue: any, info: {
28
+ scope: unknown;
29
+ }) => TTarget | undefined): ConstantStep<(parent: TParent) => void> | ApplyInputStep<TParent, TTarget>;
23
30
  /**
24
31
  * Modifiers modify their parent (which may be another modifier or anything
25
32
  * else). First they gather all the requirements from their children (if any)
@@ -18,13 +18,14 @@ class ApplyInputStep extends step_js_1.UnbatchedStep {
18
18
  moduleName: "grafast",
19
19
  exportName: "ApplyInputStep",
20
20
  }; }
21
- constructor(inputType, $value, getTargetFromParent) {
21
+ constructor(inputType, $value, getTargetFromParent, $scope) {
22
22
  super();
23
23
  this.inputType = inputType;
24
24
  this.getTargetFromParent = getTargetFromParent;
25
25
  this.isSyncAndSafe = true;
26
26
  this.allowMultipleOptimizations = true;
27
27
  this.valueDepId = this.addUnaryDependency($value);
28
+ this.scopeDepId = $scope ? this.addUnaryDependency($scope) : null;
28
29
  if (!this._isUnary) {
29
30
  throw new Error(`applyInput() must be unary`);
30
31
  }
@@ -36,30 +37,33 @@ class ApplyInputStep extends step_js_1.UnbatchedStep {
36
37
  }
37
38
  optimize() {
38
39
  const $value = this.getDep(this.valueDepId);
39
- if ($value instanceof constant_js_1.ConstantStep) {
40
+ const $scope = this.scopeDepId === null ? null : this.getDep(this.scopeDepId);
41
+ if ((!$scope || $scope instanceof constant_js_1.ConstantStep) &&
42
+ $value instanceof constant_js_1.ConstantStep) {
40
43
  // Replace myself with a constant!
41
44
  const { operationPlan: { schema }, inputType, getTargetFromParent, } = this;
42
45
  const { data } = $value;
46
+ const scope = $scope?.data;
43
47
  return (0, constant_js_1.constant)(function applyInputConstant(parent) {
44
- inputArgsApply(schema, inputType, parent, data, getTargetFromParent);
48
+ inputArgsApply(schema, inputType, parent, data, getTargetFromParent, scope);
45
49
  }, false);
46
50
  }
47
51
  return this;
48
52
  }
49
- unbatchedExecute(extra, value) {
53
+ unbatchedExecute(extra, value, scope) {
50
54
  const { getTargetFromParent } = this;
51
- return (parentThing) => inputArgsApply(this.operationPlan.schema, this.inputType, parentThing, value, getTargetFromParent);
55
+ return (parentThing) => inputArgsApply(this.operationPlan.schema, this.inputType, parentThing, value, getTargetFromParent, scope);
52
56
  }
53
57
  }
54
58
  exports.ApplyInputStep = ApplyInputStep;
55
- function inputArgsApply(schema, inputType, parent, inputValue, getTargetFromParent) {
59
+ function inputArgsApply(schema, inputType, parent, inputValue, getTargetFromParent, scope) {
56
60
  try {
57
61
  inputArgsApplyDepth++;
58
62
  const target = getTargetFromParent
59
- ? getTargetFromParent(parent, inputValue)
63
+ ? getTargetFromParent(parent, inputValue, { scope })
60
64
  : parent;
61
65
  if (target != null) {
62
- _inputArgsApply(schema, inputType, target, inputValue);
66
+ _inputArgsApply(schema, inputType, target, inputValue, scope);
63
67
  }
64
68
  }
65
69
  finally {
@@ -82,16 +86,20 @@ function inputArgsApply(schema, inputType, parent, inputValue, getTargetFromPare
82
86
  function applyInput(inputType, $value, getTargetFromParent) {
83
87
  const opPlan = (0, global_js_1.operationPlan)();
84
88
  const { schema } = opPlan;
89
+ const namedType = (0, graphql_1.getNamedType)(inputType);
85
90
  return opPlan.withRootLayerPlan(() => {
86
- if ($value instanceof constant_js_1.ConstantStep) {
91
+ const $scope = namedType.extensions?.grafast?.applyScope?.() ?? null;
92
+ if ((!$scope || $scope instanceof constant_js_1.ConstantStep) &&
93
+ $value instanceof constant_js_1.ConstantStep) {
87
94
  // Replace us with a constant
88
95
  const { data } = $value;
96
+ const scope = $scope?.data;
89
97
  return (0, constant_js_1.constant)(function applyInputConstant(parent) {
90
- inputArgsApply(schema, inputType, parent, data, getTargetFromParent);
98
+ inputArgsApply(schema, inputType, parent, data, getTargetFromParent, scope);
91
99
  }, false);
92
100
  }
93
101
  else {
94
- return new ApplyInputStep(inputType, $value, getTargetFromParent);
102
+ return new ApplyInputStep(inputType, $value, getTargetFromParent, $scope);
95
103
  }
96
104
  });
97
105
  }
@@ -106,7 +114,7 @@ const defaultInputObjectTypeInputPlanResolver: InputObjectTypeInputPlanResolver
106
114
  return object(obj);
107
115
  };
108
116
  */
109
- function _inputArgsApply(schema, inputType, target, inputValue) {
117
+ function _inputArgsApply(schema, inputType, target, inputValue, scope) {
110
118
  // PERF: we should have the plan generate a digest of `inputType` so that we
111
119
  // can jump right to the relevant parts without too much traversal cost.
112
120
  if (inputValue === undefined) {
@@ -116,7 +124,7 @@ function _inputArgsApply(schema, inputType, target, inputValue) {
116
124
  if (inputValue === null) {
117
125
  throw new Error(`null value found in non-null position`);
118
126
  }
119
- _inputArgsApply(schema, inputType.ofType, target, inputValue);
127
+ _inputArgsApply(schema, inputType.ofType, target, inputValue, scope);
120
128
  }
121
129
  else if ((0, graphql_1.isListType)(inputType)) {
122
130
  if (inputValue == null)
@@ -126,7 +134,7 @@ function _inputArgsApply(schema, inputType, target, inputValue) {
126
134
  }
127
135
  for (const item of inputValue) {
128
136
  const itemTarget = typeof target === "function" ? target() : target;
129
- _inputArgsApply(schema, inputType.ofType, itemTarget, item);
137
+ _inputArgsApply(schema, inputType.ofType, itemTarget, item, scope);
130
138
  }
131
139
  }
132
140
  else if (typeof target === "function") {
@@ -146,9 +154,10 @@ function _inputArgsApply(schema, inputType, target, inputValue) {
146
154
  schema,
147
155
  field,
148
156
  fieldName,
157
+ scope,
149
158
  });
150
159
  if (newTarget != null) {
151
- _inputArgsApply(schema, field.type, newTarget, val);
160
+ _inputArgsApply(schema, field.type, newTarget, val, scope);
152
161
  }
153
162
  }
154
163
  }
@@ -165,7 +174,7 @@ function _inputArgsApply(schema, inputType, target, inputValue) {
165
174
  const value = values.find((v) => v.value === inputValue);
166
175
  if (value) {
167
176
  if (value.extensions.grafast?.apply) {
168
- value.extensions.grafast.apply(target);
177
+ value.extensions.grafast.apply(target, { scope, value });
169
178
  }
170
179
  }
171
180
  else {
@@ -78,11 +78,11 @@ function bakedInputRuntime(schema, inputType, value) {
78
78
  schema,
79
79
  applyChildren(parent) {
80
80
  applied = true;
81
- (0, applyInput_js_1.inputArgsApply)(schema, nullableInputType, parent, value, undefined);
81
+ (0, applyInput_js_1.inputArgsApply)(schema, nullableInputType, parent, value, undefined, undefined);
82
82
  },
83
83
  });
84
84
  if (!applied) {
85
- (0, applyInput_js_1.inputArgsApply)(schema, nullableInputType, bakedObj, value, undefined);
85
+ (0, applyInput_js_1.inputArgsApply)(schema, nullableInputType, bakedObj, value, undefined, undefined);
86
86
  }
87
87
  return bakedObj;
88
88
  }
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version = "0.1.1-beta.22";
1
+ export declare const version = "0.1.1-beta.24";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
4
  // This file is autogenerated by /scripts/postversion.mjs
5
- exports.version = "0.1.1-beta.22";
5
+ exports.version = "0.1.1-beta.24";
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grafast",
3
- "version": "0.1.1-beta.22",
3
+ "version": "0.1.1-beta.24",
4
4
  "description": "Cutting edge GraphQL planning and execution engine",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -57,9 +57,9 @@
57
57
  "dependencies": {
58
58
  "@graphile/lru": "^5.0.0-beta.4",
59
59
  "chalk": "^4.1.2",
60
- "debug": "^4.3.4",
60
+ "debug": "^4.4.1",
61
61
  "eventemitter3": "^5.0.1",
62
- "graphile-config": "^0.0.1-beta.16",
62
+ "graphile-config": "^0.0.1-beta.17",
63
63
  "graphql": "^16.1.0-experimental-stream-defer.6",
64
64
  "iterall": "^1.3.0",
65
65
  "tamedevil": "^0.0.0-beta.8",
@@ -73,6 +73,12 @@
73
73
  "peerDependenciesMeta": {
74
74
  "@envelop/core": {
75
75
  "optional": true
76
+ },
77
+ "graphql": {
78
+ "optional": true
79
+ },
80
+ "tamedevil": {
81
+ "optional": true
76
82
  }
77
83
  },
78
84
  "files": [