babel-plugin-canyontestgo 1.0.0

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,7 @@
1
+ import type { CanyonBabelPluginConfig } from '../types';
2
+ /**
3
+ * 从 CI/CD 环境变量中自动检测配置
4
+ * 支持 GitLab CI 和 GitHub Actions
5
+ */
6
+ export declare function detectCIConfig(): Partial<CanyonBabelPluginConfig>;
7
+ //# sourceMappingURL=detect-ci-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-ci-config.d.ts","sourceRoot":"","sources":["../../src/helpers/detect-ci-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAgCjE"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectCIConfig = detectCIConfig;
4
+ /**
5
+ * 从 CI/CD 环境变量中自动检测配置
6
+ * 支持 GitLab CI 和 GitHub Actions
7
+ */
8
+ function detectCIConfig() {
9
+ const ciConfig = {};
10
+ // 检测是否在 CI 环境中
11
+ const isCI = !!(process.env.CI ||
12
+ process.env.GITLAB_CI ||
13
+ process.env.GITHUB_ACTIONS);
14
+ if (!isCI) {
15
+ return ciConfig;
16
+ }
17
+ ciConfig.ci = true;
18
+ // 检测 GitLab CI
19
+ if (process.env.GITLAB_CI || process.env.CI_PROJECT_ID) {
20
+ ciConfig.provider = 'gitlab';
21
+ ciConfig.repoID =
22
+ process.env.CI_PROJECT_ID || process.env.CI_PROJECT_PATH || '';
23
+ ciConfig.sha = process.env.CI_COMMIT_SHA || '';
24
+ }
25
+ // 检测 GitHub Actions
26
+ else if (process.env.GITHUB_ACTIONS || process.env.GITHUB_REPOSITORY) {
27
+ ciConfig.provider = 'github';
28
+ ciConfig.repoID =
29
+ process.env.GITHUB_REPOSITORY_ID || process.env.GITHUB_REPOSITORY || '';
30
+ ciConfig.sha = process.env.GITHUB_SHA || '';
31
+ }
32
+ return ciConfig;
33
+ }
34
+ //# sourceMappingURL=detect-ci-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-ci-config.js","sourceRoot":"","sources":["../../src/helpers/detect-ci-config.ts"],"names":[],"mappings":";;;AAEA;;;GAGG;AACH,0BAAmE;IACjE,MAAM,QAAQ,GAAqC,EAAE,CAAC;IAEtD,+BAAe;IACf,MAAM,IAAI,GAAG,CAAC,CAAC,CACb,OAAO,CAAC,GAAG,CAAC,EAAE;QACd,OAAO,CAAC,GAAG,CAAC,SAAS;QACrB,OAAO,CAAC,GAAG,CAAC,cAAc,CAC3B,CAAC;IAEF,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,QAAQ,CAAC,EAAE,GAAG,IAAI,CAAC;IAEnB,mBAAe;IACf,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QACvD,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC7B,QAAQ,CAAC,MAAM;YACb,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;QACjE,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IACjD,CAAC;IACD,wBAAoB;SACf,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACrE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC7B,QAAQ,CAAC,MAAM;YACb,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC;QAC1E,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;IAC9C,CAAC;IAED,OAAO,QAAQ,CAAC;AAAA,CACjB"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * 从脚本内容中提取覆盖率数据
3
+ * 支持两种格式:
4
+ * 1. var coverageData = {...};
5
+ * 2. var xxx = function() {...}();
6
+ *
7
+ * @param scriptContent - 包含覆盖率数据的脚本内容
8
+ * @returns 提取的覆盖率数据对象,如果提取失败则返回 null
9
+ */
10
+ export declare function extractCoverageData(scriptContent: string): Record<string, unknown> | null;
11
+ //# sourceMappingURL=extract-coverage-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-coverage-data.d.ts","sourceRoot":"","sources":["../../src/helpers/extract-coverage-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,GACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAgChC"}
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractCoverageData = extractCoverageData;
4
+ /**
5
+ * 从脚本内容中提取覆盖率数据
6
+ * 支持两种格式:
7
+ * 1. var coverageData = {...};
8
+ * 2. var xxx = function() {...}();
9
+ *
10
+ * @param scriptContent - 包含覆盖率数据的脚本内容
11
+ * @returns 提取的覆盖率数据对象,如果提取失败则返回 null
12
+ */
13
+ function extractCoverageData(scriptContent) {
14
+ // 匹配格式:var coverageData = {...};
15
+ const coverageDataPattern = /var\s+coverageData\s*=\s*({[\s\S]*?});/;
16
+ // 匹配格式:var xxx = function() {...}();
17
+ const functionPattern = /var\s+(\w+)\s*=\s*function\s*\(\)\s*\{([\s\S]*?)\}\(\);/;
18
+ try {
19
+ // 尝试匹配第一种格式
20
+ const coverageDataMatch = coverageDataPattern.exec(scriptContent);
21
+ if (coverageDataMatch) {
22
+ const objectString = coverageDataMatch[1];
23
+ return new Function(`return ${objectString}`)();
24
+ }
25
+ // 尝试匹配第二种格式
26
+ const functionMatch = functionPattern.exec(scriptContent);
27
+ if (functionMatch) {
28
+ const functionBody = functionMatch[2];
29
+ const func = new Function(`${functionBody}return coverageData;`);
30
+ const result = func();
31
+ return result;
32
+ }
33
+ }
34
+ catch (_error) {
35
+ // 提取失败时返回 null
36
+ return null;
37
+ }
38
+ return null;
39
+ }
40
+ //# sourceMappingURL=extract-coverage-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-coverage-data.js","sourceRoot":"","sources":["../../src/helpers/extract-coverage-data.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,6BACE,aAAqB,EACW;IAChC,2CAAiC;IACjC,MAAM,mBAAmB,GAAG,wCAAwC,CAAC;IACrE,+CAAqC;IACrC,MAAM,eAAe,GACnB,yDAAyD,CAAC;IAE5D,IAAI,CAAC;QACH,8BAAY;QACZ,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAClE,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,YAAY,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;YAC1C,OAAO,IAAI,QAAQ,CAAC,UAAU,YAAY,EAAE,CAAC,EAG5C,CAAC;QACJ,CAAC;QAED,8BAAY;QACZ,MAAM,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1D,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,GAAG,YAAY,sBAAsB,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC;YACtB,OAAO,MAAiC,CAAC;QAC3C,CAAC;IACH,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,6BAAe;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC;AAAA,CACb"}
@@ -0,0 +1,10 @@
1
+ import type { CanyonBabelPluginConfig } from '../types';
2
+ /**
3
+ * 生成 buildHash
4
+ * 基于 provider, repoID, sha, buildTarget 四个字段生成稳定的构建身份标识
5
+ *
6
+ * @param config - 插件配置参数
7
+ * @returns buildHash 字符串
8
+ */
9
+ export declare function generateBuildHash(config: Required<CanyonBabelPluginConfig>): string;
10
+ //# sourceMappingURL=generate-build-hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-build-hash.d.ts","sourceRoot":"","sources":["../../src/helpers/generate-build-hash.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GACxC,MAAM,CAgBR"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateBuildHash = generateBuildHash;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
9
+ /**
10
+ * 生成 buildHash
11
+ * 基于 provider, repoID, sha, buildTarget 四个字段生成稳定的构建身份标识
12
+ *
13
+ * @param config - 插件配置参数
14
+ * @returns buildHash 字符串
15
+ */
16
+ function generateBuildHash(config) {
17
+ // buildHash 只包含这四个核心字段:
18
+ // provider + repoID + sha + buildTarget
19
+ const buildHashFields = {
20
+ provider: config.provider || '',
21
+ repoID: config.repoID || '',
22
+ sha: config.sha || '',
23
+ buildTarget: config.buildTarget || '',
24
+ };
25
+ // 使用 json-stable-stringify 确保键顺序稳定,与后端保持一致
26
+ const hash = (0, node_crypto_1.createHash)('sha1')
27
+ .update((0, json_stable_stringify_1.default)(buildHashFields) || '')
28
+ .digest('hex');
29
+ return hash;
30
+ }
31
+ //# sourceMappingURL=generate-build-hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-build-hash.js","sourceRoot":"","sources":["../../src/helpers/generate-build-hash.ts"],"names":[],"mappings":";;;;;;AAAA,6CAAyC;AACzC,kFAA8C;AAG9C;;;;;;GAMG;AACH,2BACE,MAAyC,EACjC;IACR,8CAAwB;IACxB,wCAAwC;IACxC,MAAM,eAAe,GAA2B;QAC9C,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE;QAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,EAAE;KACtC,CAAC;IAEF,6EAA2C;IAC3C,MAAM,IAAI,GAAG,IAAA,wBAAU,EAAC,MAAM,CAAC;SAC5B,MAAM,CAAC,IAAA,+BAAS,EAAC,eAAe,CAAC,IAAI,EAAE,CAAC;SACxC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEjB,OAAO,IAAI,CAAC;AAAA,CACb"}
@@ -0,0 +1,18 @@
1
+ import type { CanyonBabelPluginConfig } from '../types';
2
+ /**
3
+ * 覆盖率数据接口
4
+ */
5
+ interface CoverageData {
6
+ path?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ /**
10
+ * 生成初始覆盖率数据
11
+ *
12
+ * @param sourceCode - 源代码内容
13
+ * @param _config - 插件配置参数(当前未使用,保留以兼容接口)
14
+ * @returns 提取的覆盖率数据对象,如果提取失败则返回 null
15
+ */
16
+ export declare function generateInitialCoverage(sourceCode: string, _config: Required<CanyonBabelPluginConfig>): CoverageData | null;
17
+ export {};
18
+ //# sourceMappingURL=generate-initial-coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-initial-coverage.d.ts","sourceRoot":"","sources":["../../src/helpers/generate-initial-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAGxD;;GAEG;AACH,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GACzC,YAAY,GAAG,IAAI,CAGrB"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateInitialCoverage = generateInitialCoverage;
4
+ const extract_coverage_data_1 = require("./extract-coverage-data");
5
+ /**
6
+ * 生成初始覆盖率数据
7
+ *
8
+ * @param sourceCode - 源代码内容
9
+ * @param _config - 插件配置参数(当前未使用,保留以兼容接口)
10
+ * @returns 提取的覆盖率数据对象,如果提取失败则返回 null
11
+ */
12
+ function generateInitialCoverage(sourceCode, _config) {
13
+ const coverageData = (0, extract_coverage_data_1.extractCoverageData)(sourceCode);
14
+ return coverageData;
15
+ }
16
+ //# sourceMappingURL=generate-initial-coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-initial-coverage.js","sourceRoot":"","sources":["../../src/helpers/generate-initial-coverage.ts"],"names":[],"mappings":";;;AACA,mEAA8D;AAU9D;;;;;;GAMG;AACH,iCACE,UAAkB,EAClB,OAA0C,EACrB;IACrB,MAAM,YAAY,GAAG,IAAA,2CAAmB,EAAC,UAAU,CAAC,CAAC;IACrD,OAAO,YAAY,CAAC;AAAA,CACrB"}
@@ -0,0 +1,15 @@
1
+ import type { NodePath } from '@babel/core';
2
+ import type * as t from '@babel/types';
3
+ /**
4
+ * Babel 插件主入口
5
+ * 用于在代码中注入覆盖率收集逻辑和元数据
6
+ */
7
+ declare const _default: (api: object, options: Record<string, any> | null | undefined, dirname: string) => {
8
+ visitor: {
9
+ Program: {
10
+ exit: (path: NodePath<t.Program>) => void;
11
+ };
12
+ };
13
+ };
14
+ export default _default;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,KAAK,KAAK,CAAC,MAAM,cAAc,CAAC;AA6CvC;;;GAGG;;;;;;;;AACH,wBAoBE"}
package/dist/index.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const helper_plugin_utils_1 = require("@babel/helper-plugin-utils");
4
+ const detect_ci_config_1 = require("./helpers/detect-ci-config");
5
+ const visitor_program_exit_1 = require("./visitor-program-exit");
6
+ /**
7
+ * 默认配置对象
8
+ */
9
+ const defaultConfig = {
10
+ repoID: '',
11
+ sha: '',
12
+ provider: '',
13
+ buildTarget: '',
14
+ ci: false,
15
+ };
16
+ /**
17
+ * 合并用户配置、CI 自动检测配置和默认配置
18
+ *
19
+ * @param config - 用户提供的配置
20
+ * @returns 合并后的完整配置对象
21
+ */
22
+ function mergeConfig(config) {
23
+ // 首先从 CI 环境变量中自动检测配置
24
+ const ciConfig = (0, detect_ci_config_1.detectCIConfig)();
25
+ // 合并优先级:用户配置 > CI 自动检测 > 默认配置
26
+ return {
27
+ repoID: config?.repoID ?? ciConfig.repoID ?? defaultConfig.repoID,
28
+ sha: config?.sha ?? ciConfig.sha ?? defaultConfig.sha,
29
+ // branch: config?.branch ?? ciConfig.branch ?? defaultConfig.branch,
30
+ provider: config?.provider ?? ciConfig.provider ?? defaultConfig.provider,
31
+ buildTarget: config?.buildTarget ?? ciConfig.buildTarget ?? defaultConfig.buildTarget,
32
+ ci: config?.ci ?? ciConfig.ci ?? defaultConfig.ci,
33
+ // buildProvider:
34
+ // config?.buildProvider ??
35
+ // ciConfig.buildProvider ??
36
+ // defaultConfig.buildProvider,
37
+ // buildID: config?.buildID ?? ciConfig.buildID ?? defaultConfig.buildID,
38
+ };
39
+ }
40
+ /**
41
+ * Babel 插件主入口
42
+ * 用于在代码中注入覆盖率收集逻辑和元数据
43
+ */
44
+ exports.default = (0, helper_plugin_utils_1.declare)((api, config) => {
45
+ api.assertVersion(7);
46
+ const userConfig = config;
47
+ const validatedConfig = mergeConfig(userConfig);
48
+ return {
49
+ visitor: {
50
+ Program: {
51
+ exit: (programPath) => {
52
+ (0, visitor_program_exit_1.visitorProgramExit)(api, programPath, validatedConfig);
53
+ },
54
+ },
55
+ },
56
+ };
57
+ });
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AACA,oEAAqD;AAErD,iEAA4D;AAE5D,iEAA4D;AAE5D;;GAEG;AACH,MAAM,aAAa,GAAsC;IACvD,MAAM,EAAE,EAAE;IACV,GAAG,EAAE,EAAE;IACP,QAAQ,EAAE,EAAE;IACZ,WAAW,EAAE,EAAE;IACf,EAAE,EAAE,KAAK;CACV,CAAC;AAEF;;;;;GAKG;AACH,SAAS,WAAW,CAClB,MAA2C,EACR;IACnC,iDAAqB;IACrB,MAAM,QAAQ,GAAG,IAAA,iCAAc,GAAE,CAAC;IAElC,kEAA8B;IAC9B,OAAO;QACL,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,QAAQ,CAAC,MAAM,IAAI,aAAa,CAAC,MAAM;QACjE,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,GAAG,IAAI,aAAa,CAAC,GAAG;QACrD,qEAAqE;QACrE,QAAQ,EAAE,MAAM,EAAE,QAAQ,IAAI,QAAQ,CAAC,QAAQ,IAAI,aAAa,CAAC,QAAQ;QACzE,WAAW,EACT,MAAM,EAAE,WAAW,IAAI,QAAQ,CAAC,WAAW,IAAI,aAAa,CAAC,WAAW;QAC1E,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,QAAQ,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE;QACjD,iBAAiB;QACjB,6BAA6B;QAC7B,8BAA8B;QAC9B,iCAAiC;QACjC,yEAAyE;KAC1E,CAAC;AAAA,CACH;AAED;;;GAGG;kBACY,IAAA,6BAAO,EACpB,CACE,GAAc,EACd,MAAe,EAGf,EAAE,CAAC;IACH,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,UAAU,GAAG,MAA6C,CAAC;IACjE,MAAM,eAAe,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAChD,OAAO;QACL,OAAO,EAAE;YACP,OAAO,EAAE;gBACP,IAAI,EAAE,CAAC,WAAgC,EAAE,EAAE,CAAC;oBAC1C,IAAA,yCAAkB,EAAC,GAAG,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;gBAAA,CACvD;aACF;SACF;KACF,CAAC;AAAA,CACH,CACF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Babel plugin 配置接口
3
+ */
4
+ export interface CanyonBabelPluginConfig {
5
+ /** 仓库 ID */
6
+ repoID?: string;
7
+ /** Git commit SHA */
8
+ sha?: string;
9
+ /** Git 提供商 */
10
+ provider?: string;
11
+ /** 构建目标 */
12
+ buildTarget?: string;
13
+ /** 是否为 CI 环境 */
14
+ ci?: boolean;
15
+ }
16
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,gBAAY;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAAgB;IAChB,EAAE,CAAC,EAAE,OAAO,CAAC;CACd"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import type { types as BabelTypes, ConfigAPI, NodePath } from '@babel/core';
2
+ import type { CanyonBabelPluginConfig } from './types';
3
+ /**
4
+ * 覆盖率数据接口
5
+ */
6
+ interface CoverageData {
7
+ path?: string;
8
+ [key: string]: unknown;
9
+ }
10
+ /**
11
+ * 返回值接口
12
+ */
13
+ interface VisitorProgramExitResult {
14
+ initialCoverageDataForTheCurrentFile: CoverageData | null;
15
+ }
16
+ /**
17
+ * Program 节点退出时的访问器函数
18
+ * 用于处理覆盖率数据,添加元数据并生成初始覆盖率文件
19
+ *
20
+ * @param api - Babel Plugin API 实例
21
+ * @param programPath - Program 节点的路径
22
+ * @param config - 插件配置参数
23
+ * @returns 包含初始覆盖率数据的对象
24
+ */
25
+ export declare function visitorProgramExit(api: ConfigAPI, programPath: NodePath<BabelTypes.Program>, config: Required<CanyonBabelPluginConfig>): VisitorProgramExitResult;
26
+ export {};
27
+ //# sourceMappingURL=visitor-program-exit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor-program-exit.d.ts","sourceRoot":"","sources":["../src/visitor-program-exit.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,IAAI,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAI5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvD;;GAEG;AACH,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,UAAU,wBAAwB;IAChC,oCAAoC,EAAE,YAAY,GAAG,IAAI,CAAC;CAC3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,EACzC,MAAM,EAAE,QAAQ,CAAC,uBAAuB,CAAC,GACxC,wBAAwB,CAyH1B"}
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.visitorProgramExit = visitorProgramExit;
40
+ const node_crypto_1 = require("node:crypto");
41
+ const fs = __importStar(require("node:fs"));
42
+ const generator_1 = __importDefault(require("@babel/generator"));
43
+ const generate_build_hash_1 = require("./helpers/generate-build-hash");
44
+ const generate_initial_coverage_1 = require("./helpers/generate-initial-coverage");
45
+ /**
46
+ * Program 节点退出时的访问器函数
47
+ * 用于处理覆盖率数据,添加元数据并生成初始覆盖率文件
48
+ *
49
+ * @param api - Babel Plugin API 实例
50
+ * @param programPath - Program 节点的路径
51
+ * @param config - 插件配置参数
52
+ * @returns 包含初始覆盖率数据的对象
53
+ */
54
+ function visitorProgramExit(api, programPath, config) {
55
+ const sourceCode = (0, generator_1.default)(programPath.node).code;
56
+ const initialCoverageData = (0, generate_initial_coverage_1.generateInitialCoverage)(sourceCode, config);
57
+ // CI 环境下生成覆盖率文件
58
+ if (config.ci) {
59
+ const outputDir = './.canyon_output';
60
+ if (!fs.existsSync(outputDir)) {
61
+ fs.mkdirSync(outputDir, { recursive: true });
62
+ }
63
+ // 确保覆盖率数据有效
64
+ if (initialCoverageData?.path) {
65
+ // 使用 crypto.randomBytes 生成更安全的随机后缀(16 字节 = 32 个十六进制字符)
66
+ const randomSuffix = (0, node_crypto_1.randomBytes)(16).toString('hex');
67
+ const outputFilePath = `./.canyon_output/coverage-final-init-${randomSuffix}.json`;
68
+ const coverageDataObject = {
69
+ [initialCoverageData.path]: initialCoverageData,
70
+ };
71
+ fs.writeFileSync(outputFilePath, JSON.stringify(coverageDataObject, null, 2), 'utf-8');
72
+ }
73
+ }
74
+ // 处理代码中的 coverageData 变量
75
+ if (sourceCode.includes('coverageData')) {
76
+ // 使用 api 的 types,Babel 类型定义可能不完整,使用类型断言
77
+ const types = api.types;
78
+ programPath.traverse({
79
+ VariableDeclarator(variablePath) {
80
+ const { id, init } = variablePath.node;
81
+ // 检查是否是 coverageData 变量且初始化为对象表达式
82
+ if (types.isIdentifier(id, { name: 'coverageData' }) &&
83
+ init &&
84
+ types.isObjectExpression(init)) {
85
+ const objectExpression = init;
86
+ // 过滤掉 SpreadElement,只处理 ObjectProperty 和 ObjectMethod
87
+ const validProperties = objectExpression.properties.filter((property) => types.isObjectProperty(property) ||
88
+ types.isObjectMethod(property));
89
+ const hasInstrumentation = validProperties.some((property) => types.isObjectProperty(property) &&
90
+ types.isIdentifier(property.key, { name: '_coverageSchema' }));
91
+ if (hasInstrumentation) {
92
+ const objectProperties = objectExpression.properties;
93
+ // 查找 inputSourceMap 属性的索引
94
+ const inputSourceMapPropertyIndex = objectProperties.findIndex((property) => (types.isObjectProperty(property) ||
95
+ types.isObjectMethod(property)) &&
96
+ types.isObjectProperty(property) &&
97
+ types.isIdentifier(property.key, { name: 'inputSourceMap' }));
98
+ // 如果不保留 source map,则删除相关属性并替换 inputSourceMap
99
+ // 注意:keepMap 属性不在配置接口中,这里保留原逻辑但添加注释说明
100
+ const shouldKeepMap = false; // 默认不保留 map
101
+ if (!shouldKeepMap) {
102
+ const keysToRemove = ['statementMap', 'fnMap', 'branchMap'];
103
+ keysToRemove.forEach((keyToRemove) => {
104
+ const propertyIndex = objectProperties.findIndex((property) => (types.isObjectProperty(property) ||
105
+ types.isObjectMethod(property)) &&
106
+ types.isObjectProperty(property) &&
107
+ types.isIdentifier(property.key, { name: keyToRemove }));
108
+ if (propertyIndex !== -1) {
109
+ objectProperties.splice(propertyIndex, 1);
110
+ }
111
+ });
112
+ if (inputSourceMapPropertyIndex !== -1) {
113
+ objectProperties[inputSourceMapPropertyIndex] =
114
+ types.objectProperty(types.identifier('inputSourceMap'), types.numericLiteral(1));
115
+ }
116
+ }
117
+ // 添加 buildHash 元数据属性
118
+ // 根据架构设计,不再将 repoID、sha、provider 等业务信息直接插桩到产物中
119
+ // 而是生成 buildHash,服务端通过 buildHash 查询对应的构建信息
120
+ const buildHash = (0, generate_build_hash_1.generateBuildHash)(config);
121
+ const buildHashProperty = types.objectProperty(types.identifier('buildHash'), types.stringLiteral(buildHash));
122
+ objectProperties.push(buildHashProperty);
123
+ }
124
+ }
125
+ },
126
+ });
127
+ }
128
+ return { initialCoverageDataForTheCurrentFile: initialCoverageData };
129
+ }
130
+ //# sourceMappingURL=visitor-program-exit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor-program-exit.js","sourceRoot":"","sources":["../src/visitor-program-exit.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "babel-plugin-canyontestgo",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "keywords": [],
6
+ "main": "dist/index.js",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "author": "",
11
+ "license": "ISC",
12
+ "devDependencies": {
13
+ "@babel/cli": "^7.24.1",
14
+ "@types/babel__core": "^7.20.5",
15
+ "@types/babel__generator": "^7.6.8",
16
+ "@types/babel__helper-plugin-utils": "^7.10.3",
17
+ "@types/node": "^25.0.3",
18
+ "@typescript/native-preview": "7.0.0-dev.20251228.1",
19
+ "babel-plugin-istanbul": "^7.0.1"
20
+ },
21
+ "dependencies": {
22
+ "@babel/core": "^7.28.5",
23
+ "@babel/helper-plugin-utils": "^7.27.1",
24
+ "@babel/types": "^7.28.5",
25
+ "json-stable-stringify": "^1.3.0"
26
+ },
27
+ "scripts": {
28
+ "build": "tsgo",
29
+ "release": "tsgo",
30
+ "pretest": "tsgo",
31
+ "test": "babel features --config-file ./test-babel-config.js --out-dir features-dist"
32
+ }
33
+ }