@cp949/japanpost-react 1.0.1 → 1.0.3
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/README.ko.md +89 -23
- package/README.md +231 -191
- package/dist/client.d.ts +1 -0
- package/dist/client.es.js +3 -0
- package/dist/index.d.ts +1 -11
- package/dist/index.es.js +156 -290
- package/dist/src/client.d.ts +7 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/components/AddressSearchInput.d.ts.map +1 -0
- package/dist/src/components/PostalCodeInput.d.ts.map +1 -0
- package/dist/src/core/errors.d.ts.map +1 -0
- package/dist/src/core/formatters.d.ts.map +1 -0
- package/dist/src/core/normalizers.d.ts.map +1 -0
- package/dist/{core → src/core}/types.d.ts +27 -7
- package/dist/src/core/types.d.ts.map +1 -0
- package/dist/src/core/validators.d.ts.map +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/react/toJapanAddressError.d.ts.map +1 -0
- package/dist/src/react/useJapanAddress.d.ts.map +1 -0
- package/dist/src/react/useJapanAddressSearch.d.ts.map +1 -0
- package/dist/src/react/useJapanPostalCode.d.ts.map +1 -0
- package/dist/{react → src/react}/useLatestRequestState.d.ts +1 -0
- package/dist/src/react/useLatestRequestState.d.ts.map +1 -0
- package/package.json +11 -8
- package/dist/components/AddressSearchInput.d.ts.map +0 -1
- package/dist/components/PostalCodeInput.d.ts.map +0 -1
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/formatters.d.ts.map +0 -1
- package/dist/core/normalizers.d.ts.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/validators.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.umd.cjs +0 -6
- package/dist/react/toJapanAddressError.d.ts.map +0 -1
- package/dist/react/useJapanAddress.d.ts.map +0 -1
- package/dist/react/useJapanAddressSearch.d.ts.map +0 -1
- package/dist/react/useJapanPostalCode.d.ts.map +0 -1
- package/dist/react/useLatestRequestState.d.ts.map +0 -1
- /package/dist/{components → src/components}/AddressSearchInput.d.ts +0 -0
- /package/dist/{components → src/components}/PostalCodeInput.d.ts +0 -0
- /package/dist/{core → src/core}/errors.d.ts +0 -0
- /package/dist/{core → src/core}/formatters.d.ts +0 -0
- /package/dist/{core → src/core}/normalizers.d.ts +0 -0
- /package/dist/{core → src/core}/validators.d.ts +0 -0
- /package/dist/{react → src/react}/toJapanAddressError.d.ts +0 -0
- /package/dist/{react → src/react}/useJapanAddress.d.ts +0 -0
- /package/dist/{react → src/react}/useJapanAddressSearch.d.ts +0 -0
- /package/dist/{react → src/react}/useJapanPostalCode.d.ts +0 -0
package/README.md
CHANGED
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
<!-- This file is generated by `pnpm readme:package`. Edit docs/README.en.md and docs/README.ko.md instead. -->
|
|
6
6
|
|
|
7
|
-
React
|
|
8
|
-
lookup.
|
|
7
|
+
React hooks, headless input components, and utilities for Japan postal-code
|
|
8
|
+
and address lookup.
|
|
9
9
|
|
|
10
|
-
This package
|
|
11
|
-
|
|
12
|
-
and are documented in the root README.
|
|
10
|
+
This package does not call Japan Post directly. You provide a
|
|
11
|
+
`JapanAddressDataSource` that talks to your own backend API.
|
|
13
12
|
|
|
14
13
|
## Install
|
|
15
14
|
|
|
@@ -17,45 +16,76 @@ and are documented in the root README.
|
|
|
17
16
|
pnpm add @cp949/japanpost-react
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
-
|
|
19
|
+
- Peer dependencies: React 18 or React 19
|
|
20
|
+
- Package source in this repository:
|
|
21
|
+
`packages/japanpost-react`
|
|
22
|
+
- Demo app in this repository: `apps/demo`
|
|
23
|
+
|
|
24
|
+
This package is published as ESM. Keep server utilities and shared types on
|
|
25
|
+
`@cp949/japanpost-react`, and import hooks or headless input components for the
|
|
26
|
+
Next.js App Router from `@cp949/japanpost-react/client`. CommonJS consumers
|
|
27
|
+
must use ESM interop. `require("@cp949/japanpost-react")` and
|
|
28
|
+
`require("@cp949/japanpost-react/client")` are not supported. In CommonJS, use
|
|
29
|
+
ESM interop such as `const pkg = await import("@cp949/japanpost-react");`.
|
|
30
|
+
|
|
31
|
+
## Next.js
|
|
32
|
+
|
|
33
|
+
When you use hooks or headless input components in the Next.js App Router,
|
|
34
|
+
import them from `@cp949/japanpost-react/client` inside a Client Component.
|
|
35
|
+
Keep utility functions and shared types on the root entry.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
"use client";
|
|
39
|
+
|
|
40
|
+
import { PostalCodeInput, useJapanPostalCode } from "@cp949/japanpost-react/client";
|
|
41
|
+
import { normalizeJapanPostalCode, type JapanAddressDataSource } from "@cp949/japanpost-react";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## What The Package Provides
|
|
45
|
+
|
|
46
|
+
- Hooks for postal-code lookup and address search:
|
|
47
|
+
`useJapanPostalCode`, `useJapanAddressSearch`, `useJapanAddress`
|
|
48
|
+
- Headless form components:
|
|
49
|
+
`PostalCodeInput`, `AddressSearchInput`
|
|
50
|
+
- Utilities:
|
|
51
|
+
`normalizeJapanPostalCode`, `formatJapanPostalCode`,
|
|
52
|
+
`isValidJapanPostalCode`, `normalizeJapanPostAddressRecord`,
|
|
53
|
+
`createJapanAddressError`
|
|
54
|
+
- Public types for the request, response, error, and data-source contracts
|
|
21
55
|
|
|
22
56
|
## Quick Start
|
|
23
57
|
|
|
58
|
+
The package expects a `JapanAddressDataSource` with two methods:
|
|
59
|
+
|
|
60
|
+
- `lookupPostalCode(request, options?)`
|
|
61
|
+
- `searchAddress(request, options?)`
|
|
62
|
+
|
|
63
|
+
Both methods return `Promise<Page<JapanAddress>>`.
|
|
64
|
+
|
|
24
65
|
```tsx
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
JapanAddress,
|
|
30
|
-
|
|
66
|
+
import {
|
|
67
|
+
PostalCodeInput,
|
|
68
|
+
createJapanAddressError,
|
|
69
|
+
useJapanPostalCode,
|
|
70
|
+
type JapanAddress,
|
|
71
|
+
type JapanAddressDataSource,
|
|
72
|
+
type JapanAddressRequestOptions,
|
|
73
|
+
type Page,
|
|
31
74
|
} from "@cp949/japanpost-react";
|
|
32
|
-
import { createJapanAddressError } from "@cp949/japanpost-react";
|
|
33
75
|
|
|
34
|
-
// The only supported integration model is a real server-backed flow.
|
|
35
|
-
// Point the data source at your own backend API.
|
|
36
|
-
// On beta-compatible backends, blank addresszip searches and postal-code misses
|
|
37
|
-
// may return HTTP 200 with an empty page. Keep those as successful Page results.
|
|
38
|
-
// The status mapping below applies only to non-OK responses.
|
|
39
76
|
function isAbortError(error: unknown): boolean {
|
|
40
77
|
return error instanceof DOMException && error.name === "AbortError";
|
|
41
78
|
}
|
|
42
79
|
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (status === 400) {
|
|
53
|
-
return path === "/q/japanpost/searchcode"
|
|
54
|
-
? "invalid_postal_code"
|
|
55
|
-
: "invalid_query";
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return "data_source_error";
|
|
80
|
+
function isPagePayload(payload: unknown): payload is Page<JapanAddress> {
|
|
81
|
+
return (
|
|
82
|
+
typeof payload === "object" &&
|
|
83
|
+
payload !== null &&
|
|
84
|
+
Array.isArray((payload as { elements?: unknown }).elements) &&
|
|
85
|
+
typeof (payload as { totalElements?: unknown }).totalElements === "number" &&
|
|
86
|
+
typeof (payload as { pageNumber?: unknown }).pageNumber === "number" &&
|
|
87
|
+
typeof (payload as { rowsPerPage?: unknown }).rowsPerPage === "number"
|
|
88
|
+
);
|
|
59
89
|
}
|
|
60
90
|
|
|
61
91
|
async function readPage(
|
|
@@ -63,10 +93,10 @@ async function readPage(
|
|
|
63
93
|
request: unknown,
|
|
64
94
|
options?: JapanAddressRequestOptions,
|
|
65
95
|
): Promise<Page<JapanAddress>> {
|
|
66
|
-
let
|
|
96
|
+
let response: Response;
|
|
67
97
|
|
|
68
98
|
try {
|
|
69
|
-
|
|
99
|
+
response = await fetch(path, {
|
|
70
100
|
method: "POST",
|
|
71
101
|
headers: {
|
|
72
102
|
"content-type": "application/json",
|
|
@@ -78,173 +108,217 @@ async function readPage(
|
|
|
78
108
|
throw createJapanAddressError(
|
|
79
109
|
isAbortError(error) ? "timeout" : "network_error",
|
|
80
110
|
isAbortError(error) ? "Request timed out" : "Network request failed",
|
|
81
|
-
{
|
|
82
|
-
cause: error,
|
|
83
|
-
},
|
|
111
|
+
{ cause: error },
|
|
84
112
|
);
|
|
85
113
|
}
|
|
86
114
|
|
|
87
|
-
if (!
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
status:
|
|
92
|
-
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw createJapanAddressError(
|
|
117
|
+
"data_source_error",
|
|
118
|
+
`Request failed with status ${response.status}`,
|
|
119
|
+
{ status: response.status },
|
|
120
|
+
);
|
|
93
121
|
}
|
|
94
122
|
|
|
95
123
|
let payload: unknown;
|
|
96
124
|
|
|
97
125
|
try {
|
|
98
|
-
payload = await
|
|
126
|
+
payload = await response.json();
|
|
99
127
|
} catch (error) {
|
|
100
128
|
throw createJapanAddressError(
|
|
101
129
|
"bad_response",
|
|
102
130
|
"Response payload was not valid JSON",
|
|
103
|
-
{
|
|
104
|
-
cause: error,
|
|
105
|
-
},
|
|
131
|
+
{ cause: error },
|
|
106
132
|
);
|
|
107
133
|
}
|
|
108
134
|
|
|
109
|
-
if (
|
|
110
|
-
typeof payload !== "object" ||
|
|
111
|
-
payload === null ||
|
|
112
|
-
!Array.isArray((payload as { elements?: unknown }).elements) ||
|
|
113
|
-
typeof (payload as { totalElements?: unknown }).totalElements !== "number" ||
|
|
114
|
-
typeof (payload as { pageNumber?: unknown }).pageNumber !== "number" ||
|
|
115
|
-
typeof (payload as { rowsPerPage?: unknown }).rowsPerPage !== "number"
|
|
116
|
-
) {
|
|
135
|
+
if (!isPagePayload(payload)) {
|
|
117
136
|
throw createJapanAddressError(
|
|
118
137
|
"bad_response",
|
|
119
138
|
"Response payload must include a valid page payload",
|
|
120
139
|
);
|
|
121
140
|
}
|
|
122
141
|
|
|
123
|
-
return payload
|
|
142
|
+
return payload;
|
|
124
143
|
}
|
|
125
144
|
|
|
126
145
|
const dataSource: JapanAddressDataSource = {
|
|
127
|
-
|
|
128
|
-
return readPage(
|
|
146
|
+
lookupPostalCode(request, options) {
|
|
147
|
+
return readPage("/q/japanpost/searchcode", request, options);
|
|
129
148
|
},
|
|
130
|
-
|
|
131
|
-
return readPage(
|
|
149
|
+
searchAddress(request, options) {
|
|
150
|
+
return readPage("/q/japanpost/addresszip", request, options);
|
|
132
151
|
},
|
|
133
152
|
};
|
|
134
153
|
|
|
135
|
-
export function
|
|
154
|
+
export function PostalCodeLookupExample() {
|
|
136
155
|
const { loading, data, error, search } = useJapanPostalCode({ dataSource });
|
|
137
156
|
|
|
138
157
|
return (
|
|
139
158
|
<div>
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
<PostalCodeInput
|
|
160
|
+
buttonLabel="Search"
|
|
161
|
+
label="Postal code"
|
|
162
|
+
onSearch={(postalCode) => {
|
|
163
|
+
void search({ postalCode });
|
|
164
|
+
}}
|
|
165
|
+
/>
|
|
166
|
+
|
|
167
|
+
{loading ? <p>Loading...</p> : null}
|
|
168
|
+
{error ? <p>{error.message}</p> : null}
|
|
169
|
+
|
|
170
|
+
<ul>
|
|
171
|
+
{(data?.elements ?? []).map((address) => (
|
|
172
|
+
<li key={`${address.postalCode}-${address.address}`}>
|
|
173
|
+
{address.address}
|
|
174
|
+
</li>
|
|
175
|
+
))}
|
|
176
|
+
</ul>
|
|
151
177
|
</div>
|
|
152
178
|
);
|
|
153
179
|
}
|
|
154
180
|
```
|
|
155
181
|
|
|
156
|
-
The
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
The example paths above match this repository's reference backend. In your own
|
|
183
|
+
app, the backend routes can be different as long as your `dataSource`
|
|
184
|
+
implementation returns the same public types.
|
|
185
|
+
|
|
186
|
+
In Next.js, keep the `dataSource` implementation pointed at your own server-side
|
|
187
|
+
API routes. Do not expose Japan Post credentials or token exchange logic to the
|
|
188
|
+
browser.
|
|
189
|
+
|
|
190
|
+
## Core Contract
|
|
191
|
+
|
|
192
|
+
`Page<T>` is the result shape shared by the hooks and the reference backend:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
type Page<T> = {
|
|
196
|
+
elements: T[];
|
|
197
|
+
totalElements: number;
|
|
198
|
+
pageNumber: number;
|
|
199
|
+
rowsPerPage: number;
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`JapanAddress` is the normalized address shape returned by the package:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
type JapanAddress = {
|
|
207
|
+
postalCode: string;
|
|
208
|
+
prefecture: string;
|
|
209
|
+
prefectureKana?: string;
|
|
210
|
+
city: string;
|
|
211
|
+
cityKana?: string;
|
|
212
|
+
town: string;
|
|
213
|
+
townKana?: string;
|
|
214
|
+
address: string;
|
|
215
|
+
provider: "japan-post";
|
|
216
|
+
};
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The hooks keep this page payload as-is, so consumers read
|
|
220
|
+
`data?.elements`, `data?.totalElements`, `data?.pageNumber`, and
|
|
221
|
+
`data?.rowsPerPage` directly.
|
|
183
222
|
|
|
184
223
|
## Hooks
|
|
185
224
|
|
|
186
|
-
### useJapanPostalCode
|
|
225
|
+
### `useJapanPostalCode`
|
|
187
226
|
|
|
188
|
-
|
|
189
|
-
|
|
227
|
+
- Accepts `string` or `JapanPostalCodeSearchInput`
|
|
228
|
+
- Normalizes the input to digits before calling the data source
|
|
229
|
+
- Allows `3-7` digits, so prefix lookup is possible
|
|
230
|
+
- Builds `{ postalCode, pageNumber: 0, rowsPerPage: 100 }` by default
|
|
231
|
+
- Exposes `loading`, `data`, `error`, `search`, `cancel`, and `reset`
|
|
190
232
|
|
|
191
233
|
```tsx
|
|
192
|
-
const
|
|
193
|
-
|
|
234
|
+
const postalCode = useJapanPostalCode({ dataSource });
|
|
235
|
+
|
|
236
|
+
void postalCode.search("100-0001");
|
|
237
|
+
void postalCode.search({
|
|
238
|
+
postalCode: "1000001",
|
|
239
|
+
pageNumber: 1,
|
|
240
|
+
rowsPerPage: 10,
|
|
241
|
+
includeParenthesesTown: true,
|
|
194
242
|
});
|
|
195
243
|
```
|
|
196
244
|
|
|
197
|
-
### useJapanAddressSearch
|
|
245
|
+
### `useJapanAddressSearch`
|
|
198
246
|
|
|
199
|
-
|
|
247
|
+
- Accepts `string` or `JapanAddressSearchInput`
|
|
248
|
+
- Supports free-form search and structured fields in the same request type
|
|
249
|
+
- Rejects a fully blank query before calling the data source
|
|
250
|
+
- Omits `includeCityDetails` and `includePrefectureDetails` unless you set them
|
|
251
|
+
- Supports `debounceMs`
|
|
252
|
+
- Exposes `loading`, `data`, `error`, `search`, `cancel`, and `reset`
|
|
200
253
|
|
|
201
254
|
```tsx
|
|
202
|
-
const
|
|
255
|
+
const addressSearch = useJapanAddressSearch({
|
|
203
256
|
dataSource,
|
|
204
257
|
debounceMs: 300,
|
|
205
258
|
});
|
|
206
|
-
```
|
|
207
259
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
260
|
+
void addressSearch.search("千代田");
|
|
261
|
+
void addressSearch.search({
|
|
262
|
+
prefName: "東京都",
|
|
263
|
+
cityName: "千代田区",
|
|
264
|
+
pageNumber: 0,
|
|
265
|
+
rowsPerPage: 10,
|
|
266
|
+
});
|
|
267
|
+
```
|
|
212
268
|
|
|
213
|
-
### useJapanAddress
|
|
269
|
+
### `useJapanAddress`
|
|
214
270
|
|
|
215
|
-
Combines postal-code lookup and
|
|
271
|
+
- Combines postal-code lookup and address search in one hook
|
|
272
|
+
- Reuses the same `dataSource`
|
|
273
|
+
- Exposes `searchByPostalCode`, `searchByAddressQuery`, and `reset`
|
|
274
|
+
- Returns `data` and `error` for the currently active search mode only
|
|
216
275
|
|
|
217
276
|
```tsx
|
|
218
|
-
const
|
|
219
|
-
|
|
277
|
+
const address = useJapanAddress({
|
|
278
|
+
dataSource,
|
|
279
|
+
debounceMs: 300,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
void address.searchByPostalCode("1000001");
|
|
283
|
+
void address.searchByAddressQuery({
|
|
284
|
+
addressQuery: "千代田",
|
|
285
|
+
pageNumber: 0,
|
|
286
|
+
rowsPerPage: 10,
|
|
287
|
+
});
|
|
220
288
|
```
|
|
221
289
|
|
|
222
|
-
|
|
290
|
+
## Headless Components
|
|
291
|
+
|
|
292
|
+
### `PostalCodeInput`
|
|
293
|
+
|
|
294
|
+
- Renders a `<form>` with `<label>`, `<input>`, and `<button>`
|
|
295
|
+
- Supports controlled and uncontrolled usage
|
|
296
|
+
- Calls `onSearch` with a normalized digits-only postal code
|
|
297
|
+
- Defaults `inputMode="numeric"` unless overridden with `inputProps`
|
|
223
298
|
|
|
224
|
-
|
|
299
|
+
### `AddressSearchInput`
|
|
225
300
|
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
- `
|
|
229
|
-
- `useJapanAddress().searchByKeyword(query: string)`
|
|
301
|
+
- Renders the same minimal form structure
|
|
302
|
+
- Supports controlled and uncontrolled usage
|
|
303
|
+
- Calls `onSearch` with a trimmed query string
|
|
230
304
|
|
|
231
|
-
|
|
305
|
+
Both components accept:
|
|
232
306
|
|
|
233
|
-
-
|
|
234
|
-
-
|
|
307
|
+
- `inputProps` for the rendered `<input>`
|
|
308
|
+
- `buttonProps` for the rendered `<button>`
|
|
235
309
|
|
|
236
|
-
|
|
237
|
-
`includePrefectureDetails` are omitted unless your own data source
|
|
238
|
-
implementation sets them explicitly.
|
|
310
|
+
## Data Source Integration
|
|
239
311
|
|
|
240
|
-
|
|
312
|
+
The package exports types for both sides of the integration:
|
|
241
313
|
|
|
242
|
-
`JapanAddressDataSource`
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
`
|
|
314
|
+
- `JapanAddressDataSource`
|
|
315
|
+
- `JapanPostSearchcodeRequest`
|
|
316
|
+
- `JapanPostAddresszipRequest`
|
|
317
|
+
- `JapanPostalCodeSearchInput`
|
|
318
|
+
- `JapanAddressSearchInput`
|
|
319
|
+
- `JapanAddressRequestOptions`
|
|
246
320
|
|
|
247
|
-
|
|
321
|
+
The optional second argument to each data-source method is:
|
|
248
322
|
|
|
249
323
|
```ts
|
|
250
324
|
type JapanAddressRequestOptions = {
|
|
@@ -252,63 +326,29 @@ type JapanAddressRequestOptions = {
|
|
|
252
326
|
};
|
|
253
327
|
```
|
|
254
328
|
|
|
255
|
-
|
|
256
|
-
`reset()` calls, and unmount cleanup
|
|
257
|
-
|
|
258
|
-
Recommended error-code mapping:
|
|
259
|
-
|
|
260
|
-
| Situation | Recommended code |
|
|
261
|
-
| --- | --- |
|
|
262
|
-
| Invalid postal code input | `invalid_postal_code` |
|
|
263
|
-
| Blank keyword input in hook-side pre-validation | `invalid_query` |
|
|
264
|
-
| Network failure | `network_error` |
|
|
265
|
-
| Request aborted / timeout | `timeout` |
|
|
266
|
-
| No matching addresses on backends that surface misses as errors | `not_found` |
|
|
267
|
-
| Malformed success payload | `bad_response` |
|
|
268
|
-
| Other backend failures | `data_source_error` |
|
|
269
|
-
|
|
270
|
-
In this repository's reference demo flow, the sample `dataSource` classifies
|
|
271
|
-
failed requests by HTTP status code only. Current beta-compatible flows may
|
|
272
|
-
return `200` with an empty page for both blank `addresszip` requests and
|
|
273
|
-
postal-code misses, and those should stay successful page results. Other
|
|
274
|
-
`400` responses can still map to `invalid_query`, `404` remains useful for
|
|
275
|
-
backends that intentionally surface misses as errors, and `504` maps to
|
|
276
|
-
`timeout`.
|
|
277
|
-
|
|
278
|
-
## Headless Components
|
|
279
|
-
|
|
280
|
-
`PostalCodeInput` and `AddressSearchInput` provide behavior and DOM structure
|
|
281
|
-
without bundled styles, so you can plug them into your own design system.
|
|
282
|
-
|
|
283
|
-
Both components also support native prop passthrough:
|
|
284
|
-
|
|
285
|
-
- `inputProps`: forwarded to the rendered `<input />`
|
|
286
|
-
- `buttonProps`: forwarded to the rendered `<button />`
|
|
287
|
-
|
|
288
|
-
Use these for `id`, `name`, `placeholder`, `aria-*`, `autoComplete`,
|
|
289
|
-
`className`, and form integration. `PostalCodeInput` defaults to
|
|
290
|
-
`inputMode="numeric"` unless you override it through `inputProps`.
|
|
291
|
-
|
|
292
|
-
## Data Source and Server Integration
|
|
329
|
+
The hooks pass `signal` so your data source can cancel superseded requests,
|
|
330
|
+
`cancel()` calls, `reset()` calls, and unmount cleanup.
|
|
293
331
|
|
|
294
|
-
|
|
295
|
-
uses token-based authentication, so browser apps should not hold upstream
|
|
296
|
-
credentials directly. The supported integration model is a real server-backed
|
|
297
|
-
flow.
|
|
332
|
+
This repository's reference backend uses these routes:
|
|
298
333
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
integration testing. The demo's `/minimal-api` path is only a development-time
|
|
302
|
-
route to that local server. When the upstream payload includes both structured
|
|
303
|
-
address parts and a free-form `address` string, the reference server keeps the
|
|
304
|
-
display address non-duplicated instead of concatenating both blindly.
|
|
334
|
+
- `POST /q/japanpost/searchcode`
|
|
335
|
+
- `POST /q/japanpost/addresszip`
|
|
305
336
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
`timeout` error code.
|
|
337
|
+
But those route names are not part of the package API. They are just the
|
|
338
|
+
example used by `apps/demo` and `apps/minimal-api`.
|
|
309
339
|
|
|
310
|
-
##
|
|
340
|
+
## Constraints And Notes
|
|
311
341
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
342
|
+
- `dataSource` is required at runtime for all hooks.
|
|
343
|
+
- `isValidJapanPostalCode()` checks for an exact 7-digit postal code after
|
|
344
|
+
normalization. `useJapanPostalCode()` is less strict and accepts `3-7`
|
|
345
|
+
digits for prefix lookup.
|
|
346
|
+
- `formatJapanPostalCode()` inserts a hyphen only when the normalized value is
|
|
347
|
+
exactly 7 digits.
|
|
348
|
+
- `cancel()` on `useJapanPostalCode()` and `useJapanAddressSearch()` aborts the
|
|
349
|
+
in-flight request but keeps the latest settled `data` and `error`.
|
|
350
|
+
- `reset()` clears both `data` and `error`.
|
|
351
|
+
- The package does not require a backend to return `404` for misses. Returning
|
|
352
|
+
`200` with an empty page is also compatible with the hook contract.
|
|
353
|
+
- Use your own server-side API in the `dataSource` implementation. Keep Japan
|
|
354
|
+
Post credentials and token exchange on the server side.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./index";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export { PostalCodeInput } from './components/PostalCodeInput';
|
|
3
|
-
export { createJapanAddressError } from './core/errors';
|
|
4
|
-
export { formatJapanPostalCode, normalizeJapanPostalCode, } from './core/formatters';
|
|
5
|
-
export { normalizeJapanPostAddressRecord } from './core/normalizers';
|
|
6
|
-
export type { AddressSearchInputProps, JapanAddress, JapanAddressDataSource, JapanAddressError, JapanAddressErrorCode, JapanPostAddresszipRequest, JapanPostSearchcodeRequest, JapanAddressRequestOptions, JapanAddressSearchResult, JapanPostalCodeLookupResult, NormalizedJapanAddressRecord, Page, PostalCodeInputProps, UseJapanAddressOptions, UseJapanAddressResult, UseJapanAddressSearchOptions, UseJapanAddressSearchResult, UseJapanPostalCodeOptions, UseJapanPostalCodeResult, } from './core/types';
|
|
7
|
-
export { isValidJapanPostalCode } from './core/validators';
|
|
8
|
-
export { useJapanAddress } from './react/useJapanAddress';
|
|
9
|
-
export { useJapanAddressSearch } from './react/useJapanAddressSearch';
|
|
10
|
-
export { useJapanPostalCode } from './react/useJapanPostalCode';
|
|
11
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
export {}
|