@pezkuwi/dev 0.84.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.
Files changed (37) hide show
  1. package/.skip-deno +0 -0
  2. package/README.md +547 -0
  3. package/config/eslint.js +160 -0
  4. package/config/eslint.rules.js +214 -0
  5. package/config/prettier.cjs +22 -0
  6. package/config/rollup.js +113 -0
  7. package/config/tsconfig.json +32 -0
  8. package/config/typedoc.cjs +18 -0
  9. package/package.json +107 -0
  10. package/scripts/polkadot-ci-ghact-build.mjs +540 -0
  11. package/scripts/polkadot-ci-ghact-docs.mjs +14 -0
  12. package/scripts/polkadot-ci-ghpages-force.mjs +43 -0
  13. package/scripts/polkadot-dev-build-docs.mjs +19 -0
  14. package/scripts/polkadot-dev-build-ts.mjs +1518 -0
  15. package/scripts/polkadot-dev-circular.mjs +29 -0
  16. package/scripts/polkadot-dev-clean-build.mjs +61 -0
  17. package/scripts/polkadot-dev-contrib.mjs +74 -0
  18. package/scripts/polkadot-dev-copy-dir.mjs +44 -0
  19. package/scripts/polkadot-dev-copy-to.mjs +53 -0
  20. package/scripts/polkadot-dev-deno-map.mjs +35 -0
  21. package/scripts/polkadot-dev-run-lint.mjs +40 -0
  22. package/scripts/polkadot-dev-run-node-ts.mjs +9 -0
  23. package/scripts/polkadot-dev-run-test.mjs +163 -0
  24. package/scripts/polkadot-dev-version.mjs +143 -0
  25. package/scripts/polkadot-dev-yarn-only.mjs +11 -0
  26. package/scripts/polkadot-exec-eslint.mjs +7 -0
  27. package/scripts/polkadot-exec-ghpages.mjs +11 -0
  28. package/scripts/polkadot-exec-ghrelease.mjs +7 -0
  29. package/scripts/polkadot-exec-node-test.mjs +368 -0
  30. package/scripts/polkadot-exec-rollup.mjs +7 -0
  31. package/scripts/polkadot-exec-tsc.mjs +7 -0
  32. package/scripts/polkadot-exec-webpack.mjs +7 -0
  33. package/scripts/util.mjs +540 -0
  34. package/tsconfig.build.json +18 -0
  35. package/tsconfig.config.json +14 -0
  36. package/tsconfig.scripts.json +14 -0
  37. package/tsconfig.spec.json +18 -0
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2017-2025 @polkadot/dev authors & contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import { importRelative } from './util.mjs';
6
+
7
+ await importRelative('gh-release', 'gh-release/bin/cli.js');
@@ -0,0 +1,368 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2017-2025 @polkadot/dev authors & contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ // For Node 18, earliest usable is 18.14:
6
+ //
7
+ // - node:test added in 18.0,
8
+ // - run method exposed in 18.9,
9
+ // - mock in 18.13,
10
+ // - diagnostics changed in 18.14
11
+ //
12
+ // Node 16 is not supported:
13
+ //
14
+ // - node:test added is 16.17,
15
+ // - run method exposed in 16.19,
16
+ // - mock not available
17
+
18
+ import fs from 'node:fs';
19
+ import os from 'node:os';
20
+ import path from 'node:path';
21
+ import process from 'node:process';
22
+ import { run } from 'node:test';
23
+ import { isMainThread, parentPort, Worker, workerData } from 'node:worker_threads';
24
+
25
+ // NOTE error should be defined as "Error", however the @types/node definitions doesn't include all
26
+ /** @typedef {{ file?: string; message?: string; }} DiagStat */
27
+ /** @typedef {{ details: { type: string; duration_ms: number; error: { message: string; failureType: unknown; stack: string; cause: { code: number; message: string; stack: string; generatedMessage?: any; }; code: number; } }; file?: string; name: string; testNumber: number; nesting: number; }} FailStat */
28
+ /** @typedef {{ details: { duration_ms: number }; name: string; }} PassStat */
29
+ /** @typedef {{ diag: DiagStat[]; fail: FailStat[]; pass: PassStat[]; skip: unknown[]; todo: unknown[]; total: number; [key: string]: any; }} Stats */
30
+
31
+ console.time('\t elapsed :');
32
+
33
+ const WITH_DEBUG = false;
34
+
35
+ const args = process.argv.slice(2);
36
+ /** @type {string[]} */
37
+ const files = [];
38
+
39
+ /** @type {Stats} */
40
+ const stats = {
41
+ diag: [],
42
+ fail: [],
43
+ pass: [],
44
+ skip: [],
45
+ todo: [],
46
+ total: 0
47
+ };
48
+ /** @type {string | null} */
49
+ let logFile = null;
50
+ /** @type {number} */
51
+ let startAt = 0;
52
+ /** @type {boolean} */
53
+ let bail = false;
54
+ /** @type {boolean} */
55
+ let toConsole = false;
56
+ /** @type {number} */
57
+ let progressRowCount = 0;
58
+
59
+ for (let i = 0; i < args.length; i++) {
60
+ if (args[i] === '--bail') {
61
+ bail = true;
62
+ } else if (args[i] === '--console') {
63
+ toConsole = true;
64
+ } else if (args[i] === '--logfile') {
65
+ logFile = args[++i];
66
+ } else {
67
+ files.push(args[i]);
68
+ }
69
+ }
70
+
71
+ /**
72
+ * @internal
73
+ *
74
+ * Performs an indent of the line (and containing lines) with the specific count
75
+ *
76
+ * @param {number} count
77
+ * @param {string} str
78
+ * @param {string} start
79
+ * @returns {string}
80
+ */
81
+ function indent (count, str = '', start = '') {
82
+ let pre = '\n';
83
+
84
+ switch (count) {
85
+ case 0:
86
+ break;
87
+
88
+ case 1:
89
+ pre += '\t';
90
+ break;
91
+
92
+ case 2:
93
+ pre += '\t\t';
94
+ break;
95
+
96
+ default:
97
+ pre += '\t\t\t';
98
+ break;
99
+ }
100
+
101
+ pre += ' ';
102
+
103
+ return `${pre}${start}${
104
+ str
105
+ .split('\n')
106
+ .map((l) => l.trim())
107
+ .join(`${pre}${start ? ' '.padStart(start.length, ' ') : ''}`)
108
+ }\n`;
109
+ }
110
+
111
+ /**
112
+ * @param {FailStat} r
113
+ * @return {string | undefined}
114
+ */
115
+ function getFilename (r) {
116
+ if (r.file?.includes('.spec.') || r.file?.includes('.test.')) {
117
+ return r.file;
118
+ }
119
+
120
+ if (r.details.error.cause.stack) {
121
+ const stack = r.details.error.cause.stack
122
+ .split('\n')
123
+ .map((l) => l.trim())
124
+ .filter((l) => l.startsWith('at ') && (l.includes('.spec.') || l.includes('.test.')))
125
+ .map((l) => l.match(/\(.*:\d\d?:\d\d?\)$/)?.[0])
126
+ .map((l) => l?.replace('(', '')?.replace(')', ''));
127
+
128
+ if (stack.length) {
129
+ return stack[0];
130
+ }
131
+ }
132
+
133
+ return r.file;
134
+ }
135
+
136
+ function complete () {
137
+ process.stdout.write('\n');
138
+
139
+ let logError = '';
140
+
141
+ stats.fail.forEach((r) => {
142
+ WITH_DEBUG && console.error(JSON.stringify(r, null, 2));
143
+
144
+ let item = '';
145
+
146
+ item += indent(1, [getFilename(r), r.name].filter((s) => !!s).join('\n'), 'x ');
147
+ item += indent(2, `${r.details.error.failureType} / ${r.details.error.code}${r.details.error.cause.code && r.details.error.cause.code !== r.details.error.code ? ` / ${r.details.error.cause.code}` : ''}`);
148
+
149
+ if (r.details.error.cause.message) {
150
+ item += indent(2, r.details.error.cause.message);
151
+ }
152
+
153
+ logError += item;
154
+
155
+ if (r.details.error.cause.stack) {
156
+ item += indent(2, r.details.error.cause.stack);
157
+ }
158
+
159
+ process.stdout.write(item);
160
+ });
161
+
162
+ if (logFile && logError) {
163
+ try {
164
+ fs.appendFileSync(path.join(process.cwd(), logFile), logError);
165
+ } catch (e) {
166
+ console.error(e);
167
+ }
168
+ }
169
+
170
+ console.log();
171
+ console.log('\t passed ::', stats.pass.length);
172
+ console.log('\t failed ::', stats.fail.length);
173
+ console.log('\t skipped ::', stats.skip.length);
174
+ console.log('\t todo ::', stats.todo.length);
175
+ console.log('\t total ::', stats.total);
176
+ console.timeEnd('\t elapsed :');
177
+ console.log();
178
+
179
+ // The full error information can be quite useful in the case of overall failures
180
+ if ((stats.fail.length || toConsole) && stats.diag.length) {
181
+ /** @type {string | undefined} */
182
+ let lastFilename = '';
183
+
184
+ stats.diag.forEach((r) => {
185
+ WITH_DEBUG && console.error(JSON.stringify(r, null, 2));
186
+
187
+ if (typeof r === 'string') {
188
+ console.log(r); // Node.js <= 18.14
189
+ } else if (r.file && r.file.includes('@polkadot/dev/scripts')) {
190
+ // Ignore internal diagnostics
191
+ } else {
192
+ if (lastFilename !== r.file) {
193
+ lastFilename = r.file;
194
+
195
+ console.log(lastFilename ? `\n${lastFilename}::\n` : '\n');
196
+ }
197
+
198
+ // Edge case: We don't need additional noise that is not useful.
199
+ if (!r.message?.split(' ').includes('tests')) {
200
+ console.log(`\t${r.message?.split('\n').join('\n\t')}`);
201
+ }
202
+ }
203
+ });
204
+ }
205
+
206
+ if (toConsole) {
207
+ stats.pass.forEach((r) => {
208
+ console.log(`pass ${r.name} ${r.details.duration_ms} ms`);
209
+ });
210
+
211
+ console.log();
212
+
213
+ stats.fail.forEach((r) => {
214
+ console.log(`fail ${r.name}`);
215
+ });
216
+
217
+ console.log();
218
+ }
219
+
220
+ if (stats.total === 0) {
221
+ console.error('FATAL: No tests executed');
222
+ console.error();
223
+ process.exit(1);
224
+ }
225
+
226
+ process.exit(stats.fail.length);
227
+ }
228
+
229
+ /**
230
+ * Prints the progress in real-time as data is passed from the worker.
231
+ *
232
+ * @param {string} symbol
233
+ */
234
+ function printProgress (symbol) {
235
+ if (!progressRowCount) {
236
+ progressRowCount = 0;
237
+ }
238
+
239
+ if (!startAt) {
240
+ startAt = performance.now();
241
+ }
242
+
243
+ // If starting a new row, calculate and print the elapsed time
244
+ if (progressRowCount === 0) {
245
+ const now = performance.now();
246
+ const elapsed = (now - startAt) / 1000;
247
+ const minutes = Math.floor(elapsed / 60);
248
+ const seconds = elapsed - minutes * 60;
249
+
250
+ process.stdout.write(
251
+ `${`${minutes}:${seconds.toFixed(3).padStart(6, '0')}`.padStart(11)} `
252
+ );
253
+ }
254
+
255
+ // Print the symbol with formatting
256
+ process.stdout.write(symbol);
257
+
258
+ progressRowCount++;
259
+
260
+ // Add spaces for readability
261
+ if (progressRowCount % 10 === 0) {
262
+ process.stdout.write(' '); // Double space every 10 symbols
263
+ } else if (progressRowCount % 5 === 0) {
264
+ process.stdout.write(' '); // Single space every 5 symbols
265
+ }
266
+
267
+ // If the row reaches 100 symbols, start a new row
268
+ if (progressRowCount >= 100) {
269
+ process.stdout.write('\n');
270
+ progressRowCount = 0;
271
+ }
272
+ }
273
+
274
+ async function runParallel () {
275
+ const MAX_WORKERS = Math.min(os.cpus().length, files.length);
276
+ const chunks = Math.ceil(files.length / MAX_WORKERS);
277
+
278
+ try {
279
+ // Create and manage worker threads
280
+ const results = await Promise.all(
281
+ Array.from({ length: MAX_WORKERS }, (_, i) => {
282
+ const fileSubset = files.slice(i * chunks, (i + 1) * chunks);
283
+
284
+ return new Promise((resolve, reject) => {
285
+ const worker = new Worker(new URL(import.meta.url), {
286
+ workerData: { files: fileSubset }
287
+ });
288
+
289
+ worker.on('message', (message) => {
290
+ if (message.type === 'progress') {
291
+ printProgress(message.data);
292
+ } else if (message.type === 'result') {
293
+ resolve(message.data);
294
+ }
295
+ });
296
+
297
+ worker.on('error', reject);
298
+ worker.on('exit', (code) => {
299
+ if (code !== 0) {
300
+ reject(new Error(`Worker stopped with exit code ${code}`));
301
+ }
302
+ });
303
+ });
304
+ })
305
+ );
306
+
307
+ // Aggregate results from workers
308
+ results.forEach((result) => {
309
+ Object.keys(stats).forEach((key) => {
310
+ if (Array.isArray(stats[key])) {
311
+ stats[key] = stats[key].concat(result[key]);
312
+ } else if (typeof stats[key] === 'number') {
313
+ stats[key] += result[key];
314
+ }
315
+ });
316
+ });
317
+
318
+ complete();
319
+ } catch (err) {
320
+ console.error('Error during parallel execution:', err);
321
+ process.exit(1);
322
+ }
323
+ }
324
+
325
+ if (isMainThread) {
326
+ console.time('\tElapsed:');
327
+ runParallel().catch((err) => console.error(err));
328
+ } else {
329
+ run({ files: workerData.files, timeout: 3_600_000 })
330
+ .on('data', () => undefined)
331
+ .on('end', () => parentPort && parentPort.postMessage(stats))
332
+ .on('test:coverage', () => undefined)
333
+ .on('test:diagnostic', (/** @type {DiagStat} */data) => {
334
+ stats.diag.push(data);
335
+ parentPort && parentPort.postMessage({ data: stats, type: 'result' });
336
+ })
337
+ .on('test:fail', (/** @type {FailStat} */ data) => {
338
+ const statFail = structuredClone(data);
339
+
340
+ if (data.details.error.cause?.stack) {
341
+ statFail.details.error.cause.stack = data.details.error.cause.stack;
342
+ }
343
+
344
+ stats.fail.push(statFail);
345
+ stats.total++;
346
+ parentPort && parentPort.postMessage({ data: 'x', type: 'progress' });
347
+
348
+ if (bail) {
349
+ complete();
350
+ }
351
+ })
352
+ .on('test:pass', (data) => {
353
+ const symbol = typeof data.skip !== 'undefined' ? '>' : typeof data.todo !== 'undefined' ? '!' : '·';
354
+
355
+ if (symbol === '>') {
356
+ stats.skip.push(data);
357
+ } else if (symbol === '!') {
358
+ stats.todo.push(data);
359
+ } else {
360
+ stats.pass.push(data);
361
+ }
362
+
363
+ stats.total++;
364
+ parentPort && parentPort.postMessage({ data: symbol, type: 'progress' });
365
+ })
366
+ .on('test:plan', () => undefined)
367
+ .on('test:start', () => undefined);
368
+ }
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2017-2025 @polkadot/dev authors & contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import { execViaNode } from './util.mjs';
6
+
7
+ execViaNode('rollup', 'rollup/dist/bin/rollup');
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2017-2025 @polkadot/dev authors & contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import { importDirect } from './util.mjs';
6
+
7
+ await importDirect('tsc', 'typescript/lib/tsc.js');
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ // Copyright 2017-2025 @polkadot/dev authors & contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import { importDirect } from './util.mjs';
6
+
7
+ await importDirect('webpack', 'webpack-cli/bin/cli.js');