@apifuse/provider-sdk 2.1.0-beta.2 → 2.1.0-beta.21

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 (231) hide show
  1. package/AUTHORING.md +330 -8
  2. package/CHANGELOG.md +89 -1
  3. package/README.md +64 -17
  4. package/SUBMISSION.md +86 -0
  5. package/bin/apifuse-check.ts +60 -6
  6. package/bin/apifuse-dev.ts +58 -8
  7. package/bin/apifuse-pack-check.ts +32 -2
  8. package/bin/apifuse-pack-smoke.ts +133 -6
  9. package/bin/apifuse-perf.ts +142 -49
  10. package/bin/apifuse-record.ts +182 -104
  11. package/bin/apifuse-submit-check.ts +3243 -0
  12. package/bin/apifuse.ts +1 -1
  13. package/dist/auth.d.ts +76 -0
  14. package/dist/auth.js +436 -0
  15. package/dist/ceremonies/index.d.ts +41 -0
  16. package/dist/ceremonies/index.js +490 -0
  17. package/dist/choice-token.d.ts +24 -0
  18. package/dist/choice-token.js +74 -0
  19. package/dist/cli/commands.d.ts +10 -0
  20. package/dist/cli/commands.js +80 -0
  21. package/dist/cli/create.d.ts +47 -0
  22. package/dist/cli/create.js +777 -0
  23. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  24. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  25. package/dist/cli/templates/provider/AGENTS.md.tpl +87 -0
  26. package/dist/cli/templates/provider/CLAUDE.md.tpl +1 -0
  27. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  28. package/dist/cli/templates/provider/README.md.tpl +163 -0
  29. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  30. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  31. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  32. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  33. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  34. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  35. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  36. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  37. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  38. package/dist/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  39. package/dist/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  40. package/dist/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  41. package/dist/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  42. package/dist/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  43. package/dist/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  44. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  45. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  46. package/dist/config/loader.d.ts +107 -0
  47. package/dist/config/loader.js +935 -0
  48. package/dist/contract-json.d.ts +9 -0
  49. package/dist/contract-json.js +51 -0
  50. package/dist/contract-serialization.d.ts +4 -0
  51. package/dist/contract-serialization.js +78 -0
  52. package/dist/contract-types.d.ts +49 -0
  53. package/dist/contract-types.js +1 -0
  54. package/dist/contract.d.ts +6 -0
  55. package/dist/contract.js +156 -0
  56. package/dist/define.d.ts +100 -0
  57. package/dist/define.js +1383 -0
  58. package/dist/dev.d.ts +9 -0
  59. package/dist/dev.js +15 -0
  60. package/dist/errors.d.ts +59 -0
  61. package/dist/errors.js +97 -0
  62. package/dist/i18n/catalog.d.ts +29 -0
  63. package/dist/i18n/catalog.js +159 -0
  64. package/dist/i18n/index.d.ts +2 -0
  65. package/dist/i18n/index.js +2 -0
  66. package/dist/i18n/keys.d.ts +10 -0
  67. package/dist/i18n/keys.js +34 -0
  68. package/dist/index.d.ts +42 -0
  69. package/dist/index.js +38 -0
  70. package/dist/lint.d.ts +74 -0
  71. package/dist/lint.js +729 -0
  72. package/dist/observability.d.ts +5 -0
  73. package/dist/observability.js +39 -0
  74. package/dist/provider.d.ts +11 -0
  75. package/dist/provider.js +9 -0
  76. package/dist/public-schema-field-lint.d.ts +2 -0
  77. package/dist/public-schema-field-lint.js +158 -0
  78. package/dist/recipes/gov-api.d.ts +19 -0
  79. package/dist/recipes/gov-api.js +72 -0
  80. package/dist/recipes/rest-api.d.ts +21 -0
  81. package/dist/recipes/rest-api.js +115 -0
  82. package/dist/runtime/auth-flow.d.ts +14 -0
  83. package/dist/runtime/auth-flow.js +46 -0
  84. package/dist/runtime/browser.d.ts +25 -0
  85. package/dist/runtime/browser.js +1237 -0
  86. package/dist/runtime/cache.d.ts +10 -0
  87. package/dist/runtime/cache.js +372 -0
  88. package/dist/runtime/choice.d.ts +15 -0
  89. package/dist/runtime/choice.js +435 -0
  90. package/dist/runtime/credential.d.ts +8 -0
  91. package/dist/runtime/credential.js +61 -0
  92. package/dist/runtime/env.d.ts +2 -0
  93. package/dist/runtime/env.js +10 -0
  94. package/dist/runtime/executor.d.ts +16 -0
  95. package/dist/runtime/executor.js +51 -0
  96. package/dist/runtime/http.d.ts +8 -0
  97. package/dist/runtime/http.js +726 -0
  98. package/dist/runtime/insights.d.ts +9 -0
  99. package/dist/runtime/insights.js +324 -0
  100. package/dist/runtime/instrumentation.d.ts +8 -0
  101. package/dist/runtime/instrumentation.js +269 -0
  102. package/dist/runtime/key-derivation.d.ts +24 -0
  103. package/dist/runtime/key-derivation.js +73 -0
  104. package/dist/runtime/keyring.d.ts +25 -0
  105. package/dist/runtime/keyring.js +93 -0
  106. package/dist/runtime/namespace.d.ts +9 -0
  107. package/dist/runtime/namespace.js +19 -0
  108. package/dist/runtime/otlp.d.ts +39 -0
  109. package/dist/runtime/otlp.js +103 -0
  110. package/dist/runtime/perf.d.ts +12 -0
  111. package/dist/runtime/perf.js +52 -0
  112. package/dist/runtime/prevalidate.d.ts +12 -0
  113. package/dist/runtime/prevalidate.js +173 -0
  114. package/dist/runtime/provider.d.ts +2 -0
  115. package/dist/runtime/provider.js +11 -0
  116. package/dist/runtime/proxy-errors.d.ts +21 -0
  117. package/dist/runtime/proxy-errors.js +83 -0
  118. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  119. package/dist/runtime/proxy-telemetry.js +174 -0
  120. package/dist/runtime/redis.d.ts +17 -0
  121. package/dist/runtime/redis.js +82 -0
  122. package/dist/runtime/request-options.d.ts +3 -0
  123. package/dist/runtime/request-options.js +42 -0
  124. package/dist/runtime/state.d.ts +17 -0
  125. package/dist/runtime/state.js +344 -0
  126. package/dist/runtime/stealth.d.ts +21 -0
  127. package/dist/runtime/stealth.js +980 -0
  128. package/dist/runtime/stt.d.ts +22 -0
  129. package/dist/runtime/stt.js +480 -0
  130. package/dist/runtime/trace.d.ts +26 -0
  131. package/dist/runtime/trace.js +142 -0
  132. package/dist/runtime/waterfall.d.ts +12 -0
  133. package/dist/runtime/waterfall.js +147 -0
  134. package/dist/schema.d.ts +74 -0
  135. package/dist/schema.js +243 -0
  136. package/dist/serve.d.ts +1 -0
  137. package/dist/serve.js +1 -0
  138. package/dist/server/index.d.ts +3 -0
  139. package/dist/server/index.js +2 -0
  140. package/dist/server/serve.d.ts +64 -0
  141. package/dist/server/serve.js +1118 -0
  142. package/dist/server/types.d.ts +136 -0
  143. package/dist/server/types.js +86 -0
  144. package/dist/stealth/profiles.d.ts +4 -0
  145. package/dist/stealth/profiles.js +259 -0
  146. package/dist/stream.d.ts +44 -0
  147. package/dist/stream.js +151 -0
  148. package/dist/testing/helpers.d.ts +23 -0
  149. package/dist/testing/helpers.js +95 -0
  150. package/dist/testing/index.d.ts +2 -0
  151. package/dist/testing/index.js +2 -0
  152. package/dist/testing/run.d.ts +34 -0
  153. package/dist/testing/run.js +307 -0
  154. package/dist/types.d.ts +1467 -0
  155. package/dist/types.js +61 -0
  156. package/dist/utils/date.d.ts +6 -0
  157. package/dist/utils/date.js +101 -0
  158. package/dist/utils/parse.d.ts +16 -0
  159. package/dist/utils/parse.js +51 -0
  160. package/dist/utils/text.d.ts +4 -0
  161. package/dist/utils/text.js +14 -0
  162. package/dist/utils/transform.d.ts +8 -0
  163. package/dist/utils/transform.js +48 -0
  164. package/package.json +57 -29
  165. package/src/auth.ts +786 -0
  166. package/src/ceremonies/index.ts +8 -2
  167. package/src/choice-token.ts +165 -0
  168. package/src/cli/commands.ts +34 -11
  169. package/src/cli/create.ts +254 -128
  170. package/src/cli/templates/provider/.dockerignore.tpl +22 -0
  171. package/src/cli/templates/provider/.gitignore.tpl +22 -0
  172. package/src/cli/templates/provider/AGENTS.md.tpl +87 -0
  173. package/src/cli/templates/provider/CLAUDE.md.tpl +1 -0
  174. package/src/cli/templates/provider/README.md.tpl +87 -7
  175. package/src/cli/templates/provider/dev.ts.tpl +1 -1
  176. package/src/cli/templates/provider/domain/README.md.tpl +3 -0
  177. package/src/cli/templates/provider/index.ts.tpl +5 -47
  178. package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
  179. package/src/cli/templates/provider/meta.ts.tpl +7 -0
  180. package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
  181. package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
  182. package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  183. package/src/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  184. package/src/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  185. package/src/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  186. package/src/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  187. package/src/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  188. package/src/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  189. package/src/cli/templates/provider/start.ts.tpl +1 -1
  190. package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
  191. package/src/config/loader.ts +1224 -9
  192. package/src/contract-json.ts +75 -0
  193. package/src/contract-serialization.ts +89 -0
  194. package/src/contract-types.ts +52 -0
  195. package/src/contract.ts +216 -0
  196. package/src/define.ts +1820 -70
  197. package/src/errors.ts +27 -0
  198. package/src/i18n/catalog.ts +277 -0
  199. package/src/i18n/index.ts +2 -0
  200. package/src/i18n/keys.ts +64 -0
  201. package/src/index.ts +189 -9
  202. package/src/lint.ts +580 -73
  203. package/src/observability.ts +41 -0
  204. package/src/provider.ts +131 -4
  205. package/src/public-schema-field-lint.ts +237 -0
  206. package/src/runtime/auth-flow.ts +9 -0
  207. package/src/runtime/browser.ts +1054 -51
  208. package/src/runtime/cache.ts +528 -0
  209. package/src/runtime/choice.ts +760 -0
  210. package/src/runtime/executor.ts +32 -3
  211. package/src/runtime/http.ts +980 -195
  212. package/src/runtime/insights.ts +11 -11
  213. package/src/runtime/instrumentation.ts +12 -4
  214. package/src/runtime/key-derivation.ts +1 -1
  215. package/src/runtime/keyring.ts +4 -3
  216. package/src/runtime/proxy-errors.ts +132 -0
  217. package/src/runtime/proxy-telemetry.ts +253 -0
  218. package/src/runtime/redis.ts +116 -0
  219. package/src/runtime/request-options.ts +66 -0
  220. package/src/runtime/state.ts +563 -0
  221. package/src/runtime/stealth.ts +1336 -0
  222. package/src/runtime/stt.ts +629 -0
  223. package/src/runtime/trace.ts +1 -1
  224. package/src/schema.ts +363 -1
  225. package/src/server/serve.ts +1192 -75
  226. package/src/server/types.ts +37 -0
  227. package/src/stream.ts +210 -0
  228. package/src/testing/run.ts +40 -6
  229. package/src/types.ts +1283 -59
  230. package/src/runtime/tls.ts +0 -434
  231. package/src/types/playwright-stealth.d.ts +0 -9
package/src/errors.ts CHANGED
@@ -1,7 +1,12 @@
1
+ import type { ProviderErrorCategory } from "./observability";
2
+
1
3
  export type ProviderErrorOptions = {
2
4
  fix?: string;
3
5
  code?: string;
6
+ details?: unknown;
4
7
  cause?: Error;
8
+ category?: ProviderErrorCategory;
9
+ retryable?: boolean;
5
10
  };
6
11
 
7
12
  export class ProviderError extends Error {
@@ -23,6 +28,10 @@ export class ProviderError extends Error {
23
28
  get code(): string | undefined {
24
29
  return this.options?.code;
25
30
  }
31
+
32
+ get details(): unknown {
33
+ return this.options?.details;
34
+ }
26
35
  }
27
36
 
28
37
  export class SDKError extends ProviderError {
@@ -39,6 +48,21 @@ export class AuthError extends ProviderError {
39
48
  }
40
49
  }
41
50
 
51
+ export class SessionExpiredError extends AuthError {
52
+ constructor(
53
+ message = "Provider session expired",
54
+ options?: ProviderErrorOptions,
55
+ ) {
56
+ super(message, {
57
+ code: "reauth_required",
58
+ category: "credential_expired",
59
+ retryable: false,
60
+ ...options,
61
+ });
62
+ this.name = "SessionExpiredError";
63
+ }
64
+ }
65
+
42
66
  export type ValidationErrorOptions = ProviderErrorOptions & {
43
67
  zodError?: unknown;
44
68
  };
@@ -55,15 +79,18 @@ export class ValidationError extends ProviderError {
55
79
 
56
80
  export type TransportErrorOptions = ProviderErrorOptions & {
57
81
  status?: number;
82
+ upstreamStatus?: number;
58
83
  };
59
84
 
60
85
  export class TransportError extends ProviderError {
61
86
  readonly status?: number;
87
+ readonly upstreamStatus?: number;
62
88
 
63
89
  constructor(message: string, options?: TransportErrorOptions) {
64
90
  super(message, options);
65
91
  this.name = "TransportError";
66
92
  this.status = options?.status;
93
+ this.upstreamStatus = options?.upstreamStatus ?? options?.status;
67
94
  }
68
95
  }
69
96
 
@@ -0,0 +1,277 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import type { AuthTurn } from "../types";
5
+ import {
6
+ getProviderLocalePath,
7
+ isProviderLocaleValue,
8
+ type ProviderLocale,
9
+ type ProviderLocaleCatalog,
10
+ type ProviderLocaleKey,
11
+ type ProviderLocaleValue,
12
+ providerLocaleKey,
13
+ } from "./keys";
14
+
15
+ export type ProviderLocaleCatalogMap = Record<
16
+ ProviderLocale,
17
+ ProviderLocaleCatalog
18
+ >;
19
+
20
+ export interface LoadProviderLocaleCatalogsOptions {
21
+ providerDir: string;
22
+ locales: readonly ProviderLocale[];
23
+ }
24
+
25
+ export interface ProviderLocaleValidationIssue {
26
+ locale: ProviderLocale;
27
+ key: string;
28
+ message: string;
29
+ severity: "error" | "warning";
30
+ }
31
+
32
+ export interface ProviderLocaleValidationResult {
33
+ ok: boolean;
34
+ issues: ProviderLocaleValidationIssue[];
35
+ }
36
+
37
+ export function loadProviderLocaleCatalogs(
38
+ options: LoadProviderLocaleCatalogsOptions,
39
+ ): ProviderLocaleCatalogMap {
40
+ const catalogs: ProviderLocaleCatalogMap = {};
41
+ for (const locale of options.locales) {
42
+ const filePath = join(options.providerDir, "locales", `${locale}.json`);
43
+ catalogs[locale] = JSON.parse(readFileSync(filePath, "utf8"));
44
+ }
45
+ return catalogs;
46
+ }
47
+
48
+ export function resolveProviderLocaleValue(
49
+ catalogs: ProviderLocaleCatalogMap,
50
+ key: ProviderLocaleKey | string,
51
+ locale: ProviderLocale,
52
+ fallbackLocale: ProviderLocale = "en",
53
+ ): ProviderLocaleValue | undefined {
54
+ providerLocaleKey(key);
55
+ return (
56
+ getProviderLocalePath(catalogs[locale] ?? {}, key) ??
57
+ getProviderLocalePath(catalogs[fallbackLocale] ?? {}, key)
58
+ );
59
+ }
60
+
61
+ function asStringValue(
62
+ value: ProviderLocaleValue | undefined,
63
+ ): string | undefined {
64
+ return typeof value === "string" ? value : undefined;
65
+ }
66
+
67
+ function isStringRecord(value: unknown): value is Record<string, string> {
68
+ return (
69
+ !!value &&
70
+ typeof value === "object" &&
71
+ !Array.isArray(value) &&
72
+ Object.values(value).every((entry) => typeof entry === "string")
73
+ );
74
+ }
75
+
76
+ function localizeAuthInputSchema(
77
+ expectedInput: Record<string, unknown> | undefined,
78
+ options: {
79
+ catalogs: ProviderLocaleCatalogMap;
80
+ locale: ProviderLocale;
81
+ fallbackLocale: ProviderLocale;
82
+ },
83
+ ): Record<string, unknown> | undefined {
84
+ if (!expectedInput) return undefined;
85
+ const schema = isRecord(expectedInput.schema)
86
+ ? expectedInput.schema
87
+ : expectedInput;
88
+ const localizedSchema = localizeAuthSchemaObject(schema, options);
89
+ if (localizedSchema === schema) return undefined;
90
+ return isRecord(expectedInput.schema)
91
+ ? { ...expectedInput, schema: localizedSchema }
92
+ : localizedSchema;
93
+ }
94
+
95
+ function isRecord(value: unknown): value is Record<string, unknown> {
96
+ return !!value && typeof value === "object" && !Array.isArray(value);
97
+ }
98
+
99
+ function localizeAuthSchemaObject(
100
+ schema: Record<string, unknown>,
101
+ options: {
102
+ catalogs: ProviderLocaleCatalogMap;
103
+ locale: ProviderLocale;
104
+ fallbackLocale: ProviderLocale;
105
+ },
106
+ ): Record<string, unknown> {
107
+ const properties = isRecord(schema.properties)
108
+ ? schema.properties
109
+ : undefined;
110
+ if (!properties) return schema;
111
+
112
+ let changed = false;
113
+ const localizedProperties = Object.fromEntries(
114
+ Object.entries(properties).map(([fieldName, property]) => {
115
+ if (!isRecord(property)) return [fieldName, property];
116
+ const nameKey =
117
+ typeof property.nameKey === "string" ? property.nameKey : undefined;
118
+ const descriptionKey =
119
+ typeof property.descriptionKey === "string"
120
+ ? property.descriptionKey
121
+ : undefined;
122
+ const title = nameKey
123
+ ? asStringValue(
124
+ resolveProviderLocaleValue(
125
+ options.catalogs,
126
+ nameKey,
127
+ options.locale,
128
+ options.fallbackLocale,
129
+ ),
130
+ )
131
+ : undefined;
132
+ const description = descriptionKey
133
+ ? asStringValue(
134
+ resolveProviderLocaleValue(
135
+ options.catalogs,
136
+ descriptionKey,
137
+ options.locale,
138
+ options.fallbackLocale,
139
+ ),
140
+ )
141
+ : undefined;
142
+ if (!title && !description) return [fieldName, property];
143
+ changed = true;
144
+ return [
145
+ fieldName,
146
+ {
147
+ ...property,
148
+ ...(title ? { title } : {}),
149
+ ...(description ? { description } : {}),
150
+ },
151
+ ];
152
+ }),
153
+ );
154
+
155
+ return changed ? { ...schema, properties: localizedProperties } : schema;
156
+ }
157
+
158
+ export function localizeAuthTurn(
159
+ turn: AuthTurn,
160
+ options: {
161
+ catalogs: ProviderLocaleCatalogMap;
162
+ locale: ProviderLocale;
163
+ fallbackLocale?: ProviderLocale;
164
+ },
165
+ ): AuthTurn {
166
+ const fallbackLocale = options.fallbackLocale ?? "en";
167
+ const hint = turn.hintKey
168
+ ? asStringValue(
169
+ resolveProviderLocaleValue(
170
+ options.catalogs,
171
+ turn.hintKey,
172
+ options.locale,
173
+ fallbackLocale,
174
+ ),
175
+ )
176
+ : undefined;
177
+ const expectedInput = localizeAuthInputSchema(turn.expectedInput, {
178
+ catalogs: options.catalogs,
179
+ locale: options.locale,
180
+ fallbackLocale,
181
+ });
182
+ const fieldErrorKeys = turn.data?.fieldErrorKeys;
183
+ const fieldErrors = isStringRecord(fieldErrorKeys)
184
+ ? Object.fromEntries(
185
+ Object.entries(fieldErrorKeys).flatMap(([fieldName, key]) => {
186
+ const message = asStringValue(
187
+ resolveProviderLocaleValue(
188
+ options.catalogs,
189
+ key,
190
+ options.locale,
191
+ fallbackLocale,
192
+ ),
193
+ );
194
+ return message ? [[fieldName, message]] : [];
195
+ }),
196
+ )
197
+ : undefined;
198
+
199
+ if (!hint && !fieldErrors && !expectedInput) return turn;
200
+
201
+ return {
202
+ ...turn,
203
+ ...(hint ? { hint } : {}),
204
+ ...(expectedInput ? { expectedInput } : {}),
205
+ ...(fieldErrors
206
+ ? {
207
+ data: {
208
+ ...(turn.data ?? {}),
209
+ fieldErrors,
210
+ },
211
+ }
212
+ : {}),
213
+ };
214
+ }
215
+
216
+ export function validateProviderLocaleCatalogs(options: {
217
+ catalogs: ProviderLocaleCatalogMap;
218
+ requiredLocales: readonly ProviderLocale[];
219
+ requiredKeys: readonly (ProviderLocaleKey | string)[];
220
+ }): ProviderLocaleValidationResult {
221
+ const issues: ProviderLocaleValidationIssue[] = [];
222
+ const uniqueKeys = Array.from(
223
+ new Set(
224
+ options.requiredKeys.map((key) => {
225
+ providerLocaleKey(key);
226
+ return key;
227
+ }),
228
+ ),
229
+ );
230
+
231
+ for (const locale of options.requiredLocales) {
232
+ const catalog = options.catalogs[locale];
233
+ if (!catalog) {
234
+ issues.push({
235
+ locale,
236
+ key: "*",
237
+ message: `Missing provider locale catalog for ${locale}`,
238
+ severity: "error",
239
+ });
240
+ continue;
241
+ }
242
+
243
+ for (const key of uniqueKeys) {
244
+ const value = getProviderLocalePath(catalog, key);
245
+ if (value === undefined) {
246
+ issues.push({
247
+ locale,
248
+ key,
249
+ message: `Missing provider locale key ${key} in ${locale}`,
250
+ severity: "error",
251
+ });
252
+ continue;
253
+ }
254
+ if (!isProviderLocaleValue(value)) {
255
+ issues.push({
256
+ locale,
257
+ key,
258
+ message: `Provider locale key ${key} must resolve to a string or string array`,
259
+ severity: "error",
260
+ });
261
+ continue;
262
+ }
263
+ for (const text of Array.isArray(value) ? value : [value]) {
264
+ if (text.trim().length === 0 || /\bTODO\b/i.test(text)) {
265
+ issues.push({
266
+ locale,
267
+ key,
268
+ message: `Provider locale key ${key} in ${locale} is empty or placeholder text`,
269
+ severity: "error",
270
+ });
271
+ }
272
+ }
273
+ }
274
+ }
275
+
276
+ return { ok: issues.every((issue) => issue.severity !== "error"), issues };
277
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./catalog";
2
+ export * from "./keys";
@@ -0,0 +1,64 @@
1
+ import type { ProviderLocaleKey } from "../types";
2
+
3
+ export type { ProviderLocale, ProviderLocaleKey } from "../types";
4
+
5
+ const PROVIDER_LOCALE_KEY_RE =
6
+ /^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]+)*(?:\.[a-z][a-z0-9]*(?:[A-Z][a-z0-9]+)*|\.[0-9]+)*$/;
7
+
8
+ export function providerLocaleKey(key: string): ProviderLocaleKey {
9
+ assertProviderLocaleKey(key);
10
+ return key;
11
+ }
12
+
13
+ export function isProviderLocaleKey(
14
+ value: unknown,
15
+ ): value is ProviderLocaleKey {
16
+ return typeof value === "string" && PROVIDER_LOCALE_KEY_RE.test(value);
17
+ }
18
+
19
+ export function assertProviderLocaleKey(
20
+ value: unknown,
21
+ ): asserts value is ProviderLocaleKey {
22
+ if (!isProviderLocaleKey(value)) {
23
+ throw new Error(
24
+ `Provider locale key must be a dot path such as "meta.description" or "operations.search.description"; received ${JSON.stringify(value)}`,
25
+ );
26
+ }
27
+ }
28
+
29
+ export function qualifyProviderLocaleKey(
30
+ providerId: string,
31
+ key: ProviderLocaleKey | string,
32
+ ): string {
33
+ assertProviderLocaleKey(key);
34
+ return `providers.${providerId}.${key}`;
35
+ }
36
+
37
+ export function getProviderLocalePath(
38
+ catalog: ProviderLocaleCatalog,
39
+ key: ProviderLocaleKey | string,
40
+ ): ProviderLocaleValue | undefined {
41
+ assertProviderLocaleKey(key);
42
+ let cursor: unknown = catalog;
43
+ for (const segment of key.split(".")) {
44
+ if (!isRecord(cursor)) return undefined;
45
+ cursor = cursor[segment];
46
+ }
47
+ return isProviderLocaleValue(cursor) ? cursor : undefined;
48
+ }
49
+
50
+ export type ProviderLocaleValue = string | readonly string[];
51
+ export type ProviderLocaleCatalog = Record<string, unknown>;
52
+
53
+ export function isProviderLocaleValue(
54
+ value: unknown,
55
+ ): value is ProviderLocaleValue {
56
+ return (
57
+ typeof value === "string" ||
58
+ (Array.isArray(value) && value.every((entry) => typeof entry === "string"))
59
+ );
60
+ }
61
+
62
+ function isRecord(value: unknown): value is Record<string, unknown> {
63
+ return typeof value === "object" && value !== null && !Array.isArray(value);
64
+ }
package/src/index.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  // @apifuse/provider-sdk
2
2
 
3
- export { z } from "zod";
3
+ export * from "./auth";
4
4
  export * from "./ceremonies";
5
+ export * from "./choice-token";
5
6
  export type {
6
7
  ApiFuseConfig,
7
8
  BrowserConfig,
@@ -9,10 +10,31 @@ export type {
9
10
  SessionConfig,
10
11
  } from "./config/loader";
11
12
  export { defineConfig, loadApiFuseConfig } from "./config/loader";
12
- export { defineOperation, defineProvider, type ProviderConfig } from "./define";
13
+ export {
14
+ canonicalJson,
15
+ digestProviderContract,
16
+ extractProviderContract,
17
+ type JsonPrimitive,
18
+ type JsonValue,
19
+ PROVIDER_CONTRACT_SCHEMA_VERSION,
20
+ type ProviderContractOperation,
21
+ type ProviderContractSnapshot,
22
+ } from "./contract";
23
+ export {
24
+ centered,
25
+ delayed,
26
+ defineHealthJourney,
27
+ defineOperation,
28
+ defineProvider,
29
+ defineSmsOtpMatcher,
30
+ defineStreamOperation,
31
+ every,
32
+ type ProviderConfig,
33
+ } from "./define";
13
34
  export type { DevServerOptions } from "./dev";
14
35
  export { createDevServer, startDevServer } from "./dev";
15
36
  export * from "./errors";
37
+ export * from "./i18n";
16
38
  export {
17
39
  type LintDiagnostic,
18
40
  lintOperation,
@@ -23,6 +45,18 @@ export * from "./recipes/rest-api";
23
45
  export { createFlowContext, createScratchpad } from "./runtime/auth-flow";
24
46
  export type { BrowserClientOptions } from "./runtime/browser";
25
47
  export { BrowserClient, createBrowserClient } from "./runtime/browser";
48
+ export {
49
+ createBypassProviderCache,
50
+ createProviderCache,
51
+ type ProviderCacheOptions,
52
+ resetProviderCacheForTests,
53
+ } from "./runtime/cache";
54
+ export {
55
+ type CreateProviderChoiceContextOptions,
56
+ createProviderChoiceContext,
57
+ createTestProviderChoiceContext,
58
+ PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
59
+ } from "./runtime/choice";
26
60
  export {
27
61
  type CreateCredentialContextOptions,
28
62
  createCredentialContext,
@@ -39,30 +73,71 @@ export {
39
73
  } from "./runtime/instrumentation";
40
74
  export { type PrevalidateResult, prevalidate } from "./runtime/prevalidate";
41
75
  export { getProviderBaseUrl } from "./runtime/provider";
42
- export { createTlsClient } from "./runtime/tls";
76
+ export {
77
+ createUnsupportedProviderRuntimeState,
78
+ UnsupportedProviderStateError,
79
+ } from "./runtime/state";
80
+ export { createStealthClient } from "./runtime/stealth";
81
+ export {
82
+ APIFUSE__STT__BACKEND_ENV,
83
+ APIFUSE__STT__CLOUDFLARE_API_TOKEN_ENV,
84
+ APIFUSE__STT__MODEL_ENV,
85
+ createSttClientFromEnv,
86
+ createUnsupportedSttClient,
87
+ extractVerificationCode,
88
+ resolveSttPrompt,
89
+ } from "./runtime/stt";
43
90
  export {
44
91
  type CreateTraceContextOptions,
45
92
  createTraceContext,
46
93
  type Span,
47
94
  type TraceContext,
48
95
  } from "./runtime/trace";
96
+ export {
97
+ APIFUSE_DESCRIPTION_KEY_META_KEY,
98
+ APIFUSE_REDACTION_MARKER,
99
+ APIFUSE_SENSITIVE_KIND_META_KEY,
100
+ APIFUSE_SENSITIVE_META_KEY,
101
+ collectSensitivePaths,
102
+ describeKey,
103
+ field,
104
+ fields,
105
+ isSensitiveSchema,
106
+ redactPayload,
107
+ type SensitiveFieldKind,
108
+ type SensitiveFieldOptions,
109
+ type SensitivePath,
110
+ sensitive,
111
+ z,
112
+ } from "./schema";
49
113
  export { createServerApp, type ServeOptions, serve } from "./server";
50
114
  export { getStealthProfile, listStealthProfiles } from "./stealth/profiles";
115
+ export * from "./stream";
51
116
  export type {
52
117
  ApiFuseResponse,
53
118
  AuthConfig,
54
119
  AuthContext,
55
120
  AuthFlowDefinition,
56
- AuthFlowHandler,
121
+ AuthFlowInputHandler,
122
+ AuthFlowStartHandler,
57
123
  AuthMode,
58
124
  AuthTurn,
125
+ Bcp47Locale,
59
126
  BrowserEngine,
60
127
  BrowserOptions,
128
+ BrowserResourceBody,
129
+ BrowserResourceDecision,
130
+ BrowserResourceMethod,
131
+ BrowserResourcePolicy,
132
+ BrowserResourceRequest,
133
+ BrowserResourceRoute,
61
134
  ConnectionMode,
62
135
  ContextDeclaration,
136
+ CookieJar,
63
137
  ContextScratchpad,
64
138
  CredentialContext,
65
139
  CredentialDeclaration,
140
+ E164PhoneNumber,
66
141
  EnvContext,
67
142
  FlowContext,
68
143
  FlowContextStore,
@@ -71,35 +146,140 @@ export type {
71
146
  HealthCheckCaseResult,
72
147
  HealthCheckSuite,
73
148
  HealthCheckUnsupported,
149
+ HealthJourneyDefinition,
150
+ HealthJourneyEventContext,
151
+ HealthJourneyGatewayContext,
152
+ HealthJourneyJournalContext,
153
+ HealthJourneyManualTriggerPolicy,
154
+ HealthJourneyRunContext,
155
+ HealthJourneyRunResult,
156
+ HealthJourneySchedule,
157
+ HealthScheduleRandomization,
158
+ HealthJourneySmsContext,
159
+ HealthJourneyStep,
74
160
  HttpClient,
161
+ HttpMethod,
75
162
  HttpResponse,
163
+ HttpRetryOptions,
164
+ HttpRetrySummary,
165
+ HttpStreamResponse,
166
+ IanaTimeZone,
76
167
  InferSchemaOutput,
168
+ Iso3166Alpha2CountryCode,
169
+ Iso4217CurrencyCode,
170
+ Iso8601Duration,
77
171
  OperationAnnotations,
172
+ OperationApprovalPolicy,
173
+ OperationContractMetadata,
78
174
  OperationDefinition,
175
+ OperationDeprecationMetadata,
79
176
  OperationDocMeta,
80
177
  OperationErrorCode,
178
+ OperationHandlerResult,
81
179
  OperationInputExample,
180
+ OperationLifecycle,
181
+ OperationObservabilityConfig,
182
+ OperationObservabilitySensitiveConfig,
82
183
  OperationRelationships,
184
+ OperationRiskClass,
185
+ OperationSensitivePath,
186
+ OperationToolRouterMetadata,
187
+ OperationTransport,
188
+ OperationTransportKind,
83
189
  ProbeInterval,
190
+ ProviderAccessConfig,
191
+ ProviderAccessVisibility,
192
+ ProviderCache,
193
+ ProviderCacheGetOrSetOptions,
194
+ ProviderCacheKeyOptions,
195
+ ProviderCacheLookupMeta,
196
+ ProviderCacheResponseMeta,
197
+ ProviderCacheResult,
198
+ ProviderChoiceBindingOptions,
199
+ ProviderChoiceContext,
200
+ ProviderChoiceIssueOptions,
201
+ ProviderChoiceParseOptions,
84
202
  ProviderContext,
85
203
  ProviderDefinition,
86
204
  ProviderHealthMonitorConfig,
205
+ ProviderLocale,
206
+ ProviderLocaleKey,
207
+ ProviderLocaleKeyInput,
208
+ ProviderLogoProfile,
209
+ ProviderLogoSource,
87
210
  ProviderMeta,
211
+ ProviderProxyConfig,
212
+ ProviderProxyMode,
213
+ ProviderProxyPolicy,
214
+ ProviderProxyProvider,
215
+ ProviderProxySessionAffinity,
216
+ ProviderPublicConnectionMode,
217
+ ProviderPublicProfile,
88
218
  ProviderReviewed,
219
+ ProviderRuntimeState,
89
220
  ProviderSecretDeclaration,
221
+ ProviderStateDurationString,
222
+ ProviderStateNamespace,
223
+ ProviderStreamEvent,
224
+ ProviderSttConfig,
225
+ ProviderSttMode,
226
+ ProviderSupportLevel,
90
227
  RequestOptions,
228
+ Rfc3339Instant,
91
229
  SchemaLike,
230
+ SmsOrigin,
231
+ SmsOtpExtractionPattern,
232
+ SmsOtpMatcherDefinition,
233
+ SseMessage,
92
234
  StandardSchemaV1,
235
+ StateCasResult,
236
+ StateNamespaceOptions,
237
+ StateValue,
238
+ StateWriteOptions,
239
+ StealthClient,
240
+ StealthFetchOptions,
93
241
  StealthPlatform,
94
242
  StealthProfile,
95
- TlsClient,
96
- TlsFetchOptions,
97
- TlsResponse,
98
- TlsSession,
243
+ StealthRedirectHop,
244
+ StealthRedirectRunOptions,
245
+ StealthRedirectRunResult,
246
+ StealthResponse,
247
+ StealthSession,
248
+ StealthSessionCookies,
249
+ SttAudioInput,
250
+ SttContext,
251
+ SttPromptPolicy,
252
+ SttSegment,
253
+ SttTranscribeMode,
254
+ SttTranscribeRequest,
255
+ SttTranscript,
256
+ SttUnsupportedOptionPolicy,
257
+ SttUsage,
258
+ SttVerificationCodeOptions,
259
+ SttWarning,
99
260
  TraceConfig,
100
261
  TraceSpan,
262
+ VerificationCodeCandidate,
263
+ VerificationCodeCandidateSource,
264
+ VerificationCodeExtractionResult,
265
+ } from "./types";
266
+ export {
267
+ DEFAULT_OPERATION_TRANSPORT,
268
+ HttpRetryAfterPolicy,
269
+ HttpRetryDelayStrategy,
270
+ HttpRetryJitter,
271
+ HttpRetryPreset,
272
+ HttpRetryUnsafeMethodPolicy,
273
+ PROBE_INTERVALS,
274
+ STREAM_CHUNK_BYTES_MAX,
275
+ STREAM_CHUNK_BYTES_MIN,
276
+ STREAM_HEARTBEAT_MS_MAX,
277
+ STREAM_HEARTBEAT_MS_MIN,
278
+ STREAM_IDLE_TIMEOUT_MS_MAX,
279
+ STREAM_IDLE_TIMEOUT_MS_MIN,
280
+ STREAM_MAX_DURATION_MS_MAX,
281
+ STREAM_MAX_DURATION_MS_MIN,
101
282
  } from "./types";
102
- export { PROBE_INTERVALS } from "./types";
103
283
  export * from "./utils/date";
104
284
  export * from "./utils/parse";
105
285
  export * from "./utils/text";