@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.
Files changed (44) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/bin/apifuse-check.ts +61 -0
  3. package/bin/apifuse-migrate-shape.ts +84 -0
  4. package/bin/apifuse-submit-check.ts +1760 -222
  5. package/dist/cli/commands.d.ts +1 -1
  6. package/dist/cli/commands.js +8 -0
  7. package/dist/cli/create.js +6 -0
  8. package/dist/cli/migrate-provider-shape.d.ts +52 -0
  9. package/dist/cli/migrate-provider-shape.js +515 -0
  10. package/dist/cli/templates/provider/provider.json.tpl +6 -0
  11. package/dist/contract.js +1 -0
  12. package/dist/define.js +22 -1
  13. package/dist/error-observability.d.ts +7 -0
  14. package/dist/error-observability.js +61 -0
  15. package/dist/errors.d.ts +15 -0
  16. package/dist/fixture-sanitization.js +13 -3
  17. package/dist/index.d.ts +1 -1
  18. package/dist/provider.d.ts +1 -1
  19. package/dist/runtime/executor.js +11 -1
  20. package/dist/server/error-observability.d.ts +1 -0
  21. package/dist/server/error-observability.js +1 -0
  22. package/dist/server/index.d.ts +2 -1
  23. package/dist/server/self-test.js +3 -0
  24. package/dist/server/serve-implementation.d.ts +12 -0
  25. package/dist/server/serve-implementation.js +135 -66
  26. package/dist/types.d.ts +18 -10
  27. package/package.json +3 -3
  28. package/src/cli/commands.ts +10 -0
  29. package/src/cli/create.ts +6 -0
  30. package/src/cli/migrate-provider-shape.ts +701 -0
  31. package/src/cli/templates/provider/provider.json.tpl +6 -0
  32. package/src/contract.ts +1 -0
  33. package/src/define.ts +33 -1
  34. package/src/error-observability.ts +64 -0
  35. package/src/errors.ts +16 -0
  36. package/src/fixture-sanitization.ts +19 -3
  37. package/src/index.ts +1 -0
  38. package/src/provider.ts +1 -0
  39. package/src/runtime/executor.ts +13 -1
  40. package/src/server/error-observability.ts +1 -0
  41. package/src/server/index.ts +2 -0
  42. package/src/server/self-test.ts +5 -0
  43. package/src/server/serve-implementation.ts +172 -84
  44. package/src/types.ts +38 -27
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @apifuse/provider-sdk Changelog
2
2
 
3
+ ## 2.2.0-beta.41
4
+
5
+ - Release candidate for main commit e1bde60e6a9e0424074a357afd9e8af56549080d.
6
+
3
7
  ## 2.2.0-beta.40
4
8
 
5
9
  - Release candidate for main commit 7e2f05a954c23593a77e89e463a9bcbc2cdc7695.
@@ -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
+ }