@apifuse/provider-sdk 2.1.0-beta.0 → 2.1.0-beta.10

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 (213) hide show
  1. package/AUTHORING.md +218 -21
  2. package/CHANGELOG.md +54 -0
  3. package/README.md +147 -10
  4. package/SUBMISSION.md +87 -0
  5. package/bin/apifuse-check.ts +86 -4
  6. package/bin/apifuse-dev.ts +87 -13
  7. package/bin/apifuse-pack-check.ts +120 -0
  8. package/bin/apifuse-pack-smoke.ts +423 -0
  9. package/bin/apifuse-perf.ts +142 -49
  10. package/bin/apifuse-record.ts +182 -104
  11. package/bin/apifuse-submit-check.ts +2538 -0
  12. package/bin/apifuse.ts +1 -1
  13. package/dist/ceremonies/index.d.ts +41 -0
  14. package/dist/ceremonies/index.js +490 -0
  15. package/dist/choice-token.d.ts +24 -0
  16. package/dist/choice-token.js +74 -0
  17. package/dist/cli/commands.d.ts +10 -0
  18. package/dist/cli/commands.js +80 -0
  19. package/dist/cli/create.d.ts +47 -0
  20. package/dist/cli/create.js +762 -0
  21. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  22. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  23. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  24. package/dist/cli/templates/provider/README.md.tpl +160 -0
  25. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  26. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  27. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  28. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  29. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  30. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  31. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  32. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  33. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  34. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  35. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  36. package/dist/config/loader.d.ts +107 -0
  37. package/dist/config/loader.js +935 -0
  38. package/dist/contract-json.d.ts +9 -0
  39. package/dist/contract-json.js +51 -0
  40. package/dist/contract-serialization.d.ts +4 -0
  41. package/dist/contract-serialization.js +78 -0
  42. package/dist/contract-types.d.ts +49 -0
  43. package/dist/contract-types.js +1 -0
  44. package/dist/contract.d.ts +6 -0
  45. package/dist/contract.js +155 -0
  46. package/dist/define.d.ts +97 -0
  47. package/dist/define.js +1320 -0
  48. package/dist/dev.d.ts +9 -0
  49. package/dist/dev.js +15 -0
  50. package/dist/errors.d.ts +59 -0
  51. package/dist/errors.js +97 -0
  52. package/dist/i18n/catalog.d.ts +29 -0
  53. package/dist/i18n/catalog.js +159 -0
  54. package/dist/i18n/index.d.ts +2 -0
  55. package/dist/i18n/index.js +2 -0
  56. package/dist/i18n/keys.d.ts +10 -0
  57. package/dist/i18n/keys.js +34 -0
  58. package/dist/index.d.ts +41 -0
  59. package/dist/index.js +37 -0
  60. package/dist/lint.d.ts +73 -0
  61. package/dist/lint.js +702 -0
  62. package/dist/observability.d.ts +5 -0
  63. package/dist/observability.js +39 -0
  64. package/dist/provider.d.ts +9 -0
  65. package/dist/provider.js +8 -0
  66. package/dist/public-schema-field-lint.d.ts +2 -0
  67. package/dist/public-schema-field-lint.js +158 -0
  68. package/dist/recipes/gov-api.d.ts +19 -0
  69. package/dist/recipes/gov-api.js +72 -0
  70. package/dist/recipes/rest-api.d.ts +21 -0
  71. package/dist/recipes/rest-api.js +115 -0
  72. package/dist/runtime/auth-flow.d.ts +14 -0
  73. package/dist/runtime/auth-flow.js +44 -0
  74. package/dist/runtime/browser.d.ts +25 -0
  75. package/dist/runtime/browser.js +1034 -0
  76. package/dist/runtime/cache.d.ts +10 -0
  77. package/dist/runtime/cache.js +372 -0
  78. package/dist/runtime/choice.d.ts +15 -0
  79. package/dist/runtime/choice.js +435 -0
  80. package/dist/runtime/credential.d.ts +8 -0
  81. package/dist/runtime/credential.js +61 -0
  82. package/dist/runtime/env.d.ts +2 -0
  83. package/dist/runtime/env.js +10 -0
  84. package/dist/runtime/executor.d.ts +16 -0
  85. package/dist/runtime/executor.js +51 -0
  86. package/dist/runtime/http.d.ts +8 -0
  87. package/dist/runtime/http.js +706 -0
  88. package/dist/runtime/insights.d.ts +9 -0
  89. package/dist/runtime/insights.js +324 -0
  90. package/dist/runtime/instrumentation.d.ts +8 -0
  91. package/dist/runtime/instrumentation.js +269 -0
  92. package/dist/runtime/key-derivation.d.ts +24 -0
  93. package/dist/runtime/key-derivation.js +73 -0
  94. package/dist/runtime/keyring.d.ts +25 -0
  95. package/dist/runtime/keyring.js +93 -0
  96. package/dist/runtime/namespace.d.ts +9 -0
  97. package/dist/runtime/namespace.js +19 -0
  98. package/dist/runtime/otlp.d.ts +39 -0
  99. package/dist/runtime/otlp.js +103 -0
  100. package/dist/runtime/perf.d.ts +12 -0
  101. package/dist/runtime/perf.js +52 -0
  102. package/dist/runtime/prevalidate.d.ts +12 -0
  103. package/dist/runtime/prevalidate.js +173 -0
  104. package/dist/runtime/provider.d.ts +2 -0
  105. package/dist/runtime/provider.js +11 -0
  106. package/dist/runtime/proxy-errors.d.ts +21 -0
  107. package/dist/runtime/proxy-errors.js +83 -0
  108. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  109. package/dist/runtime/proxy-telemetry.js +174 -0
  110. package/dist/runtime/redis.d.ts +17 -0
  111. package/dist/runtime/redis.js +82 -0
  112. package/dist/runtime/request-options.d.ts +3 -0
  113. package/dist/runtime/request-options.js +42 -0
  114. package/dist/runtime/state.d.ts +17 -0
  115. package/dist/runtime/state.js +344 -0
  116. package/dist/runtime/stealth.d.ts +18 -0
  117. package/dist/runtime/stealth.js +834 -0
  118. package/dist/runtime/stt.d.ts +22 -0
  119. package/dist/runtime/stt.js +480 -0
  120. package/dist/runtime/trace.d.ts +26 -0
  121. package/dist/runtime/trace.js +142 -0
  122. package/dist/runtime/waterfall.d.ts +12 -0
  123. package/dist/runtime/waterfall.js +147 -0
  124. package/dist/schema.d.ts +74 -0
  125. package/dist/schema.js +243 -0
  126. package/dist/serve.d.ts +1 -0
  127. package/dist/serve.js +1 -0
  128. package/dist/server/index.d.ts +3 -0
  129. package/dist/server/index.js +2 -0
  130. package/dist/server/serve.d.ts +64 -0
  131. package/dist/server/serve.js +1110 -0
  132. package/dist/server/types.d.ts +136 -0
  133. package/dist/server/types.js +86 -0
  134. package/dist/stealth/profiles.d.ts +4 -0
  135. package/dist/stealth/profiles.js +259 -0
  136. package/dist/stream.d.ts +44 -0
  137. package/dist/stream.js +151 -0
  138. package/dist/testing/helpers.d.ts +23 -0
  139. package/dist/testing/helpers.js +95 -0
  140. package/dist/testing/index.d.ts +2 -0
  141. package/dist/testing/index.js +2 -0
  142. package/dist/testing/run.d.ts +34 -0
  143. package/dist/testing/run.js +303 -0
  144. package/dist/types.d.ts +1326 -0
  145. package/dist/types.js +61 -0
  146. package/dist/utils/date.d.ts +6 -0
  147. package/dist/utils/date.js +101 -0
  148. package/dist/utils/parse.d.ts +16 -0
  149. package/dist/utils/parse.js +51 -0
  150. package/dist/utils/text.d.ts +4 -0
  151. package/dist/utils/text.js +14 -0
  152. package/dist/utils/transform.d.ts +8 -0
  153. package/dist/utils/transform.js +48 -0
  154. package/package.json +57 -29
  155. package/src/ceremonies/index.ts +30 -3
  156. package/src/choice-token.ts +165 -0
  157. package/src/cli/commands.ts +34 -11
  158. package/src/cli/create.ts +214 -52
  159. package/src/cli/templates/provider/.dockerignore.tpl +22 -0
  160. package/src/cli/templates/provider/.gitignore.tpl +22 -0
  161. package/src/cli/templates/provider/README.md.tpl +134 -2
  162. package/src/cli/templates/provider/dev.ts.tpl +1 -1
  163. package/src/cli/templates/provider/domain/README.md.tpl +3 -0
  164. package/src/cli/templates/provider/index.ts.tpl +5 -44
  165. package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
  166. package/src/cli/templates/provider/meta.ts.tpl +7 -0
  167. package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
  168. package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
  169. package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  170. package/src/cli/templates/provider/start.ts.tpl +1 -1
  171. package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
  172. package/src/config/loader.ts +1282 -7
  173. package/src/contract-json.ts +75 -0
  174. package/src/contract-serialization.ts +89 -0
  175. package/src/contract-types.ts +52 -0
  176. package/src/contract.ts +215 -0
  177. package/src/define.ts +1726 -48
  178. package/src/errors.ts +27 -0
  179. package/src/i18n/catalog.ts +277 -0
  180. package/src/i18n/index.ts +2 -0
  181. package/src/i18n/keys.ts +64 -0
  182. package/src/index.ts +174 -15
  183. package/src/lint.ts +547 -73
  184. package/src/observability.ts +41 -0
  185. package/src/provider.ts +104 -5
  186. package/src/public-schema-field-lint.ts +237 -0
  187. package/src/runtime/auth-flow.ts +7 -0
  188. package/src/runtime/browser.ts +762 -51
  189. package/src/runtime/cache.ts +528 -0
  190. package/src/runtime/choice.ts +760 -0
  191. package/src/runtime/executor.ts +32 -3
  192. package/src/runtime/http.ts +945 -185
  193. package/src/runtime/insights.ts +11 -11
  194. package/src/runtime/instrumentation.ts +12 -4
  195. package/src/runtime/key-derivation.ts +1 -1
  196. package/src/runtime/keyring.ts +4 -3
  197. package/src/runtime/proxy-errors.ts +132 -0
  198. package/src/runtime/proxy-telemetry.ts +253 -0
  199. package/src/runtime/redis.ts +116 -0
  200. package/src/runtime/request-options.ts +66 -0
  201. package/src/runtime/state.ts +563 -0
  202. package/src/runtime/stealth.ts +1159 -0
  203. package/src/runtime/stt.ts +629 -0
  204. package/src/runtime/trace.ts +1 -1
  205. package/src/schema.ts +363 -1
  206. package/src/server/serve.ts +1172 -76
  207. package/src/server/types.ts +37 -0
  208. package/src/stream.ts +210 -0
  209. package/src/testing/run.ts +31 -5
  210. package/src/types.ts +1118 -44
  211. package/src/composite.ts +0 -43
  212. package/src/runtime/tls.ts +0 -425
  213. package/src/types/playwright-stealth.d.ts +0 -9
@@ -0,0 +1,147 @@
1
+ const ANSI = {
2
+ green: "\x1b[32m",
3
+ red: "\x1b[31m",
4
+ yellow: "\x1b[33m",
5
+ dim: "\x1b[2m",
6
+ bold: "\x1b[1m",
7
+ reset: "\x1b[0m",
8
+ };
9
+ export function renderWaterfall(spans, request, options) {
10
+ if (spans.length === 0) {
11
+ return "";
12
+ }
13
+ const slowThresholdMs = options?.slowThresholdMs ?? 500;
14
+ const maxBarWidth = options?.maxBarWidth ?? 40;
15
+ const tree = buildTree(spans);
16
+ const bottleneckId = findBottleneck(tree);
17
+ const totalDuration = request.totalMs;
18
+ const lines = [];
19
+ const headerRule = "─".repeat(40);
20
+ lines.push(` ${ANSI.dim}┌─${ANSI.reset} ${request.method} ${request.path} ${ANSI.dim}${headerRule}${ANSI.reset}`);
21
+ lines.push(` ${ANSI.dim}│${ANSI.reset}`);
22
+ for (const node of tree) {
23
+ const operationDuration = formatDuration(node.span.duration_ms);
24
+ const operationBar = renderBar(node.span.duration_ms, totalDuration, maxBarWidth);
25
+ const operationColor = spanColor(node.span, slowThresholdMs);
26
+ lines.push(` ${ANSI.dim}│${ANSI.reset} ${operationColor}[${node.span.name}] ${operationDuration} ${operationBar}${ANSI.reset}`);
27
+ renderChildren(lines, node.children, 1, {
28
+ totalDuration,
29
+ maxBarWidth,
30
+ slowThresholdMs,
31
+ bottleneckId,
32
+ });
33
+ }
34
+ lines.push(` ${ANSI.dim}│${ANSI.reset}`);
35
+ const statusColor = request.status >= 400 ? ANSI.red : ANSI.green;
36
+ const totalFormatted = formatDuration(request.totalMs);
37
+ lines.push(` ${ANSI.dim}└─${ANSI.reset} ${statusColor}${request.status} ${statusText(request.status)}${ANSI.reset} (${totalFormatted})`);
38
+ return lines.join("\n");
39
+ }
40
+ function renderChildren(lines, children, depth, ctx) {
41
+ const indent = " ".repeat(depth);
42
+ for (let i = 0; i < children.length; i++) {
43
+ const node = children[i];
44
+ if (!node) {
45
+ continue;
46
+ }
47
+ const isLast = i === children.length - 1;
48
+ const provider = isLast ? "└─" : "├─";
49
+ const duration = formatDuration(node.span.duration_ms);
50
+ const bar = renderBar(node.span.duration_ms, ctx.totalDuration, ctx.maxBarWidth);
51
+ const color = spanColor(node.span, ctx.slowThresholdMs);
52
+ const star = node.span.id === ctx.bottleneckId ? ` ${ANSI.yellow}★${ANSI.reset}` : "";
53
+ const barSuffix = bar ? ` ${bar}` : "";
54
+ const nameWidth = 20;
55
+ const paddedName = node.span.name.padEnd(nameWidth);
56
+ lines.push(` ${ANSI.dim}│${ANSI.reset} ${indent}${ANSI.dim}${provider}${ANSI.reset} ${color}${paddedName}${ANSI.reset} ${duration}${barSuffix}${star}`);
57
+ if (node.children.length > 0) {
58
+ renderChildren(lines, node.children, depth + 1, ctx);
59
+ }
60
+ }
61
+ }
62
+ function buildTree(spans) {
63
+ const sorted = [...spans].sort((a, b) => a.startedAt - b.startedAt);
64
+ const nodeMap = new Map();
65
+ for (const span of sorted) {
66
+ nodeMap.set(span.id, { span, children: [] });
67
+ }
68
+ const roots = [];
69
+ for (const span of sorted) {
70
+ const node = nodeMap.get(span.id);
71
+ if (!node) {
72
+ continue;
73
+ }
74
+ if (span.parentId) {
75
+ const parent = nodeMap.get(span.parentId);
76
+ if (parent) {
77
+ parent.children.push(node);
78
+ continue;
79
+ }
80
+ }
81
+ roots.push(node);
82
+ }
83
+ return roots;
84
+ }
85
+ function findBottleneck(roots) {
86
+ if (roots.length === 0) {
87
+ return null;
88
+ }
89
+ const allTopLevel = [];
90
+ for (const root of roots) {
91
+ for (const child of root.children) {
92
+ allTopLevel.push(child.span);
93
+ }
94
+ }
95
+ if (allTopLevel.length === 0) {
96
+ return null;
97
+ }
98
+ const first = allTopLevel[0];
99
+ if (!first) {
100
+ return null;
101
+ }
102
+ let longest = first;
103
+ for (const span of allTopLevel) {
104
+ if (span.duration_ms > longest.duration_ms) {
105
+ longest = span;
106
+ }
107
+ }
108
+ return longest.id;
109
+ }
110
+ function renderBar(durationMs, totalMs, maxWidth) {
111
+ if (totalMs <= 0 || durationMs <= 0) {
112
+ return "";
113
+ }
114
+ const ratio = durationMs / totalMs;
115
+ const width = Math.max(1, Math.round(ratio * maxWidth));
116
+ return "━".repeat(width);
117
+ }
118
+ function spanColor(span, slowThresholdMs) {
119
+ if (span.status === "error") {
120
+ return ANSI.red;
121
+ }
122
+ if (span.duration_ms >= slowThresholdMs) {
123
+ return ANSI.yellow;
124
+ }
125
+ return ANSI.green;
126
+ }
127
+ function formatDuration(ms) {
128
+ if (ms >= 1000) {
129
+ return `${(ms / 1000).toFixed(1)}s`;
130
+ }
131
+ if (ms >= 10) {
132
+ return `${Math.round(ms)}ms`;
133
+ }
134
+ return `${ms.toFixed(1)}ms`;
135
+ }
136
+ function statusText(status) {
137
+ const texts = {
138
+ 200: "OK",
139
+ 201: "Created",
140
+ 400: "Bad Request",
141
+ 401: "Unauthorized",
142
+ 404: "Not Found",
143
+ 500: "Internal Server Error",
144
+ 502: "Bad Gateway",
145
+ };
146
+ return texts[status] ?? "";
147
+ }
@@ -0,0 +1,74 @@
1
+ import { type ZodString, type ZodType, z } from "zod";
2
+ import type { InferSchemaOutput, ProviderLocaleKey, SchemaLike } from "./types";
3
+ export { z };
4
+ export type SchemaValidationResult<TSchema extends SchemaLike> = {
5
+ success: true;
6
+ data: InferSchemaOutput<TSchema>;
7
+ } | {
8
+ success: false;
9
+ error: unknown;
10
+ };
11
+ export declare function parseSchema<TSchema extends SchemaLike>(schema: TSchema, value: unknown, fieldPath: string): Promise<InferSchemaOutput<TSchema>>;
12
+ export declare function safeParseSchemaSync<TSchema extends SchemaLike>(schema: TSchema, value: unknown, fieldPath: string): SchemaValidationResult<TSchema>;
13
+ export declare const APIFUSE_SENSITIVE_META_KEY = "x-apifuse-sensitive";
14
+ export declare const APIFUSE_SENSITIVE_KIND_META_KEY = "x-apifuse-sensitive-kind";
15
+ export declare const APIFUSE_DESCRIPTION_KEY_META_KEY = "x-apifuse-description-key";
16
+ export declare const APIFUSE_REDACTION_MARKER = "<redacted>";
17
+ export type SensitivePathSegment = string | "*";
18
+ export type SensitivePath = readonly SensitivePathSegment[];
19
+ export type SensitiveFieldKind = "api_key" | "authorization" | "cookie" | "credential" | "otp" | "password" | "payment_url" | "personal_data" | "phone" | "secret" | "token";
20
+ export interface SensitiveFieldOptions {
21
+ /**
22
+ * Mark this schema as sensitive. Defaults to true for the helper presets.
23
+ */
24
+ sensitive?: boolean;
25
+ /**
26
+ * Machine-readable sensitivity category propagated to JSON Schema.
27
+ */
28
+ kind?: SensitiveFieldKind;
29
+ /**
30
+ * Optional public description applied with Zod's `.describe()`.
31
+ */
32
+ description?: string;
33
+ }
34
+ export declare function describeKey<TSchema extends ZodType>(schema: TSchema, key: ProviderLocaleKey | string): TSchema;
35
+ declare module "zod" {
36
+ interface ZodType {
37
+ describeKey(key: ProviderLocaleKey | string): this;
38
+ }
39
+ }
40
+ export declare function field<TSchema extends ZodType>(schema: TSchema, options?: SensitiveFieldOptions): TSchema;
41
+ export declare function sensitive<TSchema extends ZodType>(schema: TSchema, kind?: SensitiveFieldKind): TSchema;
42
+ export declare const fields: {
43
+ readonly apiKey: (options?: {
44
+ description?: string;
45
+ }) => ZodString;
46
+ readonly authorization: (options?: {
47
+ description?: string;
48
+ }) => ZodString;
49
+ readonly cookie: (options?: {
50
+ description?: string;
51
+ }) => ZodString;
52
+ readonly otp: (options?: {
53
+ description?: string;
54
+ }) => ZodString;
55
+ readonly password: (options?: {
56
+ description?: string;
57
+ minLength?: number;
58
+ }) => ZodString;
59
+ readonly paymentUrl: (options?: {
60
+ description?: string;
61
+ }) => ZodString;
62
+ readonly phone: (options?: {
63
+ description?: string;
64
+ }) => ZodString;
65
+ readonly secret: (options?: {
66
+ description?: string;
67
+ }) => ZodString;
68
+ readonly token: (options?: {
69
+ description?: string;
70
+ }) => ZodString;
71
+ };
72
+ export declare function isSensitiveSchema(schema: unknown): boolean;
73
+ export declare function collectSensitivePaths(schema: unknown): SensitivePath[];
74
+ export declare function redactPayload(value: unknown, paths?: readonly SensitivePath[]): unknown;
package/dist/schema.js ADDED
@@ -0,0 +1,243 @@
1
+ import { z } from "zod";
2
+ import { ValidationError } from "./errors";
3
+ import { providerLocaleKey } from "./i18n/keys";
4
+ export { z };
5
+ function isFailureResult(result) {
6
+ return "issues" in result;
7
+ }
8
+ function isPromiseResult(result) {
9
+ return result instanceof Promise;
10
+ }
11
+ function formatStandardSchemaIssues(issues) {
12
+ return issues.map((issue) => issue.message).join("; ");
13
+ }
14
+ export async function parseSchema(schema, value, fieldPath) {
15
+ if ("parse" in schema && typeof schema.parse === "function")
16
+ return schema.parse(value);
17
+ const result = schema["~standard"].validate(value);
18
+ const resolved = isPromiseResult(result) ? await result : result;
19
+ if (isFailureResult(resolved))
20
+ throw new ValidationError(`Schema validation failed for ${fieldPath}: ${formatStandardSchemaIssues(resolved.issues)}`, { zodError: resolved.issues });
21
+ return resolved.value;
22
+ }
23
+ export function safeParseSchemaSync(schema, value, fieldPath) {
24
+ if ("safeParse" in schema && typeof schema.safeParse === "function")
25
+ return schema.safeParse(value);
26
+ try {
27
+ const result = schema["~standard"].validate(value);
28
+ if (isPromiseResult(result))
29
+ return {
30
+ success: false,
31
+ error: new ValidationError(`Schema validation for ${fieldPath} returned a Promise. defineProvider fixture validation requires synchronous Standard Schema validation.`),
32
+ };
33
+ if (isFailureResult(result))
34
+ return { success: false, error: result.issues };
35
+ return { success: true, data: result.value };
36
+ }
37
+ catch (error) {
38
+ return { success: false, error };
39
+ }
40
+ }
41
+ export const APIFUSE_SENSITIVE_META_KEY = "x-apifuse-sensitive";
42
+ export const APIFUSE_SENSITIVE_KIND_META_KEY = "x-apifuse-sensitive-kind";
43
+ export const APIFUSE_DESCRIPTION_KEY_META_KEY = "x-apifuse-description-key";
44
+ export const APIFUSE_REDACTION_MARKER = "<redacted>";
45
+ export function describeKey(schema, key) {
46
+ const descriptionKey = providerLocaleKey(key);
47
+ const metadata = schema.meta() ?? {};
48
+ return schema.meta({
49
+ ...metadata,
50
+ [APIFUSE_DESCRIPTION_KEY_META_KEY]: descriptionKey,
51
+ });
52
+ }
53
+ const describeKeyMethod = function (key) {
54
+ return describeKey(this, key);
55
+ };
56
+ function installDescribeKeyOnPrototype(prototype) {
57
+ const target = prototype;
58
+ if (!target || typeof target.describeKey === "function") {
59
+ return;
60
+ }
61
+ Object.defineProperty(target, "describeKey", {
62
+ configurable: true,
63
+ value: describeKeyMethod,
64
+ writable: true,
65
+ });
66
+ }
67
+ for (const [name, value] of Object.entries(z)) {
68
+ if (!name.startsWith("Zod") || name.endsWith("Error")) {
69
+ continue;
70
+ }
71
+ if (typeof value !== "function") {
72
+ continue;
73
+ }
74
+ installDescribeKeyOnPrototype(value.prototype);
75
+ }
76
+ const RESERVED_SENSITIVE_KEYS = new Set([
77
+ "authorization",
78
+ "cookie",
79
+ "secret",
80
+ "secrets",
81
+ "token",
82
+ "accesstoken",
83
+ "refreshtoken",
84
+ "apikey",
85
+ "api_key",
86
+ "password",
87
+ "passwd",
88
+ "otp",
89
+ "otpcode",
90
+ "phone",
91
+ "phonenumber",
92
+ "paymenturl",
93
+ "payment_url",
94
+ ]);
95
+ export function field(schema, options = {}) {
96
+ const described = options.description && typeof schema.describe === "function"
97
+ ? schema.describe(options.description)
98
+ : schema;
99
+ const metadata = described.meta() ?? {};
100
+ return described.meta({
101
+ ...metadata,
102
+ ...((options.sensitive ?? true)
103
+ ? { [APIFUSE_SENSITIVE_META_KEY]: true }
104
+ : {}),
105
+ ...(options.kind
106
+ ? { [APIFUSE_SENSITIVE_KIND_META_KEY]: options.kind }
107
+ : {}),
108
+ });
109
+ }
110
+ export function sensitive(schema, kind) {
111
+ return field(schema, { sensitive: true, kind });
112
+ }
113
+ function sensitiveString(kind, description, options = {}) {
114
+ const schema = options.minLength === undefined
115
+ ? z.string()
116
+ : z.string().min(options.minLength);
117
+ return field(schema, {
118
+ kind,
119
+ description: options.description ?? description,
120
+ });
121
+ }
122
+ export const fields = {
123
+ apiKey: (options) => sensitiveString("api_key", "Provider API key or credential secret.", options),
124
+ authorization: (options) => sensitiveString("authorization", "Authorization header value or bearer credential.", options),
125
+ cookie: (options) => sensitiveString("cookie", "Cookie header or browser session secret.", options),
126
+ otp: (options) => sensitiveString("otp", "One-time verification code.", options),
127
+ password: (options) => sensitiveString("password", "Password credential.", options),
128
+ paymentUrl: (options) => sensitiveString("payment_url", "Sensitive payment or checkout URL.", options),
129
+ phone: (options) => sensitiveString("phone", "Phone number or phone-based identity.", options),
130
+ secret: (options) => sensitiveString("secret", "Provider secret material.", options),
131
+ token: (options) => sensitiveString("token", "Provider access or refresh token.", options),
132
+ };
133
+ export function isSensitiveSchema(schema) {
134
+ const metadata = readZodMetadata(schema);
135
+ return (metadata !== undefined &&
136
+ Reflect.get(metadata, APIFUSE_SENSITIVE_META_KEY) === true);
137
+ }
138
+ export function collectSensitivePaths(schema) {
139
+ const out = [];
140
+ collectSensitivePathsInto(schema, [], out, new Set(), new Set());
141
+ return out;
142
+ }
143
+ export function redactPayload(value, paths = []) {
144
+ return redactValue(value, [], paths);
145
+ }
146
+ function collectSensitivePathsInto(schema, path, out, activeSchemas, emittedPaths) {
147
+ if (!schema || typeof schema !== "object" || activeSchemas.has(schema))
148
+ return;
149
+ activeSchemas.add(schema);
150
+ try {
151
+ if (isSensitiveSchema(schema))
152
+ pushSensitivePath(out, emittedPaths, path);
153
+ const def = readZodDef(schema);
154
+ if (!def)
155
+ return;
156
+ switch (Reflect.get(def, "type")) {
157
+ case "object": {
158
+ const shape = readObjectShape(def);
159
+ for (const [key, child] of Object.entries(shape)) {
160
+ collectSensitivePathsInto(child, [...path, key], out, activeSchemas, emittedPaths);
161
+ }
162
+ break;
163
+ }
164
+ case "array":
165
+ collectSensitivePathsInto(Reflect.get(def, "element"), [...path, "*"], out, activeSchemas, emittedPaths);
166
+ break;
167
+ case "optional":
168
+ case "nullable":
169
+ case "default":
170
+ case "catch":
171
+ case "readonly":
172
+ collectSensitivePathsInto(Reflect.get(def, "innerType"), path, out, activeSchemas, emittedPaths);
173
+ break;
174
+ case "pipe":
175
+ collectSensitivePathsInto(Reflect.get(def, "in"), path, out, activeSchemas, emittedPaths);
176
+ collectSensitivePathsInto(Reflect.get(def, "out"), path, out, activeSchemas, emittedPaths);
177
+ break;
178
+ }
179
+ }
180
+ finally {
181
+ activeSchemas.delete(schema);
182
+ }
183
+ }
184
+ function pushSensitivePath(out, emittedPaths, path) {
185
+ const key = JSON.stringify(path);
186
+ if (emittedPaths.has(key))
187
+ return;
188
+ emittedPaths.add(key);
189
+ out.push([...path]);
190
+ }
191
+ function redactValue(value, path, paths) {
192
+ if (pathMatches(path, paths))
193
+ return APIFUSE_REDACTION_MARKER;
194
+ if (Array.isArray(value)) {
195
+ return value.map((item) => redactValue(item, [...path, "*"], paths));
196
+ }
197
+ if (value && typeof value === "object") {
198
+ const out = {};
199
+ for (const [key, child] of Object.entries(value)) {
200
+ if (isReservedSensitiveKey(key)) {
201
+ out[key] = APIFUSE_REDACTION_MARKER;
202
+ }
203
+ else {
204
+ out[key] = redactValue(child, [...path, key], paths);
205
+ }
206
+ }
207
+ return out;
208
+ }
209
+ return value;
210
+ }
211
+ function pathMatches(path, patterns) {
212
+ return patterns.some((pattern) => {
213
+ if (pattern.length !== path.length)
214
+ return false;
215
+ return pattern.every((segment, index) => segment === "*" || segment === path[index]);
216
+ });
217
+ }
218
+ function isReservedSensitiveKey(key) {
219
+ const normalized = key.toLowerCase().replace(/[-_\s]/g, "");
220
+ return (RESERVED_SENSITIVE_KEYS.has(normalized) ||
221
+ RESERVED_SENSITIVE_KEYS.has(key.toLowerCase()));
222
+ }
223
+ function readZodMetadata(schema) {
224
+ if (!schema || typeof schema !== "object" || !("meta" in schema)) {
225
+ return undefined;
226
+ }
227
+ const maybeMeta = schema.meta;
228
+ if (typeof maybeMeta !== "function")
229
+ return undefined;
230
+ const metadata = maybeMeta.call(schema);
231
+ return metadata && typeof metadata === "object" ? metadata : undefined;
232
+ }
233
+ function readZodDef(schema) {
234
+ if (!schema || typeof schema !== "object")
235
+ return undefined;
236
+ const def = Reflect.get(schema, "def") ?? Reflect.get(schema, "_def");
237
+ return def && typeof def === "object" ? def : undefined;
238
+ }
239
+ function readObjectShape(def) {
240
+ const shape = Reflect.get(def, "shape");
241
+ const value = typeof shape === "function" ? shape() : shape;
242
+ return value && typeof value === "object" ? value : {};
243
+ }
@@ -0,0 +1 @@
1
+ export { createServerApp, type ServeOptions, serve } from "./server/serve";
package/dist/serve.js ADDED
@@ -0,0 +1 @@
1
+ export { createServerApp, serve } from "./server/serve";
@@ -0,0 +1,3 @@
1
+ export { createServerApp, type ServeOptions, serve } from "./serve";
2
+ export type { AuthFlowRequest, AuthFlowResponse, AuthFlowSuccessResponse, ConnectionMode, OperationConnection, OperationErrorResponse, OperationRequest, OperationResponse, OperationSuccessResponse, } from "./types";
3
+ export { AuthFlowRequestSchema, AuthFlowSuccessResponseSchema, ConnectionModeSchema, ErrorEnvelopeSchema, OperationConnectionSchema, OperationErrorResponseSchema, OperationRequestSchema, OperationSuccessResponseSchema, } from "./types";
@@ -0,0 +1,2 @@
1
+ export { createServerApp, serve } from "./serve";
2
+ export { AuthFlowRequestSchema, AuthFlowSuccessResponseSchema, ConnectionModeSchema, ErrorEnvelopeSchema, OperationConnectionSchema, OperationErrorResponseSchema, OperationRequestSchema, OperationSuccessResponseSchema, } from "./types";
@@ -0,0 +1,64 @@
1
+ import { Hono } from "hono";
2
+ import { type ProviderErrorCategory } from "../observability";
3
+ import type { ProviderDefinition, ProviderRuntimeState, SttContext } from "../types";
4
+ import { type OperationRequest } from "./types";
5
+ export declare function resolveProviderProxyAffinityKey(provider: ProviderDefinition, request: OperationRequest, operationId: string): string;
6
+ type ProviderRequestCost = {
7
+ durationMs: number;
8
+ cpuUserMicros: number;
9
+ cpuSystemMicros: number;
10
+ cpuTotalMicros: number;
11
+ };
12
+ type ProviderServerLogEventBase = ProviderRequestCost & {
13
+ providerId: string;
14
+ kind: "operation" | "auth";
15
+ route: string;
16
+ requestId?: string;
17
+ status: number;
18
+ };
19
+ export type ProviderServerLogEvent = (ProviderServerLogEventBase & {
20
+ level: "info";
21
+ event: "provider_request_completed";
22
+ }) | (ProviderServerLogEventBase & {
23
+ level: "warn" | "error";
24
+ event: "provider_request_failed";
25
+ code: string;
26
+ errorClass: string;
27
+ message: string;
28
+ upstreamStatus?: number;
29
+ errorCategory?: ProviderErrorCategory;
30
+ taxonomyVersion?: string;
31
+ retryable?: boolean;
32
+ issues?: Array<{
33
+ path: string;
34
+ code: string;
35
+ message: string;
36
+ }>;
37
+ }) | {
38
+ level: "warn";
39
+ event: "provider_cleanup_failed";
40
+ providerId: string;
41
+ kind: "operation";
42
+ route: string;
43
+ requestId?: string;
44
+ resource: "browser" | "stealth";
45
+ errorClass: string;
46
+ message: string;
47
+ };
48
+ export type ProviderServerLogger = (event: ProviderServerLogEvent) => void;
49
+ export type ProviderServerOptions = {
50
+ logger?: ProviderServerLogger;
51
+ /** Optional STT override for tests or custom hosts; local/prod normally resolves from env. */
52
+ stt?: SttContext;
53
+ /** Optional runtime state override for tests or custom hosts. Production resolves Redis from env and fails closed when unavailable. */
54
+ state?: ProviderRuntimeState;
55
+ /** Allow process-local runtime state only for local development and tests. */
56
+ allowMemoryStateFallback?: boolean;
57
+ };
58
+ export declare function createServerApp(provider: ProviderDefinition, options?: ProviderServerOptions): Hono;
59
+ export interface ServeOptions extends ProviderServerOptions {
60
+ host?: string;
61
+ port?: number;
62
+ }
63
+ export declare function serve(provider: ProviderDefinition, options?: ServeOptions): Promise<void>;
64
+ export {};