@ucdjs/client 0.1.1-beta.1
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/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/index.d.mts +837 -0
- package/dist/index.mjs +155 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-PRESENT Lucas Nørgård
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# @ucdjs/client
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
[![codecov][codecov-src]][codecov-href]
|
|
6
|
+
|
|
7
|
+
A TypeScript-first HTTP client for interacting with the UCD.js API, providing type-safe methods for fetching Unicode character data.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @ucdjs/client
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Basic Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { client } from "@ucdjs/client";
|
|
21
|
+
|
|
22
|
+
// Get Unicode versions
|
|
23
|
+
const { data: versions, error } = await client.GET("/api/v1/unicode-versions");
|
|
24
|
+
if (error) {
|
|
25
|
+
console.error("Error:", error.message);
|
|
26
|
+
} else {
|
|
27
|
+
console.log("Available versions:", versions);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Access Unicode data files via proxy
|
|
31
|
+
const { data: fileInfo } = await client.GET("/api/v1/unicode-proxy/{wildcard}", {
|
|
32
|
+
params: {
|
|
33
|
+
path: { wildcard: "latest/ucd.all.json" }
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
console.log("File info:", fileInfo);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Custom Client Configuration
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { createClient } from "@ucdjs/client";
|
|
43
|
+
|
|
44
|
+
// Create client with custom UCD.js API instance
|
|
45
|
+
const customClient = createClient("https://preview.api.ucdjs.dev");
|
|
46
|
+
|
|
47
|
+
// Use the custom client
|
|
48
|
+
const { data, error } = await customClient.GET("/api/v1/unicode-versions");
|
|
49
|
+
if (data) {
|
|
50
|
+
console.log("Unicode versions from preview API:", data);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Working with Binary Data
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { client } from "@ucdjs/client";
|
|
58
|
+
|
|
59
|
+
// Fetch binary Unicode data file
|
|
60
|
+
const { data: binaryData } = await client.GET("/api/v1/unicode-proxy/{wildcard}", {
|
|
61
|
+
params: {
|
|
62
|
+
path: { wildcard: "latest/UnicodeData.txt" }
|
|
63
|
+
},
|
|
64
|
+
parseAs: "arrayBuffer"
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
if (binaryData) {
|
|
68
|
+
// eslint-disable-next-line node/prefer-global/buffer
|
|
69
|
+
const text = Buffer.from(binaryData).toString("utf-8");
|
|
70
|
+
console.log("Unicode data:", `${text.substring(0, 100)}...`);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Documentation
|
|
75
|
+
|
|
76
|
+
For comprehensive documentation, examples, and API reference, visit the [Client Documentation](https://ucdjs.dev/docs/core/client).
|
|
77
|
+
|
|
78
|
+
## 📄 License
|
|
79
|
+
|
|
80
|
+
Published under [MIT License](./LICENSE).
|
|
81
|
+
|
|
82
|
+
[npm-version-src]: https://img.shields.io/npm/v/@ucdjs/client?style=flat&colorA=18181B&colorB=4169E1
|
|
83
|
+
[npm-version-href]: https://npmjs.com/package/@ucdjs/client
|
|
84
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/@ucdjs/client?style=flat&colorA=18181B&colorB=4169E1
|
|
85
|
+
[npm-downloads-href]: https://npmjs.com/package/@ucdjs/client
|
|
86
|
+
[codecov-src]: https://img.shields.io/codecov/c/gh/ucdjs/ucd?style=flat&colorA=18181B&colorB=4169E1
|
|
87
|
+
[codecov-href]: https://codecov.io/gh/ucdjs/ucd
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,837 @@
|
|
|
1
|
+
import { SafeFetchResponse } from "@ucdjs-internal/shared";
|
|
2
|
+
import { UCDStoreVersionManifest, UCDWellKnownConfig } from "@ucdjs/schemas";
|
|
3
|
+
|
|
4
|
+
//#region src/resources/config.d.ts
|
|
5
|
+
interface ConfigResource {
|
|
6
|
+
/**
|
|
7
|
+
* Get the UCD configuration including endpoints and available versions
|
|
8
|
+
* @returns {Promise<SafeFetchResponse<UCDWellKnownConfig>>} The UCD configuration
|
|
9
|
+
*/
|
|
10
|
+
get: () => Promise<SafeFetchResponse<UCDWellKnownConfig>>;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/.generated/api.d.ts
|
|
14
|
+
/**
|
|
15
|
+
* This file was auto-generated by openapi-typescript.
|
|
16
|
+
* Do not make direct changes to the file.
|
|
17
|
+
*/
|
|
18
|
+
interface paths {
|
|
19
|
+
"/api/v1/versions": {
|
|
20
|
+
parameters: {
|
|
21
|
+
query?: never;
|
|
22
|
+
header?: never;
|
|
23
|
+
path?: never;
|
|
24
|
+
cookie?: never;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @description ## List All Unicode Versions
|
|
28
|
+
*
|
|
29
|
+
* This endpoint retrieves a comprehensive list of all Unicode versions, including metadata and support status.
|
|
30
|
+
*
|
|
31
|
+
* - Provides **version metadata** such as documentation URLs and public URLs
|
|
32
|
+
* - Includes **draft versions** if available
|
|
33
|
+
* - Supports **caching** for performance optimization
|
|
34
|
+
*/
|
|
35
|
+
get: {
|
|
36
|
+
parameters: {
|
|
37
|
+
query?: never;
|
|
38
|
+
header?: never;
|
|
39
|
+
path?: never;
|
|
40
|
+
cookie?: never;
|
|
41
|
+
};
|
|
42
|
+
requestBody?: never;
|
|
43
|
+
responses: {
|
|
44
|
+
/** @description List of Unicode Versions */200: {
|
|
45
|
+
headers: {
|
|
46
|
+
[name: string]: unknown;
|
|
47
|
+
};
|
|
48
|
+
content: {
|
|
49
|
+
"application/json": components["schemas"]["UnicodeVersionList"];
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
404: components["responses"]["NotFoundError"];
|
|
53
|
+
429: components["responses"]["TooManyRequestsError"];
|
|
54
|
+
500: components["responses"]["InternalServerError"];
|
|
55
|
+
502: components["responses"]["BadGatewayError"];
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
put?: never;
|
|
59
|
+
post?: never;
|
|
60
|
+
delete?: never;
|
|
61
|
+
options?: never;
|
|
62
|
+
head?: never;
|
|
63
|
+
patch?: never;
|
|
64
|
+
trace?: never;
|
|
65
|
+
};
|
|
66
|
+
"/api/v1/versions/{version}": {
|
|
67
|
+
parameters: {
|
|
68
|
+
query?: never;
|
|
69
|
+
header?: never;
|
|
70
|
+
path?: never;
|
|
71
|
+
cookie?: never;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* @description ## Get Unicode Version Details
|
|
75
|
+
*
|
|
76
|
+
* This endpoint retrieves detailed information about a specific Unicode version.
|
|
77
|
+
*
|
|
78
|
+
* - Provides **version metadata** such as version name, documentation URL, release date, and type (stable/draft)
|
|
79
|
+
* - Includes **location information** (UCD URL and mapped version)
|
|
80
|
+
* - Returns **statistics** about characters, blocks, and scripts (if available)
|
|
81
|
+
* - Supports **caching** for performance optimization
|
|
82
|
+
*/
|
|
83
|
+
get: {
|
|
84
|
+
parameters: {
|
|
85
|
+
query?: never;
|
|
86
|
+
header?: never;
|
|
87
|
+
path: {
|
|
88
|
+
/** @description A Unicode Version */version: string;
|
|
89
|
+
};
|
|
90
|
+
cookie?: never;
|
|
91
|
+
};
|
|
92
|
+
requestBody?: never;
|
|
93
|
+
responses: {
|
|
94
|
+
/** @description Detailed information about a Unicode version */200: {
|
|
95
|
+
headers: {
|
|
96
|
+
[name: string]: unknown;
|
|
97
|
+
};
|
|
98
|
+
content: {
|
|
99
|
+
"application/json": components["schemas"]["UnicodeVersionDetails"];
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
400: components["responses"]["BadRequestError"];
|
|
103
|
+
404: components["responses"]["NotFoundError"];
|
|
104
|
+
429: components["responses"]["TooManyRequestsError"];
|
|
105
|
+
500: components["responses"]["InternalServerError"];
|
|
106
|
+
502: components["responses"]["BadGatewayError"];
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
put?: never;
|
|
110
|
+
post?: never;
|
|
111
|
+
delete?: never;
|
|
112
|
+
options?: never;
|
|
113
|
+
head?: never;
|
|
114
|
+
patch?: never;
|
|
115
|
+
trace?: never;
|
|
116
|
+
};
|
|
117
|
+
"/api/v1/versions/{version}/file-tree": {
|
|
118
|
+
parameters: {
|
|
119
|
+
query?: never;
|
|
120
|
+
header?: never;
|
|
121
|
+
path?: never;
|
|
122
|
+
cookie?: never;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* @description This endpoint provides a **structured list of all files** inside the [`ucd folder`](https://unicode.org/Public/UCD/latest/ucd) associated with a specific Unicode version.
|
|
126
|
+
*
|
|
127
|
+
* For older versions, the files are retrieved without the `/ucd` prefix, while for the latest version, the `/ucd` prefix is included.
|
|
128
|
+
*/
|
|
129
|
+
get: {
|
|
130
|
+
parameters: {
|
|
131
|
+
query?: never;
|
|
132
|
+
header?: never;
|
|
133
|
+
path: {
|
|
134
|
+
/** @description A Unicode Version */version: string;
|
|
135
|
+
};
|
|
136
|
+
cookie?: never;
|
|
137
|
+
};
|
|
138
|
+
requestBody?: never;
|
|
139
|
+
responses: {
|
|
140
|
+
/** @description Structured list of files for a Unicode version */200: {
|
|
141
|
+
headers: {
|
|
142
|
+
[name: string]: unknown;
|
|
143
|
+
};
|
|
144
|
+
content: {
|
|
145
|
+
"application/json": components["schemas"]["UnicodeFileTree"];
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
400: components["responses"]["BadRequestError"];
|
|
149
|
+
429: components["responses"]["TooManyRequestsError"];
|
|
150
|
+
500: components["responses"]["InternalServerError"];
|
|
151
|
+
502: components["responses"]["BadGatewayError"];
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
put?: never;
|
|
155
|
+
post?: never;
|
|
156
|
+
delete?: never;
|
|
157
|
+
options?: never;
|
|
158
|
+
head?: never;
|
|
159
|
+
patch?: never;
|
|
160
|
+
trace?: never;
|
|
161
|
+
};
|
|
162
|
+
"/api/v1/files/{wildcard}": {
|
|
163
|
+
parameters: {
|
|
164
|
+
query?: never;
|
|
165
|
+
header?: never;
|
|
166
|
+
path?: never;
|
|
167
|
+
cookie?: never;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* @description This endpoint proxies requests to Unicode.org's Public directory, streaming files directly while transforming directory listings into structured JSON.
|
|
171
|
+
*
|
|
172
|
+
* All paths are relative to `/api/v1/files` — for example, requesting `/api/v1/files/15.1.0/ucd/emoji/emoji-data.txt` fetches the emoji data file from Unicode version 15.1.0.
|
|
173
|
+
*
|
|
174
|
+
* > [!IMPORTANT]
|
|
175
|
+
* > The `{wildcard}` parameter accepts any valid path, including deeply nested ones like `15.1.0/ucd/emoji/emoji-data.txt`. In directory listing responses, paths for directories include a trailing slash (e.g., `/15.1.0/ucd/charts/`), while file paths do not.
|
|
176
|
+
*
|
|
177
|
+
* > [!NOTE]
|
|
178
|
+
* > To retrieve only metadata without downloading content, use a `HEAD` request instead. See [here](#tag/files/head/api/v1/files/{wildcard})
|
|
179
|
+
*
|
|
180
|
+
* ### Directory Listing Features
|
|
181
|
+
*
|
|
182
|
+
* When accessing a directory, you can filter and sort entries using these query parameters:
|
|
183
|
+
*
|
|
184
|
+
* - `query` - Prefix-based search (case-insensitive) on entry names
|
|
185
|
+
* - `pattern` - Glob pattern matching for filtering
|
|
186
|
+
* - `type` - Filter by entry type: `all` (default), `files`, or `directories`
|
|
187
|
+
* - `sort` - Sort by `name` (default) or `lastModified`
|
|
188
|
+
* - `order` - Sort order: `asc` (default) or `desc`
|
|
189
|
+
*
|
|
190
|
+
* ### Modifications
|
|
191
|
+
*
|
|
192
|
+
* Directory responses are automatically transformed into JSON arrays containing file and directory entries. Files are streamed directly from Unicode.org with appropriate content types.
|
|
193
|
+
*/
|
|
194
|
+
get: {
|
|
195
|
+
parameters: {
|
|
196
|
+
query?: {
|
|
197
|
+
/**
|
|
198
|
+
* @description A glob pattern to filter directory listing results by filename. Only applies when the response is a directory listing.
|
|
199
|
+
* The matching is **case-insensitive**.
|
|
200
|
+
*
|
|
201
|
+
* ## Supported Glob Syntax
|
|
202
|
+
*
|
|
203
|
+
* | Pattern | Description | Example |
|
|
204
|
+
* |-----------|-----------------------------------------------|------------------------------------------------------|
|
|
205
|
+
* | `*` | Match any characters (except path separators) | `*.txt` matches `file.txt` |
|
|
206
|
+
* | `?` | Match a single character | `file?.txt` matches `file1.txt` |
|
|
207
|
+
* | `{a,b}` | Match any of the patterns | `*.{txt,xml}` matches `file.txt` or `file.xml` |
|
|
208
|
+
* | `[abc]` | Match any character in the set | `file[123].txt` matches `file1.txt` |
|
|
209
|
+
*
|
|
210
|
+
* ## Examples
|
|
211
|
+
*
|
|
212
|
+
* - `*.txt` - Match all text files
|
|
213
|
+
* - `Uni*` - Match files starting with "Uni" (e.g., UnicodeData.txt)
|
|
214
|
+
* - `*Data*` - Match files containing "Data"
|
|
215
|
+
* - `*.{txt,xml}` - Match text or XML files
|
|
216
|
+
*/
|
|
217
|
+
pattern?: string;
|
|
218
|
+
/**
|
|
219
|
+
* @description A search query to filter directory listing results. Entries are matched if their name **starts with** this value (case-insensitive).
|
|
220
|
+
* This is useful for quick prefix-based searching within a directory.
|
|
221
|
+
*
|
|
222
|
+
* ## Examples
|
|
223
|
+
*
|
|
224
|
+
* - `Uni` - Match entries starting with "Uni" (e.g., UnicodeData.txt)
|
|
225
|
+
* - `15` - Match version directories starting with "15"
|
|
226
|
+
*/
|
|
227
|
+
query?: string;
|
|
228
|
+
/**
|
|
229
|
+
* @description Filter directory listing results by entry type.
|
|
230
|
+
*
|
|
231
|
+
* - `all` (default) - Return both files and directories
|
|
232
|
+
* - `files` - Return only files
|
|
233
|
+
* - `directories` - Return only directories
|
|
234
|
+
*/
|
|
235
|
+
type?: "all" | "files" | "directories";
|
|
236
|
+
/**
|
|
237
|
+
* @description The field to sort directory listing results by.
|
|
238
|
+
*
|
|
239
|
+
* - `name` (default) - Sort alphabetically by entry name
|
|
240
|
+
* - `lastModified` - Sort by last modification timestamp
|
|
241
|
+
*/
|
|
242
|
+
sort?: "name" | "lastModified";
|
|
243
|
+
/**
|
|
244
|
+
* @description The sort order for directory listing results.
|
|
245
|
+
*
|
|
246
|
+
* - `asc` (default) - Ascending order (A-Z, oldest first)
|
|
247
|
+
* - `desc` - Descending order (Z-A, newest first)
|
|
248
|
+
*/
|
|
249
|
+
order?: "asc" | "desc";
|
|
250
|
+
};
|
|
251
|
+
header?: never;
|
|
252
|
+
path: {
|
|
253
|
+
/**
|
|
254
|
+
* @description The path to the Unicode data resource you want to access. This can be any valid path from the official Unicode Public directory structure.
|
|
255
|
+
*
|
|
256
|
+
* ## Path Format Options
|
|
257
|
+
*
|
|
258
|
+
* | Pattern | Description | Example |
|
|
259
|
+
* |--------------------------------|--------------------------------|-------------------------------------|
|
|
260
|
+
* | `{version}/ucd/{filename}` | UCD files for specific version | `15.1.0/ucd/UnicodeData.txt` |
|
|
261
|
+
* | `{version}/ucd/{sub}/{file}` | Files in subdirectories | `15.1.0/ucd/emoji/emoji-data.txt` |
|
|
262
|
+
* | `{version}` | List files for version | `15.1.0` |
|
|
263
|
+
* | `latest/ucd/{filename}` | Latest version of file | `latest/ucd/PropList.txt` |
|
|
264
|
+
*/
|
|
265
|
+
wildcard: string;
|
|
266
|
+
};
|
|
267
|
+
cookie?: never;
|
|
268
|
+
};
|
|
269
|
+
requestBody?: never;
|
|
270
|
+
responses: {
|
|
271
|
+
/** @description Response from Unicode.org */200: {
|
|
272
|
+
headers: {
|
|
273
|
+
/** @description The type of the file or directory */"X-UCD-Stat-Type": "file" | "directory"; /** @description The size of the file in bytes (only for files) */
|
|
274
|
+
"X-UCD-Stat-Size"?: string; /** @description Number of children (only for directories) */
|
|
275
|
+
"X-UCD-Stat-Children"?: string; /** @description Number of child files (only for directories) */
|
|
276
|
+
"X-UCD-Stat-Children-Files"?: string; /** @description Number of child directories (only for directories) */
|
|
277
|
+
"X-UCD-Stat-Children-Dirs"?: string;
|
|
278
|
+
[name: string]: unknown;
|
|
279
|
+
};
|
|
280
|
+
content: {
|
|
281
|
+
"application/json": components["schemas"]["FileEntryList"];
|
|
282
|
+
"application/xml": string;
|
|
283
|
+
"text/plain": string;
|
|
284
|
+
"text/html": string;
|
|
285
|
+
"application/pdf": string;
|
|
286
|
+
"application/octet-stream": string;
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
400: components["responses"]["BadRequestError"];
|
|
290
|
+
404: components["responses"]["NotFoundError"];
|
|
291
|
+
500: components["responses"]["InternalServerError"];
|
|
292
|
+
502: components["responses"]["BadGatewayError"];
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
put?: never;
|
|
296
|
+
post?: never;
|
|
297
|
+
delete?: never;
|
|
298
|
+
options?: never;
|
|
299
|
+
/**
|
|
300
|
+
* @description Retrieve metadata about a file or directory without downloading the content. Useful for checking existence, file size, and other metadata.
|
|
301
|
+
*
|
|
302
|
+
* All paths are relative to `/api/v1/files`. Directory paths always include a trailing slash (e.g., `/15.1.0/ucd/charts/`), while file paths do not.
|
|
303
|
+
*
|
|
304
|
+
* > [!NOTE]
|
|
305
|
+
* > This endpoint returns the same headers as the `GET` request (file size, directory entry counts, last modified timestamps, content type) without the response body.
|
|
306
|
+
*/
|
|
307
|
+
head: {
|
|
308
|
+
parameters: {
|
|
309
|
+
query?: {
|
|
310
|
+
/**
|
|
311
|
+
* @description A glob pattern to filter directory listing results by filename. Only applies when the response is a directory listing.
|
|
312
|
+
* The matching is **case-insensitive**.
|
|
313
|
+
*
|
|
314
|
+
* ## Supported Glob Syntax
|
|
315
|
+
*
|
|
316
|
+
* | Pattern | Description | Example |
|
|
317
|
+
* |-----------|-----------------------------------------------|------------------------------------------------------|
|
|
318
|
+
* | `*` | Match any characters (except path separators) | `*.txt` matches `file.txt` |
|
|
319
|
+
* | `?` | Match a single character | `file?.txt` matches `file1.txt` |
|
|
320
|
+
* | `{a,b}` | Match any of the patterns | `*.{txt,xml}` matches `file.txt` or `file.xml` |
|
|
321
|
+
* | `[abc]` | Match any character in the set | `file[123].txt` matches `file1.txt` |
|
|
322
|
+
*
|
|
323
|
+
* ## Examples
|
|
324
|
+
*
|
|
325
|
+
* - `*.txt` - Match all text files
|
|
326
|
+
* - `Uni*` - Match files starting with "Uni" (e.g., UnicodeData.txt)
|
|
327
|
+
* - `*Data*` - Match files containing "Data"
|
|
328
|
+
* - `*.{txt,xml}` - Match text or XML files
|
|
329
|
+
*/
|
|
330
|
+
pattern?: string;
|
|
331
|
+
/**
|
|
332
|
+
* @description A search query to filter directory listing results. Entries are matched if their name **starts with** this value (case-insensitive).
|
|
333
|
+
* This is useful for quick prefix-based searching within a directory.
|
|
334
|
+
*
|
|
335
|
+
* ## Examples
|
|
336
|
+
*
|
|
337
|
+
* - `Uni` - Match entries starting with "Uni" (e.g., UnicodeData.txt)
|
|
338
|
+
* - `15` - Match version directories starting with "15"
|
|
339
|
+
*/
|
|
340
|
+
query?: string;
|
|
341
|
+
/**
|
|
342
|
+
* @description Filter directory listing results by entry type.
|
|
343
|
+
*
|
|
344
|
+
* - `all` (default) - Return both files and directories
|
|
345
|
+
* - `files` - Return only files
|
|
346
|
+
* - `directories` - Return only directories
|
|
347
|
+
*/
|
|
348
|
+
type?: "all" | "files" | "directories";
|
|
349
|
+
/**
|
|
350
|
+
* @description The field to sort directory listing results by.
|
|
351
|
+
*
|
|
352
|
+
* - `name` (default) - Sort alphabetically by entry name
|
|
353
|
+
* - `lastModified` - Sort by last modification timestamp
|
|
354
|
+
*/
|
|
355
|
+
sort?: "name" | "lastModified";
|
|
356
|
+
/**
|
|
357
|
+
* @description The sort order for directory listing results.
|
|
358
|
+
*
|
|
359
|
+
* - `asc` (default) - Ascending order (A-Z, oldest first)
|
|
360
|
+
* - `desc` - Descending order (Z-A, newest first)
|
|
361
|
+
*/
|
|
362
|
+
order?: "asc" | "desc";
|
|
363
|
+
};
|
|
364
|
+
header?: never;
|
|
365
|
+
path: {
|
|
366
|
+
/**
|
|
367
|
+
* @description The path to the Unicode data resource you want to access. This can be any valid path from the official Unicode Public directory structure.
|
|
368
|
+
*
|
|
369
|
+
* ## Path Format Options
|
|
370
|
+
*
|
|
371
|
+
* | Pattern | Description | Example |
|
|
372
|
+
* |--------------------------------|--------------------------------|-------------------------------------|
|
|
373
|
+
* | `{version}/ucd/{filename}` | UCD files for specific version | `15.1.0/ucd/UnicodeData.txt` |
|
|
374
|
+
* | `{version}/ucd/{sub}/{file}` | Files in subdirectories | `15.1.0/ucd/emoji/emoji-data.txt` |
|
|
375
|
+
* | `{version}` | List files for version | `15.1.0` |
|
|
376
|
+
* | `latest/ucd/{filename}` | Latest version of file | `latest/ucd/PropList.txt` |
|
|
377
|
+
*/
|
|
378
|
+
wildcard: string;
|
|
379
|
+
};
|
|
380
|
+
cookie?: never;
|
|
381
|
+
};
|
|
382
|
+
requestBody?: never;
|
|
383
|
+
responses: {
|
|
384
|
+
/** @description Response from Unicode.org */200: {
|
|
385
|
+
headers: {
|
|
386
|
+
/** @description The type of the file or directory */"X-UCD-Stat-Type": "file" | "directory"; /** @description The size of the file in bytes (only for files) */
|
|
387
|
+
"X-UCD-Stat-Size": string; /** @description Number of children (only for directories) */
|
|
388
|
+
"X-UCD-Stat-Children"?: string; /** @description Number of child files (only for directories) */
|
|
389
|
+
"X-UCD-Stat-Children-Files"?: string; /** @description Number of child directories (only for directories) */
|
|
390
|
+
"X-UCD-Stat-Children-Dirs"?: string; /** @description The content type of the file */
|
|
391
|
+
"Content-Type": string; /** @description Last modification time from upstream */
|
|
392
|
+
"Last-Modified"?: string; /** @description Byte length when applicable */
|
|
393
|
+
"Content-Length": string;
|
|
394
|
+
[name: string]: unknown;
|
|
395
|
+
};
|
|
396
|
+
content?: never;
|
|
397
|
+
};
|
|
398
|
+
};
|
|
399
|
+
};
|
|
400
|
+
patch?: never;
|
|
401
|
+
trace?: never;
|
|
402
|
+
};
|
|
403
|
+
"/.well-known/ucd-config.json": {
|
|
404
|
+
parameters: {
|
|
405
|
+
query?: never;
|
|
406
|
+
header?: never;
|
|
407
|
+
path?: never;
|
|
408
|
+
cookie?: never;
|
|
409
|
+
};
|
|
410
|
+
/**
|
|
411
|
+
* @description ## UCD Configuration
|
|
412
|
+
*
|
|
413
|
+
* This endpoint retrieves the UCD configuration, including available API endpoints for accessing Unicode data resources.
|
|
414
|
+
*
|
|
415
|
+
* > [!NOTE]
|
|
416
|
+
* > The configuration follows the [UCD.js Well-Known Configuration](https://ucdjs.dev/docs/usage/well-known) specification.
|
|
417
|
+
*/
|
|
418
|
+
get: {
|
|
419
|
+
parameters: {
|
|
420
|
+
query?: never;
|
|
421
|
+
header?: never;
|
|
422
|
+
path?: never;
|
|
423
|
+
cookie?: never;
|
|
424
|
+
};
|
|
425
|
+
requestBody?: never;
|
|
426
|
+
responses: {
|
|
427
|
+
/** @description Retrieves the UCD configuration */200: {
|
|
428
|
+
headers: {
|
|
429
|
+
[name: string]: unknown;
|
|
430
|
+
};
|
|
431
|
+
content: {
|
|
432
|
+
"application/json": components["schemas"]["UCDWellKnownConfig"];
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
502: components["responses"]["BadGatewayError"];
|
|
436
|
+
};
|
|
437
|
+
};
|
|
438
|
+
put?: never;
|
|
439
|
+
post?: never;
|
|
440
|
+
delete?: never;
|
|
441
|
+
options?: never;
|
|
442
|
+
head?: never;
|
|
443
|
+
patch?: never;
|
|
444
|
+
trace?: never;
|
|
445
|
+
};
|
|
446
|
+
"/.well-known/ucd-store/{version}.json": {
|
|
447
|
+
parameters: {
|
|
448
|
+
query?: never;
|
|
449
|
+
header?: never;
|
|
450
|
+
path?: never;
|
|
451
|
+
cookie?: never;
|
|
452
|
+
};
|
|
453
|
+
/**
|
|
454
|
+
* @description ## UCD Store Manifest (Per Version)
|
|
455
|
+
*
|
|
456
|
+
* This endpoint retrieves the UCD Store manifest for a specific Unicode version, containing metadata about expected files for that version.
|
|
457
|
+
*
|
|
458
|
+
* This is the recommended endpoint for fetching manifest data, as it provides:
|
|
459
|
+
* - Smaller payloads (only the requested version)
|
|
460
|
+
* - Better caching (version-specific cache invalidation)
|
|
461
|
+
* - Reduced server load
|
|
462
|
+
*
|
|
463
|
+
* Each file entry includes:
|
|
464
|
+
* - `name`: The filename only
|
|
465
|
+
* - `path`: Path for the /api/v1/files endpoint (includes /ucd/ for versions >= 4.1.0)
|
|
466
|
+
* - `storePath`: Path for the store subdomain (ucd-store.ucdjs.dev)
|
|
467
|
+
*
|
|
468
|
+
* > [!NOTE]
|
|
469
|
+
* > The monolithic endpoint `/.well-known/ucd-store.json` is deprecated. Use this per-version endpoint instead.
|
|
470
|
+
*/
|
|
471
|
+
get: {
|
|
472
|
+
parameters: {
|
|
473
|
+
query?: never;
|
|
474
|
+
header?: never;
|
|
475
|
+
path: {
|
|
476
|
+
/** @description Unicode version (e.g., '16.0.0') */version: string;
|
|
477
|
+
};
|
|
478
|
+
cookie?: never;
|
|
479
|
+
};
|
|
480
|
+
requestBody?: never;
|
|
481
|
+
responses: {
|
|
482
|
+
/** @description The UCD Store manifest for the specified version */200: {
|
|
483
|
+
headers: {
|
|
484
|
+
[name: string]: unknown;
|
|
485
|
+
};
|
|
486
|
+
content: {
|
|
487
|
+
"application/json": components["schemas"]["UCDStoreVersionManifest"];
|
|
488
|
+
};
|
|
489
|
+
};
|
|
490
|
+
404: components["responses"]["NotFoundError"];
|
|
491
|
+
429: components["responses"]["TooManyRequestsError"];
|
|
492
|
+
500: components["responses"]["InternalServerError"];
|
|
493
|
+
502: components["responses"]["BadGatewayError"];
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
put?: never;
|
|
497
|
+
post?: never;
|
|
498
|
+
delete?: never;
|
|
499
|
+
options?: never;
|
|
500
|
+
head?: never;
|
|
501
|
+
patch?: never;
|
|
502
|
+
trace?: never;
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
interface components {
|
|
506
|
+
schemas: {
|
|
507
|
+
/**
|
|
508
|
+
* @description Standard error response format used consistently across all API endpoints.
|
|
509
|
+
*
|
|
510
|
+
* Contains essential information for debugging and user feedback. The specific error scenarios and status codes are documented in the individual endpoint response definitions.
|
|
511
|
+
*/
|
|
512
|
+
ApiError: {
|
|
513
|
+
/** @description Human-readable error message describing what went wrong */message: string; /** @description HTTP status code matching the response status */
|
|
514
|
+
status: number; /** @description ISO 8601 timestamp when the error occurred */
|
|
515
|
+
timestamp: string;
|
|
516
|
+
}; /** @description A list of Unicode versions with their metadata and support status. */
|
|
517
|
+
UnicodeVersionList: components["schemas"]["UnicodeVersion"][];
|
|
518
|
+
/**
|
|
519
|
+
* @description Represents a Unicode version with its metadata and support status.
|
|
520
|
+
* @example {
|
|
521
|
+
* "version": "17.0.0",
|
|
522
|
+
* "documentationUrl": "https://www.unicode.org/versions/Unicode17.0.0/",
|
|
523
|
+
* "date": null,
|
|
524
|
+
* "url": "https://www.unicode.org/Public/17.0.0",
|
|
525
|
+
* "mappedUcdVersion": null,
|
|
526
|
+
* "type": "draft"
|
|
527
|
+
* }
|
|
528
|
+
* @example {
|
|
529
|
+
* "version": "16.0.0",
|
|
530
|
+
* "documentationUrl": "https://www.unicode.org/versions/Unicode16.0.0/",
|
|
531
|
+
* "date": "2024",
|
|
532
|
+
* "url": "https://www.unicode.org/Public/16.0.0",
|
|
533
|
+
* "mappedUcdVersion": null,
|
|
534
|
+
* "type": "stable"
|
|
535
|
+
* }
|
|
536
|
+
* @example {
|
|
537
|
+
* "version": "15.1.0",
|
|
538
|
+
* "documentationUrl": "https://www.unicode.org/versions/Unicode15.1.0/",
|
|
539
|
+
* "date": "2023",
|
|
540
|
+
* "url": "https://www.unicode.org/Public/15.1.0",
|
|
541
|
+
* "mappedUcdVersion": null,
|
|
542
|
+
* "type": "stable"
|
|
543
|
+
* }
|
|
544
|
+
*/
|
|
545
|
+
UnicodeVersion: {
|
|
546
|
+
/** @description The version of the Unicode standard. */version: string;
|
|
547
|
+
/**
|
|
548
|
+
* Format: uri
|
|
549
|
+
* @description The URL to the Unicode version documentation.
|
|
550
|
+
*/
|
|
551
|
+
documentationUrl: string; /** @description The year of the Unicode version. */
|
|
552
|
+
date: string | null;
|
|
553
|
+
/**
|
|
554
|
+
* Format: uri
|
|
555
|
+
* @description The URL to the Unicode Character Database (UCD) for this version.
|
|
556
|
+
*/
|
|
557
|
+
url: string; /** @description The corresponding UCD version mapping for this Unicode version. Null if same as version. */
|
|
558
|
+
mappedUcdVersion: string | null;
|
|
559
|
+
/**
|
|
560
|
+
* @description The status of the Unicode version. 'unsupported' means the version exists but is not yet supported by the API.
|
|
561
|
+
* @enum {string}
|
|
562
|
+
*/
|
|
563
|
+
type: "draft" | "stable" | "unsupported";
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* @description Detailed information about a Unicode version, including metadata and statistics.
|
|
567
|
+
* @example {
|
|
568
|
+
* "version": "16.0.0",
|
|
569
|
+
* "documentationUrl": "https://www.unicode.org/versions/Unicode16.0.0/",
|
|
570
|
+
* "date": "2024",
|
|
571
|
+
* "url": "https://www.unicode.org/Public/16.0.0",
|
|
572
|
+
* "mappedUcdVersion": null,
|
|
573
|
+
* "type": "stable",
|
|
574
|
+
* "statistics": {
|
|
575
|
+
* "totalCharacters": 149813,
|
|
576
|
+
* "newCharacters": 5185,
|
|
577
|
+
* "totalBlocks": 331,
|
|
578
|
+
* "newBlocks": 4,
|
|
579
|
+
* "totalScripts": 165,
|
|
580
|
+
* "newScripts": 2
|
|
581
|
+
* }
|
|
582
|
+
* }
|
|
583
|
+
*/
|
|
584
|
+
UnicodeVersionDetails: {
|
|
585
|
+
/** @description The version of the Unicode standard. */version: string;
|
|
586
|
+
/**
|
|
587
|
+
* Format: uri
|
|
588
|
+
* @description The URL to the Unicode version documentation.
|
|
589
|
+
*/
|
|
590
|
+
documentationUrl: string; /** @description The year of the Unicode version. */
|
|
591
|
+
date: string | null;
|
|
592
|
+
/**
|
|
593
|
+
* Format: uri
|
|
594
|
+
* @description The URL to the Unicode Character Database (UCD) for this version.
|
|
595
|
+
*/
|
|
596
|
+
url: string; /** @description The corresponding UCD version mapping for this Unicode version. Null if same as version. */
|
|
597
|
+
mappedUcdVersion: string | null;
|
|
598
|
+
/**
|
|
599
|
+
* @description The status of the Unicode version. 'unsupported' means the version exists but is not yet supported by the API.
|
|
600
|
+
* @enum {string}
|
|
601
|
+
*/
|
|
602
|
+
type: "draft" | "stable" | "unsupported";
|
|
603
|
+
/**
|
|
604
|
+
* @description Statistics about this Unicode version. May be null if statistics are not available.
|
|
605
|
+
* @default {
|
|
606
|
+
* "newBlocks": 0,
|
|
607
|
+
* "newCharacters": 0,
|
|
608
|
+
* "newScripts": 0,
|
|
609
|
+
* "totalBlocks": 0,
|
|
610
|
+
* "totalCharacters": 0,
|
|
611
|
+
* "totalScripts": 0
|
|
612
|
+
* }
|
|
613
|
+
*/
|
|
614
|
+
statistics: {
|
|
615
|
+
/** @description Total number of characters in this Unicode version. */totalCharacters: number; /** @description Number of new characters added in this version. */
|
|
616
|
+
newCharacters: number; /** @description Total number of blocks in this Unicode version. */
|
|
617
|
+
totalBlocks: number; /** @description Number of new blocks added in this version. */
|
|
618
|
+
newBlocks: number; /** @description Total number of scripts in this Unicode version. */
|
|
619
|
+
totalScripts: number; /** @description Number of new scripts added in this version. */
|
|
620
|
+
newScripts: number;
|
|
621
|
+
};
|
|
622
|
+
}; /** @description A recursive file tree structure rooted at an array of entries. */
|
|
623
|
+
UnicodeFileTree: components["schemas"]["UnicodeFileTreeNode"][]; /** @description A recursive file tree node; directories include children, files do not. */
|
|
624
|
+
UnicodeFileTreeNode: components["schemas"]["UnicodeFileTreeDirectory"] | components["schemas"]["UnicodeFileTreeFile"]; /** @description A directory node in the Unicode file tree, containing child nodes. */
|
|
625
|
+
UnicodeFileTreeDirectory: {
|
|
626
|
+
name: string;
|
|
627
|
+
path: string;
|
|
628
|
+
lastModified: number | null; /** @enum {string} */
|
|
629
|
+
type: "directory";
|
|
630
|
+
children: components["schemas"]["UnicodeFileTreeNode"][];
|
|
631
|
+
}; /** @description A file node in the Unicode file tree. */
|
|
632
|
+
UnicodeFileTreeFile: {
|
|
633
|
+
name: string;
|
|
634
|
+
path: string;
|
|
635
|
+
lastModified: number | null; /** @enum {string} */
|
|
636
|
+
type: "file";
|
|
637
|
+
}; /** @description An array of file entries, each representing either a file or a directory. */
|
|
638
|
+
FileEntryList: ({
|
|
639
|
+
name: string;
|
|
640
|
+
path: string;
|
|
641
|
+
lastModified: number | null; /** @enum {string} */
|
|
642
|
+
type: "directory";
|
|
643
|
+
} | {
|
|
644
|
+
name: string;
|
|
645
|
+
path: string;
|
|
646
|
+
lastModified: number | null; /** @enum {string} */
|
|
647
|
+
type: "file";
|
|
648
|
+
})[];
|
|
649
|
+
/**
|
|
650
|
+
* @description Configuration schema for the .well-known/ucd-config.json endpoint.
|
|
651
|
+
*
|
|
652
|
+
* This configuration provides clients with the necessary information to interact with the UCD API server, including endpoint paths and optional metadata about the server itself.
|
|
653
|
+
*
|
|
654
|
+
* The `manifest` endpoint is deprecated. Use the per-version endpoint `/.well-known/ucd-store/{version}.json` instead for better performance and caching.
|
|
655
|
+
*/
|
|
656
|
+
UCDWellKnownConfig: {
|
|
657
|
+
/** @default 1.0 */version: string;
|
|
658
|
+
endpoints: {
|
|
659
|
+
files: string;
|
|
660
|
+
manifest: string;
|
|
661
|
+
versions: string;
|
|
662
|
+
}; /** @default [] */
|
|
663
|
+
versions: string[];
|
|
664
|
+
};
|
|
665
|
+
/**
|
|
666
|
+
* @description Response schema for per-version manifest endpoint.
|
|
667
|
+
* Matches the schema from /.well-known/ucd-store/{version}.json
|
|
668
|
+
*/
|
|
669
|
+
UCDStoreVersionManifest: {
|
|
670
|
+
/** @description List of expected files for this version with their paths */expectedFiles: components["schemas"]["ExpectedFile"][];
|
|
671
|
+
}; /** @description A file expected to be present in a UCD version */
|
|
672
|
+
ExpectedFile: {
|
|
673
|
+
/** @description Filename only */name: string; /** @description Path relative to /api/v1/files endpoint (includes /ucd/ for versions >= 4.1.0) */
|
|
674
|
+
path: string; /** @description Path for store subdomain (without /ucd/ prefix) */
|
|
675
|
+
storePath: string;
|
|
676
|
+
};
|
|
677
|
+
};
|
|
678
|
+
responses: {
|
|
679
|
+
/** @description Bad request error */BadRequestError: {
|
|
680
|
+
headers: {
|
|
681
|
+
[name: string]: unknown;
|
|
682
|
+
};
|
|
683
|
+
content: {
|
|
684
|
+
"application/json": components["schemas"]["ApiError"];
|
|
685
|
+
};
|
|
686
|
+
}; /** @description Resource not found */
|
|
687
|
+
NotFoundError: {
|
|
688
|
+
headers: {
|
|
689
|
+
[name: string]: unknown;
|
|
690
|
+
};
|
|
691
|
+
content: {
|
|
692
|
+
"application/json": components["schemas"]["ApiError"];
|
|
693
|
+
};
|
|
694
|
+
}; /** @description Rate limit exceeded */
|
|
695
|
+
TooManyRequestsError: {
|
|
696
|
+
headers: {
|
|
697
|
+
[name: string]: unknown;
|
|
698
|
+
};
|
|
699
|
+
content: {
|
|
700
|
+
"application/json": components["schemas"]["ApiError"];
|
|
701
|
+
};
|
|
702
|
+
}; /** @description Internal server error */
|
|
703
|
+
InternalServerError: {
|
|
704
|
+
headers: {
|
|
705
|
+
[name: string]: unknown;
|
|
706
|
+
};
|
|
707
|
+
content: {
|
|
708
|
+
"application/json": components["schemas"]["ApiError"];
|
|
709
|
+
};
|
|
710
|
+
}; /** @description Bad gateway - upstream service failed */
|
|
711
|
+
BadGatewayError: {
|
|
712
|
+
headers: {
|
|
713
|
+
[name: string]: unknown;
|
|
714
|
+
};
|
|
715
|
+
content: {
|
|
716
|
+
"application/json": components["schemas"]["ApiError"];
|
|
717
|
+
};
|
|
718
|
+
};
|
|
719
|
+
};
|
|
720
|
+
parameters: never;
|
|
721
|
+
requestBodies: never;
|
|
722
|
+
headers: never;
|
|
723
|
+
pathItems: never;
|
|
724
|
+
}
|
|
725
|
+
//#endregion
|
|
726
|
+
//#region src/resources/files.d.ts
|
|
727
|
+
type FileResponse = paths["/api/v1/files/{wildcard}"]["get"]["responses"][200]["content"];
|
|
728
|
+
interface FilesResource {
|
|
729
|
+
/**
|
|
730
|
+
* Get a file or directory listing from the Unicode data
|
|
731
|
+
*
|
|
732
|
+
* @param {string} path - The path to the file (e.g., "16.0.0/ucd/UnicodeData.txt")
|
|
733
|
+
* @returns {Promise<SafeFetchResponse<FileResponse[keyof FileResponse]>>} File content as text, JSON, or other format depending on the file type
|
|
734
|
+
*/
|
|
735
|
+
get: (path: string) => Promise<SafeFetchResponse<FileResponse[keyof FileResponse]>>;
|
|
736
|
+
}
|
|
737
|
+
//#endregion
|
|
738
|
+
//#region src/resources/manifest.d.ts
|
|
739
|
+
interface ManifestResource {
|
|
740
|
+
/**
|
|
741
|
+
* Get the manifest for a specific Unicode version
|
|
742
|
+
* @param {string} version - The Unicode version (e.g., "16.0.0")
|
|
743
|
+
* @returns {Promise<SafeFetchResponse<UCDStoreVersionManifest>>} The manifest containing expectedFiles
|
|
744
|
+
*/
|
|
745
|
+
get: (version: string) => Promise<SafeFetchResponse<UCDStoreVersionManifest>>;
|
|
746
|
+
}
|
|
747
|
+
//#endregion
|
|
748
|
+
//#region src/resources/versions.d.ts
|
|
749
|
+
type VersionsListResponse = paths["/api/v1/versions"]["get"]["responses"][200]["content"]["application/json"];
|
|
750
|
+
type FileTreeResponse = paths["/api/v1/versions/{version}/file-tree"]["get"]["responses"][200]["content"]["application/json"];
|
|
751
|
+
interface VersionsResource {
|
|
752
|
+
/**
|
|
753
|
+
* List all available Unicode versions
|
|
754
|
+
* @return {Promise<SafeFetchResponse<VersionsListResponse>>} An array of available Unicode version strings
|
|
755
|
+
*/
|
|
756
|
+
list: () => Promise<SafeFetchResponse<VersionsListResponse>>;
|
|
757
|
+
/**
|
|
758
|
+
* Get the file tree for a specific Unicode version
|
|
759
|
+
*
|
|
760
|
+
* @param {string} version - The Unicode version (e.g., "16.0.0")
|
|
761
|
+
* @returns {Promise<SafeFetchResponse<FileTreeResponse>>} The file tree structure for the specified version
|
|
762
|
+
*/
|
|
763
|
+
getFileTree: (version: string) => Promise<SafeFetchResponse<FileTreeResponse>>;
|
|
764
|
+
}
|
|
765
|
+
//#endregion
|
|
766
|
+
//#region src/index.d.ts
|
|
767
|
+
interface UCDClient {
|
|
768
|
+
/**
|
|
769
|
+
* Access file-related endpoints
|
|
770
|
+
*/
|
|
771
|
+
files: FilesResource;
|
|
772
|
+
/**
|
|
773
|
+
* Access version-related endpoints
|
|
774
|
+
*/
|
|
775
|
+
versions: VersionsResource;
|
|
776
|
+
/**
|
|
777
|
+
* Access configuration endpoints
|
|
778
|
+
*/
|
|
779
|
+
config: ConfigResource;
|
|
780
|
+
/**
|
|
781
|
+
* Access manifest endpoints
|
|
782
|
+
*/
|
|
783
|
+
manifest: ManifestResource;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Creates a UCD client that automatically discovers endpoint paths
|
|
787
|
+
* via the well-known configuration endpoint
|
|
788
|
+
*
|
|
789
|
+
* @param {string} baseUrl - The base URL of the UCD API server (e.g., "https://api.ucdjs.dev")
|
|
790
|
+
* @returns {Promise<UCDClient>} A configured UCD client with resource namespaces
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```ts
|
|
794
|
+
* const client = await createUCDClient('https://api.ucdjs.dev');
|
|
795
|
+
*
|
|
796
|
+
* // List all versions
|
|
797
|
+
* const versions = await client.versions.list();
|
|
798
|
+
*
|
|
799
|
+
* // Get a file
|
|
800
|
+
* const file = await client.files.get('16.0.0/ucd/UnicodeData.txt');
|
|
801
|
+
*
|
|
802
|
+
* // Get configuration
|
|
803
|
+
* const config = await client.config.get();
|
|
804
|
+
*
|
|
805
|
+
* // Get manifest for a version
|
|
806
|
+
* const manifest = await client.manifest.get('16.0.0');
|
|
807
|
+
* ```
|
|
808
|
+
*/
|
|
809
|
+
declare function createUCDClient(baseUrl: string): Promise<UCDClient>;
|
|
810
|
+
/**
|
|
811
|
+
* Creates a UCD client with a synchronous configuration
|
|
812
|
+
*
|
|
813
|
+
* @param {string} baseUrl - The base URL of the UCD API server (e.g., "https://api.ucdjs.dev")
|
|
814
|
+
* @param {UCDWellKnownConfig} endpointConfig - The well-known configuration for endpoints
|
|
815
|
+
* @returns {UCDClient} A configured UCD client with resource namespaces
|
|
816
|
+
*
|
|
817
|
+
* @example
|
|
818
|
+
* ```ts
|
|
819
|
+
* const client = createUCDClientWithConfig('https://api.ucdjs.dev', {
|
|
820
|
+
* version: '1.0',
|
|
821
|
+
* endpoints: {
|
|
822
|
+
* files: '/files',
|
|
823
|
+
* manifest: '/files/.ucd-store.json',
|
|
824
|
+
* versions: '/versions',
|
|
825
|
+
* },
|
|
826
|
+
* });
|
|
827
|
+
*
|
|
828
|
+
* // List all versions
|
|
829
|
+
* const versions = await client.versions.list();
|
|
830
|
+
*
|
|
831
|
+
* // Get a file
|
|
832
|
+
* const file = await client.files.get('16.0.0/ucd/UnicodeData.txt');
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
declare function createUCDClientWithConfig(baseUrl: string, endpointConfig: UCDWellKnownConfig): UCDClient;
|
|
836
|
+
//#endregion
|
|
837
|
+
export { UCDClient, createUCDClient, createUCDClientWithConfig };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { customFetch, discoverEndpointsFromConfig, tryOr } from "@ucdjs-internal/shared";
|
|
2
|
+
import { UCDStoreVersionManifestSchema, UCDWellKnownConfigSchema, UnicodeFileTreeSchema, UnicodeVersionListSchema } from "@ucdjs/schemas";
|
|
3
|
+
import { PathTraversalError, resolveSafePath } from "@ucdjs/path-utils";
|
|
4
|
+
|
|
5
|
+
//#region src/resources/config.ts
|
|
6
|
+
function createConfigResource(options) {
|
|
7
|
+
const { baseUrl } = options;
|
|
8
|
+
return { async get() {
|
|
9
|
+
const url = new URL("/.well-known/ucd-config.json", baseUrl);
|
|
10
|
+
return customFetch.safe(url.toString(), {
|
|
11
|
+
parseAs: "json",
|
|
12
|
+
schema: UCDWellKnownConfigSchema
|
|
13
|
+
});
|
|
14
|
+
} };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/resources/files.ts
|
|
19
|
+
function createFilesResource(options) {
|
|
20
|
+
const { baseUrl, endpoints } = options;
|
|
21
|
+
return { async get(path) {
|
|
22
|
+
const resolvedPathOrError = tryOr({
|
|
23
|
+
try: () => resolveSafePath(endpoints.files, path),
|
|
24
|
+
err: (err) => {
|
|
25
|
+
if (err instanceof PathTraversalError) return {
|
|
26
|
+
data: null,
|
|
27
|
+
error: err
|
|
28
|
+
};
|
|
29
|
+
throw err;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (typeof resolvedPathOrError !== "string") return resolvedPathOrError;
|
|
33
|
+
const url = new URL(resolvedPathOrError, baseUrl);
|
|
34
|
+
return customFetch.safe(url.toString());
|
|
35
|
+
} };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/resources/manifest.ts
|
|
40
|
+
/**
|
|
41
|
+
* Regex pattern for validating Unicode version format (X.Y.Z)
|
|
42
|
+
* Compiled once at module load for better performance
|
|
43
|
+
*/
|
|
44
|
+
const VERSION_FORMAT_REGEX = /^\d+\.\d+\.\d+$/;
|
|
45
|
+
function createManifestResource(options) {
|
|
46
|
+
const { baseUrl } = options;
|
|
47
|
+
return { async get(version) {
|
|
48
|
+
if (!VERSION_FORMAT_REGEX.test(version)) return {
|
|
49
|
+
error: /* @__PURE__ */ new Error(`Invalid version format: ${version}. Expected X.Y.Z format.`),
|
|
50
|
+
data: null
|
|
51
|
+
};
|
|
52
|
+
const url = new URL(`/.well-known/ucd-store/${version}.json`, baseUrl);
|
|
53
|
+
return customFetch.safe(url.toString(), {
|
|
54
|
+
parseAs: "json",
|
|
55
|
+
schema: UCDStoreVersionManifestSchema
|
|
56
|
+
});
|
|
57
|
+
} };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/resources/versions.ts
|
|
62
|
+
function createVersionsResource(options) {
|
|
63
|
+
const { baseUrl, endpoints } = options;
|
|
64
|
+
return {
|
|
65
|
+
async list() {
|
|
66
|
+
const url = new URL(endpoints.versions, baseUrl);
|
|
67
|
+
return customFetch.safe(url.toString(), {
|
|
68
|
+
parseAs: "json",
|
|
69
|
+
schema: UnicodeVersionListSchema
|
|
70
|
+
});
|
|
71
|
+
},
|
|
72
|
+
async getFileTree(version) {
|
|
73
|
+
const url = new URL(`${endpoints.versions}/${version}/file-tree`, baseUrl);
|
|
74
|
+
return customFetch.safe(url.toString(), {
|
|
75
|
+
parseAs: "json",
|
|
76
|
+
schema: UnicodeFileTreeSchema
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/index.ts
|
|
84
|
+
function createResources(baseUrl, endpointConfig) {
|
|
85
|
+
return {
|
|
86
|
+
files: createFilesResource({
|
|
87
|
+
baseUrl,
|
|
88
|
+
endpoints: endpointConfig
|
|
89
|
+
}),
|
|
90
|
+
versions: createVersionsResource({
|
|
91
|
+
baseUrl,
|
|
92
|
+
endpoints: endpointConfig
|
|
93
|
+
}),
|
|
94
|
+
config: createConfigResource({ baseUrl }),
|
|
95
|
+
manifest: createManifestResource({ baseUrl })
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Creates a UCD client that automatically discovers endpoint paths
|
|
100
|
+
* via the well-known configuration endpoint
|
|
101
|
+
*
|
|
102
|
+
* @param {string} baseUrl - The base URL of the UCD API server (e.g., "https://api.ucdjs.dev")
|
|
103
|
+
* @returns {Promise<UCDClient>} A configured UCD client with resource namespaces
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const client = await createUCDClient('https://api.ucdjs.dev');
|
|
108
|
+
*
|
|
109
|
+
* // List all versions
|
|
110
|
+
* const versions = await client.versions.list();
|
|
111
|
+
*
|
|
112
|
+
* // Get a file
|
|
113
|
+
* const file = await client.files.get('16.0.0/ucd/UnicodeData.txt');
|
|
114
|
+
*
|
|
115
|
+
* // Get configuration
|
|
116
|
+
* const config = await client.config.get();
|
|
117
|
+
*
|
|
118
|
+
* // Get manifest for a version
|
|
119
|
+
* const manifest = await client.manifest.get('16.0.0');
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
async function createUCDClient(baseUrl) {
|
|
123
|
+
return createResources(baseUrl, (await discoverEndpointsFromConfig(baseUrl)).endpoints);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Creates a UCD client with a synchronous configuration
|
|
127
|
+
*
|
|
128
|
+
* @param {string} baseUrl - The base URL of the UCD API server (e.g., "https://api.ucdjs.dev")
|
|
129
|
+
* @param {UCDWellKnownConfig} endpointConfig - The well-known configuration for endpoints
|
|
130
|
+
* @returns {UCDClient} A configured UCD client with resource namespaces
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* const client = createUCDClientWithConfig('https://api.ucdjs.dev', {
|
|
135
|
+
* version: '1.0',
|
|
136
|
+
* endpoints: {
|
|
137
|
+
* files: '/files',
|
|
138
|
+
* manifest: '/files/.ucd-store.json',
|
|
139
|
+
* versions: '/versions',
|
|
140
|
+
* },
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* // List all versions
|
|
144
|
+
* const versions = await client.versions.list();
|
|
145
|
+
*
|
|
146
|
+
* // Get a file
|
|
147
|
+
* const file = await client.files.get('16.0.0/ucd/UnicodeData.txt');
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
function createUCDClientWithConfig(baseUrl, endpointConfig) {
|
|
151
|
+
return createResources(baseUrl, endpointConfig.endpoints);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
//#endregion
|
|
155
|
+
export { createUCDClient, createUCDClientWithConfig };
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ucdjs/client",
|
|
3
|
+
"version": "0.1.1-beta.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Lucas Nørgård",
|
|
7
|
+
"email": "lucasnrgaard@gmail.com",
|
|
8
|
+
"url": "https://luxass.dev"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://github.com/ucdjs/ucd",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/ucdjs/ucd.git",
|
|
15
|
+
"directory": "packages/client"
|
|
16
|
+
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/ucdjs/ucd/issues"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": "./dist/index.mjs",
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"types": "./dist/index.d.mts",
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
],
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22.18"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@ucdjs/schemas": "0.1.1-beta.1",
|
|
33
|
+
"@ucdjs/path-utils": "0.1.1-beta.1",
|
|
34
|
+
"@ucdjs-internal/shared": "0.1.1-beta.1",
|
|
35
|
+
"@ucdjs/env": "0.1.1-beta.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@luxass/eslint-config": "7.2.0",
|
|
39
|
+
"@types/picomatch": "4.0.2",
|
|
40
|
+
"eslint": "10.0.0",
|
|
41
|
+
"openapi-typescript": "7.13.0",
|
|
42
|
+
"publint": "0.3.17",
|
|
43
|
+
"tsdown": "0.20.3",
|
|
44
|
+
"tsx": "4.21.0",
|
|
45
|
+
"typescript": "5.9.3",
|
|
46
|
+
"vitest-testdirs": "4.4.2",
|
|
47
|
+
"@ucdjs-tooling/tsdown-config": "1.0.0",
|
|
48
|
+
"@ucdjs-tooling/tsconfig": "1.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsdown --tsconfig=./tsconfig.build.json",
|
|
55
|
+
"dev": "tsdown --watch",
|
|
56
|
+
"clean": "git clean -xdf dist node_modules",
|
|
57
|
+
"lint": "eslint .",
|
|
58
|
+
"typecheck": "tsc --noEmit -p tsconfig.build.json",
|
|
59
|
+
"generate:client": "openapi-typescript ../../ucd-generated/api/openapi.json -o ./src/.generated/api.d.ts",
|
|
60
|
+
"generate:client:local": "openapi-typescript http://localhost:8787/openapi.json -o ./src/.generated/api.d.ts"
|
|
61
|
+
}
|
|
62
|
+
}
|