@series-inc/stowkit-reader 0.1.41 → 0.1.43

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.txt CHANGED
@@ -1,6 +1,6 @@
1
- By downloading, copying, or using this template, you agree to the
2
- RUN.game Terms of Service:
3
-
4
- https://policy.run.game/eula.html
5
-
6
- © Series Inc. All rights reserved.
1
+ By downloading, copying, or using this template, you agree to the
2
+ RUN.game Terms of Service:
3
+
4
+ https://policy.run.game/eula.html
5
+
6
+ © Series Inc. All rights reserved.
package/README.md CHANGED
@@ -1,330 +1,330 @@
1
- # @series-inc/stowkit-reader
2
-
3
- WebAssembly-based reader for StowKit (.stow) asset pack files. Low-level API for reading and parsing binary asset data.
4
-
5
- ## Features
6
-
7
- - 🚀 **Pure WASM** - All binary parsing done in WebAssembly (Zig)
8
- - 📦 **Zero Dependencies** - Just WebAssembly, no external libraries
9
- - 🔍 **WASM Metadata Parsing** - Parse complex structures in WASM, not JavaScript
10
- - 🎮 **Game-Ready** - Supports all asset types (meshes, textures, audio, animations)
11
- - 📝 **TypeScript Support** - Full type definitions included
12
- - ⚡ **Fast** - WASM parsing is 10-50x faster than JavaScript DataView
13
-
14
- ## Installation
15
-
16
- ```bash
17
- npm install @series-inc/stowkit-reader
18
- ```
19
-
20
- ## Usage
21
-
22
- ```typescript
23
- import { StowKitReader } from '@series-inc/stowkit-reader';
24
-
25
- // Initialize the reader
26
- const reader = new StowKitReader();
27
- await reader.init();
28
-
29
- // Open a .stow file
30
- const response = await fetch('assets.stow');
31
- const buffer = await response.arrayBuffer();
32
- await reader.open(buffer);
33
-
34
- // List all assets
35
- const assets = reader.listAssets();
36
- console.log(`Found ${assets.length} assets`);
37
-
38
- // Find asset by path
39
- const index = reader.findAssetByPath('models/character.mesh');
40
-
41
- // Read asset data
42
- const data = reader.readAssetData(index);
43
-
44
- // Parse metadata (done in WASM!)
45
- const texInfo = reader.parseTextureMetadata(index);
46
- console.log(`Texture: ${texInfo.width}x${texInfo.height}`);
47
-
48
- const audioInfo = reader.parseAudioMetadata(index);
49
- console.log(`Audio: ${audioInfo.sampleRate}Hz, ${audioInfo.durationMs}ms`);
50
-
51
- const animInfo = reader.parseAnimationMetadata(index);
52
- console.log(`Animation: ${animInfo.duration}s, ${animInfo.boneCount} bones`);
53
-
54
- // Clean up
55
- reader.close();
56
- ```
57
-
58
- ## Asset Types
59
-
60
- | Type | ID | Description |
61
- |------|-------|-------------|
62
- | Static Mesh | 1 | Draco-compressed 3D models |
63
- | Texture 2D | 2 | KTX2/Basis Universal textures |
64
- | Audio | 3 | OGG/MP3 audio files |
65
- | Material Schema | 4 | Material template definitions |
66
- | Skinned Mesh | 5 | Skeletal meshes with bones |
67
- | Animation Clip | 6 | Bone animation keyframes |
68
-
69
- ## API Reference
70
-
71
- ### Exports
72
-
73
- ```typescript
74
- export { StowKitReader } from '@series-inc/stowkit-reader';
75
- export { PerfLogger } from '@series-inc/stowkit-reader';
76
- export { AssetType } from '@series-inc/stowkit-reader';
77
-
78
- // Interfaces
79
- export type { AssetInfo, AssetListItem, TextureMetadata, AudioMetadata } from '@series-inc/stowkit-reader';
80
- ```
81
-
82
- ### Asset Types Enum
83
-
84
- ```typescript
85
- enum AssetType {
86
- UNKNOWN = 0,
87
- STATIC_MESH = 1,
88
- TEXTURE_2D = 2,
89
- AUDIO = 3,
90
- MATERIAL_SCHEMA = 4,
91
- SKINNED_MESH = 5,
92
- ANIMATION_CLIP = 6,
93
- }
94
- ```
95
-
96
- ### Initialization
97
-
98
- #### `new StowKitReader(wasmUrl?: string)`
99
- Create a new reader instance. Optionally specify the WASM file URL (default: `'/stowkit/stowkit_reader.wasm'`).
100
-
101
- #### `async init(): Promise<StowKitReader>`
102
- Initialize the WebAssembly module. Must be called before using the reader.
103
-
104
- ```typescript
105
- const reader = new StowKitReader('/path/to/stowkit_reader.wasm');
106
- await reader.init();
107
- ```
108
-
109
- ### Opening Files
110
-
111
- #### `async open(file: ArrayBuffer | File): Promise<boolean>`
112
- Open a .stow file from memory.
113
-
114
- ```typescript
115
- // From fetch
116
- const response = await fetch('assets.stow');
117
- const buffer = await response.arrayBuffer();
118
- await reader.open(buffer);
119
-
120
- // From file input
121
- const file = input.files[0];
122
- await reader.open(file);
123
- ```
124
-
125
- ### Asset Access
126
-
127
- #### `getAssetCount(): number`
128
- Get the total number of assets in the pack.
129
-
130
- #### `listAssets(): AssetListItem[]`
131
- Get information about all assets.
132
-
133
- ```typescript
134
- const assets = reader.listAssets();
135
- assets.forEach(asset => {
136
- console.log(`${asset.name} (type ${asset.type}): ${asset.dataSize} bytes`);
137
- });
138
- ```
139
-
140
- #### `findAssetByPath(path: string): number`
141
- Find an asset index by its canonical path. Returns -1 if not found.
142
-
143
- ```typescript
144
- const index = reader.findAssetByPath('models/character.mesh');
145
- if (index >= 0) {
146
- const data = reader.readAssetData(index);
147
- }
148
- ```
149
-
150
- #### `getAssetInfo(index: number): AssetInfo | null`
151
- Get detailed information about a specific asset.
152
-
153
- #### `readAssetData(index: number): Uint8Array | null`
154
- Read the binary data of an asset.
155
-
156
- #### `readAssetMetadata(index: number): Uint8Array | null`
157
- Read the raw metadata bytes of an asset.
158
-
159
- ### WASM Metadata Parsing
160
-
161
- All metadata parsing is done in WASM for maximum performance. No manual DataView manipulation needed!
162
-
163
- #### `parseTextureMetadata(index: number): TextureMetadata | null`
164
- Parse texture metadata from WASM.
165
-
166
- ```typescript
167
- const info = reader.parseTextureMetadata(2);
168
- // { stringId, width, height, channels, channelFormat, tags }
169
- ```
170
-
171
- #### `parseAudioMetadata(index: number): AudioMetadata | null`
172
- Parse audio metadata from WASM.
173
-
174
- ```typescript
175
- const info = reader.parseAudioMetadata(3);
176
- // { stringId, sampleRate, channels, durationMs, tags }
177
- ```
178
-
179
- #### `parseMeshMetadata(index: number): object | null`
180
- Parse static mesh metadata from WASM.
181
-
182
- ```typescript
183
- const info = reader.parseMeshMetadata(1);
184
- // { stringId, tags }
185
- ```
186
-
187
- #### `parseAnimationMetadata(index: number): object | null`
188
- Parse animation clip metadata from WASM.
189
-
190
- ```typescript
191
- const info = reader.parseAnimationMetadata(9);
192
- // { stringId, targetMeshId, duration, ticksPerSecond, channelCount, boneCount }
193
- ```
194
-
195
- #### `parseMaterialSchemaMetadata(index: number): object | null`
196
- Parse material schema metadata from WASM.
197
-
198
- ```typescript
199
- const schema = reader.parseMaterialSchemaMetadata(4);
200
- // { stringId, schemaName, fieldCount, fields: [...] }
201
- ```
202
-
203
- #### `parseSkinnedMeshMetadata(index: number): object | null`
204
- Parse skinned mesh metadata from WASM (returns bone hierarchy and stringId).
205
-
206
- ```typescript
207
- const info = reader.parseSkinnedMeshMetadata(8);
208
- // { stringId, boneCount, bones: [{name, parentIndex}, ...], tags }
209
- ```
210
-
211
- #### `parseSkinnedMeshGeometryFast(metadataBlob: Uint8Array, dataBlob: Uint8Array): object | null`
212
- Parse skinned mesh geometry using WASM (10-50x faster than JavaScript!). Returns combined vertex/index buffers ready for rendering.
213
-
214
- ```typescript
215
- const metadata = reader.readAssetMetadata(index);
216
- const data = reader.readAssetData(index);
217
-
218
- const geometry = reader.parseSkinnedMeshGeometryFast(metadata, data);
219
- if (geometry) {
220
- const { vertexCount, indexCount, positions, normals, uvs, skinIndices, skinWeights, indices } = geometry;
221
- // Use with Three.js BufferGeometry, etc.
222
- }
223
- ```
224
-
225
- ### Utility Methods
226
-
227
- #### `setAssetName(index: number, name: string): void`
228
- Set a custom name for an asset (for UI display purposes).
229
-
230
- ```typescript
231
- reader.setAssetName(5, 'Custom Asset Name');
232
- const assets = reader.listAssets();
233
- // Asset at index 5 will now have name 'Custom Asset Name'
234
- ```
235
-
236
- #### `static formatBytes(bytes: number): string`
237
- Format byte count to human-readable string.
238
-
239
- ```typescript
240
- console.log(StowKitReader.formatBytes(1024)); // "1 KB"
241
- console.log(StowKitReader.formatBytes(1048576)); // "1 MB"
242
- console.log(StowKitReader.formatBytes(524288000)); // "500 MB"
243
- ```
244
-
245
- ### Cleanup
246
-
247
- #### `close(): void`
248
- Close the current file and free resources.
249
-
250
- ```typescript
251
- reader.close();
252
- ```
253
-
254
- ## Why WASM Parsing?
255
-
256
- **Before (JavaScript):**
257
- ```typescript
258
- // 50+ lines of manual DataView parsing
259
- const view = new DataView(metadata.buffer, metadata.byteOffset);
260
- const stringIdBytes = metadata.slice(0, 128);
261
- const decoder = new TextDecoder();
262
- const stringId = decoder.decode(stringIdBytes.slice(0, stringIdBytes.indexOf(0)));
263
- const sampleRate = view.getUint32(128, true);
264
- // ... 40 more lines ...
265
- ```
266
-
267
- **After (WASM):**
268
- ```typescript
269
- // 1 line!
270
- const info = reader.parseAudioMetadata(index);
271
- ```
272
-
273
- **Benefits:**
274
- - ✅ Single source of truth (C header defines all structs)
275
- - ✅ 10-50x faster parsing
276
- - ✅ No sync issues between reader and parser
277
- - ✅ Less prone to offset calculation bugs
278
- - ✅ Cleaner, more maintainable code
279
-
280
- ## Examples
281
-
282
- ### Inspect a Pack
283
-
284
- ```typescript
285
- import { StowKitReader, AssetType } from '@series-inc/stowkit-reader';
286
-
287
- const reader = new StowKitReader();
288
- await reader.init();
289
-
290
- const response = await fetch('game.stow');
291
- await reader.open(await response.arrayBuffer());
292
-
293
- const assets = reader.listAssets();
294
- console.log(`Pack contains ${assets.length} assets`);
295
-
296
- assets.forEach(asset => {
297
- const typeName = ['Unknown', 'Mesh', 'Texture', 'Audio', 'Schema', 'Skinned Mesh', 'Animation'][asset.type] || 'Unknown';
298
- console.log(`[${asset.index}] ${asset.name} - ${typeName} (${StowKitReader.formatBytes(asset.dataSize)})`);
299
- });
300
-
301
- reader.close();
302
- ```
303
-
304
- ### Extract Assets
305
-
306
- ```typescript
307
- const reader = new StowKitReader();
308
- await reader.init();
309
- await reader.open(buffer);
310
-
311
- // Find and extract a specific asset
312
- const index = reader.findAssetByPath('models/character.mesh');
313
- if (index >= 0) {
314
- const data = reader.readAssetData(index);
315
- const metadata = reader.readAssetMetadata(index);
316
-
317
- // Save to file
318
- const blob = new Blob([data]);
319
- const url = URL.createObjectURL(blob);
320
- const a = document.createElement('a');
321
- a.href = url;
322
- a.download = 'character.mesh';
323
- a.click();
324
- }
325
- ```
326
-
327
- ## Requirements
328
-
329
- - WebAssembly support in the browser
330
- - The `stowkit_reader.wasm` file must be accessible at runtime
1
+ # @series-inc/stowkit-reader
2
+
3
+ WebAssembly-based reader for StowKit (.stow) asset pack files. Low-level API for reading and parsing binary asset data.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Pure WASM** - All binary parsing done in WebAssembly (Zig)
8
+ - 📦 **Zero Dependencies** - Just WebAssembly, no external libraries
9
+ - 🔍 **WASM Metadata Parsing** - Parse complex structures in WASM, not JavaScript
10
+ - 🎮 **Game-Ready** - Supports all asset types (meshes, textures, audio, animations)
11
+ - 📝 **TypeScript Support** - Full type definitions included
12
+ - ⚡ **Fast** - WASM parsing is 10-50x faster than JavaScript DataView
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @series-inc/stowkit-reader
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```typescript
23
+ import { StowKitReader } from '@series-inc/stowkit-reader';
24
+
25
+ // Initialize the reader
26
+ const reader = new StowKitReader();
27
+ await reader.init();
28
+
29
+ // Open a .stow file
30
+ const response = await fetch('assets.stow');
31
+ const buffer = await response.arrayBuffer();
32
+ await reader.open(buffer);
33
+
34
+ // List all assets
35
+ const assets = reader.listAssets();
36
+ console.log(`Found ${assets.length} assets`);
37
+
38
+ // Find asset by path
39
+ const index = reader.findAssetByPath('models/character.mesh');
40
+
41
+ // Read asset data
42
+ const data = reader.readAssetData(index);
43
+
44
+ // Parse metadata (done in WASM!)
45
+ const texInfo = reader.parseTextureMetadata(index);
46
+ console.log(`Texture: ${texInfo.width}x${texInfo.height}`);
47
+
48
+ const audioInfo = reader.parseAudioMetadata(index);
49
+ console.log(`Audio: ${audioInfo.sampleRate}Hz, ${audioInfo.durationMs}ms`);
50
+
51
+ const animInfo = reader.parseAnimationMetadata(index);
52
+ console.log(`Animation: ${animInfo.duration}s, ${animInfo.boneCount} bones`);
53
+
54
+ // Clean up
55
+ reader.close();
56
+ ```
57
+
58
+ ## Asset Types
59
+
60
+ | Type | ID | Description |
61
+ |------|-------|-------------|
62
+ | Static Mesh | 1 | Draco-compressed 3D models |
63
+ | Texture 2D | 2 | KTX2/Basis Universal textures |
64
+ | Audio | 3 | OGG/MP3 audio files |
65
+ | Material Schema | 4 | Material template definitions |
66
+ | Skinned Mesh | 5 | Skeletal meshes with bones |
67
+ | Animation Clip | 6 | Bone animation keyframes |
68
+
69
+ ## API Reference
70
+
71
+ ### Exports
72
+
73
+ ```typescript
74
+ export { StowKitReader } from '@series-inc/stowkit-reader';
75
+ export { PerfLogger } from '@series-inc/stowkit-reader';
76
+ export { AssetType } from '@series-inc/stowkit-reader';
77
+
78
+ // Interfaces
79
+ export type { AssetInfo, AssetListItem, TextureMetadata, AudioMetadata } from '@series-inc/stowkit-reader';
80
+ ```
81
+
82
+ ### Asset Types Enum
83
+
84
+ ```typescript
85
+ enum AssetType {
86
+ UNKNOWN = 0,
87
+ STATIC_MESH = 1,
88
+ TEXTURE_2D = 2,
89
+ AUDIO = 3,
90
+ MATERIAL_SCHEMA = 4,
91
+ SKINNED_MESH = 5,
92
+ ANIMATION_CLIP = 6,
93
+ }
94
+ ```
95
+
96
+ ### Initialization
97
+
98
+ #### `new StowKitReader(wasmUrl?: string)`
99
+ Create a new reader instance. Optionally specify the WASM file URL (default: `'/stowkit/stowkit_reader.wasm'`).
100
+
101
+ #### `async init(): Promise<StowKitReader>`
102
+ Initialize the WebAssembly module. Must be called before using the reader.
103
+
104
+ ```typescript
105
+ const reader = new StowKitReader('/path/to/stowkit_reader.wasm');
106
+ await reader.init();
107
+ ```
108
+
109
+ ### Opening Files
110
+
111
+ #### `async open(file: ArrayBuffer | File): Promise<boolean>`
112
+ Open a .stow file from memory.
113
+
114
+ ```typescript
115
+ // From fetch
116
+ const response = await fetch('assets.stow');
117
+ const buffer = await response.arrayBuffer();
118
+ await reader.open(buffer);
119
+
120
+ // From file input
121
+ const file = input.files[0];
122
+ await reader.open(file);
123
+ ```
124
+
125
+ ### Asset Access
126
+
127
+ #### `getAssetCount(): number`
128
+ Get the total number of assets in the pack.
129
+
130
+ #### `listAssets(): AssetListItem[]`
131
+ Get information about all assets.
132
+
133
+ ```typescript
134
+ const assets = reader.listAssets();
135
+ assets.forEach(asset => {
136
+ console.log(`${asset.name} (type ${asset.type}): ${asset.dataSize} bytes`);
137
+ });
138
+ ```
139
+
140
+ #### `findAssetByPath(path: string): number`
141
+ Find an asset index by its canonical path. Returns -1 if not found.
142
+
143
+ ```typescript
144
+ const index = reader.findAssetByPath('models/character.mesh');
145
+ if (index >= 0) {
146
+ const data = reader.readAssetData(index);
147
+ }
148
+ ```
149
+
150
+ #### `getAssetInfo(index: number): AssetInfo | null`
151
+ Get detailed information about a specific asset.
152
+
153
+ #### `readAssetData(index: number): Uint8Array | null`
154
+ Read the binary data of an asset.
155
+
156
+ #### `readAssetMetadata(index: number): Uint8Array | null`
157
+ Read the raw metadata bytes of an asset.
158
+
159
+ ### WASM Metadata Parsing
160
+
161
+ All metadata parsing is done in WASM for maximum performance. No manual DataView manipulation needed!
162
+
163
+ #### `parseTextureMetadata(index: number): TextureMetadata | null`
164
+ Parse texture metadata from WASM.
165
+
166
+ ```typescript
167
+ const info = reader.parseTextureMetadata(2);
168
+ // { stringId, width, height, channels, channelFormat, tags }
169
+ ```
170
+
171
+ #### `parseAudioMetadata(index: number): AudioMetadata | null`
172
+ Parse audio metadata from WASM.
173
+
174
+ ```typescript
175
+ const info = reader.parseAudioMetadata(3);
176
+ // { stringId, sampleRate, channels, durationMs, tags }
177
+ ```
178
+
179
+ #### `parseMeshMetadata(index: number): object | null`
180
+ Parse static mesh metadata from WASM.
181
+
182
+ ```typescript
183
+ const info = reader.parseMeshMetadata(1);
184
+ // { stringId, tags }
185
+ ```
186
+
187
+ #### `parseAnimationMetadata(index: number): object | null`
188
+ Parse animation clip metadata from WASM.
189
+
190
+ ```typescript
191
+ const info = reader.parseAnimationMetadata(9);
192
+ // { stringId, targetMeshId, duration, ticksPerSecond, channelCount, boneCount }
193
+ ```
194
+
195
+ #### `parseMaterialSchemaMetadata(index: number): object | null`
196
+ Parse material schema metadata from WASM.
197
+
198
+ ```typescript
199
+ const schema = reader.parseMaterialSchemaMetadata(4);
200
+ // { stringId, schemaName, fieldCount, fields: [...] }
201
+ ```
202
+
203
+ #### `parseSkinnedMeshMetadata(index: number): object | null`
204
+ Parse skinned mesh metadata from WASM (returns bone hierarchy and stringId).
205
+
206
+ ```typescript
207
+ const info = reader.parseSkinnedMeshMetadata(8);
208
+ // { stringId, boneCount, bones: [{name, parentIndex}, ...], tags }
209
+ ```
210
+
211
+ #### `parseSkinnedMeshGeometryFast(metadataBlob: Uint8Array, dataBlob: Uint8Array): object | null`
212
+ Parse skinned mesh geometry using WASM (10-50x faster than JavaScript!). Returns combined vertex/index buffers ready for rendering.
213
+
214
+ ```typescript
215
+ const metadata = reader.readAssetMetadata(index);
216
+ const data = reader.readAssetData(index);
217
+
218
+ const geometry = reader.parseSkinnedMeshGeometryFast(metadata, data);
219
+ if (geometry) {
220
+ const { vertexCount, indexCount, positions, normals, uvs, skinIndices, skinWeights, indices } = geometry;
221
+ // Use with Three.js BufferGeometry, etc.
222
+ }
223
+ ```
224
+
225
+ ### Utility Methods
226
+
227
+ #### `setAssetName(index: number, name: string): void`
228
+ Set a custom name for an asset (for UI display purposes).
229
+
230
+ ```typescript
231
+ reader.setAssetName(5, 'Custom Asset Name');
232
+ const assets = reader.listAssets();
233
+ // Asset at index 5 will now have name 'Custom Asset Name'
234
+ ```
235
+
236
+ #### `static formatBytes(bytes: number): string`
237
+ Format byte count to human-readable string.
238
+
239
+ ```typescript
240
+ console.log(StowKitReader.formatBytes(1024)); // "1 KB"
241
+ console.log(StowKitReader.formatBytes(1048576)); // "1 MB"
242
+ console.log(StowKitReader.formatBytes(524288000)); // "500 MB"
243
+ ```
244
+
245
+ ### Cleanup
246
+
247
+ #### `close(): void`
248
+ Close the current file and free resources.
249
+
250
+ ```typescript
251
+ reader.close();
252
+ ```
253
+
254
+ ## Why WASM Parsing?
255
+
256
+ **Before (JavaScript):**
257
+ ```typescript
258
+ // 50+ lines of manual DataView parsing
259
+ const view = new DataView(metadata.buffer, metadata.byteOffset);
260
+ const stringIdBytes = metadata.slice(0, 128);
261
+ const decoder = new TextDecoder();
262
+ const stringId = decoder.decode(stringIdBytes.slice(0, stringIdBytes.indexOf(0)));
263
+ const sampleRate = view.getUint32(128, true);
264
+ // ... 40 more lines ...
265
+ ```
266
+
267
+ **After (WASM):**
268
+ ```typescript
269
+ // 1 line!
270
+ const info = reader.parseAudioMetadata(index);
271
+ ```
272
+
273
+ **Benefits:**
274
+ - ✅ Single source of truth (C header defines all structs)
275
+ - ✅ 10-50x faster parsing
276
+ - ✅ No sync issues between reader and parser
277
+ - ✅ Less prone to offset calculation bugs
278
+ - ✅ Cleaner, more maintainable code
279
+
280
+ ## Examples
281
+
282
+ ### Inspect a Pack
283
+
284
+ ```typescript
285
+ import { StowKitReader, AssetType } from '@series-inc/stowkit-reader';
286
+
287
+ const reader = new StowKitReader();
288
+ await reader.init();
289
+
290
+ const response = await fetch('game.stow');
291
+ await reader.open(await response.arrayBuffer());
292
+
293
+ const assets = reader.listAssets();
294
+ console.log(`Pack contains ${assets.length} assets`);
295
+
296
+ assets.forEach(asset => {
297
+ const typeName = ['Unknown', 'Mesh', 'Texture', 'Audio', 'Schema', 'Skinned Mesh', 'Animation'][asset.type] || 'Unknown';
298
+ console.log(`[${asset.index}] ${asset.name} - ${typeName} (${StowKitReader.formatBytes(asset.dataSize)})`);
299
+ });
300
+
301
+ reader.close();
302
+ ```
303
+
304
+ ### Extract Assets
305
+
306
+ ```typescript
307
+ const reader = new StowKitReader();
308
+ await reader.init();
309
+ await reader.open(buffer);
310
+
311
+ // Find and extract a specific asset
312
+ const index = reader.findAssetByPath('models/character.mesh');
313
+ if (index >= 0) {
314
+ const data = reader.readAssetData(index);
315
+ const metadata = reader.readAssetMetadata(index);
316
+
317
+ // Save to file
318
+ const blob = new Blob([data]);
319
+ const url = URL.createObjectURL(blob);
320
+ const a = document.createElement('a');
321
+ a.href = url;
322
+ a.download = 'character.mesh';
323
+ a.click();
324
+ }
325
+ ```
326
+
327
+ ## Requirements
328
+
329
+ - WebAssembly support in the browser
330
+ - The `stowkit_reader.wasm` file must be accessible at runtime
Binary file
package/package.json CHANGED
@@ -1,28 +1,32 @@
1
- {
2
- "name": "@series-inc/stowkit-reader",
3
- "version": "0.1.41",
4
- "description": "WebAssembly-based reader for StowKit (.stow) asset pack files",
5
- "main": "dist/stowkit-reader.js",
6
- "module": "dist/stowkit-reader.esm.js",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist",
10
- "README.md"
11
- ],
12
- "scripts": {
13
- "build": "npm run copy:wasm && rollup -c",
14
- "copy:wasm": "node scripts/copy-wasm.js",
15
- "prepublishOnly": "npm run build"
16
- },
17
- "keywords": [],
18
- "devDependencies": {
19
- "@rollup/plugin-node-resolve": "^15.2.3",
20
- "@rollup/plugin-typescript": "^11.1.5",
21
- "rollup": "^4.9.2",
22
- "tslib": "^2.8.1",
23
- "typescript": "^5.3.3"
24
- },
25
- "publishConfig": {
26
- "access": "public"
27
- }
28
- }
1
+ {
2
+ "name": "@series-inc/stowkit-reader",
3
+ "version": "0.1.43",
4
+ "description": "WebAssembly-based reader for StowKit (.stow) asset pack files",
5
+ "main": "dist/stowkit-reader.js",
6
+ "module": "dist/stowkit-reader.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "build": "npm run copy:wasm && rollup -c",
14
+ "copy:wasm": "node scripts/copy-wasm.js",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [],
18
+ "devDependencies": {
19
+ "@rollup/plugin-node-resolve": "^15.2.3",
20
+ "@rollup/plugin-typescript": "^11.1.5",
21
+ "rollup": "^4.9.2",
22
+ "tslib": "^2.8.1",
23
+ "typescript": "^5.3.3"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/series-ai/stowkit-2.git"
31
+ }
32
+ }