@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.
- package/AUTHORING.md +367 -9
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/bin/apifuse-check.ts +84 -2
- package/bin/apifuse-dev.ts +11 -31
- package/bin/apifuse-migrate-deployment.ts +200 -0
- package/bin/apifuse-pack-check.ts +11 -4
- package/bin/apifuse-pack-types.ts +187 -4
- package/bin/apifuse-record.ts +44 -32
- package/bin/apifuse-submit-check.ts +9 -5
- package/bin/apifuse-test.ts +3 -1
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +11 -0
- package/dist/cli/deployment-intent.d.ts +178 -0
- package/dist/cli/deployment-intent.js +277 -0
- package/dist/cli/migrate-deployment-intent.d.ts +132 -0
- package/dist/cli/migrate-deployment-intent.js +1552 -0
- package/dist/cli/migrate-provider-shape.d.ts +5 -1
- package/dist/cli/migrate-provider-shape.js +4 -2
- package/dist/cli/resolver-runtime.d.ts +21 -0
- package/dist/cli/resolver-runtime.js +31 -0
- package/dist/define.d.ts +3 -0
- package/dist/define.js +5 -0
- package/dist/dev.d.ts +3 -1
- package/dist/dev.js +6 -1
- package/dist/engine.d.ts +35 -1
- package/dist/engine.js +21 -2
- package/dist/error-resolution.d.ts +1 -0
- package/dist/error-resolution.js +54 -0
- package/dist/errors.d.ts +39 -1
- package/dist/errors.js +50 -0
- package/dist/handle-meta.d.ts +36 -1
- package/dist/handle-meta.js +16 -0
- package/dist/handle.d.ts +23 -5
- package/dist/handle.js +54 -8
- package/dist/health-scenario.d.ts +38 -0
- package/dist/i18n/error-messages.d.ts +86 -0
- package/dist/i18n/error-messages.js +192 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/keys.d.ts +12 -0
- package/dist/i18n/keys.js +76 -5
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -1
- package/dist/lint.d.ts +15 -0
- package/dist/lint.js +469 -82
- package/dist/provider.d.ts +6 -6
- package/dist/provider.js +3 -3
- package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
- package/dist/runtime/browser-telemetry-binding.js +83 -0
- package/dist/runtime/browser-telemetry.d.ts +76 -0
- package/dist/runtime/browser-telemetry.js +165 -0
- package/dist/runtime/browser.d.ts +3 -0
- package/dist/runtime/browser.js +208 -47
- package/dist/runtime/cache-telemetry.d.ts +71 -0
- package/dist/runtime/cache-telemetry.js +177 -0
- package/dist/runtime/cache.js +67 -7
- package/dist/runtime/capability-response.d.ts +3 -0
- package/dist/runtime/capability-response.js +56 -0
- package/dist/runtime/capability-telemetry.d.ts +46 -0
- package/dist/runtime/capability-telemetry.js +68 -0
- package/dist/runtime/diagnostic-env.d.ts +3 -0
- package/dist/runtime/diagnostic-env.js +10 -1
- package/dist/runtime/engine-mode.d.ts +74 -0
- package/dist/runtime/engine-mode.js +152 -0
- package/dist/runtime/handle.js +9 -1
- package/dist/runtime/http-telemetry-guard.d.ts +10 -0
- package/dist/runtime/http-telemetry-guard.js +62 -10
- package/dist/runtime/http.js +141 -35
- package/dist/runtime/instrumentation.js +92 -13
- package/dist/runtime/ocr-telemetry.d.ts +82 -0
- package/dist/runtime/ocr-telemetry.js +192 -0
- package/dist/runtime/ocr.js +35 -8
- package/dist/runtime/request-telemetry.d.ts +2 -0
- package/dist/runtime/request-telemetry.js +2 -1
- package/dist/runtime/resolver-runtime-options.d.ts +14 -0
- package/dist/runtime/resolver-runtime-options.js +33 -0
- package/dist/runtime/resolver-shared.d.ts +3 -2
- package/dist/runtime/resolver-shared.js +4 -4
- package/dist/runtime/resolver-telemetry.d.ts +1 -0
- package/dist/runtime/resolver-telemetry.js +1 -1
- package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
- package/dist/runtime/resolver-vendors/browser.js +46 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
- package/dist/runtime/resolver-vendors/hosts.js +35 -0
- package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
- package/dist/runtime/resolver-vendors/types.d.ts +5 -4
- package/dist/runtime/resolver.d.ts +4 -1
- package/dist/runtime/resolver.js +46 -13
- package/dist/runtime/state-telemetry.d.ts +79 -0
- package/dist/runtime/state-telemetry.js +194 -0
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +26 -7
- package/dist/runtime/stealth-cookies.d.ts +5 -1
- package/dist/runtime/stealth-cookies.js +21 -1
- package/dist/runtime/stealth-owned-headers.d.ts +26 -0
- package/dist/runtime/stealth-owned-headers.js +37 -0
- package/dist/runtime/stealth-telemetry.d.ts +92 -0
- package/dist/runtime/stealth-telemetry.js +179 -0
- package/dist/runtime/stealth.d.ts +4 -1
- package/dist/runtime/stealth.js +228 -85
- package/dist/runtime/stt-telemetry.d.ts +77 -0
- package/dist/runtime/stt-telemetry.js +176 -0
- package/dist/runtime/stt.js +15 -6
- package/dist/runtime-boundary-lint.d.ts +132 -0
- package/dist/runtime-boundary-lint.js +586 -0
- package/dist/server/error-stack-frames.d.ts +35 -0
- package/dist/server/error-stack-frames.js +219 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +4 -0
- package/dist/server/sdk-version.d.ts +3 -0
- package/dist/server/sdk-version.js +19 -0
- package/dist/server/self-test.js +1 -18
- package/dist/server/sensitive-values.d.ts +1 -1
- package/dist/server/sensitive-values.js +9 -0
- package/dist/server/serve-implementation.d.ts +51 -2
- package/dist/server/serve-implementation.js +337 -90
- package/dist/server/types.d.ts +1 -0
- package/dist/server/types.js +7 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
- package/dist/stateful/stateful-provider-runtime-context.js +1 -0
- package/dist/types.d.ts +123 -1
- package/dist/typescript-module.d.ts +39 -0
- package/dist/typescript-module.js +72 -0
- package/package.json +6 -1
- package/src/cli/commands.ts +14 -0
- package/src/cli/deployment-intent.ts +364 -0
- package/src/cli/migrate-deployment-intent.ts +1908 -0
- package/src/cli/migrate-provider-shape.ts +10 -4
- package/src/cli/resolver-runtime.ts +72 -0
- package/src/define.ts +13 -0
- package/src/dev.ts +9 -2
- package/src/engine.ts +38 -2
- package/src/error-resolution.ts +58 -0
- package/src/errors.ts +77 -1
- package/src/handle-meta.ts +51 -1
- package/src/handle.ts +92 -10
- package/src/health-scenario.ts +38 -0
- package/src/i18n/error-messages.ts +255 -0
- package/src/i18n/index.ts +1 -0
- package/src/i18n/keys.ts +80 -6
- package/src/index.ts +86 -0
- package/src/lint.ts +604 -91
- package/src/provider.ts +12 -0
- package/src/runtime/browser-telemetry-binding.ts +92 -0
- package/src/runtime/browser-telemetry.ts +289 -0
- package/src/runtime/browser.ts +249 -65
- package/src/runtime/cache-telemetry.ts +247 -0
- package/src/runtime/cache.ts +68 -17
- package/src/runtime/capability-response.ts +53 -0
- package/src/runtime/capability-telemetry.ts +101 -0
- package/src/runtime/diagnostic-env.ts +11 -1
- package/src/runtime/engine-mode.ts +233 -0
- package/src/runtime/handle.ts +9 -1
- package/src/runtime/http-telemetry-guard.ts +66 -13
- package/src/runtime/http.ts +168 -37
- package/src/runtime/instrumentation.ts +105 -16
- package/src/runtime/ocr-telemetry.ts +308 -0
- package/src/runtime/ocr.ts +114 -74
- package/src/runtime/request-telemetry.ts +2 -1
- package/src/runtime/resolver-runtime-options.ts +50 -0
- package/src/runtime/resolver-shared.ts +9 -4
- package/src/runtime/resolver-telemetry.ts +1 -1
- package/src/runtime/resolver-vendors/browser.ts +65 -7
- package/src/runtime/resolver-vendors/hosts.ts +43 -0
- package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
- package/src/runtime/resolver-vendors/types.ts +5 -4
- package/src/runtime/resolver.ts +64 -21
- package/src/runtime/state-telemetry.ts +298 -0
- package/src/runtime/state.ts +46 -45
- package/src/runtime/stealth-cookies.ts +24 -1
- package/src/runtime/stealth-owned-headers.ts +41 -0
- package/src/runtime/stealth-telemetry.ts +304 -0
- package/src/runtime/stealth.ts +355 -150
- package/src/runtime/stt-telemetry.ts +282 -0
- package/src/runtime/stt.ts +93 -71
- package/src/runtime-boundary-lint.ts +703 -0
- package/src/server/error-stack-frames.ts +214 -0
- package/src/server/index.ts +53 -0
- package/src/server/sdk-version.ts +22 -0
- package/src/server/self-test.ts +1 -21
- package/src/server/sensitive-values.ts +14 -0
- package/src/server/serve-implementation.ts +569 -108
- package/src/server/types.ts +7 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
- package/src/stateful/stateful-provider-runtime-context.ts +4 -0
- package/src/types.ts +128 -1
- package/src/typescript-module.ts +100 -0
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
package/bin/apifuse-dev.ts
CHANGED
|
@@ -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
|
|
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
|
|
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-
|
|
296
|
+
filename: "negative-control-proxy-telemetry-vendor.ts",
|
|
297
297
|
expectedCode: "TS2322",
|
|
298
|
-
description: "gateway telemetry
|
|
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: "
|
|
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");
|