@apifuse/provider-sdk 2.2.0-beta.2 → 2.2.0-beta.4
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 +14 -0
- package/CHANGELOG.md +8 -0
- package/bin/apifuse-check.ts +18 -58
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +27 -52
- package/bin/apifuse-pack-smoke.ts +22 -81
- package/bin/apifuse-pack-types.ts +266 -0
- package/bin/apifuse-perf.ts +45 -127
- package/bin/apifuse-record.ts +23 -61
- package/bin/apifuse-submit-check.ts +73 -30
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-xml-semantics.ts +204 -0
- package/bin/submit-check-xml.ts +134 -0
- package/dist/auth-turn/index.d.ts +1 -1
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +9 -18
- package/dist/ceremonies/index.d.ts +1 -1
- package/dist/ceremonies/index.js +8 -18
- package/dist/config/loader.d.ts +2 -2
- package/dist/config/loader.js +19 -42
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +3 -6
- package/dist/contract-types.d.ts +2 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +4 -6
- package/dist/define.d.ts +8 -1
- package/dist/define.js +57 -115
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/errors.d.ts +4 -1
- package/dist/errors.js +48 -0
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +43 -42
- package/dist/index.js +38 -37
- package/dist/lint.js +8 -15
- package/dist/provider.d.ts +11 -11
- package/dist/provider.js +9 -9
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +1 -1
- package/dist/runtime/auth-flow.js +3 -3
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +15 -29
- package/dist/runtime/cache.d.ts +1 -1
- package/dist/runtime/cache.js +4 -8
- package/dist/runtime/choice.d.ts +1 -1
- package/dist/runtime/choice.js +12 -34
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +8 -3
- package/dist/runtime/http.d.ts +2 -2
- package/dist/runtime/http.js +5 -5
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +5 -15
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +3 -5
- package/dist/runtime/proxy-retry-policy.d.ts +2 -2
- package/dist/runtime/proxy-retry-policy.js +2 -2
- package/dist/runtime/proxy-telemetry.d.ts +1 -1
- package/dist/runtime/proxy-telemetry.js +16 -48
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +2 -4
- package/dist/runtime/request-options.d.ts +1 -1
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +3 -3
- package/dist/runtime/stealth.d.ts +2 -2
- package/dist/runtime/stealth.js +6 -6
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +11 -15
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -7
- package/dist/server/index.js +6 -6
- package/dist/server/self-test-redaction.d.ts +1 -1
- package/dist/server/self-test-redaction.js +1 -1
- package/dist/server/self-test.d.ts +3 -3
- package/dist/server/self-test.js +3 -3
- package/dist/server/serve.d.ts +3 -3
- package/dist/server/serve.js +49 -57
- package/dist/server/types.js +2 -7
- package/dist/stealth/profiles.d.ts +1 -1
- package/dist/stealth/profiles.js +5 -14
- package/dist/stream.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/testing/run.d.ts +1 -1
- package/dist/testing/run.js +7 -14
- package/dist/types.d.ts +57 -0
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +7 -4
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +28 -86
- package/src/ceremonies/index.ts +24 -78
- package/src/config/loader.ts +58 -176
- package/src/contract-serialization.ts +5 -11
- package/src/contract-types.ts +2 -2
- package/src/contract.ts +12 -28
- package/src/define.ts +174 -495
- package/src/dev.ts +4 -9
- package/src/errors.ts +58 -5
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +44 -42
- package/src/lint.ts +89 -159
- package/src/provider.ts +15 -11
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +5 -7
- package/src/runtime/browser.ts +64 -187
- package/src/runtime/cache.ts +20 -67
- package/src/runtime/choice.ts +55 -129
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +15 -20
- package/src/runtime/http.ts +7 -7
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +19 -58
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +17 -38
- package/src/runtime/proxy-retry-policy.ts +3 -3
- package/src/runtime/proxy-telemetry.ts +23 -72
- package/src/runtime/redis.ts +4 -12
- package/src/runtime/request-options.ts +4 -13
- package/src/runtime/state.ts +30 -109
- package/src/runtime/stealth.ts +8 -8
- package/src/runtime/stt.ts +38 -94
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +1 -1
- package/src/server/index.ts +7 -7
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +5 -5
- package/src/server/serve.ts +103 -252
- package/src/server/types.ts +6 -19
- package/src/stealth/profiles.ts +10 -26
- package/src/stream.ts +8 -19
- package/src/testing/index.ts +2 -2
- package/src/testing/run.ts +19 -67
- package/src/types.ts +58 -0
- package/src/user-input.ts +118 -0
package/src/lint.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import type { ZodType } from "zod";
|
|
2
2
|
|
|
3
|
-
import { lintPublicSchemaFieldNames } from "./public-schema-field-lint";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "./schema";
|
|
8
|
-
|
|
9
|
-
type AuthModeLike =
|
|
10
|
-
| "none"
|
|
11
|
-
| "platform-managed"
|
|
12
|
-
| "credentials"
|
|
13
|
-
| "oauth2"
|
|
14
|
-
| "api-key";
|
|
3
|
+
import { lintPublicSchemaFieldNames } from "./public-schema-field-lint.js";
|
|
4
|
+
import { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_SENSITIVE_META_KEY } from "./schema.js";
|
|
5
|
+
|
|
6
|
+
type AuthModeLike = "none" | "platform-managed" | "credentials" | "oauth2" | "api-key";
|
|
15
7
|
|
|
16
8
|
type ProviderAuthLike = {
|
|
17
9
|
mode?: AuthModeLike;
|
|
@@ -141,28 +133,19 @@ function hasReusableSecretKeys(keys: readonly string[] | undefined): boolean {
|
|
|
141
133
|
}
|
|
142
134
|
|
|
143
135
|
return keys.some((key) =>
|
|
144
|
-
/(access_token|refresh_token|password|secret|cookie|session|token|api[_-]?key)/i.test(
|
|
145
|
-
key,
|
|
146
|
-
),
|
|
136
|
+
/(access_token|refresh_token|password|secret|cookie|session|token|api[_-]?key)/i.test(key),
|
|
147
137
|
);
|
|
148
138
|
}
|
|
149
139
|
|
|
150
|
-
function hasReusableReloginSecretKeys(
|
|
151
|
-
keys: readonly string[] | undefined,
|
|
152
|
-
): boolean {
|
|
140
|
+
function hasReusableReloginSecretKeys(keys: readonly string[] | undefined): boolean {
|
|
153
141
|
if (!keys) {
|
|
154
142
|
return false;
|
|
155
143
|
}
|
|
156
144
|
|
|
157
|
-
return keys.some((key) =>
|
|
158
|
-
/(password|passcode|secret|cookie|session)/i.test(key),
|
|
159
|
-
);
|
|
145
|
+
return keys.some((key) => /(password|passcode|secret|cookie|session)/i.test(key));
|
|
160
146
|
}
|
|
161
147
|
|
|
162
|
-
function getAuthFlowSource(provider: {
|
|
163
|
-
auth?: ProviderAuthLike;
|
|
164
|
-
authFlowSource?: string;
|
|
165
|
-
}): string {
|
|
148
|
+
function getAuthFlowSource(provider: { auth?: ProviderAuthLike; authFlowSource?: string }): string {
|
|
166
149
|
if (provider.authFlowSource) {
|
|
167
150
|
return provider.authFlowSource;
|
|
168
151
|
}
|
|
@@ -176,10 +159,7 @@ function getAuthFlowSource(provider: {
|
|
|
176
159
|
];
|
|
177
160
|
|
|
178
161
|
return parts
|
|
179
|
-
.filter(
|
|
180
|
-
(part): part is (...args: unknown[]) => unknown =>
|
|
181
|
-
typeof part === "function",
|
|
182
|
-
)
|
|
162
|
+
.filter((part): part is (...args: unknown[]) => unknown => typeof part === "function")
|
|
183
163
|
.map((part) => part.toString())
|
|
184
164
|
.join("\n");
|
|
185
165
|
}
|
|
@@ -243,8 +223,7 @@ function lintAuthModel(provider: {
|
|
|
243
223
|
|
|
244
224
|
if (
|
|
245
225
|
hasReusableSecretKeys(credentialKeys) &&
|
|
246
|
-
(!provider.credential?.storesReusableSecret ||
|
|
247
|
-
!provider.credential.justification)
|
|
226
|
+
(!provider.credential?.storesReusableSecret || !provider.credential.justification)
|
|
248
227
|
) {
|
|
249
228
|
diagnostics.push({
|
|
250
229
|
rule: "credential-reusable-secret",
|
|
@@ -257,8 +236,7 @@ function lintAuthModel(provider: {
|
|
|
257
236
|
if (
|
|
258
237
|
typeof provider.auth?.flow?.refresh === "function" &&
|
|
259
238
|
hasReusableReloginSecretKeys(credentialKeys) &&
|
|
260
|
-
(!provider.credential?.storesReusableSecret ||
|
|
261
|
-
!provider.credential.justification)
|
|
239
|
+
(!provider.credential?.storesReusableSecret || !provider.credential.justification)
|
|
262
240
|
) {
|
|
263
241
|
diagnostics.push({
|
|
264
242
|
rule: "auth-refresh-reusable-secret",
|
|
@@ -278,10 +256,7 @@ function lintAuthModel(provider: {
|
|
|
278
256
|
}
|
|
279
257
|
|
|
280
258
|
const authFlowSource = getAuthFlowSource(provider);
|
|
281
|
-
if (
|
|
282
|
-
authFlowSource.includes("ctx.context") &&
|
|
283
|
-
(provider.context?.keys?.length ?? 0) === 0
|
|
284
|
-
) {
|
|
259
|
+
if (authFlowSource.includes("ctx.context") && (provider.context?.keys?.length ?? 0) === 0) {
|
|
285
260
|
diagnostics.push({
|
|
286
261
|
rule: "context-keys-required",
|
|
287
262
|
level: "warn",
|
|
@@ -323,8 +298,7 @@ function isSchemaRecord(value: unknown): value is Record<string, SchemaLike> {
|
|
|
323
298
|
}
|
|
324
299
|
|
|
325
300
|
function getObjectShape(schema: SchemaLike): Record<string, SchemaLike> {
|
|
326
|
-
const rawShape =
|
|
327
|
-
typeof schema.shape === "function" ? schema.shape() : schema.shape;
|
|
301
|
+
const rawShape = typeof schema.shape === "function" ? schema.shape() : schema.shape;
|
|
328
302
|
if (isSchemaRecord(rawShape)) {
|
|
329
303
|
return rawShape;
|
|
330
304
|
}
|
|
@@ -344,9 +318,7 @@ function getObjectShape(schema: SchemaLike): Record<string, SchemaLike> {
|
|
|
344
318
|
return {};
|
|
345
319
|
}
|
|
346
320
|
|
|
347
|
-
function getChildSchemas(
|
|
348
|
-
schema: SchemaLike,
|
|
349
|
-
): Array<{ key: string; schema: SchemaLike }> {
|
|
321
|
+
function getChildSchemas(schema: SchemaLike): Array<{ key: string; schema: SchemaLike }> {
|
|
350
322
|
const seen = new Map<string, SchemaLike>();
|
|
351
323
|
const def = getSchemaDef(schema);
|
|
352
324
|
|
|
@@ -450,10 +422,7 @@ function getSchemaMetadata(schema: SchemaLike): Record<string, unknown> {
|
|
|
450
422
|
}
|
|
451
423
|
|
|
452
424
|
function getSchemaDescriptionKey(schema: SchemaLike): string | undefined {
|
|
453
|
-
const value = Reflect.get(
|
|
454
|
-
getSchemaMetadata(schema),
|
|
455
|
-
APIFUSE_DESCRIPTION_KEY_META_KEY,
|
|
456
|
-
);
|
|
425
|
+
const value = Reflect.get(getSchemaMetadata(schema), APIFUSE_DESCRIPTION_KEY_META_KEY);
|
|
457
426
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
458
427
|
}
|
|
459
428
|
|
|
@@ -597,22 +566,14 @@ function collectSchemaDescriptionKeyDiagnostics(
|
|
|
597
566
|
? `${currentPath}[]`
|
|
598
567
|
: `${currentPath}.${child.key}`;
|
|
599
568
|
diagnostics.push(
|
|
600
|
-
...collectSchemaDescriptionKeyDiagnostics(
|
|
601
|
-
child.schema,
|
|
602
|
-
childPath,
|
|
603
|
-
seen,
|
|
604
|
-
!isStructuralNode,
|
|
605
|
-
),
|
|
569
|
+
...collectSchemaDescriptionKeyDiagnostics(child.schema, childPath, seen, !isStructuralNode),
|
|
606
570
|
);
|
|
607
571
|
}
|
|
608
572
|
|
|
609
573
|
return diagnostics;
|
|
610
574
|
}
|
|
611
575
|
|
|
612
|
-
function isComplexSchema(
|
|
613
|
-
schema: unknown,
|
|
614
|
-
seen = new Set<SchemaLike>(),
|
|
615
|
-
): boolean {
|
|
576
|
+
function isComplexSchema(schema: unknown, seen = new Set<SchemaLike>()): boolean {
|
|
616
577
|
if (!isSchema(schema) || seen.has(schema)) {
|
|
617
578
|
return false;
|
|
618
579
|
}
|
|
@@ -624,10 +585,7 @@ function isComplexSchema(
|
|
|
624
585
|
return childChildren.length > 0;
|
|
625
586
|
});
|
|
626
587
|
|
|
627
|
-
return (
|
|
628
|
-
hasNestedComposite ||
|
|
629
|
-
children.some(({ schema: child }) => isComplexSchema(child, seen))
|
|
630
|
-
);
|
|
588
|
+
return hasNestedComposite || children.some(({ schema: child }) => isComplexSchema(child, seen));
|
|
631
589
|
}
|
|
632
590
|
|
|
633
591
|
function hasBidirectionalFixtures(fixtures: unknown): boolean {
|
|
@@ -638,16 +596,11 @@ function hasBidirectionalFixtures(fixtures: unknown): boolean {
|
|
|
638
596
|
return "request" in fixtures && "response" in fixtures;
|
|
639
597
|
}
|
|
640
598
|
|
|
641
|
-
function getOperationSource(operation: {
|
|
642
|
-
handler?: unknown;
|
|
643
|
-
source?: string;
|
|
644
|
-
}): string {
|
|
599
|
+
function getOperationSource(operation: { handler?: unknown; source?: string }): string {
|
|
645
600
|
if (operation.source) {
|
|
646
601
|
return operation.source;
|
|
647
602
|
}
|
|
648
|
-
return typeof operation.handler === "function"
|
|
649
|
-
? operation.handler.toString()
|
|
650
|
-
: "";
|
|
603
|
+
return typeof operation.handler === "function" ? operation.handler.toString() : "";
|
|
651
604
|
}
|
|
652
605
|
|
|
653
606
|
function lintStealthTransportUsage(provider: {
|
|
@@ -660,22 +613,20 @@ function lintStealthTransportUsage(provider: {
|
|
|
660
613
|
}
|
|
661
614
|
|
|
662
615
|
const providerLabel = provider.id ? `Provider "${provider.id}"` : "Provider";
|
|
663
|
-
return Object.entries(provider.operations).flatMap(
|
|
664
|
-
(
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
},
|
|
678
|
-
);
|
|
616
|
+
return Object.entries(provider.operations).flatMap(([operationKey, operation]) => {
|
|
617
|
+
const source = getOperationSource(operation);
|
|
618
|
+
if (!/\bctx\.stealth\b/.test(source)) {
|
|
619
|
+
return [];
|
|
620
|
+
}
|
|
621
|
+
return [
|
|
622
|
+
{
|
|
623
|
+
rule: "stealth-config-required",
|
|
624
|
+
level: "error" as const,
|
|
625
|
+
field: `operations.${operationKey}`,
|
|
626
|
+
message: `${providerLabel} operation "${operationKey}" uses ctx.stealth but provider.stealth is not declared.`,
|
|
627
|
+
},
|
|
628
|
+
];
|
|
629
|
+
});
|
|
679
630
|
}
|
|
680
631
|
|
|
681
632
|
function lintCredentialWriteUsage(provider: {
|
|
@@ -685,24 +636,22 @@ function lintCredentialWriteUsage(provider: {
|
|
|
685
636
|
return [];
|
|
686
637
|
}
|
|
687
638
|
|
|
688
|
-
return Object.entries(provider.operations).flatMap(
|
|
689
|
-
(
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
639
|
+
return Object.entries(provider.operations).flatMap(([operationKey, operation]) => {
|
|
640
|
+
const source = getOperationSource(operation);
|
|
641
|
+
if (!/\bctx\.credential\.(?:set|setMany)\s*\(/.test(source)) {
|
|
642
|
+
return [];
|
|
643
|
+
}
|
|
694
644
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
);
|
|
645
|
+
return [
|
|
646
|
+
{
|
|
647
|
+
rule: "ctx-credential-write-forbidden-in-handler",
|
|
648
|
+
level: "error" as const,
|
|
649
|
+
field: `operations.${operationKey}.handler`,
|
|
650
|
+
message:
|
|
651
|
+
"Operation handlers must not mutate credentials; return refreshed credentials from auth.flow.refresh instead.",
|
|
652
|
+
},
|
|
653
|
+
];
|
|
654
|
+
});
|
|
706
655
|
}
|
|
707
656
|
|
|
708
657
|
function lintPlaywrightDirectImports(provider: {
|
|
@@ -724,9 +673,7 @@ function lintPlaywrightDirectImports(provider: {
|
|
|
724
673
|
});
|
|
725
674
|
}
|
|
726
675
|
|
|
727
|
-
for (const [filePath, source] of Object.entries(
|
|
728
|
-
provider.providerSourceFiles ?? {},
|
|
729
|
-
)) {
|
|
676
|
+
for (const [filePath, source] of Object.entries(provider.providerSourceFiles ?? {})) {
|
|
730
677
|
if (!importPattern.test(source)) {
|
|
731
678
|
continue;
|
|
732
679
|
}
|
|
@@ -814,15 +761,11 @@ function lintSelfHostedBrowserPatterns(
|
|
|
814
761
|
sources.push({ field: "auth.flow", source: provider.authFlowSource });
|
|
815
762
|
}
|
|
816
763
|
|
|
817
|
-
for (const [filePath, source] of Object.entries(
|
|
818
|
-
provider.providerSourceFiles ?? {},
|
|
819
|
-
)) {
|
|
764
|
+
for (const [filePath, source] of Object.entries(provider.providerSourceFiles ?? {})) {
|
|
820
765
|
sources.push({ field: `sourceFiles.${filePath}`, source });
|
|
821
766
|
}
|
|
822
767
|
|
|
823
|
-
for (const [operationKey, operation] of Object.entries(
|
|
824
|
-
provider.operations ?? {},
|
|
825
|
-
)) {
|
|
768
|
+
for (const [operationKey, operation] of Object.entries(provider.operations ?? {})) {
|
|
826
769
|
const source = getOperationSource(operation);
|
|
827
770
|
if (source) {
|
|
828
771
|
sources.push({
|
|
@@ -865,16 +808,14 @@ export function lintOperation(op: {
|
|
|
865
808
|
}): LintDiagnostic[] {
|
|
866
809
|
const diagnostics: LintDiagnostic[] = [];
|
|
867
810
|
const description = op.description ?? "";
|
|
868
|
-
const hasDescriptionKey =
|
|
869
|
-
typeof op.descriptionKey === "string" && op.descriptionKey.length > 0;
|
|
811
|
+
const hasDescriptionKey = typeof op.descriptionKey === "string" && op.descriptionKey.length > 0;
|
|
870
812
|
|
|
871
813
|
if (description.trim().length > 0 && !hasDescriptionKey) {
|
|
872
814
|
diagnostics.push({
|
|
873
815
|
rule: "operation-description-raw-prose",
|
|
874
816
|
level: "error",
|
|
875
817
|
field: "description",
|
|
876
|
-
message:
|
|
877
|
-
"Operation description must use descriptionKey instead of raw static prose.",
|
|
818
|
+
message: "Operation description must use descriptionKey instead of raw static prose.",
|
|
878
819
|
});
|
|
879
820
|
}
|
|
880
821
|
|
|
@@ -892,21 +833,16 @@ export function lintOperation(op: {
|
|
|
892
833
|
rule: "operation-when-to-use-raw-prose",
|
|
893
834
|
level: "error",
|
|
894
835
|
field: "whenToUse",
|
|
895
|
-
message:
|
|
896
|
-
"Operation whenToUse must use whenToUseKeys instead of raw static prose.",
|
|
836
|
+
message: "Operation whenToUse must use whenToUseKeys instead of raw static prose.",
|
|
897
837
|
});
|
|
898
838
|
}
|
|
899
839
|
|
|
900
|
-
if (
|
|
901
|
-
(op.whenNotToUse?.length ?? 0) > 0 &&
|
|
902
|
-
!(op.whenNotToUseKeys?.length ?? 0)
|
|
903
|
-
) {
|
|
840
|
+
if ((op.whenNotToUse?.length ?? 0) > 0 && !(op.whenNotToUseKeys?.length ?? 0)) {
|
|
904
841
|
diagnostics.push({
|
|
905
842
|
rule: "operation-when-not-to-use-raw-prose",
|
|
906
843
|
level: "error",
|
|
907
844
|
field: "whenNotToUse",
|
|
908
|
-
message:
|
|
909
|
-
"Operation whenNotToUse must use whenNotToUseKeys instead of raw static prose.",
|
|
845
|
+
message: "Operation whenNotToUse must use whenNotToUseKeys instead of raw static prose.",
|
|
910
846
|
});
|
|
911
847
|
}
|
|
912
848
|
|
|
@@ -942,14 +878,11 @@ export function lintOperation(op: {
|
|
|
942
878
|
rule: "complex-input-has-examples",
|
|
943
879
|
level: "warn",
|
|
944
880
|
field: "inputExamples",
|
|
945
|
-
message:
|
|
946
|
-
"Complex input schemas should provide at least 2 input examples.",
|
|
881
|
+
message: "Complex input schemas should provide at least 2 input examples.",
|
|
947
882
|
});
|
|
948
883
|
}
|
|
949
884
|
|
|
950
|
-
for (const field of uniqueFields(
|
|
951
|
-
collectUnmarkedSensitiveFields(op.input, "input"),
|
|
952
|
-
)) {
|
|
885
|
+
for (const field of uniqueFields(collectUnmarkedSensitiveFields(op.input, "input"))) {
|
|
953
886
|
diagnostics.push({
|
|
954
887
|
rule: "sensitive-field-unmarked",
|
|
955
888
|
level: "warn",
|
|
@@ -958,9 +891,7 @@ export function lintOperation(op: {
|
|
|
958
891
|
});
|
|
959
892
|
}
|
|
960
893
|
|
|
961
|
-
for (const field of uniqueFields(
|
|
962
|
-
collectUnmarkedSensitiveFields(op.output, "output"),
|
|
963
|
-
)) {
|
|
894
|
+
for (const field of uniqueFields(collectUnmarkedSensitiveFields(op.output, "output"))) {
|
|
964
895
|
diagnostics.push({
|
|
965
896
|
rule: "sensitive-field-unmarked",
|
|
966
897
|
level: "warn",
|
|
@@ -1044,36 +975,35 @@ export function lintProvider(
|
|
|
1044
975
|
}
|
|
1045
976
|
|
|
1046
977
|
diagnostics.push(
|
|
1047
|
-
...Object.entries(provider.operations).flatMap(
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
})),
|
|
978
|
+
...Object.entries(provider.operations).flatMap(([operationKey, operation]) =>
|
|
979
|
+
[
|
|
980
|
+
...lintOperation({
|
|
981
|
+
description: operation.description ?? "",
|
|
982
|
+
descriptionKey: operation.descriptionKey,
|
|
983
|
+
whenToUse: operation.whenToUse,
|
|
984
|
+
whenToUseKeys: operation.whenToUseKeys,
|
|
985
|
+
whenNotToUse: operation.whenNotToUse,
|
|
986
|
+
whenNotToUseKeys: operation.whenNotToUseKeys,
|
|
987
|
+
input: operation.input,
|
|
988
|
+
output: operation.output,
|
|
989
|
+
fixtures: operation.fixtures,
|
|
990
|
+
inputExamples: operation.inputExamples,
|
|
991
|
+
derivations: operation.derivations,
|
|
992
|
+
}),
|
|
993
|
+
...lintPublicSchemaFieldNames(
|
|
994
|
+
provider.id,
|
|
995
|
+
operationKey,
|
|
996
|
+
operation.input,
|
|
997
|
+
operation.output,
|
|
998
|
+
provider.meta?.contract?.publicSchemaFieldNames === "normalized",
|
|
999
|
+
),
|
|
1000
|
+
].map((diagnostic) => ({
|
|
1001
|
+
...diagnostic,
|
|
1002
|
+
field: diagnostic.field
|
|
1003
|
+
? `operations.${operationKey}.${diagnostic.field}`
|
|
1004
|
+
: `operations.${operationKey}`,
|
|
1005
|
+
message: `[${operationKey}] ${diagnostic.message}`,
|
|
1006
|
+
})),
|
|
1077
1007
|
),
|
|
1078
1008
|
);
|
|
1079
1009
|
|
package/src/provider.ts
CHANGED
|
@@ -3,7 +3,7 @@ export {
|
|
|
3
3
|
credentialsAuthChallenge,
|
|
4
4
|
createAuthFlowHelpers,
|
|
5
5
|
defineCredentialsAuth,
|
|
6
|
-
} from "./auth";
|
|
6
|
+
} from "./auth.js";
|
|
7
7
|
export type {
|
|
8
8
|
CredentialsAuthChallengeDefinition,
|
|
9
9
|
CredentialsAuthChallengeRequest,
|
|
@@ -16,8 +16,8 @@ export type {
|
|
|
16
16
|
CredentialsAuthLoginResult,
|
|
17
17
|
DefineCredentialsAuthOptions,
|
|
18
18
|
DefinedCredentialsAuth,
|
|
19
|
-
} from "./auth";
|
|
20
|
-
export { createFormCeremony } from "./ceremonies";
|
|
19
|
+
} from "./auth.js";
|
|
20
|
+
export { createFormCeremony } from "./ceremonies/index.js";
|
|
21
21
|
export {
|
|
22
22
|
assertFreshProviderChoiceIssuedAt,
|
|
23
23
|
createProviderChoiceToken,
|
|
@@ -25,7 +25,7 @@ export {
|
|
|
25
25
|
type ProviderChoiceTokenErrorReason,
|
|
26
26
|
type ProviderChoiceTokenPayload,
|
|
27
27
|
parseProviderChoiceToken,
|
|
28
|
-
} from "./choice-token";
|
|
28
|
+
} from "./choice-token.js";
|
|
29
29
|
export {
|
|
30
30
|
centered,
|
|
31
31
|
delayed,
|
|
@@ -34,25 +34,28 @@ export {
|
|
|
34
34
|
defineProvider,
|
|
35
35
|
defineSmsOtpMatcher,
|
|
36
36
|
every,
|
|
37
|
-
} from "./define";
|
|
37
|
+
} from "./define.js";
|
|
38
38
|
export {
|
|
39
39
|
AuthError,
|
|
40
|
+
isProviderError,
|
|
41
|
+
isSessionExpiredError,
|
|
42
|
+
isTransportError,
|
|
40
43
|
ProviderError,
|
|
41
44
|
SessionExpiredError,
|
|
42
45
|
TransportError,
|
|
43
46
|
ValidationError,
|
|
44
|
-
} from "./errors";
|
|
47
|
+
} from "./errors.js";
|
|
45
48
|
export {
|
|
46
49
|
getProviderLocalePath,
|
|
47
50
|
providerLocaleKey,
|
|
48
51
|
qualifyProviderLocaleKey,
|
|
49
|
-
} from "./i18n";
|
|
52
|
+
} from "./i18n/index.js";
|
|
50
53
|
export {
|
|
51
54
|
type CreateProviderChoiceContextOptions,
|
|
52
55
|
createProviderChoiceContext,
|
|
53
56
|
createTestProviderChoiceContext,
|
|
54
57
|
PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
55
|
-
} from "./runtime/choice";
|
|
58
|
+
} from "./runtime/choice.js";
|
|
56
59
|
export {
|
|
57
60
|
APIFUSE_DESCRIPTION_KEY_META_KEY,
|
|
58
61
|
APIFUSE_REDACTION_MARKER,
|
|
@@ -69,7 +72,7 @@ export {
|
|
|
69
72
|
type SensitivePath,
|
|
70
73
|
sensitive,
|
|
71
74
|
z,
|
|
72
|
-
} from "./schema";
|
|
75
|
+
} from "./schema.js";
|
|
73
76
|
export type {
|
|
74
77
|
AuthAbortData,
|
|
75
78
|
AuthAbortRetry,
|
|
@@ -112,6 +115,7 @@ export type {
|
|
|
112
115
|
ProviderChoiceParseOptions,
|
|
113
116
|
ProviderContext,
|
|
114
117
|
ProviderDefinition,
|
|
118
|
+
ProviderDeploymentOverrides,
|
|
115
119
|
ProviderLocale,
|
|
116
120
|
ProviderLocaleKey,
|
|
117
121
|
ProviderLocaleKeyInput,
|
|
@@ -130,11 +134,11 @@ export type {
|
|
|
130
134
|
StateNamespaceOptions,
|
|
131
135
|
StateValue,
|
|
132
136
|
StateWriteOptions,
|
|
133
|
-
} from "./types";
|
|
137
|
+
} from "./types.js";
|
|
134
138
|
export {
|
|
135
139
|
HttpRetryAfterPolicy,
|
|
136
140
|
HttpRetryDelayStrategy,
|
|
137
141
|
HttpRetryJitter,
|
|
138
142
|
HttpRetryPreset,
|
|
139
143
|
HttpRetryUnsafeMethodPolicy,
|
|
140
|
-
} from "./types";
|
|
144
|
+
} from "./types.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ZodType } from "zod";
|
|
2
2
|
|
|
3
|
-
import type { LintDiagnostic } from "./lint";
|
|
3
|
+
import type { LintDiagnostic } from "./lint.js";
|
|
4
4
|
|
|
5
5
|
type SchemaLike = ZodType & {
|
|
6
6
|
def?: Record<string, unknown>;
|
|
@@ -55,8 +55,7 @@ function isSchemaRecord(value: unknown): value is Record<string, SchemaLike> {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function getObjectShape(schema: SchemaLike): Record<string, SchemaLike> {
|
|
58
|
-
const rawShape =
|
|
59
|
-
typeof schema.shape === "function" ? schema.shape() : schema.shape;
|
|
58
|
+
const rawShape = typeof schema.shape === "function" ? schema.shape() : schema.shape;
|
|
60
59
|
if (isSchemaRecord(rawShape)) {
|
|
61
60
|
return rawShape;
|
|
62
61
|
}
|
|
@@ -69,10 +68,7 @@ function getObjectShape(schema: SchemaLike): Record<string, SchemaLike> {
|
|
|
69
68
|
return isSchemaRecord(defShape) ? defShape : {};
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
function appendSchemaChildren(
|
|
73
|
-
children: SchemaLike[],
|
|
74
|
-
value: unknown,
|
|
75
|
-
): SchemaLike[] {
|
|
71
|
+
function appendSchemaChildren(children: SchemaLike[], value: unknown): SchemaLike[] {
|
|
76
72
|
if (isSchema(value)) {
|
|
77
73
|
children.push(value);
|
|
78
74
|
return children;
|
|
@@ -183,26 +179,14 @@ function collectPublicSchemaFieldDiagnostics(
|
|
|
183
179
|
});
|
|
184
180
|
}
|
|
185
181
|
diagnostics.push(
|
|
186
|
-
...collectPublicSchemaFieldDiagnostics(
|
|
187
|
-
providerId,
|
|
188
|
-
operationId,
|
|
189
|
-
child,
|
|
190
|
-
fieldPath,
|
|
191
|
-
seen,
|
|
192
|
-
),
|
|
182
|
+
...collectPublicSchemaFieldDiagnostics(providerId, operationId, child, fieldPath, seen),
|
|
193
183
|
);
|
|
194
184
|
}
|
|
195
185
|
|
|
196
186
|
for (const child of getTransparentChildSchemas(schema)) {
|
|
197
187
|
const childPath = schema.element === child ? `${basePath}[]` : basePath;
|
|
198
188
|
diagnostics.push(
|
|
199
|
-
...collectPublicSchemaFieldDiagnostics(
|
|
200
|
-
providerId,
|
|
201
|
-
operationId,
|
|
202
|
-
child,
|
|
203
|
-
childPath,
|
|
204
|
-
seen,
|
|
205
|
-
),
|
|
189
|
+
...collectPublicSchemaFieldDiagnostics(providerId, operationId, child, childPath, seen),
|
|
206
190
|
);
|
|
207
191
|
}
|
|
208
192
|
|
|
@@ -221,17 +205,7 @@ export function lintPublicSchemaFieldNames(
|
|
|
221
205
|
}
|
|
222
206
|
|
|
223
207
|
return [
|
|
224
|
-
...collectPublicSchemaFieldDiagnostics(
|
|
225
|
-
|
|
226
|
-
operationId,
|
|
227
|
-
input,
|
|
228
|
-
"input",
|
|
229
|
-
),
|
|
230
|
-
...collectPublicSchemaFieldDiagnostics(
|
|
231
|
-
providerId,
|
|
232
|
-
operationId,
|
|
233
|
-
output,
|
|
234
|
-
"output",
|
|
235
|
-
),
|
|
208
|
+
...collectPublicSchemaFieldDiagnostics(providerId, operationId, input, "input"),
|
|
209
|
+
...collectPublicSchemaFieldDiagnostics(providerId, operationId, output, "output"),
|
|
236
210
|
];
|
|
237
211
|
}
|
package/src/recipes/gov-api.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { unwrapEnvelope } from "../utils/parse";
|
|
1
|
+
import { unwrapEnvelope } from "../utils/parse.js";
|
|
2
2
|
|
|
3
3
|
function getResultCode(raw: unknown): string | undefined {
|
|
4
4
|
if (!raw || typeof raw !== "object") {
|
|
@@ -33,10 +33,7 @@ export function checkResultCode(
|
|
|
33
33
|
* Replace placeholder values with null
|
|
34
34
|
* e.g., nullIfPlaceholder('해당없음', ['해당없음', '-', '']) → null
|
|
35
35
|
*/
|
|
36
|
-
export function nullIfPlaceholder(
|
|
37
|
-
v: unknown,
|
|
38
|
-
patterns: string[],
|
|
39
|
-
): unknown | null {
|
|
36
|
+
export function nullIfPlaceholder(v: unknown, patterns: string[]): unknown | null {
|
|
40
37
|
if (v === null || v === undefined) {
|
|
41
38
|
return null;
|
|
42
39
|
}
|
package/src/runtime/auth-flow.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ContextAccessError } from "../errors";
|
|
2
|
-
import { createAuthFlowHelpers } from "../auth";
|
|
1
|
+
import { ContextAccessError } from "../errors.js";
|
|
2
|
+
import { createAuthFlowHelpers } from "../auth.js";
|
|
3
3
|
import type {
|
|
4
4
|
ContextScratchpad,
|
|
5
5
|
EnvContext,
|
|
@@ -7,8 +7,8 @@ import type {
|
|
|
7
7
|
HttpClient,
|
|
8
8
|
StealthClient,
|
|
9
9
|
SttContext,
|
|
10
|
-
} from "../types";
|
|
11
|
-
import { createUnsupportedSttClient } from "./stt";
|
|
10
|
+
} from "../types.js";
|
|
11
|
+
import { createUnsupportedSttClient } from "./stt.js";
|
|
12
12
|
|
|
13
13
|
function normalizeAllowedKeys(allowedKeys: string[]): Set<string> {
|
|
14
14
|
return new Set(allowedKeys.filter((key) => key.trim().length > 0));
|
|
@@ -16,9 +16,7 @@ function normalizeAllowedKeys(allowedKeys: string[]): Set<string> {
|
|
|
16
16
|
|
|
17
17
|
function assertAllowedKey(allowedKeys: Set<string>, key: string): void {
|
|
18
18
|
if (!allowedKeys.has(key)) {
|
|
19
|
-
throw new ContextAccessError(
|
|
20
|
-
`Context key "${key}" is not declared in context.keys.`,
|
|
21
|
-
);
|
|
19
|
+
throw new ContextAccessError(`Context key "${key}" is not declared in context.keys.`);
|
|
22
20
|
}
|
|
23
21
|
}
|
|
24
22
|
|