Initial rebrand: @polkadot -> @pezkuwi (3 packages)

- Package namespace: @polkadot/dev -> @pezkuwi/dev
- Repository: polkadot-js/dev -> pezkuwichain/pezkuwi-dev
- Author: Pezkuwi Team <team@pezkuwichain.io>

Packages:
- @pezkuwi/dev (build tools, linting, CI scripts)
- @pezkuwi/dev-test (test runner)
- @pezkuwi/dev-ts (TypeScript build)

Upstream: polkadot-js/dev v0.83.3
This commit is contained in:
2026-01-05 14:22:47 +03:00
commit 8d28b36f9c
135 changed files with 19232 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { loaderOptions } from './common.js';
loaderOptions.isCached = true;
export * from './index.js';
+32
View File
@@ -0,0 +1,32 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { LoaderOptions } from './types.js';
import path from 'node:path';
import process from 'node:process';
import { pathToFileURL } from 'node:url';
/** The path we are being executed from */
export const CWD_PATH = process.cwd();
/** The cwd path we are being executed from in URL form */
export const CWD_URL = pathToFileURL(`${CWD_PATH}/`);
/** The root path to node_modules (assuming it is in the root) */
export const MOD_PATH = path.join(CWD_PATH, 'node_modules');
/** List of allowed extensions for mappings */
export const EXT_TS_ARRAY = ['.ts', '.tsx'];
/** RegEx for files that we support via this loader */
export const EXT_TS_REGEX = /\.tsx?$/;
/** RegEx for matching JS files (imports map to TS) */
export const EXT_JS_REGEX = /\.jsx?$/;
/** RegEx for json files (as actually aliassed in polkadot-js) */
export const EXT_JSON_REGEX = /\.json$/;
/** Options for loader config */
export const loaderOptions: LoaderOptions = {};
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
// Adapted from: https://nodejs.org/api/esm.html#esm_transpiler_loader
//
// NOTE: This assumes the loader implementation for Node.js >= 18
import { loaderOptions } from './common.js';
loaderOptions.isCached = new URL(import.meta.url).searchParams.get('isCached') === 'true';
export { load } from './loader.js';
export { resolve } from './resolver.js';
+89
View File
@@ -0,0 +1,89 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
import crypto from 'node:crypto';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import ts from 'typescript';
import { EXT_TS_REGEX, loaderOptions } from './common.js';
interface Loaded {
format: 'commonjs' | 'module';
shortCircuit?: boolean;
source: string;
}
type NexLoad = (url: string, context: Record<string, unknown>) => Promise<Loaded>;
/**
* Load all TypeScript files, compile via tsc on-the-fly
**/
export async function load (url: string, context: Record<string, unknown>, nextLoad: NexLoad): Promise<Loaded> {
if (EXT_TS_REGEX.test(url)) {
// used the chained loaders to retrieve
const { source } = await nextLoad(url, {
...context,
format: 'module'
});
// we use a hash of the source to determine caching
const sourceHash = `//# sourceHash=${crypto.createHash('sha256').update(source).digest('hex')}`;
const compiledFile = url.includes('/src/')
? fileURLToPath(
url
.replace(/\.tsx?$/, '.js')
.replace('/src/', '/build-loader/')
)
: null;
if (loaderOptions.isCached && compiledFile && fs.existsSync(compiledFile)) {
const compiled = fs.readFileSync(compiledFile, 'utf-8');
if (compiled.includes(sourceHash)) {
return {
format: 'module',
source: compiled
};
}
}
// compile via typescript
const { outputText } = ts.transpileModule(source.toString(), {
compilerOptions: {
...(
url.endsWith('.tsx')
? { jsx: ts.JsxEmit.ReactJSX }
: {}
),
esModuleInterop: true,
importHelpers: true,
inlineSourceMap: true,
module: ts.ModuleKind.ESNext,
moduleResolution: ts.ModuleResolutionKind.NodeNext,
skipLibCheck: true,
// Aligns with packages/dev/scripts/polkadot-dev-build-ts & packages/dev/config/tsconfig
target: ts.ScriptTarget.ES2022
},
fileName: fileURLToPath(url)
});
if (loaderOptions.isCached && compiledFile) {
const compiledDir = path.dirname(compiledFile);
if (!fs.existsSync(compiledDir)) {
fs.mkdirSync(compiledDir, { recursive: true });
}
fs.writeFileSync(compiledFile, `${outputText}\n${sourceHash}`, 'utf-8');
}
return {
format: 'module',
source: outputText
};
}
return nextLoad(url, context);
}
+6
View File
@@ -0,0 +1,6 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
// Do not edit, auto-generated by @polkadot/dev
export const packageInfo = { name: '@polkadot/dev-ts', path: 'auto', type: 'auto', version: '0.84.2' };
+134
View File
@@ -0,0 +1,134 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
/// <reference types="@polkadot/dev-test/globals.d.ts" />
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import { CWD_PATH } from './common.js';
import { resolveAlias, resolveExtBare, resolveExtJs, resolveExtJson, resolveExtTs } from './resolver.js';
const ROOT_URL = pathToFileURL(`${CWD_PATH}/`);
const SRC_PATH = 'packages/dev/src';
const SRC_URL = pathToFileURL(`${CWD_PATH}/${SRC_PATH}/`);
const INDEX_PATH = `${SRC_PATH}/index.ts`;
const INDEX_URL = pathToFileURL(INDEX_PATH);
describe('resolveExtTs', () => {
it('returns no value for a non .{ts, tsx} extension', () => {
expect(
resolveExtTs(`./${SRC_PATH}/cjs/sample.js`, ROOT_URL)
).not.toBeDefined();
});
it('returns a correct object for a .ts extension', () => {
expect(
resolveExtTs(INDEX_PATH, ROOT_URL)
).toEqual({
format: 'module',
shortCircuit: true,
url: INDEX_URL.href
});
});
});
describe('resolveExtJs', () => {
const modFound = {
format: 'module',
shortCircuit: true,
url: pathToFileURL(`${CWD_PATH}/${SRC_PATH}/mod.ts`).href
};
it('returns the correct value for ./mod.js resolution', () => {
expect(
resolveExtJs('./mod.js', SRC_URL)
).toEqual(modFound);
});
it('returns the correct value for ../mod.js resolution', () => {
expect(
resolveExtJs('../mod.js', pathToFileURL(`${CWD_PATH}/${SRC_PATH}/rootJs/index.ts`))
).toEqual(modFound);
});
it('returns a correct object for a .jsx extension', () => {
expect(
resolveExtJs(`./${SRC_PATH}/rootJs/Jsx.jsx`, ROOT_URL)
).toEqual({
format: 'module',
shortCircuit: true,
url: pathToFileURL(`${SRC_PATH}/rootJs/Jsx.tsx`).href
});
});
});
describe('resolveExtJson', () => {
it('resolves .json files', () => {
expect(
resolveExtJson('../package.json', SRC_URL)
).toEqual({
format: 'json',
shortCircuit: true,
url: pathToFileURL(path.join(SRC_PATH, '../package.json')).href
});
});
});
describe('resolveExtBare', () => {
const indexFound = {
format: 'module',
shortCircuit: true,
url: INDEX_URL.href
};
it('does not resolve non-relative paths', () => {
expect(
resolveExtBare(INDEX_PATH, ROOT_URL)
).not.toBeDefined();
});
it('resolves to the index via .', () => {
expect(
resolveExtBare('.', SRC_URL)
).toEqual(indexFound);
});
it('resolves to the index via ./index', () => {
expect(
resolveExtBare('./index', SRC_URL)
).toEqual(indexFound);
});
it('resolves to the sub-directory via ./rootJs', () => {
expect(
resolveExtBare('./rootJs', SRC_URL)
).toEqual({
format: 'module',
shortCircuit: true,
url: pathToFileURL(`${SRC_PATH}/rootJs/index.ts`).href
});
});
it('resolves to extensionless path', () => {
expect(
resolveExtBare('./packageInfo', SRC_URL)
).toEqual({
format: 'module',
shortCircuit: true,
url: pathToFileURL(`${SRC_PATH}/packageInfo.ts`).href
});
});
});
describe('resolveAliases', () => {
it('resolves packageInfo', () => {
expect(
resolveAlias('@polkadot/dev-ts/packageInfo', ROOT_URL)
).toEqual({
format: 'module',
shortCircuit: true,
url: pathToFileURL('packages/dev-ts/src/packageInfo.ts').href
});
});
});
+224
View File
@@ -0,0 +1,224 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL, URL } from 'node:url';
import { CWD_URL, EXT_JS_REGEX, EXT_JSON_REGEX, EXT_TS_ARRAY, EXT_TS_REGEX } from './common.js';
import { tsAliases } from './tsconfig.js';
interface Resolved {
format: 'commonjs' | 'json' | 'module';
shortCircuit?: boolean;
url: string;
}
interface ResolverContext {
parentURL?: string;
}
type Resolver = (specifier: string, context: ResolverContext) => Resolved | undefined;
/**
* @internal
*
* From a specified URL, extract the actual full path as well as the
* directory that this path reflects (either equivalent to path or the
* root of the file being referenced)
*/
function getParentPath (parentUrl: URL | string): { parentDir: string; parentPath: string; } {
const parentPath = fileURLToPath(parentUrl);
return {
parentDir: fs.existsSync(parentPath) && fs.lstatSync(parentPath).isDirectory()
? parentPath
: path.dirname(parentPath),
parentPath
};
}
/**
* @internal
*
* Resolve fully-specified imports with extensions.
**/
export function resolveExtTs (specifier: string, parentUrl: URL | string): Resolved | void {
// handle .ts extensions directly
if (EXT_TS_REGEX.test(specifier)) {
return {
format: 'module',
shortCircuit: true,
url: new URL(specifier, parentUrl).href
};
}
}
/**
* @internal
*
* Resolve fully-specified imports with extensions. Here we cater for the TS
* mapping of import foo from './bar.js' where only './bar.ts' exists
**/
export function resolveExtJs (specifier: string, parentUrl: URL | string): Resolved | void {
// handle ts imports where import *.js -> *.ts
// (unlike the ts resolution, we only cater for relative paths)
if (specifier.startsWith('.') && EXT_JS_REGEX.test(specifier)) {
const full = fileURLToPath(new URL(specifier, parentUrl));
// when it doesn't exist, we try and see if a source replacement helps
if (!fs.existsSync(full)) {
const found = EXT_TS_ARRAY
.map((e) => full.replace(EXT_JS_REGEX, e))
.find((f) => fs.existsSync(f) && fs.lstatSync(f).isFile());
if (found) {
return {
format: 'module',
shortCircuit: true,
url: pathToFileURL(found).href
};
}
}
}
}
/**
* @internal
*
* Resolution for Json files. Generally these would be via path aliasing.
*/
export function resolveExtJson (specifier: string, parentUrl: URL | string): Resolved | void {
if (specifier.startsWith('.') && EXT_JSON_REGEX.test(specifier)) {
const { parentDir } = getParentPath(parentUrl);
const jsonPath = path.join(parentDir, specifier);
if (fs.existsSync(jsonPath)) {
return {
// .json needs to be in 'json' format for the loader, for the
// the rest (it should only be TS) we use the 'module' format
format: 'json',
shortCircuit: true,
url: pathToFileURL(jsonPath).href
};
}
}
}
/**
* @internal
*
* Resolve relative (extensionless) paths.
*
* At some point we probably might need to extend this to cater for the
* ts (recommended) approach for using .js extensions inside the sources.
* However, since we don't use this in the polkadot-js code, can kick this
* down the line
**/
export function resolveExtBare (specifier: string, parentUrl: URL | string): Resolved | void {
if (specifier.startsWith('.')) {
const { parentDir, parentPath } = getParentPath(parentUrl);
const found = specifier === '.'
? (
// handle . imports for <dir>/index.ts
EXT_TS_ARRAY
.map((e) => path.join(parentDir, `index${e}`))
.find((f) => fs.existsSync(f)) ||
// handle the case where parentUrl needs an extension (generally via alias)
EXT_TS_ARRAY
.map((e) => `${parentPath}${e}`)
.find((f) => fs.existsSync(f))
)
: (
// tests to see if this is a file (without extension)
EXT_TS_ARRAY
.map((e) => path.join(parentDir, `${specifier}${e}`))
.find((f) => fs.existsSync(f)) ||
// test to see if this is a directory
EXT_TS_ARRAY
.map((e) => path.join(parentDir, `${specifier}/index${e}`))
.find((f) => fs.existsSync(f))
);
if (found) {
return {
format: 'module',
shortCircuit: true,
url: pathToFileURL(found).href
};
}
}
}
/**
* @internal
*
* Resolve anything that is not an alias
**/
export function resolveNonAlias (specifier: string, parentUrl: URL | string): Resolved | void {
return (
resolveExtTs(specifier, parentUrl) ||
resolveExtJs(specifier, parentUrl) ||
resolveExtJson(specifier, parentUrl) ||
resolveExtBare(specifier, parentUrl)
);
}
/**
* @internal
*
* Resolve TS alias mappings as defined in the tsconfig.json file
**/
export function resolveAlias (specifier: string, _parentUrl: URL | string, aliases = tsAliases): Resolved | void {
const parts = specifier.split(/[\\/]/);
const found = aliases
// return a [filter, [...partIndex]] mapping
.map((alias) => ({
alias,
indexes: parts
.map((_, i) => i)
.filter((start) =>
(
alias.isWildcard
// parts should have more entries than the wildcard
? parts.length > alias.filter.length
// or the same amount in case of a non-wildcard match
: parts.length === alias.filter.length
) &&
// match all parts of the alias
alias.filter.every((f, i) =>
parts[start + i] &&
parts[start + i] === f
)
)
}))
// we only return the first
.find(({ indexes }) => indexes.length);
if (found) {
// do the actual un-aliased resolution
return resolveNonAlias(
`./${found.alias.path.replace('*', path.join(...parts.slice(found.alias.filter.length)))}`,
found.alias.url
);
}
}
/**
* Resolves a path using our logic.
*
* 1. First we attempt to directly resolve if .ts/.tsx extension is found
* 2. Then we do relative resolves (this is for extension-less .ts files)
* 3. The we try to do resolution via TS aliases
*
* ... finally, try the next loader in the chain
*/
export function resolve (specifier: string, context: ResolverContext, nextResolve: Resolver) {
const parentUrl = context.parentURL || CWD_URL;
return (
resolveNonAlias(specifier, parentUrl) ||
resolveAlias(specifier, parentUrl) ||
nextResolve(specifier, context)
);
}
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
// Adapted from: https://nodejs.org/api/esm.html#esm_transpiler_loader
//
// NOTE: This assumes the loader implementation for Node.js >= 18
import { loaderOptions } from './common.js';
loaderOptions.isCached = true;
export { resolve } from './resolver.js';
export { load } from './testLoader.js';
+92
View File
@@ -0,0 +1,92 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
import crypto from 'node:crypto';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import ts from 'typescript';
import { EXT_TS_REGEX, loaderOptions } from './common.js';
interface Loaded {
format: 'commonjs' | 'module';
shortCircuit?: boolean;
source: string;
}
type NexLoad = (url: string, context: Record<string, unknown>) => Promise<Loaded>;
/**
* Load all TypeScript files, compile via tsc on-the-fly
**/
export async function load (url: string, context: Record<string, unknown>, nextLoad: NexLoad): Promise<Loaded> {
if (EXT_TS_REGEX.test(url)) {
// used the chained loaders to retrieve
const { source } = await nextLoad(url, {
...context,
format: 'module'
});
// This ensures there is support for Node v22 while also maintaining backwards compatibility for testing.
const modifiedSrc = Buffer.from(source.toString().replace(/assert\s*\{\s*type:\s*'json'\s*\}/g, 'with { type: \'json\' }'), 'utf-8');
// we use a hash of the source to determine caching
const sourceHash = `//# sourceHash=${crypto.createHash('sha256').update(modifiedSrc as unknown as string).digest('hex')}`;
const compiledFile = url.includes('/src/')
? fileURLToPath(
url
.replace(/\.tsx?$/, '.js')
.replace('/src/', '/build-loader/')
)
: null;
if (loaderOptions.isCached && compiledFile && fs.existsSync(compiledFile)) {
const compiled = fs.readFileSync(compiledFile, 'utf-8');
if (compiled.includes(sourceHash)) {
return {
format: 'module',
source: compiled
};
}
}
// compile via typescript
const { outputText } = ts.transpileModule(modifiedSrc.toString(), {
compilerOptions: {
...(
url.endsWith('.tsx')
? { jsx: ts.JsxEmit.ReactJSX }
: {}
),
esModuleInterop: true,
importHelpers: true,
inlineSourceMap: true,
module: ts.ModuleKind.ESNext,
moduleResolution: ts.ModuleResolutionKind.NodeNext,
skipLibCheck: true,
// Aligns with packages/dev/scripts/polkadot-dev-build-ts & packages/dev/config/tsconfig
target: ts.ScriptTarget.ES2022
},
fileName: fileURLToPath(url)
});
if (loaderOptions.isCached && compiledFile) {
const compiledDir = path.dirname(compiledFile);
if (!fs.existsSync(compiledDir)) {
fs.mkdirSync(compiledDir, { recursive: true });
}
fs.writeFileSync(compiledFile, `${outputText}\n${sourceHash}`, 'utf-8');
}
return {
format: 'module',
source: outputText
};
}
return nextLoad(url, context);
}
+121
View File
@@ -0,0 +1,121 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { TsAlias } from './types.js';
import JSON5 from 'json5';
import fs from 'node:fs';
import path from 'node:path';
import { pathToFileURL } from 'node:url';
import { CWD_PATH, CWD_URL, MOD_PATH } from './common.js';
interface JsonConfig {
compilerOptions?: {
baseUrl?: string;
paths?: Record<string, string[]>;
};
extends?: string | string[];
}
interface PartialConfig {
paths: Record<string, string[]>;
url?: URL;
}
/**
* @internal
*
* Extracts the (relevant) tsconfig info, also using extends
**/
function readConfigFile (currentPath = CWD_PATH, tsconfig = 'tsconfig.json', fromFile?: string): PartialConfig {
const configFile = path.join(currentPath, tsconfig);
if (!fs.existsSync(configFile)) {
console.warn(`No ${configFile}${fromFile ? ` (extended from ${fromFile})` : ''} found, assuming defaults`);
return { paths: {} };
}
try {
const { compilerOptions, extends: parentConfig } = JSON5.parse<JsonConfig>(fs.readFileSync(configFile, 'utf8'));
let url: URL | undefined;
if (compilerOptions?.baseUrl) {
const configDir = path.dirname(configFile);
// the baseParentUrl is relative to the actual config file
url = pathToFileURL(path.join(configDir, `${compilerOptions.baseUrl}/`));
}
// empty paths if none are found
let paths = compilerOptions?.paths || {};
if (parentConfig) {
const allExtends = Array.isArray(parentConfig)
? parentConfig
: [parentConfig];
for (const extendsPath of allExtends) {
const extRoot = extendsPath.startsWith('.')
? currentPath
: MOD_PATH;
const extSubs = extendsPath.split(/[\\/]/);
const extPath = path.join(extRoot, ...extSubs.slice(0, -1));
const extConfig = readConfigFile(extPath, extSubs.at(-1), configFile);
// base configs are overridden by later configs, order here matters
// FIXME The paths would be relative to the baseUrl at that point... for
// now we don't care much since we define these 2 together in all @polkadot
// configs, but it certainly _may_ create and issue at some point (for others)
paths = { ...extConfig.paths, ...paths };
url = url || extConfig.url;
}
}
return url
? { paths, url }
: { paths };
} catch (error) {
console.error(`FATAL: Error parsing ${configFile}:: ${(error as Error).message}`);
throw error;
}
}
/**
* @internal
*
* Retrieves all TS aliases definitions
**/
function extractAliases (): TsAlias[] {
const { paths, url = CWD_URL } = readConfigFile();
return Object
.entries(paths)
.filter((kv): kv is [string, [string, ...string[]]] => !!kv[1].length)
// TODO The path value is an array - we only handle the first entry in there,
// this is a possible fix into the future if it is ever an issue... (may have
// some impacts on the actual loader where only 1 alias is retrieved)
.map(([key, [path]]) => {
const filter = key.split(/[\\/]/);
const isWildcard = filter.at(-1) === '*';
// ensure that when we have wilcards specified, they always occur in the last position
if (filter.filter((f) => f.includes('*')).length !== (isWildcard ? 1 : 0)) {
throw new Error(`FATAL: Wildcards in tsconfig.json path entries are only supported in the last position. Invalid ${key}: ${path} mapping`);
}
return {
filter: isWildcard
? filter.slice(0, -1)
: filter,
isWildcard,
path,
url
};
});
}
/** We only export the aliases from the config */
export const tsAliases = extractAliases();
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2017-2025 @polkadot/dev-ts authors & contributors
// SPDX-License-Identifier: Apache-2.0
export interface TsAlias {
filter: string[];
isWildcard?: boolean;
path: string;
url: URL;
}
export interface LoaderOptions {
isCached?: boolean;
}