@mailwoman/api 9.2.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{app.ts → lib/app.ts} +29 -6
- package/{engine.ts → lib/engine.ts} +2 -2
- package/{index.ts → lib/index.ts} +4 -4
- package/{routes.ts → lib/routes.ts} +34 -21
- package/{schema.ts → lib/schema.ts} +125 -13
- package/out/app.d.ts +9 -2
- package/out/app.d.ts.map +1 -1
- package/out/app.js +16 -4
- package/out/app.js.map +1 -1
- package/out/engine.d.ts +2 -2
- package/out/engine.d.ts.map +1 -1
- package/out/engine.js.map +1 -1
- package/out/index.d.ts +4 -4
- package/out/index.d.ts.map +1 -1
- package/out/index.js +4 -4
- package/out/index.js.map +1 -1
- package/out/routes.d.ts +8 -3
- package/out/routes.d.ts.map +1 -1
- package/out/routes.js +20 -19
- package/out/routes.js.map +1 -1
- package/out/schema.d.ts +341 -10
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js +112 -13
- package/out/schema.js.map +1 -1
- package/package.json +23 -9
package/{app.ts → lib/app.ts}
RENAMED
|
@@ -9,15 +9,24 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { OpenAPIHono } from "@hono/zod-openapi"
|
|
12
|
-
import {
|
|
12
|
+
import { attachOpenAPIDocs, engineHeaders, errorResponse, type OpenAPIDocInfo } from "@mailwoman/api-kit"
|
|
13
|
+
import { readLocalJSONFile } from "@mailwoman/core/fs/readers"
|
|
14
|
+
import type { EngineStamp } from "@mailwoman/core/license"
|
|
15
|
+
import { resolvePackagePath } from "@mailwoman/core/module/resolvers"
|
|
13
16
|
import { bodyLimit } from "hono/body-limit"
|
|
14
17
|
import { cors } from "hono/cors"
|
|
15
18
|
|
|
16
|
-
import
|
|
19
|
+
import type { MailwomanAPIEngine } from "#engine"
|
|
20
|
+
import { DEFAULT_BATCH_MAX, registerMailwomanAPIRoutes } from "#routes"
|
|
21
|
+
import type { GeocodeOutcomeLike } from "#schema"
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
/**
|
|
24
|
+
* This package's own manifest, read at load rather than imported as a module: a JSON import makes `tsc` copy the file
|
|
25
|
+
* into `out/`, where it becomes the package scope for the compiled tree and breaks every `#` import in it.
|
|
26
|
+
*/
|
|
27
|
+
const packageJson = await readLocalJSONFile<{ name: string; version: string; description: string }>(
|
|
28
|
+
resolvePackagePath("@mailwoman/api", "package.json")
|
|
29
|
+
)
|
|
21
30
|
|
|
22
31
|
/**
|
|
23
32
|
* 2 MiB — carried from the express server's `express.json({ limit: "2mb" })` (`mailwoman/server/index.ts`).
|
|
@@ -45,6 +54,13 @@ export interface MailwomanAPIOptions {
|
|
|
45
54
|
* Max `addresses` rows accepted by `POST /v1/batch`. Default 500 (see `routes.ts`'s `DEFAULT_BATCH_MAX`).
|
|
46
55
|
*/
|
|
47
56
|
batchMax?: number
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The engine stamp to carry on every response: `engine` in each `/v1` body and the `Server` + `Link: rel="license"`
|
|
60
|
+
* headers everywhere. Absent when an embedding application builds the app without the `mailwoman` package; the
|
|
61
|
+
* `mailwoman serve` command always passes one.
|
|
62
|
+
*/
|
|
63
|
+
engine?: EngineStamp
|
|
48
64
|
}
|
|
49
65
|
|
|
50
66
|
/**
|
|
@@ -110,6 +126,10 @@ export function createMailwomanAPI<T extends Partial<GeocodeOutcomeLike> = Geoco
|
|
|
110
126
|
app.use(cors({ origin: "*", allowMethods: ["GET", "POST", "OPTIONS"], allowHeaders: ["*"], maxAge: 86_400 }))
|
|
111
127
|
}
|
|
112
128
|
|
|
129
|
+
if (options.engine) {
|
|
130
|
+
app.use(engineHeaders(options.engine))
|
|
131
|
+
}
|
|
132
|
+
|
|
113
133
|
// Safety net: an engine fault answers the native envelope, never a crash. `detail` carries the raw message —
|
|
114
134
|
// this surface is ours to design, so (unlike the vendor-constrained drop-in envelopes) we can be helpful.
|
|
115
135
|
app.onError((error, c) => {
|
|
@@ -133,7 +153,10 @@ export function createMailwomanAPI<T extends Partial<GeocodeOutcomeLike> = Geoco
|
|
|
133
153
|
})
|
|
134
154
|
)
|
|
135
155
|
|
|
136
|
-
registerMailwomanAPIRoutes(app, engine, {
|
|
156
|
+
registerMailwomanAPIRoutes(app, engine, {
|
|
157
|
+
batchMax: options.batchMax ?? DEFAULT_BATCH_MAX,
|
|
158
|
+
engine: options.engine,
|
|
159
|
+
})
|
|
137
160
|
|
|
138
161
|
attachOpenAPIDocs(app, MAILWOMAN_API_DOC_INFO)
|
|
139
162
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import type { AddressTree } from "@mailwoman/core"
|
|
12
12
|
|
|
13
|
-
import type { GeocodeOutcomeLike } from "
|
|
13
|
+
import type { GeocodeOutcomeLike } from "#schema"
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* One parsed component in reading order (a `ComponentTag` + the covered text).
|
|
@@ -71,5 +71,5 @@ export interface MailwomanAPIEngine<T extends Partial<GeocodeOutcomeLike> = Geoc
|
|
|
71
71
|
batch?(addresses: string[], opts?: ParseInit): Promise<{ results: BatchResultEntry<T>[] }>
|
|
72
72
|
resolveTree?(tree: AddressTree, opts: Record<string, unknown>): Promise<ResolveTreeOutcome>
|
|
73
73
|
reload?(): Promise<{ reloaded: boolean; versions: unknown }>
|
|
74
|
-
health?(): HealthData
|
|
74
|
+
health?(): Promise<HealthData>
|
|
75
75
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* engine contract in `engine.ts`; the zod wire schemas in `schema.ts`.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
export * from "
|
|
20
|
-
export * from "
|
|
21
|
-
export * from "
|
|
22
|
-
export * from "
|
|
19
|
+
export * from "#app"
|
|
20
|
+
export * from "#engine"
|
|
21
|
+
export * from "#routes"
|
|
22
|
+
export * from "#schema"
|
|
@@ -20,12 +20,19 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import { createRoute, type OpenAPIHono, z } from "@hono/zod-openapi"
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
geocoderUnavailableError,
|
|
25
|
+
metricsSnapshot,
|
|
26
|
+
recordTimed,
|
|
27
|
+
stampedResponseSchema,
|
|
28
|
+
withEngineStamp,
|
|
29
|
+
} from "@mailwoman/api-kit"
|
|
24
30
|
import type { AddressTree } from "@mailwoman/core/decoder"
|
|
31
|
+
import type { EngineStamp } from "@mailwoman/core/license"
|
|
25
32
|
import type { ComponentTag } from "@mailwoman/core/types"
|
|
26
33
|
import { canonicalKey, type ComponentDict, formatAddress, type FormatAddressOptions } from "@mailwoman/formatter"
|
|
27
34
|
|
|
28
|
-
import type { MailwomanAPIEngine } from "
|
|
35
|
+
import type { MailwomanAPIEngine } from "#engine"
|
|
29
36
|
import {
|
|
30
37
|
APIErrorSchema,
|
|
31
38
|
BatchRequestSchema,
|
|
@@ -40,12 +47,12 @@ import {
|
|
|
40
47
|
ResolveRequestSchema,
|
|
41
48
|
ResolveResponseSchema,
|
|
42
49
|
type GeocodeOutcome,
|
|
43
|
-
} from "
|
|
50
|
+
} from "#schema"
|
|
44
51
|
|
|
45
52
|
/**
|
|
46
53
|
* Default `POST /v1/batch` row cap when {@link RegisterMailwomanAPIRoutesOptions.batchMax} is omitted. This is the
|
|
47
54
|
* standalone-engine default, not derived from env — `mailwoman serve` always passes the env-derived value explicitly
|
|
48
|
-
* (`$public.MAILWOMAN_BATCH_MAX`, default 1000; see `
|
|
55
|
+
* (`$public.MAILWOMAN_BATCH_MAX`, default 1000; see `mailwoman/lib/env/schema.ts`).
|
|
49
56
|
*/
|
|
50
57
|
export const DEFAULT_BATCH_MAX = 500
|
|
51
58
|
|
|
@@ -59,6 +66,11 @@ export interface RegisterMailwomanAPIRoutesOptions {
|
|
|
59
66
|
* Max `addresses` rows accepted by `POST /v1/batch`. Default {@link DEFAULT_BATCH_MAX}.
|
|
60
67
|
*/
|
|
61
68
|
batchMax?: number
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The engine stamp attached as `engine` to every `/v1` success body. Absent: no field is added.
|
|
72
|
+
*/
|
|
73
|
+
engine?: EngineStamp
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
const errorContent = (description: string) => ({
|
|
@@ -78,7 +90,7 @@ const parseQueryParams = z.object({
|
|
|
78
90
|
const parseResponses = {
|
|
79
91
|
200: {
|
|
80
92
|
description: "The tokenized input span + ranked solutions.",
|
|
81
|
-
content: { "application/json": { schema: ParseOutcomeSchema } },
|
|
93
|
+
content: { "application/json": { schema: stampedResponseSchema(ParseOutcomeSchema) } },
|
|
82
94
|
},
|
|
83
95
|
400: errorContent("`address` is required."),
|
|
84
96
|
501: errorContent("The backing engine method is not wired for this deployment."),
|
|
@@ -87,7 +99,7 @@ const parseResponses = {
|
|
|
87
99
|
const geocodeResponses = {
|
|
88
100
|
200: {
|
|
89
101
|
description: "One geocode result (parse → resolve cascade), passed through from the engine verbatim.",
|
|
90
|
-
content: { "application/json": { schema: GeocodeOutcomeSchema } },
|
|
102
|
+
content: { "application/json": { schema: stampedResponseSchema(GeocodeOutcomeSchema) } },
|
|
91
103
|
},
|
|
92
104
|
400: errorContent("`address` is required."),
|
|
93
105
|
503: errorContent("The geocoding engine is not wired for this deployment (dependencies missing)."),
|
|
@@ -96,7 +108,7 @@ const geocodeResponses = {
|
|
|
96
108
|
const batchResponses = {
|
|
97
109
|
200: {
|
|
98
110
|
description: "One result per input address, in input order (per-row error isolation).",
|
|
99
|
-
content: { "application/json": { schema: BatchResponseSchema } },
|
|
111
|
+
content: { "application/json": { schema: stampedResponseSchema(BatchResponseSchema) } },
|
|
100
112
|
},
|
|
101
113
|
400: errorContent("Body must be `{ addresses: string[] }`."),
|
|
102
114
|
413: errorContent("`addresses.length` exceeds the configured batch cap."),
|
|
@@ -106,7 +118,7 @@ const batchResponses = {
|
|
|
106
118
|
const resolveResponses = {
|
|
107
119
|
200: {
|
|
108
120
|
description: "The same tree, decorated in place with gazetteer coordinates + attribution.",
|
|
109
|
-
content: { "application/json": { schema: ResolveResponseSchema } },
|
|
121
|
+
content: { "application/json": { schema: stampedResponseSchema(ResolveResponseSchema) } },
|
|
110
122
|
},
|
|
111
123
|
400: errorContent("Body must be `{ tree: AddressTree, opts? }`."),
|
|
112
124
|
503: errorContent("The resolver is not wired for this deployment (dependencies missing)."),
|
|
@@ -114,7 +126,7 @@ const resolveResponses = {
|
|
|
114
126
|
|
|
115
127
|
const reloadResponses = {
|
|
116
128
|
200: {
|
|
117
|
-
description: "Versioned data switchover result — the new per-
|
|
129
|
+
description: "Versioned data switchover result — the new per-extract version map.",
|
|
118
130
|
content: {
|
|
119
131
|
"application/json": { schema: z.looseObject({ reloaded: z.boolean(), versions: z.unknown() }) },
|
|
120
132
|
},
|
|
@@ -125,7 +137,7 @@ const reloadResponses = {
|
|
|
125
137
|
const formatResponses = {
|
|
126
138
|
200: {
|
|
127
139
|
description: "The rendered address string + the deterministic canonical match key.",
|
|
128
|
-
content: { "application/json": { schema: FormatResponseSchema } },
|
|
140
|
+
content: { "application/json": { schema: stampedResponseSchema(FormatResponseSchema) } },
|
|
129
141
|
},
|
|
130
142
|
400: errorContent("Invalid request body."),
|
|
131
143
|
}
|
|
@@ -198,7 +210,7 @@ const reloadRoute = createRoute({
|
|
|
198
210
|
method: "post",
|
|
199
211
|
path: "/v1/reload",
|
|
200
212
|
operationId: "reload",
|
|
201
|
-
summary: "Reload versioned data
|
|
213
|
+
summary: "Reload versioned data extracts (deploy-only; check at ingress)",
|
|
202
214
|
tags: ["meta"],
|
|
203
215
|
responses: reloadResponses,
|
|
204
216
|
})
|
|
@@ -259,6 +271,7 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
259
271
|
options: RegisterMailwomanAPIRoutesOptions = {}
|
|
260
272
|
): void {
|
|
261
273
|
const batchMax = options.batchMax ?? DEFAULT_BATCH_MAX
|
|
274
|
+
const stamp = options.engine
|
|
262
275
|
|
|
263
276
|
app.openapi(parseGetRoute, async (c) => {
|
|
264
277
|
if (!engine.parse) return c.json({ error: "parse not implemented" }, 501)
|
|
@@ -271,7 +284,7 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
271
284
|
const inputMode = inputModeRaw === "fragmented" || inputModeRaw === "formatted" ? inputModeRaw : undefined
|
|
272
285
|
const outcome = await engine.parse(address, { debug, inputMode })
|
|
273
286
|
|
|
274
|
-
return c.json(outcome, 200)
|
|
287
|
+
return c.json(withEngineStamp(outcome, stamp), 200)
|
|
275
288
|
})
|
|
276
289
|
|
|
277
290
|
app.openapi(
|
|
@@ -290,7 +303,7 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
290
303
|
|
|
291
304
|
const outcome = await engine.parse(trimmed, { debug: debug ?? false, inputMode: input_mode })
|
|
292
305
|
|
|
293
|
-
return c.json(outcome, 200)
|
|
306
|
+
return c.json(withEngineStamp(outcome, stamp), 200)
|
|
294
307
|
},
|
|
295
308
|
(result, c) => {
|
|
296
309
|
if (!result.success) return c.json({ error: "address is required" }, 400)
|
|
@@ -317,7 +330,7 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
317
330
|
.then((outcome) => {
|
|
318
331
|
recordTimed(performance.now() - t0, String(outcome.resolution_tier ?? "admin"))
|
|
319
332
|
|
|
320
|
-
return c.json(outcome as
|
|
333
|
+
return c.json(withEngineStamp(outcome as GeocodeOutcome, stamp), 200)
|
|
321
334
|
})
|
|
322
335
|
.catch((error) => {
|
|
323
336
|
recordTimed(performance.now() - t0, "error")
|
|
@@ -339,7 +352,7 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
339
352
|
async (c) => {
|
|
340
353
|
const { addresses, input_mode } = c.req.valid("json")
|
|
341
354
|
|
|
342
|
-
if (!addresses.length) return c.json({ results: [] }, 200)
|
|
355
|
+
if (!addresses.length) return c.json(withEngineStamp({ results: [] }, stamp), 200)
|
|
343
356
|
|
|
344
357
|
if (addresses.length > batchMax) {
|
|
345
358
|
return c.json({ error: `batch too large: ${addresses.length} > ${batchMax}` }, 413)
|
|
@@ -361,7 +374,7 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
361
374
|
// Same wire-vs-domain cast as `/v1/geocode` above — `BatchRow`'s `GeocodeOutcome` half is a
|
|
362
375
|
// `Record<string, unknown>` passthrough; `BatchResponseSchema` now types its `GeocodeOutcome` union
|
|
363
376
|
// member as the real shape.
|
|
364
|
-
return c.json(outcome as
|
|
377
|
+
return c.json(withEngineStamp(outcome as z.infer<typeof BatchResponseSchema>, stamp), 200)
|
|
365
378
|
} catch (error) {
|
|
366
379
|
recordTimed(performance.now() - t0, "error")
|
|
367
380
|
throw error
|
|
@@ -388,9 +401,9 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
388
401
|
|
|
389
402
|
const { tree, opts } = c.req.valid("json")
|
|
390
403
|
|
|
391
|
-
const outcome = await engine.resolveTree(tree as
|
|
404
|
+
const outcome = await engine.resolveTree(tree as AddressTree, opts ?? {})
|
|
392
405
|
|
|
393
|
-
return c.json(outcome, 200)
|
|
406
|
+
return c.json(withEngineStamp(outcome, stamp), 200)
|
|
394
407
|
},
|
|
395
408
|
(result, c) => {
|
|
396
409
|
if (!result.success) return c.json({ error: "body must be { tree: AddressTree, opts? }" }, 400)
|
|
@@ -414,13 +427,13 @@ export function registerMailwomanAPIRoutes<T extends Partial<GeocodeOutcome> = G
|
|
|
414
427
|
const dict = toComponentDict(components)
|
|
415
428
|
const formatted = formatAddress(dict, country, formatOptions as FormatAddressOptions | undefined)
|
|
416
429
|
|
|
417
|
-
return c.json({ formatted, canonicalKey: canonicalKey(dict) }, 200)
|
|
430
|
+
return c.json(withEngineStamp({ formatted, canonicalKey: canonicalKey(dict) }, stamp), 200)
|
|
418
431
|
})
|
|
419
432
|
|
|
420
|
-
app.openapi(healthRoute, (c) => {
|
|
433
|
+
app.openapi(healthRoute, async (c) => {
|
|
421
434
|
const uptimeSeconds = Math.round((Date.now() - startedAt) / 1000)
|
|
422
435
|
|
|
423
|
-
return c.json({ status: "ok", uptime_s: uptimeSeconds, ...engine.health?.() }, 200)
|
|
436
|
+
return c.json({ status: "ok", uptime_s: uptimeSeconds, ...(await engine.health?.()) }, 200)
|
|
424
437
|
})
|
|
425
438
|
|
|
426
439
|
app.openapi(metricsRoute, (c) => c.json(metricsSnapshot(), 200))
|
|
@@ -17,12 +17,25 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { z } from "@hono/zod-openapi"
|
|
20
|
+
import type { AddressNode } from "@mailwoman/core/decoder"
|
|
21
|
+
import type { DerivationProjection, Evidence } from "@mailwoman/evidence"
|
|
20
22
|
|
|
21
23
|
export { APIErrorSchema } from "@mailwoman/api-kit"
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* `POST /v1/parse` request body.
|
|
25
27
|
*/
|
|
28
|
+
/**
|
|
29
|
+
* One node of the decoded address tree. The decoder's `AddressNode` is a recursive union the OpenAPI generator cannot
|
|
30
|
+
* derive a schema for on its own, so it is registered as an open object; the shape is documented by the type.
|
|
31
|
+
*/
|
|
32
|
+
export const AddressNodeSchema = z.custom<AddressNode>().openapi("AddressNode", {
|
|
33
|
+
type: "object",
|
|
34
|
+
additionalProperties: true,
|
|
35
|
+
description:
|
|
36
|
+
"A decoded address-tree node: a tag, its span, and its children. See `AddressNode` in `@mailwoman/core/decoder`.",
|
|
37
|
+
})
|
|
38
|
+
|
|
26
39
|
/**
|
|
27
40
|
* The input register (Decision A / GTM B10): `fragmented` = the map-search register (evidence-bundle channels feed);
|
|
28
41
|
* `formatted` = the validation/record register (channels off). Unset → the engine derives it from the input's shape.
|
|
@@ -70,7 +83,7 @@ export const ParseOutcomeSchema = z
|
|
|
70
83
|
.object({
|
|
71
84
|
input: z.string(),
|
|
72
85
|
components: z.array(ParseComponentSchema),
|
|
73
|
-
tree: z.looseObject({
|
|
86
|
+
tree: z.looseObject({ raw: z.string(), roots: z.array(AddressNodeSchema) }),
|
|
74
87
|
debug: z.string().optional(),
|
|
75
88
|
})
|
|
76
89
|
.openapi("ParseOutcome")
|
|
@@ -150,6 +163,7 @@ const ComponentTagSchema = z.enum([
|
|
|
150
163
|
"sub_block",
|
|
151
164
|
"building_number",
|
|
152
165
|
"building_name",
|
|
166
|
+
"locality_unit",
|
|
153
167
|
])
|
|
154
168
|
|
|
155
169
|
/**
|
|
@@ -186,13 +200,80 @@ const QueryIntentMarkerSchema = z
|
|
|
186
200
|
"near_me",
|
|
187
201
|
"poi_category",
|
|
188
202
|
]),
|
|
189
|
-
code: z.enum([
|
|
203
|
+
code: z.enum([
|
|
204
|
+
"declared_ambiguity",
|
|
205
|
+
"declared_fork",
|
|
206
|
+
"focus_point_required",
|
|
207
|
+
"poi_category",
|
|
208
|
+
"coverage_qualified_absence",
|
|
209
|
+
"authority_designation",
|
|
210
|
+
]),
|
|
190
211
|
mechanism: z.string(),
|
|
191
212
|
message: z.string(),
|
|
192
213
|
evidence: z.record(z.string(), z.unknown()).optional(),
|
|
193
214
|
})
|
|
194
215
|
.openapi("QueryIntentMarker")
|
|
195
216
|
|
|
217
|
+
/**
|
|
218
|
+
* One authoritative-provider match on the wire (#1901) — hoisted so the outcome schema below stays inside the
|
|
219
|
+
* call-nesting bound. Field-for-field mirror of `mailwoman/authoritative.ts`'s `AuthoritativeAssertionMatch`.
|
|
220
|
+
*/
|
|
221
|
+
const AuthoritativeMatchSchema = z.object({
|
|
222
|
+
provider_place_id: z.string(),
|
|
223
|
+
object_ids: z.record(z.string(), z.string()).optional(),
|
|
224
|
+
canonical_fields: z.record(z.string(), z.string()).optional(),
|
|
225
|
+
lat: z.number().optional(),
|
|
226
|
+
lon: z.number().optional(),
|
|
227
|
+
precision: z.string().optional(),
|
|
228
|
+
match_status: z.enum(["exact", "approximate"]),
|
|
229
|
+
provider_score: z.number().optional(),
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
const EpistemicStatusSchema = z.enum(["designated", "observed", "derived", "inferred", "unresolved"])
|
|
233
|
+
|
|
234
|
+
const CoverageBasisSchema = z.enum(["designated", "surveyed", "source_present"])
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* `@mailwoman/evidence`'s `Evidence` union, spelled for the wire. The `EvidencePin` below fails to compile the moment
|
|
238
|
+
* either side gains, loses or retypes a field.
|
|
239
|
+
*/
|
|
240
|
+
const EvidenceSchema = z.discriminatedUnion("kind", [
|
|
241
|
+
z.object({ kind: z.literal("observation"), source: z.string(), vintage: z.string().nullable(), value: z.unknown() }),
|
|
242
|
+
z.object({
|
|
243
|
+
kind: z.literal("exclusion"),
|
|
244
|
+
source: z.string(),
|
|
245
|
+
vintage: z.string(),
|
|
246
|
+
scope: z.object({ layer: z.string(), h3Cell: z.number(), basis: CoverageBasisSchema, fold: z.string() }),
|
|
247
|
+
}),
|
|
248
|
+
z.object({
|
|
249
|
+
kind: z.literal("relation"),
|
|
250
|
+
source: z.string(),
|
|
251
|
+
vintage: z.string(),
|
|
252
|
+
relationship: z.string(),
|
|
253
|
+
assertion: z.enum(["authoritative", "inferred"]),
|
|
254
|
+
score: z.number().optional(),
|
|
255
|
+
}),
|
|
256
|
+
z.object({ kind: z.literal("prior"), source: z.string(), label: z.string(), weight: z.number() }),
|
|
257
|
+
])
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* The derivation behind a geocode answer, present only when the engine was asked to trace — `@mailwoman/evidence`'s
|
|
261
|
+
* `DerivationProjection` on the wire.
|
|
262
|
+
*/
|
|
263
|
+
export const DerivationProjectionSchema = z.object({
|
|
264
|
+
status: EpistemicStatusSchema,
|
|
265
|
+
constraints: z.array(z.object({ label: z.string(), evidence: EvidenceSchema, contribution: z.string() })).readonly(),
|
|
266
|
+
uncertaintyM: z.number().nullable(),
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
// Both directions: the schema's inferred type is exactly the evidence package's, or this does not compile.
|
|
270
|
+
type Mutual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false
|
|
271
|
+
const evidencePin: Mutual<z.infer<typeof EvidenceSchema>, Evidence> = true
|
|
272
|
+
const derivationPin: Mutual<z.infer<typeof DerivationProjectionSchema>, DerivationProjection> = true
|
|
273
|
+
|
|
274
|
+
void evidencePin
|
|
275
|
+
void derivationPin
|
|
276
|
+
|
|
196
277
|
/**
|
|
197
278
|
* `POST /v1/geocode` response — a hand-modeled mirror of `GeocodeResult`'s wire shape (`mailwoman/geocode-core.ts`),
|
|
198
279
|
* `.loose()` so a field the engine adds that this schema doesn't yet know about still rides through undocumented rather
|
|
@@ -200,8 +281,8 @@ const QueryIntentMarkerSchema = z
|
|
|
200
281
|
* (`GeocodeOutcome = Record<string, unknown>`, `api/engine.ts`) — nothing here validates a real response, so a
|
|
201
282
|
* schema/engine mismatch can never reject or mutate a result at runtime. Deliberately carries NO import from
|
|
202
283
|
* `mailwoman` (the engine-agnosticism boundary — `mailwoman` is the one workspace allowed to depend on
|
|
203
|
-
* `@mailwoman/api`, never the reverse). `mailwoman/test/api-schema-drift.test.ts` is the compile-time
|
|
204
|
-
* catches this shape drifting from the real `GeocodeResult` interface.
|
|
284
|
+
* `@mailwoman/api`, never the reverse). `mailwoman/test/api-schema-drift.test.ts` is the compile-time regression check
|
|
285
|
+
* that catches this shape drifting from the real `GeocodeResult` interface.
|
|
205
286
|
*/
|
|
206
287
|
export const GeocodeOutcomeLikeSchema = z.object({
|
|
207
288
|
input: z.string(),
|
|
@@ -209,6 +290,12 @@ export const GeocodeOutcomeLikeSchema = z.object({
|
|
|
209
290
|
lat: z.number().nullable(),
|
|
210
291
|
lon: z.number().nullable(),
|
|
211
292
|
resolution_tier: z.enum(["address_point", "interpolated", "street", "admin", "venue", "plus_code"]),
|
|
293
|
+
// What the evidence permits a consumer to claim about the coordinate, orthogonal to how it was produced; see
|
|
294
|
+
// `@mailwoman/evidence`'s `EpistemicStatus`.
|
|
295
|
+
epistemic_status: z.enum(["designated", "observed", "derived", "inferred", "unresolved"]),
|
|
296
|
+
// The derivation behind the answer, present only when the engine was asked to trace. `DerivationProjectionSchema` is
|
|
297
|
+
// pinned to `@mailwoman/evidence`'s types below, so the wire contract and the evidence union cannot drift apart.
|
|
298
|
+
derivation: DerivationProjectionSchema.optional(),
|
|
212
299
|
// The fork→entity probe's answer (#1585) — present only on the `venue` tier; see geocode-core's
|
|
213
300
|
// GeocodeResult.entity.
|
|
214
301
|
entity: z
|
|
@@ -234,7 +321,7 @@ export const GeocodeOutcomeLikeSchema = z.object({
|
|
|
234
321
|
countryCode: z.string().nullable(),
|
|
235
322
|
hierarchy: z.array(GeocodeHierarchyEntrySchema),
|
|
236
323
|
candidates: z.array(GeocodeCandidateSchema),
|
|
237
|
-
// The register row's OWN scope tags when the address_point tier answered and its
|
|
324
|
+
// The register row's OWN scope tags when the address_point tier answered and its extract carries
|
|
238
325
|
// them (normalized locality key + postcode of the ROOFTOP) — see geocode-core's GeocodeResult.rooftop.
|
|
239
326
|
rooftop: z
|
|
240
327
|
.object({
|
|
@@ -246,11 +333,17 @@ export const GeocodeOutcomeLikeSchema = z.object({
|
|
|
246
333
|
// OVERRODE the request's country prior — so a caller who asked for US and got an FR answer can see which
|
|
247
334
|
// evidence bought the change instead of reading it as a bug.
|
|
248
335
|
postcode_country_scope: z.string().nullable(),
|
|
336
|
+
// #1880: the capital promotion's firing receipt — the promoted candidate's country, present only when the
|
|
337
|
+
// promotion changed some node's leading candidate. Advisory, same posture as postcode_country_scope.
|
|
338
|
+
capital_promotion: z.string().optional(),
|
|
339
|
+
// #1893: the variant-alias exemption's firing receipt — present (true) only when the winning candidate reached
|
|
340
|
+
// the top because the exemption spared it the cross-country alias penalty. Advisory, same posture again.
|
|
341
|
+
variant_alias_exemption: z.literal(true).optional(),
|
|
249
342
|
// ROAD_TO_V9 §4: query-intent advisories. Always present; empty means the vocabulary looked and had nothing to
|
|
250
343
|
// say. Advisory ONLY — no marker changed which answer won, and a client is free to ignore the array entirely.
|
|
251
344
|
intent_markers: z.array(QueryIntentMarkerSchema),
|
|
252
345
|
// #1717 stage 1: flag-only admin-coherence verdicts — did the winning candidate's resolved ancestry confirm,
|
|
253
|
-
// contradict, or fail to speak to the PARSED region/country qualifiers? Nothing ranks or
|
|
346
|
+
// contradict, or fail to speak to the PARSED region/country qualifiers? Nothing ranks or filters on these; present
|
|
254
347
|
// whenever a winner resolved (both members always populated — `unstated` is the explicit no-qualifier claim),
|
|
255
348
|
// absent when nothing resolved to check against. See mailwoman's `admin-coherence.ts` for the verdict contract.
|
|
256
349
|
admin_coherence: z
|
|
@@ -259,6 +352,23 @@ export const GeocodeOutcomeLikeSchema = z.object({
|
|
|
259
352
|
country: z.enum(["confirmed", "contradicted", "unstated", "unverifiable"]),
|
|
260
353
|
})
|
|
261
354
|
.optional(),
|
|
355
|
+
// #1901: a configured authoritative provider's answer, carried BESIDE the open result — every value inside is
|
|
356
|
+
// the PROVIDER'S assertion, hand-modeled here to match `mailwoman/authoritative.ts`'s wire shape (the
|
|
357
|
+
// engine-agnosticism boundary forbids importing it). Absent when no provider is configured; `refused` is the
|
|
358
|
+
// provider declining (distinct from a parse failure or a gazetteer miss); `transport_error` is the provider
|
|
359
|
+
// being unreachable, reported rather than silently dropped. An `ambiguous` status carries EVERY candidate.
|
|
360
|
+
authoritative: z
|
|
361
|
+
.object({
|
|
362
|
+
provider: z.string(),
|
|
363
|
+
status: z.enum(["matched", "ambiguous", "refused", "transport_error"]),
|
|
364
|
+
matches: z.array(AuthoritativeMatchSchema).optional(),
|
|
365
|
+
attribution: z.string().optional(),
|
|
366
|
+
license: z.string().optional(),
|
|
367
|
+
retrieved_at: z.string().optional(),
|
|
368
|
+
dataset_version: z.string().optional(),
|
|
369
|
+
error: z.string().optional(),
|
|
370
|
+
})
|
|
371
|
+
.optional(),
|
|
262
372
|
// #1755: spans the flat `components` map could not represent. `components` holds one value per tag, so a second
|
|
263
373
|
// `locality` span ceases to exist there — and without this line `region: null` means both "the input named no
|
|
264
374
|
// region" and "it named one and we deleted it". Absent when nothing was dropped; never an empty array on the wire,
|
|
@@ -284,8 +394,8 @@ export type GeocodeOutcomeLike = z.infer<typeof GeocodeOutcomeLikeSchema>
|
|
|
284
394
|
* (`GeocodeOutcome = Record<string, unknown>`, `api/engine.ts`) — nothing here validates a real response, so a
|
|
285
395
|
* schema/engine mismatch can never reject or mutate a result at runtime. Deliberately carries NO import from
|
|
286
396
|
* `mailwoman` (the engine-agnosticism boundary — `mailwoman` is the one workspace allowed to depend on
|
|
287
|
-
* `@mailwoman/api`, never the reverse). `mailwoman/test/api-schema-drift.test.ts` is the compile-time
|
|
288
|
-
* catches this shape drifting from the real `GeocodeResult` interface.
|
|
397
|
+
* `@mailwoman/api`, never the reverse). `mailwoman/test/api-schema-drift.test.ts` is the compile-time regression check
|
|
398
|
+
* that catches this shape drifting from the real `GeocodeResult` interface.
|
|
289
399
|
*/
|
|
290
400
|
export const GeocodeOutcomeSchema = GeocodeOutcomeLikeSchema.loose().openapi("GeocodeOutcome")
|
|
291
401
|
|
|
@@ -331,7 +441,7 @@ export const BatchResponseSchema = z
|
|
|
331
441
|
*/
|
|
332
442
|
export const ResolveRequestSchema = z
|
|
333
443
|
.object({
|
|
334
|
-
tree: z.looseObject({
|
|
444
|
+
tree: z.looseObject({ raw: z.string(), roots: z.array(AddressNodeSchema) }),
|
|
335
445
|
opts: z.looseObject({}).optional(),
|
|
336
446
|
})
|
|
337
447
|
.openapi("ResolveRequest")
|
|
@@ -341,7 +451,7 @@ export const ResolveRequestSchema = z
|
|
|
341
451
|
*/
|
|
342
452
|
export const ResolveResponseSchema = z
|
|
343
453
|
.object({
|
|
344
|
-
tree: z.looseObject({
|
|
454
|
+
tree: z.looseObject({ raw: z.string(), roots: z.array(AddressNodeSchema) }),
|
|
345
455
|
})
|
|
346
456
|
.openapi("ResolveResponse")
|
|
347
457
|
|
|
@@ -377,9 +487,11 @@ export const FormatResponseSchema = z
|
|
|
377
487
|
|
|
378
488
|
/**
|
|
379
489
|
* `GET /health` response — `status`/`uptime_s` are stamped by the ROUTE itself, unconditionally, regardless of engine
|
|
380
|
-
* (`api/routes.ts`'s `healthRoute` handler: `{ status: "ok", uptime_s, ...engine.health?.() }`), so those two are
|
|
381
|
-
*
|
|
382
|
-
*
|
|
490
|
+
* (`api/routes.ts`'s `healthRoute` handler: `{ status: "ok", uptime_s, ...engine.health?.() }`), so those two are
|
|
491
|
+
* cheap
|
|
492
|
+
*
|
|
493
|
+
* - Accurate to pin. Everything else is `HealthData` (`api/engine.ts`) — an engine-defined block (model card, data-root
|
|
494
|
+
* inventory for `mailwoman serve`; something else entirely for another engine) — stays loose.
|
|
383
495
|
*/
|
|
384
496
|
export const HealthResponseSchema = z
|
|
385
497
|
.object({
|
package/out/app.d.ts
CHANGED
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
11
11
|
import { type OpenAPIDocInfo } from "@mailwoman/api-kit";
|
|
12
|
-
import type {
|
|
13
|
-
import type {
|
|
12
|
+
import type { EngineStamp } from "@mailwoman/core/license";
|
|
13
|
+
import type { MailwomanAPIEngine } from "#engine";
|
|
14
|
+
import type { GeocodeOutcomeLike } from "#schema";
|
|
14
15
|
/**
|
|
15
16
|
* Options for {@link createMailwomanAPI}.
|
|
16
17
|
*/
|
|
@@ -30,6 +31,12 @@ export interface MailwomanAPIOptions {
|
|
|
30
31
|
* Max `addresses` rows accepted by `POST /v1/batch`. Default 500 (see `routes.ts`'s `DEFAULT_BATCH_MAX`).
|
|
31
32
|
*/
|
|
32
33
|
batchMax?: number;
|
|
34
|
+
/**
|
|
35
|
+
* The engine stamp to carry on every response: `engine` in each `/v1` body and the `Server` + `Link: rel="license"`
|
|
36
|
+
* headers everywhere. Absent when an embedding application builds the app without the `mailwoman` package; the
|
|
37
|
+
* `mailwoman serve` command always passes one.
|
|
38
|
+
*/
|
|
39
|
+
engine?: EngineStamp;
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* The document info stamped into the emitted OpenAPI document. Exported (not inlined) so the `mailwoman openapi`
|
package/out/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../app.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../lib/app.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAmD,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEzG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAK1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAejD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;CACpB;AAUD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,cAoBpC,CAAA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,EAC5F,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC7B,OAAO,GAAE,mBAAwB,GAC/B,WAAW,CAyDb"}
|
package/out/app.js
CHANGED
|
@@ -8,11 +8,17 @@
|
|
|
8
8
|
* CLI wires the real parse/geocode/resolve stack (phase 4b); tests inject fixtures.
|
|
9
9
|
*/
|
|
10
10
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
11
|
-
import {
|
|
11
|
+
import { attachOpenAPIDocs, engineHeaders, errorResponse } from "@mailwoman/api-kit";
|
|
12
|
+
import { readLocalJSONFile } from "@mailwoman/core/fs/readers";
|
|
13
|
+
import { resolvePackagePath } from "@mailwoman/core/module/resolvers";
|
|
12
14
|
import { bodyLimit } from "hono/body-limit";
|
|
13
15
|
import { cors } from "hono/cors";
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
+
import { DEFAULT_BATCH_MAX, registerMailwomanAPIRoutes } from "#routes";
|
|
17
|
+
/**
|
|
18
|
+
* This package's own manifest, read at load rather than imported as a module: a JSON import makes `tsc` copy the file
|
|
19
|
+
* into `out/`, where it becomes the package scope for the compiled tree and breaks every `#` import in it.
|
|
20
|
+
*/
|
|
21
|
+
const packageJson = await readLocalJSONFile(resolvePackagePath("@mailwoman/api", "package.json"));
|
|
16
22
|
/**
|
|
17
23
|
* 2 MiB — carried from the express server's `express.json({ limit: "2mb" })` (`mailwoman/server/index.ts`).
|
|
18
24
|
*/
|
|
@@ -72,6 +78,9 @@ export function createMailwomanAPI(engine, options = {}) {
|
|
|
72
78
|
if (options.cors !== false) {
|
|
73
79
|
app.use(cors({ origin: "*", allowMethods: ["GET", "POST", "OPTIONS"], allowHeaders: ["*"], maxAge: 86_400 }));
|
|
74
80
|
}
|
|
81
|
+
if (options.engine) {
|
|
82
|
+
app.use(engineHeaders(options.engine));
|
|
83
|
+
}
|
|
75
84
|
// Safety net: an engine fault answers the native envelope, never a crash. `detail` carries the raw message —
|
|
76
85
|
// this surface is ours to design, so (unlike the vendor-constrained drop-in envelopes) we can be helpful.
|
|
77
86
|
app.onError((error, c) => {
|
|
@@ -89,7 +98,10 @@ export function createMailwomanAPI(engine, options = {}) {
|
|
|
89
98
|
maxSize: options.bodyLimitBytes ?? DEFAULT_BODY_LIMIT_BYTES,
|
|
90
99
|
onError: (c) => errorResponse(c, 413, "request body too large"),
|
|
91
100
|
}));
|
|
92
|
-
registerMailwomanAPIRoutes(app, engine, {
|
|
101
|
+
registerMailwomanAPIRoutes(app, engine, {
|
|
102
|
+
batchMax: options.batchMax ?? DEFAULT_BATCH_MAX,
|
|
103
|
+
engine: options.engine,
|
|
104
|
+
});
|
|
93
105
|
attachOpenAPIDocs(app, MAILWOMAN_API_DOC_INFO);
|
|
94
106
|
return app;
|
|
95
107
|
}
|
package/out/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../app.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../lib/app.ts"],"names":[],"mappings":"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"}
|
package/out/engine.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* exception — it's wired in-package from `@mailwoman/formatter` (the surface exists to expose it).
|
|
9
9
|
*/
|
|
10
10
|
import type { AddressTree } from "@mailwoman/core";
|
|
11
|
-
import type { GeocodeOutcomeLike } from "
|
|
11
|
+
import type { GeocodeOutcomeLike } from "#schema";
|
|
12
12
|
/**
|
|
13
13
|
* One parsed component in reading order (a `ComponentTag` + the covered text).
|
|
14
14
|
*/
|
|
@@ -61,6 +61,6 @@ export interface MailwomanAPIEngine<T extends Partial<GeocodeOutcomeLike> = Geoc
|
|
|
61
61
|
reloaded: boolean;
|
|
62
62
|
versions: unknown;
|
|
63
63
|
}>;
|
|
64
|
-
health?(): HealthData
|
|
64
|
+
health?(): Promise<HealthData>;
|
|
65
65
|
}
|
|
66
66
|
//# sourceMappingURL=engine.d.ts.map
|
package/out/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../lib/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAElD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,cAAc,EAAE,CAAA;IAC5B,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,IAAI,CAAC,GAAG,kBAAkB,CAAA;AAEjH,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,WAAW,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEhD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,WAAW,CAAA;AAEtD,MAAM,WAAW,SAAS;IACzB,SAAS,CAAC,EAAE,aAAa,CAAA;IACzB,KAAK,CAAC,EAAE,OAAO,CAAA;CACf;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,IAAI,CACzF,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,SAAS,KACZ,OAAO,CAAC,CAAC,CAAC,CAAA;AAEf,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,OAAO,CAAC,kBAAkB,CAAC,GAAG,kBAAkB;IAC7F,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IACtE,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,CAAA;IAC5B,KAAK,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAA;KAAE,CAAC,CAAA;IAC1F,WAAW,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;IAC3F,MAAM,CAAC,IAAI,OAAO,CAAC;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAC5D,MAAM,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,CAAA;CAC9B"}
|