@superblocksteam/sdk-api 2.0.118-next.0 → 2.0.118-next.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/dist/integrations/base/graphql-integration-client.d.ts +2 -6
- package/dist/integrations/base/graphql-integration-client.d.ts.map +1 -1
- package/dist/integrations/base/graphql-integration-client.js +5 -18
- package/dist/integrations/base/graphql-integration-client.js.map +1 -1
- package/dist/integrations/documentation-resolver.test.js +1 -143
- package/dist/integrations/documentation-resolver.test.js.map +1 -1
- package/dist/integrations/documentation.d.ts +0 -1
- package/dist/integrations/documentation.d.ts.map +1 -1
- package/dist/integrations/documentation.js +8 -31
- package/dist/integrations/documentation.js.map +1 -1
- package/dist/integrations/graphql/types.d.ts +2 -21
- package/dist/integrations/graphql/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/integrations/base/graphql-integration-client.ts +3 -24
- package/src/integrations/documentation-resolver.test.ts +1 -159
- package/src/integrations/documentation.ts +11 -63
- package/src/integrations/graphql/docs.manifest.json +1 -6
- package/src/integrations/graphql/types.ts +0 -21
- package/dist/integrations/graphql/client.test.d.ts +0 -15
- package/dist/integrations/graphql/client.test.d.ts.map +0 -1
- package/dist/integrations/graphql/client.test.js +0 -148
- package/dist/integrations/graphql/client.test.js.map +0 -1
- package/src/integrations/graphql/client.test.ts +0 -220
- package/src/integrations/graphql/overlays/dynamic-headers.md +0 -34
|
@@ -5,11 +5,8 @@
|
|
|
5
5
|
* Handles proto message construction and response validation.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { PartialMessage } from "@bufbuild/protobuf";
|
|
9
8
|
import { z } from "zod";
|
|
10
9
|
|
|
11
|
-
import type { Property } from "@superblocksteam/types/dist/src/common/v1/plugin_pb";
|
|
12
|
-
|
|
13
10
|
import { RestApiValidationError } from "../../errors.js";
|
|
14
11
|
import type { QueryExecutor, TraceMetadata } from "../registry.js";
|
|
15
12
|
import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
|
|
@@ -22,8 +19,6 @@ import type { IntegrationConfig, IntegrationClientImpl } from "../types.js";
|
|
|
22
19
|
* - Executing queries and mutations through the orchestrator
|
|
23
20
|
* - Required Zod schema validation on full GraphQL response
|
|
24
21
|
* - Variables serialization for parameterized queries
|
|
25
|
-
* - Optional per-request HTTP headers (in addition to any headers configured
|
|
26
|
-
* on the integration)
|
|
27
22
|
*/
|
|
28
23
|
export abstract class GraphQLIntegrationClient implements IntegrationClientImpl {
|
|
29
24
|
readonly name: string;
|
|
@@ -45,7 +40,6 @@ export abstract class GraphQLIntegrationClient implements IntegrationClientImpl
|
|
|
45
40
|
* @param schema - Zod schema for full response validation (REQUIRED)
|
|
46
41
|
* @param variables - Optional variables for the query
|
|
47
42
|
* @param metadata - Optional trace metadata for observability
|
|
48
|
-
* @param headers - Optional HTTP headers to send with the request
|
|
49
43
|
* @returns Validated query result
|
|
50
44
|
*/
|
|
51
45
|
async query<TResponse>(
|
|
@@ -53,9 +47,8 @@ export abstract class GraphQLIntegrationClient implements IntegrationClientImpl
|
|
|
53
47
|
schema: { response: z.ZodSchema<TResponse> },
|
|
54
48
|
variables?: Record<string, unknown>,
|
|
55
49
|
metadata?: TraceMetadata,
|
|
56
|
-
headers?: Record<string, string>,
|
|
57
50
|
): Promise<TResponse> {
|
|
58
|
-
return this.executeGraphQL(query, schema, variables, metadata
|
|
51
|
+
return this.executeGraphQL(query, schema, variables, metadata);
|
|
59
52
|
}
|
|
60
53
|
|
|
61
54
|
/**
|
|
@@ -65,7 +58,6 @@ export abstract class GraphQLIntegrationClient implements IntegrationClientImpl
|
|
|
65
58
|
* @param schema - Zod schema for full response validation (REQUIRED)
|
|
66
59
|
* @param variables - Optional variables for the mutation
|
|
67
60
|
* @param metadata - Optional trace metadata for observability
|
|
68
|
-
* @param headers - Optional HTTP headers to send with the request
|
|
69
61
|
* @returns Validated mutation result
|
|
70
62
|
*/
|
|
71
63
|
async mutation<TResponse>(
|
|
@@ -73,9 +65,8 @@ export abstract class GraphQLIntegrationClient implements IntegrationClientImpl
|
|
|
73
65
|
schema: { response: z.ZodSchema<TResponse> },
|
|
74
66
|
variables?: Record<string, unknown>,
|
|
75
67
|
metadata?: TraceMetadata,
|
|
76
|
-
headers?: Record<string, string>,
|
|
77
68
|
): Promise<TResponse> {
|
|
78
|
-
return this.executeGraphQL(mutation, schema, variables, metadata
|
|
69
|
+
return this.executeGraphQL(mutation, schema, variables, metadata);
|
|
79
70
|
}
|
|
80
71
|
|
|
81
72
|
/**
|
|
@@ -89,17 +80,9 @@ export abstract class GraphQLIntegrationClient implements IntegrationClientImpl
|
|
|
89
80
|
schema: { response: z.ZodSchema<TResponse> },
|
|
90
81
|
variables?: Record<string, unknown>,
|
|
91
82
|
metadata?: TraceMetadata,
|
|
92
|
-
headers?: Record<string, string>,
|
|
93
83
|
): Promise<TResponse> {
|
|
94
|
-
const headerProps: PartialMessage<Property>[] = [];
|
|
95
|
-
if (headers) {
|
|
96
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
97
|
-
headerProps.push({ key, value });
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
84
|
// Build graphql.v1.Plugin proto message
|
|
102
|
-
const request
|
|
85
|
+
const request = {
|
|
103
86
|
body: queryString,
|
|
104
87
|
custom: variables
|
|
105
88
|
? {
|
|
@@ -113,10 +96,6 @@ export abstract class GraphQLIntegrationClient implements IntegrationClientImpl
|
|
|
113
96
|
failOnGraphqlErrors: true,
|
|
114
97
|
};
|
|
115
98
|
|
|
116
|
-
if (headerProps.length > 0) {
|
|
117
|
-
request.headers = headerProps;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
99
|
// Execute query through orchestrator
|
|
121
100
|
const response = await this.executeQuery(request, undefined, metadata);
|
|
122
101
|
|
|
@@ -659,27 +659,7 @@ describe("resolveIntegrationDocumentation", () => {
|
|
|
659
659
|
}
|
|
660
660
|
});
|
|
661
661
|
|
|
662
|
-
it("throws when overlay entry has
|
|
663
|
-
const integrationsDirectory = createPluginDocsFixture("dropbox", {
|
|
664
|
-
"README.md": "base",
|
|
665
|
-
"docs.manifest.json": JSON.stringify({
|
|
666
|
-
overlays: [{ file: "overlays/01.md" }],
|
|
667
|
-
}),
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
try {
|
|
671
|
-
await expect(
|
|
672
|
-
resolveIntegrationDocumentation("dropbox", {
|
|
673
|
-
pluginVersion: "0.4.0",
|
|
674
|
-
integrationsDirectory,
|
|
675
|
-
}),
|
|
676
|
-
).rejects.toThrowError(/Invalid overlay entry/);
|
|
677
|
-
} finally {
|
|
678
|
-
rmSync(integrationsDirectory, { recursive: true, force: true });
|
|
679
|
-
}
|
|
680
|
-
});
|
|
681
|
-
|
|
682
|
-
it("throws when overlay entry has empty versionRange and no sdkVersionRange", async () => {
|
|
662
|
+
it("throws when overlay entry has empty versionRange", async () => {
|
|
683
663
|
const integrationsDirectory = createPluginDocsFixture("dropbox", {
|
|
684
664
|
"README.md": "base",
|
|
685
665
|
"docs.manifest.json": JSON.stringify({
|
|
@@ -700,144 +680,6 @@ describe("resolveIntegrationDocumentation", () => {
|
|
|
700
680
|
});
|
|
701
681
|
});
|
|
702
682
|
|
|
703
|
-
describe("sdkVersionRange", () => {
|
|
704
|
-
it("applies overlay when sdkVersion matches sdkVersionRange", async () => {
|
|
705
|
-
const integrationsDirectory = createPluginDocsFixture("graphql", {
|
|
706
|
-
"README.md": "base-graphql-docs",
|
|
707
|
-
"docs.manifest.json": JSON.stringify({
|
|
708
|
-
overlays: [
|
|
709
|
-
{ file: "overlays/headers.md", sdkVersionRange: ">=0.0.2" },
|
|
710
|
-
],
|
|
711
|
-
}),
|
|
712
|
-
"overlays/headers.md": "dynamic-headers-docs",
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
try {
|
|
716
|
-
const docs = await resolveIntegrationDocumentation("graphql", {
|
|
717
|
-
sdkVersion: "0.0.2",
|
|
718
|
-
integrationsDirectory,
|
|
719
|
-
});
|
|
720
|
-
expect(docs).toBe("base-graphql-docs\n\ndynamic-headers-docs");
|
|
721
|
-
} finally {
|
|
722
|
-
rmSync(integrationsDirectory, { recursive: true, force: true });
|
|
723
|
-
}
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
it("skips overlay when sdkVersion does not match sdkVersionRange", async () => {
|
|
727
|
-
const integrationsDirectory = createPluginDocsFixture("graphql", {
|
|
728
|
-
"README.md": "base-graphql-docs",
|
|
729
|
-
"docs.manifest.json": JSON.stringify({
|
|
730
|
-
overlays: [
|
|
731
|
-
{ file: "overlays/headers.md", sdkVersionRange: ">=0.0.2" },
|
|
732
|
-
],
|
|
733
|
-
}),
|
|
734
|
-
"overlays/headers.md": "dynamic-headers-docs",
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
try {
|
|
738
|
-
const docs = await resolveIntegrationDocumentation("graphql", {
|
|
739
|
-
sdkVersion: "0.0.1",
|
|
740
|
-
integrationsDirectory,
|
|
741
|
-
});
|
|
742
|
-
expect(docs).toBe("base-graphql-docs");
|
|
743
|
-
} finally {
|
|
744
|
-
rmSync(integrationsDirectory, { recursive: true, force: true });
|
|
745
|
-
}
|
|
746
|
-
});
|
|
747
|
-
|
|
748
|
-
it("skips overlay when sdkVersion is not provided", async () => {
|
|
749
|
-
const integrationsDirectory = createPluginDocsFixture("graphql", {
|
|
750
|
-
"README.md": "base-graphql-docs",
|
|
751
|
-
"docs.manifest.json": JSON.stringify({
|
|
752
|
-
overlays: [
|
|
753
|
-
{ file: "overlays/headers.md", sdkVersionRange: ">=0.0.2" },
|
|
754
|
-
],
|
|
755
|
-
}),
|
|
756
|
-
"overlays/headers.md": "dynamic-headers-docs",
|
|
757
|
-
});
|
|
758
|
-
|
|
759
|
-
try {
|
|
760
|
-
const docs = await resolveIntegrationDocumentation("graphql", {
|
|
761
|
-
pluginVersion: "0.0.10",
|
|
762
|
-
integrationsDirectory,
|
|
763
|
-
});
|
|
764
|
-
expect(docs).toBe("base-graphql-docs");
|
|
765
|
-
} finally {
|
|
766
|
-
rmSync(integrationsDirectory, { recursive: true, force: true });
|
|
767
|
-
}
|
|
768
|
-
});
|
|
769
|
-
|
|
770
|
-
it("requires both versionRange and sdkVersionRange to match when both are specified", async () => {
|
|
771
|
-
const integrationsDirectory = createPluginDocsFixture("graphql", {
|
|
772
|
-
"README.md": "base",
|
|
773
|
-
"docs.manifest.json": JSON.stringify({
|
|
774
|
-
overlays: [
|
|
775
|
-
{
|
|
776
|
-
file: "overlays/both.md",
|
|
777
|
-
versionRange: ">=0.0.10",
|
|
778
|
-
sdkVersionRange: ">=0.0.2",
|
|
779
|
-
},
|
|
780
|
-
],
|
|
781
|
-
}),
|
|
782
|
-
"overlays/both.md": "both-match-overlay",
|
|
783
|
-
});
|
|
784
|
-
|
|
785
|
-
try {
|
|
786
|
-
// Both match
|
|
787
|
-
expect(
|
|
788
|
-
await resolveIntegrationDocumentation("graphql", {
|
|
789
|
-
pluginVersion: "0.0.10",
|
|
790
|
-
sdkVersion: "0.0.2",
|
|
791
|
-
integrationsDirectory,
|
|
792
|
-
}),
|
|
793
|
-
).toBe("base\n\nboth-match-overlay");
|
|
794
|
-
|
|
795
|
-
// Only plugin matches
|
|
796
|
-
expect(
|
|
797
|
-
await resolveIntegrationDocumentation("graphql", {
|
|
798
|
-
pluginVersion: "0.0.10",
|
|
799
|
-
sdkVersion: "0.0.1",
|
|
800
|
-
integrationsDirectory,
|
|
801
|
-
}),
|
|
802
|
-
).toBe("base");
|
|
803
|
-
|
|
804
|
-
// Only sdk matches
|
|
805
|
-
expect(
|
|
806
|
-
await resolveIntegrationDocumentation("graphql", {
|
|
807
|
-
pluginVersion: "0.0.9",
|
|
808
|
-
sdkVersion: "0.0.2",
|
|
809
|
-
integrationsDirectory,
|
|
810
|
-
}),
|
|
811
|
-
).toBe("base");
|
|
812
|
-
} finally {
|
|
813
|
-
rmSync(integrationsDirectory, { recursive: true, force: true });
|
|
814
|
-
}
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
it("allows overlay with only sdkVersionRange (no versionRange)", async () => {
|
|
818
|
-
const integrationsDirectory = createPluginDocsFixture("graphql", {
|
|
819
|
-
"README.md": "base",
|
|
820
|
-
"docs.manifest.json": JSON.stringify({
|
|
821
|
-
overlays: [
|
|
822
|
-
{ file: "overlays/sdk-only.md", sdkVersionRange: ">=0.0.2" },
|
|
823
|
-
],
|
|
824
|
-
}),
|
|
825
|
-
"overlays/sdk-only.md": "sdk-gated-overlay",
|
|
826
|
-
});
|
|
827
|
-
|
|
828
|
-
try {
|
|
829
|
-
// No pluginVersion needed — only sdkVersion matters
|
|
830
|
-
const docs = await resolveIntegrationDocumentation("graphql", {
|
|
831
|
-
sdkVersion: "0.0.3",
|
|
832
|
-
integrationsDirectory,
|
|
833
|
-
});
|
|
834
|
-
expect(docs).toBe("base\n\nsdk-gated-overlay");
|
|
835
|
-
} finally {
|
|
836
|
-
rmSync(integrationsDirectory, { recursive: true, force: true });
|
|
837
|
-
}
|
|
838
|
-
});
|
|
839
|
-
});
|
|
840
|
-
|
|
841
683
|
it("blocks overlay paths outside the plugin directory", async () => {
|
|
842
684
|
const integrationsDirectory = createPluginDocsFixture("dropbox", {
|
|
843
685
|
"README.md": "base",
|
|
@@ -11,13 +11,7 @@ const DOC_DIRECTORY_ALIASES = {
|
|
|
11
11
|
|
|
12
12
|
interface DocumentationOverlay {
|
|
13
13
|
file: string;
|
|
14
|
-
versionRange
|
|
15
|
-
/** When set, checks against the sdk-api version ("javascriptsdkapi") running
|
|
16
|
-
* in the orchestrator instead of the plugin-specific version. Use this to
|
|
17
|
-
* gate overlays on sdk-api features that ship independently of plugin
|
|
18
|
-
* version bumps. Both versionRange and sdkVersionRange can be specified
|
|
19
|
-
* together — the overlay is applied only when all specified ranges match. */
|
|
20
|
-
sdkVersionRange?: string;
|
|
14
|
+
versionRange: string;
|
|
21
15
|
}
|
|
22
16
|
|
|
23
17
|
interface DocumentationManifest {
|
|
@@ -38,7 +32,6 @@ type OverlayOperation =
|
|
|
38
32
|
|
|
39
33
|
export interface ResolveIntegrationDocumentationOptions {
|
|
40
34
|
pluginVersion?: SemVer;
|
|
41
|
-
sdkVersion?: SemVer;
|
|
42
35
|
integrationsDirectory?: string;
|
|
43
36
|
}
|
|
44
37
|
|
|
@@ -89,17 +82,16 @@ async function parseDocumentationManifest(
|
|
|
89
82
|
typeof overlay !== "object" ||
|
|
90
83
|
overlay === null ||
|
|
91
84
|
!("file" in overlay) ||
|
|
92
|
-
|
|
85
|
+
!("versionRange" in overlay)
|
|
93
86
|
) {
|
|
94
87
|
throw new Error(
|
|
95
88
|
`Invalid overlay entry at index ${index} in ${manifestPath}.`,
|
|
96
89
|
);
|
|
97
90
|
}
|
|
98
91
|
|
|
99
|
-
const { file, versionRange
|
|
92
|
+
const { file, versionRange } = overlay as {
|
|
100
93
|
file: unknown;
|
|
101
94
|
versionRange: unknown;
|
|
102
|
-
sdkVersionRange: unknown;
|
|
103
95
|
};
|
|
104
96
|
|
|
105
97
|
if (typeof file !== "string" || file.trim().length === 0) {
|
|
@@ -107,35 +99,18 @@ async function parseDocumentationManifest(
|
|
|
107
99
|
`Invalid "file" for overlay index ${index} in ${manifestPath}.`,
|
|
108
100
|
);
|
|
109
101
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
typeof sdkVersionRange === "string" &&
|
|
115
|
-
sdkVersionRange.trim().length > 0;
|
|
116
|
-
|
|
117
|
-
if ("versionRange" in overlay && !hasVersionRange) {
|
|
102
|
+
if (
|
|
103
|
+
typeof versionRange !== "string" ||
|
|
104
|
+
versionRange.trim().length === 0
|
|
105
|
+
) {
|
|
118
106
|
throw new Error(
|
|
119
107
|
`Invalid "versionRange" for overlay index ${index} in ${manifestPath}.`,
|
|
120
108
|
);
|
|
121
109
|
}
|
|
122
|
-
if ("sdkVersionRange" in overlay && !hasSdkVersionRange) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
`Invalid "sdkVersionRange" for overlay index ${index} in ${manifestPath}.`,
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
if (!hasVersionRange && !hasSdkVersionRange) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
`Overlay at index ${index} in ${manifestPath} must specify at least one of "versionRange" or "sdkVersionRange".`,
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
110
|
|
|
133
111
|
return {
|
|
134
112
|
file,
|
|
135
|
-
|
|
136
|
-
...(hasSdkVersionRange
|
|
137
|
-
? { sdkVersionRange: sdkVersionRange as string }
|
|
138
|
-
: {}),
|
|
113
|
+
versionRange,
|
|
139
114
|
};
|
|
140
115
|
},
|
|
141
116
|
);
|
|
@@ -405,38 +380,11 @@ function ensureOverlayPathIsWithinPluginDir(
|
|
|
405
380
|
}
|
|
406
381
|
}
|
|
407
382
|
|
|
408
|
-
function overlayMatchesVersions(
|
|
409
|
-
overlay: DocumentationOverlay,
|
|
410
|
-
pluginVersion: SemVer | undefined,
|
|
411
|
-
sdkVersion: SemVer | undefined,
|
|
412
|
-
): boolean {
|
|
413
|
-
if (
|
|
414
|
-
overlay.versionRange &&
|
|
415
|
-
(!pluginVersion ||
|
|
416
|
-
!versionMatchesRange(pluginVersion, overlay.versionRange))
|
|
417
|
-
) {
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
if (
|
|
422
|
-
overlay.sdkVersionRange &&
|
|
423
|
-
(!sdkVersion || !versionMatchesRange(sdkVersion, overlay.sdkVersionRange))
|
|
424
|
-
) {
|
|
425
|
-
return false;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
return true;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
383
|
export async function resolveIntegrationDocumentation(
|
|
432
384
|
pluginId: string,
|
|
433
385
|
options: ResolveIntegrationDocumentationOptions = {},
|
|
434
386
|
): Promise<string> {
|
|
435
|
-
const {
|
|
436
|
-
pluginVersion,
|
|
437
|
-
sdkVersion,
|
|
438
|
-
integrationsDirectory = INTEGRATIONS_DIR,
|
|
439
|
-
} = options;
|
|
387
|
+
const { pluginVersion, integrationsDirectory = INTEGRATIONS_DIR } = options;
|
|
440
388
|
|
|
441
389
|
const pluginDirectory = resolve(
|
|
442
390
|
integrationsDirectory,
|
|
@@ -449,13 +397,13 @@ export async function resolveIntegrationDocumentation(
|
|
|
449
397
|
const baseDocumentationPath = resolve(pluginDirectory, baseFileName);
|
|
450
398
|
const baseDocumentation = await readFile(baseDocumentationPath, "utf8");
|
|
451
399
|
|
|
452
|
-
if (!manifest) {
|
|
400
|
+
if (!manifest || !pluginVersion) {
|
|
453
401
|
return baseDocumentation;
|
|
454
402
|
}
|
|
455
403
|
|
|
456
404
|
let resolvedDocumentation = baseDocumentation;
|
|
457
405
|
for (const overlay of manifest.overlays) {
|
|
458
|
-
if (!
|
|
406
|
+
if (!versionMatchesRange(pluginVersion, overlay.versionRange)) {
|
|
459
407
|
continue;
|
|
460
408
|
}
|
|
461
409
|
|
|
@@ -62,17 +62,6 @@ import type { TraceMetadata } from "../registry.js";
|
|
|
62
62
|
* { response: MutationResponseSchema },
|
|
63
63
|
* { name: 'John Doe' }
|
|
64
64
|
* );
|
|
65
|
-
*
|
|
66
|
-
* // Send per-request headers (e.g. a dynamic Authorization token).
|
|
67
|
-
* // Static headers and auth configured on the integration apply automatically;
|
|
68
|
-
* // use this parameter only for values that vary per request.
|
|
69
|
-
* await graphql.query(
|
|
70
|
-
* `query { me { id } }`,
|
|
71
|
-
* { response: z.object({ data: z.object({ me: z.object({ id: z.string() }) }) }) },
|
|
72
|
-
* undefined,
|
|
73
|
-
* undefined,
|
|
74
|
-
* { Authorization: `Bearer ${token}` },
|
|
75
|
-
* );
|
|
76
65
|
* ```
|
|
77
66
|
*/
|
|
78
67
|
export interface GraphQLClient extends BaseIntegrationClient {
|
|
@@ -85,10 +74,6 @@ export interface GraphQLClient extends BaseIntegrationClient {
|
|
|
85
74
|
* `metadata` accept plain objects, pass `undefined` for variables when you only need metadata:
|
|
86
75
|
* `query(q, schema, undefined, { label: "..." })`
|
|
87
76
|
* @param metadata - Optional trace metadata for observability
|
|
88
|
-
* @param headers - Optional HTTP headers to include on this request. Static
|
|
89
|
-
* headers and auth configured on the integration apply automatically; use
|
|
90
|
-
* this parameter only for values that vary per request (e.g. a bearer token
|
|
91
|
-
* derived from the API's input).
|
|
92
77
|
* @returns Validated query result
|
|
93
78
|
*
|
|
94
79
|
* @example
|
|
@@ -110,7 +95,6 @@ export interface GraphQLClient extends BaseIntegrationClient {
|
|
|
110
95
|
schema: { response: z.ZodSchema<TResponse> },
|
|
111
96
|
variables?: Record<string, unknown>,
|
|
112
97
|
metadata?: TraceMetadata,
|
|
113
|
-
headers?: Record<string, string>,
|
|
114
98
|
): Promise<TResponse>;
|
|
115
99
|
|
|
116
100
|
/**
|
|
@@ -122,10 +106,6 @@ export interface GraphQLClient extends BaseIntegrationClient {
|
|
|
122
106
|
* `metadata` accept plain objects, pass `undefined` for variables when you only need metadata:
|
|
123
107
|
* `mutation(m, schema, undefined, { label: "..." })`
|
|
124
108
|
* @param metadata - Optional trace metadata for observability
|
|
125
|
-
* @param headers - Optional HTTP headers to include on this request. Static
|
|
126
|
-
* headers and auth configured on the integration apply automatically; use
|
|
127
|
-
* this parameter only for values that vary per request (e.g. a bearer token
|
|
128
|
-
* derived from the API's input).
|
|
129
109
|
* @returns Validated mutation result
|
|
130
110
|
*
|
|
131
111
|
* @example
|
|
@@ -148,6 +128,5 @@ export interface GraphQLClient extends BaseIntegrationClient {
|
|
|
148
128
|
schema: { response: z.ZodSchema<TResponse> },
|
|
149
129
|
variables?: Record<string, unknown>,
|
|
150
130
|
metadata?: TraceMetadata,
|
|
151
|
-
headers?: Record<string, string>,
|
|
152
131
|
): Promise<TResponse>;
|
|
153
132
|
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for GraphQLClientImpl.
|
|
3
|
-
*
|
|
4
|
-
* Validates:
|
|
5
|
-
* - The proto request built by query()/mutation() matches the
|
|
6
|
-
* graphql.v1.Plugin shape expected by the orchestrator.
|
|
7
|
-
* - Optional per-request headers are forwarded as the proto's repeated
|
|
8
|
-
* `headers` field (key/value Property entries) so dynamic values like
|
|
9
|
-
* Authorization tokens can be sent from API code.
|
|
10
|
-
* - Variables are serialized into the proto `custom.variables` Property.
|
|
11
|
-
* - Trace metadata is passed through to the executeQuery callback.
|
|
12
|
-
* - Response Zod validation throws RestApiValidationError on mismatch.
|
|
13
|
-
*/
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=client.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/graphql/client.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for GraphQLClientImpl.
|
|
3
|
-
*
|
|
4
|
-
* Validates:
|
|
5
|
-
* - The proto request built by query()/mutation() matches the
|
|
6
|
-
* graphql.v1.Plugin shape expected by the orchestrator.
|
|
7
|
-
* - Optional per-request headers are forwarded as the proto's repeated
|
|
8
|
-
* `headers` field (key/value Property entries) so dynamic values like
|
|
9
|
-
* Authorization tokens can be sent from API code.
|
|
10
|
-
* - Variables are serialized into the proto `custom.variables` Property.
|
|
11
|
-
* - Trace metadata is passed through to the executeQuery callback.
|
|
12
|
-
* - Response Zod validation throws RestApiValidationError on mismatch.
|
|
13
|
-
*/
|
|
14
|
-
import { describe, it, expect, vi } from "vitest";
|
|
15
|
-
import { z } from "zod";
|
|
16
|
-
import { RestApiValidationError } from "../../errors.js";
|
|
17
|
-
import { GraphQLClientImpl } from "./client.js";
|
|
18
|
-
const TEST_CONFIG = {
|
|
19
|
-
id: "graphql-test-id",
|
|
20
|
-
name: "Test GraphQL",
|
|
21
|
-
pluginId: "graphqlintegration",
|
|
22
|
-
configuration: {},
|
|
23
|
-
};
|
|
24
|
-
function createClient(mockResult) {
|
|
25
|
-
const executeQuery = vi.fn().mockResolvedValue(mockResult);
|
|
26
|
-
const client = new GraphQLClientImpl(TEST_CONFIG, executeQuery);
|
|
27
|
-
return { client, executeQuery };
|
|
28
|
-
}
|
|
29
|
-
const UserResponseSchema = z.object({
|
|
30
|
-
data: z.object({
|
|
31
|
-
user: z.object({
|
|
32
|
-
id: z.string(),
|
|
33
|
-
name: z.string(),
|
|
34
|
-
}),
|
|
35
|
-
}),
|
|
36
|
-
});
|
|
37
|
-
const SAMPLE_QUERY = `query GetUser($id: ID!) {
|
|
38
|
-
user(id: $id) { id name }
|
|
39
|
-
}`;
|
|
40
|
-
const SAMPLE_MUTATION = `mutation CreateUser($name: String!) {
|
|
41
|
-
createUser(name: $name) { id name }
|
|
42
|
-
}`;
|
|
43
|
-
describe("GraphQLClientImpl", () => {
|
|
44
|
-
describe("query()", () => {
|
|
45
|
-
it("returns validated data on a successful response", async () => {
|
|
46
|
-
const { client } = createClient({
|
|
47
|
-
data: { user: { id: "u1", name: "Alice" } },
|
|
48
|
-
});
|
|
49
|
-
const result = await client.query(SAMPLE_QUERY, { response: UserResponseSchema }, { id: "u1" });
|
|
50
|
-
expect(result.data.user).toEqual({ id: "u1", name: "Alice" });
|
|
51
|
-
});
|
|
52
|
-
it("builds the proto request with body, variables, and defaults", async () => {
|
|
53
|
-
const { client, executeQuery } = createClient({
|
|
54
|
-
data: { user: { id: "u1", name: "Alice" } },
|
|
55
|
-
});
|
|
56
|
-
await client.query(SAMPLE_QUERY, { response: UserResponseSchema }, { id: "u1" });
|
|
57
|
-
expect(executeQuery).toHaveBeenCalledOnce();
|
|
58
|
-
const request = executeQuery.mock.calls[0][0];
|
|
59
|
-
expect(request.body).toBe(SAMPLE_QUERY);
|
|
60
|
-
expect(request.verboseHttpOutput).toBe(false);
|
|
61
|
-
expect(request.failOnGraphqlErrors).toBe(true);
|
|
62
|
-
expect(request.custom).toEqual({
|
|
63
|
-
variables: {
|
|
64
|
-
key: "variables",
|
|
65
|
-
value: JSON.stringify({ id: "u1" }),
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
expect(request.headers).toBeUndefined();
|
|
69
|
-
});
|
|
70
|
-
it("omits custom when no variables are provided", async () => {
|
|
71
|
-
const { client, executeQuery } = createClient({
|
|
72
|
-
data: { user: { id: "u1", name: "Alice" } },
|
|
73
|
-
});
|
|
74
|
-
await client.query(SAMPLE_QUERY, { response: UserResponseSchema });
|
|
75
|
-
const request = executeQuery.mock.calls[0][0];
|
|
76
|
-
expect(request.custom).toBeUndefined();
|
|
77
|
-
});
|
|
78
|
-
it("forwards per-request headers into the proto headers field", async () => {
|
|
79
|
-
const { client, executeQuery } = createClient({
|
|
80
|
-
data: { user: { id: "u1", name: "Alice" } },
|
|
81
|
-
});
|
|
82
|
-
await client.query(SAMPLE_QUERY, { response: UserResponseSchema }, { id: "u1" }, undefined, {
|
|
83
|
-
Authorization: "Bearer abc123",
|
|
84
|
-
"X-Trace-Id": "trace-1",
|
|
85
|
-
});
|
|
86
|
-
const request = executeQuery.mock.calls[0][0];
|
|
87
|
-
expect(request.headers).toEqual([
|
|
88
|
-
{ key: "Authorization", value: "Bearer abc123" },
|
|
89
|
-
{ key: "X-Trace-Id", value: "trace-1" },
|
|
90
|
-
]);
|
|
91
|
-
});
|
|
92
|
-
it("does not set headers when an empty headers object is passed", async () => {
|
|
93
|
-
const { client, executeQuery } = createClient({
|
|
94
|
-
data: { user: { id: "u1", name: "Alice" } },
|
|
95
|
-
});
|
|
96
|
-
await client.query(SAMPLE_QUERY, { response: UserResponseSchema }, undefined, undefined, {});
|
|
97
|
-
const request = executeQuery.mock.calls[0][0];
|
|
98
|
-
expect(request.headers).toBeUndefined();
|
|
99
|
-
});
|
|
100
|
-
it("passes trace metadata through to executeQuery", async () => {
|
|
101
|
-
const { client, executeQuery } = createClient({
|
|
102
|
-
data: { user: { id: "u1", name: "Alice" } },
|
|
103
|
-
});
|
|
104
|
-
await client.query(SAMPLE_QUERY, { response: UserResponseSchema }, undefined, { label: "graphql.getUser", description: "Fetch a user by id" });
|
|
105
|
-
expect(executeQuery).toHaveBeenCalledWith(expect.any(Object), undefined, {
|
|
106
|
-
label: "graphql.getUser",
|
|
107
|
-
description: "Fetch a user by id",
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
it("throws RestApiValidationError when the response fails schema validation", async () => {
|
|
111
|
-
const { client } = createClient({
|
|
112
|
-
data: { user: { id: "u1" /* missing name */ } },
|
|
113
|
-
});
|
|
114
|
-
await expect(client.query(SAMPLE_QUERY, { response: UserResponseSchema })).rejects.toThrow(RestApiValidationError);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
describe("mutation()", () => {
|
|
118
|
-
it("returns validated data on a successful response", async () => {
|
|
119
|
-
const { client } = createClient({
|
|
120
|
-
data: { createUser: { id: "u2", name: "Bob" } },
|
|
121
|
-
});
|
|
122
|
-
const Schema = z.object({
|
|
123
|
-
data: z.object({
|
|
124
|
-
createUser: z.object({ id: z.string(), name: z.string() }),
|
|
125
|
-
}),
|
|
126
|
-
});
|
|
127
|
-
const result = await client.mutation(SAMPLE_MUTATION, { response: Schema }, { name: "Bob" });
|
|
128
|
-
expect(result.data.createUser).toEqual({ id: "u2", name: "Bob" });
|
|
129
|
-
});
|
|
130
|
-
it("forwards per-request headers into the proto headers field", async () => {
|
|
131
|
-
const { client, executeQuery } = createClient({
|
|
132
|
-
data: { createUser: { id: "u2", name: "Bob" } },
|
|
133
|
-
});
|
|
134
|
-
const Schema = z.object({
|
|
135
|
-
data: z.object({
|
|
136
|
-
createUser: z.object({ id: z.string(), name: z.string() }),
|
|
137
|
-
}),
|
|
138
|
-
});
|
|
139
|
-
await client.mutation(SAMPLE_MUTATION, { response: Schema }, { name: "Bob" }, undefined, { Authorization: "Bearer xyz" });
|
|
140
|
-
const request = executeQuery.mock.calls[0][0];
|
|
141
|
-
expect(request.body).toBe(SAMPLE_MUTATION);
|
|
142
|
-
expect(request.headers).toEqual([
|
|
143
|
-
{ key: "Authorization", value: "Bearer xyz" },
|
|
144
|
-
]);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
//# sourceMappingURL=client.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../../src/integrations/graphql/client.test.ts"],"names":[],"mappings":"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"}
|