Open
chore(npm): sync source and docs to the published @liu_wentao/cptf-* names #58
chore(npm): sync source and docs to the published @liu_wentao/cptf-* names #58
Open
liu_wentaoAdd on 26 days ago
Total: 57 files changed+1331-1096
M.cspell.json+37-0File content is under review, please try again later
@@ -8,13 +8,13 @@
8 "postinstall": "pnpm run _setup:hooks",8 "postinstall": "pnpm run _setup:hooks",
9 "_setup:hooks": "node -e \"try{const cp=require('child_process'),fs=require('fs');cp.execSync('git config core.hooksPath .husky',{stdio:'inherit'});if(fs.existsSync('.quality-toolkit/templates/gitmessage'))cp.execSync('git config commit.template .quality-toolkit/templates/gitmessage',{stdio:'inherit'})}catch(e){console.warn('[postinstall] git or repository unavailable, skip hook setup')}\"",9 "_setup:hooks": "node -e \"try{const cp=require('child_process'),fs=require('fs');cp.execSync('git config core.hooksPath .husky',{stdio:'inherit'});if(fs.existsSync('.quality-toolkit/templates/gitmessage'))cp.execSync('git config commit.template .quality-toolkit/templates/gitmessage',{stdio:'inherit'})}catch(e){console.warn('[postinstall] git or repository unavailable, skip hook setup')}\"",
10 "build": "pnpm -r build",10 "build": "pnpm -r build",
11- "build:framework": "pnpm --filter @cptf/framework build",11+ "build:framework": "pnpm --filter @liu_wentao/cptf-framework build",
12- "build:benchmark": "pnpm --filter @cptf/benchmark build",12+ "build:benchmark": "pnpm --filter @liu_wentao/cptf-benchmark build",
13- "dev:framework": "pnpm --filter @cptf/framework dev",13+ "dev:framework": "pnpm --filter @liu_wentao/cptf-framework dev",
14- "test": "pnpm --filter @cptf/framework test",14+ "test": "pnpm --filter @liu_wentao/cptf-framework test",
15 "typecheck": "pnpm -r typecheck",15 "typecheck": "pnpm -r typecheck",
16 "clean": "pnpm -r clean",16 "clean": "pnpm -r clean",
17- "pack": "pnpm --filter \"@cptf/*\" run pack",17+ "pack": "pnpm --filter \"@liu_wentao/cptf-*\" run pack",
18 "install:all": "pnpm install",18 "install:all": "pnpm install",
19 "_harness": "node ./.quality-toolkit/tools/harness/harness.js",19 "_harness": "node ./.quality-toolkit/tools/harness/harness.js",
20 "harness": "node ./.quality-toolkit/tools/harness/harness.js",20 "harness": "node ./.quality-toolkit/tools/harness/harness.js",
Mpackages/benchmark-rn/README.md+78-48File content is under review, please try again later
Mpackages/benchmark-rn/harmony/benchmarkrn/oh-package.json5+3-3File content is under review, please try again later
@@ -1,6 +1,6 @@
1{1{
2- "name": "@cptf/benchmark-rn",2+ "name": "@liu_wentao/cptf-benchmark-rn",
3- "version": "0.1.0",3+ "version": "0.2.0",
4 "description": "Device-side React Native benchmark components (MeasureContainer, metric providers) and native implementations consumed by metro",4 "description": "Device-side React Native benchmark components (MeasureContainer, metric providers) and native implementations consumed by metro",
5 "main": "src/index",5 "main": "src/index",
6 "scripts": {6 "scripts": {
@@ -15,7 +15,7 @@
15 }15 }
16 },16 },
17 "dependencies": {17 "dependencies": {
18- "@cptf/benchmark": "workspace:*"18+ "@liu_wentao/cptf-benchmark": "workspace:*"
19 },19 },
20 "author": "gaoyang <gyange@163.com>",20 "author": "gaoyang <gyange@163.com>",
21 "license": "MIT",21 "license": "MIT",
Mpackages/benchmark-rn/src/MeasureContainer.tsx+1-1File content is under review, please try again later
Mpackages/benchmark-rn/src/device-metric-provider.ts+1-1File content is under review, please try again later
Mpackages/benchmark-rn/src/index.tsx+4-1File content is under review, please try again later
Mpackages/benchmark/README.md+52-33File content is under review, please try again later
@@ -1,7 +1,7 @@
1{1{
2- "name": "@cptf/benchmark",2+ "name": "@liu_wentao/cptf-benchmark",
3- "version": "0.1.0",3+ "version": "0.2.0",
4- "description": "Preset metric collectors (renderTime / unmountTime) extending @cptf/framework for React Native component benchmarks",4+ "description": "Preset metric collectors (renderTime / unmountTime) extending @liu_wentao/cptf-framework for React Native component benchmarks",
5 "main": "dist/index.js",5 "main": "dist/index.js",
6 "types": "dist/index.d.ts",6 "types": "dist/index.d.ts",
7 "exports": {7 "exports": {
@@ -42,7 +42,7 @@
42 "LICENSE"42 "LICENSE"
43 ],43 ],
44 "dependencies": {44 "dependencies": {
45- "@cptf/framework": "workspace:*"45+ "@liu_wentao/cptf-framework": "workspace:*"
46 },46 },
47 "devDependencies": {47 "devDependencies": {
48 "@types/node": "^20.0.0",48 "@types/node": "^20.0.0",
Mpackages/benchmark/src/index.ts+1-1File content is under review, please try again later
@@ -3,11 +3,9 @@ import { RENDER_TIME_METRIC_TYPE, BENCHMARK_PHASE } from '../metric-types';
3 * Copyright 2026 gaoyang (gyange@163.com)3 * Copyright 2026 gaoyang (gyange@163.com)
4 * SPDX-License-Identifier: MIT4 * SPDX-License-Identifier: MIT
5 */5 */
6-import { BaseMetricCollector, MetricCollectorContext, createLogger } from '@cptf/framework';6+import { BaseMetricCollector, MetricCollectorContext, createLogger } from '@liu_wentao/cptf-framework';
7import { MetricBridge, MetricEvent, Unsubscribe } from '../metric-bridge';7import { MetricBridge, MetricEvent, Unsubscribe } from '../metric-bridge';
8 8 
9- 
10- 
11export class RenderTimeCollector extends BaseMetricCollector {9export class RenderTimeCollector extends BaseMetricCollector {
12 type = RENDER_TIME_METRIC_TYPE;10 type = RENDER_TIME_METRIC_TYPE;
13 private value = 0;11 private value = 0;
@@ -20,7 +18,9 @@ export class RenderTimeCollector extends BaseMetricCollector {
20 18 
21 private deviceId: string | null = null;19 private deviceId: string | null = null;
22 20 
23- private static readonly logger = createLogger({ level: (process.env.CPTF_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error' | undefined) || 'info' });21+ private static readonly logger = createLogger({
22+ level: (process.env.CPTF_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error' | undefined) || 'info',
23+ });
24 private log(msg: string): void {24 private log(msg: string): void {
25 RenderTimeCollector.logger.debug(msg);25 RenderTimeCollector.logger.debug(msg);
26 }26 }
@@ -30,10 +30,14 @@ export class RenderTimeCollector extends BaseMetricCollector {
30 this.startTime = Date.now();30 this.startTime = Date.now();
31 this.deviceId = ctx.device?.id || null;31 this.deviceId = ctx.device?.id || null;
32 this.log(`onStart: deviceId=${this.deviceId} startTime=${this.startTime}`);32 this.log(`onStart: deviceId=${this.deviceId} startTime=${this.startTime}`);
33- this.unsub = this.bridge.subscribe<MetricEvent>(`renderTime:${this.deviceId}`, (event) => {33+ this.unsub = this.bridge.subscribe<MetricEvent>(`renderTime:${this.deviceId}`, event => {
34 if (event && typeof event.value === 'number') {34 if (event && typeof event.value === 'number') {
35 if (event.timestamp && event.timestamp < this.startTime - 5000) {35 if (event.timestamp && event.timestamp < this.startTime - 5000) {
36- this.log(`event rejected: stale timestamp (event=${event.timestamp} startTime=${this.startTime} diff=${event.timestamp - this.startTime}ms)`);36+ this.log(
37+ `event rejected: stale timestamp (event=${event.timestamp} startTime=${this.startTime} diff=${
38+ event.timestamp - this.startTime
39+ }ms)`
40+ );
37 return;41 return;
38 }42 }
39 this.value = event.value;43 this.value = event.value;
@@ -3,11 +3,9 @@ import { UNMOUNT_TIME_METRIC_TYPE, BENCHMARK_PHASE } from '../metric-types';
3 * Copyright 2026 gaoyang (gyange@163.com)3 * Copyright 2026 gaoyang (gyange@163.com)
4 * SPDX-License-Identifier: MIT4 * SPDX-License-Identifier: MIT
5 */5 */
6-import { BaseMetricCollector, MetricCollectorContext, createLogger } from '@cptf/framework';6+import { BaseMetricCollector, MetricCollectorContext, createLogger } from '@liu_wentao/cptf-framework';
7import { MetricBridge, MetricEvent, Unsubscribe } from '../metric-bridge';7import { MetricBridge, MetricEvent, Unsubscribe } from '../metric-bridge';
8 8 
9- 
10- 
11export class UnmountTimeCollector extends BaseMetricCollector {9export class UnmountTimeCollector extends BaseMetricCollector {
12 type = UNMOUNT_TIME_METRIC_TYPE;10 type = UNMOUNT_TIME_METRIC_TYPE;
13 private value = 0;11 private value = 0;
@@ -20,7 +18,9 @@ export class UnmountTimeCollector extends BaseMetricCollector {
20 18 
21 private deviceId: string | null = null;19 private deviceId: string | null = null;
22 20 
23- private static readonly logger = createLogger({ level: (process.env.CPTF_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error' | undefined) || 'info' });21+ private static readonly logger = createLogger({
22+ level: (process.env.CPTF_LOG_LEVEL as 'debug' | 'info' | 'warn' | 'error' | undefined) || 'info',
23+ });
24 private log(msg: string): void {24 private log(msg: string): void {
25 UnmountTimeCollector.logger.debug(msg);25 UnmountTimeCollector.logger.debug(msg);
26 }26 }
@@ -30,7 +30,7 @@ export class UnmountTimeCollector extends BaseMetricCollector {
30 this.startTime = Date.now();30 this.startTime = Date.now();
31 this.deviceId = ctx.device?.id || null;31 this.deviceId = ctx.device?.id || null;
32 this.log(`onStart: deviceId=${this.deviceId} startTime=${this.startTime}`);32 this.log(`onStart: deviceId=${this.deviceId} startTime=${this.startTime}`);
33- this.unsub = this.bridge.subscribe<MetricEvent>(`unmountTime:${this.deviceId}`, (event) => {33+ this.unsub = this.bridge.subscribe<MetricEvent>(`unmountTime:${this.deviceId}`, event => {
34 if (event && typeof event.value === 'number') {34 if (event && typeof event.value === 'number') {
35 if (event.timestamp && event.timestamp < this.startTime - 5000) {35 if (event.timestamp && event.timestamp < this.startTime - 5000) {
36 this.log(`event rejected: stale timestamp (event=${event.timestamp} startTime=${this.startTime})`);36 this.log(`event rejected: stale timestamp (event=${event.timestamp} startTime=${this.startTime})`);
Mpackages/framework/BUILD.md+14-12File content is under review, please try again later
Mpackages/framework/CHANGELOG.md+6-0File content is under review, please try again later
Mpackages/framework/README.md+4-3File content is under review, please try again later
Mpackages/framework/docs/MIGRATION.md+4-4File content is under review, please try again later
Mpackages/framework/docs/PERFORMANCE-TUNING.md+3-3File content is under review, please try again later
Mpackages/framework/docs/advanced/EXPECT-GUIDE.md+79-73File content is under review, please try again later
Mpackages/framework/docs/advanced/IMPERATIVE-TEST-GUIDE.md+86-91File content is under review, please try again later
Mpackages/framework/docs/advanced/UI-COMPARISON.md+37-36File content is under review, please try again later
Mpackages/framework/docs/architecture/ARCHITECTURE-OVERVIEW.md+74-73File content is under review, please try again later
Mpackages/framework/docs/architecture/ARCHITECTURE-VIEWS.md+39-38File content is under review, please try again later
Mpackages/framework/docs/architecture/CAPABILITY-SPEC.md+5-5File content is under review, please try again later
Mpackages/framework/docs/architecture/DEVICE-NATIVE-ARCHITECTURE.md+31-32File content is under review, please try again later
Mpackages/framework/docs/architecture/PERFORMANCE-METRICS-SPEC.md+15-15File content is under review, please try again later
Mpackages/framework/docs/architecture/STABILITY-SPEC.md+1-1File content is under review, please try again later
@@ -77,7 +77,7 @@
77 <text x="365" y="276" text-anchor="middle" font-size="9" fill="#fff">UnmountTimeCollector</text>77 <text x="365" y="276" text-anchor="middle" font-size="9" fill="#fff">UnmountTimeCollector</text>
78 <rect x="480" y="258" width="160" height="28" rx="6" fill="url(#gBenchmark)" opacity="0.7"/>78 <rect x="480" y="258" width="160" height="28" rx="6" fill="url(#gBenchmark)" opacity="0.7"/>
79 <text x="560" y="276" text-anchor="middle" font-size="9" fill="#fff">BENCHMARK_PHASE</text>79 <text x="560" y="276" text-anchor="middle" font-size="9" fill="#fff">BENCHMARK_PHASE</text>
80- <text x="660" y="276" font-size="9" fill="#c7d2fe">(@cptf/benchmark 包, phase 常量定义于此)</text>80+ <text x="660" y="276" font-size="9" fill="#c7d2fe">(@liu_wentao/cptf-benchmark 包, phase 常量定义于此)</text>
81 81 
82 <!-- ===== 系统层 ===== -->82 <!-- ===== 系统层 ===== -->
83 <g filter="url(#sh)"><rect x="30" y="310" width="1140" height="200" rx="10" fill="url(#gSys)" opacity="0.95"/></g>83 <g filter="url(#sh)"><rect x="30" y="310" width="1140" height="200" rx="10" fill="url(#gSys)" opacity="0.95"/></g>
@@ -167,5 +167,5 @@
167 <rect x="40" y="730" width="14" height="14" rx="3" fill="url(#gSched)"/><text x="60" y="741" font-size="9" fill="#64748b">调度层 (原能力层+编排层)</text>167 <rect x="40" y="730" width="14" height="14" rx="3" fill="url(#gSched)"/><text x="60" y="741" font-size="9" fill="#64748b">调度层 (原能力层+编排层)</text>
168 <rect x="210" y="730" width="14" height="14" rx="3" fill="url(#gSys)"/><text x="230" y="741" font-size="9" fill="#64748b">系统层 (平台抽象+Agent)</text>168 <rect x="210" y="730" width="14" height="14" rx="3" fill="url(#gSys)"/><text x="230" y="741" font-size="9" fill="#64748b">系统层 (平台抽象+Agent)</text>
169 <rect x="370" y="730" width="14" height="14" rx="3" fill="url(#gInfra)"/><text x="390" y="741" font-size="9" fill="#64748b">基础设施层 (原基础层+基础设施层)</text>169 <rect x="370" y="730" width="14" height="14" rx="3" fill="url(#gInfra)"/><text x="390" y="741" font-size="9" fill="#64748b">基础设施层 (原基础层+基础设施层)</text>
170- <rect x="600" y="730" width="14" height="14" rx="3" fill="url(#gBenchmark)"/><text x="620" y="741" font-size="9" fill="#64748b">@cptf/benchmark (phase常量)</text>170+ <rect x="600" y="730" width="14" height="14" rx="3" fill="url(#gBenchmark)"/><text x="620" y="741" font-size="9" fill="#64748b">@liu_wentao/cptf-benchmark (phase常量)</text>
171</svg>171</svg>
@@ -50,7 +50,7 @@
50 <text x="415" y="245" font-weight="600" font-size="9" fill="#c4b5fd">phase: BENCHMARK_PHASE.RENDER</text>50 <text x="415" y="245" font-weight="600" font-size="9" fill="#c4b5fd">phase: BENCHMARK_PHASE.RENDER</text>
51 <text x="415" y="260" font-size="9" fill="#ede9fe">waitForStable: 300</text>51 <text x="415" y="260" font-size="9" fill="#ede9fe">waitForStable: 300</text>
52 <text x="415" y="275" font-size="9" fill="#ede9fe">→ 触发 onStepComplete(phase)</text>52 <text x="415" y="275" font-size="9" fill="#ede9fe">→ 触发 onStepComplete(phase)</text>
53- <text x="415" y="287" font-size="9" fill="#ede9fe">phase 常量定义在 @cptf/benchmark</text>53+ <text x="415" y="287" font-size="9" fill="#ede9fe">phase 常量定义在 @liu_wentao/cptf-benchmark</text>
54 </g>54 </g>
55 55 
56 <g filter="url(#sh)">56 <g filter="url(#sh)">
Mpackages/framework/docs/development/METRIC-COLLECTOR-GUIDE.md+9-4File content is under review, please try again later
Mpackages/framework/docs/development/PLUGIN-GUIDE.md+147-111File content is under review, please try again later
Mpackages/framework/docs/getting-started/DECLARATIVE-TEST-GUIDE.md+186-190File content is under review, please try again later
Mpackages/framework/docs/getting-started/USER-GUIDE.md+166-168File content is under review, please try again later
@@ -1,6 +1,6 @@
1{1{
2- "name": "@cptf/framework",2+ "name": "@liu_wentao/cptf-framework",
3- "version": "0.1.0",3+ "version": "0.2.0",
4 "description": "Cross-Platform Test Framework for React Native (HarmonyOS / Android / iOS): declarative @Test/@Step cases, dual-mode native/external drivers, performance metrics, stability detectors and cross-platform UI comparison",4 "description": "Cross-Platform Test Framework for React Native (HarmonyOS / Android / iOS): declarative @Test/@Step cases, dual-mode native/external drivers, performance metrics, stability detectors and cross-platform UI comparison",
5 "main": "dist/index.js",5 "main": "dist/index.js",
6 "types": "dist/index.d.ts",6 "types": "dist/index.d.ts",
@@ -58,7 +58,7 @@
58 "directory": "packages/framework"58 "directory": "packages/framework"
59 },59 },
60 "dependencies": {60 "dependencies": {
61- "@cptf/schema": "workspace:*",61+ "@liu_wentao/cptf-schema": "workspace:*",
62 "chalk": "^4.1.2",62 "chalk": "^4.1.2",
63 "commander": "^11.1.0",63 "commander": "^11.1.0",
64 "jimp": "^1.6.1",64 "jimp": "^1.6.1",
@@ -8,7 +8,12 @@ jest.mock('child_process');
8 8 
9import * as fsp from 'fs/promises';9import * as fsp from 'fs/promises';
10import * as path from 'path';10import * as path from 'path';
11-import { scanTestCasesLazy, groupByScene, groupByModule, clearScanCache } from '../../infrastructure/config/lazy-scanner';11+import {
12+ scanTestCasesLazy,
13+ groupByScene,
14+ groupByModule,
15+ clearScanCache,
16+} from '../../infrastructure/config/lazy-scanner';
12import { TEST_FILE_RE, NAV_ID_PATTERN, parseTestCaseFromContent } from '../../infrastructure/config/case-parser';17import { TEST_FILE_RE, NAV_ID_PATTERN, parseTestCaseFromContent } from '../../infrastructure/config/case-parser';
13 18 
14describe('lazy-scanner 100%', () => {19describe('lazy-scanner 100%', () => {
@@ -21,7 +26,7 @@ describe('lazy-scanner 100%', () => {
21 (fsp.stat as jest.Mock).mockResolvedValue({ isDirectory: () => true });26 (fsp.stat as jest.Mock).mockResolvedValue({ isDirectory: () => true });
22 (fsp.access as jest.Mock).mockResolvedValue(undefined);27 (fsp.access as jest.Mock).mockResolvedValue(undefined);
23 (fsp.readFile as jest.Mock).mockResolvedValue(`28 (fsp.readFile as jest.Mock).mockResolvedValue(`
24- import { Test } from '@cptf/framework';29+ import { Test } from '@liu_wentao/cptf-framework';
25 @Test({ id: 'test-1', name: 'Test 1', module: 'functional' })30 @Test({ id: 'test-1', name: 'Test 1', module: 'functional' })
26 export class Test1 {}31 export class Test1 {}
27 `);32 `);
@@ -36,7 +41,13 @@ describe('lazy-scanner 100%', () => {
36 (fsp.stat as jest.Mock).mockResolvedValue({ mtimeMs: 1000, size: 100 });41 (fsp.stat as jest.Mock).mockResolvedValue({ mtimeMs: 1000, size: 100 });
37 (fsp.readFile as jest.Mock).mockImplementation(async (p: string) => {42 (fsp.readFile as jest.Mock).mockImplementation(async (p: string) => {
38 if (String(p).includes('scan-cache')) {43 if (String(p).includes('scan-cache')) {
39- return JSON.stringify({ version: 1, casesDir: '/tmp/cases', fingerprint: 'abc', cases: [], builtAt: Date.now() });44+ return JSON.stringify({
45+ version: 1,
46+ casesDir: '/tmp/cases',
47+ fingerprint: 'abc',
48+ cases: [],
49+ builtAt: Date.now(),
50+ });
40 }51 }
41 return '';52 return '';
42 });53 });
@@ -117,7 +128,14 @@ describe('lazy-scanner 100%', () => {
117 (fsp.readdir as jest.Mock).mockResolvedValue([]);128 (fsp.readdir as jest.Mock).mockResolvedValue([]);
118 (fsp.stat as jest.Mock).mockResolvedValue({ isDirectory: () => false, mtimeMs: 1000, size: 100 });129 (fsp.stat as jest.Mock).mockResolvedValue({ isDirectory: () => false, mtimeMs: 1000, size: 100 });
119 (fsp.readFile as jest.Mock).mockImplementation(async (p: string) => {130 (fsp.readFile as jest.Mock).mockImplementation(async (p: string) => {
120- if (String(p).includes('cache')) return JSON.stringify({ version: 999, casesDir: '/tmp/cases', fingerprint: 'abc', cases: [], builtAt: Date.now() });131+ if (String(p).includes('cache'))
132+ return JSON.stringify({
133+ version: 999,
134+ casesDir: '/tmp/cases',
135+ fingerprint: 'abc',
136+ cases: [],
137+ builtAt: Date.now(),
138+ });
121 return '';139 return '';
122 });140 });
123 const result = await scanTestCasesLazy('/tmp/cases', { cache: true, cachePath: '/tmp/cache.json' });141 const result = await scanTestCasesLazy('/tmp/cases', { cache: true, cachePath: '/tmp/cache.json' });
@@ -129,7 +147,8 @@ describe('lazy-scanner 100%', () => {
129 (fsp.readdir as jest.Mock).mockResolvedValue([]);147 (fsp.readdir as jest.Mock).mockResolvedValue([]);
130 (fsp.stat as jest.Mock).mockResolvedValue({ isDirectory: () => false, mtimeMs: 1000, size: 100 });148 (fsp.stat as jest.Mock).mockResolvedValue({ isDirectory: () => false, mtimeMs: 1000, size: 100 });
131 (fsp.readFile as jest.Mock).mockImplementation(async (p: string) => {149 (fsp.readFile as jest.Mock).mockImplementation(async (p: string) => {
132- if (String(p).includes('cache')) return JSON.stringify({ version: 1, casesDir: '/tmp/cases', fingerprint: 'abc', cases: [], builtAt: 0 });150+ if (String(p).includes('cache'))
151+ return JSON.stringify({ version: 1, casesDir: '/tmp/cases', fingerprint: 'abc', cases: [], builtAt: 0 });
133 return '';152 return '';
134 });153 });
135 const result = await scanTestCasesLazy('/tmp/cases', { cache: true, cachePath: '/tmp/cache.json', cacheTtlMs: 1 });154 const result = await scanTestCasesLazy('/tmp/cases', { cache: true, cachePath: '/tmp/cache.json', cacheTtlMs: 1 });
@@ -158,10 +177,7 @@ describe('lazy-scanner 100%', () => {
158 });177 });
159 178 
160 test('groupByModule', () => {179 test('groupByModule', () => {
161- const cases = [180+ const cases = [{ id: 'a', module: 'functional' } as any, { id: 'b', module: 'performance' } as any];
162- { id: 'a', module: 'functional' } as any,
163- { id: 'b', module: 'performance' } as any,
164- ];
165 const groups = groupByModule(cases);181 const groups = groupByModule(cases);
166 expect(groups.get('functional')?.length).toBe(1);182 expect(groups.get('functional')?.length).toBe(1);
167 expect(groups.get('performance')?.length).toBe(1);183 expect(groups.get('performance')?.length).toBe(1);
Mpackages/framework/src/base/utils/metric-event-bus.ts+2-2File content is under review, please try again later
@@ -9,7 +9,7 @@ import { EventEmitter } from 'events';
9import { Logger, createLogger } from '../../base/utils/logger';9import { Logger, createLogger } from '../../base/utils/logger';
10import { PortManager } from '../../base/utils/port-pool';10import { PortManager } from '../../base/utils/port-pool';
11import { emitMetricEvent } from './metric-event-bus';11import { emitMetricEvent } from './metric-event-bus';
12-import type { MetricEvent } from '@cptf/schema';12+import type { MetricEvent } from '@liu_wentao/cptf-schema';
13import { DEFAULT_NATIVE_DRIVER_WS_PORT } from '../../base/types/constants';13import { DEFAULT_NATIVE_DRIVER_WS_PORT } from '../../base/types/constants';
14 14 
15/** 指标事件回调类型(MetricWebSocketServer 收到设备推送时调用)。 */15/** 指标事件回调类型(MetricWebSocketServer 收到设备推送时调用)。 */
@@ -82,7 +82,11 @@ export class MetricWebSocketServer extends EventEmitter {
82 const dead = this.server;82 const dead = this.server;
83 this.server = null;83 this.server = null;
84 if (dead) {84 if (dead) {
85- try { dead.close(); } catch { /* noop */ }85+ try {
86+ dead.close();
87+ } catch {
88+ /* noop */
89+ }
86 }90 }
87 reject(err);91 reject(err);
88 }92 }
@@ -131,7 +135,11 @@ export class MetricWebSocketServer extends EventEmitter {
131 });135 });
132 socket.on('error', () => {136 socket.on('error', () => {
133 this.sockets.delete(ms);137 this.sockets.delete(ms);
134- try { socket.destroy(); } catch { /* noop */ }138+ try {
139+ socket.destroy();
140+ } catch {
141+ /* noop */
142+ }
135 });143 });
136 if (head && head.length > 0) {144 if (head && head.length > 0) {
137 this.handleData(ms, head);145 this.handleData(ms, head);
@@ -141,8 +149,14 @@ export class MetricWebSocketServer extends EventEmitter {
141 private handleData(ms: MetricSocket, buf: Buffer): void {149 private handleData(ms: MetricSocket, buf: Buffer): void {
142 const data = ms.recvBuffer.length === 0 ? buf : Buffer.concat([ms.recvBuffer, buf]);150 const data = ms.recvBuffer.length === 0 ? buf : Buffer.concat([ms.recvBuffer, buf]);
143 if (data.length > MetricWebSocketServer.MAX_RECV_BUFFER_BYTES) {151 if (data.length > MetricWebSocketServer.MAX_RECV_BUFFER_BYTES) {
144- this.logger.warn(`MetricWebSocketServer: recv buffer overflow (${data.length}B > ${MetricWebSocketServer.MAX_RECV_BUFFER_BYTES}B), closing connection`);152+ this.logger.warn(
145- try { ms.socket.destroy(); } catch { /* noop */ }153+ `MetricWebSocketServer: recv buffer overflow (${data.length}B > ${MetricWebSocketServer.MAX_RECV_BUFFER_BYTES}B), closing connection`
154+ );
155+ try {
156+ ms.socket.destroy();
157+ } catch {
158+ /* noop */
159+ }
146 ms.recvBuffer = Buffer.alloc(0);160 ms.recvBuffer = Buffer.alloc(0);
147 return;161 return;
148 }162 }
@@ -199,7 +213,7 @@ export class MetricWebSocketServer extends EventEmitter {
199 if (closed) {213 if (closed) {
200 ms.recvBuffer = Buffer.alloc(0);214 ms.recvBuffer = Buffer.alloc(0);
201 } else {215 } else {
202- ms.recvBuffer = offset >= data.length ? Buffer.alloc(0) : (offset > 0 ? data.subarray(offset) : data);216+ ms.recvBuffer = offset >= data.length ? Buffer.alloc(0) : offset > 0 ? data.subarray(offset) : data;
203 }217 }
204 }218 }
205 219 
@@ -233,13 +247,15 @@ export class MetricWebSocketServer extends EventEmitter {
233 }247 }
234 248 
235 stop(): Promise<void> {249 stop(): Promise<void> {
236- return new Promise((resolve) => {250+ return new Promise(resolve => {
237 if (!this.server) {251 if (!this.server) {
238 resolve();252 resolve();
239 return;253 return;
240 }254 }
241 for (const ms of this.sockets) {255 for (const ms of this.sockets) {
242- try { ms.socket.destroy(); } catch {}256+ try {
257+ ms.socket.destroy();
258+ } catch {}
243 }259 }
244 this.sockets.clear();260 this.sockets.clear();
245 let done = false;261 let done = false;
@@ -272,7 +288,12 @@ export class MetricWebSocketServer extends EventEmitter {
272const _servers: Map<string, { server: MetricWebSocketServer; refCount: number; port: number }> = new Map();288const _servers: Map<string, { server: MetricWebSocketServer; refCount: number; port: number }> = new Map();
273 289 
274/** 获取共享指标 WS 服务实例(引用计数,同设备复用同一端口)。 */290/** 获取共享指标 WS 服务实例(引用计数,同设备复用同一端口)。 */
275-export async function acquireMetricServer(options: { port?: number; host?: string; deviceId?: string; logger?: any }): Promise<MetricWebSocketServer> {291+export async function acquireMetricServer(options: {
292+ port?: number;
293+ host?: string;
294+ deviceId?: string;
295+ logger?: any;
296+}): Promise<MetricWebSocketServer> {
276 const deviceId = options.deviceId || 'default';297 const deviceId = options.deviceId || 'default';
277 const logger = options.logger ?? createLogger();298 const logger = options.logger ?? createLogger();
278 const existing = _servers.get(deviceId);299 const existing = _servers.get(deviceId);
Mpackages/framework/src/capability/measurement/performance-collector.ts+1-1File content is under review, please try again later
Mpackages/framework/src/cli/templates/index.ts+24-18File content is under review, please try again later
@@ -9,7 +9,7 @@
9 * 如无重大变更说明,不会做不兼容修改。9 * 如无重大变更说明,不会做不兼容修改。
10 *10 *
11 * 实现细节 / 编排引擎 / 平台注册等仅在 CLI 与框架内部使用的 API11 * 实现细节 / 编排引擎 / 平台注册等仅在 CLI 与框架内部使用的 API
12- * 已迁移到 `'@cptf/framework/internal'`,请勿在新代码中依赖。如确有需要,12+ * 已迁移到 `'@liu_wentao/cptf-framework/internal'`,请勿在新代码中依赖。如确有需要,
13 * 提交 issue 说明使用场景,由维护者评估是否提升到公共 API。13 * 提交 issue 说明使用场景,由维护者评估是否提升到公共 API。
14 */14 */
15 15 
@@ -60,16 +60,9 @@ export type { UIStyle, UIElementSelector, UIComparisonConfig } from './base/type
60 60 
61export type { OverlayInfo, OverlayKind, OverlayOcclusion } from './base/types';61export type { OverlayInfo, OverlayKind, OverlayOcclusion } from './base/types';
62 62 
63-export {63+export { SCENE_TESTID_PREFIX, SECTION_TESTID_PREFIX } from './base/types';
64- SCENE_TESTID_PREFIX,
65- SECTION_TESTID_PREFIX,
66-} from './base/types';
67 64 
68-export type {65+export type { SceneSection, SceneProps, SceneDefinition } from './base/types';
69- SceneSection,
70- SceneProps,
71- SceneDefinition,
72-} from './base/types';
73 66 
74// ==================== Config types ====================67// ==================== Config types ====================
75 68 
@@ -121,8 +114,5 @@ export type { ColorRegion } from './capability/expect/expect-color-analyzer';
121 114 
122// ==================== Metric collector extension (user-registered custom collectors) ====================115// ==================== Metric collector extension (user-registered custom collectors) ====================
123 116 
124-export {117+export { BaseMetricCollector, MetricCollectorFactory } from './capability/measurement/metric-collectors';
125- BaseMetricCollector,
126- MetricCollectorFactory,
127-} from './capability/measurement/metric-collectors';
128export type { MetricCollectorContext } from './capability/measurement/metric-collectors';118export type { MetricCollectorContext } from './capability/measurement/metric-collectors';
Mpackages/framework/src/infrastructure/config/index-template-builder.ts+3-3File content is under review, please try again later
@@ -5,7 +5,7 @@
5/**5/**
6 * CPTF internal API surface.6 * CPTF internal API surface.
7 *7 *
8- * Imports from `'@cptf/framework/internal'` are reserved for the framework and CLI8+ * Imports from `'@liu_wentao/cptf-framework/internal'` are reserved for the framework and CLI
9 * implementation. They are NOT part of the public contract — symbols9 * implementation. They are NOT part of the public contract — symbols
10 * may be renamed, removed, or have their signatures changed between10 * may be renamed, removed, or have their signatures changed between
11 * minor releases without notice.11 * minor releases without notice.
@@ -20,7 +20,12 @@
20 20 
21// ==================== Infrastructure: config loading / scanning / device discovery ====================21// ==================== Infrastructure: config loading / scanning / device discovery ====================
22 22 
23-export { loadConfigFile, resolveConfigAsync, getDeviceInfoAsync, getAvailablePlatforms } from './infrastructure/config/loader';23+export {
24+ loadConfigFile,
25+ resolveConfigAsync,
26+ getDeviceInfoAsync,
27+ getAvailablePlatforms,
28+} from './infrastructure/config/loader';
24export type { CPTFConfigFile, EmailConfig } from './infrastructure/config/loader';29export type { CPTFConfigFile, EmailConfig } from './infrastructure/config/loader';
25export { scanTestCasesLazy, groupByScene, groupByModule, clearScanCache } from './infrastructure/config/lazy-scanner';30export { scanTestCasesLazy, groupByScene, groupByModule, clearScanCache } from './infrastructure/config/lazy-scanner';
26export type { ScanFilter, ScanOptions, ScanResult } from './infrastructure/config/lazy-scanner';31export type { ScanFilter, ScanOptions, ScanResult } from './infrastructure/config/lazy-scanner';
@@ -32,14 +37,34 @@ export { EmailSender } from './infrastructure/notification/email-sender';
32 37 
33// ==================== System layer internal types & factory ====================38// ==================== System layer internal types & factory ====================
34 39 
35-export { ISystem, SystemConfig, FPSData, MemoryData, CPUData, ANRData, CrashData, AppState, RandomActionConfig } from './system/i-system';40+export {
41+ ISystem,
42+ SystemConfig,
43+ FPSData,
44+ MemoryData,
45+ CPUData,
46+ ANRData,
47+ CrashData,
48+ AppState,
49+ RandomActionConfig,
50+} from './system/i-system';
36export { SystemFactory } from './system/system-factory';51export { SystemFactory } from './system/system-factory';
37 52 
38// ==================== Performance / stability collectors ====================53// ==================== Performance / stability collectors ====================
39 54 
40export { PerformanceCollector } from './capability/measurement/performance-collector';55export { PerformanceCollector } from './capability/measurement/performance-collector';
41export type { PerformanceMetrics, CompressedMetrics } from './capability/measurement/performance-collector';56export type { PerformanceMetrics, CompressedMetrics } from './capability/measurement/performance-collector';
42-export { BaseMetricCollector, MetricCollectorFactory, StartLatencyCollector, FinishLatencyCollector, BigJankCollector, InteractionLatencyCollector, MemoryGrowthRateCollector, HotStartLatencyCollector, BlankScreenRatioCollector } from './capability/measurement/metric-collectors';57+export {
58+ BaseMetricCollector,
59+ MetricCollectorFactory,
60+ StartLatencyCollector,
61+ FinishLatencyCollector,
62+ BigJankCollector,
63+ InteractionLatencyCollector,
64+ MemoryGrowthRateCollector,
65+ HotStartLatencyCollector,
66+ BlankScreenRatioCollector,
67+} from './capability/measurement/metric-collectors';
43export type { MetricCollectorContext } from './capability/measurement/metric-collectors';68export type { MetricCollectorContext } from './capability/measurement/metric-collectors';
44export { MemoryLeakDetector } from './capability/measurement/memory-leak-detector';69export { MemoryLeakDetector } from './capability/measurement/memory-leak-detector';
45export { SmartMonkey } from './capability/measurement/smart-monkey';70export { SmartMonkey } from './capability/measurement/smart-monkey';
@@ -52,11 +77,20 @@ export { ExpectExecutor } from './capability/expect/expect-executor';
52// ==================== Orchestration: runner engines (CLI internal) ====================77// ==================== Orchestration: runner engines (CLI internal) ====================
53 78 
54export { TestRunner } from './orchestration/test-runner';79export { TestRunner } from './orchestration/test-runner';
55-export type { TestRunnerOptions, TestRunnerResult, TestRunnerDependencies, TestRunnerProgress } from './orchestration/test-runner';80+export type {
81+ TestRunnerOptions,
82+ TestRunnerResult,
83+ TestRunnerDependencies,
84+ TestRunnerProgress,
85+} from './orchestration/test-runner';
56export { ComparisonRunner } from './orchestration/comparison-runner';86export { ComparisonRunner } from './orchestration/comparison-runner';
57export type { ComparisonRunnerOptions } from './orchestration/comparison-runner';87export type { ComparisonRunnerOptions } from './orchestration/comparison-runner';
58export { ParallelTestRunner } from './orchestration/parallel-test-runner';88export { ParallelTestRunner } from './orchestration/parallel-test-runner';
59-export type { ParallelTestRunnerOptions, ParallelTestRunnerResult, DeviceExecutionResult } from './orchestration/parallel-test-runner';89+export type {
90+ ParallelTestRunnerOptions,
91+ ParallelTestRunnerResult,
92+ DeviceExecutionResult,
93+} from './orchestration/parallel-test-runner';
60export { TestExecutor } from './orchestration/test-executor';94export { TestExecutor } from './orchestration/test-executor';
61export { BaseTest } from './orchestration/core/base-test';95export { BaseTest } from './orchestration/core/base-test';
62export { RunnerStrategy, RunnerStrategyRegistry } from './orchestration/runner-strategy';96export { RunnerStrategy, RunnerStrategyRegistry } from './orchestration/runner-strategy';
@@ -81,5 +115,9 @@ export type { VisualComparisonResult } from './capability/analysis/visual-compar
81 115 
82export { defaultRegistry, NavigationStrategyFactory } from './orchestration/core/navigation-strategy-registry';116export { defaultRegistry, NavigationStrategyFactory } from './orchestration/core/navigation-strategy-registry';
83export type { StrategyFactoryFn } from './orchestration/core/navigation-strategy-registry';117export type { StrategyFactoryFn } from './orchestration/core/navigation-strategy-registry';
84-export { NavigationStrategy, DefaultNavigationStrategy, NavigationHost } from './orchestration/core/navigation-strategy';118+export {
119+ NavigationStrategy,
120+ DefaultNavigationStrategy,
121+ NavigationHost,
122+} from './orchestration/core/navigation-strategy';
85export type { NavigationContext } from './orchestration/core/navigation-strategy';123export type { NavigationContext } from './orchestration/core/navigation-strategy';
Mpackages/framework/src/orchestration/core/navigation-strategy-registry.ts+10-5File content is under review, please try again later
@@ -65,7 +65,10 @@ export class SceneAwareShardingPolicy implements ShardingPolicy {
65 const half = Math.ceil(groupCases.length / 2);65 const half = Math.ceil(groupCases.length / 2);
66 shards[targetShard].push(...groupCases.slice(0, half));66 shards[targetShard].push(...groupCases.slice(0, half));
67 if (shardCount > 1 && groupCases.length > half) {67 if (shardCount > 1 && groupCases.length > half) {
68- const remainingShards = shards.map((s, i) => ({ i, len: s.length })).filter(s => s.i !== targetShard).sort((a, b) => a.len - b.len);68+ const remainingShards = shards
69+ .map((s, i) => ({ i, len: s.length }))
70+ .filter(s => s.i !== targetShard)
71+ .sort((a, b) => a.len - b.len);
69 const secondShard = remainingShards[0].i;72 const secondShard = remainingShards[0].i;
70 shards[secondShard].push(...groupCases.slice(half));73 shards[secondShard].push(...groupCases.slice(half));
71 }74 }
@@ -174,7 +177,8 @@ export class TCPHealthCheckPolicy implements HealthCheckPolicy {
174 177 
175 if (appCrashed && bundleId) {178 if (appCrashed && bundleId) {
176 logger.warn(`应用已崩溃/不在前台,重启应用: ${bundleId}`);179 logger.warn(`应用已崩溃/不在前台,重启应用: ${bundleId}`);
177- const resetApp = (system as unknown as { resetApp?: (level?: 'restart' | 'clear') => Promise<boolean> }).resetApp;180+ const resetApp = (system as unknown as { resetApp?: (level?: 'restart' | 'clear') => Promise<boolean> })
181+ .resetApp;
178 if (typeof resetApp === 'function') {182 if (typeof resetApp === 'function') {
179 try {183 try {
180 const ok = await resetApp.call(system, 'restart');184 const ok = await resetApp.call(system, 'restart');
@@ -187,7 +191,9 @@ export class TCPHealthCheckPolicy implements HealthCheckPolicy {
187 logger.warn(`resetApp 失败: ${(err as Error).message}`);191 logger.warn(`resetApp 失败: ${(err as Error).message}`);
188 }192 }
189 } else {193 } else {
190- try { await system.stopApp(bundleId); } catch {}194+ try {
195+ await system.stopApp(bundleId);
196+ } catch {}
191 if (typeof system.setCurrentApp === 'function') {197 if (typeof system.setCurrentApp === 'function') {
192 system.setCurrentApp(bundleId);198 system.setCurrentApp(bundleId);
193 }199 }
@@ -195,10 +201,14 @@ export class TCPHealthCheckPolicy implements HealthCheckPolicy {
195 let launched = false;201 let launched = false;
196 const deepLinkScheme = NavigationCoordinator.getGlobalDeepLinkScheme();202 const deepLinkScheme = NavigationCoordinator.getGlobalDeepLinkScheme();
197 if (deepLinkScheme && typeof system.deepLink === 'function') {203 if (deepLinkScheme && typeof system.deepLink === 'function') {
198- try { launched = await system.deepLink(`${deepLinkScheme}://home`); } catch {}204+ try {
205+ launched = await system.deepLink(`${deepLinkScheme}://home`);
206+ } catch {}
199 }207 }
200 if (!launched && typeof system.launchApp === 'function') {208 if (!launched && typeof system.launchApp === 'function') {
201- try { launched = await system.launchApp(bundleId); } catch {}209+ try {
210+ launched = await system.launchApp(bundleId);
211+ } catch {}
202 }212 }
203 if (launched) {213 if (launched) {
204 logger.success('应用重启成功');214 logger.success('应用重启成功');
@@ -247,11 +257,14 @@ export class RunnerStrategy {
247 healthCheckPolicy: HealthCheckPolicy;257 healthCheckPolicy: HealthCheckPolicy;
248 private logger: Logger;258 private logger: Logger;
249 259 
250- constructor(logger: Logger, options?: {260+ constructor(
251- retryPolicy?: RetryPolicy;261+ logger: Logger,
252- shardingPolicy?: ShardingPolicy;262+ options?: {
253- healthCheckPolicy?: HealthCheckPolicy;263+ retryPolicy?: RetryPolicy;
254- }) {264+ shardingPolicy?: ShardingPolicy;
265+ healthCheckPolicy?: HealthCheckPolicy;
266+ }
267+ ) {
255 this.logger = logger;268 this.logger = logger;
256 this.retryPolicy = options?.retryPolicy || new DefaultRetryPolicy();269 this.retryPolicy = options?.retryPolicy || new DefaultRetryPolicy();
257 this.shardingPolicy = options?.shardingPolicy || new SceneAwareShardingPolicy();270 this.shardingPolicy = options?.shardingPolicy || new SceneAwareShardingPolicy();
@@ -281,9 +294,15 @@ export class RunnerStrategy {
281 * Replace one of the three policies at runtime. Used by the runners294 * Replace one of the three policies at runtime. Used by the runners
282 * to inject a custom policy (e.g. a CI-specific retry strategy).295 * to inject a custom policy (e.g. a CI-specific retry strategy).
283 */296 */
284- setRetryPolicy(p: RetryPolicy): void { this.retryPolicy = p; }297+ setRetryPolicy(p: RetryPolicy): void {
285- setShardingPolicy(p: ShardingPolicy): void { this.shardingPolicy = p; }298+ this.retryPolicy = p;
286- setHealthCheckPolicy(p: HealthCheckPolicy): void { this.healthCheckPolicy = p; }299+ }
300+ setShardingPolicy(p: ShardingPolicy): void {
301+ this.shardingPolicy = p;
302+ }
303+ setHealthCheckPolicy(p: HealthCheckPolicy): void {
304+ this.healthCheckPolicy = p;
305+ }
287}306}
288 307 
289/**308/**
@@ -293,7 +312,7 @@ export class RunnerStrategy {
293 *312 *
294 * @example313 * @example
295 * ```ts314 * ```ts
296- * import { RunnerStrategyRegistry } from '@cptf/framework/internal';315+ * import { RunnerStrategyRegistry } from '@liu_wentao/cptf-framework/internal';
297 * RunnerStrategyRegistry.register('ci-fast', (logger) => new RunnerStrategy(logger, {316 * RunnerStrategyRegistry.register('ci-fast', (logger) => new RunnerStrategy(logger, {
298 * retryPolicy: new CIRetryPolicy(),317 * retryPolicy: new CIRetryPolicy(),
299 * shardingPolicy: new ByCaseShardingPolicy(),318 * shardingPolicy: new ByCaseShardingPolicy(),
Mpackages/framework/src/system/synchronizer.ts+2-2File content is under review, please try again later
Mpackages/framework/src/system/system-factory.ts+5-5File content is under review, please try again later
Mpackages/native-harmony/README.md+2-2File content is under review, please try again later
Mpackages/native-harmony/harmony/nativeharmony/oh-package.json5+9-9File content is under review, please try again later
@@ -1,6 +1,6 @@
1{1{
2- "name": "@cptf/native-harmony",2+ "name": "@liu_wentao/cptf-native-harmony",
3- "version": "0.1.0",3+ "version": "0.2.0",
4 "description": "HarmonyOS ohosTest native driver (NativeTestDriver.ets) executed on-device for CPTF native driver mode",4 "description": "HarmonyOS ohosTest native driver (NativeTestDriver.ets) executed on-device for CPTF native driver mode",
5 "main": "harmony/nativeharmony/Index.ets",5 "main": "harmony/nativeharmony/Index.ets",
6 "scripts": {6 "scripts": {
Mpackages/plugin-rn/README.md+1-1File content is under review, please try again later
@@ -1,15 +1,15 @@
1{1{
2- "name": "@cptf/plugin-rn",2+ "name": "@liu_wentao/cptf-plugin-rn",
3- "version": "0.1.0",3+ "version": "0.2.0",
4 "description": "React Native app probes (JS thread / network / bridge) feeding CPTF performance collection",4 "description": "React Native app probes (JS thread / network / bridge) feeding CPTF performance collection",
5 "main": "src/index",5 "main": "src/index",
6 "scripts": {6 "scripts": {
7 "pack": "pnpm pack"7 "pack": "pnpm pack"
8 },8 },
9 "dependencies": {9 "dependencies": {
10- "@cptf/native-harmony": "workspace:*",10+ "@liu_wentao/cptf-native-harmony": "workspace:*",
11- "@cptf/framework": "workspace:*",11+ "@liu_wentao/cptf-framework": "workspace:*",
12- "@cptf/schema": "workspace:*"12+ "@liu_wentao/cptf-schema": "workspace:*"
13 },13 },
14 "peerDependencies": {14 "peerDependencies": {
15 "react-native": "*"15 "react-native": "*"
Mpackages/plugin-rn/src/JSThreadProbe.ts+2-2File content is under review, please try again later
Mpackages/plugin-rn/src/NetworkProbe.ts+2-2File content is under review, please try again later
Mpackages/plugin-rn/src/RNBridgeProbe.ts+2-2File content is under review, please try again later
Mpackages/plugin-rn/src/register.ts+2-2File content is under review, please try again later
Mpackages/schema/README.md+2-2File content is under review, please try again later
@@ -1,6 +1,6 @@
1{1{
2- "name": "@cptf/schema",2+ "name": "@liu_wentao/cptf-schema",
3- "version": "0.1.0",3+ "version": "0.2.0",
4 "description": "Shared type contracts for the CPTF ecosystem (cross-host/device schemas, zero dependencies)",4 "description": "Shared type contracts for the CPTF ecosystem (cross-host/device schemas, zero dependencies)",
5 "main": "dist/index.js",5 "main": "dist/index.js",
6 "types": "dist/index.d.ts",6 "types": "dist/index.d.ts",