@apifuse/provider-sdk 2.2.0-beta.40 → 2.2.0-beta.41
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/CHANGELOG.md +4 -0
- package/bin/apifuse-check.ts +61 -0
- package/bin/apifuse-migrate-shape.ts +84 -0
- package/bin/apifuse-submit-check.ts +1760 -222
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +8 -0
- package/dist/cli/create.js +6 -0
- package/dist/cli/migrate-provider-shape.d.ts +52 -0
- package/dist/cli/migrate-provider-shape.js +515 -0
- package/dist/cli/templates/provider/provider.json.tpl +6 -0
- package/dist/contract.js +1 -0
- package/dist/define.js +22 -1
- package/dist/error-observability.d.ts +7 -0
- package/dist/error-observability.js +61 -0
- package/dist/errors.d.ts +15 -0
- package/dist/fixture-sanitization.js +13 -3
- package/dist/index.d.ts +1 -1
- package/dist/provider.d.ts +1 -1
- package/dist/runtime/executor.js +11 -1
- package/dist/server/error-observability.d.ts +1 -0
- package/dist/server/error-observability.js +1 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/self-test.js +3 -0
- package/dist/server/serve-implementation.d.ts +12 -0
- package/dist/server/serve-implementation.js +135 -66
- package/dist/types.d.ts +18 -10
- package/package.json +3 -3
- package/src/cli/commands.ts +10 -0
- package/src/cli/create.ts +6 -0
- package/src/cli/migrate-provider-shape.ts +701 -0
- package/src/cli/templates/provider/provider.json.tpl +6 -0
- package/src/contract.ts +1 -0
- package/src/define.ts +33 -1
- package/src/error-observability.ts +64 -0
- package/src/errors.ts +16 -0
- package/src/fixture-sanitization.ts +19 -3
- package/src/index.ts +1 -0
- package/src/provider.ts +1 -0
- package/src/runtime/executor.ts +13 -1
- package/src/server/error-observability.ts +1 -0
- package/src/server/index.ts +2 -0
- package/src/server/self-test.ts +5 -0
- package/src/server/serve-implementation.ts +172 -84
- package/src/types.ts +38 -27
package/CHANGELOG.md
CHANGED
package/bin/apifuse-check.ts
CHANGED
|
@@ -123,6 +123,7 @@ export async function runChecks(
|
|
|
123
123
|
const indexPath = resolve(providerRoot, "index.ts");
|
|
124
124
|
const dockerfilePath = resolve(providerRoot, "Dockerfile");
|
|
125
125
|
const packageJsonPath = resolve(providerRoot, "package.json");
|
|
126
|
+
const providerJsonPath = resolve(providerRoot, "provider.json");
|
|
126
127
|
|
|
127
128
|
let providerModule: Record<string, unknown> | undefined;
|
|
128
129
|
let providerImportError: unknown;
|
|
@@ -150,6 +151,7 @@ export async function runChecks(
|
|
|
150
151
|
checkProviderMetadata(provider),
|
|
151
152
|
checkDockerfile(dockerfilePath),
|
|
152
153
|
checkPackageJson(packageJsonPath),
|
|
154
|
+
checkProviderJson(providerJsonPath, packageJsonPath),
|
|
153
155
|
checkPromptAssets(providerRoot),
|
|
154
156
|
];
|
|
155
157
|
}
|
|
@@ -478,6 +480,65 @@ function checkPackageJson(packageJsonPath: string): CheckResult {
|
|
|
478
480
|
}
|
|
479
481
|
}
|
|
480
482
|
|
|
483
|
+
export const PROVIDER_JSON_CHECK_MESSAGE = "provider.json exists with a valid declaration";
|
|
484
|
+
|
|
485
|
+
const providerDeclarationSchema = z
|
|
486
|
+
.object({
|
|
487
|
+
schemaVersion: z.literal(1),
|
|
488
|
+
providerId: z.string(),
|
|
489
|
+
owner: z.string(),
|
|
490
|
+
lifecycle: z.enum(["draft", "ready", "live", "retired"]),
|
|
491
|
+
})
|
|
492
|
+
.strict();
|
|
493
|
+
|
|
494
|
+
function checkProviderJson(providerJsonPath: string, packageJsonPath: string): CheckResult {
|
|
495
|
+
if (!existsSync(providerJsonPath)) {
|
|
496
|
+
return {
|
|
497
|
+
message: PROVIDER_JSON_CHECK_MESSAGE,
|
|
498
|
+
passed: false,
|
|
499
|
+
details: ["Missing provider.json at the provider root"],
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
try {
|
|
504
|
+
const declaration = providerDeclarationSchema.parse(
|
|
505
|
+
JSON.parse(readFileSync(providerJsonPath, "utf-8")) as unknown,
|
|
506
|
+
);
|
|
507
|
+
const expectedProviderId = readProviderIdFromPackageName(packageJsonPath);
|
|
508
|
+
if (expectedProviderId !== undefined && declaration.providerId !== expectedProviderId) {
|
|
509
|
+
return {
|
|
510
|
+
message: PROVIDER_JSON_CHECK_MESSAGE,
|
|
511
|
+
passed: false,
|
|
512
|
+
details: [
|
|
513
|
+
`provider.json providerId "${declaration.providerId}" does not match package.json name (expected "${expectedProviderId}")`,
|
|
514
|
+
],
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
message: PROVIDER_JSON_CHECK_MESSAGE,
|
|
520
|
+
passed: true,
|
|
521
|
+
details: [`providerId: ${declaration.providerId}`, `lifecycle: ${declaration.lifecycle}`],
|
|
522
|
+
};
|
|
523
|
+
} catch (error) {
|
|
524
|
+
return {
|
|
525
|
+
message: PROVIDER_JSON_CHECK_MESSAGE,
|
|
526
|
+
passed: false,
|
|
527
|
+
details: [error instanceof Error ? error.message : String(error)],
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function readProviderIdFromPackageName(packageJsonPath: string): string | undefined {
|
|
533
|
+
try {
|
|
534
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as unknown;
|
|
535
|
+
if (!isRecord(packageJson) || typeof packageJson.name !== "string") return undefined;
|
|
536
|
+
return /^(?:apifuse-provider-|@apifuse\/provider-)(.+)$/.exec(packageJson.name)?.[1];
|
|
537
|
+
} catch {
|
|
538
|
+
return undefined;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
481
542
|
function assertProviderDefinition(value: unknown): ProviderDefinition | undefined {
|
|
482
543
|
return isProviderDefinition(value) ? value : undefined;
|
|
483
544
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `apifuse migrate-shape [path] [--check] [--json]`
|
|
5
|
+
*
|
|
6
|
+
* Applies the provider authoring-shape migration (single-phase
|
|
7
|
+
* `defineProvider({...operations})` to the two-phase declaration builder) to
|
|
8
|
+
* a provider's `index.ts`. This is the source half of a breaking SDK bump:
|
|
9
|
+
* the pin bump and this transform must land in the same commit, because the
|
|
10
|
+
* single-phase shape default-exports a builder function under 2.2.0-beta.37+
|
|
11
|
+
* and the module stops loading.
|
|
12
|
+
*
|
|
13
|
+
* Exit codes: 0 migrated or already two-phase; 1 skipped (the transform
|
|
14
|
+
* refuses to guess) or the file is missing. `--check` reports without
|
|
15
|
+
* writing. A skip is a hard stop for fan-out callers — never pair a pin bump
|
|
16
|
+
* with a skipped migration.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
20
|
+
import { resolve } from "node:path";
|
|
21
|
+
|
|
22
|
+
import { migrateProviderShape } from "../src/cli/migrate-provider-shape.js";
|
|
23
|
+
|
|
24
|
+
export async function main(): Promise<void> {
|
|
25
|
+
const args = process.argv.slice(3);
|
|
26
|
+
const check = args.includes("--check");
|
|
27
|
+
const json = args.includes("--json");
|
|
28
|
+
const positional = args.filter((argument) => !argument.startsWith("--"));
|
|
29
|
+
const providerRoot = resolve(positional[0] ?? ".");
|
|
30
|
+
const indexPath = resolve(providerRoot, "index.ts");
|
|
31
|
+
|
|
32
|
+
const report = (payload: Record<string, unknown>, humanText: string): void => {
|
|
33
|
+
if (json) {
|
|
34
|
+
console.log(JSON.stringify({ schemaVersion: 1, indexPath, ...payload }));
|
|
35
|
+
} else {
|
|
36
|
+
console.log(humanText);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (!existsSync(indexPath)) {
|
|
41
|
+
report(
|
|
42
|
+
{ status: "skipped", reason: "index.ts not found" },
|
|
43
|
+
`migrate-shape: ${indexPath} not found.`,
|
|
44
|
+
);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const sourceText = readFileSync(indexPath, "utf8");
|
|
49
|
+
const result = migrateProviderShape(sourceText, indexPath);
|
|
50
|
+
|
|
51
|
+
if (result.status === "skipped") {
|
|
52
|
+
report(
|
|
53
|
+
{ status: "skipped", reason: result.reason },
|
|
54
|
+
`migrate-shape: skipped — ${result.reason}\nThis provider needs a manual migration; do not bump its SDK pin without one.`,
|
|
55
|
+
);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (result.status === "unchanged") {
|
|
60
|
+
report(
|
|
61
|
+
{ status: "unchanged" },
|
|
62
|
+
"migrate-shape: already two-phase; nothing to do.",
|
|
63
|
+
);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (check) {
|
|
68
|
+
report(
|
|
69
|
+
{ status: "would-migrate", kind: result.kind },
|
|
70
|
+
`migrate-shape: would migrate (${result.kind}). Run without --check to write.`,
|
|
71
|
+
);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
writeFileSync(indexPath, result.code, "utf8");
|
|
76
|
+
report(
|
|
77
|
+
{ status: "migrated", kind: result.kind },
|
|
78
|
+
`migrate-shape: migrated (${result.kind}). Review the diff, then run \`apifuse check\` and \`bun test\`.`,
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (import.meta.main) {
|
|
83
|
+
await main();
|
|
84
|
+
}
|