@shayc/open-board-format 1.3.3 → 1.3.4
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/CHANGELOG.md +6 -0
- package/README.md +35 -53
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@shayc/open-board-format)
|
|
4
4
|
[](https://github.com/shayc/open-board-format/actions/workflows/ci.yml)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
A TypeScript/JavaScript library for parsing, validating, and creating [Open Board Format](https://www.openboardformat.org/) (OBF) communication boards (`.obf`) and archives (`.obz`) for AAC applications.
|
|
7
7
|
|
|
8
|
-
Add
|
|
9
|
-
|
|
10
|
-
The package handles format detection, validation, archive creation, and schema access so applications can focus on board experiences instead of file handling.
|
|
8
|
+
Add Open Board Format import and export without implementing schemas, manifests, or archive handling yourself.
|
|
11
9
|
|
|
12
10
|
## Features
|
|
13
11
|
|
|
@@ -15,7 +13,6 @@ The package handles format detection, validation, archive creation, and schema a
|
|
|
15
13
|
- Create OBZ archives with generated manifests and validated media resources.
|
|
16
14
|
- Use exported [Zod](https://zod.dev/) schemas and inferred TypeScript types.
|
|
17
15
|
- Preserve unknown fields, including vendor extensions.
|
|
18
|
-
- Run as pure ESM in Node.js 22+ and modern browsers.
|
|
19
16
|
|
|
20
17
|
It focuses on board data and archives only. It does not render boards, play media, fetch remote resources, or resolve navigation and media references.
|
|
21
18
|
|
|
@@ -27,20 +24,21 @@ npm install @shayc/open-board-format zod
|
|
|
27
24
|
|
|
28
25
|
`zod ^4.4.3` is a required peer dependency.
|
|
29
26
|
|
|
27
|
+
Works in browsers and Node.js. Browser `File` uploads and Node.js `Buffer` values use the same loading API. Pure ESM; CommonJS is not supported.
|
|
28
|
+
|
|
30
29
|
## Quick start
|
|
31
30
|
|
|
32
31
|
```ts
|
|
33
32
|
import { loadBoard } from "@shayc/open-board-format";
|
|
34
|
-
import type { BinaryInput, OBFBoard } from "@shayc/open-board-format";
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
const loaded = await loadBoard(input);
|
|
38
|
-
|
|
39
|
-
return loaded.format === "obf" ? loaded.board : loaded.archive.rootBoard;
|
|
40
|
-
}
|
|
34
|
+
const loaded = await loadBoard(input);
|
|
41
35
|
```
|
|
42
36
|
|
|
43
|
-
`
|
|
37
|
+
`loadBoard` accepts a `File`, `Blob`, `ArrayBuffer`, or `ArrayBufferView` and detects the format from the bytes, not the filename. It returns a TypeScript discriminated union: OBF files contain a board directly, while OBZ files contain an archive whose `rootBoard` is the entry point.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const board = loaded.format === "obf" ? loaded.board : loaded.archive.rootBoard;
|
|
41
|
+
```
|
|
44
42
|
|
|
45
43
|
## Formats
|
|
46
44
|
|
|
@@ -92,32 +90,16 @@ For untrusted archives, configure [extraction limits](#extraction-limits).
|
|
|
92
90
|
|
|
93
91
|
### Create an OBZ archive
|
|
94
92
|
|
|
95
|
-
|
|
93
|
+
Given an existing board and its media resources:
|
|
96
94
|
|
|
97
95
|
```ts
|
|
98
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
99
96
|
import { createOBZ } from "@shayc/open-board-format";
|
|
100
|
-
import type { OBFBoard } from "@shayc/open-board-format";
|
|
101
|
-
|
|
102
|
-
const board: OBFBoard = {
|
|
103
|
-
format: "open-board-0.1",
|
|
104
|
-
id: "board-1",
|
|
105
|
-
buttons: [{ id: "btn-1", label: "Hello", image_id: "img-1" }],
|
|
106
|
-
grid: { rows: 1, columns: 1, order: [["btn-1"]] },
|
|
107
|
-
images: [{ id: "img-1", path: "images/hello.png" }],
|
|
108
|
-
};
|
|
109
97
|
|
|
110
|
-
const
|
|
111
|
-
const resources = new Map([["images/hello.png", pngBytes]]);
|
|
112
|
-
|
|
113
|
-
const blob = await createOBZ([board], "board-1", resources);
|
|
114
|
-
await writeFile("my-board.obz", new Uint8Array(await blob.arrayBuffer()));
|
|
98
|
+
const blob = await createOBZ([existingBoard], existingBoard.id, resources);
|
|
115
99
|
```
|
|
116
100
|
|
|
117
101
|
`createOBZ` generates the manifest automatically, writes boards to `boards/<encoded-id>.obf`, and uses `rootBoardId` as the archive's entry board.
|
|
118
102
|
|
|
119
|
-
Before writing the archive, it checks board IDs, the root board, generated paths, media-path conflicts, and declared media resources. It does not resolve `load_board`, `image_id`, or `sound_id` references.
|
|
120
|
-
|
|
121
103
|
### Validate a board
|
|
122
104
|
|
|
123
105
|
```ts
|
|
@@ -129,7 +111,7 @@ export const validateBoard = (value: unknown) =>
|
|
|
129
111
|
|
|
130
112
|
Every public OBF data model has a matching Zod schema export with a `Schema` suffix. The schemas can also be composed with Zod APIs such as `.extend()` and `.pick()`.
|
|
131
113
|
|
|
132
|
-
## Validation
|
|
114
|
+
## Validation details
|
|
133
115
|
|
|
134
116
|
Validation returns a parsed copy of the input. Known fields may be normalized during parsing:
|
|
135
117
|
|
|
@@ -158,7 +140,7 @@ Add application-specific checks after parsing when those guarantees matter.
|
|
|
158
140
|
|
|
159
141
|
## API reference
|
|
160
142
|
|
|
161
|
-
###
|
|
143
|
+
### High-level API
|
|
162
144
|
|
|
163
145
|
#### Board data
|
|
164
146
|
|
|
@@ -179,13 +161,7 @@ Add application-specific checks after parsing when those guarantees matter.
|
|
|
179
161
|
| `createOBZ(boards, rootBoardId, resources?)` | `Promise<Blob>` | Validate and package boards and resources with a generated manifest |
|
|
180
162
|
| `parseManifest(json)` | `OBFManifest` | Parse and validate manifest JSON |
|
|
181
163
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
| Function | Returns | Behavior |
|
|
185
|
-
| ------------------------- | ---------------------------------- | -------------------------------------------------------- |
|
|
186
|
-
| `isZip(buffer)` | `boolean` | Check whether an `ArrayBuffer` has a ZIP signature |
|
|
187
|
-
| `zip(entries)` | `Promise<Uint8Array>` | Compress a map of paths to `Uint8Array` or `ArrayBuffer` |
|
|
188
|
-
| `unzip(buffer, options?)` | `Promise<Map<string, Uint8Array>>` | Extract an `ArrayBuffer` and omit directory markers |
|
|
164
|
+
Before writing an archive, `createOBZ` checks board IDs, the root board, generated paths, media-path conflicts, and declared media resources. It does not resolve `load_board`, `image_id`, or `sound_id` references.
|
|
189
165
|
|
|
190
166
|
### Types and schemas
|
|
191
167
|
|
|
@@ -222,22 +198,15 @@ Branch on `error.info.code`, not `error.message`.
|
|
|
222
198
|
|
|
223
199
|
```ts
|
|
224
200
|
import { loadBoard, OBFError } from "@shayc/open-board-format";
|
|
225
|
-
import type { BinaryInput } from "@shayc/open-board-format";
|
|
226
|
-
|
|
227
|
-
export async function openBoard(input: BinaryInput) {
|
|
228
|
-
try {
|
|
229
|
-
return await loadBoard(input);
|
|
230
|
-
} catch (error) {
|
|
231
|
-
if (!(error instanceof OBFError)) throw error;
|
|
232
201
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
throw error;
|
|
202
|
+
try {
|
|
203
|
+
await loadBoard(file);
|
|
204
|
+
} catch (error) {
|
|
205
|
+
if (error instanceof OBFError) {
|
|
206
|
+
console.error(error.info.code);
|
|
240
207
|
}
|
|
208
|
+
|
|
209
|
+
throw error;
|
|
241
210
|
}
|
|
242
211
|
```
|
|
243
212
|
|
|
@@ -271,6 +240,19 @@ Validation failures expose the underlying `ZodError` as `error.cause` and provid
|
|
|
271
240
|
|
|
272
241
|
Direct schema `.parse()` calls throw `ZodError` rather than `OBFError`.
|
|
273
242
|
|
|
243
|
+
<details>
|
|
244
|
+
<summary><strong>Low-level ZIP utilities</strong></summary>
|
|
245
|
+
|
|
246
|
+
The following exports are available for advanced archive workflows:
|
|
247
|
+
|
|
248
|
+
| Function | Returns | Behavior |
|
|
249
|
+
| ------------------------- | ---------------------------------- | -------------------------------------------------------- |
|
|
250
|
+
| `isZip(buffer)` | `boolean` | Check whether an `ArrayBuffer` has a ZIP signature |
|
|
251
|
+
| `zip(entries)` | `Promise<Uint8Array>` | Compress a map of paths to `Uint8Array` or `ArrayBuffer` |
|
|
252
|
+
| `unzip(buffer, options?)` | `Promise<Map<string, Uint8Array>>` | Extract an `ArrayBuffer` and omit directory markers |
|
|
253
|
+
|
|
254
|
+
</details>
|
|
255
|
+
|
|
274
256
|
## Security
|
|
275
257
|
|
|
276
258
|
Treat OBZ archives and their contents as untrusted input.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shayc/open-board-format",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "Parse, validate, and create Open Board Format (.obf/.obz) files — the open standard for Augmentative and Alternative Communication (AAC) boards. TypeScript, browser and Node.js.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Shay Cojocaru <shayc@outlook.com>",
|