@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,5 @@
1
+ export declare const PROVIDER_OBSERVABILITY_TAXONOMY_VERSION = "2026-05-26";
2
+ export declare const PROVIDER_ERROR_CATEGORIES: readonly ["ok", "timeout", "network", "upstream_http", "upstream_rate_limited", "upstream_auth", "upstream_schema_drift", "proxy_pool", "anti_bot_blocked", "credential_expired", "credential_unavailable", "input_validation", "output_validation", "provider_error", "internal_error", "unclassified"];
3
+ export type ProviderErrorCategory = (typeof PROVIDER_ERROR_CATEGORIES)[number];
4
+ export declare function categoryForStatus(status: number): ProviderErrorCategory;
5
+ export declare function isRetryableCategory(category: ProviderErrorCategory): boolean;
@@ -0,0 +1,39 @@
1
+ export const PROVIDER_OBSERVABILITY_TAXONOMY_VERSION = "2026-05-26";
2
+ export const PROVIDER_ERROR_CATEGORIES = [
3
+ "ok",
4
+ "timeout",
5
+ "network",
6
+ "upstream_http",
7
+ "upstream_rate_limited",
8
+ "upstream_auth",
9
+ "upstream_schema_drift",
10
+ "proxy_pool",
11
+ "anti_bot_blocked",
12
+ "credential_expired",
13
+ "credential_unavailable",
14
+ "input_validation",
15
+ "output_validation",
16
+ "provider_error",
17
+ "internal_error",
18
+ "unclassified",
19
+ ];
20
+ export function categoryForStatus(status) {
21
+ if (status >= 200 && status < 400)
22
+ return "ok";
23
+ if (status === 408 || status === 504)
24
+ return "timeout";
25
+ if (status === 429)
26
+ return "upstream_rate_limited";
27
+ if (status === 401 || status === 403)
28
+ return "upstream_auth";
29
+ if (status >= 400)
30
+ return "upstream_http";
31
+ return "unclassified";
32
+ }
33
+ export function isRetryableCategory(category) {
34
+ return (category === "timeout" ||
35
+ category === "network" ||
36
+ category === "upstream_rate_limited" ||
37
+ category === "upstream_http" ||
38
+ category === "proxy_pool");
39
+ }
@@ -0,0 +1,9 @@
1
+ export { createFormCeremony } from "./ceremonies";
2
+ export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, type ProviderChoiceTokenErrorReason, type ProviderChoiceTokenPayload, parseProviderChoiceToken, } from "./choice-token";
3
+ export { defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define";
4
+ export { AuthError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors";
5
+ export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n";
6
+ export { type CreateProviderChoiceContextOptions, createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice";
7
+ export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, type SensitiveFieldKind, type SensitiveFieldOptions, type SensitivePath, sensitive, z, } from "./schema";
8
+ export type { AuthMode, FlowContext, HealthCheckAssertionContext, HealthCheckCase, HealthCheckSuite, HealthCheckUnsupported, HealthJourneyDefinition, HealthJourneyEventContext, HealthJourneyManualTriggerPolicy, HealthJourneyRunContext, HealthJourneyRunResult, HttpRetryOptions, HttpRetrySummary, InferSchemaOutput, OperationApprovalPolicy, OperationContractMetadata, OperationDefinition, OperationDocMeta, OperationErrorCode, OperationInputExample, OperationLifecycle, OperationObservabilityConfig, OperationObservabilitySensitiveConfig, OperationRelationships, OperationRiskClass, OperationSensitivePath, OperationToolRouterMetadata, OperationTransport, ProviderAccessVisibility, ProviderChoiceBindingOptions, ProviderChoiceContext, ProviderChoiceIssueOptions, ProviderChoiceParseOptions, ProviderContext, ProviderDefinition, ProviderLocale, ProviderLocaleKey, ProviderLocaleKeyInput, ProviderLogoProfile, ProviderProxyPolicy, ProviderPublicConnectionMode, ProviderPublicProfile, ProviderRuntimeState, ProviderStateDurationString, ProviderStateNamespace, ProviderSupportLevel, SchemaLike, SmsOtpMatcherDefinition, StandardSchemaV1, StateCasResult, StateNamespaceOptions, StateValue, StateWriteOptions, } from "./types";
9
+ export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types";
@@ -0,0 +1,8 @@
1
+ export { createFormCeremony } from "./ceremonies";
2
+ export { assertFreshProviderChoiceIssuedAt, createProviderChoiceToken, ProviderChoiceTokenError, parseProviderChoiceToken, } from "./choice-token";
3
+ export { defineHealthJourney, defineOperation, defineProvider, defineSmsOtpMatcher, every, } from "./define";
4
+ export { AuthError, ProviderError, SessionExpiredError, TransportError, ValidationError, } from "./errors";
5
+ export { getProviderLocalePath, providerLocaleKey, qualifyProviderLocaleKey, } from "./i18n";
6
+ export { createProviderChoiceContext, createTestProviderChoiceContext, PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV, } from "./runtime/choice";
7
+ export { APIFUSE_DESCRIPTION_KEY_META_KEY, APIFUSE_REDACTION_MARKER, APIFUSE_SENSITIVE_KIND_META_KEY, APIFUSE_SENSITIVE_META_KEY, collectSensitivePaths, describeKey, field, fields, isSensitiveSchema, redactPayload, sensitive, z, } from "./schema";
8
+ export { HttpRetryAfterPolicy, HttpRetryDelayStrategy, HttpRetryJitter, HttpRetryPreset, HttpRetryUnsafeMethodPolicy, } from "./types";
@@ -0,0 +1,2 @@
1
+ import type { LintDiagnostic } from "./lint";
2
+ export declare function lintPublicSchemaFieldNames(providerId: string | undefined, operationId: string, input: unknown, output: unknown, enforce: boolean): LintDiagnostic[];
@@ -0,0 +1,158 @@
1
+ const ESTABLISHED_APIFUSE_PROTOCOL_FIELDS = new Set(["externalRef"]);
2
+ const UPSTREAM_FIELD_REPLACEMENTS = new Map([
3
+ ["display", "limit"],
4
+ ["start", "offset"],
5
+ ["sort", "sort_by"],
6
+ ["lprice", "lowest_price"],
7
+ ["hprice", "highest_price"],
8
+ ["mallName", "mall_name"],
9
+ ["productId", "product_id"],
10
+ ["productType", "product_type_code"],
11
+ ["lastBuildDate", "upstream_generated_at"],
12
+ ["meta", "summary"],
13
+ ]);
14
+ function isSchema(value) {
15
+ return (!!value &&
16
+ typeof value === "object" &&
17
+ "safeParse" in value &&
18
+ typeof value.safeParse === "function");
19
+ }
20
+ function getSchemaDef(schema) {
21
+ const def = schema.def ?? schema._def;
22
+ return def && typeof def === "object" ? def : {};
23
+ }
24
+ function isSchemaRecord(value) {
25
+ if (!value || typeof value !== "object") {
26
+ return false;
27
+ }
28
+ return Object.values(value).every(isSchema);
29
+ }
30
+ function getObjectShape(schema) {
31
+ const rawShape = typeof schema.shape === "function" ? schema.shape() : schema.shape;
32
+ if (isSchemaRecord(rawShape)) {
33
+ return rawShape;
34
+ }
35
+ const defShape = getSchemaDef(schema).shape;
36
+ if (typeof defShape === "function") {
37
+ const resolved = defShape();
38
+ return isSchemaRecord(resolved) ? resolved : {};
39
+ }
40
+ return isSchemaRecord(defShape) ? defShape : {};
41
+ }
42
+ function appendSchemaChildren(children, value) {
43
+ if (isSchema(value)) {
44
+ children.push(value);
45
+ return children;
46
+ }
47
+ if (Array.isArray(value)) {
48
+ children.push(...value.filter(isSchema));
49
+ return children;
50
+ }
51
+ if (value instanceof Set) {
52
+ children.push(...Array.from(value).filter(isSchema));
53
+ return children;
54
+ }
55
+ if (value instanceof Map) {
56
+ children.push(...Array.from(value.values()).filter(isSchema));
57
+ return children;
58
+ }
59
+ return children;
60
+ }
61
+ function safeSourceType(schema) {
62
+ try {
63
+ return schema.sourceType?.();
64
+ }
65
+ catch {
66
+ return undefined;
67
+ }
68
+ }
69
+ function safeUnwrap(schema) {
70
+ try {
71
+ return schema.unwrap?.();
72
+ }
73
+ catch {
74
+ return undefined;
75
+ }
76
+ }
77
+ function getTransparentChildSchemas(schema) {
78
+ const def = getSchemaDef(schema);
79
+ const children = [];
80
+ for (const value of [
81
+ schema.element,
82
+ schema.items,
83
+ schema.options,
84
+ schema.innerType,
85
+ safeSourceType(schema),
86
+ safeUnwrap(schema),
87
+ schema.in,
88
+ schema.out,
89
+ schema.left,
90
+ schema.right,
91
+ def.schema,
92
+ def.innerType,
93
+ def.type,
94
+ def.valueType,
95
+ def.item,
96
+ def.items,
97
+ def.rest,
98
+ def.catchall,
99
+ def.option,
100
+ def.options,
101
+ def.pipe,
102
+ def.payload,
103
+ def.sourceType,
104
+ def.left,
105
+ def.right,
106
+ ]) {
107
+ appendSchemaChildren(children, value);
108
+ }
109
+ return children;
110
+ }
111
+ function recommendedReplacement(fieldName) {
112
+ if (/^category\d+$/.test(fieldName)) {
113
+ return "category_path";
114
+ }
115
+ if (UPSTREAM_FIELD_REPLACEMENTS.has(fieldName)) {
116
+ return UPSTREAM_FIELD_REPLACEMENTS.get(fieldName);
117
+ }
118
+ if (/[a-z][A-Z]/.test(fieldName)) {
119
+ return fieldName.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
120
+ }
121
+ return undefined;
122
+ }
123
+ function collectPublicSchemaFieldDiagnostics(providerId, operationId, schema, basePath, seen = new Set()) {
124
+ if (!isSchema(schema) || seen.has(schema)) {
125
+ return [];
126
+ }
127
+ seen.add(schema);
128
+ const diagnostics = [];
129
+ for (const [fieldName, child] of Object.entries(getObjectShape(schema))) {
130
+ const fieldPath = `${basePath}.${fieldName}`;
131
+ const replacement = ESTABLISHED_APIFUSE_PROTOCOL_FIELDS.has(fieldName)
132
+ ? undefined
133
+ : recommendedReplacement(fieldName);
134
+ if (replacement) {
135
+ diagnostics.push({
136
+ rule: "public-schema-upstream-field",
137
+ level: "error",
138
+ field: fieldPath,
139
+ message: `Provider "${providerId}" operation "${operationId}" public schema field "${fieldPath}" uses upstream-shaped field "${fieldName}"; use APIFuse field "${replacement}" instead.`,
140
+ });
141
+ }
142
+ diagnostics.push(...collectPublicSchemaFieldDiagnostics(providerId, operationId, child, fieldPath, seen));
143
+ }
144
+ for (const child of getTransparentChildSchemas(schema)) {
145
+ const childPath = schema.element === child ? `${basePath}[]` : basePath;
146
+ diagnostics.push(...collectPublicSchemaFieldDiagnostics(providerId, operationId, child, childPath, seen));
147
+ }
148
+ return diagnostics;
149
+ }
150
+ export function lintPublicSchemaFieldNames(providerId, operationId, input, output, enforce) {
151
+ if (!providerId || !enforce) {
152
+ return [];
153
+ }
154
+ return [
155
+ ...collectPublicSchemaFieldDiagnostics(providerId, operationId, input, "input"),
156
+ ...collectPublicSchemaFieldDiagnostics(providerId, operationId, output, "output"),
157
+ ];
158
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Check Korean government API result code
3
+ * Returns true if resultCode matches successCodes (default: ['00', '000', '0000'])
4
+ */
5
+ export declare function checkResultCode(raw: unknown, successCodes?: string[]): boolean;
6
+ /**
7
+ * Replace placeholder values with null
8
+ * e.g., nullIfPlaceholder('해당없음', ['해당없음', '-', '']) → null
9
+ */
10
+ export declare function nullIfPlaceholder(v: unknown, patterns: string[]): unknown | null;
11
+ /**
12
+ * Unwrap Korean government API envelope
13
+ * Handles: {response: {body: {items: {item: ...}}}} nested structure
14
+ */
15
+ export declare function unwrapGovEnvelope(raw: unknown): unknown;
16
+ /**
17
+ * Check if Korean government API returned empty result
18
+ */
19
+ export declare function isEmptyResult(raw: unknown): boolean;
@@ -0,0 +1,72 @@
1
+ import { unwrapEnvelope } from "../utils/parse";
2
+ function getResultCode(raw) {
3
+ if (!raw || typeof raw !== "object") {
4
+ return undefined;
5
+ }
6
+ const record = raw;
7
+ if (typeof record.resultCode === "string") {
8
+ return record.resultCode;
9
+ }
10
+ const response = record.response;
11
+ const header = response?.header;
12
+ return typeof header?.resultCode === "string" ? header.resultCode : undefined;
13
+ }
14
+ /**
15
+ * Check Korean government API result code
16
+ * Returns true if resultCode matches successCodes (default: ['00', '000', '0000'])
17
+ */
18
+ export function checkResultCode(raw, successCodes = ["00", "000", "0000"]) {
19
+ const code = getResultCode(raw);
20
+ return code ? successCodes.includes(code) : false;
21
+ }
22
+ /**
23
+ * Replace placeholder values with null
24
+ * e.g., nullIfPlaceholder('해당없음', ['해당없음', '-', '']) → null
25
+ */
26
+ export function nullIfPlaceholder(v, patterns) {
27
+ if (v === null || v === undefined) {
28
+ return null;
29
+ }
30
+ if (typeof v !== "string") {
31
+ return v;
32
+ }
33
+ const normalized = v.trim();
34
+ return patterns.some((pattern) => normalized === pattern.trim()) ? null : v;
35
+ }
36
+ /**
37
+ * Unwrap Korean government API envelope
38
+ * Handles: {response: {body: {items: {item: ...}}}} nested structure
39
+ */
40
+ export function unwrapGovEnvelope(raw) {
41
+ const item = unwrapEnvelope(raw, "response.body.items.item");
42
+ if (Array.isArray(item)) {
43
+ return item;
44
+ }
45
+ if (item !== undefined && item !== null) {
46
+ return [item];
47
+ }
48
+ const items = unwrapEnvelope(raw, "response.body.items");
49
+ if (Array.isArray(items)) {
50
+ return items;
51
+ }
52
+ if (items !== undefined && items !== null) {
53
+ return items;
54
+ }
55
+ return raw;
56
+ }
57
+ /**
58
+ * Check if Korean government API returned empty result
59
+ */
60
+ export function isEmptyResult(raw) {
61
+ if (getResultCode(raw) === "03") {
62
+ return true;
63
+ }
64
+ const items = unwrapGovEnvelope(raw);
65
+ if (Array.isArray(items)) {
66
+ return items.length === 0;
67
+ }
68
+ if (items && typeof items === "object") {
69
+ return Object.keys(items).length === 0;
70
+ }
71
+ return false;
72
+ }
@@ -0,0 +1,21 @@
1
+ export interface PaginationInfo {
2
+ page: number;
3
+ perPage: number;
4
+ total: number;
5
+ totalPages: number;
6
+ hasNext: boolean;
7
+ hasPrev: boolean;
8
+ }
9
+ /**
10
+ * Extract pagination info from various REST API response shapes.
11
+ * Handles: {page, per_page, total}, {meta: {pagination: {...}}}, {currentPage, totalCount, pageSize}
12
+ */
13
+ export declare function extractPagination(raw: unknown): PaginationInfo | null;
14
+ /**
15
+ * Normalize error response to a standard format.
16
+ * Handles: {error: string}, {message: string}, {errors: []}, {error: {message: string}}
17
+ */
18
+ export declare function normalizeErrorResponse(raw: unknown): {
19
+ message: string;
20
+ code?: string;
21
+ } | null;
@@ -0,0 +1,115 @@
1
+ function toPositiveInteger(value) {
2
+ if (typeof value === "number" && Number.isFinite(value)) {
3
+ return Math.trunc(value);
4
+ }
5
+ if (typeof value === "string" && value.trim() !== "") {
6
+ const parsed = Number.parseInt(value, 10);
7
+ return Number.isNaN(parsed) ? null : parsed;
8
+ }
9
+ return null;
10
+ }
11
+ function readPath(raw, path) {
12
+ if (!raw || typeof raw !== "object") {
13
+ return undefined;
14
+ }
15
+ let current = raw;
16
+ for (const segment of path.split(".")) {
17
+ if (!current || typeof current !== "object") {
18
+ return undefined;
19
+ }
20
+ current = current[segment];
21
+ }
22
+ return current;
23
+ }
24
+ /**
25
+ * Extract pagination info from various REST API response shapes.
26
+ * Handles: {page, per_page, total}, {meta: {pagination: {...}}}, {currentPage, totalCount, pageSize}
27
+ */
28
+ export function extractPagination(raw) {
29
+ const candidates = [
30
+ {
31
+ page: readPath(raw, "page"),
32
+ perPage: readPath(raw, "per_page"),
33
+ total: readPath(raw, "total"),
34
+ },
35
+ {
36
+ page: readPath(raw, "meta.pagination.page"),
37
+ perPage: readPath(raw, "meta.pagination.per_page"),
38
+ total: readPath(raw, "meta.pagination.total"),
39
+ },
40
+ {
41
+ page: readPath(raw, "meta.pagination.currentPage"),
42
+ perPage: readPath(raw, "meta.pagination.pageSize"),
43
+ total: readPath(raw, "meta.pagination.totalCount"),
44
+ },
45
+ {
46
+ page: readPath(raw, "currentPage"),
47
+ perPage: readPath(raw, "pageSize"),
48
+ total: readPath(raw, "totalCount"),
49
+ },
50
+ ];
51
+ for (const candidate of candidates) {
52
+ const page = toPositiveInteger(candidate.page);
53
+ const perPage = toPositiveInteger(candidate.perPage);
54
+ const total = toPositiveInteger(candidate.total);
55
+ if (page === null || perPage === null || total === null) {
56
+ continue;
57
+ }
58
+ const totalPages = perPage > 0 ? Math.ceil(total / perPage) : 0;
59
+ return {
60
+ page,
61
+ perPage,
62
+ total,
63
+ totalPages,
64
+ hasNext: page < totalPages,
65
+ hasPrev: page > 1,
66
+ };
67
+ }
68
+ return null;
69
+ }
70
+ function extractMessage(value) {
71
+ if (typeof value === "string" && value.trim() !== "") {
72
+ return value;
73
+ }
74
+ if (!value || typeof value !== "object") {
75
+ return null;
76
+ }
77
+ const record = value;
78
+ if (typeof record.message === "string" && record.message.trim() !== "") {
79
+ return record.message;
80
+ }
81
+ if (typeof record.error === "string" && record.error.trim() !== "") {
82
+ return record.error;
83
+ }
84
+ return null;
85
+ }
86
+ /**
87
+ * Normalize error response to a standard format.
88
+ * Handles: {error: string}, {message: string}, {errors: []}, {error: {message: string}}
89
+ */
90
+ export function normalizeErrorResponse(raw) {
91
+ if (!raw || typeof raw !== "object") {
92
+ return null;
93
+ }
94
+ const record = raw;
95
+ const directMessage = extractMessage(record.error) ?? extractMessage(record.message);
96
+ if (directMessage) {
97
+ const code = typeof record.code === "string" && record.code.trim() !== ""
98
+ ? record.code
99
+ : undefined;
100
+ return code ? { message: directMessage, code } : { message: directMessage };
101
+ }
102
+ const errors = record.errors;
103
+ if (Array.isArray(errors) && errors.length > 0) {
104
+ for (const item of errors) {
105
+ const message = extractMessage(item);
106
+ if (message) {
107
+ const code = typeof record.code === "string" && record.code.trim() !== ""
108
+ ? record.code
109
+ : undefined;
110
+ return code ? { message, code } : { message };
111
+ }
112
+ }
113
+ }
114
+ return null;
115
+ }
@@ -0,0 +1,14 @@
1
+ import type { ContextScratchpad, EnvContext, FlowContext, HttpClient, StealthClient, SttContext } from "../types";
2
+ export declare function createScratchpad(allowedKeys: string[], initial?: Record<string, unknown>): ContextScratchpad;
3
+ export declare function createFlowContext(options: {
4
+ http: HttpClient;
5
+ stealth: StealthClient;
6
+ env: EnvContext;
7
+ tenantId: string;
8
+ providerId: string;
9
+ connectionId?: string;
10
+ externalRef?: string;
11
+ allowedKeys: string[];
12
+ initialContext?: Record<string, unknown>;
13
+ stt?: SttContext;
14
+ }): FlowContext;
@@ -0,0 +1,44 @@
1
+ import { ContextAccessError } from "../errors";
2
+ import { createUnsupportedSttClient } from "./stt";
3
+ function normalizeAllowedKeys(allowedKeys) {
4
+ return new Set(allowedKeys.filter((key) => key.trim().length > 0));
5
+ }
6
+ function assertAllowedKey(allowedKeys, key) {
7
+ if (!allowedKeys.has(key)) {
8
+ throw new ContextAccessError(`Context key "${key}" is not declared in context.keys.`);
9
+ }
10
+ }
11
+ export function createScratchpad(allowedKeys, initial = {}) {
12
+ const normalizedAllowedKeys = normalizeAllowedKeys(allowedKeys);
13
+ const values = new Map();
14
+ for (const [key, value] of Object.entries(initial)) {
15
+ assertAllowedKey(normalizedAllowedKeys, key);
16
+ values.set(key, value);
17
+ }
18
+ return {
19
+ get(key) {
20
+ assertAllowedKey(normalizedAllowedKeys, key);
21
+ return values.get(key);
22
+ },
23
+ set(key, value) {
24
+ assertAllowedKey(normalizedAllowedKeys, key);
25
+ values.set(key, value);
26
+ },
27
+ toJSON() {
28
+ return Object.fromEntries(values.entries());
29
+ },
30
+ };
31
+ }
32
+ export function createFlowContext(options) {
33
+ return {
34
+ connectionId: options.connectionId,
35
+ externalRef: options.externalRef,
36
+ tenantId: options.tenantId,
37
+ providerId: options.providerId,
38
+ http: options.http,
39
+ stealth: options.stealth,
40
+ env: options.env,
41
+ context: createScratchpad(options.allowedKeys, options.initialContext),
42
+ stt: options.stt ?? createUnsupportedSttClient(),
43
+ };
44
+ }
@@ -0,0 +1,25 @@
1
+ import type { BrowserChallengeRequest, BrowserChallengeResult, BrowserClient as BrowserClientContract, BrowserEngine, BrowserOptions, BrowserPage } from "../types";
2
+ type BrowserPageContract = BrowserPage;
3
+ export type BrowserClientOptions = BrowserOptions & {
4
+ allowedHosts?: string[];
5
+ cdpUrl?: string;
6
+ executablePath?: string;
7
+ extraArgs?: string[];
8
+ };
9
+ export declare class BrowserClient implements BrowserClientContract {
10
+ private readonly client;
11
+ private readonly cdpUrl?;
12
+ private activePage?;
13
+ private readonly activePages;
14
+ private readonly _engine;
15
+ constructor(options?: BrowserClientOptions);
16
+ get engine(): BrowserEngine;
17
+ newPage(): Promise<BrowserPageContract>;
18
+ rawPage(): Promise<BrowserPageContract>;
19
+ withIsolatedContext<T>(handler: (page: BrowserPageContract) => Promise<T>): Promise<T>;
20
+ private activatePage;
21
+ solveChallenge(request: BrowserChallengeRequest): Promise<BrowserChallengeResult>;
22
+ close(): Promise<void>;
23
+ }
24
+ export declare function createBrowserClient(options?: BrowserClientOptions): BrowserClient;
25
+ export {};