@datamoc/mw_games 0.19.0 → 0.20.0
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 +28 -0
- package/dist/ai/index.d.ts +2 -2
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +1 -1
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/search.d.ts +49 -0
- package/dist/ai/search.d.ts.map +1 -1
- package/dist/ai/search.js +48 -0
- package/dist/ai/search.js.map +1 -1
- package/dist/audio/MidiRender.d.ts +39 -2
- package/dist/audio/MidiRender.d.ts.map +1 -1
- package/dist/audio/MidiRender.js +286 -199
- package/dist/audio/MidiRender.js.map +1 -1
- package/dist/audio/index.d.ts +2 -2
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +1 -1
- package/dist/audio/index.js.map +1 -1
- package/dist/board/Engine.d.ts +33 -0
- package/dist/board/Engine.d.ts.map +1 -1
- package/dist/board/Engine.js +448 -1
- package/dist/board/Engine.js.map +1 -1
- package/dist/board/index.d.ts +2 -2
- package/dist/board/index.d.ts.map +1 -1
- package/dist/board/index.js +1 -1
- package/dist/board/index.js.map +1 -1
- package/dist/mw_games.global.js +22 -22
- package/dist/threads/index.d.ts +3 -0
- package/dist/threads/index.d.ts.map +1 -0
- package/dist/threads/index.js +2 -0
- package/dist/threads/index.js.map +1 -0
- package/dist/threads/spawn.d.ts +41 -0
- package/dist/threads/spawn.d.ts.map +1 -0
- package/dist/threads/spawn.js +143 -0
- package/dist/threads/spawn.js.map +1 -0
- package/dist/threads/worker.d.ts +51 -0
- package/dist/threads/worker.d.ts.map +1 -0
- package/dist/threads/worker.js +84 -0
- package/dist/threads/worker.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -1
- package/sbom.cdx.json +54 -28
- package/tools/compress-dist.d.mts +8 -0
- package/tools/compress-dist.mjs +76 -30
package/tools/compress-dist.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { relative, extname, basename } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { gzip, brotliCompress, constants } from 'node:zlib';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { availableParallelism } from 'node:os';
|
|
4
6
|
import { spawnSync } from 'node:child_process';
|
|
5
7
|
import { walk } from './compile-resources.mjs';
|
|
6
8
|
|
|
@@ -21,6 +23,11 @@ import { walk } from './compile-resources.mjs';
|
|
|
21
23
|
* a server can negotiate: `gz` stays the fallback.
|
|
22
24
|
*
|
|
23
25
|
* usage: node tools/compress-dist.mjs <dist folder> [--xz] [--no-gzip] [--no-brotli]
|
|
26
|
+
*
|
|
27
|
+
* Files compress in parallel over async `zlib` (the libuv threadpool, not worker
|
|
28
|
+
* threads): one chain per job over a shared queue, defaulting to MWG_COMPRESS_JOBS
|
|
29
|
+
* when it names a positive integer, else the machine's thread count, else 4. Rows
|
|
30
|
+
* land by index, so the report keeps walk order no matter who finishes first.
|
|
24
31
|
*/
|
|
25
32
|
|
|
26
33
|
const TEXT_EXTENSIONS = new Set(['.js', '.html', '.css', '.svg', '.json', '.txt', '.map']);
|
|
@@ -41,6 +48,26 @@ const ALREADY_COMPRESSED = new Set([
|
|
|
41
48
|
]);
|
|
42
49
|
const MIN_BYTES = 1024;
|
|
43
50
|
|
|
51
|
+
const gzipAsync = promisify(gzip);
|
|
52
|
+
const brotliAsync = promisify(brotliCompress);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* How many files `compressDist` works on at once: `MWG_COMPRESS_JOBS` when it names
|
|
56
|
+
* a positive integer, else the machine's own thread count, else 4. An env knob rather
|
|
57
|
+
* than a constant so a loaded CI host can turn one build down without editing anything.
|
|
58
|
+
*/
|
|
59
|
+
export function compressJobs() {
|
|
60
|
+
const raw = Number(process.env.MWG_COMPRESS_JOBS);
|
|
61
|
+
if (Number.isInteger(raw) && raw > 0) return raw;
|
|
62
|
+
try {
|
|
63
|
+
const parallel = availableParallelism();
|
|
64
|
+
if (Number.isInteger(parallel) && parallel > 0) return parallel;
|
|
65
|
+
} catch {
|
|
66
|
+
//a build tool must never fail for lack of a hint about its own host
|
|
67
|
+
}
|
|
68
|
+
return 4;
|
|
69
|
+
}
|
|
70
|
+
|
|
44
71
|
/** true when the system `xz` binary (LZMA2) is available for the opt-in archive pass */
|
|
45
72
|
export function hasXz() {
|
|
46
73
|
try {
|
|
@@ -67,44 +94,63 @@ function compressXz(data) {
|
|
|
67
94
|
* @param options.gzip write `.gz` siblings (default true)
|
|
68
95
|
* @param options.brotli write `.br` siblings (default true)
|
|
69
96
|
* @param options.xz also write `.xz` siblings where smaller (default false, needs `xz`)
|
|
70
|
-
* @
|
|
97
|
+
* @param options.jobs files to compress at once (default `compressJobs()`)
|
|
98
|
+
* @returns one row per file considered, with the sizes actually written, in walk order
|
|
71
99
|
*/
|
|
72
|
-
export async function compressDist(dir, { gzip = true, brotli = true, xz = false } = {}) {
|
|
73
|
-
const
|
|
74
|
-
const wantXz = xz && hasXz();
|
|
100
|
+
export async function compressDist(dir, { gzip = true, brotli = true, xz = false, jobs = compressJobs() } = {}) {
|
|
101
|
+
const candidates = [];
|
|
75
102
|
for await (const file of walk(dir)) {
|
|
76
103
|
const ext = extname(file).toLowerCase();
|
|
77
104
|
if (!TEXT_EXTENSIONS.has(ext) || ALREADY_COMPRESSED.has(ext)) continue;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
105
|
+
candidates.push(file);
|
|
106
|
+
}
|
|
107
|
+
const wantXz = xz && hasXz();
|
|
108
|
+
const lanes = Math.max(1, Math.min(Math.floor(jobs) || 1, Math.max(candidates.length, 1)));
|
|
109
|
+
const rows = new Array(candidates.length);
|
|
110
|
+
let next = 0;
|
|
111
|
+
await Promise.all(
|
|
112
|
+
Array.from({ length: lanes }, async () => {
|
|
113
|
+
for (;;) {
|
|
114
|
+
const index = next++;
|
|
115
|
+
if (index >= candidates.length) return;
|
|
116
|
+
rows[index] = await compressOne(dir, candidates[index], { gzip, brotli, wantXz });
|
|
87
117
|
}
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
return rows.filter((row) => row !== undefined);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** gzip and brotli of one file, or undefined when it is too small to bother with */
|
|
124
|
+
async function compressOne(dir, file, { gzip, brotli, wantXz }) {
|
|
125
|
+
const data = await readFile(file);
|
|
126
|
+
if (data.length < MIN_BYTES) return undefined;
|
|
127
|
+
const row = { file: relative(dir, file), raw: data.length, gzip: 0, brotli: 0, xz: 0 };
|
|
128
|
+
if (gzip) {
|
|
129
|
+
const zipped = await gzipAsync(data, { level: 9 });
|
|
130
|
+
if (zipped.length < data.length) {
|
|
131
|
+
await writeFile(file + '.gz', zipped);
|
|
132
|
+
row.gzip = zipped.length;
|
|
88
133
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
134
|
+
}
|
|
135
|
+
if (brotli) {
|
|
136
|
+
const squeezed = await brotliAsync(data, {
|
|
137
|
+
params: { [constants.BROTLI_PARAM_QUALITY]: 11 },
|
|
138
|
+
});
|
|
139
|
+
if (squeezed.length < data.length) {
|
|
140
|
+
await writeFile(file + '.br', squeezed);
|
|
141
|
+
row.brotli = squeezed.length;
|
|
97
142
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
143
|
+
}
|
|
144
|
+
if (wantXz) {
|
|
145
|
+
//the opt-in archive pass stays synchronous: xz is a child process either way, and
|
|
146
|
+
//it sits outside the measured gzip/brotli path this parallelizes
|
|
147
|
+
const archived = compressXz(data);
|
|
148
|
+
if (archived && archived.length < data.length) {
|
|
149
|
+
await writeFile(file + '.xz', archived);
|
|
150
|
+
row.xz = archived.length;
|
|
104
151
|
}
|
|
105
|
-
rows.push(row);
|
|
106
152
|
}
|
|
107
|
-
return
|
|
153
|
+
return row;
|
|
108
154
|
}
|
|
109
155
|
|
|
110
156
|
const isMain = process.argv[1] && import.meta.url.endsWith(basename(process.argv[1]));
|