Set up comprehensive frontend testing infrastructure

- Install Jest for unit testing with React Testing Library
- Install Playwright for end-to-end testing
- Configure Jest with proper TypeScript support and module mapping
- Create test setup files and utilities for both unit and e2e tests

Components:
* Jest configuration with coverage thresholds
* Playwright configuration with browser automation
* Unit tests for LoginForm, AuthContext, and useSocketIO hook
* E2E tests for authentication, dashboard, and agents workflows
* GitHub Actions workflow for automated testing
* Mock data and API utilities for consistent testing
* Test documentation with best practices

Testing features:
- Unit tests with 70% coverage threshold
- E2E tests with API mocking and user journey testing
- CI/CD integration for automated test runs
- Cross-browser testing support with Playwright
- Authentication system testing end-to-end

🚀 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-07-11 14:06:34 +10:00
parent c6d69695a8
commit aacb45156b
6109 changed files with 777927 additions and 1 deletions

2
frontend/node_modules/napi-postinstall/lib/cli.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};

6
frontend/node_modules/napi-postinstall/lib/cli.js generated vendored Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const index_js_1 = require("./index.js");
void (0, index_js_1.checkAndPreparePackage)(process.argv[2], process.argv[3], ['1', 'check', 'true', 'yes'].includes(process.argv[4]));
//# sourceMappingURL=cli.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,yCAAmD;AAEnD,KAAK,IAAA,iCAAsB,EACzB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EACf,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CACxD,CAAA"}

View File

@@ -0,0 +1,9 @@
import type { PackageJson } from './types.js';
export declare const DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org/";
export declare const meta: PackageJson;
export declare const LOG_PREFIX: string;
export declare const WASM32 = "wasm32";
export declare const WASI = "wasi";
export declare const WASM32_WASI = "wasm32-wasi";
export declare const EABI = "eabi";
export declare const PACKAGE_JSON = "package.json";

View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PACKAGE_JSON = exports.EABI = exports.WASM32_WASI = exports.WASI = exports.WASM32 = exports.LOG_PREFIX = exports.meta = exports.DEFAULT_NPM_REGISTRY = void 0;
const path = require("node:path");
exports.DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org/';
exports.meta = require(path.resolve(__dirname, '../package.json'));
const { name, version } = exports.meta;
exports.LOG_PREFIX = `[${name}@${version}] `;
exports.WASM32 = 'wasm32';
exports.WASI = 'wasi';
exports.WASM32_WASI = `${exports.WASM32}-${exports.WASI}`;
exports.EABI = 'eabi';
exports.PACKAGE_JSON = 'package.json';
//# sourceMappingURL=constants.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAA,kCAAiC;AAIpB,QAAA,oBAAoB,GAAG,6BAA6B,CAAA;AAEpD,QAAA,IAAI,GAAG,OAAO,CACzB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAC5B,CAAA;AAEhB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,YAAI,CAAA;AAEjB,QAAA,UAAU,GAAG,IAAI,IAAI,IAAI,OAAO,IAAI,CAAA;AAEpC,QAAA,MAAM,GAAG,QAAQ,CAAA;AACjB,QAAA,IAAI,GAAG,MAAM,CAAA;AACb,QAAA,WAAW,GAAG,GAAG,cAAM,IAAI,YAAI,EAAE,CAAA;AAEjC,QAAA,IAAI,GAAG,MAAM,CAAA;AAEb,QAAA,YAAY,GAAG,cAAc,CAAA"}

View File

@@ -0,0 +1,2 @@
declare function fallback<T = unknown>(packageJsonPath: string, checkVersion?: boolean): T;
export = fallback;

74
frontend/node_modules/napi-postinstall/lib/fallback.js generated vendored Normal file
View File

@@ -0,0 +1,74 @@
"use strict";
const node_child_process_1 = require("node:child_process");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const constants_js_1 = require("./constants.js");
const helpers_js_1 = require("./helpers.js");
const EXECUTORS = {
npm: 'npx',
pnpm: 'pnpm',
yarn: 'yarn',
bun: 'bun',
deno: (args) => ['deno', 'run', `npm:${args[0]}`, ...args.slice(1)],
};
function constructCommand(value, args) {
const list = typeof value === 'function'
? value(args)
:
[].concat(value, args);
return {
command: list[0],
args: list.slice(1),
};
}
function fallback(packageJsonPath, checkVersion) {
const packageJson = require(packageJsonPath);
const { name, version: pkgVersion, optionalDependencies } = packageJson;
const { napi, version = pkgVersion } = (0, helpers_js_1.getNapiInfoFromPackageJson)(packageJson, checkVersion);
if (checkVersion && pkgVersion !== version) {
throw new Error((0, helpers_js_1.errorMessage)(`Inconsistent package versions found for \`${name}\` v${pkgVersion} vs \`${napi.packageName}\` v${version}.`));
}
if (process.versions.webcontainer) {
const bindingPkgName = `${napi.packageName}-${constants_js_1.WASM32_WASI}`;
if (!optionalDependencies?.[bindingPkgName]) {
throw new Error((0, helpers_js_1.errorMessage)(`\`${constants_js_1.WASM32_WASI}\` target is unavailable for \`${name}\` v${version}`));
}
const baseDir = path.resolve(os.tmpdir(), `${name}-${version}`);
const bindingEntry = path.resolve(baseDir, `node_modules/${bindingPkgName}/${napi.binaryName}.wasi.cjs`);
if (!fs.existsSync(bindingEntry)) {
fs.rmSync(baseDir, { recursive: true, force: true });
fs.mkdirSync(baseDir, { recursive: true });
const bindingPkg = `${bindingPkgName}@${version}`;
console.log((0, helpers_js_1.errorMessage)(`Downloading \`${bindingPkg}\` on WebContainer...`));
(0, node_child_process_1.execFileSync)('pnpm', ['i', bindingPkg], {
cwd: baseDir,
stdio: 'inherit',
});
}
return require(bindingEntry);
}
const userAgent = ((process.env.npm_config_user_agent || '').split('/')[0] ||
'npm');
const executor = EXECUTORS[userAgent];
if (!executor) {
throw new Error((0, helpers_js_1.errorMessage)(`Unsupported package manager: ${userAgent}. Supported managers are: ${Object.keys(EXECUTORS).join(', ')}.`));
}
const { command, args } = constructCommand(executor, [
'napi-postinstall',
name,
version,
checkVersion ? '1' : '0',
]);
const pkgDir = path.dirname(packageJsonPath);
(0, node_child_process_1.execFileSync)(command, args, {
cwd: pkgDir,
stdio: 'inherit',
});
process.env[`SKIP_${name.replace(/-/g, '_').toUpperCase()}_FALLBACK`] = '1';
const PKG_RESOLVED_PATH = require.resolve(pkgDir);
delete require.cache[PKG_RESOLVED_PATH];
return require(pkgDir);
}
module.exports = fallback;
//# sourceMappingURL=fallback.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fallback.js","sourceRoot":"","sources":["../src/fallback.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,13 @@
import type { NapiInfo, PackageJson } from './types.js';
export declare function getGlobalNpmRegistry(): string;
export declare function removeRecursive(dir: string): void;
export declare function downloadedNodePath(name: string, subpath: string): string;
export declare function getNapiInfoFromPackageJson(packageJson: PackageJson, checkVersion: true): NapiInfo & {
version: string;
};
export declare function getNapiInfoFromPackageJson(packageJson: PackageJson, checkVersion?: boolean): NapiInfo;
export declare function getNapiNativeTarget(): string[] | string;
export declare function getNapiNativeTargets(): string[];
export declare function getErrorMessage(err: unknown): string;
export declare function errorLog(message: string, ...args: unknown[]): void;
export declare function errorMessage(message: string, extra?: string): string;

234
frontend/node_modules/napi-postinstall/lib/helpers.js generated vendored Normal file
View File

@@ -0,0 +1,234 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getGlobalNpmRegistry = getGlobalNpmRegistry;
exports.removeRecursive = removeRecursive;
exports.downloadedNodePath = downloadedNodePath;
exports.getNapiInfoFromPackageJson = getNapiInfoFromPackageJson;
exports.getNapiNativeTarget = getNapiNativeTarget;
exports.getNapiNativeTargets = getNapiNativeTargets;
exports.getErrorMessage = getErrorMessage;
exports.errorLog = errorLog;
exports.errorMessage = errorMessage;
const node_child_process_1 = require("node:child_process");
const fs = require("node:fs");
const path = require("node:path");
const constants_js_1 = require("./constants.js");
const target_js_1 = require("./target.js");
function getGlobalNpmRegistry() {
try {
const registry = (0, node_child_process_1.execSync)('npm config get registry', {
encoding: 'utf8',
}).trim();
return registry.endsWith('/') ? registry : `${registry}/`;
}
catch {
return constants_js_1.DEFAULT_NPM_REGISTRY;
}
}
function removeRecursive(dir) {
for (const entry of fs.readdirSync(dir)) {
const entryPath = path.join(dir, entry);
let stats;
try {
stats = fs.lstatSync(entryPath);
}
catch {
continue;
}
if (stats.isDirectory()) {
removeRecursive(entryPath);
}
else {
fs.unlinkSync(entryPath);
}
}
fs.rmdirSync(dir);
}
function downloadedNodePath(name, subpath) {
const pkgLibDir = path.dirname(require.resolve(name + '/package.json'));
return path.join(pkgLibDir, path.basename(subpath));
}
function getNapiInfoFromPackageJson(packageJson, checkVersion) {
const { name, napi: napi_, optionalDependencies } = packageJson;
const targets = napi_?.targets ?? napi_?.triples?.additional;
if (!targets?.length) {
throw new Error(errorMessage(`No \`napi.targets\` nor \`napi.triples.additional\` field found in \`${name}\`'s \`package.json\`. Please ensure the package is built with NAPI support.`));
}
const napi = napi_;
napi.binaryName ?? (napi.binaryName = napi.name);
napi.packageName ?? (napi.packageName = napi.package?.name ?? name);
napi.targets = targets;
if (!optionalDependencies) {
return { napi };
}
let version;
for (const target of targets) {
const { platformArchABI } = (0, target_js_1.parseTriple)(target);
const pkg = `${napi.packageName}-${platformArchABI}`;
const packageVersion = optionalDependencies[pkg];
if (!packageVersion) {
continue;
}
if (version) {
if (checkVersion && version !== packageVersion) {
throw new Error(errorMessage(`Inconsistent package versions found for \`${name}\` with \`${pkg}\` v${packageVersion} vs v${version}.`));
}
}
else if (packageVersion) {
version = packageVersion;
if (!checkVersion) {
break;
}
}
}
return { napi, version };
}
function isMusl() {
let musl = false;
if (process.platform === 'linux') {
musl = isMuslFromFilesystem();
if (musl === null) {
musl = isMuslFromReport();
}
if (musl === null) {
musl = isMuslFromChildProcess();
}
}
return musl;
}
const isFileMusl = (f) => f.includes('libc.musl-') || f.includes('ld-musl-');
function isMuslFromFilesystem() {
try {
return fs.readFileSync('/usr/bin/ldd', 'utf8').includes('musl');
}
catch {
return null;
}
}
function isMuslFromReport() {
let report = null;
if (typeof process.report.getReport === 'function') {
process.report.excludeNetwork = true;
report = process.report.getReport();
}
if (!report) {
return null;
}
if ('header' in report &&
report.header != null &&
typeof report.header === 'object' &&
'glibcVersionRuntime' in report.header &&
report.header.glibcVersionRuntime) {
return false;
}
return ('sharedObjects' in report &&
Array.isArray(report.sharedObjects) &&
report.sharedObjects.some(isFileMusl));
}
function isMuslFromChildProcess() {
try {
return (0, node_child_process_1.execSync)('ldd --version', { encoding: 'utf8' }).includes('musl');
}
catch {
return false;
}
}
function getNapiNativeTarget() {
switch (process.platform) {
case 'android': {
if (process.arch === 'arm64') {
return 'android-arm64';
}
if (process.arch === 'arm') {
return 'android-arm-eabi';
}
break;
}
case 'win32': {
if (process.arch === 'x64') {
return 'win32-x64-msvc';
}
if (process.arch === 'ia32') {
return 'win32-ia32-msvc';
}
if (process.arch === 'arm64') {
return 'win32-arm64-msvc';
}
break;
}
case 'darwin': {
const targets = ['darwin-universal'];
if (process.arch === 'x64') {
targets.push('darwin-x64');
}
else if (process.arch === 'arm64') {
targets.push('darwin-arm64');
}
return targets;
}
case 'freebsd': {
if (process.arch === 'x64') {
return 'freebsd-x64';
}
if (process.arch === 'arm64') {
return 'freebsd-arm64';
}
break;
}
case 'linux': {
if (process.arch === 'x64') {
if (isMusl()) {
return 'linux-x64-musl';
}
return 'linux-x64-gnu';
}
if (process.arch === 'arm64') {
if (isMusl()) {
return 'linux-arm64-musl';
}
return 'linux-arm64-gnu';
}
if (process.arch === 'arm') {
if (isMusl()) {
return 'linux-arm-musleabihf';
}
return 'linux-arm-gnueabihf';
}
if (process.arch === 'riscv64') {
if (isMusl()) {
return 'linux-riscv64-musl';
}
return 'linux-riscv64-gnu';
}
if (process.arch === 'ppc64') {
return 'linux-ppc64-gnu';
}
if (process.arch === 's390x') {
return 'linux-s390x-gnu';
}
break;
}
}
return [];
}
const WASI_TARGET = 'wasm32-wasi';
function getNapiNativeTargets() {
if (process.versions.webcontainer) {
return [WASI_TARGET];
}
const targets = getNapiNativeTarget();
if (Array.isArray(targets)) {
return [...targets, WASI_TARGET];
}
return [targets, WASI_TARGET];
}
function getErrorMessage(err) {
return err?.message || String(err);
}
function errorLog(message, ...args) {
console.error(`${constants_js_1.LOG_PREFIX}${message}`, ...args);
}
function errorMessage(message, extra) {
return `${constants_js_1.LOG_PREFIX}${message}` + (extra ? ': ' + extra : '');
}
//# sourceMappingURL=helpers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,6 @@
import type { PackageJson } from './types.js';
export type * from './types.js';
export declare function isNpm(): boolean | undefined;
export declare function isPnp(): boolean;
export declare function checkAndPreparePackage(packageName: string, version?: string, checkVersion?: boolean): Promise<void>;
export declare function checkAndPreparePackage(packageJson: PackageJson, checkVersion?: boolean): Promise<void>;

240
frontend/node_modules/napi-postinstall/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,240 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isNpm = isNpm;
exports.isPnp = isPnp;
exports.checkAndPreparePackage = checkAndPreparePackage;
const node_child_process_1 = require("node:child_process");
const fs = require("node:fs");
const https = require("node:https");
const path = require("node:path");
const zlib = require("node:zlib");
const constants_js_1 = require("./constants.js");
const helpers_js_1 = require("./helpers.js");
const REDIRECT_STATUS_CODES = new Set([301, 302, 307, 308]);
function fetch(url) {
return new Promise((resolve, reject) => {
https
.get(url, res => {
if (REDIRECT_STATUS_CODES.has(res.statusCode) &&
res.headers.location) {
fetch(res.headers.location).then(resolve, reject);
return;
}
if (res.statusCode !== 200) {
return reject(new Error(`Server responded with ${res.statusCode}`));
}
const chunks = [];
res.on('data', (chunk) => chunks.push(chunk));
res.on('end', () => resolve(Buffer.concat(chunks)));
})
.on('error', reject);
});
}
function extractFileFromTarGzip(buffer, subpath) {
try {
buffer = zlib.unzipSync(buffer);
}
catch (err) {
throw new Error((0, helpers_js_1.errorMessage)(`Invalid gzip data in archive`, (0, helpers_js_1.getErrorMessage)(err)));
}
const str = (i, n) => String.fromCodePoint(...buffer.subarray(i, i + n)).replace(/\0.*$/, '');
let offset = 0;
subpath = `package/${subpath}`;
while (offset < buffer.length) {
const name = str(offset, 100);
const size = Number.parseInt(str(offset + 124, 12), 8);
offset += 512;
if (!Number.isNaN(size)) {
if (name === subpath) {
return buffer.subarray(offset, offset + size);
}
offset += (size + 511) & ~511;
}
}
throw new Error((0, helpers_js_1.errorMessage)(`Could not find \`${subpath}\` in archive`));
}
function isNpm() {
return process.env.npm_config_user_agent?.startsWith('npm/');
}
function isPnp() {
return !!process.versions.pnp;
}
function installUsingNPM(hostPkg, pkg, version, target, subpath, nodePath) {
const isWasm32Wasi = target === constants_js_1.WASM32_WASI;
const env = { ...process.env, npm_config_global: undefined };
const pkgDir = path.dirname(require.resolve(hostPkg + `/${constants_js_1.PACKAGE_JSON}`));
const installDir = path.join(pkgDir, 'npm-install');
try {
fs.mkdirSync(installDir, { recursive: true });
}
catch (err) {
const error = err;
if (error.code === 'EROFS') {
(0, helpers_js_1.errorLog)(`Failed to create the temporary directory on read-only location: ${error.message}`);
(0, helpers_js_1.errorLog)(`You have to install \`${pkg}\` manually in this case.`);
return;
}
throw err;
}
try {
const packageJsonPath = path.join(installDir, constants_js_1.PACKAGE_JSON);
fs.writeFileSync(packageJsonPath, '{}');
(0, node_child_process_1.execSync)(`npm install --loglevel=error --prefer-offline --no-audit --progress=false${isWasm32Wasi ? ` --cpu=${constants_js_1.WASM32} --force` : ''} ${pkg}@${version}`, { cwd: installDir, stdio: 'pipe', env });
if (isWasm32Wasi) {
fs.unlinkSync(packageJsonPath);
}
const nodeModulesDir = path.join(installDir, 'node_modules');
try {
if (isWasm32Wasi) {
const newNodeModulesDir = path.resolve(installDir, '../node_modules');
const dirs = fs.readdirSync(nodeModulesDir);
for (const dir of dirs) {
if (dir.startsWith('@')) {
const newPath = path.join(newNodeModulesDir, dir);
fs.mkdirSync(newPath, { recursive: true });
const subdir = path.join(nodeModulesDir, dir);
const nestedDirs = fs.readdirSync(subdir);
for (const nestedDir of nestedDirs) {
try {
fs.renameSync(path.join(subdir, nestedDir), path.join(newPath, nestedDir));
}
catch {
}
}
}
else {
try {
fs.renameSync(path.join(nodeModulesDir, dir), path.join(newNodeModulesDir, dir));
}
catch {
}
}
}
}
else {
const newPath = path.resolve(pkgDir, hostPkg
.split('/')
.map(() => '..')
.join('/'), pkg);
fs.mkdirSync(newPath, { recursive: true });
fs.renameSync(path.join(nodeModulesDir, pkg), newPath);
}
}
catch {
fs.renameSync(path.join(nodeModulesDir, pkg, subpath), nodePath);
}
}
finally {
try {
(0, helpers_js_1.removeRecursive)(installDir);
}
catch {
}
}
}
async function downloadDirectlyFromNPM(pkg, version, subpath, nodePath) {
const url = `${(0, helpers_js_1.getGlobalNpmRegistry)()}${pkg}/-/${pkg.startsWith('@') ? pkg.split('/')[1] : pkg}-${version}.tgz`;
(0, helpers_js_1.errorLog)(`Trying to download ${JSON.stringify(url)}`);
try {
fs.writeFileSync(nodePath, extractFileFromTarGzip(await fetch(url), subpath));
}
catch (err) {
(0, helpers_js_1.errorLog)(`Failed to download ${JSON.stringify(url)}`, (0, helpers_js_1.getErrorMessage)(err));
throw err;
}
}
async function checkAndPreparePackage(packageNameOrPackageJson, versionOrCheckVersion, checkVersion) {
let packageJson;
if (typeof packageNameOrPackageJson === 'string') {
try {
packageJson = require(packageNameOrPackageJson + `/${constants_js_1.PACKAGE_JSON}`);
}
catch {
if (typeof versionOrCheckVersion !== 'string') {
throw new TypeError((0, helpers_js_1.errorMessage)(`Failed to load \`${constants_js_1.PACKAGE_JSON}\` from \`${packageNameOrPackageJson}\`, please provide a version.`));
}
const pkg = packageNameOrPackageJson;
const packageJsonBuffer = await fetch(`${(0, helpers_js_1.getGlobalNpmRegistry)()}${pkg}/${versionOrCheckVersion}`);
packageJson = JSON.parse(packageJsonBuffer.toString('utf8'));
}
}
else {
packageJson = packageNameOrPackageJson;
if (checkVersion === undefined &&
typeof versionOrCheckVersion === 'boolean') {
checkVersion = versionOrCheckVersion;
}
}
const { name, version: pkgVersion, optionalDependencies } = packageJson;
const { napi, version = pkgVersion } = (0, helpers_js_1.getNapiInfoFromPackageJson)(packageJson, checkVersion);
if (checkVersion && pkgVersion !== version) {
throw new Error((0, helpers_js_1.errorMessage)(`Inconsistent package versions found for \`${name}\` v${pkgVersion} vs \`${napi.packageName}\` v${version}.`));
}
const targets = (0, helpers_js_1.getNapiNativeTargets)();
for (const target of targets) {
const pkg = `${napi.packageName}-${target}`;
if (!optionalDependencies?.[pkg]) {
continue;
}
const isWasm32Wasi = target === constants_js_1.WASM32_WASI;
const binaryPrefix = napi.binaryName ? `${napi.binaryName}.` : '';
const subpath = `${binaryPrefix}${target}.${isWasm32Wasi ? 'wasm' : 'node'}`;
try {
require.resolve(`${pkg}/${subpath}`);
break;
}
catch {
try {
require.resolve(`${name}/${subpath}`);
break;
}
catch { }
if (isPnp()) {
if (isWasm32Wasi) {
try {
(0, node_child_process_1.execSync)(`yarn add -D ${pkg}@${version}`);
}
catch (err) {
(0, helpers_js_1.errorLog)(`Failed to install package \`${pkg}\` automatically in the yarn P'n'P environment`, (0, helpers_js_1.getErrorMessage)(err));
(0, helpers_js_1.errorLog)("You'll have to install it manually in this case.");
}
}
return;
}
if (!isNpm()) {
(0, helpers_js_1.errorLog)(`Failed to find package "${pkg}" on the file system
This can happen if you use the "--no-optional" flag. The "optionalDependencies"
${constants_js_1.PACKAGE_JSON} feature is used by ${name} to install the correct napi binary
for your current platform. This install script will now attempt to work around
this. If that fails, you need to remove the "--no-optional" flag to use ${name}.
`);
}
let nodePath;
try {
nodePath = (0, helpers_js_1.downloadedNodePath)(name, subpath);
}
catch {
const nodeModulesDir = path.resolve(require.resolve(constants_js_1.meta.name + `/${constants_js_1.PACKAGE_JSON}`), '../..');
nodePath = path.join(nodeModulesDir, name, subpath);
fs.mkdirSync(path.dirname(nodePath), { recursive: true });
}
try {
(0, helpers_js_1.errorLog)(`Trying to install package "${pkg}" using npm`);
installUsingNPM(name, pkg, version, target, subpath, nodePath);
break;
}
catch (err) {
(0, helpers_js_1.errorLog)(`Failed to install package "${pkg}" using npm`, (0, helpers_js_1.getErrorMessage)(err));
try {
await downloadDirectlyFromNPM(pkg, version, subpath, nodePath);
break;
}
catch (err) {
throw new Error((0, helpers_js_1.errorMessage)(`Failed to install package "${pkg}"`, (0, helpers_js_1.getErrorMessage)(err)));
}
}
}
}
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
import type { Target } from './types.js';
export declare function parseTriple(rawTriple: string): Target;

56
frontend/node_modules/napi-postinstall/lib/target.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseTriple = parseTriple;
const constants_js_1 = require("./constants.js");
const CpuToNodeArch = {
x86_64: 'x64',
aarch64: 'arm64',
i686: 'ia32',
armv7: 'arm',
riscv64gc: 'riscv64',
powerpc64le: 'ppc64',
};
const SysToNodePlatform = {
linux: 'linux',
freebsd: 'freebsd',
darwin: 'darwin',
windows: 'win32',
};
function parseTriple(rawTriple) {
if (rawTriple === constants_js_1.WASM32_WASI ||
rawTriple === `${constants_js_1.WASM32_WASI}-preview1-threads` ||
rawTriple.startsWith(`${constants_js_1.WASM32}-${constants_js_1.WASI}p`)) {
return {
triple: rawTriple,
platformArchABI: constants_js_1.WASM32_WASI,
platform: constants_js_1.WASI,
arch: constants_js_1.WASM32,
abi: constants_js_1.WASI,
};
}
const triple = rawTriple.endsWith(constants_js_1.EABI)
? `${rawTriple.slice(0, -4)}-${constants_js_1.EABI}`
: rawTriple;
const triples = triple.split('-');
let cpu;
let sys;
let abi = null;
if (triples.length === 2) {
;
[cpu, sys] = triples;
}
else {
;
[cpu, , sys, abi = null] = triples;
}
const platform = SysToNodePlatform[sys] ?? sys;
const arch = CpuToNodeArch[cpu] ?? cpu;
return {
triple: rawTriple,
platformArchABI: abi ? `${platform}-${arch}-${abi}` : `${platform}-${arch}`,
platform,
arch,
abi,
};
}
//# sourceMappingURL=target.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"target.js","sourceRoot":"","sources":["../src/target.ts"],"names":[],"mappings":";;AAqCA,kCA0CC;AA7ED,iDAAgE;AAGhE,MAAM,aAAa,GAA+B;IAChD,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,OAAO;IAChB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,KAAK;IACZ,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,OAAO;CACrB,CAAA;AAED,MAAM,iBAAiB,GAA6B;IAClD,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,OAAO;CACjB,CAAA;AAkBD,SAAgB,WAAW,CAAC,SAAiB;IAC3C,IACE,SAAS,KAAK,0BAAW;QACzB,SAAS,KAAK,GAAG,0BAAW,mBAAmB;QAC/C,SAAS,CAAC,UAAU,CAAC,GAAG,qBAAM,IAAI,mBAAI,GAAG,CAAC,EAC1C,CAAC;QACD,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,eAAe,EAAE,0BAAW;YAC5B,QAAQ,EAAE,mBAAI;YACd,IAAI,EAAE,qBAAM;YACZ,GAAG,EAAE,mBAAI;SACV,CAAA;IACH,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,mBAAI,CAAC;QACrC,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,mBAAI,EAAE;QACrC,CAAC,CAAC,SAAS,CAAA;IACb,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,GAAW,CAAA;IACf,IAAI,GAAW,CAAA;IACf,IAAI,GAAG,GAAkB,IAAI,CAAA;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAGzB,CAAC;QAAA,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,OAAO,CAAA;IACvB,CAAC;SAAM,CAAC;QAKN,CAAC;QAAA,CAAC,GAAG,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,OAAO,CAAA;IACrC,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,IAAK,GAAgB,CAAA;IAC5D,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,IAAK,GAAkB,CAAA;IACtD,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,eAAe,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,IAAI,EAAE;QAC3E,QAAQ;QACR,IAAI;QACJ,GAAG;KACJ,CAAA;AACH,CAAC"}

37
frontend/node_modules/napi-postinstall/lib/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,37 @@
export interface Napi {
binaryName?: string;
name?: string;
packageName?: string;
package?: {
name: string;
};
targets?: string[];
triples?: {
defaults?: boolean;
additional?: string[];
};
wasm?: {
browser?: {
fs?: boolean;
};
};
}
export interface NapiInfo {
napi: Napi;
version?: string;
}
export interface PackageJson {
name: string;
version: string;
optionalDependencies?: Partial<Record<string, string>>;
napi?: Napi;
}
export type Platform = NodeJS.Platform | 'wasi' | 'wasm';
export type NodeJSArch = NodeJS.Architecture | 'universal' | 'wasm32' | 'x32';
export interface Target {
triple: string;
platformArchABI: string;
platform: Platform;
arch: NodeJSArch;
abi: string | null;
}

3
frontend/node_modules/napi-postinstall/lib/types.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}