# @apm-js-collab/code-transformer 中文文档

规范地址：https://npmcn.com/package/%40apm-js-collab/code-transformer/

版本：0\.19\.0
npm 元数据更新时间：2026-10-22T11:57:08.949Z
中文译文更新时间：2026-11-06T10:39:53.768Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40apm-js-collab/code-transformer
原文对照：https://npmcn.com/package/%40apm-js-collab/code-transformer/?lang=original
项目主页：https://github.com/nodejs/orchestrion-js#readme
源码仓库：https://github.com/nodejs/orchestrion-js

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：86 kB，11 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：6 个
- 首次发布：2025-06-02T09:54:23.573Z
- 最新版本发布：2026-10-22T11:57:08.533Z
- 近 30 天下载量：45730135（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：25（近 12 个月 11 个）

## 中文简介

这是一个在构建或加载时间帮助给Node.js 库配置仪器的图书馆.

## 安装

```sh
npm install @apm-js-collab/code-transformer
```

也可以使用：`pnpm add @apm-js-collab/code-transformer`、`yarn add @apm-js-collab/code-transformer`、`bun add @apm-js-collab/code-transformer`

## README

# 管弦乐-JS/ `@apm-js-collab/code-transformer`

这是一个用于帮助在构建或加载时对 Node.js 库进行设备化的图书馆 时间.

它使用一个AST行走器来注入代码,该代码称为Node.js [`TracingChannel`](https://nodejs.org/api/diagnostics_channel.html#class-tracingchannel)。 。 。 .

您可能不想直接使用此库, 而是考虑使用 :

-   [`@apm-js-collab/tracing-hooks/`](https://github.com/apm-js-collab/tracing-hooks/)
    -   无害环境管理 `require` 装入时对仪器模块的钩子.
-   [`apm-js-collab/code-transformer-bundler-plugins`](https://github.com/apm-js-collab/code-transformer-bundler-plugins)
    -   用于 Webpack、Vite、Rollup 和安装仪器模块的 Bundler 插件 在建设时间.

## Java 脚本

`@apm-js-collab/code-transformer` 揭发图书馆.

### 使用量

```javascript
import * as codeTransformer from "@apm-js-collab/code-transformer";

// The full instrumentation config
const instrumentation = {
    // The name of the diagnostics channel
    channelName: "my-channel",
    // Define the module you'd like to inject tracing channels into
    module: {
        name: "my-module",
        versionRange: ">=1.0.0",
        filePath: "./dist/index.js",
    },
    // Define the function you'd like to instrument
    // (e.g., match a method named 'foo' that returns a Promise)
    functionQuery: {
        methodName: "fetch",
        kind: "Async",
    },
};

// Create an InstrumentationMatcher with an array of instrumentation configs
const matcher = codeTransformer.create([instrumentation]);

// Get a transformer for a specific module
const transformer = matcher.getTransformer(
    "my-module",
    "1.2.3",
    "./dist/index.js",
);

if (transformer === undefined) {
    throw new Error("No transformer found for module");
}

// Transform code
const inputCode = "async function fetch() { return 42; }";
const result = transformer.transform(inputCode, "unknown");
console.log(result.code);
```

### 导出异名

当模块使用不同的名称再导出函数或类时 `export { local as exported }`,你可以瞄准 **导出** 名称中 `FunctionQuery` 设置 `isExportAlias: true`。变压器将解决 在匹配前将别名移至本地声明.

例如:

```js
function f(url) { return fetch(url); }
export { f as fetchAliased };
```

你可以瞄准目标 `fetchAliased` 在配置中 :

```js
const instrumentation = {
    channelName: "my-channel",
    module: { name: "my-module", versionRange: ">=1.0.0", filePath: "./index.mjs" },
    functionQuery: { functionName: "fetchAliased", kind: "Async", isExportAlias: true },
};
```

这也有利于阶级出口(例如:, `export { MyClass as PublicClass }`) (中文(简体) ).

### 更改返回值

用户既可以观察函数的返回值,也可以变异函数的返回值 通过 `message.result`重新调配 `message.result` 当 函数返回您需要的另一个函数(或对象) 包装,像工厂 返回每个要求处理器.

对于 **同步** 函数,重新指定 `message.result` 输入 `end` 处理器 :

```js
const instrumentation = {
    channelName: "create-handler",
    module: { name: "my-framework", versionRange: ">=1.0.0", filePath: "lib/router.js" },
    functionQuery: { methodName: "create", kind: "Sync" },
};
```

```js
const { tracingChannel } = require("node:diagnostics_channel");

tracingChannel("orchestrion:my-framework:create-handler").subscribe({
    end(message) {
        const original = message.result;
        // Replace the returned handler with a wrapped version.
        message.result = function wrapped(...args) {
            // ...start a span, etc.
            return original.apply(this, args);
        };
    },
});
```

对于 **一个同步** 函数,重新指定 `message.result` 输入 `asyncEnd` 操作者替换返回的许诺值 决心——例如,将承诺决定的功能包起来 改为:

```js
const instrumentation = {
    channelName: "load-handler",
    module: { name: "my-framework", versionRange: ">=1.0.0", filePath: "lib/router.js" },
    functionQuery: { methodName: "load", kind: "Async" },
};
```

```js
tracingChannel("orchestrion:my-framework:load-handler").subscribe({
    asyncEnd(message) {
        const original = message.result;
        message.result = function wrapped(...args) {
            // ...start a span, etc.
            return original.apply(this, args);
        };
    },
});
```

> \[!INFO\]
> 
> 更改一个合成函数的解析值, 仅工作 当它返回本地时 `Promise` (单位:千美元)`value instanceof Promise`) (中文(简体) ). 承诺子类和其他可使用土地是 侧链并返回到呼叫者 不变,以便他们 子类特定方法(例如:. `APIPromise.withResponse()`(中文(简体) ) 仍可使用;因此,其确定的价值 **无法** 为: 变异,和再分配 `message.result` 他们没有 效应.

在抛出路径上,原始错误仍然传播 替换返回值仅适用于函数返回时(或 通常情况下。 如果没有订阅者重新指定 `message.result`,则 原始返回值保持不变.

### AST 查询

名称 `FunctionQuery` 涵盖常见情况的变式 (命名函数,类/对象方法,表达式). 当你 需要瞄准一个无法表达的节点,例如 **匿名 由工厂返回的函数** (装饰厂,a) 每个请求处理器,您可以设置 `astQuery` 改为生 [风情](https://github.com/estools/esquery) 选择器代替.

现在, `astQuery` 选择乐器的节点 优先于 `functionQuery`匹配字段; `functionQuery` 然后只提供行为(`kind`, (中文(简体) ), `index`, (中文(简体) ), `callbackIndex`)并可能被省略(默认为 `kind: "Sync"`) (中文(简体) ).

例如,工厂归还的装饰器的仪器:

```js
function Injectable(options) {
    return (target) => { /* applied to the decorated class */ };
}
```

```js
const instrumentation = {
    channelName: "injectable-apply",
    module: { name: "@nestjs/common", versionRange: ">=8.0.0", filePath: "decorators/core/injectable.decorator.js" },
    // Match the arrow returned from `Injectable`. There is no name to target!
    astQuery: 'FunctionDeclaration[id.name="Injectable"] ReturnStatement > ArrowFunctionExpression',
    functionQuery: { kind: "Sync" },
};
```

每次安装时,通道会起火 可用的装饰目标为 `message.arguments[0]`,哪个a 订阅者可以变异,例如用来包装原型方法.

一个 `astQuery` 用于逐字记录,因此可以匹配任何节点, 包括那些基于名称的变体不暴露的,例如 匿名或深度嵌入功能。 (两个名称均基于 `astQuery` 匹配同步和同步函数的工作 类似。 )

如果一个 `astQuery` 匹配节点, “找不到注入” 点"出错包括选择器,因此可以调试.

### 自定义变形

内置运算符( E)`traceSync`, (中文(简体) ), `tracePromise`, (中文(简体) ), `traceCallback`, (中文(简体) ), `traceAuto`选择 `functionQuery.kind`(中文(简体) ) 包括诊断渠道追踪。 当你需要重写一个 匹配不同的节点,将自定义操作员注册到 `matcher.addTransform(name, fn)` 并参考从一个配置 `transform` 字段。 何时 `transform` 设定为优先 结束 `functionQuery.kind`。 。 。 .

自定义变换收到相同的参数 横向产量,加上合并的仪器状态,以及 变异匹配的节点 :

```ts
type CustomTransform = (state, node, parent, ancestry) => void;
```

-   `state` - 配置与运行时域合并 (单位:千美元)`moduleVersion`, (中文(简体) ), `moduleType`, (中文(简体) ), `operator`,解决 `functionQuery`(中文(简体) ).
-   `node` - 匹配的 AST 节点(选定的函数/表达式) 以 `functionQuery` 或者说 `astQuery`) (中文(简体) ).
-   `parent`, (中文(简体) ), `ancestry` - 父节点和完整的祖先链 (最后根数); `ancestry[ancestry.length - 1]` 这是 `Program`。 。 。 .

一个自定义的变换是完全自主的 `node` 重写。 没有 需要插入一个追踪通道.

```js
const matcher = codeTransformer.create([
    {
        channelName: "fetch",
        module: { name: "my-module", versionRange: ">=1.0.0", filePath: "index.js" },
        functionQuery: { functionName: "fetch", kind: "Sync" },
        transform: "myCustomTransform",
    },
]);

matcher.addTransform("myCustomTransform", (state, node) => {
    // Mutate the matched node's AST however you need.
    node.body.body.unshift(/* an ESTree statement */);
});
```

注册匹配内置变换的名称( N)`traceSync`, (中文(简体) ), `tracePromise`, (中文(简体) ), `traceCallback`, (中文(简体) ), `traceAuto`, (中文(简体) ), `tracingChannelImport`, (中文(简体) ), `tracingChannelDeclaration`() 超过它 在它派遣的任何地方—— 包括当有人内在援引 另一个内部(例如,追踪操作员呼叫 `tracingChannelDeclaration`,这反过来又要求 `tracingChannelImport`) (中文(简体) ). `state.transforms` 持有合并的地图 用于此发送的(已安装内置外加已注册的覆盖); 至 代表给原内置的,从一个覆盖,称它通过 页:1 `@apm-js-collab/code-transformer/lib/transforms` 模块 直接说.

(CLI通过 `customTransforms` 区域。 见: [CLI 工具](https://npmcn.com/package/%40apm-js-collab/code-transformer/#readme-cli-tool). ) (中文(简体) )

### API 参考

```ts
type ModuleType = "esm" | "cjs" | "unknown";
type FunctionKind = "Sync" | "Async" | "Callback" | "Auto";
```

#### **`FunctionQuery` 备选案文**

```ts
type FunctionQuery =
    | // Match class constructor
    { className: string; index?: number | null; isExportAlias?: boolean }
    | // Match class method
    {
        className: string;
        methodName: string;
        kind: FunctionKind;
        index?: number | null;
        callbackIndex?: number;
        isExportAlias?: boolean;
    }
    | // Match method on objects
    { methodName: string; kind: FunctionKind; index?: number | null; callbackIndex?: number }
    | // Match standalone function
    { functionName: string; kind: FunctionKind; index?: number | null; callbackIndex?: number; isExportAlias?: boolean }
    | // Match arrow function or function expression
    { expressionName: string; kind: FunctionKind; index?: number | null; callbackIndex?: number; isExportAlias?: boolean };
    | // Match private class methods
    { className: string; privateMethodName: string; kind: FunctionKind; index?: number | null; callbackIndex?: number };
```

#### **`ModuleMatcher`**

```ts
type ModuleMatcher = {
    /** Module name */
    name: string; 
    /** Matching semver range */
    versionRange: string;
    /** 
     * Relative Unix-style path to the file from the module root (e.g. "lib/index.js") 
     * Or a regular expression to test against the Unix-style path.
     */
    filePath: string | RegExp;
};
```

#### **`InstrumentationConfig`**

```ts
// Behaviour-only fields, used when `astQuery` does the matching.
type FunctionBehavior = {
    kind?: FunctionKind;
    index?: number | null;
    callbackIndex?: number;
};

type InstrumentationConfig =
    | {
        channelName: string; // Name of the diagnostics channel
        module: ModuleMatcher;
        functionQuery: FunctionQuery; // Name-based matching
        astQuery?: string; // Raw esquery selector; takes precedence over functionQuery matching
        transform?: string; // Name of a custom transform registered via addTransform
    }
    | {
        channelName: string;
        module: ModuleMatcher;
        astQuery: string; // Raw esquery selector chooses the node(s)
        functionQuery?: FunctionBehavior; // Behaviour only; matching fields ignored
        transform?: string;
    };
```

### 职能

```ts
create(configs: InstrumentationConfig[], dcModule?: string | null): InstrumentationMatcher;
```

为一个或多个仪器配置创建匹配器.

-   `configs` - 仪器配置阵列.
-   `dcModule` - 要导入的可选模块 `diagnostics_channel` API从.

#### **`InstrumentationMatcher`**

```ts
getTransformer(moduleName: string, version: string, filePath: string): Transformer | undefined;
```

获取特定模块和文件的变压器.

回返a `Transformer` 用于给定模块,或 `undefined` 如果没有 匹配仪器配置.

-   `moduleName` - 舱名.
-   `version` - 模块的版本.
-   `filePath` - 从模块根(如:. `"lib/index.js"`) (中文(简体) ). Windows风格的回斜道也被接受,并将自动正常化.

```ts
addTransform(name: string, fn: CustomTransform): void;
```

注册自定义变换操作员 `name`编号 从配置 `transform` 字段。 见 [自定义 变换](https://npmcn.com/package/%40apm-js-collab/code-transformer/#readme-custom-transforms)。 。 。 .

-   `name` - 运算符名称(也用作配置) `transform` 数值).
-   `fn` - 说吧 `(state, node, parent, ancestry) => void`; 变异 匹配节点.

#### **`Transformer`**

```ts
transform(code: string | Buffer, moduleType: ModuleType, sourcemap?: string | undefined): TransformOutput;
```

转换代码,按配置进行注射跟踪.

回返 `{ code, map }`。 。 。 . `map` 如果没有提供源图,则将取消定义.

-   `code` - JavaScript代码要转换.
-   `moduleType` - 正在改造的模块类型.
-   `sourcemap` - 代码的可选现有源地图.

## CLI 工具

软件包包括一个用于应用转换到源文件的 CLI 工具 :

```bash
npx @apm-js-collab/code-transformer transformer.js source-file.js
```

### CLI 使用量

CLI 工具需要两个参数:

1.  `transformer.js` - 一个导出仪器配置的文件
2.  `source-file.js` - 要转换的源文件(可以是任何路径,包括节点 模块)

已转换的代码被写入 stdout, 您可以将它重定向到文件或管道到其他命令中 .

### CLI 示例

创建变压器配置文件 :

```javascript
// my-transformer.js
module.exports = [{
  channelName: 'my-fetch-channel',
  module: {
    name: 'my-module',
    versionRange: '>=1.0.0',
    filePath: 'index.js'
  },
  functionQuery: {
    functionName: 'fetch',
    kind: 'Async'
  }
}]
```

应用转换 :

```bash
npx @apm-js-collab/code-transformer my-transformer.js lib/index.js > instrumented.js
```

变压器配置文件还可以导出一个带有额外选项的对象:

```javascript
module.exports = {
  configs: [/* array of configs */],
  dcModule: './custom-diagnostics-channel.js', // optional custom dc module
  customTransforms: {  // optional custom transform functions
    myCustomTransform: (state, node) => {
      // custom AST transformation logic
    }
  }
}
```

## 许可证

见LICENSE

## 常见问题

### @apm-js-collab/code-transformer 是什么？

这是一个在构建或加载时间帮助给Node\.js 库配置仪器的图书馆\.

### 如何安装 @apm-js-collab/code-transformer？

在项目目录运行 npm install @apm-js-collab/code-transformer，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 code-transformer，可以用 npx code-transformer 直接运行。

### @apm-js-collab/code-transformer 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @apm-js-collab/code-transformer 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @apm-js-collab/code-transformer 可以商用吗？

@apm-js-collab/code-transformer 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @apm-js-collab/code-transformer 的下载量有多少？

根据 npm 官方下载统计，@apm-js-collab/code-transformer 在 2026/10/07 – 2026/11/05 这 30 天内被下载 45,730,135 次，日均约 1,524,338 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @apm-js-collab/code-transformer 还在维护吗？

最新版本 0\.19\.0 发布于 2026/10/22（16 天前）；至今共发布 25 个版本，其中过去 12 个月发布了 11 个；首次发布于 2025/06/02。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

