@apifuse/provider-sdk 2.2.0-beta.36 → 2.2.0-beta.38
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/AUTHORING.md +22 -8
- package/CHANGELOG.md +8 -0
- package/README.md +20 -8
- package/bin/apifuse-dev.ts +1 -1
- package/bin/apifuse-pack-types.ts +6 -5
- package/bin/apifuse-record.ts +1 -1
- package/bin/apifuse-submit-check.ts +23 -10
- package/dist/cli/templates/provider/index.ts.tpl +6 -3
- package/dist/cli/templates/provider/operations/ping.ts.tpl +2 -1
- package/dist/declaration-validation.d.ts +2 -0
- package/dist/declaration-validation.js +29 -3
- package/dist/define.d.ts +39 -21
- package/dist/define.js +33 -9
- package/dist/health-scenario.d.ts +1842 -0
- package/dist/health-scenario.js +624 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +1 -0
- package/dist/provider.d.ts +5 -1
- package/dist/provider.js +1 -0
- package/dist/runtime/browser.js +19 -11
- package/dist/runtime/resolver-public.d.ts +1 -1
- package/dist/runtime/resolver-public.js +1 -1
- package/dist/runtime/resolver-vendors/browser.js +57 -14
- package/dist/runtime/resolver-vendors/types.d.ts +9 -1
- package/dist/runtime/resolver-vendors/types.js +15 -0
- package/dist/runtime/resolver.d.ts +1 -0
- package/dist/runtime/resolver.js +13 -7
- package/dist/server/serve-implementation.d.ts +1 -1
- package/dist/server/serve-implementation.js +25 -0
- package/dist/server/types.d.ts +4 -4
- package/dist/types.d.ts +35 -25
- package/package.json +1 -1
- package/src/cli/templates/provider/index.ts.tpl +6 -3
- package/src/cli/templates/provider/operations/ping.ts.tpl +2 -1
- package/src/declaration-validation.ts +30 -3
- package/src/define.ts +144 -51
- package/src/health-scenario.ts +875 -0
- package/src/index.ts +78 -2
- package/src/provider.ts +81 -1
- package/src/runtime/browser.ts +34 -11
- package/src/runtime/resolver-public.ts +2 -0
- package/src/runtime/resolver-vendors/browser.ts +69 -11
- package/src/runtime/resolver-vendors/types.ts +21 -0
- package/src/runtime/resolver.ts +17 -5
- package/src/server/serve-implementation.ts +39 -1
- package/src/testing/run.ts +3 -3
- package/src/types.ts +52 -25
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { defineProvider } from "@apifuse/provider-sdk/provider";
|
|
1
|
+
import { defineProvider, type ProviderContextOf } from "@apifuse/provider-sdk/provider";
|
|
2
2
|
|
|
3
3
|
import { providerMeta } from "./meta";
|
|
4
4
|
import { operations } from "./operations";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const buildProvider = defineProvider({
|
|
7
7
|
id: "{{PROVIDER_ID}}",
|
|
8
8
|
version: "1.0.0",
|
|
9
9
|
runtime: "{{RUNTIME}}"{{BROWSER_BLOCK}},
|
|
@@ -11,5 +11,8 @@ export default defineProvider({
|
|
|
11
11
|
reviewed: "community",
|
|
12
12
|
{{SECRETS_BLOCK}}{{CREDENTIAL_BLOCK}}auth: {{AUTH_BLOCK}},
|
|
13
13
|
meta: providerMeta,
|
|
14
|
-
operations: operations,
|
|
15
14
|
});
|
|
15
|
+
|
|
16
|
+
export type ProviderContext = ProviderContextOf<typeof buildProvider>;
|
|
17
|
+
|
|
18
|
+
export default buildProvider({ operations });
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { defineOperation } from "@apifuse/provider-sdk/provider";
|
|
2
|
+
import type { ProviderContext } from "../index";
|
|
2
3
|
|
|
3
4
|
import { pingInputSchema, pingOutputSchema } from "../schemas/ping";
|
|
4
5
|
|
|
5
|
-
export const pingOperation = defineOperation({
|
|
6
|
+
export const pingOperation = defineOperation<ProviderContext>()({
|
|
6
7
|
descriptionKey: "operations.ping.description",
|
|
7
8
|
input: pingInputSchema,
|
|
8
9
|
output: pingOutputSchema,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describeSchema } from "./contract-serialization.js";
|
|
2
2
|
import { ProviderError } from "./errors.js";
|
|
3
|
+
import { HealthScenarioSchema } from "./health-scenario.js";
|
|
3
4
|
import type {
|
|
4
5
|
HealthJourneyDefinition,
|
|
5
6
|
ProviderDefinition,
|
|
@@ -12,6 +13,8 @@ export const DECLARATION_INVALID_CODE = "DECLARATION_INVALID";
|
|
|
12
13
|
export const DECLARATION_RULE_IDS = {
|
|
13
14
|
challengeShape: "credentials-challenge-shape",
|
|
14
15
|
journeyExecutable: "health-journey-executable",
|
|
16
|
+
journeyRunScenarioExclusive: "health-journey-run-scenario-exclusive",
|
|
17
|
+
journeyScenarioValid: "health-journey-scenario-valid",
|
|
15
18
|
schemaSerializable: "operation-schema-serializable",
|
|
16
19
|
proxyExplicitPolicy: "proxy-explicit-policy",
|
|
17
20
|
proxyVendorExclusive: "proxy-vendor-fields-exclusive",
|
|
@@ -62,15 +65,39 @@ function validateHealthDeclaration(
|
|
|
62
65
|
): void {
|
|
63
66
|
for (const [index, journey] of (provider.healthJourneys ?? []).entries()) {
|
|
64
67
|
if (!journey || typeof journey !== "object") continue;
|
|
65
|
-
|
|
68
|
+
const hasRun = journey.run !== undefined;
|
|
69
|
+
const hasScenario = journey.scenario !== undefined;
|
|
70
|
+
if (hasRun && hasScenario) {
|
|
71
|
+
const journeyPath = healthJourneyPath(journey, index);
|
|
72
|
+
violations.push({
|
|
73
|
+
ruleId: DECLARATION_RULE_IDS.journeyRunScenarioExclusive,
|
|
74
|
+
path: journeyPath,
|
|
75
|
+
message: "A health journey must declare exactly one of run or scenario, not both.",
|
|
76
|
+
fix: `Remove either ${journeyPath}.run or ${journeyPath}.scenario.`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (!hasRun && !hasScenario) {
|
|
66
80
|
const journeyPath = healthJourneyPath(journey, index);
|
|
67
81
|
violations.push({
|
|
68
82
|
ruleId: DECLARATION_RULE_IDS.journeyExecutable,
|
|
69
83
|
path: `${journeyPath}.run`,
|
|
70
|
-
message:
|
|
71
|
-
|
|
84
|
+
message:
|
|
85
|
+
"coversOperations cannot provide health coverage without run or a declarative scenario.",
|
|
86
|
+
fix: `Add an async run(ctx) implementation or a valid scenario to ${journeyPath}.`,
|
|
72
87
|
});
|
|
73
88
|
}
|
|
89
|
+
if (hasScenario) {
|
|
90
|
+
const parsed = HealthScenarioSchema.safeParse(journey.scenario);
|
|
91
|
+
if (!parsed.success) {
|
|
92
|
+
const journeyPath = healthJourneyPath(journey, index);
|
|
93
|
+
violations.push({
|
|
94
|
+
ruleId: DECLARATION_RULE_IDS.journeyScenarioValid,
|
|
95
|
+
path: `${journeyPath}.scenario`,
|
|
96
|
+
message: "scenario must conform to HealthScenario.",
|
|
97
|
+
fix: "Build the scenario with defineHealthScenario().",
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
74
101
|
}
|
|
75
102
|
|
|
76
103
|
// NOTE: healthCheck.cases[].enabled is intentionally NOT validated here.
|
package/src/define.ts
CHANGED
|
@@ -31,6 +31,8 @@ import type {
|
|
|
31
31
|
ProviderAccessConfig,
|
|
32
32
|
ProviderChallengeKind,
|
|
33
33
|
ProviderDefinition,
|
|
34
|
+
ProviderContext,
|
|
35
|
+
ProviderContextFor,
|
|
34
36
|
ProviderOcrConfig,
|
|
35
37
|
ProviderDeploymentOverrides,
|
|
36
38
|
ProviderHealthMonitorConfig,
|
|
@@ -197,54 +199,65 @@ function parsePositiveMsDuration(value: string): number | undefined {
|
|
|
197
199
|
return parsed;
|
|
198
200
|
}
|
|
199
201
|
|
|
200
|
-
type ProviderOperation = OperationDefinition<
|
|
201
|
-
type OperationConfig<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
type ProviderOperation = OperationDefinition<any, any, any>;
|
|
203
|
+
type OperationConfig<
|
|
204
|
+
TInput extends SchemaLike,
|
|
205
|
+
TOutput extends SchemaLike,
|
|
206
|
+
TContext = ProviderContext,
|
|
207
|
+
> = Omit<OperationDefinition<TInput, TOutput, TContext>, "handler"> & {
|
|
205
208
|
handler(
|
|
206
|
-
ctx:
|
|
209
|
+
ctx: TContext,
|
|
207
210
|
input: InferSchemaOutput<TInput>,
|
|
208
211
|
):
|
|
209
212
|
| OperationHandlerResult<InferSchemaOutput<TOutput>>
|
|
210
213
|
| Promise<OperationHandlerResult<InferSchemaOutput<TOutput>>>;
|
|
211
214
|
};
|
|
212
|
-
type OperationMapConfig<
|
|
215
|
+
type OperationMapConfig<
|
|
216
|
+
TOperations extends Record<string, ProviderOperation>,
|
|
217
|
+
TContext = ProviderContext,
|
|
218
|
+
> = {
|
|
213
219
|
[K in keyof TOperations]: TOperations[K] extends OperationDefinition<infer TInput, infer TOutput>
|
|
214
|
-
? OperationConfig<TInput, TOutput> | OperationDefinition<TInput, TOutput>
|
|
220
|
+
? OperationConfig<TInput, TOutput, TContext> | OperationDefinition<TInput, TOutput, TContext>
|
|
215
221
|
: never;
|
|
216
222
|
};
|
|
217
|
-
type StreamOperationConfig<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
type StreamOperationConfig<
|
|
224
|
+
TInput extends SchemaLike,
|
|
225
|
+
TOutput extends SchemaLike,
|
|
226
|
+
TContext = ProviderContext,
|
|
227
|
+
> =
|
|
228
|
+
| SseOperationConfig<TInput, TOutput, TContext>
|
|
229
|
+
| HttpStreamOperationConfig<TInput, TOutput, TContext>
|
|
230
|
+
| WebSocketOperationConfig<TInput, TOutput, TContext>;
|
|
231
|
+
type SseOperationConfig<
|
|
232
|
+
TInput extends SchemaLike,
|
|
233
|
+
TOutput extends SchemaLike,
|
|
234
|
+
TContext = ProviderContext,
|
|
235
|
+
> = Omit<OperationConfig<TInput, TOutput, TContext>, "handler" | "transport"> & {
|
|
225
236
|
transport: OperationSseTransport;
|
|
226
237
|
handler(
|
|
227
|
-
ctx:
|
|
238
|
+
ctx: TContext,
|
|
228
239
|
input: InferSchemaOutput<TInput>,
|
|
229
240
|
): AsyncIterable<ProviderStreamEvent> | Promise<AsyncIterable<ProviderStreamEvent>>;
|
|
230
241
|
};
|
|
231
|
-
type HttpStreamOperationConfig<
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
242
|
+
type HttpStreamOperationConfig<
|
|
243
|
+
TInput extends SchemaLike,
|
|
244
|
+
TOutput extends SchemaLike,
|
|
245
|
+
TContext = ProviderContext,
|
|
246
|
+
> = Omit<OperationConfig<TInput, TOutput, TContext>, "handler" | "transport"> & {
|
|
235
247
|
transport: OperationHttpStreamTransport;
|
|
236
248
|
handler(
|
|
237
|
-
ctx:
|
|
249
|
+
ctx: TContext,
|
|
238
250
|
input: InferSchemaOutput<TInput>,
|
|
239
251
|
): Response | ReadableStream<Uint8Array> | Promise<Response | ReadableStream<Uint8Array>>;
|
|
240
252
|
};
|
|
241
|
-
type WebSocketOperationConfig<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
253
|
+
type WebSocketOperationConfig<
|
|
254
|
+
TInput extends SchemaLike,
|
|
255
|
+
TOutput extends SchemaLike,
|
|
256
|
+
TContext = ProviderContext,
|
|
257
|
+
> = Omit<OperationConfig<TInput, TOutput, TContext>, "handler" | "transport"> & {
|
|
245
258
|
transport: OperationWebSocketTransport;
|
|
246
259
|
handler(
|
|
247
|
-
ctx:
|
|
260
|
+
ctx: TContext,
|
|
248
261
|
input: InferSchemaOutput<TInput>,
|
|
249
262
|
): Response | ReadableStream<Uint8Array> | Promise<Response | ReadableStream<Uint8Array>>;
|
|
250
263
|
};
|
|
@@ -562,7 +575,7 @@ function authStartHasHiddenInput(start: unknown): boolean {
|
|
|
562
575
|
return /\s=\s/.test(second);
|
|
563
576
|
}
|
|
564
577
|
|
|
565
|
-
export interface
|
|
578
|
+
export interface ProviderDeclaration {
|
|
566
579
|
id: string;
|
|
567
580
|
version: string;
|
|
568
581
|
runtime: "standard" | "shared" | "browser";
|
|
@@ -573,6 +586,8 @@ export interface ProviderConfig<TOperations extends Record<string, ProviderOpera
|
|
|
573
586
|
* resolves omitted fields against the runtime deployment profiles.
|
|
574
587
|
*/
|
|
575
588
|
deployment?: ProviderDeploymentOverrides;
|
|
589
|
+
/** Declares that provider operations use the SDK HTTP client. */
|
|
590
|
+
http?: true;
|
|
576
591
|
allowedHosts?: string[];
|
|
577
592
|
native?: NativeProviderConfig;
|
|
578
593
|
stealth?: {
|
|
@@ -585,11 +600,21 @@ export interface ProviderConfig<TOperations extends Record<string, ProviderOpera
|
|
|
585
600
|
resolver?: ProviderResolverConfig;
|
|
586
601
|
browser?: { engine: BrowserEngine };
|
|
587
602
|
auth?: AuthConfig;
|
|
603
|
+
/** Declares that provider operations issue and consume SDK choice tokens. */
|
|
604
|
+
choice?: true;
|
|
588
605
|
reviewed?: ProviderReviewed;
|
|
589
606
|
access?: ProviderAccessConfig;
|
|
590
607
|
secrets?: ProviderSecretDeclaration[];
|
|
608
|
+
/** Declares that provider operations read SDK-managed environment values. */
|
|
609
|
+
env?: true;
|
|
591
610
|
credential?: CredentialDeclaration;
|
|
592
611
|
context?: ContextDeclaration;
|
|
612
|
+
/** Declares that provider operations use SDK-managed persistent state. */
|
|
613
|
+
state?: true;
|
|
614
|
+
/** Declares that provider operations use the SDK provider cache. */
|
|
615
|
+
cache?: true;
|
|
616
|
+
/** Declares that provider operations access runtime-resolvable files. */
|
|
617
|
+
files?: true;
|
|
593
618
|
meta: {
|
|
594
619
|
displayName: string;
|
|
595
620
|
displayNameKey?: string;
|
|
@@ -611,25 +636,35 @@ export interface ProviderConfig<TOperations extends Record<string, ProviderOpera
|
|
|
611
636
|
publicSchemaFieldNames?: "normalized";
|
|
612
637
|
};
|
|
613
638
|
};
|
|
614
|
-
operations: OperationMapConfig<TOperations>;
|
|
615
639
|
healthMonitor?: ProviderHealthMonitorConfig;
|
|
616
640
|
/** New name for `healthMonitor` (transitional alias); declaring both is a ValidationError. */
|
|
617
641
|
healthProbe?: ProviderHealthMonitorConfig;
|
|
618
642
|
healthJourneys?: readonly HealthJourneyDefinition[];
|
|
619
643
|
}
|
|
620
644
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
645
|
+
interface ProviderConfig<
|
|
646
|
+
TOperations extends Record<string, ProviderOperation>,
|
|
647
|
+
TContext = ProviderContext,
|
|
648
|
+
> extends ProviderDeclaration {
|
|
649
|
+
operations: OperationMapConfig<TOperations, TContext>;
|
|
626
650
|
}
|
|
627
651
|
|
|
628
|
-
/** Define
|
|
629
|
-
export function
|
|
630
|
-
operation
|
|
631
|
-
|
|
632
|
-
|
|
652
|
+
/** Define one factored provider operation with schema-driven handler inference. */
|
|
653
|
+
export function defineOperation<TContext>() {
|
|
654
|
+
return function operation<TInput extends SchemaLike, TOutput extends SchemaLike>(
|
|
655
|
+
config: OperationConfig<TInput, TOutput, TContext>,
|
|
656
|
+
): OperationDefinition<TInput, TOutput, TContext> {
|
|
657
|
+
return config;
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/** Define a factored non-JSON operation with explicit transport metadata. */
|
|
662
|
+
export function defineStreamOperation<TContext>() {
|
|
663
|
+
return function streamOperation<TInput extends SchemaLike, TOutput extends SchemaLike>(
|
|
664
|
+
config: StreamOperationConfig<TInput, TOutput, TContext>,
|
|
665
|
+
): OperationDefinition<TInput, TOutput, TContext> {
|
|
666
|
+
return config;
|
|
667
|
+
};
|
|
633
668
|
}
|
|
634
669
|
|
|
635
670
|
function assertObjectConfig(value: unknown): asserts value is Record<string, unknown> {
|
|
@@ -780,6 +815,14 @@ function validateProviderShape(config: unknown): void {
|
|
|
780
815
|
assertRequiredField(config, "operations", String(config.id));
|
|
781
816
|
if (typeof config.runtime === "string")
|
|
782
817
|
assertLiteralField(config.runtime, "runtime", VALID_RUNTIMES, String(config.id));
|
|
818
|
+
if (config.native !== undefined && config.runtime === "browser") {
|
|
819
|
+
throw new ValidationError(
|
|
820
|
+
`Provider "${String(config.id)}" cannot declare capability "native" with runtime "browser"`,
|
|
821
|
+
{
|
|
822
|
+
fix: 'Use runtime: "standard" or runtime: "shared", or remove the native declaration.',
|
|
823
|
+
},
|
|
824
|
+
);
|
|
825
|
+
}
|
|
783
826
|
const auth = config.auth;
|
|
784
827
|
if (auth && typeof auth === "object" && "mode" in auth && typeof auth.mode === "string")
|
|
785
828
|
assertLiteralField(auth.mode, "auth.mode", VALID_AUTH_MODES, String(config.id));
|
|
@@ -1087,12 +1130,14 @@ function validateProviderResolver(config: { id: string; resolver?: ProviderResol
|
|
|
1087
1130
|
"resolver",
|
|
1088
1131
|
config.id,
|
|
1089
1132
|
);
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1133
|
+
if (resolver.vendors !== undefined) {
|
|
1134
|
+
validateResolverLiteralArray(
|
|
1135
|
+
resolver.vendors,
|
|
1136
|
+
"resolver.vendors",
|
|
1137
|
+
VALID_PROVIDER_RESOLVER_VENDORS,
|
|
1138
|
+
config.id,
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1096
1141
|
validateResolverLiteralArray(
|
|
1097
1142
|
resolver.kinds,
|
|
1098
1143
|
"resolver.kinds",
|
|
@@ -2087,6 +2132,7 @@ const HEALTH_JOURNEY_FIELDS = new Set([
|
|
|
2087
2132
|
"manualTrigger",
|
|
2088
2133
|
"steps",
|
|
2089
2134
|
"run",
|
|
2135
|
+
"scenario",
|
|
2090
2136
|
]);
|
|
2091
2137
|
const HEALTH_JOURNEY_SCHEDULE_FIELDS = new Set(["kind", "interval", "jitter", "randomize"]);
|
|
2092
2138
|
const HEALTH_JOURNEY_STEP_FIELDS = new Set([
|
|
@@ -2622,6 +2668,14 @@ function validateHealthJourneys(
|
|
|
2622
2668
|
}
|
|
2623
2669
|
if (journey.manualTrigger !== undefined)
|
|
2624
2670
|
validateHealthJourneyManualTrigger(providerId, journey.id, journey.manualTrigger);
|
|
2671
|
+
if (journey.scenario !== undefined && journey.smsMatchers !== undefined)
|
|
2672
|
+
throw new ValidationError(
|
|
2673
|
+
`Provider "${providerId}" healthJourneys.${journey.id}.smsMatchers is not allowed on declarative scenarios.`,
|
|
2674
|
+
);
|
|
2675
|
+
if (journey.scenario !== undefined && journey.requiredSecrets !== undefined)
|
|
2676
|
+
throw new ValidationError(
|
|
2677
|
+
`Provider "${providerId}" healthJourneys.${journey.id}.requiredSecrets is not allowed on declarative scenarios.`,
|
|
2678
|
+
);
|
|
2625
2679
|
if (journey.timeout !== undefined)
|
|
2626
2680
|
assertIsoDuration(
|
|
2627
2681
|
journey.timeout,
|
|
@@ -2783,12 +2837,48 @@ function validateProviderDeployment(providerId: string, deployment: unknown): vo
|
|
|
2783
2837
|
});
|
|
2784
2838
|
}
|
|
2785
2839
|
|
|
2786
|
-
|
|
2840
|
+
/** The second authoring phase for a declaration established by defineProvider. */
|
|
2841
|
+
export type ProviderBuilder<TDeclaration extends ProviderDeclaration> = <
|
|
2842
|
+
TOperations extends Record<string, ProviderOperation>,
|
|
2843
|
+
>(
|
|
2844
|
+
implementation: {
|
|
2845
|
+
operations: OperationMapConfig<TOperations, ProviderContextFor<TDeclaration>>;
|
|
2846
|
+
},
|
|
2847
|
+
) => ProviderDefinition & {
|
|
2848
|
+
operations: OperationMapConfig<TOperations, ProviderContextFor<TDeclaration>>;
|
|
2849
|
+
};
|
|
2850
|
+
|
|
2851
|
+
/** Extract the declaration-derived operation context from a provider builder. */
|
|
2852
|
+
export type ProviderContextOf<TBuilder> = TBuilder extends ProviderBuilder<infer TDeclaration>
|
|
2853
|
+
? ProviderContextFor<TDeclaration>
|
|
2854
|
+
: never;
|
|
2855
|
+
|
|
2856
|
+
/** Establish a provider declaration before its operations are contextually typed. */
|
|
2857
|
+
export function defineProvider<const TDeclaration extends ProviderDeclaration>(
|
|
2858
|
+
declaration: TDeclaration &
|
|
2859
|
+
Record<Exclude<keyof TDeclaration, keyof ProviderDeclaration>, never> &
|
|
2860
|
+
AuthStartNoInputGuard<TDeclaration>,
|
|
2861
|
+
): ProviderBuilder<TDeclaration> {
|
|
2862
|
+
const buildProvider = <TOperations extends Record<string, ProviderOperation>>(
|
|
2863
|
+
implementation: {
|
|
2864
|
+
operations: OperationMapConfig<TOperations, ProviderContextFor<TDeclaration>>;
|
|
2865
|
+
},
|
|
2866
|
+
) =>
|
|
2867
|
+
finalizeProvider({
|
|
2868
|
+
...declaration,
|
|
2869
|
+
...implementation,
|
|
2870
|
+
} as ProviderConfig<TOperations, ProviderContextFor<TDeclaration>>);
|
|
2871
|
+
return buildProvider as ProviderBuilder<TDeclaration>;
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
function finalizeProvider<
|
|
2787
2875
|
TOperations extends Record<string, ProviderOperation>,
|
|
2788
|
-
|
|
2876
|
+
TContext,
|
|
2789
2877
|
>(
|
|
2790
|
-
config:
|
|
2791
|
-
): ProviderDefinition & {
|
|
2878
|
+
config: ProviderConfig<TOperations, TContext>,
|
|
2879
|
+
): ProviderDefinition & {
|
|
2880
|
+
operations: OperationMapConfig<TOperations, TContext>;
|
|
2881
|
+
} {
|
|
2792
2882
|
validateProviderShape(config);
|
|
2793
2883
|
const operations = resolveOperationFixtureRequests(config.operations);
|
|
2794
2884
|
if (!CONNECTOR_ID_REGEX.test(config.id))
|
|
@@ -2849,7 +2939,9 @@ export function defineProvider<
|
|
|
2849
2939
|
`Provider "${config.id}" cannot define browser config unless runtime is "browser"`,
|
|
2850
2940
|
{ fix: 'Set runtime: "browser" or remove the browser config' },
|
|
2851
2941
|
);
|
|
2852
|
-
const provider: ProviderDefinition & {
|
|
2942
|
+
const provider: ProviderDefinition & {
|
|
2943
|
+
operations: OperationMapConfig<TOperations, TContext>;
|
|
2944
|
+
} = {
|
|
2853
2945
|
id: config.id,
|
|
2854
2946
|
version: config.version,
|
|
2855
2947
|
runtime: config.runtime,
|
|
@@ -2871,7 +2963,8 @@ export function defineProvider<
|
|
|
2871
2963
|
credential: config.credential,
|
|
2872
2964
|
context: config.context,
|
|
2873
2965
|
meta: config.meta,
|
|
2874
|
-
operations
|
|
2966
|
+
operations: operations as ProviderDefinition["operations"] &
|
|
2967
|
+
OperationMapConfig<TOperations, TContext>,
|
|
2875
2968
|
// Transitional healthMonitor → healthProbe alias: mirror whichever field
|
|
2876
2969
|
// was declared onto both so old and new consumers keep working.
|
|
2877
2970
|
healthMonitor: config.healthMonitor ?? config.healthProbe,
|