@mailwoman/api 8.6.0 → 9.0.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/out/schema.d.ts +21 -3
- package/out/schema.d.ts.map +1 -1
- package/out/schema.js +28 -6
- package/out/schema.js.map +1 -1
- package/package.json +4 -4
- package/schema.ts +29 -6
package/out/schema.d.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Zod wire schemas for the native `/v1` surface. Unlike the drop-ins (photon, nominatim,
|
|
7
7
|
* libpostal), nothing here is a vendor contract — this surface is ours to design, so request
|
|
8
8
|
* bodies are REQUIRED and validator-enforced (no legacy tolerance to preserve). A `defaultHook`
|
|
9
|
-
* on the app
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* on the app maps validation failures through the shared `APIErrorSchema` envelope
|
|
10
|
+
* (`apiError(c, 400, "invalid request body", <zod summary>)`) — the pattern boundary every
|
|
11
|
+
* surface holds to: where no legacy contract exists, the validator MAY speak, but only in
|
|
12
12
|
* our envelope.
|
|
13
13
|
*
|
|
14
14
|
* `APIErrorSchema` itself is owned by `@mailwoman/api-kit` (plumbing shared by every native
|
|
@@ -29,6 +29,20 @@ export declare const InputModeSchema: z.ZodEnum<{
|
|
|
29
29
|
fragmented: "fragmented";
|
|
30
30
|
formatted: "formatted";
|
|
31
31
|
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Longest accepted `address`, in characters.
|
|
34
|
+
*
|
|
35
|
+
* Sized against what the model can actually read, not against a guess at abuse. The classifier's window is 128
|
|
36
|
+
* SentencePiece pieces — roughly 330 characters of address text — and everything past it is truncated before inference,
|
|
37
|
+
* so input beyond this bound cannot influence a result. The margin over that window leaves room for scripts that
|
|
38
|
+
* tokenize denser than Latin, and for the department-and-division prefixes web forms concatenate.
|
|
39
|
+
*
|
|
40
|
+
* The bound exists because preprocessing is linear but not free: a 1 MB body costs ~1.7 s across normalize, query-shape
|
|
41
|
+
* and the phrase grouper, and Node runs them on the one thread every other request is waiting on. A cap here is cheaper
|
|
42
|
+
* than fairness plumbing, and rejecting is more honest than accepting a body whose tail the parser will silently
|
|
43
|
+
* discard.
|
|
44
|
+
*/
|
|
45
|
+
export declare const MAX_ADDRESS_LENGTH = 1024;
|
|
32
46
|
/**
|
|
33
47
|
* `POST /v1/parse` request body.
|
|
34
48
|
*/
|
|
@@ -101,6 +115,7 @@ export declare const GeocodeOutcomeSchema: z.ZodObject<{
|
|
|
101
115
|
street: z.ZodNullable<z.ZodString>;
|
|
102
116
|
venue: z.ZodNullable<z.ZodString>;
|
|
103
117
|
dependent_locality: z.ZodNullable<z.ZodString>;
|
|
118
|
+
unit: z.ZodNullable<z.ZodString>;
|
|
104
119
|
countryCode: z.ZodNullable<z.ZodString>;
|
|
105
120
|
hierarchy: z.ZodArray<z.ZodObject<{
|
|
106
121
|
tag: z.ZodString;
|
|
@@ -118,6 +133,7 @@ export declare const GeocodeOutcomeSchema: z.ZodObject<{
|
|
|
118
133
|
countryCode: z.ZodNullable<z.ZodString>;
|
|
119
134
|
placeID: z.ZodOptional<z.ZodString>;
|
|
120
135
|
}, z.core.$strip>>;
|
|
136
|
+
postcode_country_scope: z.ZodNullable<z.ZodString>;
|
|
121
137
|
}, z.core.$loose>;
|
|
122
138
|
/**
|
|
123
139
|
* `POST /v1/batch` request body.
|
|
@@ -151,6 +167,7 @@ export declare const BatchResponseSchema: z.ZodObject<{
|
|
|
151
167
|
street: z.ZodNullable<z.ZodString>;
|
|
152
168
|
venue: z.ZodNullable<z.ZodString>;
|
|
153
169
|
dependent_locality: z.ZodNullable<z.ZodString>;
|
|
170
|
+
unit: z.ZodNullable<z.ZodString>;
|
|
154
171
|
countryCode: z.ZodNullable<z.ZodString>;
|
|
155
172
|
hierarchy: z.ZodArray<z.ZodObject<{
|
|
156
173
|
tag: z.ZodString;
|
|
@@ -168,6 +185,7 @@ export declare const BatchResponseSchema: z.ZodObject<{
|
|
|
168
185
|
countryCode: z.ZodNullable<z.ZodString>;
|
|
169
186
|
placeID: z.ZodOptional<z.ZodString>;
|
|
170
187
|
}, z.core.$strip>>;
|
|
188
|
+
postcode_country_scope: z.ZodNullable<z.ZodString>;
|
|
171
189
|
}, z.core.$loose>, z.ZodObject<{
|
|
172
190
|
input: z.ZodString;
|
|
173
191
|
error: z.ZodString;
|
package/out/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAA;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD;;GAEG;AACH;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;EAA2D,CAAA;AAEvF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;iBAMN,CAAA;AAEzB;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;iBAA6E,CAAA;AAE9G;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;iBAON,CAAA;AAEzB;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;iBAKN,CAAA;AAiC3B;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAA;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD;;GAEG;AACH;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;EAA2D,CAAA;AAEvF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,OAAO,CAAA;AAEtC;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;;iBAMN,CAAA;AAEzB;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;iBAA6E,CAAA;AAE9G;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;iBAON,CAAA;AAEzB;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;;;iBAKN,CAAA;AAiC3B;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2BN,CAAA;AAE3B;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;;;iBAUN,CAAA;AAYzB;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAIN,CAAA;AAE1B;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;iBAKN,CAAA;AAE3B;;GAEG;AACH,eAAO,MAAM,qBAAqB;;;;iBAIN,CAAA;AAQ5B;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB;;;;iBAMN,CAAA;AAE1B;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;iBAKN,CAAA;AAE3B;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;iBAMN,CAAA"}
|
package/out/schema.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Zod wire schemas for the native `/v1` surface. Unlike the drop-ins (photon, nominatim,
|
|
7
7
|
* libpostal), nothing here is a vendor contract — this surface is ours to design, so request
|
|
8
8
|
* bodies are REQUIRED and validator-enforced (no legacy tolerance to preserve). A `defaultHook`
|
|
9
|
-
* on the app
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* on the app maps validation failures through the shared `APIErrorSchema` envelope
|
|
10
|
+
* (`apiError(c, 400, "invalid request body", <zod summary>)`) — the pattern boundary every
|
|
11
|
+
* surface holds to: where no legacy contract exists, the validator MAY speak, but only in
|
|
12
12
|
* our envelope.
|
|
13
13
|
*
|
|
14
14
|
* `APIErrorSchema` itself is owned by `@mailwoman/api-kit` (plumbing shared by every native
|
|
@@ -26,12 +26,26 @@ export { APIErrorSchema } from "@mailwoman/api-kit";
|
|
|
26
26
|
* `/v1/batch` defaults to `formatted` (batch rows are the record register by nature).
|
|
27
27
|
*/
|
|
28
28
|
export const InputModeSchema = z.enum(["fragmented", "formatted"]).openapi("InputMode");
|
|
29
|
+
/**
|
|
30
|
+
* Longest accepted `address`, in characters.
|
|
31
|
+
*
|
|
32
|
+
* Sized against what the model can actually read, not against a guess at abuse. The classifier's window is 128
|
|
33
|
+
* SentencePiece pieces — roughly 330 characters of address text — and everything past it is truncated before inference,
|
|
34
|
+
* so input beyond this bound cannot influence a result. The margin over that window leaves room for scripts that
|
|
35
|
+
* tokenize denser than Latin, and for the department-and-division prefixes web forms concatenate.
|
|
36
|
+
*
|
|
37
|
+
* The bound exists because preprocessing is linear but not free: a 1 MB body costs ~1.7 s across normalize, query-shape
|
|
38
|
+
* and the phrase grouper, and Node runs them on the one thread every other request is waiting on. A cap here is cheaper
|
|
39
|
+
* than fairness plumbing, and rejecting is more honest than accepting a body whose tail the parser will silently
|
|
40
|
+
* discard.
|
|
41
|
+
*/
|
|
42
|
+
export const MAX_ADDRESS_LENGTH = 1024;
|
|
29
43
|
/**
|
|
30
44
|
* `POST /v1/parse` request body.
|
|
31
45
|
*/
|
|
32
46
|
export const ParseRequestSchema = z
|
|
33
47
|
.object({
|
|
34
|
-
address: z.string(),
|
|
48
|
+
address: z.string().max(MAX_ADDRESS_LENGTH),
|
|
35
49
|
debug: z.boolean().optional(),
|
|
36
50
|
input_mode: InputModeSchema.optional(),
|
|
37
51
|
})
|
|
@@ -58,7 +72,7 @@ export const ParseOutcomeSchema = z
|
|
|
58
72
|
*/
|
|
59
73
|
export const GeocodeRequestSchema = z
|
|
60
74
|
.object({
|
|
61
|
-
address: z.string(),
|
|
75
|
+
address: z.string().max(MAX_ADDRESS_LENGTH),
|
|
62
76
|
input_mode: InputModeSchema.optional(),
|
|
63
77
|
})
|
|
64
78
|
.openapi("GeocodeRequest");
|
|
@@ -117,9 +131,15 @@ export const GeocodeOutcomeSchema = z
|
|
|
117
131
|
venue: z.string().nullable(),
|
|
118
132
|
// The parsed dependent-locality span (parse view; `hierarchy` is the resolved view).
|
|
119
133
|
dependent_locality: z.string().nullable(),
|
|
134
|
+
// The parsed unit / sub-venue span (parse view) — "Terminal 5", "Suite 300".
|
|
135
|
+
unit: z.string().nullable(),
|
|
120
136
|
countryCode: z.string().nullable(),
|
|
121
137
|
hierarchy: z.array(GeocodeHierarchyEntrySchema),
|
|
122
138
|
candidates: z.array(GeocodeCandidateSchema),
|
|
139
|
+
// #42: the country the postcode-country coherence pass scoped the walk to, or null. Non-null ONLY when it
|
|
140
|
+
// OVERRODE the request's country prior — so a caller who asked for US and got an FR answer can see which
|
|
141
|
+
// evidence bought the change instead of reading it as a bug.
|
|
142
|
+
postcode_country_scope: z.string().nullable(),
|
|
123
143
|
})
|
|
124
144
|
.loose()
|
|
125
145
|
.openapi("GeocodeOutcome");
|
|
@@ -128,7 +148,9 @@ export const GeocodeOutcomeSchema = z
|
|
|
128
148
|
*/
|
|
129
149
|
export const BatchRequestSchema = z
|
|
130
150
|
.object({
|
|
131
|
-
|
|
151
|
+
// Per-ROW, not just per-request: the row cap (`batchMax`, default 500) bounds how many addresses arrive,
|
|
152
|
+
// and this bounds how large each may be. Without both, one request is 500 unbounded bodies.
|
|
153
|
+
addresses: z.array(z.string().max(MAX_ADDRESS_LENGTH)),
|
|
132
154
|
/**
|
|
133
155
|
* Register override for every row. DEFAULT `"formatted"` — batch rows are the record register by nature.
|
|
134
156
|
*/
|
package/out/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAA;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD;;GAEG;AACH;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;AAEvF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KACjC,MAAM,CAAC;IACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mailwoman/api",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0",
|
|
4
4
|
"description": "The native Mailwoman HTTP API — engine-agnostic /v1 surface (parse, geocode, batch, resolve, format) with health, metrics, and an emitted OpenAPI document.",
|
|
5
5
|
"license": "AGPL-3.0-only OR LicenseRef-Commercial",
|
|
6
6
|
"repository": {
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@hono/zod-openapi": "^1.5.1",
|
|
46
|
-
"@mailwoman/api-kit": "
|
|
47
|
-
"@mailwoman/core": "
|
|
48
|
-
"@mailwoman/formatter": "
|
|
46
|
+
"@mailwoman/api-kit": "9.0.0",
|
|
47
|
+
"@mailwoman/core": "9.0.0",
|
|
48
|
+
"@mailwoman/formatter": "9.0.0",
|
|
49
49
|
"hono": "^4.12.32",
|
|
50
50
|
"zod": "^4.4.3"
|
|
51
51
|
}
|
package/schema.ts
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Zod wire schemas for the native `/v1` surface. Unlike the drop-ins (photon, nominatim,
|
|
7
7
|
* libpostal), nothing here is a vendor contract — this surface is ours to design, so request
|
|
8
8
|
* bodies are REQUIRED and validator-enforced (no legacy tolerance to preserve). A `defaultHook`
|
|
9
|
-
* on the app
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* on the app maps validation failures through the shared `APIErrorSchema` envelope
|
|
10
|
+
* (`apiError(c, 400, "invalid request body", <zod summary>)`) — the pattern boundary every
|
|
11
|
+
* surface holds to: where no legacy contract exists, the validator MAY speak, but only in
|
|
12
12
|
* our envelope.
|
|
13
13
|
*
|
|
14
14
|
* `APIErrorSchema` itself is owned by `@mailwoman/api-kit` (plumbing shared by every native
|
|
@@ -30,12 +30,27 @@ export { APIErrorSchema } from "@mailwoman/api-kit"
|
|
|
30
30
|
*/
|
|
31
31
|
export const InputModeSchema = z.enum(["fragmented", "formatted"]).openapi("InputMode")
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Longest accepted `address`, in characters.
|
|
35
|
+
*
|
|
36
|
+
* Sized against what the model can actually read, not against a guess at abuse. The classifier's window is 128
|
|
37
|
+
* SentencePiece pieces — roughly 330 characters of address text — and everything past it is truncated before inference,
|
|
38
|
+
* so input beyond this bound cannot influence a result. The margin over that window leaves room for scripts that
|
|
39
|
+
* tokenize denser than Latin, and for the department-and-division prefixes web forms concatenate.
|
|
40
|
+
*
|
|
41
|
+
* The bound exists because preprocessing is linear but not free: a 1 MB body costs ~1.7 s across normalize, query-shape
|
|
42
|
+
* and the phrase grouper, and Node runs them on the one thread every other request is waiting on. A cap here is cheaper
|
|
43
|
+
* than fairness plumbing, and rejecting is more honest than accepting a body whose tail the parser will silently
|
|
44
|
+
* discard.
|
|
45
|
+
*/
|
|
46
|
+
export const MAX_ADDRESS_LENGTH = 1024
|
|
47
|
+
|
|
33
48
|
/**
|
|
34
49
|
* `POST /v1/parse` request body.
|
|
35
50
|
*/
|
|
36
51
|
export const ParseRequestSchema = z
|
|
37
52
|
.object({
|
|
38
|
-
address: z.string(),
|
|
53
|
+
address: z.string().max(MAX_ADDRESS_LENGTH),
|
|
39
54
|
debug: z.boolean().optional(),
|
|
40
55
|
input_mode: InputModeSchema.optional(),
|
|
41
56
|
})
|
|
@@ -65,7 +80,7 @@ export const ParseOutcomeSchema = z
|
|
|
65
80
|
*/
|
|
66
81
|
export const GeocodeRequestSchema = z
|
|
67
82
|
.object({
|
|
68
|
-
address: z.string(),
|
|
83
|
+
address: z.string().max(MAX_ADDRESS_LENGTH),
|
|
69
84
|
input_mode: InputModeSchema.optional(),
|
|
70
85
|
})
|
|
71
86
|
.openapi("GeocodeRequest")
|
|
@@ -127,9 +142,15 @@ export const GeocodeOutcomeSchema = z
|
|
|
127
142
|
venue: z.string().nullable(),
|
|
128
143
|
// The parsed dependent-locality span (parse view; `hierarchy` is the resolved view).
|
|
129
144
|
dependent_locality: z.string().nullable(),
|
|
145
|
+
// The parsed unit / sub-venue span (parse view) — "Terminal 5", "Suite 300".
|
|
146
|
+
unit: z.string().nullable(),
|
|
130
147
|
countryCode: z.string().nullable(),
|
|
131
148
|
hierarchy: z.array(GeocodeHierarchyEntrySchema),
|
|
132
149
|
candidates: z.array(GeocodeCandidateSchema),
|
|
150
|
+
// #42: the country the postcode-country coherence pass scoped the walk to, or null. Non-null ONLY when it
|
|
151
|
+
// OVERRODE the request's country prior — so a caller who asked for US and got an FR answer can see which
|
|
152
|
+
// evidence bought the change instead of reading it as a bug.
|
|
153
|
+
postcode_country_scope: z.string().nullable(),
|
|
133
154
|
})
|
|
134
155
|
.loose()
|
|
135
156
|
.openapi("GeocodeOutcome")
|
|
@@ -139,7 +160,9 @@ export const GeocodeOutcomeSchema = z
|
|
|
139
160
|
*/
|
|
140
161
|
export const BatchRequestSchema = z
|
|
141
162
|
.object({
|
|
142
|
-
|
|
163
|
+
// Per-ROW, not just per-request: the row cap (`batchMax`, default 500) bounds how many addresses arrive,
|
|
164
|
+
// and this bounds how large each may be. Without both, one request is 500 unbounded bodies.
|
|
165
|
+
addresses: z.array(z.string().max(MAX_ADDRESS_LENGTH)),
|
|
143
166
|
/**
|
|
144
167
|
* Register override for every row. DEFAULT `"formatted"` — batch rows are the record register by nature.
|
|
145
168
|
*/
|