@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.64

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 (261) hide show
  1. package/AUTHORING.md +367 -9
  2. package/CHANGELOG.md +8 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/bin/apifuse-check.ts +84 -2
  6. package/bin/apifuse-dev.ts +11 -31
  7. package/bin/apifuse-migrate-deployment.ts +200 -0
  8. package/bin/apifuse-pack-check.ts +11 -4
  9. package/bin/apifuse-pack-types.ts +187 -4
  10. package/bin/apifuse-record.ts +44 -32
  11. package/bin/apifuse-submit-check.ts +9 -5
  12. package/bin/apifuse-test.ts +3 -1
  13. package/dist/cli/commands.d.ts +1 -1
  14. package/dist/cli/commands.js +11 -0
  15. package/dist/cli/deployment-intent.d.ts +178 -0
  16. package/dist/cli/deployment-intent.js +277 -0
  17. package/dist/cli/migrate-deployment-intent.d.ts +132 -0
  18. package/dist/cli/migrate-deployment-intent.js +1552 -0
  19. package/dist/cli/migrate-provider-shape.d.ts +5 -1
  20. package/dist/cli/migrate-provider-shape.js +4 -2
  21. package/dist/cli/resolver-runtime.d.ts +21 -0
  22. package/dist/cli/resolver-runtime.js +31 -0
  23. package/dist/define.d.ts +3 -0
  24. package/dist/define.js +5 -0
  25. package/dist/dev.d.ts +3 -1
  26. package/dist/dev.js +6 -1
  27. package/dist/engine.d.ts +35 -1
  28. package/dist/engine.js +21 -2
  29. package/dist/error-resolution.d.ts +1 -0
  30. package/dist/error-resolution.js +54 -0
  31. package/dist/errors.d.ts +39 -1
  32. package/dist/errors.js +50 -0
  33. package/dist/handle-meta.d.ts +36 -1
  34. package/dist/handle-meta.js +16 -0
  35. package/dist/handle.d.ts +23 -5
  36. package/dist/handle.js +54 -8
  37. package/dist/health-scenario.d.ts +38 -0
  38. package/dist/i18n/error-messages.d.ts +86 -0
  39. package/dist/i18n/error-messages.js +192 -0
  40. package/dist/i18n/index.d.ts +1 -0
  41. package/dist/i18n/index.js +1 -0
  42. package/dist/i18n/keys.d.ts +12 -0
  43. package/dist/i18n/keys.js +76 -5
  44. package/dist/index.d.ts +11 -3
  45. package/dist/index.js +9 -1
  46. package/dist/lint.d.ts +15 -0
  47. package/dist/lint.js +469 -82
  48. package/dist/provider.d.ts +6 -6
  49. package/dist/provider.js +3 -3
  50. package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
  51. package/dist/runtime/browser-telemetry-binding.js +83 -0
  52. package/dist/runtime/browser-telemetry.d.ts +76 -0
  53. package/dist/runtime/browser-telemetry.js +165 -0
  54. package/dist/runtime/browser.d.ts +3 -0
  55. package/dist/runtime/browser.js +208 -47
  56. package/dist/runtime/cache-telemetry.d.ts +71 -0
  57. package/dist/runtime/cache-telemetry.js +177 -0
  58. package/dist/runtime/cache.js +67 -7
  59. package/dist/runtime/capability-response.d.ts +3 -0
  60. package/dist/runtime/capability-response.js +56 -0
  61. package/dist/runtime/capability-telemetry.d.ts +46 -0
  62. package/dist/runtime/capability-telemetry.js +68 -0
  63. package/dist/runtime/diagnostic-env.d.ts +3 -0
  64. package/dist/runtime/diagnostic-env.js +10 -1
  65. package/dist/runtime/engine-mode.d.ts +74 -0
  66. package/dist/runtime/engine-mode.js +152 -0
  67. package/dist/runtime/handle.js +9 -1
  68. package/dist/runtime/http-telemetry-guard.d.ts +10 -0
  69. package/dist/runtime/http-telemetry-guard.js +62 -10
  70. package/dist/runtime/http.js +141 -35
  71. package/dist/runtime/instrumentation.js +92 -13
  72. package/dist/runtime/ocr-telemetry.d.ts +82 -0
  73. package/dist/runtime/ocr-telemetry.js +192 -0
  74. package/dist/runtime/ocr.js +35 -8
  75. package/dist/runtime/request-telemetry.d.ts +2 -0
  76. package/dist/runtime/request-telemetry.js +2 -1
  77. package/dist/runtime/resolver-runtime-options.d.ts +14 -0
  78. package/dist/runtime/resolver-runtime-options.js +33 -0
  79. package/dist/runtime/resolver-shared.d.ts +3 -2
  80. package/dist/runtime/resolver-shared.js +4 -4
  81. package/dist/runtime/resolver-telemetry.d.ts +1 -0
  82. package/dist/runtime/resolver-telemetry.js +1 -1
  83. package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
  84. package/dist/runtime/resolver-vendors/browser.js +46 -0
  85. package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
  86. package/dist/runtime/resolver-vendors/hosts.js +35 -0
  87. package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
  88. package/dist/runtime/resolver-vendors/types.d.ts +5 -4
  89. package/dist/runtime/resolver.d.ts +4 -1
  90. package/dist/runtime/resolver.js +46 -13
  91. package/dist/runtime/state-telemetry.d.ts +79 -0
  92. package/dist/runtime/state-telemetry.js +194 -0
  93. package/dist/runtime/state.d.ts +3 -0
  94. package/dist/runtime/state.js +26 -7
  95. package/dist/runtime/stealth-cookies.d.ts +5 -1
  96. package/dist/runtime/stealth-cookies.js +21 -1
  97. package/dist/runtime/stealth-owned-headers.d.ts +26 -0
  98. package/dist/runtime/stealth-owned-headers.js +37 -0
  99. package/dist/runtime/stealth-telemetry.d.ts +92 -0
  100. package/dist/runtime/stealth-telemetry.js +179 -0
  101. package/dist/runtime/stealth.d.ts +4 -1
  102. package/dist/runtime/stealth.js +228 -85
  103. package/dist/runtime/stt-telemetry.d.ts +77 -0
  104. package/dist/runtime/stt-telemetry.js +176 -0
  105. package/dist/runtime/stt.js +15 -6
  106. package/dist/runtime-boundary-lint.d.ts +132 -0
  107. package/dist/runtime-boundary-lint.js +586 -0
  108. package/dist/server/error-stack-frames.d.ts +35 -0
  109. package/dist/server/error-stack-frames.js +219 -0
  110. package/dist/server/index.d.ts +7 -0
  111. package/dist/server/index.js +4 -0
  112. package/dist/server/sdk-version.d.ts +3 -0
  113. package/dist/server/sdk-version.js +19 -0
  114. package/dist/server/self-test.js +1 -18
  115. package/dist/server/sensitive-values.d.ts +1 -1
  116. package/dist/server/sensitive-values.js +9 -0
  117. package/dist/server/serve-implementation.d.ts +51 -2
  118. package/dist/server/serve-implementation.js +337 -90
  119. package/dist/server/types.d.ts +1 -0
  120. package/dist/server/types.js +7 -0
  121. package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
  122. package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
  123. package/dist/stateful/stateful-provider-runtime-context.js +1 -0
  124. package/dist/types.d.ts +123 -1
  125. package/dist/typescript-module.d.ts +39 -0
  126. package/dist/typescript-module.js +72 -0
  127. package/package.json +6 -1
  128. package/src/cli/commands.ts +14 -0
  129. package/src/cli/deployment-intent.ts +364 -0
  130. package/src/cli/migrate-deployment-intent.ts +1908 -0
  131. package/src/cli/migrate-provider-shape.ts +10 -4
  132. package/src/cli/resolver-runtime.ts +72 -0
  133. package/src/define.ts +13 -0
  134. package/src/dev.ts +9 -2
  135. package/src/engine.ts +38 -2
  136. package/src/error-resolution.ts +58 -0
  137. package/src/errors.ts +77 -1
  138. package/src/handle-meta.ts +51 -1
  139. package/src/handle.ts +92 -10
  140. package/src/health-scenario.ts +38 -0
  141. package/src/i18n/error-messages.ts +255 -0
  142. package/src/i18n/index.ts +1 -0
  143. package/src/i18n/keys.ts +80 -6
  144. package/src/index.ts +86 -0
  145. package/src/lint.ts +604 -91
  146. package/src/provider.ts +12 -0
  147. package/src/runtime/browser-telemetry-binding.ts +92 -0
  148. package/src/runtime/browser-telemetry.ts +289 -0
  149. package/src/runtime/browser.ts +249 -65
  150. package/src/runtime/cache-telemetry.ts +247 -0
  151. package/src/runtime/cache.ts +68 -17
  152. package/src/runtime/capability-response.ts +53 -0
  153. package/src/runtime/capability-telemetry.ts +101 -0
  154. package/src/runtime/diagnostic-env.ts +11 -1
  155. package/src/runtime/engine-mode.ts +233 -0
  156. package/src/runtime/handle.ts +9 -1
  157. package/src/runtime/http-telemetry-guard.ts +66 -13
  158. package/src/runtime/http.ts +168 -37
  159. package/src/runtime/instrumentation.ts +105 -16
  160. package/src/runtime/ocr-telemetry.ts +308 -0
  161. package/src/runtime/ocr.ts +114 -74
  162. package/src/runtime/request-telemetry.ts +2 -1
  163. package/src/runtime/resolver-runtime-options.ts +50 -0
  164. package/src/runtime/resolver-shared.ts +9 -4
  165. package/src/runtime/resolver-telemetry.ts +1 -1
  166. package/src/runtime/resolver-vendors/browser.ts +65 -7
  167. package/src/runtime/resolver-vendors/hosts.ts +43 -0
  168. package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
  169. package/src/runtime/resolver-vendors/types.ts +5 -4
  170. package/src/runtime/resolver.ts +64 -21
  171. package/src/runtime/state-telemetry.ts +298 -0
  172. package/src/runtime/state.ts +46 -45
  173. package/src/runtime/stealth-cookies.ts +24 -1
  174. package/src/runtime/stealth-owned-headers.ts +41 -0
  175. package/src/runtime/stealth-telemetry.ts +304 -0
  176. package/src/runtime/stealth.ts +355 -150
  177. package/src/runtime/stt-telemetry.ts +282 -0
  178. package/src/runtime/stt.ts +93 -71
  179. package/src/runtime-boundary-lint.ts +703 -0
  180. package/src/server/error-stack-frames.ts +214 -0
  181. package/src/server/index.ts +53 -0
  182. package/src/server/sdk-version.ts +22 -0
  183. package/src/server/self-test.ts +1 -21
  184. package/src/server/sensitive-values.ts +14 -0
  185. package/src/server/serve-implementation.ts +569 -108
  186. package/src/server/types.ts +7 -0
  187. package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
  188. package/src/stateful/stateful-provider-runtime-context.ts +4 -0
  189. package/src/types.ts +128 -1
  190. package/src/typescript-module.ts +100 -0
  191. package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
  192. package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
  193. package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
  194. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
  195. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
  196. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
  197. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
  198. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
  199. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
  200. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
  201. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
  202. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
  203. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
  204. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
  205. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
  206. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
  207. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
  208. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
  209. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
  210. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
  211. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
  212. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
  213. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
  214. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
  215. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
  216. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
  217. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
  218. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
  219. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
  220. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
  221. package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
  222. package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
  223. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
  224. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
  225. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
  226. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
  227. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
  228. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
  229. package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
  230. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
  231. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
  232. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
  233. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
  234. package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
  235. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
  236. package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
  237. package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
  238. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
  239. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
  240. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
  241. package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
  242. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
  243. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
  244. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
  245. package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
  246. package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
  247. package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
  248. package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
  249. package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
  250. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
  251. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
  252. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
  253. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
  254. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
  255. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
  256. package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
  257. package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
  258. package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
  259. package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
  260. package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
  261. package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
@@ -11,20 +11,18 @@ import {
11
11
  createProviderCache,
12
12
  createHandleContext,
13
13
  createProviderEnvironment,
14
- createUnsupportedResolverClient,
15
14
  createSttClientFromEnv,
16
- readEngineProxyCredentials,
17
15
  type ProviderDefinition,
18
16
  type ProviderEngineBindingCandidates,
19
17
  ProviderError,
20
- type ProviderProxyPolicy,
21
18
  } from "../src/index.js";
19
+ import { createCliResolverRuntime } from "../src/cli/resolver-runtime.js";
20
+ import { assertProcessEngineModeSupported } from "../src/runtime/engine-mode.js";
22
21
  import { createBrowserClient } from "../src/runtime/browser.js";
23
- import { createResolverClientFromEnv } from "../src/runtime/resolver.js";
24
22
  import { createMemoryProviderRuntimeState } from "../src/runtime/state.js";
25
23
  import { createStealthClient } from "../src/runtime/stealth.js";
24
+ import type { ResolverTelemetryCollector } from "../src/runtime/resolver-telemetry.js";
26
25
  import { createTraceContext } from "../src/runtime/trace.js";
27
- import { getStealthProfile } from "../src/stealth/profiles.js";
28
26
  import type { BrowserClient, ProviderContext } from "../src/types.js";
29
27
 
30
28
  const HELP_TEXT = `Usage: apifuse dev [path]
@@ -43,6 +41,9 @@ export async function main() {
43
41
  const providerModule = await import(resolve(providerPath, "index.ts"));
44
42
  const provider = assertProviderDefinition(providerModule.default, providerPath);
45
43
 
44
+ // Fail fast before the server starts: this is a developer tool, and an
45
+ // explicit remote request must never silently fall back to in-process.
46
+ assertProcessEngineModeSupported();
46
47
  const { startDevServer } = await import("../src/dev.js");
47
48
  const port = Number(process.env.APIFUSE__RUNTIME__PORT) || 3900;
48
49
 
@@ -50,6 +51,7 @@ export async function main() {
50
51
 
51
52
  console.log("\nEndpoints:");
52
53
  console.log(` GET http://localhost:${port}/health`);
54
+ console.log(` GET http://localhost:${port}/readyz`);
53
55
 
54
56
  for (const operationId of Object.keys(provider.operations)) {
55
57
  console.log(` POST http://localhost:${port}/v1/${operationId}`);
@@ -81,18 +83,17 @@ export async function main() {
81
83
 
82
84
  export function createProviderContext(provider: ProviderDefinition): {
83
85
  ctx: ProviderContext;
86
+ resolverTelemetry: ResolverTelemetryCollector;
84
87
  } {
85
88
  const providerEnvironment = createProviderEnvironment(
86
89
  process.env,
87
90
  provider.secrets?.map((secret) => secret.name) ?? [],
88
91
  );
89
92
  const providerEnv = { get: (key: string) => readDiagnosticEnv(key, providerEnvironment) };
90
- const engineCredentials = readEngineProxyCredentials();
91
93
  const credential = createCredentialContext();
92
94
  const state = createMemoryProviderRuntimeState();
93
95
  const cache = createProviderCache({ providerId: provider.id });
94
- const proxyPolicy = resolveNativeProxyPolicy(provider);
95
- const stealthProfile = provider.stealth ? getStealthProfile(provider.stealth) : undefined;
96
+ const { resolver, resolverTelemetry } = createCliResolverRuntime(provider, cache);
96
97
  const candidates: ProviderEngineBindingCandidates = {
97
98
  env: providerEnv,
98
99
  credential,
@@ -113,21 +114,7 @@ export function createProviderContext(provider: ProviderDefinition): {
113
114
  }),
114
115
  ocr: createOcrClientFromEnv(provider.ocr),
115
116
  stt: createSttClientFromEnv(provider.stt),
116
- resolver: provider.resolver
117
- ? createResolverClientFromEnv(provider.resolver, engineCredentials, {
118
- allowedHosts: provider.allowedHosts,
119
- cache,
120
- ...(proxyPolicy
121
- ? {
122
- proxyIntent: {
123
- mode: proxyPolicy.mode,
124
- upstream: { proxy: provider.proxy },
125
- ...(stealthProfile ? { userAgent: stealthProfile.userAgent } : {}),
126
- },
127
- }
128
- : {}),
129
- })
130
- : createUnsupportedResolverClient("Provider does not declare resolver capability"),
117
+ resolver,
131
118
  handle: createHandleContext({
132
119
  providerId: provider.id,
133
120
  // Local dev is a single-user session: one stable connection scope so
@@ -141,14 +128,7 @@ export function createProviderContext(provider: ProviderDefinition): {
141
128
  bindings: candidates,
142
129
  }) as ProviderContext;
143
130
 
144
- return { ctx };
145
- }
146
-
147
- function resolveNativeProxyPolicy(provider: ProviderDefinition): ProviderProxyPolicy | undefined {
148
- if (typeof provider.proxy === "object") return provider.proxy;
149
- if (provider.proxy === true) return { mode: "optional" };
150
- if (provider.proxy === false) return { mode: "disabled" };
151
- return undefined;
131
+ return { ctx, resolverTelemetry };
152
132
  }
153
133
 
154
134
  function normalizeArgs(argv: string[]): string[] {
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * `apifuse migrate-deployment [path] [--check] [--json] [--drop-codeowners-lock]`
5
+ *
6
+ * Retires a provider repository's standalone `deploy.ts`. Deployment intent
7
+ * has one home — the `deployment` key on `defineProvider({...})` — and only
8
+ * the fields that differ from the runtime profile are written there. The
9
+ * command:
10
+ *
11
+ * 1. reads `deploy.ts`, subtracts the profile defaults, and proves the
12
+ * resulting key resolves to exactly what the file declared;
13
+ * 2. writes the key into the declaration literal (after `runtime`), removes
14
+ * a `deployment` extra from a `{ ...provider, deployment }` default export
15
+ * and any `import ... from "./deploy"`;
16
+ * 3. deletes `deploy.ts` — after checking that no other repository source
17
+ * (tests included) imports the module. The `.github/CODEOWNERS`
18
+ * `/deploy.ts` lock stays unless `--drop-codeowners-lock` is passed: the
19
+ * platform still honors a re-added legacy file until its fallback is
20
+ * retired.
21
+ *
22
+ * Exit codes: 0 migrated or already migrated; 1 refused (the transform does
23
+ * not guess — a refusal names the manual step) or missing index.ts.
24
+ * `--check` reports without writing.
25
+ */
26
+
27
+ import { existsSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
28
+ import { join, relative, resolve } from "node:path";
29
+
30
+ import type * as MigrateModule from "../src/cli/migrate-deployment-intent.js";
31
+
32
+ /** Directories never scanned for deploy-module consumers. */
33
+ const SKIPPED_DIRECTORIES = new Set([
34
+ "node_modules",
35
+ ".git",
36
+ "dist",
37
+ "build",
38
+ "coverage",
39
+ ".turbo",
40
+ "__generated__",
41
+ ]);
42
+ const SOURCE_FILE = /\.(?:[cm]?[jt]s|[jt]sx)$/u;
43
+
44
+ export const LEGACY_DEPLOY_FILE = "deploy.ts";
45
+ export const CODEOWNERS_FILE = ".github/CODEOWNERS";
46
+
47
+ export async function main(): Promise<void> {
48
+ // The transform needs the TypeScript compiler; load it here so a missing
49
+ // devDependency is a one-line report instead of an import stack trace.
50
+ let migrateDeploymentIntent: typeof MigrateModule.migrateDeploymentIntent;
51
+ let findDeployModuleConsumers: typeof MigrateModule.findDeployModuleConsumers;
52
+ try {
53
+ ({ migrateDeploymentIntent, findDeployModuleConsumers } = await import(
54
+ "../src/cli/migrate-deployment-intent.js"
55
+ ));
56
+ } catch (error) {
57
+ console.error(error instanceof Error ? error.message : String(error));
58
+ process.exit(1);
59
+ }
60
+ const args = normalizeArgs(process.argv.slice(2));
61
+ const check = args.includes("--check");
62
+ const json = args.includes("--json");
63
+ const dropCodeownersLock = args.includes("--drop-codeowners-lock");
64
+ const positional = args.filter((argument) => !argument.startsWith("--"));
65
+ const providerRoot = resolve(positional[0] ?? ".");
66
+ const indexPath = resolve(providerRoot, "index.ts");
67
+ const deployPath = resolve(providerRoot, LEGACY_DEPLOY_FILE);
68
+ const codeownersPath = resolve(providerRoot, CODEOWNERS_FILE);
69
+
70
+ const report = (payload: Record<string, unknown>, humanText: string): void => {
71
+ if (json) {
72
+ console.log(JSON.stringify({ schemaVersion: 1, providerRoot, ...payload }));
73
+ } else {
74
+ console.log(humanText);
75
+ }
76
+ };
77
+
78
+ if (!existsSync(indexPath)) {
79
+ report(
80
+ { status: "refused", reason: "index.ts not found" },
81
+ `migrate-deployment: ${indexPath} not found.`,
82
+ );
83
+ process.exit(1);
84
+ }
85
+
86
+ const deploySource = existsSync(deployPath) ? readFileSync(deployPath, "utf8") : undefined;
87
+ const codeownersSource = existsSync(codeownersPath)
88
+ ? readFileSync(codeownersPath, "utf8")
89
+ : undefined;
90
+ const result = migrateDeploymentIntent({
91
+ indexSource: readFileSync(indexPath, "utf8"),
92
+ deploySource,
93
+ codeownersSource,
94
+ dropCodeownersLock,
95
+ indexFileName: indexPath,
96
+ });
97
+
98
+ if (result.status === "refused") {
99
+ report(
100
+ { status: "refused", reason: result.reason },
101
+ `migrate-deployment: refused — ${result.reason}\nThis provider needs a manual migration; do not delete deploy.ts without one.`,
102
+ );
103
+ process.exit(1);
104
+ }
105
+
106
+ if (result.status === "unchanged") {
107
+ report(
108
+ { status: "unchanged", notes: result.notes },
109
+ `migrate-deployment: already migrated; nothing to do.${formatNotes(result.notes)}`,
110
+ );
111
+ return;
112
+ }
113
+
114
+ if (result.removeDeployFile) {
115
+ // index.ts is accounted for by the transform; any other source that
116
+ // imports the module (a test, a helper) would break when it is deleted.
117
+ const consumers = findDeployModuleConsumers(
118
+ providerRoot,
119
+ collectOtherSources(providerRoot, [indexPath, deployPath]),
120
+ );
121
+ if (consumers.length > 0) {
122
+ const reason = `deploy.ts is still imported by ${consumers.join(", ")}; remove or rewrite those imports before migrating.`;
123
+ report(
124
+ { status: "refused", reason },
125
+ `migrate-deployment: refused — ${reason}\nThis provider needs a manual migration; do not delete deploy.ts without one.`,
126
+ );
127
+ process.exit(1);
128
+ }
129
+ }
130
+
131
+ const touchedPaths: string[] = [];
132
+ if (result.indexChanged) touchedPaths.push("index.ts");
133
+ if (result.removeDeployFile) touchedPaths.push(LEGACY_DEPLOY_FILE);
134
+ if (result.codeownersChanged) touchedPaths.push(CODEOWNERS_FILE);
135
+ const payload = {
136
+ shape: result.shape,
137
+ legacy: result.legacy,
138
+ intent: result.intent,
139
+ resolved: result.resolved,
140
+ resolvedEqual: result.legacy === undefined ? undefined : true,
141
+ touchedPaths,
142
+ notes: result.notes,
143
+ };
144
+ const intentSummary =
145
+ Object.keys(result.intent).length === 0
146
+ ? "profile defaults (no deployment key)"
147
+ : `deployment: ${JSON.stringify(result.intent)}`;
148
+
149
+ if (check) {
150
+ report(
151
+ { status: "would-migrate", ...payload },
152
+ `migrate-deployment: would migrate (${intentSummary}; touches ${touchedPaths.join(", ")}). Run without --check to write.${formatNotes(result.notes)}`,
153
+ );
154
+ return;
155
+ }
156
+
157
+ if (result.indexChanged) writeFileSync(indexPath, result.indexSource, "utf8");
158
+ if (result.codeownersChanged && result.codeownersSource !== undefined) {
159
+ writeFileSync(codeownersPath, result.codeownersSource, "utf8");
160
+ }
161
+ if (result.removeDeployFile) rmSync(deployPath, { force: true });
162
+ report(
163
+ { status: "migrated", ...payload },
164
+ `migrate-deployment: migrated (${intentSummary}; touched ${touchedPaths.join(", ")}). Review the diff, then run \`apifuse check\` and \`bun run type-check\`.${formatNotes(result.notes)}`,
165
+ );
166
+ }
167
+
168
+ function normalizeArgs(argv: string[]): string[] {
169
+ return argv[0] === "migrate-deployment" ? argv.slice(1) : argv;
170
+ }
171
+
172
+ /** Every source file under `providerRoot` except `excluded`, with text. */
173
+ function collectOtherSources(
174
+ providerRoot: string,
175
+ excluded: readonly string[],
176
+ ): { readonly path: string; readonly text: string }[] {
177
+ const skip = new Set(excluded.map((file) => resolve(file)));
178
+ const files: { readonly path: string; readonly text: string }[] = [];
179
+ const walk = (directory: string): void => {
180
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
181
+ const absolute = join(directory, entry.name);
182
+ if (entry.isDirectory()) {
183
+ if (!SKIPPED_DIRECTORIES.has(entry.name)) walk(absolute);
184
+ continue;
185
+ }
186
+ if (!entry.isFile() || !SOURCE_FILE.test(entry.name) || skip.has(resolve(absolute))) continue;
187
+ files.push({ path: relative(providerRoot, absolute), text: readFileSync(absolute, "utf8") });
188
+ }
189
+ };
190
+ walk(providerRoot);
191
+ return files;
192
+ }
193
+
194
+ function formatNotes(notes: readonly string[]): string {
195
+ return notes.length === 0 ? "" : `\n${notes.map((note) => ` - ${note}`).join("\n")}`;
196
+ }
197
+
198
+ if (import.meta.main) {
199
+ await main();
200
+ }
@@ -82,11 +82,18 @@ const requiredPaths = [
82
82
  "dist/auth-turn/fixtures/invalid/unknown-top-level-field.json",
83
83
  "src/auth-turn/auth-turn.v1.schema.json",
84
84
  ];
85
+ // Test material must never reach the published tarball: it carries no consumer
86
+ // value and the `.deploy.ts.txt` codemod fixtures describe internal provider
87
+ // deployment intent. The `files` negations in package.json do the excluding;
88
+ // these patterns are the ratchet that fails the build when a new test directory
89
+ // escapes them (top-level negations do not cover nested `__tests__`).
90
+ const isPackagedTestMaterial = (path: string): boolean =>
91
+ path.startsWith("__tests__/") ||
92
+ path.includes("/__tests__/") ||
93
+ path.endsWith(".test.ts") ||
94
+ path.endsWith(".spec.ts");
85
95
  const forbiddenMatches = filePaths.filter(
86
- (path) =>
87
- path.startsWith("src/__tests__/") ||
88
- path === "src/index.test.ts" ||
89
- path === "bin/apifuse-init.ts",
96
+ (path) => isPackagedTestMaterial(path) || path === "bin/apifuse-init.ts",
90
97
  );
91
98
  const missingRequiredPaths = requiredPaths.filter(
92
99
  (path) => !filePaths.includes(path),
@@ -22,7 +22,7 @@
22
22
  // type errors, so this check cannot rot into a false-positive green.
23
23
 
24
24
  import { execFileSync, spawnSync } from "node:child_process";
25
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
25
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
26
26
  import { tmpdir } from "node:os";
27
27
  import { join, resolve } from "node:path";
28
28
  import { z } from "zod";
@@ -293,14 +293,14 @@ const NEGATIVE_CONTROLS = [
293
293
  ].join("\n"),
294
294
  },
295
295
  {
296
- filename: "negative-control-telemetry-header-vendor.ts",
296
+ filename: "negative-control-proxy-telemetry-vendor.ts",
297
297
  expectedCode: "TS2322",
298
- description: "gateway telemetry headers reject an unbranded vendor string",
298
+ description: "proxy gateway telemetry rejects an unbranded vendor string",
299
299
  source: [
300
300
  'import type { TelemetryContributor } from "@apifuse/provider-sdk";',
301
301
  "",
302
302
  "const bad: TelemetryContributor<{}, { vendor: string }> = {",
303
- '\tkey: "resolver",',
303
+ '\tkey: "proxy",',
304
304
  "\ttoLogPayload: () => ({}),",
305
305
  '\ttoHeaderPayload: () => ({ vendor: "free-text" }),',
306
306
  "};",
@@ -450,6 +450,28 @@ const NEGATIVE_CONTROLS = [
450
450
  "",
451
451
  ].join("\n"),
452
452
  },
453
+ {
454
+ filename: "negative-control-native-telemetry-description.ts",
455
+ expectedCode: "TS2322",
456
+ description: "native gateway telemetry rejects free-string diagnostic fields",
457
+ source: [
458
+ 'import type { GatewayIngestible, NativeTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
459
+ "type UnsafeHeader = NativeTelemetryHeaderPayload & { vendorErrorMessage: string };",
460
+ "declare const header: NativeTelemetryHeaderPayload;",
461
+ 'export const mustNotCompile: GatewayIngestible<UnsafeHeader> = { ...header, vendorErrorMessage: "free text stays log-only" };',
462
+ ].join("\n"),
463
+ },
464
+ {
465
+ filename: "positive-control-native-telemetry-contributor.ts",
466
+ expectedCode: "",
467
+ description: "native telemetry contributor satisfies the gateway-ingestible contract",
468
+ source: [
469
+ 'import { NativeTelemetryCollector, type GatewayIngestible, type NativeTelemetryHeaderPayload, type NativeTelemetryLogPayload, type TelemetryContributor } from "@apifuse/provider-sdk";',
470
+ "export const native: TelemetryContributor<NativeTelemetryLogPayload, NativeTelemetryHeaderPayload> = new NativeTelemetryCollector();",
471
+ "declare const header: NativeTelemetryHeaderPayload;",
472
+ "export const ingestible: GatewayIngestible<NativeTelemetryHeaderPayload> = header;",
473
+ ].join("\n"),
474
+ },
453
475
  {
454
476
  filename: "negative-control-http-telemetry-free-text.ts",
455
477
  expectedCode: "TS2322",
@@ -476,8 +498,169 @@ const NEGATIVE_CONTROLS = [
476
498
  "",
477
499
  ].join("\n"),
478
500
  },
501
+ {
502
+ filename: "negative-control-stealth-telemetry-diagnostics.ts",
503
+ expectedCode: "TS2322",
504
+ description: "stealth gateway telemetry rejects a free-string header field",
505
+ source: [
506
+ 'import { type GatewayIngestible, type StealthTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
507
+ "type UnsafeHeader = StealthTelemetryHeaderPayload & { diagnostics: string };",
508
+ "declare const unsafeHeader: UnsafeHeader;",
509
+ "export const mustNotCompile: GatewayIngestible<UnsafeHeader> = unsafeHeader;",
510
+ "",
511
+ ].join("\n"),
512
+ },
513
+ {
514
+ filename: "positive-control-stealth-telemetry-contributor.ts",
515
+ expectedCode: "",
516
+ description: "stealth telemetry contributor satisfies the gateway-ingestible contract",
517
+ source: [
518
+ 'import { StealthTelemetryCollector, type GatewayIngestible, type StealthTelemetryHeaderPayload, type StealthTelemetryLogPayload, type TelemetryContributor } from "@apifuse/provider-sdk";',
519
+ "",
520
+ "export const stealth: TelemetryContributor<StealthTelemetryLogPayload, StealthTelemetryHeaderPayload> = new StealthTelemetryCollector();",
521
+ "declare const header: StealthTelemetryHeaderPayload;",
522
+ "export const ingestible: GatewayIngestible<StealthTelemetryHeaderPayload> = header;",
523
+ "",
524
+ ].join("\n"),
525
+ },
526
+ {
527
+ filename: "negative-control-ocr-telemetry-free-text.ts",
528
+ expectedCode: "TS2322",
529
+ description: "ocr gateway telemetry rejects a free-string field",
530
+ source: [
531
+ 'import type { GatewayIngestible, OcrTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
532
+ "type Unsafe = OcrTelemetryHeaderPayload & { message: string };",
533
+ "declare const value: Unsafe;",
534
+ "export const bad: GatewayIngestible<Unsafe> = value;",
535
+ ].join("\n"),
536
+ },
537
+ {
538
+ filename: "positive-control-ocr-telemetry-contributor.ts",
539
+ expectedCode: "",
540
+ description: "ocr telemetry contributor satisfies the gateway-ingestible contract",
541
+ source: [
542
+ 'import { OcrTelemetryCollector, type TelemetryContributor, type OcrTelemetryLogPayload, type OcrTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
543
+ "export const ocr: TelemetryContributor<OcrTelemetryLogPayload, OcrTelemetryHeaderPayload> = new OcrTelemetryCollector();",
544
+ ].join("\n"),
545
+ },
546
+ {
547
+ filename: "negative-control-stt-telemetry-free-text.ts",
548
+ expectedCode: "TS2322",
549
+ description: "stt gateway telemetry rejects a free-string field",
550
+ source: [
551
+ 'import type { GatewayIngestible, SttTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
552
+ "type Unsafe = SttTelemetryHeaderPayload & { message: string };",
553
+ "declare const value: Unsafe;",
554
+ "export const bad: GatewayIngestible<Unsafe> = value;",
555
+ ].join("\n"),
556
+ },
557
+ {
558
+ filename: "positive-control-stt-telemetry-contributor.ts",
559
+ expectedCode: "",
560
+ description: "stt telemetry contributor satisfies the gateway-ingestible contract",
561
+ source: [
562
+ 'import { SttTelemetryCollector, type TelemetryContributor, type SttTelemetryLogPayload, type SttTelemetryHeaderPayload } from "@apifuse/provider-sdk";',
563
+ "export const stt: TelemetryContributor<SttTelemetryLogPayload, SttTelemetryHeaderPayload> = new SttTelemetryCollector();",
564
+ ].join("\n"),
565
+ },
566
+ {
567
+ filename: "negative-control-browser-telemetry-free-text.ts",
568
+ expectedCode: "TS2322",
569
+ description: "browser gateway telemetry rejects a free-string field",
570
+ source: [
571
+ 'import type { BrowserTelemetryHeaderPayload, GatewayIngestible } from "@apifuse/provider-sdk";',
572
+ "declare const header: BrowserTelemetryHeaderPayload;",
573
+ "type Unsafe = BrowserTelemetryHeaderPayload & { message: string };",
574
+ 'export const bad: GatewayIngestible<Unsafe> = { ...header, message: "free text" };',
575
+ ].join("\n"),
576
+ },
577
+ {
578
+ filename: "positive-control-browser-telemetry-contributor.ts",
579
+ expectedCode: "",
580
+ description: "browser telemetry contributor satisfies the gateway-ingestible contract",
581
+ source: [
582
+ 'import { BrowserTelemetryCollector, type BrowserTelemetryHeaderPayload, type BrowserTelemetryLogPayload, type TelemetryContributor } from "@apifuse/provider-sdk";',
583
+ "export const browser: TelemetryContributor<BrowserTelemetryLogPayload, BrowserTelemetryHeaderPayload> = new BrowserTelemetryCollector();",
584
+ ].join("\n"),
585
+ },
586
+ {
587
+ filename: "negative-control-cache-telemetry-free-text.ts",
588
+ expectedCode: "TS2322",
589
+ description: "cache gateway telemetry rejects raw cache-key samples",
590
+ source: [
591
+ 'import type { TelemetryContributor } from "@apifuse/provider-sdk";',
592
+ "const bad: TelemetryContributor<{}, { key: string }> = {",
593
+ '\tkey: "cache",',
594
+ "\ttoLogPayload: () => ({}),",
595
+ '\ttoHeaderPayload: () => ({ key: "raw" }),',
596
+ "};",
597
+ ].join("\n"),
598
+ },
599
+ {
600
+ filename: "positive-control-cache-telemetry-contributor.ts",
601
+ expectedCode: "",
602
+ description: "cache telemetry contributor satisfies the public contributor contract",
603
+ source: [
604
+ 'import { CacheTelemetryCollector, type TelemetryContributor, type CacheTelemetryHeaderPayload, type CacheTelemetryLogPayload } from "@apifuse/provider-sdk";',
605
+ "export const cache: TelemetryContributor<CacheTelemetryLogPayload, CacheTelemetryHeaderPayload> = new CacheTelemetryCollector();",
606
+ ].join("\n"),
607
+ },
608
+ {
609
+ filename: "negative-control-state-telemetry-free-text.ts",
610
+ expectedCode: "TS2322",
611
+ description: "state gateway telemetry rejects raw state-key samples",
612
+ source: [
613
+ 'import type { TelemetryContributor } from "@apifuse/provider-sdk";',
614
+ "const bad: TelemetryContributor<{}, { key: string }> = {",
615
+ '\tkey: "state",',
616
+ "\ttoLogPayload: () => ({}),",
617
+ '\ttoHeaderPayload: () => ({ key: "raw" }),',
618
+ "};",
619
+ ].join("\n"),
620
+ },
621
+ {
622
+ filename: "positive-control-state-telemetry-contributor.ts",
623
+ expectedCode: "",
624
+ description: "state telemetry contributor satisfies the public contributor contract",
625
+ source: [
626
+ 'import { StateTelemetryCollector, type TelemetryContributor, type StateTelemetryHeaderPayload, type StateTelemetryLogPayload } from "@apifuse/provider-sdk";',
627
+ "export const state: TelemetryContributor<StateTelemetryLogPayload, StateTelemetryHeaderPayload> = new StateTelemetryCollector();",
628
+ ].join("\n"),
629
+ },
479
630
  ] as const;
480
631
 
632
+ assertTelemetryContributorControls();
633
+
634
+ function assertTelemetryContributorControls(): void {
635
+ const requestTelemetry = readFileSync(join(sdkRoot, "src/runtime/request-telemetry.ts"), "utf8");
636
+ const priorityMatch = requestTelemetry.match(
637
+ /const HEADER_PRIORITY = \[([\s\S]*?)\] as const satisfies/,
638
+ );
639
+ if (!priorityMatch) throw new Error("Could not read request telemetry header priority list");
640
+
641
+ const priority = [...priorityMatch[1].matchAll(/"([a-z]+)"/g)].map((match) => match[1]);
642
+ const shipped = priority.filter((name) =>
643
+ existsSync(join(sdkRoot, "src/runtime", `${name}-telemetry.ts`)),
644
+ );
645
+ const missing: string[] = [];
646
+ for (const name of shipped) {
647
+ const hasPositive = NEGATIVE_CONTROLS.some(
648
+ ({ filename }) => filename === `positive-control-${name}-telemetry-contributor.ts`,
649
+ );
650
+ const hasNegative = NEGATIVE_CONTROLS.some(({ filename }) =>
651
+ filename.startsWith(`negative-control-${name}-telemetry-`),
652
+ );
653
+ if (!hasNegative || !hasPositive) {
654
+ missing.push(
655
+ `${name} (${hasNegative ? "negative" : "missing negative"}, ${hasPositive ? "positive" : "missing positive"})`,
656
+ );
657
+ }
658
+ }
659
+ if (missing.length > 0) {
660
+ throw new Error(`Missing telemetry contributor pack controls: ${missing.join(", ")}`);
661
+ }
662
+ }
663
+
481
664
  const tempRoot = mkdtempSync(join(tmpdir(), "apifuse-provider-sdk-pack-types-"));
482
665
  const packDir = join(tempRoot, "pack");
483
666
  const consumerDir = join(tempRoot, "consumer");