WIP: bootstrap and partial real Solana watcher implementation
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"name": "chalk",
|
||||
"version": "5.6.2",
|
||||
"description": "Terminal string styling done right",
|
||||
"license": "MIT",
|
||||
"repository": "chalk/chalk",
|
||||
"funding": "https://github.com/chalk/chalk?sponsor=1",
|
||||
"type": "module",
|
||||
"main": "./source/index.js",
|
||||
"exports": "./source/index.js",
|
||||
"imports": {
|
||||
"#ansi-styles": "./source/vendor/ansi-styles/index.js",
|
||||
"#supports-color": {
|
||||
"node": "./source/vendor/supports-color/index.js",
|
||||
"default": "./source/vendor/supports-color/browser.js"
|
||||
}
|
||||
},
|
||||
"types": "./source/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && c8 ava && tsd",
|
||||
"bench": "matcha benchmark.js"
|
||||
},
|
||||
"files": [
|
||||
"source",
|
||||
"!source/index.test-d.ts"
|
||||
],
|
||||
"keywords": [
|
||||
"color",
|
||||
"colour",
|
||||
"colors",
|
||||
"terminal",
|
||||
"console",
|
||||
"cli",
|
||||
"string",
|
||||
"ansi",
|
||||
"style",
|
||||
"styles",
|
||||
"tty",
|
||||
"formatting",
|
||||
"rgb",
|
||||
"256",
|
||||
"shell",
|
||||
"xterm",
|
||||
"log",
|
||||
"logging",
|
||||
"command-line",
|
||||
"text"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.10",
|
||||
"ava": "^3.15.0",
|
||||
"c8": "^7.10.0",
|
||||
"color-convert": "^2.0.1",
|
||||
"execa": "^6.0.0",
|
||||
"log-update": "^5.0.0",
|
||||
"matcha": "^0.7.0",
|
||||
"tsd": "^0.19.0",
|
||||
"xo": "^0.57.0",
|
||||
"yoctodelay": "^2.0.0"
|
||||
},
|
||||
"xo": {
|
||||
"rules": {
|
||||
"unicorn/prefer-string-slice": "off",
|
||||
"@typescript-eslint/consistent-type-imports": "off",
|
||||
"@typescript-eslint/consistent-type-exports": "off",
|
||||
"@typescript-eslint/consistent-type-definitions": "off",
|
||||
"unicorn/expiring-todo-comments": "off"
|
||||
}
|
||||
},
|
||||
"c8": {
|
||||
"reporter": [
|
||||
"text",
|
||||
"lcov"
|
||||
],
|
||||
"exclude": [
|
||||
"source/vendor"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { isBuiltin } from 'node:module';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import { resolve } from 'pathe';
|
||||
import { ModuleRunner, EvaluatedModules } from 'vite/module-runner';
|
||||
import { b as VitestTransport } from './startVitestModuleRunner.DB-7oCpn.js';
|
||||
import { e as environments } from './index.DC7d2Pf8.js';
|
||||
import { serializeValue } from '@vitest/utils/serialize';
|
||||
import { serializeError } from '@vitest/utils/error';
|
||||
import { disableDefaultColors } from 'tinyrainbow';
|
||||
import { T as Traces } from './traces.DT5aQ62U.js';
|
||||
import { o as onCancel, a as rpcDone, c as createRuntimeRpc } from './rpc.MzXet3jl.js';
|
||||
import { createStackString, parseStacktrace } from '@vitest/utils/source-map';
|
||||
import { s as setupInspect } from './inspector.CvyFGlXm.js';
|
||||
import { V as VitestEvaluatedModules } from './evaluatedModules.Dg1zASAC.js';
|
||||
import { E as EnvironmentTeardownError } from './utils.BX5Fg8C4.js';
|
||||
|
||||
function isBuiltinEnvironment(env) {
|
||||
return env in environments;
|
||||
}
|
||||
const isWindows = process.platform === "win32";
|
||||
const _loaders = /* @__PURE__ */ new Map();
|
||||
function createEnvironmentLoader(root, rpc) {
|
||||
const cachedLoader = _loaders.get(root);
|
||||
if (!cachedLoader || cachedLoader.isClosed()) {
|
||||
_loaders.delete(root);
|
||||
const moduleRunner = new ModuleRunner({
|
||||
hmr: false,
|
||||
sourcemapInterceptor: "prepareStackTrace",
|
||||
transport: new VitestTransport({
|
||||
async fetchModule(id, importer, options) {
|
||||
const result = await rpc.fetch(id, importer, "__vitest__", options);
|
||||
if ("cached" in result) return {
|
||||
code: readFileSync(result.tmp, "utf-8"),
|
||||
...result
|
||||
};
|
||||
if (isWindows && "externalize" in result)
|
||||
// TODO: vitest returns paths for external modules, but Vite returns file://
|
||||
// https://github.com/vitejs/vite/pull/20449
|
||||
result.externalize = isBuiltin(id) || /^(?:node:|data:|http:|https:|file:)/.test(id) ? result.externalize : pathToFileURL(result.externalize).toString();
|
||||
return result;
|
||||
},
|
||||
async resolveId(id, importer) {
|
||||
return rpc.resolve(id, importer, "__vitest__");
|
||||
}
|
||||
}, new EvaluatedModules(), /* @__PURE__ */ new WeakMap())
|
||||
});
|
||||
_loaders.set(root, moduleRunner);
|
||||
}
|
||||
return _loaders.get(root);
|
||||
}
|
||||
async function loadNativeEnvironment(name, root, traces) {
|
||||
const packageId = name[0] === "." || name[0] === "/" ? pathToFileURL(resolve(root, name)).toString() : import.meta.resolve(`vitest-environment-${name}`, pathToFileURL(root).toString());
|
||||
return resolveEnvironmentFromModule(name, packageId, await traces.$("vitest.runtime.environment.import", () => import(packageId)));
|
||||
}
|
||||
function resolveEnvironmentFromModule(name, packageId, pkg) {
|
||||
if (!pkg || !pkg.default || typeof pkg.default !== "object") throw new TypeError(`Environment "${name}" is not a valid environment. Path "${packageId}" should export default object with a "setup" or/and "setupVM" method.`);
|
||||
const environment = pkg.default;
|
||||
if (environment.transformMode != null && environment.transformMode !== "web" && environment.transformMode !== "ssr") throw new TypeError(`Environment "${name}" is not a valid environment. Path "${packageId}" should export default object with a "transformMode" method equal to "ssr" or "web", received "${environment.transformMode}".`);
|
||||
if (environment.transformMode) {
|
||||
console.warn(`The Vitest environment ${environment.name} defines the "transformMode". This options was deprecated in Vitest 4 and will be removed in the next major version. Please, use "viteEnvironment" instead.`);
|
||||
// keep for backwards compat
|
||||
environment.viteEnvironment ??= environment.transformMode === "ssr" ? "ssr" : "client";
|
||||
}
|
||||
return environment;
|
||||
}
|
||||
async function loadEnvironment(name, root, rpc, traces, viteModuleRunner) {
|
||||
if (isBuiltinEnvironment(name)) return { environment: environments[name] };
|
||||
if (!viteModuleRunner) return { environment: await loadNativeEnvironment(name, root, traces) };
|
||||
const loader = createEnvironmentLoader(root, rpc);
|
||||
const packageId = name[0] === "." || name[0] === "/" ? resolve(root, name) : (await traces.$("vitest.runtime.environment.resolve", () => rpc.resolve(`vitest-environment-${name}`, void 0, "__vitest__")))?.id ?? resolve(root, name);
|
||||
return {
|
||||
environment: resolveEnvironmentFromModule(name, packageId, await traces.$("vitest.runtime.environment.import", () => loader.import(packageId))),
|
||||
loader
|
||||
};
|
||||
}
|
||||
|
||||
const cleanupListeners = /* @__PURE__ */ new Set();
|
||||
const moduleRunnerListeners = /* @__PURE__ */ new Set();
|
||||
function onCleanup(cb) {
|
||||
cleanupListeners.add(cb);
|
||||
}
|
||||
async function cleanup() {
|
||||
await Promise.all([...cleanupListeners].map((l) => l()));
|
||||
}
|
||||
function onModuleRunner(cb) {
|
||||
moduleRunnerListeners.add(cb);
|
||||
}
|
||||
function emitModuleRunner(moduleRunner) {
|
||||
moduleRunnerListeners.forEach((l) => l(moduleRunner));
|
||||
}
|
||||
|
||||
// Store globals in case tests overwrite them
|
||||
const processListeners = process.listeners.bind(process);
|
||||
const processOn = process.on.bind(process);
|
||||
const processOff = process.off.bind(process);
|
||||
const dispose = [];
|
||||
function listenForErrors(state) {
|
||||
dispose.forEach((fn) => fn());
|
||||
dispose.length = 0;
|
||||
function catchError(err, type, event) {
|
||||
const worker = state();
|
||||
// if there is another listener, assume that it's handled by user code
|
||||
// one is Vitest's own listener
|
||||
if (processListeners(event).length > 1) return;
|
||||
const error = serializeValue(err);
|
||||
if (typeof error === "object" && error != null) {
|
||||
error.VITEST_TEST_NAME = worker.current?.type === "test" ? worker.current.name : void 0;
|
||||
if (worker.filepath) error.VITEST_TEST_PATH = worker.filepath;
|
||||
}
|
||||
state().rpc.onUnhandledError(error, type);
|
||||
}
|
||||
const uncaughtException = (e) => catchError(e, "Uncaught Exception", "uncaughtException");
|
||||
const unhandledRejection = (e) => catchError(e, "Unhandled Rejection", "unhandledRejection");
|
||||
processOn("uncaughtException", uncaughtException);
|
||||
processOn("unhandledRejection", unhandledRejection);
|
||||
dispose.push(() => {
|
||||
processOff("uncaughtException", uncaughtException);
|
||||
processOff("unhandledRejection", unhandledRejection);
|
||||
});
|
||||
}
|
||||
|
||||
const resolvingModules = /* @__PURE__ */ new Set();
|
||||
async function execute(method, ctx, worker, traces) {
|
||||
const prepareStart = performance.now();
|
||||
const cleanups = [setupInspect(ctx)];
|
||||
// RPC is used to communicate between worker (be it a thread worker or child process or a custom implementation) and the main thread
|
||||
const rpc = ctx.rpc;
|
||||
try {
|
||||
// do not close the RPC channel so that we can get the error messages sent to the main thread
|
||||
cleanups.push(async () => {
|
||||
await Promise.all(rpc.$rejectPendingCalls(({ method, reject }) => {
|
||||
reject(new EnvironmentTeardownError(`[vitest-worker]: Closing rpc while "${method}" was pending`));
|
||||
}));
|
||||
});
|
||||
const state = {
|
||||
ctx,
|
||||
evaluatedModules: new VitestEvaluatedModules(),
|
||||
resolvingModules,
|
||||
moduleExecutionInfo: /* @__PURE__ */ new Map(),
|
||||
config: ctx.config,
|
||||
environment: null,
|
||||
durations: {
|
||||
environment: 0,
|
||||
prepare: prepareStart
|
||||
},
|
||||
rpc,
|
||||
onCancel,
|
||||
onCleanup: onCleanup,
|
||||
providedContext: ctx.providedContext,
|
||||
onFilterStackTrace(stack) {
|
||||
return createStackString(parseStacktrace(stack));
|
||||
},
|
||||
metaEnv: createImportMetaEnvProxy()
|
||||
};
|
||||
const methodName = method === "collect" ? "collectTests" : "runTests";
|
||||
if (!worker[methodName] || typeof worker[methodName] !== "function") throw new TypeError(`Test worker should expose "runTests" method. Received "${typeof worker.runTests}".`);
|
||||
await worker[methodName](state, traces);
|
||||
} finally {
|
||||
await rpcDone().catch(() => {});
|
||||
await Promise.all(cleanups.map((fn) => fn())).catch(() => {});
|
||||
}
|
||||
}
|
||||
function run(ctx, worker, traces) {
|
||||
return execute("run", ctx, worker, traces);
|
||||
}
|
||||
function collect(ctx, worker, traces) {
|
||||
return execute("collect", ctx, worker, traces);
|
||||
}
|
||||
async function teardown() {
|
||||
await cleanup();
|
||||
}
|
||||
const env = process.env;
|
||||
function createImportMetaEnvProxy() {
|
||||
// packages/vitest/src/node/plugins/index.ts:146
|
||||
const booleanKeys = [
|
||||
"DEV",
|
||||
"PROD",
|
||||
"SSR"
|
||||
];
|
||||
return new Proxy(env, {
|
||||
get(_, key) {
|
||||
if (typeof key !== "string") return;
|
||||
if (booleanKeys.includes(key)) return !!process.env[key];
|
||||
return process.env[key];
|
||||
},
|
||||
set(_, key, value) {
|
||||
if (typeof key !== "string") return true;
|
||||
if (booleanKeys.includes(key)) process.env[key] = value ? "1" : "";
|
||||
else process.env[key] = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const __vitest_worker_response__ = true;
|
||||
const memoryUsage = process.memoryUsage.bind(process);
|
||||
let reportMemory = false;
|
||||
let traces;
|
||||
/** @experimental */
|
||||
function init(worker) {
|
||||
worker.on(onMessage);
|
||||
if (worker.onModuleRunner) onModuleRunner(worker.onModuleRunner);
|
||||
let runPromise;
|
||||
let isRunning = false;
|
||||
let workerTeardown;
|
||||
let setupContext;
|
||||
function send(response) {
|
||||
worker.post(worker.serialize ? worker.serialize(response) : response);
|
||||
}
|
||||
async function onMessage(rawMessage) {
|
||||
const message = worker.deserialize ? worker.deserialize(rawMessage) : rawMessage;
|
||||
if (message?.__vitest_worker_request__ !== true) return;
|
||||
switch (message.type) {
|
||||
case "start": {
|
||||
process.env.VITEST_POOL_ID = String(message.poolId);
|
||||
process.env.VITEST_WORKER_ID = String(message.workerId);
|
||||
reportMemory = message.options.reportMemory;
|
||||
if (message.context.config.isAgent) disableDefaultColors();
|
||||
traces ??= await new Traces({
|
||||
enabled: message.traces.enabled,
|
||||
sdkPath: message.traces.sdkPath
|
||||
}).waitInit();
|
||||
const { environment, config, pool } = message.context;
|
||||
const context = traces.getContextFromCarrier(message.traces.otelCarrier);
|
||||
// record telemetry as part of "start"
|
||||
traces.recordInitSpan(context);
|
||||
try {
|
||||
setupContext = {
|
||||
environment,
|
||||
config,
|
||||
pool,
|
||||
rpc: createRuntimeRpc(worker),
|
||||
projectName: config.name || "",
|
||||
traces
|
||||
};
|
||||
workerTeardown = await traces.$("vitest.runtime.setup", { context }, () => worker.setup?.(setupContext));
|
||||
send({
|
||||
type: "started",
|
||||
__vitest_worker_response__
|
||||
});
|
||||
} catch (error) {
|
||||
send({
|
||||
type: "started",
|
||||
__vitest_worker_response__,
|
||||
error: serializeError(error)
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "run":
|
||||
// Prevent concurrent execution if worker is already running
|
||||
if (isRunning) {
|
||||
send({
|
||||
type: "testfileFinished",
|
||||
__vitest_worker_response__,
|
||||
error: serializeError(/* @__PURE__ */ new Error("[vitest-worker]: Worker is already running tests"))
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
||||
} catch (error) {
|
||||
return send({
|
||||
type: "testfileFinished",
|
||||
__vitest_worker_response__,
|
||||
error: serializeError(error),
|
||||
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
||||
});
|
||||
}
|
||||
isRunning = true;
|
||||
try {
|
||||
const tracesContext = traces.getContextFromCarrier(message.otelCarrier);
|
||||
runPromise = traces.$("vitest.runtime.run", {
|
||||
context: tracesContext,
|
||||
attributes: {
|
||||
"vitest.worker.specifications": traces.isEnabled() ? getFilesWithLocations(message.context.files) : [],
|
||||
"vitest.worker.id": message.context.workerId
|
||||
}
|
||||
}, () => run({
|
||||
...setupContext,
|
||||
...message.context
|
||||
}, worker, traces).catch((error) => serializeError(error)));
|
||||
send({
|
||||
type: "testfileFinished",
|
||||
__vitest_worker_response__,
|
||||
error: await runPromise,
|
||||
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
||||
});
|
||||
} finally {
|
||||
runPromise = void 0;
|
||||
isRunning = false;
|
||||
}
|
||||
break;
|
||||
case "collect":
|
||||
// Prevent concurrent execution if worker is already running
|
||||
if (isRunning) {
|
||||
send({
|
||||
type: "testfileFinished",
|
||||
__vitest_worker_response__,
|
||||
error: serializeError(/* @__PURE__ */ new Error("[vitest-worker]: Worker is already running tests"))
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
process.env.VITEST_WORKER_ID = String(message.context.workerId);
|
||||
} catch (error) {
|
||||
return send({
|
||||
type: "testfileFinished",
|
||||
__vitest_worker_response__,
|
||||
error: serializeError(error),
|
||||
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
||||
});
|
||||
}
|
||||
isRunning = true;
|
||||
try {
|
||||
const tracesContext = traces.getContextFromCarrier(message.otelCarrier);
|
||||
runPromise = traces.$("vitest.runtime.collect", {
|
||||
context: tracesContext,
|
||||
attributes: {
|
||||
"vitest.worker.specifications": traces.isEnabled() ? getFilesWithLocations(message.context.files) : [],
|
||||
"vitest.worker.id": message.context.workerId
|
||||
}
|
||||
}, () => collect({
|
||||
...setupContext,
|
||||
...message.context
|
||||
}, worker, traces).catch((error) => serializeError(error)));
|
||||
send({
|
||||
type: "testfileFinished",
|
||||
__vitest_worker_response__,
|
||||
error: await runPromise,
|
||||
usedMemory: reportMemory ? memoryUsage().heapUsed : void 0
|
||||
});
|
||||
} finally {
|
||||
runPromise = void 0;
|
||||
isRunning = false;
|
||||
}
|
||||
break;
|
||||
case "stop":
|
||||
await runPromise;
|
||||
try {
|
||||
const context = traces.getContextFromCarrier(message.otelCarrier);
|
||||
const error = await traces.$("vitest.runtime.teardown", { context }, async () => {
|
||||
const error = await teardown().catch((error) => serializeError(error));
|
||||
await workerTeardown?.();
|
||||
return error;
|
||||
});
|
||||
await traces.finish();
|
||||
send({
|
||||
type: "stopped",
|
||||
error,
|
||||
__vitest_worker_response__
|
||||
});
|
||||
} catch (error) {
|
||||
send({
|
||||
type: "stopped",
|
||||
error: serializeError(error),
|
||||
__vitest_worker_response__
|
||||
});
|
||||
}
|
||||
worker.teardown?.();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
function getFilesWithLocations(files) {
|
||||
return files.flatMap((file) => {
|
||||
if (!file.testLocations) return file.filepath;
|
||||
return file.testLocations.map((location) => {
|
||||
return `${file}:${location}`;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export { listenForErrors as a, emitModuleRunner as e, init as i, loadEnvironment as l };
|
||||
@@ -0,0 +1,403 @@
|
||||
# ES Module Lexer
|
||||
|
||||
[![Build Status][actions-image]][actions-url]
|
||||
|
||||
A JS module syntax lexer used in [es-module-shims](https://github.com/guybedford/es-module-shims).
|
||||
|
||||
Outputs the list of exports and locations of import specifiers, including dynamic import and import meta handling.
|
||||
|
||||
Supports new syntax features including import attributes and source phase imports.
|
||||
|
||||
A very small single JS file (~7KiB gzipped) that includes inlined Web Assembly for very fast source analysis of ECMAScript module syntax only.
|
||||
|
||||
For an example of the performance, Angular 1 (720KiB) is fully parsed in 5ms, in comparison to the fastest JS parser, Acorn which takes over 100ms.
|
||||
|
||||
_Comprehensively handles the JS language grammar while remaining small and fast. - ~10ms per MB of JS cold and ~5ms per MB of JS warm, [see benchmarks](#benchmarks) for more info._
|
||||
|
||||
> [Built with](https://github.com/guybedford/es-module-lexer/blob/main/chompfile.toml) [Chomp](https://chompbuild.com/)
|
||||
|
||||
### Usage
|
||||
|
||||
```
|
||||
npm install es-module-lexer
|
||||
```
|
||||
|
||||
See [src/lexer.ts](src/lexer.ts) for the type definitions.
|
||||
|
||||
For use in CommonJS:
|
||||
|
||||
```js
|
||||
const { init, parse } = require('es-module-lexer');
|
||||
|
||||
(async () => {
|
||||
// either await init, or call parse asynchronously
|
||||
// this is necessary for the Web Assembly boot
|
||||
await init;
|
||||
|
||||
const source = 'export var p = 5';
|
||||
const [imports, exports] = parse(source);
|
||||
|
||||
// Returns "p"
|
||||
source.slice(exports[0].s, exports[0].e);
|
||||
// Returns "p"
|
||||
source.slice(exports[0].ls, exports[0].le);
|
||||
})();
|
||||
```
|
||||
|
||||
An ES module version is also available:
|
||||
|
||||
```js
|
||||
import { init, parse } from 'es-module-lexer';
|
||||
|
||||
(async () => {
|
||||
await init;
|
||||
|
||||
const source = `
|
||||
import { name } from 'mod\\u1011';
|
||||
import json from './json.json' with { type: 'json' }
|
||||
export var p = 5;
|
||||
export function q () {
|
||||
|
||||
};
|
||||
export { x as 'external name' } from 'external';
|
||||
|
||||
// Comments provided to demonstrate edge cases
|
||||
import /*comment!*/ ( 'asdf', { with: { type: 'json' }});
|
||||
import /*comment!*/.meta.asdf;
|
||||
|
||||
// Source phase imports:
|
||||
import source mod from './mod.wasm';
|
||||
import.source('./mod.wasm');
|
||||
`;
|
||||
|
||||
const [imports, exports] = parse(source, 'optional-sourcename');
|
||||
|
||||
// Returns "modထ"
|
||||
imports[0].n
|
||||
// Returns "mod\u1011"
|
||||
source.slice(imports[0].s, imports[0].e);
|
||||
// "s" = start
|
||||
// "e" = end
|
||||
|
||||
// Returns "import { name } from 'mod'"
|
||||
source.slice(imports[0].ss, imports[0].se);
|
||||
// "ss" = statement start
|
||||
// "se" = statement end
|
||||
|
||||
// Returns "{ type: 'json' }"
|
||||
source.slice(imports[1].a, imports[1].se);
|
||||
// "a" = attribute start, -1 for no import attributes
|
||||
|
||||
// Parsed import attributes are available in `at`
|
||||
// Returns [['type', 'json']]
|
||||
imports[1].at;
|
||||
// Returns 'json'
|
||||
imports[1].at[0][1];
|
||||
|
||||
// Returns null (no attributes)
|
||||
imports[0].at;
|
||||
|
||||
// Returns "external"
|
||||
source.slice(imports[2].s, imports[2].e);
|
||||
|
||||
// Returns "p"
|
||||
source.slice(exports[0].s, exports[0].e);
|
||||
// Returns "p"
|
||||
source.slice(exports[0].ls, exports[0].le);
|
||||
// Returns "q"
|
||||
source.slice(exports[1].s, exports[1].e);
|
||||
// Returns "q"
|
||||
source.slice(exports[1].ls, exports[1].le);
|
||||
|
||||
// "ss" = export statement start (only the start is tracked, not the end)
|
||||
// Returns "export"
|
||||
source.slice(exports[0].ss, exports[0].ss + 6);
|
||||
|
||||
// Returns "'external name'"
|
||||
source.slice(exports[2].s, exports[2].e);
|
||||
// Returns -1
|
||||
exports[2].ls;
|
||||
// Returns -1
|
||||
exports[2].le;
|
||||
|
||||
// Import type is provided by `t` value
|
||||
// (1 for static, 2, for dynamic)
|
||||
// Returns true
|
||||
imports[2].t == 2;
|
||||
|
||||
// Returns "asdf" (only for string literal dynamic imports)
|
||||
imports[2].n
|
||||
// Returns "import /*comment!*/ ( 'asdf', { with: { type: 'json' } })"
|
||||
source.slice(imports[3].ss, imports[3].se);
|
||||
// Returns "'asdf'"
|
||||
source.slice(imports[3].s, imports[3].e);
|
||||
// Returns "( 'asdf', { with: { type: 'json' } })"
|
||||
source.slice(imports[3].d, imports[3].se);
|
||||
// Returns "{ with: { type: 'json' } }"
|
||||
source.slice(imports[3].a, imports[3].se - 1);
|
||||
|
||||
// For non-string dynamic import expressions:
|
||||
// - n will be undefined
|
||||
// - a is currently -1 even if there is an import attribute
|
||||
// - e is currently the character before the closing )
|
||||
|
||||
// For nested dynamic imports, the se value of the outer import is -1 as end tracking does not
|
||||
// currently support nested dynamic immports
|
||||
|
||||
// import.meta is indicated by imports[3].d === -2
|
||||
// Returns true
|
||||
imports[4].d === -2;
|
||||
// Returns "import /*comment!*/.meta"
|
||||
source.slice(imports[4].s, imports[4].e);
|
||||
// ss and se are the same for import meta
|
||||
|
||||
// Returns "'./mod.wasm'"
|
||||
source.slice(imports[5].s, imports[5].e);
|
||||
|
||||
// Import type 4 and 5 for static and dynamic source phase
|
||||
imports[5].t === 4;
|
||||
imports[6].t === 5;
|
||||
})();
|
||||
```
|
||||
|
||||
### CSP asm.js Build
|
||||
|
||||
The default version of the library uses Wasm and (safe) eval usage for performance and a minimal footprint.
|
||||
|
||||
Neither of these represent security escalation possibilities since there are no execution string injection vectors, but that can still violate existing CSP policies for applications.
|
||||
|
||||
For a version that works with CSP eval disabled, use the `es-module-lexer/js` build:
|
||||
|
||||
```js
|
||||
import { parse } from 'es-module-lexer/js';
|
||||
```
|
||||
|
||||
Instead of Web Assembly, this uses an asm.js build which is almost as fast as the Wasm version ([see benchmarks below](#benchmarks)).
|
||||
|
||||
### Minimal Build
|
||||
|
||||
For size-sensitive embedders, the `es-module-lexer/minimal` build drops certain features to reduce the binary size. This is used for example by [es-module-shims](https://github.com/guybedford/es-module-shims):
|
||||
|
||||
```js
|
||||
import { parse } from 'es-module-lexer/minimal';
|
||||
```
|
||||
|
||||
Compared to the full build:
|
||||
|
||||
* `parse` returns a two-element `[imports, exports]` tuple only - the third and fourth facade and `hasModuleSyntax` booleans are dropped.
|
||||
* Imports drop the parsed attribute list `at` (the attribute source remains recoverable via the `a` attributes index).
|
||||
* Exports drop the statement start `ss`.
|
||||
|
||||
All other fields are identical to the full build. For CSP eval disabled support, the equivalent asm.js build is available as `es-module-lexer/minimal/js`.
|
||||
|
||||
### Import Attributes
|
||||
|
||||
The `a` field provides the index of the start of the `{` attributes bracket, or -1 for no attributes.
|
||||
|
||||
The list of attribute key and value pairs are provided on the `at` field (full build only):
|
||||
|
||||
```js
|
||||
const [imports] = parse(`
|
||||
import json from './foo.json' with { type: 'json' };
|
||||
import './foo.css' with { type: 'css' };
|
||||
import pkg from 'pkg' with { type: 'json', integrity: 'sha384-...' };
|
||||
`);
|
||||
|
||||
// Returns [['type', 'json']]
|
||||
imports[0].at;
|
||||
|
||||
// Returns [['type', 'css']]
|
||||
imports[1].at;
|
||||
|
||||
// Multiple attributes
|
||||
// Returns [['type', 'json'], ['integrity', 'sha384-...']]
|
||||
imports[2].at;
|
||||
```
|
||||
|
||||
The `at` field is an array of `[key, value]` tuples, or `null` if there are no attributes.
|
||||
|
||||
Both keys and values support escape sequences:
|
||||
|
||||
```js
|
||||
const [imports] = parse(`
|
||||
import foo from './foo.js' with { "custom-key": "value" };
|
||||
import bar from './bar.js' with { "key\\nwith\\nnewlines": "value\\twith\\ttabs" };
|
||||
`);
|
||||
|
||||
// Quoted keys are unquoted
|
||||
// Returns [['custom-key', 'value']]
|
||||
imports[0].at;
|
||||
|
||||
// Escape sequences are processed
|
||||
// Returns [['key\nwith\nnewlines', 'value\twith\ttabs']]
|
||||
imports[1].at;
|
||||
```
|
||||
|
||||
### Escape Sequences
|
||||
|
||||
To handle escape sequences in specifier strings, the `.n` field of imported specifiers will be provided where possible.
|
||||
|
||||
For dynamic import expressions, this field will be empty if not a valid JS string.
|
||||
|
||||
### Facade Detection
|
||||
|
||||
Facade modules that only use import / export syntax can be detected via the third return value (full build only):
|
||||
|
||||
```js
|
||||
const [,, facade] = parse(`
|
||||
export * from 'external';
|
||||
import * as ns from 'external2';
|
||||
export { a as b } from 'external3';
|
||||
export { ns };
|
||||
`);
|
||||
facade === true;
|
||||
```
|
||||
|
||||
### ESM Detection
|
||||
|
||||
Modules that uses ESM syntaxes can be detected via the fourth return value (full build only):
|
||||
|
||||
```js
|
||||
const [,,, hasModuleSyntax] = parse(`
|
||||
export {}
|
||||
`);
|
||||
hasModuleSyntax === true;
|
||||
```
|
||||
|
||||
Dynamic imports are ignored since they can be used in Non-ESM files.
|
||||
|
||||
```js
|
||||
const [,,, hasModuleSyntax] = parse(`
|
||||
import('./foo.js')
|
||||
`);
|
||||
hasModuleSyntax === false;
|
||||
```
|
||||
|
||||
### Environment Support
|
||||
|
||||
Node.js 10+, and [all browsers with Web Assembly support](https://caniuse.com/#feat=wasm).
|
||||
|
||||
### Grammar Support
|
||||
|
||||
* Token state parses all line comments, block comments, strings, template strings, blocks, parens and punctuators.
|
||||
* Division operator / regex token ambiguity is handled via backtracking checks against punctuator prefixes, including closing brace or paren backtracking.
|
||||
* Always correctly parses valid JS source, but may parse invalid JS source without errors.
|
||||
|
||||
### Limitations
|
||||
|
||||
The lexing approach is designed to deal with the full language grammar including RegEx / division operator ambiguity through backtracking and paren / brace tracking.
|
||||
|
||||
Because it lexes rather than fully parses, the analysis is not a validation pass: valid JS source is always analyzed correctly, but some invalid source is accepted without an error rather than rejected. For example `export const = 1` lexes to an empty exports list instead of throwing. Callers that need to reject invalid source should run a validating parser separately.
|
||||
|
||||
Multiple exports per declaration (`export var a = 'asdf', q = z`) and renamed destructured exports (`export var { a: b } = asdf`) are detected correctly; earlier versions missed `q` and `b` in these forms.
|
||||
|
||||
### Benchmarks
|
||||
|
||||
Benchmarks can be run with `npm run bench`.
|
||||
|
||||
Current results on a standard desktop machine:
|
||||
|
||||
#### Wasm Build
|
||||
|
||||
```
|
||||
Module load time
|
||||
> 1ms
|
||||
Cold Run, All Samples
|
||||
test/samples/*.js (3057 KiB)
|
||||
> 13ms
|
||||
|
||||
Warm Runs (average of 25 runs)
|
||||
test/samples/angular.js (719 KiB)
|
||||
> 1ms
|
||||
test/samples/angular.min.js (188 KiB)
|
||||
> 1ms
|
||||
test/samples/d3.js (491 KiB)
|
||||
> 2ms
|
||||
test/samples/d3.min.js (274 KiB)
|
||||
> 1.04ms
|
||||
test/samples/magic-string.js (34 KiB)
|
||||
> 0ms
|
||||
test/samples/magic-string.min.js (20 KiB)
|
||||
> 0ms
|
||||
test/samples/rollup.js (902 KiB)
|
||||
> 3ms
|
||||
test/samples/rollup.min.js (429 KiB)
|
||||
> 2ms
|
||||
|
||||
Warm Runs, All Samples (average of 25 runs)
|
||||
test/samples/*.js (3057 KiB)
|
||||
> 10m
|
||||
```
|
||||
|
||||
### JS Build (asm.js)
|
||||
|
||||
```
|
||||
Module load time
|
||||
> 1ms
|
||||
Cold Run, All Samples
|
||||
test/samples/*.js (3057 KiB)
|
||||
> 92ms
|
||||
|
||||
Warm Runs (average of 25 runs)
|
||||
test/samples/angular.js (719 KiB)
|
||||
> 3.6ms
|
||||
test/samples/angular.min.js (188 KiB)
|
||||
> 2ms
|
||||
test/samples/d3.js (491 KiB)
|
||||
> 4ms
|
||||
test/samples/d3.min.js (274 KiB)
|
||||
> 2.52ms
|
||||
test/samples/magic-string.js (34 KiB)
|
||||
> 0ms
|
||||
test/samples/magic-string.min.js (20 KiB)
|
||||
> 0ms
|
||||
test/samples/rollup.js (902 KiB)
|
||||
> 6ms
|
||||
test/samples/rollup.min.js (429 KiB)
|
||||
> 3.2ms
|
||||
|
||||
Warm Runs, All Samples (average of 25 runs)
|
||||
test/samples/*.js (3057 KiB)
|
||||
> 20.88ms
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
This project uses [Chomp](https://chompbuild.com) for building.
|
||||
|
||||
With Chomp installed, download the WASI SDK 12.0 from https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-12.
|
||||
|
||||
- [Linux](https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz)
|
||||
- [Windows (MinGW)](https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-mingw.tar.gz)
|
||||
- [macOS](https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz)
|
||||
|
||||
Locate the WASI-SDK as a sibling folder, or customize the path via the `WASI_PATH` environment variable.
|
||||
|
||||
Emscripten emsdk is also assumed to be a sibling folder or via the `EMSDK_PATH` environment variable.
|
||||
|
||||
Example setup:
|
||||
|
||||
```
|
||||
git clone https://github.com:guybedford/es-module-lexer
|
||||
git clone https://github.com/emscripten-core/emsdk
|
||||
cd emsdk
|
||||
git checkout 1.40.1-fastcomp
|
||||
./emsdk install 1.40.1-fastcomp
|
||||
cd ..
|
||||
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
|
||||
gunzip wasi-sdk-12.0-linux.tar.gz
|
||||
tar -xf wasi-sdk-12.0-linux.tar
|
||||
mv wasi-sdk-12.0-linux.tar wasi-sdk-12.0
|
||||
cargo install chompbuild
|
||||
cd es-module-lexer
|
||||
chomp test
|
||||
```
|
||||
|
||||
For the `asm.js` build, git clone `emsdk` from is assumed to be a sibling folder as well.
|
||||
|
||||
### License
|
||||
|
||||
MIT
|
||||
|
||||
[actions-image]: https://github.com/guybedford/es-module-lexer/actions/workflows/build.yml/badge.svg
|
||||
[actions-url]: https://github.com/guybedford/es-module-lexer/actions/workflows/build.yml
|
||||
@@ -0,0 +1,212 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.valueMatchesSomeSpecifier = exports.typeMatchesSomeSpecifier = exports.typeOrValueSpecifiersSchema = void 0;
|
||||
exports.typeMatchesSpecifier = typeMatchesSpecifier;
|
||||
exports.valueMatchesSpecifier = valueMatchesSpecifier;
|
||||
const types_1 = require("@typescript-eslint/types");
|
||||
const tsutils = __importStar(require("ts-api-utils"));
|
||||
const specifierNameMatches_1 = require("./typeOrValueSpecifiers/specifierNameMatches");
|
||||
const typeDeclaredInFile_1 = require("./typeOrValueSpecifiers/typeDeclaredInFile");
|
||||
const typeDeclaredInLib_1 = require("./typeOrValueSpecifiers/typeDeclaredInLib");
|
||||
const typeDeclaredInPackageDeclarationFile_1 = require("./typeOrValueSpecifiers/typeDeclaredInPackageDeclarationFile");
|
||||
exports.typeOrValueSpecifiersSchema = {
|
||||
items: {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
from: {
|
||||
enum: ['file'],
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
minItems: 1,
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: ['from', 'name'],
|
||||
type: 'object',
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
from: {
|
||||
enum: ['lib'],
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
minItems: 1,
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
required: ['from', 'name'],
|
||||
type: 'object',
|
||||
},
|
||||
{
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
from: {
|
||||
enum: ['package'],
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
oneOf: [
|
||||
{
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
minItems: 1,
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
package: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
required: ['from', 'name', 'package'],
|
||||
type: 'object',
|
||||
},
|
||||
],
|
||||
},
|
||||
type: 'array',
|
||||
};
|
||||
function typeMatchesSpecifier(type, specifier, program) {
|
||||
if (tsutils.isUnionType(type)) {
|
||||
return type.types.every(t => typeMatchesSpecifier(t, specifier, program));
|
||||
}
|
||||
const wholeTypeMatches = (() => {
|
||||
if (tsutils.isIntrinsicErrorType(type)) {
|
||||
return false;
|
||||
}
|
||||
if (typeof specifier === 'string') {
|
||||
return (0, specifierNameMatches_1.specifierNameMatches)(type, specifier);
|
||||
}
|
||||
if (!(0, specifierNameMatches_1.specifierNameMatches)(type, specifier.name)) {
|
||||
return false;
|
||||
}
|
||||
const symbol = type.getSymbol() ?? type.aliasSymbol;
|
||||
const declarations = symbol?.getDeclarations() ?? [];
|
||||
const declarationFiles = declarations.map(declaration => declaration.getSourceFile());
|
||||
switch (specifier.from) {
|
||||
case 'file':
|
||||
return (0, typeDeclaredInFile_1.typeDeclaredInFile)(specifier.path, declarationFiles, program);
|
||||
case 'lib':
|
||||
return (0, typeDeclaredInLib_1.typeDeclaredInLib)(declarationFiles, program);
|
||||
case 'package':
|
||||
return (0, typeDeclaredInPackageDeclarationFile_1.typeDeclaredInPackageDeclarationFile)(specifier.package, declarations, declarationFiles, program);
|
||||
}
|
||||
})();
|
||||
if (wholeTypeMatches) {
|
||||
return true;
|
||||
}
|
||||
if (tsutils.isIntersectionType(type) &&
|
||||
tsutils
|
||||
.intersectionConstituents(type)
|
||||
.some(part => typeMatchesSpecifier(part, specifier, program))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const typeMatchesSomeSpecifier = (type, specifiers = [], program) => specifiers.some(specifier => typeMatchesSpecifier(type, specifier, program));
|
||||
exports.typeMatchesSomeSpecifier = typeMatchesSomeSpecifier;
|
||||
const getSpecifierNames = (specifierName) => {
|
||||
return typeof specifierName === 'string' ? [specifierName] : specifierName;
|
||||
};
|
||||
const getStaticName = (node) => {
|
||||
if (node.type === types_1.AST_NODE_TYPES.Identifier ||
|
||||
node.type === types_1.AST_NODE_TYPES.JSXIdentifier ||
|
||||
node.type === types_1.AST_NODE_TYPES.PrivateIdentifier) {
|
||||
return node.name;
|
||||
}
|
||||
if (node.type === types_1.AST_NODE_TYPES.Literal && typeof node.value === 'string') {
|
||||
return node.value;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
function valueMatchesSpecifier(node, specifier, program, type) {
|
||||
const staticName = getStaticName(node);
|
||||
if (!staticName) {
|
||||
return false;
|
||||
}
|
||||
if (typeof specifier === 'string') {
|
||||
return specifier === staticName;
|
||||
}
|
||||
if (!getSpecifierNames(specifier.name).includes(staticName)) {
|
||||
return false;
|
||||
}
|
||||
if (specifier.from === 'package') {
|
||||
const symbol = type.getSymbol() ?? type.aliasSymbol;
|
||||
const declarations = symbol?.getDeclarations() ?? [];
|
||||
const declarationFiles = declarations.map(declaration => declaration.getSourceFile());
|
||||
return (0, typeDeclaredInPackageDeclarationFile_1.typeDeclaredInPackageDeclarationFile)(specifier.package, declarations, declarationFiles, program);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const valueMatchesSomeSpecifier = (node, specifiers = [], program, type) => specifiers.some(specifier => valueMatchesSpecifier(node, specifier, program, type));
|
||||
exports.valueMatchesSomeSpecifier = valueMatchesSomeSpecifier;
|
||||
@@ -0,0 +1,179 @@
|
||||
import { Readable, Writable } from 'node:stream'
|
||||
|
||||
export default CacheHandler
|
||||
|
||||
declare namespace CacheHandler {
|
||||
export type CacheMethods = 'GET' | 'HEAD' | 'OPTIONS' | 'TRACE'
|
||||
|
||||
export interface CacheHandlerOptions {
|
||||
store: CacheStore
|
||||
|
||||
cacheByDefault?: number
|
||||
|
||||
type?: CacheOptions['type']
|
||||
}
|
||||
|
||||
export interface CacheOptions {
|
||||
store?: CacheStore
|
||||
|
||||
/**
|
||||
* The methods to cache
|
||||
* Note we can only cache safe methods. Unsafe methods (i.e. PUT, POST)
|
||||
* invalidate the cache for a origin.
|
||||
* @see https://www.rfc-editor.org/rfc/rfc9111.html#name-invalidating-stored-respons
|
||||
* @see https://www.rfc-editor.org/rfc/rfc9110#section-9.2.1
|
||||
*/
|
||||
methods?: CacheMethods[]
|
||||
|
||||
/**
|
||||
* RFC9111 allows for caching responses that we aren't explicitly told to
|
||||
* cache or to not cache.
|
||||
* @see https://www.rfc-editor.org/rfc/rfc9111.html#section-3-5
|
||||
* @default undefined
|
||||
*/
|
||||
cacheByDefault?: number
|
||||
|
||||
/**
|
||||
* TODO docs
|
||||
* @default 'shared'
|
||||
*/
|
||||
type?: 'shared' | 'private'
|
||||
|
||||
/**
|
||||
* Array of origins to cache. Only requests to these origins will be cached.
|
||||
* Supports strings (case insensitive) and RegExp patterns.
|
||||
* @default undefined (cache all origins)
|
||||
*/
|
||||
origins?: (string | RegExp)[]
|
||||
}
|
||||
|
||||
export interface CacheControlDirectives {
|
||||
'max-stale'?: number;
|
||||
'min-fresh'?: number;
|
||||
'max-age'?: number;
|
||||
's-maxage'?: number;
|
||||
'stale-while-revalidate'?: number;
|
||||
'stale-if-error'?: number;
|
||||
public?: true;
|
||||
private?: true | string[];
|
||||
'no-store'?: true;
|
||||
'no-cache'?: true | string[];
|
||||
'must-revalidate'?: true;
|
||||
'proxy-revalidate'?: true;
|
||||
immutable?: true;
|
||||
'no-transform'?: true;
|
||||
'must-understand'?: true;
|
||||
'only-if-cached'?: true;
|
||||
}
|
||||
|
||||
export interface CacheKey {
|
||||
origin: string
|
||||
method: string
|
||||
path: string
|
||||
headers?: Record<string, string | string[]>
|
||||
}
|
||||
|
||||
export interface CacheValue {
|
||||
statusCode: number
|
||||
statusMessage: string
|
||||
headers: Record<string, string | string[]>
|
||||
vary?: Record<string, string | string[] | null>
|
||||
etag?: string
|
||||
cacheControlDirectives?: CacheControlDirectives
|
||||
cachedAt: number
|
||||
staleAt: number
|
||||
deleteAt: number
|
||||
}
|
||||
|
||||
export interface DeleteByUri {
|
||||
origin: string
|
||||
method: string
|
||||
path: string
|
||||
}
|
||||
|
||||
type GetResult = {
|
||||
statusCode: number
|
||||
statusMessage: string
|
||||
headers: Record<string, string | string[]>
|
||||
vary?: Record<string, string | string[] | null>
|
||||
etag?: string
|
||||
body?: Readable | Iterable<Buffer> | AsyncIterable<Buffer> | Buffer | Iterable<string> | AsyncIterable<string> | string
|
||||
cacheControlDirectives: CacheControlDirectives,
|
||||
cachedAt: number
|
||||
staleAt: number
|
||||
deleteAt: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Underlying storage provider for cached responses
|
||||
*/
|
||||
export interface CacheStore {
|
||||
get(key: CacheKey): GetResult | Promise<GetResult | undefined> | undefined
|
||||
|
||||
createWriteStream(key: CacheKey, val: CacheValue): Writable | undefined
|
||||
|
||||
delete(key: CacheKey): void | Promise<void>
|
||||
}
|
||||
|
||||
export interface MemoryCacheStoreOpts {
|
||||
/**
|
||||
* @default Infinity
|
||||
*/
|
||||
maxCount?: number
|
||||
|
||||
/**
|
||||
* @default Infinity
|
||||
*/
|
||||
maxSize?: number
|
||||
|
||||
/**
|
||||
* @default Infinity
|
||||
*/
|
||||
maxEntrySize?: number
|
||||
|
||||
errorCallback?: (err: Error) => void
|
||||
}
|
||||
|
||||
export class MemoryCacheStore implements CacheStore {
|
||||
constructor (opts?: MemoryCacheStoreOpts)
|
||||
|
||||
get (key: CacheKey): GetResult | Promise<GetResult | undefined> | undefined
|
||||
|
||||
createWriteStream (key: CacheKey, value: CacheValue): Writable | undefined
|
||||
|
||||
delete (key: CacheKey): void | Promise<void>
|
||||
}
|
||||
|
||||
export interface SqliteCacheStoreOpts {
|
||||
/**
|
||||
* Location of the database
|
||||
* @default ':memory:'
|
||||
*/
|
||||
location?: string
|
||||
|
||||
/**
|
||||
* @default Infinity
|
||||
*/
|
||||
maxCount?: number
|
||||
|
||||
/**
|
||||
* @default Infinity
|
||||
*/
|
||||
maxEntrySize?: number
|
||||
}
|
||||
|
||||
export class SqliteCacheStore implements CacheStore {
|
||||
constructor (opts?: SqliteCacheStoreOpts)
|
||||
|
||||
/**
|
||||
* Closes the connection to the database
|
||||
*/
|
||||
close (): void
|
||||
|
||||
get (key: CacheKey): GetResult | Promise<GetResult | undefined> | undefined
|
||||
|
||||
createWriteStream (key: CacheKey, value: CacheValue): Writable | undefined
|
||||
|
||||
delete (key: CacheKey): void | Promise<void>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { UUIDTypes } from './types.js';
|
||||
export { DNS, URL } from './v35.js';
|
||||
declare function v5(value: string | Uint8Array, namespace: UUIDTypes, buf?: undefined, offset?: number): string;
|
||||
declare function v5<TBuf extends Uint8Array = Uint8Array>(value: string | Uint8Array, namespace: UUIDTypes, buf: TBuf, offset?: number): TBuf;
|
||||
declare namespace v5 {
|
||||
var DNS: string;
|
||||
var URL: string;
|
||||
}
|
||||
export default v5;
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"typePredicateKind.enum.d.ts","sourceRoot":"","sources":["../../src/enums/typePredicateKind.enum.ts"],"names":[],"mappings":"AAEA,oBAAY,iBAAiB;IACzB,IAAI,IAAI;IACR,UAAU,IAAI;IACd,WAAW,IAAI;IACf,iBAAiB,IAAI;CACxB"}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Zod 3 compat layer
|
||||
import * as core from "../core/index.js";
|
||||
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
||||
export const ZodIssueCode = {
|
||||
invalid_type: "invalid_type",
|
||||
too_big: "too_big",
|
||||
too_small: "too_small",
|
||||
invalid_format: "invalid_format",
|
||||
not_multiple_of: "not_multiple_of",
|
||||
unrecognized_keys: "unrecognized_keys",
|
||||
invalid_union: "invalid_union",
|
||||
invalid_key: "invalid_key",
|
||||
invalid_element: "invalid_element",
|
||||
invalid_value: "invalid_value",
|
||||
custom: "custom",
|
||||
};
|
||||
export { $brand, config } from "../core/index.js";
|
||||
/** @deprecated Use `z.config(params)` instead. */
|
||||
export function setErrorMap(map) {
|
||||
core.config({
|
||||
customError: map,
|
||||
});
|
||||
}
|
||||
/** @deprecated Use `z.config()` instead. */
|
||||
export function getErrorMap() {
|
||||
return core.config().customError;
|
||||
}
|
||||
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
||||
export var ZodFirstPartyTypeKind;
|
||||
(function (ZodFirstPartyTypeKind) {
|
||||
})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
|
||||
@@ -0,0 +1,27 @@
|
||||
const postfixRE = /[?#].*$/;
|
||||
function cleanUrl(url) {
|
||||
return url.replace(postfixRE, "");
|
||||
}
|
||||
function createManualModuleSource(moduleUrl, exports$1, globalAccessor = "\"__vitest_mocker__\"") {
|
||||
const source = `
|
||||
const __factoryModule__ = await globalThis[${globalAccessor}].getFactoryModule("${moduleUrl}");
|
||||
`;
|
||||
const keys = exports$1.map((name, index) => {
|
||||
return `let __${index} = __factoryModule__["${name}"]
|
||||
export { __${index} as "${name}" }`;
|
||||
}).join("\n");
|
||||
let code = `${source}\n${keys}`;
|
||||
// this prevents recursion
|
||||
code += `
|
||||
if (__factoryModule__.__factoryPromise != null) {
|
||||
__factoryModule__.__factoryPromise.then((resolvedModule) => {
|
||||
${exports$1.map((name, index) => {
|
||||
return `__${index} = resolvedModule["${name}"];`;
|
||||
}).join("\n")}
|
||||
})
|
||||
}
|
||||
`;
|
||||
return code;
|
||||
}
|
||||
|
||||
export { cleanUrl as a, createManualModuleSource as c };
|
||||
@@ -0,0 +1,4 @@
|
||||
import type * as ts from 'typescript';
|
||||
import type { ASTMaps } from './convert';
|
||||
import type { ParserServices } from './parser-options';
|
||||
export declare function createParserServices(astMaps: ASTMaps, program: ts.Program | null): ParserServices;
|
||||
@@ -0,0 +1,8 @@
|
||||
import type * as ts from 'typescript/lib/tsserverlibrary';
|
||||
/**
|
||||
* Parses a TSConfig file using the same logic as tsserver.
|
||||
*
|
||||
* @param configFile the path to the tsconfig.json file, relative to `projectDirectory`
|
||||
* @param projectDirectory the project directory to use as the CWD, defaults to `process.cwd()`
|
||||
*/
|
||||
export declare function getParsedConfigFile(tsserver: typeof ts, configFile: string, projectDirectory?: string): ts.ParsedCommandLine;
|
||||
@@ -0,0 +1,29 @@
|
||||
function _ts_generator(thisArg, body) {
|
||||
var f, y, t, _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
|
||||
return d(g, "next", { value: verb(0) }), d(g, "throw", { value: verb(1) }), d(g, "return", { value: verb(2) }), typeof Symbol === "function" && d(g, Symbol.iterator, { value: function () { return this; } }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f) throw new TypeError("Generator is already executing.");
|
||||
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
||||
if (y = 0, t) op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0: case 1: t = op; break;
|
||||
case 4: _.label++; return { value: op[1], done: false };
|
||||
case 5: _.label++; y = op[1]; op = [0]; continue;
|
||||
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
||||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
||||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
||||
if (t[2]) _.ops.pop();
|
||||
_.trys.pop(); continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
||||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
}
|
||||
|
||||
export { _ts_generator as _ };
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = require('ws');
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encodeToCurve = exports.hashToCurve = exports.secp256r1 = exports.p256 = void 0;
|
||||
const nist_ts_1 = require("./nist.js");
|
||||
/** @deprecated use `import { p256 } from '@noble/curves/nist.js';` */
|
||||
exports.p256 = nist_ts_1.p256;
|
||||
/** @deprecated use `import { p256 } from '@noble/curves/nist.js';` */
|
||||
exports.secp256r1 = nist_ts_1.p256;
|
||||
/** @deprecated use `import { p256_hasher } from '@noble/curves/nist.js';` */
|
||||
exports.hashToCurve = (() => nist_ts_1.p256_hasher.hashToCurve)();
|
||||
/** @deprecated use `import { p256_hasher } from '@noble/curves/nist.js';` */
|
||||
exports.encodeToCurve = (() => nist_ts_1.p256_hasher.encodeToCurve)();
|
||||
//# sourceMappingURL=p256.js.map
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Core schema meta-schema",
|
||||
"definitions": {
|
||||
"schemaArray": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#" }
|
||||
},
|
||||
"nonNegativeInteger": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"nonNegativeIntegerDefault0": {
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/nonNegativeInteger" },
|
||||
{ "default": 0 }
|
||||
]
|
||||
},
|
||||
"simpleTypes": {
|
||||
"enum": [
|
||||
"array",
|
||||
"boolean",
|
||||
"integer",
|
||||
"null",
|
||||
"number",
|
||||
"object",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"stringArray": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"uniqueItems": true,
|
||||
"default": []
|
||||
}
|
||||
},
|
||||
"type": ["object", "boolean"],
|
||||
"properties": {
|
||||
"$id": {
|
||||
"type": "string",
|
||||
"format": "uri-reference"
|
||||
},
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"$ref": {
|
||||
"type": "string",
|
||||
"format": "uri-reference"
|
||||
},
|
||||
"$comment": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"default": true,
|
||||
"readOnly": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"examples": {
|
||||
"type": "array",
|
||||
"items": true
|
||||
},
|
||||
"multipleOf": {
|
||||
"type": "number",
|
||||
"exclusiveMinimum": 0
|
||||
},
|
||||
"maximum": {
|
||||
"type": "number"
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"type": "number"
|
||||
},
|
||||
"minimum": {
|
||||
"type": "number"
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"type": "number"
|
||||
},
|
||||
"maxLength": { "$ref": "#/definitions/nonNegativeInteger" },
|
||||
"minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
|
||||
"pattern": {
|
||||
"type": "string",
|
||||
"format": "regex"
|
||||
},
|
||||
"additionalItems": { "$ref": "#" },
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#" },
|
||||
{ "$ref": "#/definitions/schemaArray" }
|
||||
],
|
||||
"default": true
|
||||
},
|
||||
"maxItems": { "$ref": "#/definitions/nonNegativeInteger" },
|
||||
"minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
|
||||
"uniqueItems": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"contains": { "$ref": "#" },
|
||||
"maxProperties": { "$ref": "#/definitions/nonNegativeInteger" },
|
||||
"minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" },
|
||||
"required": { "$ref": "#/definitions/stringArray" },
|
||||
"additionalProperties": { "$ref": "#" },
|
||||
"definitions": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#" },
|
||||
"default": {}
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#" },
|
||||
"default": {}
|
||||
},
|
||||
"patternProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "$ref": "#" },
|
||||
"propertyNames": { "format": "regex" },
|
||||
"default": {}
|
||||
},
|
||||
"dependencies": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#" },
|
||||
{ "$ref": "#/definitions/stringArray" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"propertyNames": { "$ref": "#" },
|
||||
"const": true,
|
||||
"enum": {
|
||||
"type": "array",
|
||||
"items": true,
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"type": {
|
||||
"anyOf": [
|
||||
{ "$ref": "#/definitions/simpleTypes" },
|
||||
{
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/simpleTypes" },
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"format": { "type": "string" },
|
||||
"contentMediaType": { "type": "string" },
|
||||
"contentEncoding": { "type": "string" },
|
||||
"if": {"$ref": "#"},
|
||||
"then": {"$ref": "#"},
|
||||
"else": {"$ref": "#"},
|
||||
"allOf": { "$ref": "#/definitions/schemaArray" },
|
||||
"anyOf": { "$ref": "#/definitions/schemaArray" },
|
||||
"oneOf": { "$ref": "#/definitions/schemaArray" },
|
||||
"not": { "$ref": "#" }
|
||||
},
|
||||
"default": true
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"name": "uuid",
|
||||
"version": "14.0.1",
|
||||
"description": "RFC9562 UUIDs",
|
||||
"type": "module",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"commitlint": {
|
||||
"extends": [
|
||||
"@commitlint/config-conventional"
|
||||
]
|
||||
},
|
||||
"keywords": [
|
||||
"uuid",
|
||||
"guid",
|
||||
"rfc4122",
|
||||
"rfc9562"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"uuid": "./dist-node/bin/uuid"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"types": "./dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"node": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./dist-node/index.js"
|
||||
},
|
||||
"default": "./dist/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"dist-node",
|
||||
"!**/test"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.4.10",
|
||||
"@commitlint/cli": "20.5.0",
|
||||
"@commitlint/config-conventional": "20.5.0",
|
||||
"bundlewatch": "0.4.1",
|
||||
"commander": "14.0.3",
|
||||
"globals": "17.4.0",
|
||||
"jest": "30.3.0",
|
||||
"lefthook": "1.11.13",
|
||||
"lint-staged": "16.4.0",
|
||||
"neostandard": "0.13.0",
|
||||
"npm-run-all2": "8.0.4",
|
||||
"prettier": "3.8.3",
|
||||
"release-please": "17.3.0",
|
||||
"runmd": "2.1.1",
|
||||
"standard-version": "9.5.0",
|
||||
"typescript": "5.4.3"
|
||||
},
|
||||
"optionalDevDependencies": {
|
||||
"@wdio/browserstack-service": "9.27.0",
|
||||
"@wdio/cli": "9.27.0",
|
||||
"@wdio/jasmine-framework": "9.27.0",
|
||||
"@wdio/local-runner": "9.27.0",
|
||||
"@wdio/spec-reporter": "9.27.0",
|
||||
"@wdio/static-server-service": "9.27.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "./scripts/build.sh",
|
||||
"build:watch": "tsc --watch -p tsconfig.json",
|
||||
"bundlewatch": "npm run pretest:browser && bundlewatch --config bundlewatch.config.json",
|
||||
"docs:diff": "npm run docs && git diff README.md",
|
||||
"docs": "npm run build && npx runmd --output=README.md README_js.md",
|
||||
"biome:check": "biome check .",
|
||||
"biome:fix": "biome check --write .",
|
||||
"examples:browser:rollup:build": "cd examples/browser-rollup && npm run build",
|
||||
"examples:browser:webpack:build": "cd examples/browser-webpack && npm run build",
|
||||
"examples:node:esmodules:test": "cd examples/node-esmodules && npm test",
|
||||
"examples:node:jest:test": "cd examples/node-jest && npm test",
|
||||
"examples:node:typescript:test": "cd examples/typescript && npm test",
|
||||
"lint": "npm run biome:check",
|
||||
"md": "runmd --watch --output=README.md README_js.md",
|
||||
"prepack": "npm run build -- --no-pack",
|
||||
"prepare": "lefthook install",
|
||||
"prepublishOnly": "npm run build",
|
||||
"pretest:benchmark": "npm run build",
|
||||
"pretest:browser": "./scripts/iodd && npm run build && npm-run-all --parallel examples:browser:**",
|
||||
"pretest:node": "npm run build",
|
||||
"pretest": "npm run build",
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome format --check .",
|
||||
"release": "standard-version --no-verify",
|
||||
"test:benchmark": "cd examples/benchmark && npm test",
|
||||
"test:browser": "wdio run ./wdio.conf.js",
|
||||
"test:node": "npm-run-all --parallel examples:node:**",
|
||||
"test:watch": "node --test --enable-source-maps --watch dist-node/test/*.js",
|
||||
"test": "node --test --enable-source-maps dist-node/test/*.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/uuidjs/uuid.git"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": [
|
||||
"biome check --write --no-errors-on-unmatched"
|
||||
]
|
||||
},
|
||||
"standard-version": {
|
||||
"scripts": {
|
||||
"postchangelog": "biome format --write CHANGELOG.md"
|
||||
}
|
||||
},
|
||||
"packageManager": "npm@11.12.1"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"encoder.generated.d.ts","sourceRoot":"","sources":["../../../src/api/node/encoder.generated.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAiBR,IAAI,EAMP,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAOhD,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAuBxD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CA6CpD"}
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const { createWarning } = require('..')
|
||||
|
||||
const CUSTDEP001 = createWarning({
|
||||
name: 'DeprecationWarning',
|
||||
code: 'CUSTDEP001',
|
||||
message: 'This is a deprecation warning'
|
||||
})
|
||||
|
||||
CUSTDEP001()
|
||||
@@ -0,0 +1 @@
|
||||
export { _ as default } from "../esm/_super_prop_base.js";
|
||||
@@ -0,0 +1,27 @@
|
||||
import type { TSESTree } from '@typescript-eslint/utils';
|
||||
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
|
||||
/**
|
||||
* Parses a syntactically possible `Promise.then()` call. Does not check the
|
||||
* type of the callee.
|
||||
*/
|
||||
export declare function parseThenCall(node: TSESTree.CallExpression, context: RuleContext<string, unknown[]>): {
|
||||
onFulfilled?: TSESTree.Expression | undefined;
|
||||
onRejected?: TSESTree.Expression | undefined;
|
||||
object: TSESTree.Expression;
|
||||
} | undefined;
|
||||
/**
|
||||
* Parses a syntactically possible `Promise.catch()` call. Does not check the
|
||||
* type of the callee.
|
||||
*/
|
||||
export declare function parseCatchCall(node: TSESTree.CallExpression, context: RuleContext<string, unknown[]>): {
|
||||
onRejected?: TSESTree.Expression | undefined;
|
||||
object: TSESTree.Expression;
|
||||
} | undefined;
|
||||
/**
|
||||
* Parses a syntactically possible `Promise.finally()` call. Does not check the
|
||||
* type of the callee.
|
||||
*/
|
||||
export declare function parseFinallyCall(node: TSESTree.CallExpression, context: RuleContext<string, unknown[]>): {
|
||||
object: TSESTree.Expression;
|
||||
onFinally?: TSESTree.Expression | undefined;
|
||||
} | undefined;
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,40 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("passing validations", () => {
|
||||
const example1 = z.custom<number>((x) => typeof x === "number");
|
||||
example1.parse(1234);
|
||||
expect(() => example1.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("string params", () => {
|
||||
const example1 = z.custom<number>((x) => typeof x !== "number", "customerr");
|
||||
const result = example1.safeParse(1234);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(JSON.stringify(result.error).includes("customerr")).toEqual(true);
|
||||
});
|
||||
|
||||
test("instanceof", () => {
|
||||
const fn = (value: string) => Uint8Array.from(Buffer.from(value, "base64"));
|
||||
|
||||
// Argument of type 'ZodCustom<Uint8Array<ArrayBuffer>, unknown>' is not assignable to parameter of type '$ZodType<any, Uint8Array<ArrayBuffer>>'.
|
||||
z.string().transform(fn).pipe(z.instanceof(Uint8Array));
|
||||
});
|
||||
|
||||
test("non-continuable by default", () => {
|
||||
const A = z
|
||||
.custom<string>((val) => typeof val === "string")
|
||||
.transform((_) => {
|
||||
throw new Error("Invalid input");
|
||||
});
|
||||
expect(A.safeParse(123).error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @fileoverview Rule to disallow use of the new operator with the `Symbol` object
|
||||
* @author Alberto Rodríguez
|
||||
* @deprecated in ESLint v9.0.0
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "Disallow `new` operators with the `Symbol` object",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-new-symbol",
|
||||
},
|
||||
|
||||
deprecated: {
|
||||
message: "The rule was replaced with a more general rule.",
|
||||
url: "https://eslint.org/docs/latest/use/migrate-to-9.0.0#eslint-recommended",
|
||||
deprecatedSince: "9.0.0",
|
||||
availableUntil: "11.0.0",
|
||||
replacedBy: [
|
||||
{
|
||||
rule: {
|
||||
name: "no-new-native-nonconstructor",
|
||||
url: "https://eslint.org/docs/latest/rules/no-new-native-nonconstructor",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
noNewSymbol: "`Symbol` cannot be called as a constructor.",
|
||||
},
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
return {
|
||||
"Program:exit"(node) {
|
||||
const globalScope = sourceCode.getScope(node);
|
||||
const variable = globalScope.set.get("Symbol");
|
||||
|
||||
if (variable && variable.defs.length === 0) {
|
||||
variable.references.forEach(ref => {
|
||||
const idNode = ref.identifier;
|
||||
const parent = idNode.parent;
|
||||
|
||||
if (
|
||||
parent &&
|
||||
parent.type === "NewExpression" &&
|
||||
parent.callee === idNode
|
||||
) {
|
||||
context.report({
|
||||
node: idNode,
|
||||
messageId: "noNewSymbol",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
// Code generated by Herebyfile.mjs generate:enums from internal/ast/utilities.go. DO NOT EDIT.
|
||||
export var OuterExpressionKinds;
|
||||
(function (OuterExpressionKinds) {
|
||||
OuterExpressionKinds[OuterExpressionKinds["Parentheses"] = 1] = "Parentheses";
|
||||
OuterExpressionKinds[OuterExpressionKinds["TypeAssertions"] = 2] = "TypeAssertions";
|
||||
OuterExpressionKinds[OuterExpressionKinds["NonNullAssertions"] = 4] = "NonNullAssertions";
|
||||
OuterExpressionKinds[OuterExpressionKinds["PartiallyEmittedExpressions"] = 8] = "PartiallyEmittedExpressions";
|
||||
OuterExpressionKinds[OuterExpressionKinds["ExpressionsWithTypeArguments"] = 16] = "ExpressionsWithTypeArguments";
|
||||
OuterExpressionKinds[OuterExpressionKinds["Satisfies"] = 32] = "Satisfies";
|
||||
OuterExpressionKinds[OuterExpressionKinds["ExcludeJSDocTypeAssertion"] = 64] = "ExcludeJSDocTypeAssertion";
|
||||
OuterExpressionKinds[OuterExpressionKinds["Assignments"] = 128] = "Assignments";
|
||||
OuterExpressionKinds[OuterExpressionKinds["Comma"] = 256] = "Comma";
|
||||
OuterExpressionKinds[OuterExpressionKinds["Assertions"] = 38] = "Assertions";
|
||||
OuterExpressionKinds[OuterExpressionKinds["All"] = 63] = "All";
|
||||
OuterExpressionKinds[OuterExpressionKinds["AllExceptAssertionsOrExpressionsWithTypeArguments"] = 9] = "AllExceptAssertionsOrExpressionsWithTypeArguments";
|
||||
OuterExpressionKinds[OuterExpressionKinds["ExpressionTypePassthrough"] = 385] = "ExpressionTypePassthrough";
|
||||
})(OuterExpressionKinds || (OuterExpressionKinds = {}));
|
||||
//# sourceMappingURL=outerExpressionKinds.js.map
|
||||
@@ -0,0 +1,13 @@
|
||||
Copyright (c) 2017, Emil Bay <github@tixz.dk>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
@@ -0,0 +1,517 @@
|
||||
'use strict';
|
||||
|
||||
const StreamValues = require('stream-json/streamers/StreamValues');
|
||||
const Verifier = require('stream-json/utils/Verifier');
|
||||
const JSONstringify = require('json-stringify-safe');
|
||||
const uuid = require('uuid').v4;
|
||||
|
||||
const generateRequest = require('./generateRequest');
|
||||
|
||||
/** * @namespace */
|
||||
const Utils = module.exports;
|
||||
|
||||
// same reference as other files use, for tidyness
|
||||
const utils = Utils;
|
||||
|
||||
Utils.request = generateRequest;
|
||||
|
||||
/**
|
||||
* Generates a JSON-RPC 1.0 or 2.0 response
|
||||
* @param {Object} error Error member
|
||||
* @param {Object} result Result member
|
||||
* @param {String|Number|null} id Id of request
|
||||
* @param {Number} version JSON-RPC version to use
|
||||
* @return {Object} A JSON-RPC 1.0 or 2.0 response
|
||||
*/
|
||||
Utils.response = function(error, result, id, version) {
|
||||
id = typeof(id) === 'undefined' || id === null ? null : id;
|
||||
error = typeof(error) === 'undefined' || error === null ? null : error;
|
||||
version = typeof(version) === 'undefined' || version === null ? 2 : version;
|
||||
result = typeof(result) === 'undefined' || result === null ? null : result;
|
||||
const response = (version === 2) ? { jsonrpc: "2.0", id: id } : { id: id };
|
||||
|
||||
// errors are always included in version 1
|
||||
if(version === 1) {
|
||||
response.error = error;
|
||||
}
|
||||
|
||||
// one or the other with precedence for errors
|
||||
if(error) {
|
||||
response.error = error;
|
||||
} else {
|
||||
response.result = result;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a random UUID
|
||||
* @return {String}
|
||||
*/
|
||||
Utils.generateId = function() {
|
||||
return uuid();
|
||||
};
|
||||
|
||||
/**
|
||||
* Merges properties of object b into object a
|
||||
* @param {...Object} args Objects to be merged
|
||||
* @return {Object}
|
||||
* @private
|
||||
*/
|
||||
Utils.merge = function(...args) {
|
||||
return args.reduce(function (out, obj) {
|
||||
return {...out, ...obj};
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses an incoming stream for requests using stream-json
|
||||
* @param {Stream} stream
|
||||
* @param {Object} options
|
||||
* @param {Function} onRequest Called once for stream errors and an unlimited amount of times for valid requests
|
||||
*/
|
||||
Utils.parseStream = function(stream, options, onRequest) {
|
||||
const onError = Utils.once(onRequest);
|
||||
const onSuccess = (...args) => onRequest(null, ...args);
|
||||
|
||||
const verifier = new Verifier({jsonStreaming: true});
|
||||
const parser = StreamValues.withParser();
|
||||
|
||||
parser.on('data', function(obj) {
|
||||
let data = obj.value;
|
||||
|
||||
// apply reviver walk function to prevent stringify/parse again
|
||||
if(typeof options.reviver === 'function') {
|
||||
data = Utils.walk({'': data}, '', options.reviver);
|
||||
}
|
||||
|
||||
onSuccess(data);
|
||||
});
|
||||
|
||||
parser.on('error', onError);
|
||||
verifier.on('error', onError);
|
||||
stream.on('error', onError);
|
||||
|
||||
stream.pipe(verifier);
|
||||
stream.pipe(parser);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a function that can only be called once
|
||||
* @param {Function} fn
|
||||
* @return {Function}
|
||||
*/
|
||||
Utils.once = function (fn) {
|
||||
let called = false;
|
||||
let lastRetval;
|
||||
return function (...args) {
|
||||
if (called) return lastRetval;
|
||||
called = true;
|
||||
lastRetval = fn.call(this, ...args);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if obj is a plain object (not null)
|
||||
* @param {*} obj
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.isPlainObject = function (obj) {
|
||||
return typeof obj === 'object' && obj !== null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an object to an array
|
||||
* @param {*} obj
|
||||
* @return {Array}
|
||||
*/
|
||||
Utils.toArray = function (obj) {
|
||||
if (Array.isArray(obj)) return obj;
|
||||
if (Utils.isPlainObject(obj)) return Object.keys(obj).map(function (key) {
|
||||
return obj[key];
|
||||
});
|
||||
if (!obj) return [];
|
||||
return Array.prototype.slice.call(obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an object to a plain object
|
||||
* @param {*} obj
|
||||
* @return {Object}
|
||||
*/
|
||||
Utils.toPlainObject = function (value) {
|
||||
value = Object(value);
|
||||
const result = {};
|
||||
for (const key in value) {
|
||||
result[key] = value[key];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Picks keys from obj
|
||||
* @param {Object} obj
|
||||
* @param {String[]} keys
|
||||
* @return {Object}
|
||||
*/
|
||||
Utils.pick = function (obj, keys) {
|
||||
return keys.reduce(function (out, key) {
|
||||
out[key] = obj[key];
|
||||
return out;
|
||||
}, {});
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to parse a stream and interpret it as JSON
|
||||
* @param {Stream} stream Stream instance
|
||||
* @param {Function} [options] Optional options for JSON.parse
|
||||
* @param {Function} callback
|
||||
*/
|
||||
Utils.parseBody = function(stream, options, callback) {
|
||||
|
||||
callback = Utils.once(callback);
|
||||
let data = '';
|
||||
|
||||
stream.setEncoding('utf8');
|
||||
|
||||
stream.on('data', function(str) {
|
||||
data += str;
|
||||
});
|
||||
|
||||
stream.on('error', function(err) {
|
||||
callback(err);
|
||||
});
|
||||
|
||||
stream.on('end', function() {
|
||||
utils.JSON.parse(data, options, function(err, request) {
|
||||
if(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
callback(null, request);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a HTTP request listener bound to the server in the argument.
|
||||
* @param {http.Server} self Instance of a HTTP server
|
||||
* @param {JaysonServer} server Instance of JaysonServer (typically jayson.Server)
|
||||
* @return {Function}
|
||||
* @private
|
||||
*/
|
||||
Utils.getHttpListener = function(self, server) {
|
||||
return function(req, res) {
|
||||
const options = self.options || {};
|
||||
|
||||
server.emit('http request', req);
|
||||
|
||||
// 405 method not allowed if not POST
|
||||
if(!Utils.isMethod(req, 'POST')) {
|
||||
return respond('Method Not Allowed', 405, {'allow': 'POST'});
|
||||
}
|
||||
|
||||
// 415 unsupported media type if Content-Type is not correct
|
||||
if(!Utils.isContentType(req, 'application/json')) {
|
||||
return respond('Unsupported Media Type', 415);
|
||||
}
|
||||
|
||||
Utils.parseBody(req, options, function(err, request) {
|
||||
if(err) {
|
||||
return respond(err, 400);
|
||||
}
|
||||
|
||||
server.call(request, function(error, success) {
|
||||
const response = error || success;
|
||||
if(!response) {
|
||||
// no response received at all, must be a notification
|
||||
return respond('', 204);
|
||||
}
|
||||
|
||||
utils.JSON.stringify(response, options, function(err, body) {
|
||||
if(err) {
|
||||
return respond(err, 500);
|
||||
}
|
||||
|
||||
const headers = {
|
||||
'content-length': Buffer.byteLength(body, options.encoding),
|
||||
'content-type': 'application/json; charset=utf-8'
|
||||
};
|
||||
|
||||
respond(body, 200, headers);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function respond(response, code, headers) {
|
||||
const body = response instanceof Error ? response.toString() : response;
|
||||
server.emit('http response', res, req);
|
||||
res.writeHead(code, headers || {});
|
||||
res.end(body);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if a HTTP Request comes with a specific Content-Type
|
||||
* @param {ServerRequest} request
|
||||
* @param {String} type
|
||||
* @return {Boolean}
|
||||
* @private
|
||||
*/
|
||||
Utils.isContentType = function(request, type) {
|
||||
request = request || {headers: {}};
|
||||
const contentType = request.headers['content-type'] || '';
|
||||
return RegExp(type, 'i').test(contentType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if a HTTP Request is of a specific method
|
||||
* @param {ServerRequest} request
|
||||
* @param {String} method
|
||||
* @return {Boolean}
|
||||
* @private
|
||||
*/
|
||||
Utils.isMethod = function(request, method) {
|
||||
method = (method || '').toUpperCase();
|
||||
return (request.method || '') === method;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively walk an object and apply a function on its members
|
||||
* @param {Object} holder The object to walk
|
||||
* @param {String} key The key to look at
|
||||
* @param {Function} fn The function to apply to members
|
||||
* @return {Object}
|
||||
*/
|
||||
Utils.walk = function(holder, key, fn) {
|
||||
let k, v, value = holder[key];
|
||||
if (value && typeof value === 'object') {
|
||||
for (k in value) {
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
||||
v = Utils.walk(value, k, fn);
|
||||
if (v !== undefined) {
|
||||
value[k] = v;
|
||||
} else {
|
||||
delete value[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fn.call(holder, key, value);
|
||||
};
|
||||
|
||||
/** * @namespace */
|
||||
Utils.JSON = {};
|
||||
|
||||
/**
|
||||
* Parses a JSON string and then invokes the given callback
|
||||
* @param {String} str The string to parse
|
||||
* @param {Object} options Object with options, possibly holding a "reviver" function
|
||||
* @param {Function} callback
|
||||
*/
|
||||
Utils.JSON.parse = function(str, options, callback) {
|
||||
let reviver = null;
|
||||
let obj = null;
|
||||
options = options || {};
|
||||
|
||||
if(typeof options.reviver === 'function') {
|
||||
reviver = options.reviver;
|
||||
}
|
||||
|
||||
try {
|
||||
obj = JSON.parse.apply(JSON, [str, reviver].filter(v => v));
|
||||
} catch(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stringifies JSON and then invokes the given callback
|
||||
* @param {Object} obj The object to stringify
|
||||
* @param {Object} options Object with options, possibly holding a "replacer" function
|
||||
* @param {Function} callback
|
||||
*/
|
||||
Utils.JSON.stringify = function(obj, options, callback) {
|
||||
let replacer = null;
|
||||
let str = null;
|
||||
options = options || {};
|
||||
|
||||
if(typeof options.replacer === 'function') {
|
||||
replacer = options.replacer;
|
||||
}
|
||||
|
||||
try {
|
||||
str = JSONstringify.apply(JSON, [obj, replacer].filter(v => v));
|
||||
} catch(err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, str);
|
||||
};
|
||||
|
||||
/** * @namespace */
|
||||
Utils.Request = {};
|
||||
|
||||
/**
|
||||
* Determines if the passed request is a batch request
|
||||
* @param {Object} request The request
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Request.isBatch = function(request) {
|
||||
return Array.isArray(request);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the passed request is a notification request
|
||||
* @param {Object} request The request
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Request.isNotification = function(request) {
|
||||
return Boolean(
|
||||
request
|
||||
&& !Utils.Request.isBatch(request)
|
||||
&& (typeof(request.id) === 'undefined'
|
||||
|| request.id === null)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the passed request is a valid JSON-RPC 2.0 Request
|
||||
* @param {Object} request The request
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Request.isValidVersionTwoRequest = function(request) {
|
||||
return Boolean(
|
||||
request
|
||||
&& typeof(request) === 'object'
|
||||
&& request.jsonrpc === '2.0'
|
||||
&& typeof(request.method) === 'string'
|
||||
&& (
|
||||
typeof(request.params) === 'undefined'
|
||||
|| Array.isArray(request.params)
|
||||
|| (request.params && typeof(request.params) === 'object')
|
||||
)
|
||||
&& (
|
||||
typeof(request.id) === 'undefined'
|
||||
|| typeof(request.id) === 'string'
|
||||
|| typeof(request.id) === 'number'
|
||||
|| request.id === null
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the passed request is a valid JSON-RPC 1.0 Request
|
||||
* @param {Object} request The request
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Request.isValidVersionOneRequest = function(request) {
|
||||
return Boolean(
|
||||
request
|
||||
&& typeof(request) === 'object'
|
||||
&& typeof(request.method) === 'string'
|
||||
&& Array.isArray(request.params)
|
||||
&& typeof(request.id) !== 'undefined'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the passed request is a valid JSON-RPC Request
|
||||
* @param {Object} request The request
|
||||
* @param {Number} [version=2] JSON-RPC version 1 or 2
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Request.isValidRequest = function(request, version) {
|
||||
version = version === 1 ? 1 : 2;
|
||||
return Boolean(
|
||||
request
|
||||
&& (
|
||||
(version === 1 && Utils.Request.isValidVersionOneRequest(request)) ||
|
||||
(version === 2 && Utils.Request.isValidVersionTwoRequest(request))
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/** * @namespace */
|
||||
Utils.Response = {};
|
||||
|
||||
/**
|
||||
* Determines if the passed error is a valid JSON-RPC error response
|
||||
* @param {Object} error The error
|
||||
* @param {Number} [version=2] JSON-RPC version 1 or 2
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Response.isValidError = function(error, version) {
|
||||
version = version === 1 ? 1 : 2;
|
||||
return Boolean(
|
||||
version === 1 && (
|
||||
typeof(error) !== 'undefined'
|
||||
&& error !== null
|
||||
)
|
||||
|| version === 2 && (
|
||||
error
|
||||
&& typeof(error.code) === 'number'
|
||||
&& parseInt(error.code, 10) === error.code
|
||||
&& typeof(error.message) === 'string'
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the passed object is a valid JSON-RPC response
|
||||
* @param {Object} response The response
|
||||
* @param {Number} [version=2] JSON-RPC version 1 or 2
|
||||
* @return {Boolean}
|
||||
*/
|
||||
Utils.Response.isValidResponse = function(response, version) {
|
||||
version = version === 1 ? 1 : 2;
|
||||
return Boolean(
|
||||
response !== null
|
||||
&& typeof response === 'object'
|
||||
&& (version === 2 && (
|
||||
// check version
|
||||
response.jsonrpc === '2.0'
|
||||
&& (
|
||||
// check id
|
||||
response.id === null
|
||||
|| typeof response.id === 'string'
|
||||
|| typeof response.id === 'number'
|
||||
)
|
||||
&& (
|
||||
// result and error do not exist at the same time
|
||||
(typeof response.result === 'undefined' && typeof response.error !== 'undefined')
|
||||
|| (typeof response.result !== 'undefined' && typeof response.error === 'undefined')
|
||||
)
|
||||
&& (
|
||||
// check result
|
||||
(typeof response.result !== 'undefined')
|
||||
// check error object
|
||||
|| (
|
||||
response.error !== null
|
||||
&& typeof response.error === 'object'
|
||||
&& typeof response.error.code === 'number'
|
||||
// check error.code is integer
|
||||
&& ((response.error.code | 0) === response.error.code)
|
||||
&& typeof response.error.message === 'string'
|
||||
)
|
||||
)
|
||||
)
|
||||
|| version === 1 && (
|
||||
typeof response.id !== 'undefined'
|
||||
&& (
|
||||
// result and error relation (the other null if one is not)
|
||||
(typeof response.result !== 'undefined' && response.error === null)
|
||||
|| (typeof response.error !== 'undefined' && response.result === null)
|
||||
)
|
||||
))
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { ArrayOfStringOrObject, RuleListener } from 'eslint/lib/rules/no-restricted-imports';
|
||||
import type { InferMessageIdsTypeFromRule, InferOptionsTypeFromRule } from '../util';
|
||||
declare const baseRule: import("@typescript-eslint/utils/ts-eslint").RuleModule<"everything" | "everythingWithCustomMessage" | "importName" | "importNameWithCustomMessage" | "path" | "pathWithCustomMessage" | "patternWithCustomMessage" | "patterns", ArrayOfStringOrObject | [import("eslint/lib/rules/no-restricted-imports").ObjectOfPathsAndPatterns], unknown, RuleListener>;
|
||||
export type Options = InferOptionsTypeFromRule<typeof baseRule>;
|
||||
export type MessageIds = InferMessageIdsTypeFromRule<typeof baseRule>;
|
||||
declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"everything" | "everythingWithCustomMessage" | "importName" | "importNameWithCustomMessage" | "path" | "pathWithCustomMessage" | "patternWithCustomMessage" | "patterns", ArrayOfStringOrObject | [import("eslint/lib/rules/no-restricted-imports").ObjectOfPathsAndPatterns], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
|
||||
name: string;
|
||||
};
|
||||
export default _default;
|
||||
@@ -0,0 +1,267 @@
|
||||
'use strict'
|
||||
|
||||
/* eslint no-prototype-builtins: 0 */
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert')
|
||||
|
||||
const { sink, once } = require('./helper')
|
||||
const pino = require('../')
|
||||
|
||||
// Silence all warnings for this test
|
||||
process.removeAllListeners('warning')
|
||||
process.on('warning', () => {})
|
||||
|
||||
test('adds additional levels', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
foo: 35,
|
||||
bar: 45
|
||||
}
|
||||
}, stream)
|
||||
|
||||
logger.foo('test')
|
||||
const { level } = await once(stream, 'data')
|
||||
assert.equal(level, 35)
|
||||
})
|
||||
|
||||
test('custom levels does not override default levels', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
foo: 35
|
||||
}
|
||||
}, stream)
|
||||
|
||||
logger.info('test')
|
||||
const { level } = await once(stream, 'data')
|
||||
assert.equal(level, 30)
|
||||
})
|
||||
|
||||
test('default levels can be redefined using custom levels', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
info: 35,
|
||||
debug: 45
|
||||
},
|
||||
useOnlyCustomLevels: true
|
||||
}, stream)
|
||||
|
||||
assert.equal(logger.hasOwnProperty('info'), true)
|
||||
|
||||
logger.info('test')
|
||||
const { level } = await once(stream, 'data')
|
||||
assert.equal(level, 35)
|
||||
})
|
||||
|
||||
test('custom levels overrides default level label if use useOnlyCustomLevels', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
foo: 35
|
||||
},
|
||||
useOnlyCustomLevels: true,
|
||||
level: 'foo'
|
||||
}, stream)
|
||||
|
||||
assert.equal(logger.hasOwnProperty('info'), false)
|
||||
})
|
||||
|
||||
test('custom levels overrides default level value if use useOnlyCustomLevels', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
foo: 35
|
||||
},
|
||||
useOnlyCustomLevels: true,
|
||||
level: 35
|
||||
}, stream)
|
||||
|
||||
assert.equal(logger.hasOwnProperty('info'), false)
|
||||
})
|
||||
|
||||
test('custom levels are inherited by children', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
foo: 35
|
||||
}
|
||||
}, stream)
|
||||
|
||||
logger.child({ childMsg: 'ok' }).foo('test')
|
||||
const { msg, childMsg, level } = await once(stream, 'data')
|
||||
assert.equal(level, 35)
|
||||
assert.equal(childMsg, 'ok')
|
||||
assert.equal(msg, 'test')
|
||||
})
|
||||
|
||||
test('custom levels can be specified on child bindings', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino(stream).child({
|
||||
childMsg: 'ok'
|
||||
}, {
|
||||
customLevels: {
|
||||
foo: 35
|
||||
}
|
||||
})
|
||||
|
||||
logger.foo('test')
|
||||
const { msg, childMsg, level } = await once(stream, 'data')
|
||||
assert.equal(level, 35)
|
||||
assert.equal(childMsg, 'ok')
|
||||
assert.equal(msg, 'test')
|
||||
})
|
||||
|
||||
test('customLevels property child bindings does not get logged', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino(stream).child({
|
||||
childMsg: 'ok'
|
||||
}, {
|
||||
customLevels: {
|
||||
foo: 35
|
||||
}
|
||||
})
|
||||
|
||||
logger.foo('test')
|
||||
const { customLevels } = await once(stream, 'data')
|
||||
assert.equal(customLevels, undefined)
|
||||
})
|
||||
|
||||
test('throws when specifying pre-existing parent labels via child bindings', async () => {
|
||||
const stream = sink()
|
||||
assert.throws(
|
||||
() => pino({
|
||||
customLevels: {
|
||||
foo: 35
|
||||
}
|
||||
}, stream).child({}, {
|
||||
customLevels: {
|
||||
foo: 45
|
||||
}
|
||||
}),
|
||||
/levels cannot be overridden/
|
||||
)
|
||||
})
|
||||
|
||||
test('throws when specifying pre-existing parent values via child bindings', async () => {
|
||||
const stream = sink()
|
||||
assert.throws(
|
||||
() => pino({
|
||||
customLevels: {
|
||||
foo: 35
|
||||
}
|
||||
}, stream).child({}, {
|
||||
customLevels: {
|
||||
bar: 35
|
||||
}
|
||||
}),
|
||||
/pre-existing level values cannot be used for new levels/
|
||||
)
|
||||
})
|
||||
|
||||
test('throws when specifying core values via child bindings', async () => {
|
||||
const stream = sink()
|
||||
assert.throws(
|
||||
() => pino(stream).child({}, {
|
||||
customLevels: {
|
||||
foo: 30
|
||||
}
|
||||
}),
|
||||
/pre-existing level values cannot be used for new levels/
|
||||
)
|
||||
})
|
||||
|
||||
test('throws when useOnlyCustomLevels is set true without customLevels', async () => {
|
||||
const stream = sink()
|
||||
assert.throws(
|
||||
() => pino({
|
||||
useOnlyCustomLevels: true
|
||||
}, stream),
|
||||
/customLevels is required if useOnlyCustomLevels is set true/
|
||||
)
|
||||
})
|
||||
|
||||
test('custom level on one instance does not affect other instances', async () => {
|
||||
pino({
|
||||
customLevels: {
|
||||
foo: 37
|
||||
}
|
||||
})
|
||||
assert.equal(typeof pino().foo, 'undefined')
|
||||
})
|
||||
|
||||
test('setting level below or at custom level will successfully log', async () => {
|
||||
const stream = sink()
|
||||
const instance = pino({ customLevels: { foo: 35 } }, stream)
|
||||
instance.level = 'foo'
|
||||
instance.info('nope')
|
||||
instance.foo('bar')
|
||||
const { msg } = await once(stream, 'data')
|
||||
assert.equal(msg, 'bar')
|
||||
})
|
||||
|
||||
test('custom level below level threshold will not log', async () => {
|
||||
const stream = sink()
|
||||
const instance = pino({ customLevels: { foo: 15 } }, stream)
|
||||
instance.level = 'info'
|
||||
instance.info('bar')
|
||||
instance.foo('nope')
|
||||
const { msg } = await once(stream, 'data')
|
||||
assert.equal(msg, 'bar')
|
||||
})
|
||||
|
||||
test('does not share custom level state across siblings', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino(stream)
|
||||
logger.child({}, {
|
||||
customLevels: { foo: 35 }
|
||||
})
|
||||
assert.doesNotThrow(() => {
|
||||
logger.child({}, {
|
||||
customLevels: { foo: 35 }
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('custom level does not affect the levels serializer', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
foo: 35,
|
||||
bar: 45
|
||||
},
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
return { priority: number }
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
logger.foo('test')
|
||||
const { priority } = await once(stream, 'data')
|
||||
assert.equal(priority, 35)
|
||||
})
|
||||
|
||||
test('When useOnlyCustomLevels is set to true, the level formatter should only get custom levels', async () => {
|
||||
const stream = sink()
|
||||
const logger = pino({
|
||||
customLevels: {
|
||||
answer: 42
|
||||
},
|
||||
useOnlyCustomLevels: true,
|
||||
level: 42,
|
||||
formatters: {
|
||||
level (label, number) {
|
||||
assert.equal(label, 'answer')
|
||||
assert.equal(number, 42)
|
||||
return { level: number }
|
||||
}
|
||||
}
|
||||
}, stream)
|
||||
|
||||
logger.answer('test')
|
||||
const { level } = await once(stream, 'data')
|
||||
assert.equal(level, 42)
|
||||
})
|
||||
Reference in New Issue
Block a user