@effect-gql/federation 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2025 Nick Fisher
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,136 @@
1
+ import type { FederationDirective, KeyDirective } from "./types";
2
+ /**
3
+ * Create a @key directive for entity identification
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * entity({
8
+ * name: "User",
9
+ * schema: UserSchema,
10
+ * keys: [key({ fields: "id" })],
11
+ * resolveReference: (ref) => UserService.findById(ref.id),
12
+ * })
13
+ * ```
14
+ */
15
+ export declare const key: (config: KeyDirective) => FederationDirective;
16
+ /**
17
+ * Create a @shareable directive
18
+ * Marks a type or field as resolvable by multiple subgraphs
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * entity({
23
+ * name: "Product",
24
+ * schema: ProductSchema,
25
+ * keys: [key({ fields: "id" })],
26
+ * directives: [shareable()],
27
+ * })
28
+ * ```
29
+ */
30
+ export declare const shareable: () => FederationDirective;
31
+ /**
32
+ * Create an @inaccessible directive
33
+ * Omits the type/field from the public API while keeping it available for federation
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * objectType({
38
+ * name: "InternalMetadata",
39
+ * schema: MetadataSchema,
40
+ * directives: [inaccessible()],
41
+ * })
42
+ * ```
43
+ */
44
+ export declare const inaccessible: () => FederationDirective;
45
+ /**
46
+ * Create an @interfaceObject directive
47
+ * Indicates this object represents an interface from another subgraph
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * objectType({
52
+ * name: "Media",
53
+ * schema: MediaSchema,
54
+ * directives: [interfaceObject()],
55
+ * })
56
+ * ```
57
+ */
58
+ export declare const interfaceObject: () => FederationDirective;
59
+ /**
60
+ * Create a @tag directive for metadata annotation
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * entity({
65
+ * name: "Product",
66
+ * schema: ProductSchema,
67
+ * keys: [key({ fields: "id" })],
68
+ * directives: [tag("public"), tag("catalog")],
69
+ * })
70
+ * ```
71
+ */
72
+ export declare const tag: (name: string) => FederationDirective;
73
+ /**
74
+ * Create an @external directive
75
+ * Marks a field as defined in another subgraph
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * field("User", "externalId", {
80
+ * type: S.String,
81
+ * directives: [external()],
82
+ * resolve: (parent) => parent.externalId,
83
+ * })
84
+ * ```
85
+ */
86
+ export declare const external: () => FederationDirective;
87
+ /**
88
+ * Create a @requires directive
89
+ * Specifies fields that must be fetched from other subgraphs before this field can be resolved
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * field("Product", "shippingEstimate", {
94
+ * type: S.Int,
95
+ * directives: [requires({ fields: "weight dimensions { height width }" })],
96
+ * resolve: (product) => calculateShipping(product.weight, product.dimensions),
97
+ * })
98
+ * ```
99
+ */
100
+ export declare const requires: (config: {
101
+ fields: string;
102
+ }) => FederationDirective;
103
+ /**
104
+ * Create a @provides directive
105
+ * Router optimization hint - indicates this field provides additional fields on the returned type
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * field("Review", "author", {
110
+ * type: UserSchema,
111
+ * directives: [provides({ fields: "name email" })],
112
+ * resolve: (review) => UserService.findById(review.authorId),
113
+ * })
114
+ * ```
115
+ */
116
+ export declare const provides: (config: {
117
+ fields: string;
118
+ }) => FederationDirective;
119
+ /**
120
+ * Create an @override directive
121
+ * Transfers resolution responsibility from another subgraph
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * field("Product", "price", {
126
+ * type: S.Number,
127
+ * directives: [override({ from: "legacy-pricing" })],
128
+ * resolve: (product) => PricingService.getPrice(product.id),
129
+ * })
130
+ * ```
131
+ */
132
+ export declare const override: (config: {
133
+ from: string;
134
+ label?: string;
135
+ }) => FederationDirective;
136
+ //# sourceMappingURL=directives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directives.d.ts","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAMhE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,GAAG,GAAI,QAAQ,YAAY,KAAG,mBAIzC,CAAA;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,SAAS,QAAO,mBAE3B,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,QAAO,mBAE9B,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,QAAO,mBAEjC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,mBAGjC,CAAA;AAMF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,QAAO,mBAE1B,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,GAAI,QAAQ;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,KAAG,mBAGpD,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,GAAI,QAAQ;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,KAAG,mBAGpD,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,QAAQ,GAAI,QAAQ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,mBAIlE,CAAA"}
@@ -0,0 +1,171 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.override = exports.provides = exports.requires = exports.external = exports.tag = exports.interfaceObject = exports.inaccessible = exports.shareable = exports.key = void 0;
4
+ // ============================================================================
5
+ // Type-Level Directive Factories
6
+ // ============================================================================
7
+ /**
8
+ * Create a @key directive for entity identification
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * entity({
13
+ * name: "User",
14
+ * schema: UserSchema,
15
+ * keys: [key({ fields: "id" })],
16
+ * resolveReference: (ref) => UserService.findById(ref.id),
17
+ * })
18
+ * ```
19
+ */
20
+ const key = (config) => ({
21
+ _tag: "key",
22
+ fields: config.fields,
23
+ resolvable: config.resolvable,
24
+ });
25
+ exports.key = key;
26
+ /**
27
+ * Create a @shareable directive
28
+ * Marks a type or field as resolvable by multiple subgraphs
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * entity({
33
+ * name: "Product",
34
+ * schema: ProductSchema,
35
+ * keys: [key({ fields: "id" })],
36
+ * directives: [shareable()],
37
+ * })
38
+ * ```
39
+ */
40
+ const shareable = () => ({
41
+ _tag: "shareable",
42
+ });
43
+ exports.shareable = shareable;
44
+ /**
45
+ * Create an @inaccessible directive
46
+ * Omits the type/field from the public API while keeping it available for federation
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * objectType({
51
+ * name: "InternalMetadata",
52
+ * schema: MetadataSchema,
53
+ * directives: [inaccessible()],
54
+ * })
55
+ * ```
56
+ */
57
+ const inaccessible = () => ({
58
+ _tag: "inaccessible",
59
+ });
60
+ exports.inaccessible = inaccessible;
61
+ /**
62
+ * Create an @interfaceObject directive
63
+ * Indicates this object represents an interface from another subgraph
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * objectType({
68
+ * name: "Media",
69
+ * schema: MediaSchema,
70
+ * directives: [interfaceObject()],
71
+ * })
72
+ * ```
73
+ */
74
+ const interfaceObject = () => ({
75
+ _tag: "interfaceObject",
76
+ });
77
+ exports.interfaceObject = interfaceObject;
78
+ /**
79
+ * Create a @tag directive for metadata annotation
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * entity({
84
+ * name: "Product",
85
+ * schema: ProductSchema,
86
+ * keys: [key({ fields: "id" })],
87
+ * directives: [tag("public"), tag("catalog")],
88
+ * })
89
+ * ```
90
+ */
91
+ const tag = (name) => ({
92
+ _tag: "tag",
93
+ name,
94
+ });
95
+ exports.tag = tag;
96
+ // ============================================================================
97
+ // Field-Level Directive Factories
98
+ // ============================================================================
99
+ /**
100
+ * Create an @external directive
101
+ * Marks a field as defined in another subgraph
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * field("User", "externalId", {
106
+ * type: S.String,
107
+ * directives: [external()],
108
+ * resolve: (parent) => parent.externalId,
109
+ * })
110
+ * ```
111
+ */
112
+ const external = () => ({
113
+ _tag: "external",
114
+ });
115
+ exports.external = external;
116
+ /**
117
+ * Create a @requires directive
118
+ * Specifies fields that must be fetched from other subgraphs before this field can be resolved
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * field("Product", "shippingEstimate", {
123
+ * type: S.Int,
124
+ * directives: [requires({ fields: "weight dimensions { height width }" })],
125
+ * resolve: (product) => calculateShipping(product.weight, product.dimensions),
126
+ * })
127
+ * ```
128
+ */
129
+ const requires = (config) => ({
130
+ _tag: "requires",
131
+ fields: config.fields,
132
+ });
133
+ exports.requires = requires;
134
+ /**
135
+ * Create a @provides directive
136
+ * Router optimization hint - indicates this field provides additional fields on the returned type
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * field("Review", "author", {
141
+ * type: UserSchema,
142
+ * directives: [provides({ fields: "name email" })],
143
+ * resolve: (review) => UserService.findById(review.authorId),
144
+ * })
145
+ * ```
146
+ */
147
+ const provides = (config) => ({
148
+ _tag: "provides",
149
+ fields: config.fields,
150
+ });
151
+ exports.provides = provides;
152
+ /**
153
+ * Create an @override directive
154
+ * Transfers resolution responsibility from another subgraph
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * field("Product", "price", {
159
+ * type: S.Number,
160
+ * directives: [override({ from: "legacy-pricing" })],
161
+ * resolve: (product) => PricingService.getPrice(product.id),
162
+ * })
163
+ * ```
164
+ */
165
+ const override = (config) => ({
166
+ _tag: "override",
167
+ from: config.from,
168
+ label: config.label,
169
+ });
170
+ exports.override = override;
171
+ //# sourceMappingURL=directives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"directives.js","sourceRoot":"","sources":["../src/directives.ts"],"names":[],"mappings":";;;AAEA,+EAA+E;AAC/E,iCAAiC;AACjC,+EAA+E;AAE/E;;;;;;;;;;;;GAYG;AACI,MAAM,GAAG,GAAG,CAAC,MAAoB,EAAuB,EAAE,CAAC,CAAC;IACjE,IAAI,EAAE,KAAK;IACX,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,UAAU,EAAE,MAAM,CAAC,UAAU;CAC9B,CAAC,CAAA;AAJW,QAAA,GAAG,OAId;AAEF;;;;;;;;;;;;;GAaG;AACI,MAAM,SAAS,GAAG,GAAwB,EAAE,CAAC,CAAC;IACnD,IAAI,EAAE,WAAW;CAClB,CAAC,CAAA;AAFW,QAAA,SAAS,aAEpB;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,YAAY,GAAG,GAAwB,EAAE,CAAC,CAAC;IACtD,IAAI,EAAE,cAAc;CACrB,CAAC,CAAA;AAFW,QAAA,YAAY,gBAEvB;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,eAAe,GAAG,GAAwB,EAAE,CAAC,CAAC;IACzD,IAAI,EAAE,iBAAiB;CACxB,CAAC,CAAA;AAFW,QAAA,eAAe,mBAE1B;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,GAAG,GAAG,CAAC,IAAY,EAAuB,EAAE,CAAC,CAAC;IACzD,IAAI,EAAE,KAAK;IACX,IAAI;CACL,CAAC,CAAA;AAHW,QAAA,GAAG,OAGd;AAEF,+EAA+E;AAC/E,kCAAkC;AAClC,+EAA+E;AAE/E;;;;;;;;;;;;GAYG;AACI,MAAM,QAAQ,GAAG,GAAwB,EAAE,CAAC,CAAC;IAClD,IAAI,EAAE,UAAU;CACjB,CAAC,CAAA;AAFW,QAAA,QAAQ,YAEnB;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,QAAQ,GAAG,CAAC,MAA0B,EAAuB,EAAE,CAAC,CAAC;IAC5E,IAAI,EAAE,UAAU;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CAAC,CAAA;AAHW,QAAA,QAAQ,YAGnB;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,QAAQ,GAAG,CAAC,MAA0B,EAAuB,EAAE,CAAC,CAAC;IAC5E,IAAI,EAAE,UAAU;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM;CACtB,CAAC,CAAA;AAHW,QAAA,QAAQ,YAGnB;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,QAAQ,GAAG,CAAC,MAAwC,EAAuB,EAAE,CAAC,CAAC;IAC1F,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,MAAM,CAAC,IAAI;IACjB,KAAK,EAAE,MAAM,CAAC,KAAK;CACpB,CAAC,CAAA;AAJW,QAAA,QAAQ,YAInB"}
@@ -0,0 +1,31 @@
1
+ import { Runtime } from "effect";
2
+ import { GraphQLObjectType, GraphQLUnionType } from "@effect-gql/core";
3
+ import type { EntityRegistration, EntityRepresentation } from "./types";
4
+ /**
5
+ * Create the _Entity union type from registered entities
6
+ */
7
+ export declare function createEntityUnion(entities: Map<string, EntityRegistration<any, any>>, typeRegistry: Map<string, GraphQLObjectType>): GraphQLUnionType;
8
+ /**
9
+ * Create the _entities resolver
10
+ *
11
+ * This resolver receives an array of representations (objects with __typename and key fields)
12
+ * and returns the corresponding entities by calling each entity's resolveReference function.
13
+ *
14
+ * Uses Effect.all with unbounded concurrency to resolve all entities in parallel.
15
+ */
16
+ export declare function createEntitiesResolver<R>(entities: Map<string, EntityRegistration<any, R>>): (_parent: any, args: {
17
+ representations: readonly EntityRepresentation[];
18
+ }, context: {
19
+ runtime: Runtime.Runtime<R>;
20
+ }) => Promise<(any | null)[]>;
21
+ /**
22
+ * Create the _Service type for SDL introspection
23
+ */
24
+ export declare function createServiceType(): GraphQLObjectType;
25
+ /**
26
+ * Create the _service resolver
27
+ */
28
+ export declare function createServiceResolver(sdl: string): () => {
29
+ sdl: string;
30
+ };
31
+ //# sourceMappingURL=entities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../src/entities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAiB,MAAM,kBAAkB,CAAA;AACrF,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEvE;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EACnD,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAC3C,gBAAgB,CAelB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAEvF,SAAS,GAAG,EACZ,MAAM;IAAE,eAAe,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAAE,EAC1D,SAAS;IAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;CAAE,KACvC,OAAO,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CA0B3B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,CAWrD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM;;EAEhD"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createEntityUnion = createEntityUnion;
4
+ exports.createEntitiesResolver = createEntitiesResolver;
5
+ exports.createServiceType = createServiceType;
6
+ exports.createServiceResolver = createServiceResolver;
7
+ const effect_1 = require("effect");
8
+ const core_1 = require("@effect-gql/core");
9
+ /**
10
+ * Create the _Entity union type from registered entities
11
+ */
12
+ function createEntityUnion(entities, typeRegistry) {
13
+ const types = Array.from(entities.keys())
14
+ .map((name) => typeRegistry.get(name))
15
+ .filter(Boolean);
16
+ if (types.length === 0) {
17
+ throw new Error("At least one entity must be registered to create _Entity union");
18
+ }
19
+ return new core_1.GraphQLUnionType({
20
+ name: "_Entity",
21
+ description: "Union of all types that have @key directives",
22
+ types: () => types,
23
+ resolveType: (value) => value.__typename,
24
+ });
25
+ }
26
+ /**
27
+ * Create the _entities resolver
28
+ *
29
+ * This resolver receives an array of representations (objects with __typename and key fields)
30
+ * and returns the corresponding entities by calling each entity's resolveReference function.
31
+ *
32
+ * Uses Effect.all with unbounded concurrency to resolve all entities in parallel.
33
+ */
34
+ function createEntitiesResolver(entities) {
35
+ return async (_parent, args, context) => {
36
+ const effects = args.representations.map((representation) => {
37
+ const entityName = representation.__typename;
38
+ const entity = entities.get(entityName);
39
+ if (!entity) {
40
+ return effect_1.Effect.fail(new Error(`Unknown entity type: ${entityName}`));
41
+ }
42
+ return entity.resolveReference(representation).pipe(effect_1.Effect.map((result) => {
43
+ // Add __typename to the result for union type resolution
44
+ if (result !== null && typeof result === "object") {
45
+ return { ...result, __typename: entityName };
46
+ }
47
+ return result;
48
+ }),
49
+ // Catch individual entity resolution errors and return null
50
+ effect_1.Effect.catchAll((error) => effect_1.Effect.logError(`Failed to resolve entity ${entityName}`, error).pipe(effect_1.Effect.as(null))));
51
+ });
52
+ return effect_1.Runtime.runPromise(context.runtime)(effect_1.Effect.all(effects, { concurrency: "unbounded" }));
53
+ };
54
+ }
55
+ /**
56
+ * Create the _Service type for SDL introspection
57
+ */
58
+ function createServiceType() {
59
+ return new core_1.GraphQLObjectType({
60
+ name: "_Service",
61
+ description: "Provides SDL for the subgraph schema",
62
+ fields: {
63
+ sdl: {
64
+ type: core_1.GraphQLString,
65
+ description: "The SDL representing the subgraph schema",
66
+ },
67
+ },
68
+ });
69
+ }
70
+ /**
71
+ * Create the _service resolver
72
+ */
73
+ function createServiceResolver(sdl) {
74
+ return () => ({ sdl });
75
+ }
76
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../src/entities.ts"],"names":[],"mappings":";;AAOA,8CAkBC;AAUD,wDA+BC;AAKD,8CAWC;AAKD,sDAEC;AAzFD,mCAAwC;AACxC,2CAAqF;AAGrF;;GAEG;AACH,SAAgB,iBAAiB,CAC/B,QAAmD,EACnD,YAA4C;IAE5C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;SACtC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;SACtC,MAAM,CAAC,OAAO,CAAC,CAAA;IAElB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAA;IACnF,CAAC;IAED,OAAO,IAAI,uBAAgB,CAAC;QAC1B,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,8CAA8C;QAC3D,KAAK,EAAE,GAAG,EAAE,CAAC,KAAK;QAClB,WAAW,EAAE,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU;KAC9C,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,sBAAsB,CAAI,QAAiD;IACzF,OAAO,KAAK,EACV,OAAY,EACZ,IAA0D,EAC1D,OAAwC,EACf,EAAE;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE;YAC1D,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,CAAA;YAC5C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;YAEvC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,eAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,wBAAwB,UAAU,EAAE,CAAC,CAAC,CAAA;YACrE,CAAC;YAED,OAAO,MAAM,CAAC,gBAAgB,CAAC,cAAqB,CAAC,CAAC,IAAI,CACxD,eAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;gBACpB,yDAAyD;gBACzD,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAClD,OAAO,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAA;gBAC9C,CAAC;gBACD,OAAO,MAAM,CAAA;YACf,CAAC,CAAC;YACF,4DAA4D;YAC5D,eAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,eAAM,CAAC,QAAQ,CAAC,4BAA4B,UAAU,EAAE,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,eAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CACvF,CACF,CAAA;QACH,CAAC,CAAC,CAAA;QAEF,OAAO,gBAAO,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,eAAM,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;IAC/F,CAAC,CAAA;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,OAAO,IAAI,wBAAiB,CAAC;QAC3B,IAAI,EAAE,UAAU;QAChB,WAAW,EAAE,sCAAsC;QACnD,MAAM,EAAE;YACN,GAAG,EAAE;gBACH,IAAI,EAAE,oBAAa;gBACnB,WAAW,EAAE,0CAA0C;aACxD;SACF;KACF,CAAC,CAAA;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,qBAAqB,CAAC,GAAW;IAC/C,OAAO,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;AACxB,CAAC"}
@@ -0,0 +1,182 @@
1
+ import { Effect, Pipeable } from "effect";
2
+ import * as S from "effect/Schema";
3
+ import { GraphQLSchemaBuilder, GraphQLSchema, type DirectiveApplication } from "@effect-gql/core";
4
+ import type { EntityRegistration, FederatedSchemaConfig, FederatedSchemaResult } from "./types";
5
+ /**
6
+ * Federation-aware schema builder that extends the core GraphQLSchemaBuilder
7
+ * with Apollo Federation 2.x support.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const schema = FederatedSchemaBuilder.empty
12
+ * .pipe(
13
+ * entity({
14
+ * name: "User",
15
+ * schema: UserSchema,
16
+ * keys: [key({ fields: "id" })],
17
+ * resolveReference: (ref) => UserService.findById(ref.id),
18
+ * }),
19
+ * query("me", {
20
+ * type: UserSchema,
21
+ * resolve: () => UserService.getCurrentUser(),
22
+ * }),
23
+ * )
24
+ * .buildFederatedSchema()
25
+ * ```
26
+ */
27
+ export declare class FederatedSchemaBuilder<R = never> implements Pipeable.Pipeable {
28
+ private readonly state;
29
+ private constructor();
30
+ /**
31
+ * Pipeable interface implementation
32
+ */
33
+ pipe<A>(this: A): A;
34
+ pipe<A, B>(this: A, ab: (a: A) => B): B;
35
+ pipe<A, B, C>(this: A, ab: (a: A) => B, bc: (b: B) => C): C;
36
+ pipe<A, B, C, D>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D;
37
+ pipe<A, B, C, D, E>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E): E;
38
+ pipe<A, B, C, D, E, F>(this: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D, de: (d: D) => E, ef: (e: E) => F): F;
39
+ /**
40
+ * Create an empty federated schema builder
41
+ */
42
+ static empty: FederatedSchemaBuilder<never>;
43
+ /**
44
+ * Create a builder with custom configuration
45
+ */
46
+ static create(config?: FederatedSchemaConfig): FederatedSchemaBuilder<never>;
47
+ /**
48
+ * Create a new builder with updated state
49
+ */
50
+ private with;
51
+ /**
52
+ * Get the underlying core builder for advanced usage
53
+ */
54
+ get coreBuilder(): GraphQLSchemaBuilder<R>;
55
+ /**
56
+ * Register an entity type with @key directive(s) and reference resolver.
57
+ *
58
+ * Entities are the core building block of Apollo Federation. They represent
59
+ * types that can be resolved across subgraph boundaries using their key fields.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * builder.entity({
64
+ * name: "User",
65
+ * schema: UserSchema,
66
+ * keys: [key({ fields: "id" })],
67
+ * resolveReference: (ref) => UserService.findById(ref.id),
68
+ * })
69
+ * ```
70
+ */
71
+ entity<A, R2>(config: EntityRegistration<A, R2>): FederatedSchemaBuilder<R | R2>;
72
+ /**
73
+ * Add a query field
74
+ */
75
+ query<A, E, R2, Args = void>(name: string, config: {
76
+ type: S.Schema<A, any, any>;
77
+ args?: S.Schema<Args, any, any>;
78
+ description?: string;
79
+ directives?: readonly DirectiveApplication[];
80
+ resolve: (args: Args) => Effect.Effect<A, E, R2>;
81
+ }): FederatedSchemaBuilder<R | R2>;
82
+ /**
83
+ * Add a mutation field
84
+ */
85
+ mutation<A, E, R2, Args = void>(name: string, config: {
86
+ type: S.Schema<A, any, any>;
87
+ args?: S.Schema<Args, any, any>;
88
+ description?: string;
89
+ directives?: readonly DirectiveApplication[];
90
+ resolve: (args: Args) => Effect.Effect<A, E, R2>;
91
+ }): FederatedSchemaBuilder<R | R2>;
92
+ /**
93
+ * Add a subscription field
94
+ */
95
+ subscription<A, E, R2, Args = void>(name: string, config: {
96
+ type: S.Schema<A, any, any>;
97
+ args?: S.Schema<Args, any, any>;
98
+ description?: string;
99
+ directives?: readonly DirectiveApplication[];
100
+ subscribe: (args: Args) => Effect.Effect<import("effect").Stream.Stream<A, E, R2>, E, R2>;
101
+ resolve?: (value: A, args: Args) => Effect.Effect<A, E, R2>;
102
+ }): FederatedSchemaBuilder<R | R2>;
103
+ /**
104
+ * Register an object type (non-entity)
105
+ */
106
+ objectType<A, R2 = never>(config: {
107
+ name?: string;
108
+ schema: S.Schema<A, any, any>;
109
+ implements?: readonly string[];
110
+ directives?: readonly DirectiveApplication[];
111
+ }): FederatedSchemaBuilder<R | R2>;
112
+ /**
113
+ * Register an interface type
114
+ */
115
+ interfaceType(config: {
116
+ name?: string;
117
+ schema: S.Schema<any, any, any>;
118
+ resolveType?: (value: any) => string;
119
+ directives?: readonly DirectiveApplication[];
120
+ }): FederatedSchemaBuilder<R>;
121
+ /**
122
+ * Register an enum type
123
+ */
124
+ enumType(config: {
125
+ name: string;
126
+ values: readonly string[];
127
+ description?: string;
128
+ directives?: readonly DirectiveApplication[];
129
+ }): FederatedSchemaBuilder<R>;
130
+ /**
131
+ * Register a union type
132
+ */
133
+ unionType(config: {
134
+ name: string;
135
+ types: readonly string[];
136
+ resolveType?: (value: any) => string;
137
+ directives?: readonly DirectiveApplication[];
138
+ }): FederatedSchemaBuilder<R>;
139
+ /**
140
+ * Register an input type
141
+ */
142
+ inputType(config: {
143
+ name?: string;
144
+ schema: S.Schema<any, any, any>;
145
+ description?: string;
146
+ directives?: readonly DirectiveApplication[];
147
+ }): FederatedSchemaBuilder<R>;
148
+ /**
149
+ * Add a computed/relational field to an object type
150
+ */
151
+ field<Parent, A, E, R2, Args = void>(typeName: string, fieldName: string, config: {
152
+ type: S.Schema<A, any, any>;
153
+ args?: S.Schema<Args, any, any>;
154
+ description?: string;
155
+ directives?: readonly DirectiveApplication[];
156
+ resolve: (parent: Parent, args: Args) => Effect.Effect<A, E, R2>;
157
+ }): FederatedSchemaBuilder<R | R2>;
158
+ /**
159
+ * Build the federated GraphQL schema with _entities and _service queries.
160
+ *
161
+ * Returns both the executable schema and the Federation-compliant SDL.
162
+ */
163
+ buildFederatedSchema(): FederatedSchemaResult;
164
+ /**
165
+ * Check if the core builder has any query fields registered
166
+ */
167
+ private hasQueryFields;
168
+ /**
169
+ * Build a standard (non-federated) schema.
170
+ * Useful for testing or running without a gateway.
171
+ */
172
+ buildSchema(): GraphQLSchema;
173
+ /**
174
+ * Generate Federation-compliant SDL with directive annotations.
175
+ */
176
+ private generateFederatedSDL;
177
+ /**
178
+ * Annotate SDL types with their federation directives from extensions.
179
+ */
180
+ private annotateSDLWithDirectives;
181
+ }
182
+ //# sourceMappingURL=federated-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federated-builder.d.ts","sourceRoot":"","sources":["../src/federated-builder.ts"],"names":[],"mappings":"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"}