@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,540 @@
1
+ // Copyright 2017-2025 @polkadot/dev authors & contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import cp from 'node:child_process';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import process from 'node:process';
8
+ import url from 'node:url';
9
+
10
+ /** @internal logging */
11
+ const BLANK = ''.padStart(75);
12
+
13
+ /** CJS/ESM compatible __dirname */
14
+ export const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
15
+
16
+ /** Deno prefix for externals */
17
+ export const DENO_EXT_PRE = 'https://esm.sh';
18
+
19
+ /** Deno prefix for built-ins */
20
+ export const DENO_LND_PRE = 'https://deno.land';
21
+
22
+ /** Deno prefix for the polkadot package */
23
+ export const DENO_POL_PRE = `${DENO_LND_PRE}/x/polkadot`;
24
+
25
+ /** The GH user that we use for actions */
26
+ export const GITHUB_USER = 'github-actions[bot]';
27
+
28
+ /** The GH email for actions */
29
+ export const GITHUB_MAIL = '41898282+github-actions[bot]@users.noreply.github.com';
30
+
31
+ /** The GH repo link */
32
+ export const GITHUB_REPO = process.env['GITHUB_REPOSITORY'];
33
+
34
+ /** The GH token */
35
+ export const GITHUB_TOKEN = process.env['GH_PAT'];
36
+
37
+ /** The GH repo URL */
38
+ export const GITHUB_TOKEN_URL = `https://${GITHUB_TOKEN}@github.com`;
39
+
40
+ /** Paths that we generally building to (catch-all for possible usages) */
41
+ export const PATHS_BUILD = ['', '-cjs', '-esm'].reduce((r, a) => r.concat(['', '-babel', '-esbuild', '-swc', '-tsc'].map((b) => `${b}${a}`)), ['-deno', '-docs', '-loader', '-wasm']).sort();
42
+
43
+ /** Paths that are generally excluded from source operations */
44
+ export const PATHS_EXCL = ['node_modules', ...PATHS_BUILD.map((e) => `build${e}`)];
45
+
46
+ /**
47
+ * Copy a file to a target dir
48
+ *
49
+ * @param {string | string[]} src
50
+ * @param {string} destDir
51
+ **/
52
+ export function copyFileSync (src, destDir) {
53
+ if (Array.isArray(src)) {
54
+ src.forEach((s) => copyFileSync(s, destDir));
55
+ } else {
56
+ fs.copyFileSync(src, path.join(destDir, path.basename(src)));
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Recursively copies a directory to a target dir
62
+ *
63
+ * @param {string | string[]} src
64
+ * @param {string} dest
65
+ * @param {string[]} [include]
66
+ * @param {string[]} [exclude]
67
+ **/
68
+ export function copyDirSync (src, dest, include, exclude) {
69
+ if (Array.isArray(src)) {
70
+ src.forEach((s) => copyDirSync(s, dest, include, exclude));
71
+ } else if (!fs.existsSync(src)) {
72
+ // it doesn't exist, so we have nothing to copy
73
+ } else if (!fs.statSync(src).isDirectory()) {
74
+ exitFatal(`Source ${src} should be a directory`);
75
+ } else {
76
+ mkdirpSync(dest);
77
+
78
+ fs
79
+ .readdirSync(src)
80
+ .forEach((file) => {
81
+ const srcPath = path.join(src, file);
82
+
83
+ if (fs.statSync(srcPath).isDirectory()) {
84
+ copyDirSync(srcPath, path.join(dest, file), include, exclude);
85
+ } else if (!include?.length || include.some((e) => file.endsWith(e))) {
86
+ if (!exclude || !exclude.some((e) => file.endsWith(e))) {
87
+ copyFileSync(srcPath, dest);
88
+ }
89
+ }
90
+ });
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Creates a deno directory name
96
+ *
97
+ * @param {string} name
98
+ * @returns {string}
99
+ **/
100
+ export function denoCreateDir (name) {
101
+ // aligns with name above - since we have sub-paths, we only return
102
+ // the actual path inside packages/* (i.e. the last part of the name)
103
+ return name.replace('@polkadot/', '');
104
+ }
105
+
106
+ /**
107
+ * @internal
108
+ *
109
+ * Adjusts the engine setting, highest of current and requested
110
+ *
111
+ * @param {string} [a]
112
+ * @param {string} [b]
113
+ * @returns {number}
114
+ */
115
+ export function engineVersionCmp (a, b) {
116
+ const aVer = engineVersionSplit(a);
117
+ const bVer = engineVersionSplit(b);
118
+
119
+ for (let i = 0; i < 3; i++) {
120
+ if (aVer[i] < bVer[i]) {
121
+ return -1;
122
+ } else if (aVer[i] > bVer[i]) {
123
+ return 1;
124
+ }
125
+ }
126
+
127
+ return 0;
128
+ }
129
+
130
+ /**
131
+ * @internal
132
+ *
133
+ * Splits a engines version, i.e. >=xx(.yy) into
134
+ * the major/minor/patch parts
135
+ *
136
+ * @param {string} [ver]
137
+ * @returns {[number, number, number]}
138
+ */
139
+ export function engineVersionSplit (ver) {
140
+ const parts = (ver || '>=0')
141
+ .replace('v', '') // process.version returns v18.14.0
142
+ .replace('>=', '') // engines have >= prefix
143
+ .split('.')
144
+ .map((e) => e.trim());
145
+
146
+ return [parseInt(parts[0] || '0', 10), parseInt(parts[1] || '0', 10), parseInt(parts[2] || '0', 10)];
147
+ }
148
+
149
+ /**
150
+ * Process execution
151
+ *
152
+ * @param {string} cmd
153
+ * @param {boolean} [noLog]
154
+ **/
155
+ export function execSync (cmd, noLog) {
156
+ const exec = cmd
157
+ .replace(/ {2}/g, ' ')
158
+ .trim();
159
+
160
+ if (!noLog) {
161
+ logBin(exec, true);
162
+ }
163
+
164
+ cp.execSync(exec, { stdio: 'inherit' });
165
+ }
166
+
167
+ /**
168
+ * Node execution with ts support
169
+ *
170
+ * @param {string} cmd
171
+ * @param {string[]} [nodeFlags]
172
+ * @param {boolean} [noLog]
173
+ * @param {string} [loaderPath]
174
+ **/
175
+ export function execNodeTs (cmd, nodeFlags = [], noLog, loaderPath = '@polkadot/dev-ts/cached') {
176
+ const loadersGlo = [];
177
+ const loadersLoc = [];
178
+ const otherFlags = [];
179
+
180
+ for (let i = 0; i < nodeFlags.length; i++) {
181
+ const flag = nodeFlags[i];
182
+
183
+ if (['--import', '--loader', '--require'].includes(flag)) {
184
+ const arg = nodeFlags[++i];
185
+
186
+ // We split the loader arguments based on type in execSync. The
187
+ // split here is to extract the various provided types:
188
+ //
189
+ // 1. Global loaders are added first, then
190
+ // 2. Our specific dev-ts loader is added, then
191
+ // 3. Any provided local loaders are added
192
+ //
193
+ // The ordering requirement here is driven from the use of global
194
+ // loaders inside the apps repo (specifically extensionless), while
195
+ // ensuring we don't break local loader usage in the wasm repo
196
+ if (arg.startsWith('.')) {
197
+ loadersLoc.push(flag);
198
+ loadersLoc.push(arg);
199
+ } else {
200
+ loadersGlo.push(flag);
201
+ loadersGlo.push(arg);
202
+ }
203
+ } else {
204
+ otherFlags.push(flag);
205
+ }
206
+ }
207
+
208
+ execSync(`${process.execPath} ${otherFlags.join(' ')} --no-warnings --enable-source-maps ${loadersGlo.join(' ')} --loader ${loaderPath} ${loadersLoc.join(' ')} ${cmd}`, noLog);
209
+ }
210
+
211
+ /**
212
+ * Execute the git command
213
+ *
214
+ * @param {string} cmd
215
+ * @param {boolean} [noLog]
216
+ **/
217
+ export function execGit (cmd, noLog) {
218
+ execSync(`git ${cmd}`, noLog);
219
+ }
220
+
221
+ /**
222
+ * Execute the package manager (yarn by default)
223
+ *
224
+ * @param {string} cmd
225
+ * @param {boolean} [noLog]
226
+ **/
227
+ export function execPm (cmd, noLog) {
228
+ // It could be possible to extends this to npm/pnpm, but the package manager
229
+ // arguments are not quite the same between them, so we may need to do mangling
230
+ // and adjust to convert yarn-isms to the specific target.
231
+ //
232
+ // Instead of defaulting here, we could possibly use process.env['npm_execpath']
233
+ // to determine the package manager which would work in most (???) cases where the
234
+ // top-level has been executed via a package manager and the env is set - no bets
235
+ // atm for what happens when execSync/fork is used
236
+ //
237
+ // TL;DR Not going to spend effort on this, but quite possibly there is an avenue
238
+ // to support other package managers, aka pick-your-poison
239
+ execSync(`yarn ${cmd}`, noLog);
240
+ }
241
+
242
+ /**
243
+ * Node binary execution
244
+ *
245
+ * @param {string} name
246
+ * @param {string} cmd
247
+ **/
248
+ export function execViaNode (name, cmd) {
249
+ logBin(name);
250
+
251
+ execSync(`${importPath(cmd)} ${process.argv.slice(2).join(' ')}`, true);
252
+ }
253
+
254
+ /** A consistent setup for git variables */
255
+ export function gitSetup () {
256
+ execGit(`config user.name "${GITHUB_USER}"`);
257
+ execGit(`config user.email "${GITHUB_MAIL}"`);
258
+
259
+ execGit('config push.default simple');
260
+ execGit('config merge.ours.driver true');
261
+
262
+ execGit('checkout master');
263
+ }
264
+
265
+ /**
266
+ * Create an absolute import path into node_modules from a
267
+ * <this module> module name
268
+ *
269
+ * @param {string} req
270
+ * @returns {string}
271
+ **/
272
+ export function importPath (req) {
273
+ return path.join(process.cwd(), 'node_modules', req);
274
+ }
275
+
276
+ /**
277
+ * Do an async import
278
+ *
279
+ * @param {string} bin
280
+ * @param {string} req
281
+ * @returns {Promise<any>}
282
+ **/
283
+ export async function importDirect (bin, req) {
284
+ logBin(bin);
285
+
286
+ try {
287
+ const mod = await import(req);
288
+
289
+ return mod;
290
+ } catch (/** @type {any} */ error) {
291
+ exitFatal(`Error importing ${req}`, error);
292
+ }
293
+ }
294
+
295
+ /**
296
+ * Do a relative async import
297
+ *
298
+ * @param {string} bin
299
+ * @param {string} req
300
+ * @returns {Promise<any>}
301
+ **/
302
+ export function importRelative (bin, req) {
303
+ return importDirect(bin, importPath(req));
304
+ }
305
+
306
+ /**
307
+ * Logs the binary name with the calling args
308
+ *
309
+ * @param {string} bin
310
+ * @param {boolean} [noArgs]
311
+ */
312
+ export function logBin (bin, noArgs) {
313
+ const extra = noArgs
314
+ ? ''
315
+ : process.argv.slice(2).join(' ');
316
+
317
+ console.log(`$ ${bin} ${extra}`.replace(/ {2}/g, ' ').trim());
318
+ }
319
+
320
+ /**
321
+ * Do a mkdirp (no global support, native)
322
+ *
323
+ * @param {string} dir
324
+ **/
325
+ export function mkdirpSync (dir) {
326
+ fs.mkdirSync(dir, { recursive: true });
327
+ }
328
+
329
+ /**
330
+ * Delete the ful path (no glob support)
331
+ *
332
+ * @param {string} dir
333
+ **/
334
+ export function rimrafSync (dir) {
335
+ if (fs.existsSync(dir)) {
336
+ fs.rmSync(dir, { force: true, recursive: true });
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Recursively reads a directory, making a list of the matched extensions
342
+ *
343
+ * @param {string} src
344
+ * @param {string[]} extensions
345
+ * @param {string[]} [files]
346
+ **/
347
+ export function readdirSync (src, extensions, files = []) {
348
+ if (!fs.statSync(src).isDirectory()) {
349
+ exitFatal(`Source ${src} should be a directory`);
350
+ }
351
+
352
+ fs
353
+ .readdirSync(src)
354
+ .forEach((file) => {
355
+ const srcPath = path.join(src, file);
356
+
357
+ if (fs.statSync(srcPath).isDirectory()) {
358
+ if (!PATHS_EXCL.includes(file)) {
359
+ readdirSync(srcPath, extensions, files);
360
+ }
361
+ } else if (extensions.some((e) => file.endsWith(e))) {
362
+ files.push(srcPath);
363
+ }
364
+ });
365
+
366
+ return files;
367
+ }
368
+
369
+ /**
370
+ * Prints the fatal error message and exit with a non-zero return code
371
+ *
372
+ * @param {string} message
373
+ * @param {Error} [error]
374
+ * @returns {never}
375
+ **/
376
+ export function exitFatal (message, error) {
377
+ console.error();
378
+ console.error('FATAL:', message);
379
+
380
+ if (error) {
381
+ console.error();
382
+ console.error(error);
383
+ }
384
+
385
+ console.error();
386
+ process.exit(1);
387
+ }
388
+
389
+ /**
390
+ * Checks for Node version with a fatal exit code
391
+ */
392
+ export function exitFatalEngine () {
393
+ const pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'));
394
+
395
+ if (engineVersionCmp(process.version, pkg.engines?.node) === -1) {
396
+ console.error(
397
+ `${BLANK}\n FATAL: At least Node version ${pkg.engines.node} is required for development.\n${BLANK}`
398
+ );
399
+
400
+ console.error(`
401
+ Technical explanation: For a development environment all projects in
402
+ the @polkadot famility uses node:test in their operation. Currently the
403
+ minimum required version of Node is thus set at the first first version
404
+ with operational support, hence this limitation. Additionally only LTS
405
+ Node versions are supported.
406
+
407
+ LTS Node versions are detailed on https://nodejs.dev/en/about/releases/
408
+
409
+ `);
410
+
411
+ process.exit(1);
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Checks for yarn usage with a fatal exit code
417
+ */
418
+ export function exitFatalYarn () {
419
+ if (!process.env['npm_execpath']?.includes('yarn')) {
420
+ console.error(
421
+ `${BLANK}\n FATAL: The use of yarn is required, install via npm is not supported.\n${BLANK}`
422
+ );
423
+ console.error(`
424
+ Technical explanation: All the projects in the @polkadot' family use
425
+ yarn specific configs and assume yarn for build operations and locks.
426
+
427
+ If yarn is not available, you can get it from https://yarnpkg.com/
428
+
429
+ `);
430
+
431
+ process.exit(1);
432
+ }
433
+ }
434
+
435
+ /**
436
+ * Topological sort of dependencies. It handles circular deps by placing them at the end
437
+ * of the sorted array from circular dep with the smallest vertices to the greatest vertices.
438
+ *
439
+ * Credit to: https://gist.github.com/shinout/1232505 (Parts of this were used as a starting point for the structure of the topoSort)
440
+ *
441
+ * @param {string[]} dirs
442
+ */
443
+ export function topoSort (dirs) {
444
+ /** @type {Record<string, Node>} */
445
+ const nodes = {};
446
+ /** @type {string[]} */
447
+ const sorted = [];
448
+ /** @type {Record<string, boolean>} */
449
+ const visited = {};
450
+ /** @type {Record<string, Node>} */
451
+ const circular = {};
452
+
453
+ if (dirs.length === 1) {
454
+ return dirs;
455
+ }
456
+
457
+ class Node {
458
+ /** @param {string} id */
459
+ constructor (id) {
460
+ this.id = id;
461
+ /** @type {string[]} */
462
+ this.vertices = [];
463
+ }
464
+ }
465
+
466
+ /**
467
+ * @param {*} key
468
+ * @param {string[]} ancestors
469
+ * @returns
470
+ */
471
+ function cb (key, ancestors) {
472
+ const node = nodes[key];
473
+ const id = node.id;
474
+
475
+ if (visited[key]) {
476
+ return;
477
+ }
478
+
479
+ ancestors.push(id);
480
+ visited[key] = true;
481
+
482
+ node.vertices.forEach((i) => {
483
+ if (ancestors.indexOf(i) >= 0) {
484
+ console.log('CIRCULAR: closed chain : ' + i + ' is in ' + id);
485
+
486
+ if (nodes[id].vertices.includes(i)) {
487
+ circular[id] = nodes[id];
488
+ }
489
+
490
+ circular[i] = nodes[i];
491
+ }
492
+
493
+ cb(i.toString(), ancestors.map((v) => v));
494
+ });
495
+
496
+ if (!circular[id]) {
497
+ sorted.push(id);
498
+ }
499
+ }
500
+
501
+ // Build edges
502
+ const edges = dirs.map((dir) => {
503
+ const json = fs.readFileSync(path.join('packages', dir, 'package.json'), 'utf8');
504
+ const deps = JSON.parse(json).dependencies;
505
+
506
+ return dirs
507
+ .filter((d) => d !== dir && deps && Object.keys(deps).includes(`@polkadot/${d}`))
508
+ .map((d) => [dir, d]);
509
+ }).flat();
510
+
511
+ edges.forEach((v) => {
512
+ const from = v[0]; const to = v[1];
513
+
514
+ if (!nodes[from]) {
515
+ nodes[from] = new Node(from);
516
+ }
517
+
518
+ if (!nodes[to]) {
519
+ nodes[to] = new Node(to);
520
+ }
521
+
522
+ nodes[from].vertices.push(to);
523
+ });
524
+
525
+ const keys = Object.keys(nodes);
526
+
527
+ for (const key of keys) {
528
+ cb(key, []);
529
+ }
530
+
531
+ const circularSorted = Object.keys(circular)
532
+ .sort((a, b) => circular[a].vertices.length < circular[b].vertices.length ? -1 : 1);
533
+
534
+ const flattenedEdges = edges.flat();
535
+ // Packages that have no edges
536
+ /** @type {string[]} */
537
+ const standAlones = dirs.filter((d) => !flattenedEdges.includes(d));
538
+
539
+ return sorted.concat(circularSorted).concat(standAlones);
540
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "..",
5
+ "outDir": "./build",
6
+ "rootDir": "./src"
7
+ },
8
+ "exclude": [
9
+ "**/mod.ts",
10
+ "**/*.spec.ts",
11
+ "**/*.spec.tsx"
12
+ ],
13
+ "include": [
14
+ "src/**/*",
15
+ "src/**/*.json"
16
+ ],
17
+ "references": []
18
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "..",
5
+ "outDir": "./build",
6
+ "rootDir": "./config",
7
+ "emitDeclarationOnly": false,
8
+ "noEmit": true
9
+ },
10
+ "include": [
11
+ "config/**/*"
12
+ ],
13
+ "references": []
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "..",
5
+ "outDir": "./build",
6
+ "rootDir": "./scripts",
7
+ "emitDeclarationOnly": false,
8
+ "noEmit": true
9
+ },
10
+ "include": [
11
+ "scripts/**/*"
12
+ ],
13
+ "references": []
14
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "baseUrl": "..",
5
+ "outDir": "./build",
6
+ "rootDir": "./src",
7
+ "emitDeclarationOnly": false,
8
+ "noEmit": true
9
+ },
10
+ "include": [
11
+ "**/*.spec.ts",
12
+ "**/*.spec.tsx"
13
+ ],
14
+ "references": [
15
+ { "path": "../dev/tsconfig.build.json" },
16
+ { "path": "../dev-test/tsconfig.build.json" }
17
+ ]
18
+ }