@datamoc/mw_games 0.43.0 → 0.44.2
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 +67 -0
- package/README.md +22 -0
- package/REFERENCE.md +82 -6
- package/api-surface.json +1028 -2
- package/dist/actors/Resource.d.ts.map +1 -1
- package/dist/actors/Resource.js +2 -3
- package/dist/actors/Resource.js.map +1 -1
- package/dist/audio/AdaptiveMusic.d.ts +85 -0
- package/dist/audio/AdaptiveMusic.d.ts.map +1 -0
- package/dist/audio/AdaptiveMusic.js +230 -0
- package/dist/audio/AdaptiveMusic.js.map +1 -0
- package/dist/audio/AudioLoader.d.ts +7 -2
- package/dist/audio/AudioLoader.d.ts.map +1 -1
- package/dist/audio/AudioLoader.js +23 -18
- package/dist/audio/AudioLoader.js.map +1 -1
- package/dist/audio/AudioViews.d.ts +70 -0
- package/dist/audio/AudioViews.d.ts.map +1 -0
- package/dist/audio/AudioViews.js +119 -0
- package/dist/audio/AudioViews.js.map +1 -0
- package/dist/audio/BusBudget.d.ts +89 -0
- package/dist/audio/BusBudget.d.ts.map +1 -0
- package/dist/audio/BusBudget.js +120 -0
- package/dist/audio/BusBudget.js.map +1 -0
- package/dist/audio/Channels.d.ts +65 -1
- package/dist/audio/Channels.d.ts.map +1 -1
- package/dist/audio/Channels.js +117 -30
- package/dist/audio/Channels.js.map +1 -1
- package/dist/audio/CoreHost.d.ts +114 -0
- package/dist/audio/CoreHost.d.ts.map +1 -0
- package/dist/audio/CoreHost.js +335 -0
- package/dist/audio/CoreHost.js.map +1 -0
- package/dist/audio/DecoderGuard.d.ts +139 -0
- package/dist/audio/DecoderGuard.d.ts.map +1 -0
- package/dist/audio/DecoderGuard.js +208 -0
- package/dist/audio/DecoderGuard.js.map +1 -0
- package/dist/audio/Fft.d.ts +3 -0
- package/dist/audio/Fft.d.ts.map +1 -0
- package/dist/audio/Fft.js +45 -0
- package/dist/audio/Fft.js.map +1 -0
- package/dist/audio/LoopTags.d.ts +18 -0
- package/dist/audio/LoopTags.d.ts.map +1 -1
- package/dist/audio/LoopTags.js +20 -0
- package/dist/audio/LoopTags.js.map +1 -1
- package/dist/audio/Midi.d.ts +35 -0
- package/dist/audio/Midi.d.ts.map +1 -1
- package/dist/audio/Midi.js +71 -1
- package/dist/audio/Midi.js.map +1 -1
- package/dist/audio/MidiRender.d.ts +31 -0
- package/dist/audio/MidiRender.d.ts.map +1 -1
- package/dist/audio/MidiRender.js +79 -2
- package/dist/audio/MidiRender.js.map +1 -1
- package/dist/audio/MidiSynth.d.ts +147 -0
- package/dist/audio/MidiSynth.d.ts.map +1 -0
- package/dist/audio/MidiSynth.js +205 -0
- package/dist/audio/MidiSynth.js.map +1 -0
- package/dist/audio/Playable.d.ts +7 -0
- package/dist/audio/Playable.d.ts.map +1 -1
- package/dist/audio/Playable.js.map +1 -1
- package/dist/audio/Positional.d.ts +12 -4
- package/dist/audio/Positional.d.ts.map +1 -1
- package/dist/audio/Positional.js +5 -2
- package/dist/audio/Positional.js.map +1 -1
- package/dist/audio/Resample.d.ts +61 -0
- package/dist/audio/Resample.d.ts.map +1 -0
- package/dist/audio/Resample.js +97 -0
- package/dist/audio/Resample.js.map +1 -0
- package/dist/audio/Settings.d.ts +99 -0
- package/dist/audio/Settings.d.ts.map +1 -0
- package/dist/audio/Settings.js +134 -0
- package/dist/audio/Settings.js.map +1 -0
- package/dist/audio/Sfx.d.ts +148 -0
- package/dist/audio/Sfx.d.ts.map +1 -0
- package/dist/audio/Sfx.js +213 -0
- package/dist/audio/Sfx.js.map +1 -0
- package/dist/audio/SpectralDistance.d.ts +34 -0
- package/dist/audio/SpectralDistance.d.ts.map +1 -0
- package/dist/audio/SpectralDistance.js +64 -0
- package/dist/audio/SpectralDistance.js.map +1 -0
- package/dist/audio/StreamChannel.d.ts +150 -0
- package/dist/audio/StreamChannel.d.ts.map +1 -0
- package/dist/audio/StreamChannel.js +390 -0
- package/dist/audio/StreamChannel.js.map +1 -0
- package/dist/audio/StreamPlayable.d.ts +73 -0
- package/dist/audio/StreamPlayable.d.ts.map +1 -0
- package/dist/audio/StreamPlayable.js +130 -0
- package/dist/audio/StreamPlayable.js.map +1 -0
- package/dist/audio/SyxBank.d.ts +73 -0
- package/dist/audio/SyxBank.d.ts.map +1 -0
- package/dist/audio/SyxBank.js +130 -0
- package/dist/audio/SyxBank.js.map +1 -0
- package/dist/audio/Underrun.d.ts +25 -0
- package/dist/audio/Underrun.d.ts.map +1 -0
- package/dist/audio/Underrun.js +18 -0
- package/dist/audio/Underrun.js.map +1 -0
- package/dist/audio/Wav.d.ts +56 -0
- package/dist/audio/Wav.d.ts.map +1 -0
- package/dist/audio/Wav.js +164 -0
- package/dist/audio/Wav.js.map +1 -0
- package/dist/audio/WebMidi.d.ts +58 -0
- package/dist/audio/WebMidi.d.ts.map +1 -0
- package/dist/audio/WebMidi.js +79 -0
- package/dist/audio/WebMidi.js.map +1 -0
- package/dist/audio/humanize/Onsets.d.ts.map +1 -1
- package/dist/audio/humanize/Onsets.js +1 -44
- package/dist/audio/humanize/Onsets.js.map +1 -1
- package/dist/audio/index.d.ts +38 -6
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +19 -3
- package/dist/audio/index.js.map +1 -1
- package/dist/battle/AttackPreview.d.ts.map +1 -1
- package/dist/battle/AttackPreview.js +8 -8
- package/dist/battle/AttackPreview.js.map +1 -1
- package/dist/battle/StatStages.d.ts.map +1 -1
- package/dist/battle/StatStages.js +2 -1
- package/dist/battle/StatStages.js.map +1 -1
- package/dist/board/Engine.d.ts +2 -0
- package/dist/board/Engine.d.ts.map +1 -1
- package/dist/board/Engine.js +1 -1
- package/dist/board/Engine.js.map +1 -1
- package/dist/board/HexSkirmish.d.ts.map +1 -1
- package/dist/board/HexSkirmish.js +11 -72
- package/dist/board/HexSkirmish.js.map +1 -1
- package/dist/board/Tactics.d.ts.map +1 -1
- package/dist/board/Tactics.js +3 -5
- package/dist/board/Tactics.js.map +1 -1
- package/dist/board/tourney.d.ts.map +1 -1
- package/dist/board/tourney.js +2 -19
- package/dist/board/tourney.js.map +1 -1
- package/dist/core/Handles.js +7 -7
- package/dist/core/Handles.js.map +1 -1
- package/dist/mw_games.global.js +25 -22
- package/dist/mwl/conditions.d.ts +12 -0
- package/dist/mwl/conditions.d.ts.map +1 -1
- package/dist/mwl/conditions.js +49 -8
- package/dist/mwl/conditions.js.map +1 -1
- package/dist/mwl/index.d.ts +11 -0
- package/dist/mwl/index.d.ts.map +1 -1
- package/dist/mwl/index.js +6 -0
- package/dist/mwl/index.js.map +1 -1
- package/dist/mwl/package-container.d.ts +185 -0
- package/dist/mwl/package-container.d.ts.map +1 -0
- package/dist/mwl/package-container.js +446 -0
- package/dist/mwl/package-container.js.map +1 -0
- package/dist/mwl/package-document.d.ts +217 -0
- package/dist/mwl/package-document.d.ts.map +1 -0
- package/dist/mwl/package-document.js +639 -0
- package/dist/mwl/package-document.js.map +1 -0
- package/dist/mwl/package-rom.d.ts +37 -0
- package/dist/mwl/package-rom.d.ts.map +1 -0
- package/dist/mwl/package-rom.js +96 -0
- package/dist/mwl/package-rom.js.map +1 -0
- package/dist/mwl/package-verify.d.ts +34 -0
- package/dist/mwl/package-verify.d.ts.map +1 -0
- package/dist/mwl/package-verify.js +111 -0
- package/dist/mwl/package-verify.js.map +1 -0
- package/dist/mwl/package.d.ts +184 -0
- package/dist/mwl/package.d.ts.map +1 -0
- package/dist/mwl/package.js +382 -0
- package/dist/mwl/package.js.map +1 -0
- package/dist/physics/PhysicsWorld.d.ts.map +1 -1
- package/dist/physics/PhysicsWorld.js +4 -3
- package/dist/physics/PhysicsWorld.js.map +1 -1
- package/dist/physics/XpbdWorld.d.ts.map +1 -1
- package/dist/physics/XpbdWorld.js +2 -1
- package/dist/physics/XpbdWorld.js.map +1 -1
- package/dist/testing/FakeAudio.d.ts +149 -0
- package/dist/testing/FakeAudio.d.ts.map +1 -0
- package/dist/testing/FakeAudio.js +219 -0
- package/dist/testing/FakeAudio.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/threads/index.d.ts +2 -2
- package/dist/threads/index.d.ts.map +1 -1
- package/dist/threads/index.js +1 -1
- package/dist/threads/index.js.map +1 -1
- package/dist/threads/spawn.d.ts +32 -0
- package/dist/threads/spawn.d.ts.map +1 -1
- package/dist/threads/spawn.js +35 -11
- package/dist/threads/spawn.js.map +1 -1
- package/dist/two-d/Game.d.ts +13 -2
- package/dist/two-d/Game.d.ts.map +1 -1
- package/dist/two-d/Game.js +42 -18
- package/dist/two-d/Game.js.map +1 -1
- package/dist/two-d/render/HazeLayer.d.ts.map +1 -1
- package/dist/two-d/render/HazeLayer.js +2 -1
- package/dist/two-d/render/HazeLayer.js.map +1 -1
- package/dist/two-d/render/ImageModifiers.d.ts +4 -2
- package/dist/two-d/render/ImageModifiers.d.ts.map +1 -1
- package/dist/two-d/render/ImageModifiers.js +13 -8
- package/dist/two-d/render/ImageModifiers.js.map +1 -1
- package/dist/two-d/render/NeonGlow.d.ts.map +1 -1
- package/dist/two-d/render/NeonGlow.js +2 -1
- package/dist/two-d/render/NeonGlow.js.map +1 -1
- package/dist/two-d/render/Particles.d.ts.map +1 -1
- package/dist/two-d/render/Particles.js +2 -1
- package/dist/two-d/render/Particles.js.map +1 -1
- package/dist/two-d/render/SceneTransition.d.ts +29 -0
- package/dist/two-d/render/SceneTransition.d.ts.map +1 -1
- package/dist/two-d/render/SceneTransition.js +27 -0
- package/dist/two-d/render/SceneTransition.js.map +1 -1
- package/dist/two-d/render/ScreenEffects.d.ts.map +1 -1
- package/dist/two-d/render/ScreenEffects.js +2 -1
- package/dist/two-d/render/ScreenEffects.js.map +1 -1
- package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
- package/dist/two-d/render/SkeletalSprite.js +2 -1
- package/dist/two-d/render/SkeletalSprite.js.map +1 -1
- package/dist/two-d/render/Types2D.d.ts +2 -2
- package/dist/two-d/render/Types2D.d.ts.map +1 -1
- package/dist/two-d/render/Types2D.js +2 -2
- package/dist/two-d/render/Types2D.js.map +1 -1
- package/dist/two-d/render/index.d.ts +2 -2
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +1 -1
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/ui/Bar.d.ts.map +1 -1
- package/dist/two-d/ui/Bar.js +3 -5
- package/dist/two-d/ui/Bar.js.map +1 -1
- package/dist/two-d/ui/Dropdown.d.ts +5 -1
- package/dist/two-d/ui/Dropdown.d.ts.map +1 -1
- package/dist/two-d/ui/Dropdown.js +8 -1
- package/dist/two-d/ui/Dropdown.js.map +1 -1
- package/dist/two-d/ui/DropdownView.d.ts +15 -1
- package/dist/two-d/ui/DropdownView.d.ts.map +1 -1
- package/dist/two-d/ui/DropdownView.js +21 -3
- package/dist/two-d/ui/DropdownView.js.map +1 -1
- package/dist/two-d/ui/FloatingText.d.ts.map +1 -1
- package/dist/two-d/ui/FloatingText.js +2 -1
- package/dist/two-d/ui/FloatingText.js.map +1 -1
- package/dist/two-d/ui/IconGrid.d.ts.map +1 -1
- package/dist/two-d/ui/IconGrid.js +2 -1
- package/dist/two-d/ui/IconGrid.js.map +1 -1
- package/dist/two-d/ui/ListView.d.ts.map +1 -1
- package/dist/two-d/ui/ListView.js +2 -1
- package/dist/two-d/ui/ListView.js.map +1 -1
- package/dist/two-d/ui/ScrollBox.d.ts +6 -0
- package/dist/two-d/ui/ScrollBox.d.ts.map +1 -1
- package/dist/two-d/ui/ScrollBox.js +12 -1
- package/dist/two-d/ui/ScrollBox.js.map +1 -1
- package/dist/two-d/ui/ScrollText.d.ts +11 -2
- package/dist/two-d/ui/ScrollText.d.ts.map +1 -1
- package/dist/two-d/ui/ScrollText.js +18 -2
- package/dist/two-d/ui/ScrollText.js.map +1 -1
- package/dist/two-d/ui/Slider.d.ts.map +1 -1
- package/dist/two-d/ui/Slider.js +4 -4
- package/dist/two-d/ui/Slider.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -1
- package/sbom.cdx.json +6 -6
- package/tools/audio.d.mts +75 -0
- package/tools/audio.mjs +437 -0
- package/tools/mwl.mjs +144 -2
- package/tools.md +1 -1
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `.mwp` container: a magic, a DEFLATE JSON directory and the entries back to back.
|
|
3
|
+
*
|
|
4
|
+
* ```
|
|
5
|
+
* "MWP1" u32le directory size directory (JSON, raw DEFLATE) entry 0 entry 1 ...
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* ZIP was the other candidate. This directory is simpler to hash and to read without a library,
|
|
9
|
+
* rejects what ZIP leaves ambiguous (duplicate names, absolute paths, overlapping members) by
|
|
10
|
+
* construction, and keeps the one rule that matters for content from strangers: nothing is
|
|
11
|
+
* returned unless every entry has been inflated within its declared size and matched its digest.
|
|
12
|
+
* Compression and digests use the platform (`CompressionStream`, `crypto.subtle`), so the module
|
|
13
|
+
* runs unchanged in a browser and in Node.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* The base of every error a package can raise, so a caller can refuse them all with one test.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { PackageError } from '@datamoc/mw_games/mwl';
|
|
21
|
+
*
|
|
22
|
+
* console.log(new PackageError('refused') instanceof Error); // true
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class PackageError extends Error {
|
|
26
|
+
constructor(message) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = 'PackageError';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The file is not a well-formed package: bad magic, truncated, malformed directory or media.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { decodePackage, PackageFormatError } from '@datamoc/mw_games/mwl';
|
|
37
|
+
*
|
|
38
|
+
* await decodePackage(new Uint8Array(8)).catch((error) => console.log(error instanceof PackageFormatError)); // true
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class PackageFormatError extends PackageError {
|
|
42
|
+
constructor(message) {
|
|
43
|
+
super(message);
|
|
44
|
+
this.name = 'PackageFormatError';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* An entry does not match the digest the directory declares for it.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { PackageIntegrityError } from '@datamoc/mw_games/mwl';
|
|
53
|
+
*
|
|
54
|
+
* console.log(new PackageIntegrityError('sha256 mismatch').name); // 'PackageIntegrityError'
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export class PackageIntegrityError extends PackageError {
|
|
58
|
+
constructor(message) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'PackageIntegrityError';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The package exceeds a declared limit (size, entry count, image dimensions, audio length).
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* import { PackageLimitError } from '@datamoc/mw_games/mwl';
|
|
69
|
+
*
|
|
70
|
+
* console.log(new PackageLimitError('too many entries').name); // 'PackageLimitError'
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export class PackageLimitError extends PackageError {
|
|
74
|
+
constructor(message) {
|
|
75
|
+
super(message);
|
|
76
|
+
this.name = 'PackageLimitError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A path escapes the package (absolute, `..`, a drive, a backslash) or appears twice.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* import { checkPackagePath, PackagePathError } from '@datamoc/mw_games/mwl';
|
|
85
|
+
*
|
|
86
|
+
* try {
|
|
87
|
+
* checkPackagePath('../escape.txt');
|
|
88
|
+
* } catch (error) {
|
|
89
|
+
* console.log(error instanceof PackagePathError); // true
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export class PackagePathError extends PackageError {
|
|
94
|
+
constructor(message) {
|
|
95
|
+
super(message);
|
|
96
|
+
this.name = 'PackagePathError';
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The limits applied when a caller names none. A game raises them by spreading over this object.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* import { DEFAULT_PACKAGE_LIMITS, decodePackage } from '@datamoc/mw_games/mwl';
|
|
105
|
+
*
|
|
106
|
+
* const roomy = { ...DEFAULT_PACKAGE_LIMITS, maxEntries: 4096 };
|
|
107
|
+
* await decodePackage(new Uint8Array(8), roomy).catch(() => console.log(roomy.maxEntries)); // 4096
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export const DEFAULT_PACKAGE_LIMITS = {
|
|
111
|
+
maxPackageBytes: 64 * 1024 * 1024,
|
|
112
|
+
maxTotalBytes: 128 * 1024 * 1024,
|
|
113
|
+
maxEntries: 512,
|
|
114
|
+
maxEntryBytes: 32 * 1024 * 1024,
|
|
115
|
+
maxAudioSeconds: 600,
|
|
116
|
+
maxImageWidth: 4096,
|
|
117
|
+
maxImageHeight: 4096,
|
|
118
|
+
};
|
|
119
|
+
const MAGIC = [0x4d, 0x57, 0x50, 0x31]; // 'MWP1'
|
|
120
|
+
const HEADER_BYTES = 8;
|
|
121
|
+
/** the directory is a list of short records; a bigger one is not a package */
|
|
122
|
+
const MAX_DIRECTORY_BYTES = 4 * 1024 * 1024;
|
|
123
|
+
const DEFAULT_MAIN = 'content.mwl';
|
|
124
|
+
/**
|
|
125
|
+
* Validates a path that will live inside a package and returns it unchanged.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* import { checkPackagePath } from '@datamoc/mw_games/mwl';
|
|
130
|
+
*
|
|
131
|
+
* console.log(checkPackagePath('media/portrait.png')); // 'media/portrait.png'
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export function checkPackagePath(path) {
|
|
135
|
+
if (typeof path !== 'string' || path === '' || path.length > 240)
|
|
136
|
+
throw new PackagePathError(`bad package path`);
|
|
137
|
+
// eslint-disable-next-line no-control-regex
|
|
138
|
+
if (path.includes('\\') || /[\u0000-\u001f]/.test(path) || path.startsWith('/') || /^[A-Za-z]:/.test(path))
|
|
139
|
+
throw new PackagePathError(`package path "${path}" must be relative with forward slashes`);
|
|
140
|
+
for (const segment of path.split('/'))
|
|
141
|
+
if (segment === '' || segment === '.' || segment === '..')
|
|
142
|
+
throw new PackagePathError(`package path "${path}" escapes or is not normalised`);
|
|
143
|
+
return path;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Lower-case hex SHA-256 of some bytes, through `crypto.subtle`.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* import { sha256Hex } from '@datamoc/mw_games/mwl';
|
|
151
|
+
*
|
|
152
|
+
* console.log((await sha256Hex(new Uint8Array(0))).slice(0, 8)); // 'e3b0c442'
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
export async function sha256Hex(bytes) {
|
|
156
|
+
const digest = await globalThis.crypto.subtle.digest('SHA-256', bytes);
|
|
157
|
+
return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Packs files into one `.mwp`. It refuses what `decodePackage` would refuse, so a package that
|
|
161
|
+
* was written can be read back under the same limits.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* import { decodePackage, encodePackage } from '@datamoc/mw_games/mwl';
|
|
166
|
+
*
|
|
167
|
+
* const text = new TextEncoder().encode('[]');
|
|
168
|
+
* const bytes = await encodePackage([{ path: 'content.mwl', data: text }]);
|
|
169
|
+
* console.log((await decodePackage(bytes)).main); // 'content.mwl'
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export async function encodePackage(files, options = {}) {
|
|
173
|
+
const limits = { ...DEFAULT_PACKAGE_LIMITS, ...options.limits };
|
|
174
|
+
const main = options.main ?? DEFAULT_MAIN;
|
|
175
|
+
const sorted = [...files].sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
176
|
+
checkTable(sorted.map((file) => ({ path: file.path, size: file.data.length })), limits);
|
|
177
|
+
if (!sorted.some((file) => file.path === main))
|
|
178
|
+
throw new PackageFormatError(`main document "${main}" is missing`);
|
|
179
|
+
const entries = [];
|
|
180
|
+
const bodies = [];
|
|
181
|
+
let offset = 0;
|
|
182
|
+
for (const file of sorted) {
|
|
183
|
+
checkMedia(file.path, file.data, limits);
|
|
184
|
+
const packed = await deflateRaw(file.data);
|
|
185
|
+
entries.push({
|
|
186
|
+
path: file.path,
|
|
187
|
+
size: file.data.length,
|
|
188
|
+
packed: packed.length,
|
|
189
|
+
offset,
|
|
190
|
+
sha256: await sha256Hex(file.data),
|
|
191
|
+
});
|
|
192
|
+
bodies.push(packed);
|
|
193
|
+
offset += packed.length;
|
|
194
|
+
}
|
|
195
|
+
const directory = await deflateRaw(new TextEncoder().encode(JSON.stringify({ entries, main })));
|
|
196
|
+
const header = new Uint8Array(HEADER_BYTES);
|
|
197
|
+
header.set(MAGIC, 0);
|
|
198
|
+
new DataView(header.buffer).setUint32(4, directory.length, true);
|
|
199
|
+
const out = concat([header, directory, ...bodies]);
|
|
200
|
+
if (out.length > limits.maxPackageBytes)
|
|
201
|
+
throw new PackageLimitError(`package is ${out.length} bytes, over the ${limits.maxPackageBytes} limit`);
|
|
202
|
+
return out;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Reads a `.mwp`. Every entry is inflated within its declared size and matched to its SHA-256
|
|
206
|
+
* before anything is returned; any problem throws a `PackageError` subclass and no partial
|
|
207
|
+
* content escapes.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* import { decodePackage, encodePackage } from '@datamoc/mw_games/mwl';
|
|
212
|
+
*
|
|
213
|
+
* const bytes = await encodePackage([{ path: 'content.mwl', data: new TextEncoder().encode('[]') }]);
|
|
214
|
+
* const decoded = await decodePackage(bytes, { maxEntries: 8 });
|
|
215
|
+
* console.log(decoded.files.map((file) => file.path)); // ['content.mwl']
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
export async function decodePackage(bytes, overrides = {}) {
|
|
219
|
+
const limits = { ...DEFAULT_PACKAGE_LIMITS, ...overrides };
|
|
220
|
+
if (bytes.length > limits.maxPackageBytes)
|
|
221
|
+
throw new PackageLimitError(`package is ${bytes.length} bytes, over the ${limits.maxPackageBytes} limit`);
|
|
222
|
+
if (bytes.length < HEADER_BYTES || MAGIC.some((byte, index) => bytes[index] !== byte))
|
|
223
|
+
throw new PackageFormatError('not an MWP1 package (bad magic)');
|
|
224
|
+
const directorySize = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(4, true);
|
|
225
|
+
if (directorySize > MAX_DIRECTORY_BYTES || HEADER_BYTES + directorySize > bytes.length)
|
|
226
|
+
throw new PackageFormatError('package directory size is out of range');
|
|
227
|
+
const dataStart = HEADER_BYTES + directorySize;
|
|
228
|
+
const directoryText = new TextDecoder('utf-8', { fatal: true });
|
|
229
|
+
let raw;
|
|
230
|
+
try {
|
|
231
|
+
raw = JSON.parse(directoryText.decode(await inflateRaw(bytes.subarray(HEADER_BYTES, dataStart), MAX_DIRECTORY_BYTES, 'directory')));
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
if (error instanceof PackageError)
|
|
235
|
+
throw error;
|
|
236
|
+
throw new PackageFormatError('package directory is not valid JSON');
|
|
237
|
+
}
|
|
238
|
+
const { entries, main } = readDirectory(raw, bytes.length - dataStart, limits);
|
|
239
|
+
if (!entries.some((entry) => entry.path === main))
|
|
240
|
+
throw new PackageFormatError(`main document "${main}" is not in the package`);
|
|
241
|
+
const files = [];
|
|
242
|
+
for (const entry of entries) {
|
|
243
|
+
const start = dataStart + entry.offset;
|
|
244
|
+
const data = await inflateRaw(bytes.subarray(start, start + entry.packed), entry.size, entry.path);
|
|
245
|
+
if (data.length !== entry.size)
|
|
246
|
+
throw new PackageFormatError(`entry "${entry.path}" inflates to ${data.length} bytes, not ${entry.size}`);
|
|
247
|
+
if ((await sha256Hex(data)) !== entry.sha256)
|
|
248
|
+
throw new PackageIntegrityError(`entry "${entry.path}" does not match its sha256`);
|
|
249
|
+
checkMedia(entry.path, data, limits);
|
|
250
|
+
files.push({ path: entry.path, data });
|
|
251
|
+
}
|
|
252
|
+
return { main, entries, files };
|
|
253
|
+
}
|
|
254
|
+
function readDirectory(raw, dataBytes, limits) {
|
|
255
|
+
const record = raw;
|
|
256
|
+
if (!record || typeof record !== 'object' || !Array.isArray(record.entries) || typeof record.main !== 'string')
|
|
257
|
+
throw new PackageFormatError('package directory needs "entries" and "main"');
|
|
258
|
+
// Count before reading any field, so a directory of a million records is refused cheaply.
|
|
259
|
+
if (record.entries.length > limits.maxEntries)
|
|
260
|
+
throw new PackageLimitError(`package has ${record.entries.length} entries, over the ${limits.maxEntries} limit`);
|
|
261
|
+
const entries = record.entries.map((item, index) => {
|
|
262
|
+
const entry = item;
|
|
263
|
+
const count = (name) => {
|
|
264
|
+
const value = entry?.[name];
|
|
265
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)
|
|
266
|
+
throw new PackageFormatError(`directory entry ${index} has a bad "${name}"`);
|
|
267
|
+
return value;
|
|
268
|
+
};
|
|
269
|
+
if (typeof entry?.path !== 'string')
|
|
270
|
+
throw new PackageFormatError(`directory entry ${index} has no path`);
|
|
271
|
+
const sha256 = entry.sha256;
|
|
272
|
+
if (typeof sha256 !== 'string' || !/^[0-9a-f]{64}$/.test(sha256))
|
|
273
|
+
throw new PackageFormatError(`directory entry ${index} has a bad sha256`);
|
|
274
|
+
const result = {
|
|
275
|
+
path: checkPackagePath(entry.path),
|
|
276
|
+
size: count('size'),
|
|
277
|
+
packed: count('packed'),
|
|
278
|
+
offset: count('offset'),
|
|
279
|
+
sha256,
|
|
280
|
+
};
|
|
281
|
+
if (result.offset + result.packed > dataBytes)
|
|
282
|
+
throw new PackageFormatError(`entry "${result.path}" lies outside the package`);
|
|
283
|
+
return result;
|
|
284
|
+
});
|
|
285
|
+
checkTable(entries, limits);
|
|
286
|
+
return { entries, main: checkPackagePath(record.main) };
|
|
287
|
+
}
|
|
288
|
+
/** duplicate names (also by case, which collide on common filesystems) and the size limits */
|
|
289
|
+
function checkTable(entries, limits) {
|
|
290
|
+
if (entries.length > limits.maxEntries)
|
|
291
|
+
throw new PackageLimitError(`package has ${entries.length} entries, over the ${limits.maxEntries} limit`);
|
|
292
|
+
const seen = new Set();
|
|
293
|
+
let total = 0;
|
|
294
|
+
for (const entry of entries) {
|
|
295
|
+
checkPackagePath(entry.path);
|
|
296
|
+
const key = entry.path.toLowerCase();
|
|
297
|
+
if (seen.has(key))
|
|
298
|
+
throw new PackagePathError(`duplicate package path "${entry.path}"`);
|
|
299
|
+
seen.add(key);
|
|
300
|
+
if (entry.size > limits.maxEntryBytes)
|
|
301
|
+
throw new PackageLimitError(`entry "${entry.path}" is ${entry.size} bytes, over the ${limits.maxEntryBytes} limit`);
|
|
302
|
+
total += entry.size;
|
|
303
|
+
}
|
|
304
|
+
if (total > limits.maxTotalBytes)
|
|
305
|
+
throw new PackageLimitError(`package inflates to ${total} bytes, over the ${limits.maxTotalBytes} limit`);
|
|
306
|
+
}
|
|
307
|
+
/** `.png` dimensions and `.wav` length are cheap to read from the header; other media are not probed */
|
|
308
|
+
function checkMedia(path, data, limits) {
|
|
309
|
+
const lower = path.toLowerCase();
|
|
310
|
+
if (lower.endsWith('.png')) {
|
|
311
|
+
const size = readPngSize(data);
|
|
312
|
+
if (!size)
|
|
313
|
+
throw new PackageFormatError(`"${path}" is not a PNG image`);
|
|
314
|
+
if (size.width > limits.maxImageWidth || size.height > limits.maxImageHeight)
|
|
315
|
+
throw new PackageLimitError(`image "${path}" is ${size.width}x${size.height}, over ${limits.maxImageWidth}x${limits.maxImageHeight}`);
|
|
316
|
+
}
|
|
317
|
+
else if (lower.endsWith('.wav')) {
|
|
318
|
+
const seconds = readWavSeconds(data);
|
|
319
|
+
if (seconds === undefined)
|
|
320
|
+
throw new PackageFormatError(`"${path}" is not a readable WAV file`);
|
|
321
|
+
if (seconds > limits.maxAudioSeconds)
|
|
322
|
+
throw new PackageLimitError(`audio "${path}" lasts ${seconds.toFixed(1)} s, over the ${limits.maxAudioSeconds} s limit`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function readPngSize(data) {
|
|
326
|
+
const signature = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
327
|
+
if (data.length < 24 || signature.some((byte, index) => data[index] !== byte))
|
|
328
|
+
return undefined;
|
|
329
|
+
if (String.fromCharCode(data[12], data[13], data[14], data[15]) !== 'IHDR')
|
|
330
|
+
return undefined;
|
|
331
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
332
|
+
return { width: view.getUint32(16), height: view.getUint32(20) };
|
|
333
|
+
}
|
|
334
|
+
function readWavSeconds(data) {
|
|
335
|
+
const tag = (at) => String.fromCharCode(data[at], data[at + 1], data[at + 2], data[at + 3]);
|
|
336
|
+
if (data.length < 12 || tag(0) !== 'RIFF' || tag(8) !== 'WAVE')
|
|
337
|
+
return undefined;
|
|
338
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
339
|
+
let byteRate = 0; // the lowest rate the header's fields imply, so a lying header cannot shorten the duration
|
|
340
|
+
for (let at = 12; at + 8 <= data.length;) {
|
|
341
|
+
const length = view.getUint32(at + 4, true);
|
|
342
|
+
if (tag(at) === 'fmt ' && at + 24 <= data.length) {
|
|
343
|
+
const sampleRate = view.getUint32(at + 12, true);
|
|
344
|
+
// a zero in any of these makes the rate 0, so the file is refused as unreadable rather than trusted
|
|
345
|
+
byteRate = Math.min(view.getUint32(at + 16, true), sampleRate * view.getUint16(at + 20, true), sampleRate * view.getUint16(at + 10, true) * Math.ceil(view.getUint16(at + 22, true) / 8));
|
|
346
|
+
}
|
|
347
|
+
// a streaming writer may leave the data size at 0xFFFFFFFF; the real length is what is there
|
|
348
|
+
if (tag(at) === 'data')
|
|
349
|
+
return byteRate > 0 ? Math.min(length, data.length - at - 8) / byteRate : undefined;
|
|
350
|
+
at += 8 + length + (length & 1);
|
|
351
|
+
}
|
|
352
|
+
return undefined;
|
|
353
|
+
}
|
|
354
|
+
function blobStream(bytes) {
|
|
355
|
+
return new Blob([bytes]).stream();
|
|
356
|
+
}
|
|
357
|
+
/** reads a stream, giving up the moment it passes `limit`: a zip bomb is stopped while inflating */
|
|
358
|
+
async function collect(stream, limit, what) {
|
|
359
|
+
const reader = stream.getReader();
|
|
360
|
+
const chunks = [];
|
|
361
|
+
let total = 0;
|
|
362
|
+
for (;;) {
|
|
363
|
+
const { done, value } = await reader.read();
|
|
364
|
+
if (done)
|
|
365
|
+
break;
|
|
366
|
+
total += value.length;
|
|
367
|
+
if (total > limit) {
|
|
368
|
+
await reader.cancel();
|
|
369
|
+
throw new PackageLimitError(`"${what}" inflates past its declared ${limit} bytes`);
|
|
370
|
+
}
|
|
371
|
+
chunks.push(value);
|
|
372
|
+
}
|
|
373
|
+
return concat(chunks);
|
|
374
|
+
}
|
|
375
|
+
function concat(chunks) {
|
|
376
|
+
const out = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0));
|
|
377
|
+
let at = 0;
|
|
378
|
+
for (const chunk of chunks) {
|
|
379
|
+
out.set(chunk, at);
|
|
380
|
+
at += chunk.length;
|
|
381
|
+
}
|
|
382
|
+
return out;
|
|
383
|
+
}
|
|
384
|
+
async function inflateRaw(data, limit, what) {
|
|
385
|
+
if (typeof DecompressionStream === 'undefined')
|
|
386
|
+
return inflateStored(data, limit, what);
|
|
387
|
+
try {
|
|
388
|
+
return await collect(blobStream(data).pipeThrough(new DecompressionStream('deflate-raw')), limit, what);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
if (error instanceof PackageError)
|
|
392
|
+
throw error;
|
|
393
|
+
throw new PackageFormatError(`"${what}" is not valid DEFLATE data`);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
async function deflateRaw(data) {
|
|
397
|
+
const stored = storeBlocks(data);
|
|
398
|
+
if (typeof CompressionStream === 'undefined')
|
|
399
|
+
return stored;
|
|
400
|
+
const packed = await collect(blobStream(data).pipeThrough(new CompressionStream('deflate-raw')), Infinity, 'entry');
|
|
401
|
+
return packed.length < stored.length ? packed : stored;
|
|
402
|
+
}
|
|
403
|
+
/** raw DEFLATE made only of stored blocks: valid for every inflater, needs no compressor */
|
|
404
|
+
function storeBlocks(data) {
|
|
405
|
+
const blocks = Math.max(1, Math.ceil(data.length / 65535));
|
|
406
|
+
const out = new Uint8Array(data.length + blocks * 5);
|
|
407
|
+
let at = 0;
|
|
408
|
+
for (let block = 0; block < blocks; block++) {
|
|
409
|
+
const chunk = data.subarray(block * 65535, (block + 1) * 65535);
|
|
410
|
+
out[at++] = block === blocks - 1 ? 1 : 0;
|
|
411
|
+
out[at++] = chunk.length & 0xff;
|
|
412
|
+
out[at++] = chunk.length >> 8;
|
|
413
|
+
out[at++] = ~chunk.length & 0xff;
|
|
414
|
+
out[at++] = (~chunk.length >> 8) & 0xff;
|
|
415
|
+
out.set(chunk, at);
|
|
416
|
+
at += chunk.length;
|
|
417
|
+
}
|
|
418
|
+
return out;
|
|
419
|
+
}
|
|
420
|
+
/** the inflater of last resort, for a platform without `DecompressionStream`: stored blocks only */
|
|
421
|
+
function inflateStored(data, limit, what) {
|
|
422
|
+
const chunks = [];
|
|
423
|
+
let at = 0;
|
|
424
|
+
let total = 0;
|
|
425
|
+
for (let final = false; !final;) {
|
|
426
|
+
if (at + 5 > data.length)
|
|
427
|
+
throw new PackageFormatError(`"${what}" is truncated`);
|
|
428
|
+
final = (data[at] & 1) === 1;
|
|
429
|
+
if ((data[at] >> 1) & 3)
|
|
430
|
+
throw new PackageFormatError(`"${what}" is compressed and this platform has no DecompressionStream`);
|
|
431
|
+
const length = data[at + 1] | (data[at + 2] << 8);
|
|
432
|
+
if (((data[at + 3] | (data[at + 4] << 8)) ^ 0xffff) !== length)
|
|
433
|
+
throw new PackageFormatError(`"${what}" has a corrupt stored block`);
|
|
434
|
+
total += length;
|
|
435
|
+
if (total > limit)
|
|
436
|
+
throw new PackageLimitError(`"${what}" inflates past its declared ${limit} bytes`);
|
|
437
|
+
if (at + 5 + length > data.length)
|
|
438
|
+
throw new PackageFormatError(`"${what}" is truncated`);
|
|
439
|
+
chunks.push(data.subarray(at + 5, at + 5 + length));
|
|
440
|
+
at += 5 + length;
|
|
441
|
+
}
|
|
442
|
+
if (at !== data.length)
|
|
443
|
+
throw new PackageFormatError(`"${what}" has trailing bytes`);
|
|
444
|
+
return concat(chunks);
|
|
445
|
+
}
|
|
446
|
+
//# sourceMappingURL=package-container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-container.js","sourceRoot":"","sources":["../../src/mwl/package-container.ts"],"names":[],"mappings":"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"}
|