@pokujs/dom 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ import type { DomAdapter } from './types.ts';
2
+ export type RuntimeSupport = {
3
+ supportsNodeLikeImport: boolean;
4
+ supportsDenoPreload: boolean;
5
+ };
6
+ export type BuildRunnerCommandInput = {
7
+ runtime: string;
8
+ command: string[];
9
+ file: string;
10
+ domSetupPath: string;
11
+ runtimeOptionArgs: string[];
12
+ extensions: Set<string>;
13
+ };
14
+ export type BuildRunnerCommandOutput = {
15
+ shouldHandle: boolean;
16
+ command: string[];
17
+ };
18
+ export declare const isNodeRuntime: (runtime: string) => runtime is "node";
19
+ export declare const getRuntimeSupport: (runtime: string) => RuntimeSupport;
20
+ export declare const canHandleRuntime: (runtime: string) => boolean;
21
+ export declare const createDomSetupPathResolver: (packageTag: string, happyDomSetupPath: string, jsdomSetupPath: string) => (adapter: DomAdapter | undefined) => string;
22
+ export declare const buildRunnerCommand: ({ runtime, command, file, domSetupPath, runtimeOptionArgs, extensions, }: BuildRunnerCommandInput) => BuildRunnerCommandOutput;
@@ -0,0 +1,94 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { extname, resolve } from 'node:path';
3
+ const isTsxImport = (arg) => arg === '--import=tsx' || arg === '--loader=tsx';
4
+ export const isNodeRuntime = (runtime) => runtime === 'node';
5
+ const isBunRuntime = (runtime) => runtime === 'bun';
6
+ const isDenoRuntime = (runtime) => runtime === 'deno';
7
+ export const getRuntimeSupport = (runtime) => ({
8
+ supportsNodeLikeImport: isNodeRuntime(runtime) || isBunRuntime(runtime),
9
+ supportsDenoPreload: isDenoRuntime(runtime),
10
+ });
11
+ export const canHandleRuntime = (runtime) => {
12
+ const support = getRuntimeSupport(runtime);
13
+ return support.supportsNodeLikeImport || support.supportsDenoPreload;
14
+ };
15
+ export const createDomSetupPathResolver = (packageTag, happyDomSetupPath, jsdomSetupPath) => {
16
+ return (adapter) => {
17
+ if (!adapter || adapter === 'happy-dom')
18
+ return happyDomSetupPath;
19
+ if (adapter === 'jsdom')
20
+ return jsdomSetupPath;
21
+ const customPath = resolve(process.cwd(), adapter.setupModule);
22
+ if (!existsSync(customPath)) {
23
+ throw new Error(`[${packageTag}] Custom DOM setup module not found: "${customPath}"\n` +
24
+ 'Check the "dom.setupModule" option in your poku.config.js.');
25
+ }
26
+ return customPath;
27
+ };
28
+ };
29
+ export const buildRunnerCommand = ({ runtime, command, file, domSetupPath, runtimeOptionArgs, extensions, }) => {
30
+ const support = getRuntimeSupport(runtime);
31
+ if (!support.supportsNodeLikeImport && !support.supportsDenoPreload) {
32
+ return { shouldHandle: false, command };
33
+ }
34
+ if (!extensions.has(extname(file))) {
35
+ return { shouldHandle: false, command };
36
+ }
37
+ const fileIndex = command.lastIndexOf(file);
38
+ if (fileIndex === -1)
39
+ return { shouldHandle: false, command };
40
+ const nodeImportFlag = `--import=${domSetupPath}`;
41
+ const denoPreloadFlag = `--preload=${domSetupPath}`;
42
+ const beforeFile = [];
43
+ const afterFile = [];
44
+ let hasTsx = false;
45
+ let hasNodeLikeDomSetup = false;
46
+ let hasDenoDomSetup = false;
47
+ const existingArgs = new Set();
48
+ for (let index = 1; index < command.length; index += 1) {
49
+ const arg = command[index];
50
+ if (typeof arg !== 'string')
51
+ continue;
52
+ existingArgs.add(arg);
53
+ if (index < fileIndex) {
54
+ beforeFile.push(arg);
55
+ if (isTsxImport(arg))
56
+ hasTsx = true;
57
+ else if (arg === nodeImportFlag)
58
+ hasNodeLikeDomSetup = true;
59
+ else if (arg === denoPreloadFlag)
60
+ hasDenoDomSetup = true;
61
+ continue;
62
+ }
63
+ if (index > fileIndex) {
64
+ afterFile.push(arg);
65
+ }
66
+ }
67
+ const extraImports = [];
68
+ if (isNodeRuntime(runtime) && !hasTsx)
69
+ extraImports.push('--import=tsx');
70
+ if (support.supportsNodeLikeImport && !hasNodeLikeDomSetup) {
71
+ extraImports.push(nodeImportFlag);
72
+ }
73
+ if (support.supportsDenoPreload && !hasDenoDomSetup) {
74
+ extraImports.push(denoPreloadFlag);
75
+ }
76
+ const runtimeArgsToInject = [];
77
+ for (const runtimeOptionArg of runtimeOptionArgs) {
78
+ if (existingArgs.has(runtimeOptionArg))
79
+ continue;
80
+ runtimeArgsToInject.push(runtimeOptionArg);
81
+ }
82
+ return {
83
+ shouldHandle: true,
84
+ command: [
85
+ runtime,
86
+ ...beforeFile,
87
+ ...extraImports,
88
+ file,
89
+ ...runtimeArgsToInject,
90
+ ...afterFile,
91
+ ],
92
+ };
93
+ };
94
+ //# sourceMappingURL=plugin-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-command.js","sourceRoot":"","sources":["../src/plugin-command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { DomAdapter, FrameworkDescriptor, TestingPluginOptions } from './types.ts';
2
+ import { buildRunnerCommand, canHandleRuntime } from './plugin-command.ts';
3
+ import { buildRuntimeOptionArgs, createMetricsSummary, getComponentName, isRenderMetricBatchMessage, isRenderMetricMessage, normalizeMetricsOptions, selectTopSlowestMetrics } from './plugin-metrics.ts';
4
+ export type FrameworkPluginInternals = {
5
+ buildRunnerCommand: typeof buildRunnerCommand;
6
+ canHandleRuntime: typeof canHandleRuntime;
7
+ buildRuntimeOptionArgs: typeof buildRuntimeOptionArgs;
8
+ normalizeMetricsOptions: typeof normalizeMetricsOptions;
9
+ selectTopSlowestMetrics: typeof selectTopSlowestMetrics;
10
+ createMetricsSummary: typeof createMetricsSummary;
11
+ getComponentName: typeof getComponentName;
12
+ isRenderMetricMessage: typeof isRenderMetricMessage;
13
+ isRenderMetricBatchMessage: typeof isRenderMetricBatchMessage;
14
+ resolveDomSetupPath: (adapter: DomAdapter | undefined) => string;
15
+ };
16
+ export declare const createFrameworkTestingPluginFactory: (descriptor: FrameworkDescriptor, moduleUrl: string) => {
17
+ createTestingPlugin: (options?: TestingPluginOptions) => any;
18
+ resolveDomSetupPath: (adapter: DomAdapter | undefined) => string;
19
+ runtimeOptionArgPrefixes: import("./types.ts").RuntimeOptionArgPrefixes;
20
+ internals: FrameworkPluginInternals;
21
+ };
@@ -0,0 +1,117 @@
1
+ import { definePlugin } from 'poku/plugins';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { existsSync } from 'node:fs';
5
+ import { buildRunnerCommand, canHandleRuntime, createDomSetupPathResolver, } from "./plugin-command.js";
6
+ import { buildRuntimeOptionArgs, createMetricsSummary, getComponentName, isRenderMetricBatchMessage, isRenderMetricMessage, normalizeMetricsOptions, printMetricsSummary, selectTopSlowestMetrics, } from "./plugin-metrics.js";
7
+ import { setupInProcessEnvironment } from "./plugin-setup.js";
8
+ import { createRuntimeOptionArgPrefixes } from "./runtime-options.js";
9
+ export const createFrameworkTestingPluginFactory = (descriptor, moduleUrl) => {
10
+ const currentDir = dirname(fileURLToPath(moduleUrl));
11
+ const resolveSetupModulePath = (baseName) => {
12
+ const jsPath = resolve(currentDir, `${baseName}.js`);
13
+ if (existsSync(jsPath))
14
+ return jsPath;
15
+ return resolve(currentDir, `${baseName}.ts`);
16
+ };
17
+ const happyDomSetupPath = resolveSetupModulePath('dom-setup-happy');
18
+ const jsdomSetupPath = resolveSetupModulePath('dom-setup-jsdom');
19
+ const resolveDomSetupPath = createDomSetupPathResolver(descriptor.packageTag, happyDomSetupPath, jsdomSetupPath);
20
+ const prefixes = createRuntimeOptionArgPrefixes(descriptor.runtimeArgBase);
21
+ const extensions = new Set(descriptor.testFileExtensions ?? ['.tsx', '.jsx']);
22
+ const createTestingPlugin = (options = {}) => {
23
+ let metrics = [];
24
+ let cleanupNodeTsxLoader;
25
+ const domSetupPath = resolveDomSetupPath(options.dom);
26
+ const metricsOptions = normalizeMetricsOptions(options.metrics);
27
+ const runtimeOptionArgs = buildRuntimeOptionArgs(options, metricsOptions, prefixes);
28
+ return definePlugin({
29
+ name: descriptor.pluginName,
30
+ ipc: metricsOptions.enabled,
31
+ async setup(context) {
32
+ cleanupNodeTsxLoader = await setupInProcessEnvironment({
33
+ isolation: context.configs.isolation,
34
+ runtime: context.runtime,
35
+ runtimeOptionArgs,
36
+ domSetupPath,
37
+ packageTag: descriptor.packageTag,
38
+ });
39
+ },
40
+ runner(command, file) {
41
+ const runtime = command[0];
42
+ if (!runtime)
43
+ return command;
44
+ const result = descriptor.commandBuilder
45
+ ? descriptor.commandBuilder({ runtime, command, file, domSetupPath, runtimeOptionArgs })
46
+ : buildRunnerCommand({ runtime, command, file, domSetupPath, runtimeOptionArgs, extensions });
47
+ if (!result.shouldHandle)
48
+ return command;
49
+ return result.command;
50
+ },
51
+ onTestProcess(child, file) {
52
+ if (!metricsOptions.enabled)
53
+ return;
54
+ const maybePruneMetrics = () => {
55
+ if (metrics.length > metricsOptions.topN * 10) {
56
+ metrics = selectTopSlowestMetrics(metrics, metricsOptions);
57
+ }
58
+ };
59
+ child.on('message', (message) => {
60
+ if (isRenderMetricBatchMessage(message, descriptor.metricBatchMessageType)) {
61
+ for (const metric of message.metrics) {
62
+ const durationMs = Number(metric.durationMs) || 0;
63
+ metrics.push({
64
+ file,
65
+ componentName: getComponentName(metric.componentName),
66
+ durationMs,
67
+ });
68
+ }
69
+ maybePruneMetrics();
70
+ return;
71
+ }
72
+ if (!isRenderMetricMessage(message, descriptor.metricMessageType)) {
73
+ return;
74
+ }
75
+ const durationMs = Number(message.durationMs) || 0;
76
+ metrics.push({
77
+ file,
78
+ componentName: getComponentName(message.componentName),
79
+ durationMs,
80
+ });
81
+ maybePruneMetrics();
82
+ });
83
+ },
84
+ teardown() {
85
+ cleanupNodeTsxLoader?.();
86
+ cleanupNodeTsxLoader = undefined;
87
+ const summary = createMetricsSummary(metrics, metricsOptions);
88
+ if (!summary)
89
+ return;
90
+ if (metricsOptions.reporter) {
91
+ metricsOptions.reporter(summary);
92
+ return;
93
+ }
94
+ printMetricsSummary(summary, descriptor.packageTag);
95
+ },
96
+ });
97
+ };
98
+ const internals = {
99
+ buildRunnerCommand,
100
+ canHandleRuntime,
101
+ buildRuntimeOptionArgs,
102
+ normalizeMetricsOptions,
103
+ selectTopSlowestMetrics,
104
+ createMetricsSummary,
105
+ getComponentName,
106
+ isRenderMetricMessage,
107
+ isRenderMetricBatchMessage,
108
+ resolveDomSetupPath,
109
+ };
110
+ return {
111
+ createTestingPlugin,
112
+ resolveDomSetupPath,
113
+ runtimeOptionArgPrefixes: prefixes,
114
+ internals,
115
+ };
116
+ };
117
+ //# sourceMappingURL=plugin-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-factory.js","sourceRoot":"","sources":["../src/plugin-factory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { MetricsOptions, MetricsSummary, NormalizedMetricsOptions, RenderMetric, RuntimeOptionArgPrefixes, TestingPluginOptions } from './types.ts';
2
+ export declare const isRenderMetricMessage: (message: unknown, metricMessageType: string) => message is {
3
+ type: string;
4
+ componentName?: string;
5
+ durationMs?: number;
6
+ };
7
+ export declare const isRenderMetricBatchMessage: (message: unknown, metricBatchMessageType: string) => message is {
8
+ type: string;
9
+ metrics: Array<{
10
+ componentName?: string;
11
+ durationMs?: number;
12
+ }>;
13
+ };
14
+ export declare const getComponentName: (componentName: unknown) => string;
15
+ export declare const buildRuntimeOptionArgs: (options: TestingPluginOptions, metricsOptions: NormalizedMetricsOptions, prefixes: RuntimeOptionArgPrefixes) => string[];
16
+ export declare const normalizeMetricsOptions: (metrics: boolean | MetricsOptions | undefined) => NormalizedMetricsOptions;
17
+ export declare const selectTopSlowestMetrics: (metrics: RenderMetric[], options: NormalizedMetricsOptions) => RenderMetric[];
18
+ export declare const createMetricsSummary: (metrics: RenderMetric[], options: NormalizedMetricsOptions) => MetricsSummary | null;
19
+ export declare const printMetricsSummary: (summary: MetricsSummary, packageTag: string) => void;
@@ -0,0 +1,93 @@
1
+ const DEFAULT_TOP_N = 5;
2
+ const DEFAULT_MIN_DURATION_MS = 0;
3
+ export const isRenderMetricMessage = (message, metricMessageType) => {
4
+ if (!message || typeof message !== 'object')
5
+ return false;
6
+ return message.type === metricMessageType;
7
+ };
8
+ export const isRenderMetricBatchMessage = (message, metricBatchMessageType) => {
9
+ if (!message || typeof message !== 'object')
10
+ return false;
11
+ const record = message;
12
+ return (record.type === metricBatchMessageType && Array.isArray(record.metrics));
13
+ };
14
+ export const getComponentName = (componentName) => typeof componentName === 'string' && componentName.length > 0
15
+ ? componentName
16
+ : 'AnonymousComponent';
17
+ const getPositiveIntegerOrDefault = (value, fallback) => {
18
+ const numeric = typeof value === 'number'
19
+ ? value
20
+ : typeof value === 'string' && value.trim().length > 0
21
+ ? Number(value.trim())
22
+ : NaN;
23
+ if (!Number.isFinite(numeric) || numeric <= 0)
24
+ return fallback;
25
+ return Math.floor(numeric);
26
+ };
27
+ const getNonNegativeNumberOrDefault = (value, fallback) => {
28
+ const numeric = typeof value === 'number'
29
+ ? value
30
+ : typeof value === 'string' && value.trim().length > 0
31
+ ? Number(value.trim())
32
+ : NaN;
33
+ if (!Number.isFinite(numeric) || numeric < 0)
34
+ return fallback;
35
+ return numeric;
36
+ };
37
+ export const buildRuntimeOptionArgs = (options, metricsOptions, prefixes) => {
38
+ const args = [];
39
+ if (options.domUrl) {
40
+ args.push(`${prefixes.domUrl}${options.domUrl}`);
41
+ }
42
+ if (metricsOptions.enabled) {
43
+ args.push(`${prefixes.metrics}1`);
44
+ args.push(`${prefixes.minMetricMs}${metricsOptions.minDurationMs}`);
45
+ }
46
+ return args;
47
+ };
48
+ export const normalizeMetricsOptions = (metrics) => {
49
+ if (metrics === true) {
50
+ return {
51
+ enabled: true,
52
+ topN: DEFAULT_TOP_N,
53
+ minDurationMs: DEFAULT_MIN_DURATION_MS,
54
+ };
55
+ }
56
+ if (!metrics) {
57
+ return {
58
+ enabled: false,
59
+ topN: DEFAULT_TOP_N,
60
+ minDurationMs: DEFAULT_MIN_DURATION_MS,
61
+ };
62
+ }
63
+ const normalized = {
64
+ enabled: metrics.enabled ?? true,
65
+ topN: getPositiveIntegerOrDefault(metrics.topN, DEFAULT_TOP_N),
66
+ minDurationMs: getNonNegativeNumberOrDefault(metrics.minDurationMs, DEFAULT_MIN_DURATION_MS),
67
+ };
68
+ if (metrics.reporter)
69
+ normalized.reporter = metrics.reporter;
70
+ return normalized;
71
+ };
72
+ export const selectTopSlowestMetrics = (metrics, options) => [...metrics]
73
+ .sort((a, b) => b.durationMs - a.durationMs)
74
+ .slice(0, options.topN);
75
+ export const createMetricsSummary = (metrics, options) => {
76
+ if (!options.enabled || metrics.length === 0)
77
+ return null;
78
+ const topSlowest = selectTopSlowestMetrics(metrics, options);
79
+ if (topSlowest.length === 0)
80
+ return null;
81
+ return {
82
+ totalCaptured: metrics.length,
83
+ totalReported: topSlowest.length,
84
+ topSlowest,
85
+ };
86
+ };
87
+ export const printMetricsSummary = (summary, packageTag) => {
88
+ const lines = summary.topSlowest.map((metric) => ` - ${metric.componentName} in ${metric.file}: ${metric.durationMs.toFixed(2)}ms`);
89
+ console.log(`\n[${packageTag}] Slowest component renders`);
90
+ for (const line of lines)
91
+ console.log(line);
92
+ };
93
+ //# sourceMappingURL=plugin-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-metrics.js","sourceRoot":"","sources":["../src/plugin-metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type InProcessSetupOptions = {
2
+ isolation: string | undefined;
3
+ runtime: string;
4
+ runtimeOptionArgs: string[];
5
+ domSetupPath: string;
6
+ packageTag: string;
7
+ };
8
+ export declare const setupInProcessEnvironment: (options: InProcessSetupOptions) => Promise<(() => void) | undefined>;
@@ -0,0 +1,60 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { pathToFileURL } from 'node:url';
10
+ import { createRequire } from 'node:module';
11
+ import { canHandleRuntime, isNodeRuntime } from "./plugin-command.js";
12
+ const TSX_LOADER_MODULE = 'tsx/esm/api';
13
+ // Once tsx is registered in a Node.js process it cannot be safely deregistered
14
+ // and re-registered (tsx's hook worker re-instantiation fails with an invalid
15
+ // URL scheme). Under isolation:'none' everything runs in the same process for
16
+ // its lifetime, so keeping the loader registered permanently is correct.
17
+ const TSX_LOADER_REGISTERED_KEY = Symbol.for('@pokujs/dom.tsx-loader-registered');
18
+ const appendMissingRuntimeArgs = (runtimeOptionArgs) => {
19
+ for (const arg of runtimeOptionArgs) {
20
+ if (process.argv.includes(arg))
21
+ continue;
22
+ process.argv.push(arg);
23
+ }
24
+ };
25
+ const loadDomSetupModule = async (domSetupPath) => {
26
+ await import(__rewriteRelativeImportExtension(pathToFileURL(domSetupPath).href));
27
+ };
28
+ const registerNodeTsxLoader = async (packageTag) => {
29
+ const g = globalThis;
30
+ if (g[TSX_LOADER_REGISTERED_KEY])
31
+ return () => { };
32
+ const requireFromCwd = createRequire(`${process.cwd()}/`);
33
+ try {
34
+ const resolvedModulePath = requireFromCwd.resolve(TSX_LOADER_MODULE);
35
+ const mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(resolvedModulePath).href)));
36
+ if (typeof mod.register !== 'function') {
37
+ throw new Error('Missing register() export from tsx loader API');
38
+ }
39
+ mod.register();
40
+ g[TSX_LOADER_REGISTERED_KEY] = true;
41
+ return () => { };
42
+ }
43
+ catch (error) {
44
+ throw new Error(`[${packageTag}] isolation "none" in Node.js requires a working "tsx" installation to load .tsx/.jsx test files.`, { cause: error });
45
+ }
46
+ };
47
+ export const setupInProcessEnvironment = async (options) => {
48
+ if (options.isolation !== 'none')
49
+ return undefined;
50
+ if (!canHandleRuntime(options.runtime))
51
+ return undefined;
52
+ let cleanupNodeTsxLoader;
53
+ if (isNodeRuntime(options.runtime)) {
54
+ cleanupNodeTsxLoader = await registerNodeTsxLoader(options.packageTag);
55
+ }
56
+ appendMissingRuntimeArgs(options.runtimeOptionArgs);
57
+ await loadDomSetupModule(options.domSetupPath);
58
+ return cleanupNodeTsxLoader;
59
+ };
60
+ //# sourceMappingURL=plugin-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-setup.js","sourceRoot":"","sources":["../src/plugin-setup.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMtE,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAExC,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,yEAAyE;AACzE,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;AAGlF,MAAM,wBAAwB,GAAG,CAAC,iBAA2B,EAAE,EAAE;IAC/D,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACpC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACzC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,YAAoB,EAAE,EAAE;IACxD,MAAM,MAAM,kCAAC,aAAa,CAAC,YAAY,CAAC,CAAC,IAAI,EAAC,CAAC;AACjD,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,KAAK,EAAE,UAAkB,EAAuB,EAAE;IAC9E,MAAM,CAAC,GAAG,UAA+B,CAAC;IAE1C,IAAI,CAAC,CAAC,yBAAyB,CAAC;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAElD,MAAM,cAAc,GAAG,aAAa,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE1D,IAAI,CAAC;QACH,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACrE,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,kCAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAC,CAAoB,CAAC;QACtF,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,GAAG,CAAC,QAAQ,EAAE,CAAC;QACf,CAAC,CAAC,yBAAyB,CAAC,GAAG,IAAI,CAAC;QACpC,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,IAAI,UAAU,mGAAmG,EACjH,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAUF,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAC5C,OAA8B,EACK,EAAE;IACrC,IAAI,OAAO,CAAC,SAAS,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACnD,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzD,IAAI,oBAA8C,CAAC;IAEnD,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,oBAAoB,GAAG,MAAM,qBAAqB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IAED,wBAAwB,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACpD,MAAM,kBAAkB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAE/C,OAAO,oBAAoB,CAAC;AAC9B,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RuntimeOptionArgPrefixes, RuntimeOptions } from './types.ts';
2
+ export declare const createRuntimeOptionArgPrefixes: (base: string) => RuntimeOptionArgPrefixes;
3
+ export declare const parseRuntimeOptions: (prefixes: RuntimeOptionArgPrefixes, argv?: string[]) => RuntimeOptions;
@@ -0,0 +1,48 @@
1
+ const DEFAULT_DOM_URL = 'http://localhost:3000/';
2
+ const DEFAULT_METRIC_BATCH_SIZE = 50;
3
+ const DEFAULT_METRIC_FLUSH_MS = 50;
4
+ const toNumber = (value) => {
5
+ if (!value)
6
+ return NaN;
7
+ const parsed = Number(value);
8
+ return Number.isFinite(parsed) ? parsed : NaN;
9
+ };
10
+ const findValueByPrefix = (argv, prefix) => {
11
+ const match = argv.find((arg) => arg.startsWith(prefix));
12
+ return match ? match.slice(prefix.length) : undefined;
13
+ };
14
+ const parsePositiveInteger = (value, fallback) => {
15
+ const numeric = toNumber(value);
16
+ if (!Number.isFinite(numeric) || numeric <= 0)
17
+ return fallback;
18
+ return Math.floor(numeric);
19
+ };
20
+ const parseNonNegativeNumber = (value, fallback) => {
21
+ const numeric = toNumber(value);
22
+ if (!Number.isFinite(numeric) || numeric < 0)
23
+ return fallback;
24
+ return numeric;
25
+ };
26
+ export const createRuntimeOptionArgPrefixes = (base) => ({
27
+ metrics: `--${base}-metrics=`,
28
+ minMetricMs: `--${base}-min-metric-ms=`,
29
+ domUrl: `--${base}-dom-url=`,
30
+ metricBatchSize: `--${base}-metric-batch-size=`,
31
+ metricFlushMs: `--${base}-metric-flush-ms=`,
32
+ });
33
+ export const parseRuntimeOptions = (prefixes, argv = process.argv) => {
34
+ const metricsEnabled = findValueByPrefix(argv, prefixes.metrics) === '1' ||
35
+ findValueByPrefix(argv, prefixes.metrics) === 'true';
36
+ const domUrl = findValueByPrefix(argv, prefixes.domUrl)?.trim() || DEFAULT_DOM_URL;
37
+ const minMetricMs = parseNonNegativeNumber(findValueByPrefix(argv, prefixes.minMetricMs), 0);
38
+ const metricBatchSize = parsePositiveInteger(findValueByPrefix(argv, prefixes.metricBatchSize), DEFAULT_METRIC_BATCH_SIZE);
39
+ const metricFlushMs = parsePositiveInteger(findValueByPrefix(argv, prefixes.metricFlushMs), DEFAULT_METRIC_FLUSH_MS);
40
+ return {
41
+ domUrl,
42
+ metricsEnabled,
43
+ minMetricMs,
44
+ metricBatchSize,
45
+ metricFlushMs,
46
+ };
47
+ };
48
+ //# sourceMappingURL=runtime-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-options.js","sourceRoot":"","sources":["../src/runtime-options.ts"],"names":[],"mappings":"AAKA,MAAM,eAAe,GAAG,wBAAwB,CAAC;AACjD,MAAM,yBAAyB,GAAG,EAAE,CAAC;AACrC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAEnC,MAAM,QAAQ,GAAG,CAAC,KAAyB,EAAE,EAAE;IAC7C,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC;IACvB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,IAAc,EAAE,MAAc,EAAE,EAAE;IAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,KAAyB,EAAE,QAAgB,EAAE,EAAE;IAC3E,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAAC,KAAyB,EAAE,QAAgB,EAAE,EAAE;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9D,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAC5C,IAAY,EACc,EAAE,CAAC,CAAC;IAC9B,OAAO,EAAE,KAAK,IAAI,WAAW;IAC7B,WAAW,EAAE,KAAK,IAAI,iBAAiB;IACvC,MAAM,EAAE,KAAK,IAAI,WAAW;IAC5B,eAAe,EAAE,KAAK,IAAI,qBAAqB;IAC/C,aAAa,EAAE,KAAK,IAAI,mBAAmB;CAC5C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,QAAkC,EAClC,OAAiB,OAAO,CAAC,IAAI,EACb,EAAE;IAClB,MAAM,cAAc,GAClB,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,GAAG;QACjD,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,KAAK,MAAM,CAAC;IAEvD,MAAM,MAAM,GACV,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,eAAe,CAAC;IAEtE,MAAM,WAAW,GAAG,sBAAsB,CACxC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC7C,CAAC,CACF,CAAC;IAEF,MAAM,eAAe,GAAG,oBAAoB,CAC1C,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,eAAe,CAAC,EACjD,yBAAyB,CAC1B,CAAC;IAEF,MAAM,aAAa,GAAG,oBAAoB,CACxC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/C,uBAAuB,CACxB,CAAC;IAEF,OAAO;QACL,MAAM;QACN,cAAc;QACd,WAAW;QACX,eAAe;QACf,aAAa;KACd,CAAC;AACJ,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Screen } from '@testing-library/dom';
2
+ import type { RuntimeOptions } from './types.ts';
3
+ export declare const getNow: () => number;
4
+ export type RenderMetricsEmitterOptions = {
5
+ runtimeOptions: RuntimeOptions;
6
+ metricsStateKey: symbol;
7
+ metricsBatchMessageType: string;
8
+ };
9
+ export declare const createRenderMetricsEmitter: (options: RenderMetricsEmitterOptions) => {
10
+ emitRenderMetric: (componentName: string, durationMs: number) => void;
11
+ flushMetricBuffer: () => void;
12
+ clearMetricFlushTimer: () => void;
13
+ };
14
+ export declare const createScreen: () => Screen;