@apollo/federation-internals 2.7.3 → 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.
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONNECT_VERSIONS = exports.ConnectSpecDefinition = exports.connectIdentity = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const coreSpec_1 = require("./coreSpec");
6
+ const definitions_1 = require("../definitions");
7
+ const knownCoreFeatures_1 = require("../knownCoreFeatures");
8
+ const directiveAndTypeSpecification_1 = require("../directiveAndTypeSpecification");
9
+ const error_1 = require("../error");
10
+ exports.connectIdentity = 'https://specs.apollo.dev/connect';
11
+ const CONNECT = "connect";
12
+ const SOURCE = "source";
13
+ const URL_PATH_TEMPLATE = "URLPathTemplate";
14
+ const JSON_SELECTION = "JSONSelection";
15
+ const CONNECT_HTTP = "ConnectHTTP";
16
+ const SOURCE_HTTP = "SourceHTTP";
17
+ const HTTP_HEADER_MAPPING = "HTTPHeaderMapping";
18
+ class ConnectSpecDefinition extends coreSpec_1.FeatureDefinition {
19
+ constructor(version, minimumFederationVersion) {
20
+ super(new coreSpec_1.FeatureUrl(exports.connectIdentity, CONNECT, version), minimumFederationVersion);
21
+ this.minimumFederationVersion = minimumFederationVersion;
22
+ this.registerDirective((0, directiveAndTypeSpecification_1.createDirectiveSpecification)({
23
+ name: CONNECT,
24
+ locations: [graphql_1.DirectiveLocation.FIELD_DEFINITION],
25
+ repeatable: true,
26
+ composes: false,
27
+ }));
28
+ this.registerDirective((0, directiveAndTypeSpecification_1.createDirectiveSpecification)({
29
+ name: SOURCE,
30
+ locations: [graphql_1.DirectiveLocation.SCHEMA],
31
+ repeatable: true,
32
+ composes: false,
33
+ }));
34
+ this.registerType({ name: URL_PATH_TEMPLATE, checkOrAdd: () => [] });
35
+ this.registerType({ name: JSON_SELECTION, checkOrAdd: () => [] });
36
+ this.registerType({ name: CONNECT_HTTP, checkOrAdd: () => [] });
37
+ this.registerType({ name: SOURCE_HTTP, checkOrAdd: () => [] });
38
+ this.registerType({ name: HTTP_HEADER_MAPPING, checkOrAdd: () => [] });
39
+ }
40
+ addElementsToSchema(schema) {
41
+ const URLPathTemplate = this.addScalarType(schema, URL_PATH_TEMPLATE);
42
+ const JSONSelection = this.addScalarType(schema, JSON_SELECTION);
43
+ const connect = this.addDirective(schema, CONNECT).addLocations(graphql_1.DirectiveLocation.FIELD_DEFINITION);
44
+ connect.repeatable = true;
45
+ connect.addArgument(SOURCE, schema.stringType());
46
+ const HTTPHeaderMapping = schema.addType(new definitions_1.InputObjectType(this.typeNameInSchema(schema, HTTP_HEADER_MAPPING)));
47
+ HTTPHeaderMapping.addField(new definitions_1.InputFieldDefinition('name')).type =
48
+ new definitions_1.NonNullType(schema.stringType());
49
+ HTTPHeaderMapping.addField(new definitions_1.InputFieldDefinition('as')).type =
50
+ schema.stringType();
51
+ HTTPHeaderMapping.addField(new definitions_1.InputFieldDefinition('value')).type =
52
+ schema.stringType();
53
+ const ConnectHTTP = schema.addType(new definitions_1.InputObjectType(this.typeNameInSchema(schema, CONNECT_HTTP)));
54
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('GET')).type = URLPathTemplate;
55
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('POST')).type = URLPathTemplate;
56
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('PUT')).type = URLPathTemplate;
57
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('PATCH')).type = URLPathTemplate;
58
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('DELETE')).type = URLPathTemplate;
59
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('body')).type = JSONSelection;
60
+ ConnectHTTP.addField(new definitions_1.InputFieldDefinition('headers')).type =
61
+ new definitions_1.ListType(new definitions_1.NonNullType(HTTPHeaderMapping));
62
+ connect.addArgument('http', ConnectHTTP);
63
+ connect.addArgument('selection', JSONSelection);
64
+ const source = this.addDirective(schema, SOURCE).addLocations(graphql_1.DirectiveLocation.SCHEMA);
65
+ source.repeatable = true;
66
+ source.addArgument('name', new definitions_1.NonNullType(schema.stringType()));
67
+ const SourceHTTP = schema.addType(new definitions_1.InputObjectType(this.typeNameInSchema(schema, SOURCE_HTTP)));
68
+ SourceHTTP.addField(new definitions_1.InputFieldDefinition('baseURL')).type =
69
+ new definitions_1.NonNullType(schema.stringType());
70
+ SourceHTTP.addField(new definitions_1.InputFieldDefinition('headers')).type =
71
+ new definitions_1.ListType(new definitions_1.NonNullType(HTTPHeaderMapping));
72
+ source.addArgument('http', SourceHTTP);
73
+ return [];
74
+ }
75
+ get defaultCorePurpose() {
76
+ return 'EXECUTION';
77
+ }
78
+ sourceDirective(schema) {
79
+ return this.directive(schema, 'source');
80
+ }
81
+ connectDirective(schema) {
82
+ return this.directive(schema, 'connect');
83
+ }
84
+ getConnectDirectives(schema) {
85
+ const result = {};
86
+ schema.schemaDefinition.appliedDirectivesOf('link')
87
+ .forEach(linkDirective => {
88
+ const { url, import: imports } = linkDirective.arguments();
89
+ const featureUrl = coreSpec_1.FeatureUrl.maybeParse(url);
90
+ if (imports && featureUrl && featureUrl.identity === exports.connectIdentity) {
91
+ imports.forEach(nameOrRename => {
92
+ const originalName = typeof nameOrRename === 'string' ? nameOrRename : nameOrRename.name;
93
+ const importedName = typeof nameOrRename === 'string' ? nameOrRename : nameOrRename.as || originalName;
94
+ const importedNameWithoutAt = importedName.replace(/^@/, '');
95
+ if (originalName === '@source') {
96
+ result.source = schema.directive(importedNameWithoutAt);
97
+ }
98
+ else if (originalName === '@connect') {
99
+ result.connect = schema.directive(importedNameWithoutAt);
100
+ }
101
+ });
102
+ }
103
+ });
104
+ return result;
105
+ }
106
+ validateSubgraphSchema(schema) {
107
+ const errors = super.validateSubgraphSchema(schema);
108
+ const { source: sourceAPI, connect: sourceField, } = this.getConnectDirectives(schema);
109
+ if (!(sourceAPI || sourceField)) {
110
+ return [];
111
+ }
112
+ errors.push(...this.validateConnectDirectives(schema));
113
+ return errors;
114
+ }
115
+ validateConnectDirectives(schema) {
116
+ try {
117
+ const { validate_connect_directives } = require('../../wasm/node');
118
+ const source = (0, graphql_1.print)(schema.toAST());
119
+ return validate_connect_directives(source).map(raw => error_1.ERRORS.WASM_VALIDATION_ERROR.err(raw.message, {
120
+ source: new graphql_1.Source(source),
121
+ positions: [raw.index],
122
+ }));
123
+ }
124
+ catch (e) {
125
+ return [error_1.ERRORS.WASM_LOAD_ERROR.err(`Error loading WASM module: ${e.message || e}`)];
126
+ }
127
+ }
128
+ }
129
+ exports.ConnectSpecDefinition = ConnectSpecDefinition;
130
+ exports.CONNECT_VERSIONS = new coreSpec_1.FeatureDefinitions(exports.connectIdentity)
131
+ .add(new ConnectSpecDefinition(new coreSpec_1.FeatureVersion(0, 1), new coreSpec_1.FeatureVersion(2, 8)));
132
+ (0, knownCoreFeatures_1.registerKnownFeature)(exports.CONNECT_VERSIONS);
133
+ //# sourceMappingURL=connectSpec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectSpec.js","sourceRoot":"","sources":["../../src/specs/connectSpec.ts"],"names":[],"mappings":";;;AAAA,qCAAyE;AACzE,yCAA+H;AAC/H,gDAOwB;AACxB,4DAA4D;AAC5D,oFAAgF;AAChF,oCAAkC;AAErB,QAAA,eAAe,GAAG,kCAAkC,CAAC;AAElE,MAAM,OAAO,GAAG,SAAS,CAAC;AAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC;AACxB,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAC5C,MAAM,cAAc,GAAG,eAAe,CAAC;AACvC,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,WAAW,GAAG,YAAY,CAAC;AACjC,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEhD,MAAa,qBAAsB,SAAQ,4BAAiB;IAC1D,YAAY,OAAuB,EAAW,wBAAwC;QACpF,KAAK,CAAC,IAAI,qBAAU,CAAC,uBAAe,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,wBAAwB,CAAC,CAAC;QADvC,6BAAwB,GAAxB,wBAAwB,CAAgB;QAGpF,IAAI,CAAC,iBAAiB,CAAC,IAAA,4DAA4B,EAAC;YAClD,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,CAAC,2BAAiB,CAAC,gBAAgB,CAAC;YAC/C,UAAU,EAAE,IAAI;YAIhB,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC,CAAC;QAEJ,IAAI,CAAC,iBAAiB,CAAC,IAAA,4DAA4B,EAAC;YAClD,IAAI,EAAE,MAAM;YACZ,SAAS,EAAE,CAAC,2BAAiB,CAAC,MAAM,CAAC;YACrC,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC,CAAC;QAEJ,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,mBAAmB,CAAC,MAAc;QAEhC,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;QAGtE,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QASjE,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,YAAY,CAAC,2BAAiB,CAAC,gBAAgB,CAAC,CAAC;QACpG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;QAE1B,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QASjD,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,6BAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,CAAE,CAAC,CAAC,CAAC;QACnH,iBAAiB,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;YAC/D,IAAI,yBAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACvC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;YAC7D,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,iBAAiB,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YAChE,MAAM,CAAC,UAAU,EAAE,CAAC;QAatB,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,6BAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAE,CAAC,CAAC,CAAC;QACtG,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,eAAe,CAAC;QAC7E,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,eAAe,CAAC;QAC9E,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,eAAe,CAAC;QAC7E,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,eAAe,CAAC;QAC/E,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,eAAe,CAAC;QAChF,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,aAAa,CAAC;QAC5E,WAAW,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YAC5D,IAAI,sBAAQ,CAAC,IAAI,yBAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEzC,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAQhD,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,YAAY,CAC3D,2BAAiB,CAAC,MAAM,CACzB,CAAC;QACF,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,yBAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAQjE,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,6BAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAE,CAAC,CAAC,CAAC;QACpG,UAAU,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YAC3D,IAAI,yBAAW,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QACvC,UAAU,CAAC,QAAQ,CAAC,IAAI,kCAAoB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YAC3D,IAAI,sBAAQ,CAAC,IAAI,yBAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAEnD,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAEvC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,kBAAkB;QACpB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,eAAe,CAAC,MAAc;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAsB,MAAM,EAAE,QAAQ,CAAE,CAAC;IAChE,CAAC;IAED,gBAAgB,CAAC,MAAc;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAuB,MAAM,EAAE,SAAS,CAAE,CAAC;IAClE,CAAC;IAEO,oBAAoB,CAAC,MAAc;QACzC,MAAM,MAAM,GAGR,EAAE,CAAC;QAEP,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,CAAoB,MAAM,CAAC;aACnE,OAAO,CAAC,aAAa,CAAC,EAAE;YACvB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,SAAS,EAAE,CAAC;YAC3D,MAAM,UAAU,GAAG,qBAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAC9C,IAAI,OAAO,IAAI,UAAU,IAAI,UAAU,CAAC,QAAQ,KAAK,uBAAe,EAAE,CAAC;gBACrE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;oBAC7B,MAAM,YAAY,GAAG,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;oBACzF,MAAM,YAAY,GAAG,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,IAAI,YAAY,CAAC;oBACvG,MAAM,qBAAqB,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAE7D,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;wBAC/B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,qBAAqB,CAA6C,CAAC;oBACtG,CAAC;yBAAM,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;wBACvC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,qBAAqB,CAA8C,CAAC;oBACxG,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;QAEL,OAAO,MAAM,CAAC;IAChB,CAAC;IAEQ,sBAAsB,CAAC,MAAc;QAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QACpD,MAAM,EACJ,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,WAAW,GACrB,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAEtC,IAAI,CAAC,CAAC,SAAS,IAAI,WAAW,CAAC,EAAE,CAAC;YAGhC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC;QAEvD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,yBAAyB,CAAC,MAAc;QAC9C,IAAI,CAAC;YACH,MAAM,EAAE,2BAA2B,EAAE,GACnC,OAAO,CAAC,iBAAiB,CAAqC,CAAC;YACjE,MAAM,MAAM,GAAG,IAAA,eAAK,EAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;YACrC,OAAO,2BAA2B,CAAC,MAAM,CAAC,CAAC,GAAG,CAC5C,GAAG,CAAC,EAAE,CAAC,cAAM,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE;gBACnD,MAAM,EAAE,IAAI,gBAAM,CAAC,MAAM,CAAC;gBAC1B,SAAS,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;aACvB,CAAC,CACH,CAAC;QACJ,CAAC;QAAC,OAAO,CAAM,EAAE,CAAC;YAChB,OAAO,CAAC,cAAM,CAAC,eAAe,CAAC,GAAG,CAChC,8BAA8B,CAAC,CAAC,OAAO,IAAI,CAAC,EAAE,CAC/C,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;AA9LD,sDA8LC;AAqCY,QAAA,gBAAgB,GAAG,IAAI,6BAAkB,CAAwB,uBAAe,CAAC;KAC3F,GAAG,CAAC,IAAI,qBAAqB,CAAC,IAAI,yBAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,yBAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtF,IAAA,wCAAoB,EAAC,wBAAgB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apollo/federation-internals",
3
- "version": "2.7.3",
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/index.ts CHANGED
@@ -24,3 +24,4 @@ export * from './specs/authenticatedSpec';
24
24
  export * from './specs/requiresScopesSpec';
25
25
  export * from './specs/policySpec';
26
26
  export * from './specs/sourceSpec';
27
+ export * from './specs/connectSpec';
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()
@@ -0,0 +1,255 @@
1
+ import { DirectiveLocation, GraphQLError, Source, print } from 'graphql';
2
+ import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureUrl, FeatureVersion, LinkDirectiveArgs } from "./coreSpec";
3
+ import {
4
+ Schema,
5
+ NonNullType,
6
+ InputObjectType,
7
+ InputFieldDefinition,
8
+ ListType,
9
+ DirectiveDefinition,
10
+ } from '../definitions';
11
+ import { registerKnownFeature } from '../knownCoreFeatures';
12
+ import { createDirectiveSpecification } from '../directiveAndTypeSpecification';
13
+ import { ERRORS } from '../error';
14
+
15
+ export const connectIdentity = 'https://specs.apollo.dev/connect';
16
+
17
+ const CONNECT = "connect";
18
+ const SOURCE = "source";
19
+ const URL_PATH_TEMPLATE = "URLPathTemplate";
20
+ const JSON_SELECTION = "JSONSelection";
21
+ const CONNECT_HTTP = "ConnectHTTP";
22
+ const SOURCE_HTTP = "SourceHTTP";
23
+ const HTTP_HEADER_MAPPING = "HTTPHeaderMapping";
24
+
25
+ export class ConnectSpecDefinition extends FeatureDefinition {
26
+ constructor(version: FeatureVersion, readonly minimumFederationVersion: FeatureVersion) {
27
+ super(new FeatureUrl(connectIdentity, CONNECT, version), minimumFederationVersion);
28
+
29
+ this.registerDirective(createDirectiveSpecification({
30
+ name: CONNECT,
31
+ locations: [DirectiveLocation.FIELD_DEFINITION],
32
+ repeatable: true,
33
+ // We "compose" these directives using the `@join__directive` mechanism,
34
+ // so they do not need to be composed in the way passing `composes: true`
35
+ // here implies.
36
+ composes: false,
37
+ }));
38
+
39
+ this.registerDirective(createDirectiveSpecification({
40
+ name: SOURCE,
41
+ locations: [DirectiveLocation.SCHEMA],
42
+ repeatable: true,
43
+ composes: false,
44
+ }));
45
+
46
+ this.registerType({ name: URL_PATH_TEMPLATE, checkOrAdd: () => [] });
47
+ this.registerType({ name: JSON_SELECTION, checkOrAdd: () => [] });
48
+ this.registerType({ name: CONNECT_HTTP, checkOrAdd: () => [] });
49
+ this.registerType({ name: SOURCE_HTTP, checkOrAdd: () => [] });
50
+ this.registerType({ name: HTTP_HEADER_MAPPING, checkOrAdd: () => [] });
51
+ }
52
+
53
+ addElementsToSchema(schema: Schema): GraphQLError[] {
54
+ /* scalar URLPathTemplate */
55
+ const URLPathTemplate = this.addScalarType(schema, URL_PATH_TEMPLATE);
56
+
57
+ /* scalar JSONSelection */
58
+ const JSONSelection = this.addScalarType(schema, JSON_SELECTION);
59
+
60
+ /*
61
+ directive @connect(
62
+ source: String
63
+ http: ConnectHTTP
64
+ selection: JSONSelection!
65
+ ) repeatable on FIELD_DEFINITION
66
+ */
67
+ const connect = this.addDirective(schema, CONNECT).addLocations(DirectiveLocation.FIELD_DEFINITION);
68
+ connect.repeatable = true;
69
+
70
+ connect.addArgument(SOURCE, schema.stringType());
71
+
72
+ /*
73
+ input HTTPHeaderMapping {
74
+ name: String!
75
+ as: String
76
+ value: String
77
+ }
78
+ */
79
+ const HTTPHeaderMapping = schema.addType(new InputObjectType(this.typeNameInSchema(schema, HTTP_HEADER_MAPPING)!));
80
+ HTTPHeaderMapping.addField(new InputFieldDefinition('name')).type =
81
+ new NonNullType(schema.stringType());
82
+ HTTPHeaderMapping.addField(new InputFieldDefinition('as')).type =
83
+ schema.stringType();
84
+ HTTPHeaderMapping.addField(new InputFieldDefinition('value')).type =
85
+ schema.stringType();
86
+
87
+ /*
88
+ input ConnectHTTP {
89
+ GET: URLPathTemplate
90
+ POST: URLPathTemplate
91
+ PUT: URLPathTemplate
92
+ PATCH: URLPathTemplate
93
+ DELETE: URLPathTemplate
94
+ body: JSONSelection
95
+ headers: [HTTPHeaderMapping!]
96
+ }
97
+ */
98
+ const ConnectHTTP = schema.addType(new InputObjectType(this.typeNameInSchema(schema, CONNECT_HTTP)!));
99
+ ConnectHTTP.addField(new InputFieldDefinition('GET')).type = URLPathTemplate;
100
+ ConnectHTTP.addField(new InputFieldDefinition('POST')).type = URLPathTemplate;
101
+ ConnectHTTP.addField(new InputFieldDefinition('PUT')).type = URLPathTemplate;
102
+ ConnectHTTP.addField(new InputFieldDefinition('PATCH')).type = URLPathTemplate;
103
+ ConnectHTTP.addField(new InputFieldDefinition('DELETE')).type = URLPathTemplate;
104
+ ConnectHTTP.addField(new InputFieldDefinition('body')).type = JSONSelection;
105
+ ConnectHTTP.addField(new InputFieldDefinition('headers')).type =
106
+ new ListType(new NonNullType(HTTPHeaderMapping));
107
+ connect.addArgument('http', ConnectHTTP);
108
+
109
+ connect.addArgument('selection', JSONSelection);
110
+
111
+ /*
112
+ directive @source(
113
+ name: String!
114
+ http: ConnectHTTP
115
+ ) repeatable on SCHEMA
116
+ */
117
+ const source = this.addDirective(schema, SOURCE).addLocations(
118
+ DirectiveLocation.SCHEMA,
119
+ );
120
+ source.repeatable = true;
121
+ source.addArgument('name', new NonNullType(schema.stringType()));
122
+
123
+ /*
124
+ input SourceHTTP {
125
+ baseURL: String!
126
+ headers: [HTTPHeaderMapping!]
127
+ }
128
+ */
129
+ const SourceHTTP = schema.addType(new InputObjectType(this.typeNameInSchema(schema, SOURCE_HTTP)!));
130
+ SourceHTTP.addField(new InputFieldDefinition('baseURL')).type =
131
+ new NonNullType(schema.stringType());
132
+ SourceHTTP.addField(new InputFieldDefinition('headers')).type =
133
+ new ListType(new NonNullType(HTTPHeaderMapping));
134
+
135
+ source.addArgument('http', SourceHTTP);
136
+
137
+ return [];
138
+ }
139
+
140
+ get defaultCorePurpose(): CorePurpose {
141
+ return 'EXECUTION';
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
+ }
215
+ }
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
+
252
+ export const CONNECT_VERSIONS = new FeatureDefinitions<ConnectSpecDefinition>(connectIdentity)
253
+ .add(new ConnectSpecDefinition(new FeatureVersion(0, 1), new FeatureVersion(2, 8)));
254
+
255
+ registerKnownFeature(CONNECT_VERSIONS);
@@ -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[];