@apollo/federation-internals 2.7.3-testing.0 → 2.7.4-testing.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apollo/federation-internals",
3
- "version": "2.7.3-testing.0",
3
+ "version": "2.7.4-testing.1",
4
4
  "description": "Apollo Federation internal utilities",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/error.ts CHANGED
@@ -674,6 +674,18 @@ const SOURCE_FIELD_NOT_ON_ROOT_OR_ENTITY_FIELD = makeCodeDefinition(
674
674
  { addedIn: '2.7.0' },
675
675
  );
676
676
 
677
+ const WASM_VALIDATION_ERROR = makeCodeDefinition(
678
+ 'WASM_VALIDATION_ERROR',
679
+ 'Subgraph validation error generated by WASM code',
680
+ { addedIn: '2.8.0' },
681
+ );
682
+
683
+ const WASM_LOAD_ERROR = makeCodeDefinition(
684
+ 'WASM_LOAD_ERROR',
685
+ 'Error loading a WebAssembly module',
686
+ { addedIn: '2.8.0' },
687
+ );
688
+
677
689
  export const ERROR_CATEGORIES = {
678
690
  DIRECTIVE_FIELDS_MISSING_EXTERNAL,
679
691
  DIRECTIVE_UNSUPPORTED_ON_INTERFACE,
@@ -782,6 +794,8 @@ export const ERRORS = {
782
794
  SOURCE_FIELD_HTTP_BODY_INVALID,
783
795
  SOURCE_FIELD_SELECTION_INVALID,
784
796
  SOURCE_FIELD_NOT_ON_ROOT_OR_ENTITY_FIELD,
797
+ WASM_VALIDATION_ERROR,
798
+ WASM_LOAD_ERROR,
785
799
  };
786
800
 
787
801
  const codeDefByCode = Object.values(ERRORS).reduce((obj: {[code: string]: ErrorCodeDefinition}, codeDef: ErrorCodeDefinition) => { obj[codeDef.code] = codeDef; return obj; }, {});
package/src/operations.ts CHANGED
@@ -879,15 +879,16 @@ function computeFragmentsToKeep(
879
879
  return toExpand.size === 0 ? fragments : fragments.filter((f) => !toExpand.has(f.name));
880
880
  }
881
881
 
882
- export class Operation {
882
+ export class Operation extends DirectiveTargetElement<Operation> {
883
883
  constructor(
884
- readonly schema: Schema,
884
+ schema: Schema,
885
885
  readonly rootKind: SchemaRootKind,
886
886
  readonly selectionSet: SelectionSet,
887
887
  readonly variableDefinitions: VariableDefinitions,
888
888
  readonly fragments?: NamedFragments,
889
889
  readonly name?: string,
890
- readonly directives?: readonly Directive<any>[]) {
890
+ directives: readonly Directive<any>[] = []) {
891
+ super(schema, directives);
891
892
  }
892
893
 
893
894
  // Returns a copy of this operation with the provided updated selection set.
@@ -898,13 +899,13 @@ export class Operation {
898
899
  }
899
900
 
900
901
  return new Operation(
901
- this.schema,
902
+ this.schema(),
902
903
  this.rootKind,
903
904
  newSelectionSet,
904
905
  this.variableDefinitions,
905
906
  this.fragments,
906
907
  this.name,
907
- this.directives
908
+ this.appliedDirectives,
908
909
  );
909
910
  }
910
911
 
@@ -915,13 +916,13 @@ export class Operation {
915
916
  }
916
917
 
917
918
  return new Operation(
918
- this.schema,
919
+ this.schema(),
919
920
  this.rootKind,
920
921
  newSelectionSet,
921
922
  this.variableDefinitions,
922
923
  newFragments,
923
924
  this.name,
924
- this.directives
925
+ this.appliedDirectives,
925
926
  );
926
927
  }
927
928
 
@@ -980,13 +981,13 @@ export class Operation {
980
981
  generateQueryFragments(): Operation {
981
982
  const [minimizedSelectionSet, fragments] = this.selectionSet.minimizeSelectionSet();
982
983
  return new Operation(
983
- this.schema,
984
+ this.schema(),
984
985
  this.rootKind,
985
986
  minimizedSelectionSet,
986
987
  this.variableDefinitions,
987
988
  fragments,
988
989
  this.name,
989
- this.directives
990
+ this.appliedDirectives,
990
991
  );
991
992
  }
992
993
 
@@ -1058,7 +1059,7 @@ export class Operation {
1058
1059
  }
1059
1060
 
1060
1061
  toString(expandFragments: boolean = false, prettyPrint: boolean = true): string {
1061
- return this.selectionSet.toOperationString(this.rootKind, this.variableDefinitions, this.fragments, this.name, this.directives, expandFragments, prettyPrint);
1062
+ return this.selectionSet.toOperationString(this.rootKind, this.variableDefinitions, this.fragments, this.name, this.appliedDirectives, expandFragments, prettyPrint);
1062
1063
  }
1063
1064
  }
1064
1065
 
@@ -3968,7 +3969,7 @@ export function operationToDocument(operation: Operation): DocumentNode {
3968
3969
  name: operation.name ? { kind: Kind.NAME, value: operation.name } : undefined,
3969
3970
  selectionSet: operation.selectionSet.toSelectionSetNode(),
3970
3971
  variableDefinitions: operation.variableDefinitions.toVariableDefinitionNodes(),
3971
- directives: directivesToDirectiveNodes(operation.directives),
3972
+ directives: directivesToDirectiveNodes(operation.appliedDirectives),
3972
3973
  };
3973
3974
  const fragmentASTs: DefinitionNode[] = operation.fragments
3974
3975
  ? operation.fragments?.toFragmentDefinitionNodes()
@@ -1,14 +1,16 @@
1
- import { DirectiveLocation, GraphQLError } from 'graphql';
2
- import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureUrl, FeatureVersion } from "./coreSpec";
1
+ import { DirectiveLocation, GraphQLError, Source, print } from 'graphql';
2
+ import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureUrl, FeatureVersion, LinkDirectiveArgs } from "./coreSpec";
3
3
  import {
4
4
  Schema,
5
5
  NonNullType,
6
6
  InputObjectType,
7
7
  InputFieldDefinition,
8
8
  ListType,
9
+ DirectiveDefinition,
9
10
  } from '../definitions';
10
11
  import { registerKnownFeature } from '../knownCoreFeatures';
11
12
  import { createDirectiveSpecification } from '../directiveAndTypeSpecification';
13
+ import { ERRORS } from '../error';
12
14
 
13
15
  export const connectIdentity = 'https://specs.apollo.dev/connect';
14
16
 
@@ -22,7 +24,7 @@ const HTTP_HEADER_MAPPING = "HTTPHeaderMapping";
22
24
 
23
25
  export class ConnectSpecDefinition extends FeatureDefinition {
24
26
  constructor(version: FeatureVersion, readonly minimumFederationVersion: FeatureVersion) {
25
- super(new FeatureUrl(connectIdentity, 'connect', version), minimumFederationVersion);
27
+ super(new FeatureUrl(connectIdentity, CONNECT, version), minimumFederationVersion);
26
28
 
27
29
  this.registerDirective(createDirectiveSpecification({
28
30
  name: CONNECT,
@@ -138,8 +140,115 @@ export class ConnectSpecDefinition extends FeatureDefinition {
138
140
  get defaultCorePurpose(): CorePurpose {
139
141
  return 'EXECUTION';
140
142
  }
143
+
144
+ sourceDirective(schema: Schema) {
145
+ return this.directive<SourceDirectiveArgs>(schema, 'source')!;
146
+ }
147
+
148
+ connectDirective(schema: Schema) {
149
+ return this.directive<ConnectDirectiveArgs>(schema, 'connect')!;
150
+ }
151
+
152
+ private getConnectDirectives(schema: Schema) {
153
+ const result: {
154
+ source?: DirectiveDefinition<SourceDirectiveArgs>;
155
+ connect?: DirectiveDefinition<ConnectDirectiveArgs>;
156
+ } = {};
157
+
158
+ schema.schemaDefinition.appliedDirectivesOf<LinkDirectiveArgs>('link')
159
+ .forEach(linkDirective => {
160
+ const { url, import: imports } = linkDirective.arguments();
161
+ const featureUrl = FeatureUrl.maybeParse(url);
162
+ if (imports && featureUrl && featureUrl.identity === connectIdentity) {
163
+ imports.forEach(nameOrRename => {
164
+ const originalName = typeof nameOrRename === 'string' ? nameOrRename : nameOrRename.name;
165
+ const importedName = typeof nameOrRename === 'string' ? nameOrRename : nameOrRename.as || originalName;
166
+ const importedNameWithoutAt = importedName.replace(/^@/, '');
167
+
168
+ if (originalName === '@source') {
169
+ result.source = schema.directive(importedNameWithoutAt) as DirectiveDefinition<SourceDirectiveArgs>;
170
+ } else if (originalName === '@connect') {
171
+ result.connect = schema.directive(importedNameWithoutAt) as DirectiveDefinition<ConnectDirectiveArgs>;
172
+ }
173
+ });
174
+ }
175
+ });
176
+
177
+ return result;
178
+ }
179
+
180
+ override validateSubgraphSchema(schema: Schema): GraphQLError[] {
181
+ const errors = super.validateSubgraphSchema(schema);
182
+ const {
183
+ source: sourceAPI,
184
+ connect: sourceField,
185
+ } = this.getConnectDirectives(schema);
186
+
187
+ if (!(sourceAPI || sourceField)) {
188
+ // If none of the @source* directives are present, nothing needs
189
+ // validating.
190
+ return [];
191
+ }
192
+
193
+ errors.push(...this.validateConnectDirectives(schema));
194
+
195
+ return errors;
196
+ }
197
+
198
+ private validateConnectDirectives(schema: Schema): GraphQLError[] {
199
+ try {
200
+ const { validate_connect_directives } =
201
+ require('../../wasm/node') as typeof import('../../wasm/node');
202
+ const source = print(schema.toAST());
203
+ return validate_connect_directives(source).map(
204
+ raw => ERRORS.WASM_VALIDATION_ERROR.err(raw.message, {
205
+ source: new Source(source),
206
+ positions: [raw.index],
207
+ }),
208
+ );
209
+ } catch (e: any) {
210
+ return [ERRORS.WASM_LOAD_ERROR.err(
211
+ `Error loading WASM module: ${e.message || e}`,
212
+ )];
213
+ }
214
+ }
141
215
  }
142
216
 
217
+ export type SourceDirectiveArgs = {
218
+ name: string;
219
+ http?: SourceDirectiveHTTP;
220
+ };
221
+
222
+ export type SourceDirectiveHTTP = {
223
+ baseURL: string;
224
+ headers?: HTTPHeaderMapping[];
225
+ };
226
+
227
+ type HTTPHeaderMapping = {
228
+ name: string;
229
+ as?: string;
230
+ value?: string;
231
+ };
232
+
233
+ type URLPathTemplate = string;
234
+ type JSONSelection = string;
235
+
236
+ export type ConnectDirectiveArgs = {
237
+ source: string;
238
+ http?: ConnectDirectiveHTTP;
239
+ selection?: JSONSelection;
240
+ };
241
+
242
+ export type ConnectDirectiveHTTP = {
243
+ GET?: URLPathTemplate;
244
+ POST?: URLPathTemplate;
245
+ PUT?: URLPathTemplate;
246
+ PATCH?: URLPathTemplate;
247
+ DELETE?: URLPathTemplate;
248
+ body?: JSONSelection;
249
+ headers?: HTTPHeaderMapping[];
250
+ };
251
+
143
252
  export const CONNECT_VERSIONS = new FeatureDefinitions<ConnectSpecDefinition>(connectIdentity)
144
253
  .add(new ConnectSpecDefinition(new FeatureVersion(0, 1), new FeatureVersion(2, 8)));
145
254
 
@@ -0,0 +1,7 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /**
4
+ * @param {string} schema
5
+ * @returns {any[]}
6
+ */
7
+ export function validate_connect_directives(schema: string): any[];
@@ -0,0 +1,278 @@
1
+ let imports = {};
2
+ imports['__wbindgen_placeholder__'] = module.exports;
3
+ let wasm;
4
+ const { TextDecoder, TextEncoder } = require(`util`);
5
+
6
+ const heap = new Array(128).fill(undefined);
7
+
8
+ heap.push(undefined, null, true, false);
9
+
10
+ function getObject(idx) { return heap[idx]; }
11
+
12
+ let heap_next = heap.length;
13
+
14
+ function dropObject(idx) {
15
+ if (idx < 132) return;
16
+ heap[idx] = heap_next;
17
+ heap_next = idx;
18
+ }
19
+
20
+ function takeObject(idx) {
21
+ const ret = getObject(idx);
22
+ dropObject(idx);
23
+ return ret;
24
+ }
25
+
26
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
27
+
28
+ cachedTextDecoder.decode();
29
+
30
+ let cachedUint8Memory0 = null;
31
+
32
+ function getUint8Memory0() {
33
+ if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {
34
+ cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
35
+ }
36
+ return cachedUint8Memory0;
37
+ }
38
+
39
+ function getStringFromWasm0(ptr, len) {
40
+ ptr = ptr >>> 0;
41
+ return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
42
+ }
43
+
44
+ function addHeapObject(obj) {
45
+ if (heap_next === heap.length) heap.push(heap.length + 1);
46
+ const idx = heap_next;
47
+ heap_next = heap[idx];
48
+
49
+ heap[idx] = obj;
50
+ return idx;
51
+ }
52
+
53
+ function debugString(val) {
54
+ // primitive types
55
+ const type = typeof val;
56
+ if (type == 'number' || type == 'boolean' || val == null) {
57
+ return `${val}`;
58
+ }
59
+ if (type == 'string') {
60
+ return `"${val}"`;
61
+ }
62
+ if (type == 'symbol') {
63
+ const description = val.description;
64
+ if (description == null) {
65
+ return 'Symbol';
66
+ } else {
67
+ return `Symbol(${description})`;
68
+ }
69
+ }
70
+ if (type == 'function') {
71
+ const name = val.name;
72
+ if (typeof name == 'string' && name.length > 0) {
73
+ return `Function(${name})`;
74
+ } else {
75
+ return 'Function';
76
+ }
77
+ }
78
+ // objects
79
+ if (Array.isArray(val)) {
80
+ const length = val.length;
81
+ let debug = '[';
82
+ if (length > 0) {
83
+ debug += debugString(val[0]);
84
+ }
85
+ for(let i = 1; i < length; i++) {
86
+ debug += ', ' + debugString(val[i]);
87
+ }
88
+ debug += ']';
89
+ return debug;
90
+ }
91
+ // Test for built-in
92
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
93
+ let className;
94
+ if (builtInMatches.length > 1) {
95
+ className = builtInMatches[1];
96
+ } else {
97
+ // Failed to match the standard '[object ClassName]'
98
+ return toString.call(val);
99
+ }
100
+ if (className == 'Object') {
101
+ // we're a user defined class or Object
102
+ // JSON.stringify avoids problems with cycles, and is generally much
103
+ // easier than looping through ownProperties of `val`.
104
+ try {
105
+ return 'Object(' + JSON.stringify(val) + ')';
106
+ } catch (_) {
107
+ return 'Object';
108
+ }
109
+ }
110
+ // errors
111
+ if (val instanceof Error) {
112
+ return `${val.name}: ${val.message}\n${val.stack}`;
113
+ }
114
+ // TODO we could test for more things here, like `Set`s and `Map`s.
115
+ return className;
116
+ }
117
+
118
+ let WASM_VECTOR_LEN = 0;
119
+
120
+ let cachedTextEncoder = new TextEncoder('utf-8');
121
+
122
+ const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
123
+ ? function (arg, view) {
124
+ return cachedTextEncoder.encodeInto(arg, view);
125
+ }
126
+ : function (arg, view) {
127
+ const buf = cachedTextEncoder.encode(arg);
128
+ view.set(buf);
129
+ return {
130
+ read: arg.length,
131
+ written: buf.length
132
+ };
133
+ });
134
+
135
+ function passStringToWasm0(arg, malloc, realloc) {
136
+
137
+ if (realloc === undefined) {
138
+ const buf = cachedTextEncoder.encode(arg);
139
+ const ptr = malloc(buf.length, 1) >>> 0;
140
+ getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
141
+ WASM_VECTOR_LEN = buf.length;
142
+ return ptr;
143
+ }
144
+
145
+ let len = arg.length;
146
+ let ptr = malloc(len, 1) >>> 0;
147
+
148
+ const mem = getUint8Memory0();
149
+
150
+ let offset = 0;
151
+
152
+ for (; offset < len; offset++) {
153
+ const code = arg.charCodeAt(offset);
154
+ if (code > 0x7F) break;
155
+ mem[ptr + offset] = code;
156
+ }
157
+
158
+ if (offset !== len) {
159
+ if (offset !== 0) {
160
+ arg = arg.slice(offset);
161
+ }
162
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
163
+ const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
164
+ const ret = encodeString(arg, view);
165
+
166
+ offset += ret.written;
167
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
168
+ }
169
+
170
+ WASM_VECTOR_LEN = offset;
171
+ return ptr;
172
+ }
173
+
174
+ let cachedInt32Memory0 = null;
175
+
176
+ function getInt32Memory0() {
177
+ if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {
178
+ cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
179
+ }
180
+ return cachedInt32Memory0;
181
+ }
182
+
183
+ let cachedUint32Memory0 = null;
184
+
185
+ function getUint32Memory0() {
186
+ if (cachedUint32Memory0 === null || cachedUint32Memory0.byteLength === 0) {
187
+ cachedUint32Memory0 = new Uint32Array(wasm.memory.buffer);
188
+ }
189
+ return cachedUint32Memory0;
190
+ }
191
+
192
+ function getArrayJsValueFromWasm0(ptr, len) {
193
+ ptr = ptr >>> 0;
194
+ const mem = getUint32Memory0();
195
+ const slice = mem.subarray(ptr / 4, ptr / 4 + len);
196
+ const result = [];
197
+ for (let i = 0; i < slice.length; i++) {
198
+ result.push(takeObject(slice[i]));
199
+ }
200
+ return result;
201
+ }
202
+ /**
203
+ * @param {string} schema
204
+ * @returns {any[]}
205
+ */
206
+ module.exports.validate_connect_directives = function(schema) {
207
+ try {
208
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
209
+ const ptr0 = passStringToWasm0(schema, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
210
+ const len0 = WASM_VECTOR_LEN;
211
+ wasm.validate_connect_directives(retptr, ptr0, len0);
212
+ var r0 = getInt32Memory0()[retptr / 4 + 0];
213
+ var r1 = getInt32Memory0()[retptr / 4 + 1];
214
+ var v2 = getArrayJsValueFromWasm0(r0, r1).slice();
215
+ wasm.__wbindgen_free(r0, r1 * 4, 4);
216
+ return v2;
217
+ } finally {
218
+ wasm.__wbindgen_add_to_stack_pointer(16);
219
+ }
220
+ };
221
+
222
+ function handleError(f, args) {
223
+ try {
224
+ return f.apply(this, args);
225
+ } catch (e) {
226
+ wasm.__wbindgen_exn_store(addHeapObject(e));
227
+ }
228
+ }
229
+
230
+ module.exports.__wbindgen_object_drop_ref = function(arg0) {
231
+ takeObject(arg0);
232
+ };
233
+
234
+ module.exports.__wbindgen_string_new = function(arg0, arg1) {
235
+ const ret = getStringFromWasm0(arg0, arg1);
236
+ return addHeapObject(ret);
237
+ };
238
+
239
+ module.exports.__wbindgen_number_new = function(arg0) {
240
+ const ret = arg0;
241
+ return addHeapObject(ret);
242
+ };
243
+
244
+ module.exports.__wbindgen_object_clone_ref = function(arg0) {
245
+ const ret = getObject(arg0);
246
+ return addHeapObject(ret);
247
+ };
248
+
249
+ module.exports.__wbg_new_72fb9a18b5ae2624 = function() {
250
+ const ret = new Object();
251
+ return addHeapObject(ret);
252
+ };
253
+
254
+ module.exports.__wbg_set_1f9b04f170055d33 = function() { return handleError(function (arg0, arg1, arg2) {
255
+ const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
256
+ return ret;
257
+ }, arguments) };
258
+
259
+ module.exports.__wbindgen_debug_string = function(arg0, arg1) {
260
+ const ret = debugString(getObject(arg1));
261
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
262
+ const len1 = WASM_VECTOR_LEN;
263
+ getInt32Memory0()[arg0 / 4 + 1] = len1;
264
+ getInt32Memory0()[arg0 / 4 + 0] = ptr1;
265
+ };
266
+
267
+ module.exports.__wbindgen_throw = function(arg0, arg1) {
268
+ throw new Error(getStringFromWasm0(arg0, arg1));
269
+ };
270
+
271
+ const path = require('path').join(__dirname, 'federation_internals_wasm_bg.wasm');
272
+ const bytes = require('fs').readFileSync(path);
273
+
274
+ const wasmModule = new WebAssembly.Module(bytes);
275
+ const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
276
+ wasm = wasmInstance.exports;
277
+ module.exports.__wasm = wasm;
278
+
@@ -0,0 +1,9 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ export const memory: WebAssembly.Memory;
4
+ export function validate_connect_directives(a: number, b: number, c: number): void;
5
+ export function __wbindgen_malloc(a: number, b: number): number;
6
+ export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
7
+ export function __wbindgen_add_to_stack_pointer(a: number): number;
8
+ export function __wbindgen_free(a: number, b: number, c: number): void;
9
+ export function __wbindgen_exn_store(a: number): void;
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "federation-internals-wasm",
3
+ "collaborators": [
4
+ "Ben Newman <ben@apollographql.com>"
5
+ ],
6
+ "version": "0.1.0",
7
+ "files": [
8
+ "federation_internals_wasm_bg.wasm",
9
+ "federation_internals_wasm.js",
10
+ "federation_internals_wasm.d.ts"
11
+ ],
12
+ "main": "federation_internals_wasm.js",
13
+ "types": "federation_internals_wasm.d.ts"
14
+ }