Logo of magicast

magicast

以编程方式修改 JavaScript 和 TypeScript 源代码。

以简化、优雅且熟悉的语法,以编程方式修改 JavaScript 和 TypeScript 源代码。构建于 AST 之上,由 recastbabel 解析。

❯ 🧙🏼 神奇地 修改 JS/TS 文件并像 JSON 一样神奇地写回!
❯ 🔀 导出/导入 轻松操作模块的导入和导出
❯ 💼 函数参数 轻松操作传递给函数调用的参数,例如 defineConfig()
❯ 🎨 智能格式化 保留原始代码的格式风格(引号、制表符等)
❯ 🧑‍💻 可读性强 摆脱 AST 操作的复杂性,让您的代码超级可读

安装

安装 npm 包

# using yarn
yarn add --dev magicast

# using npm
npm install -D magicast

# using pnpm
pnpm add -D magicast

导入工具函数

// ESM / Bundler
import { parseModule, generateCode, builders, createNode } from "magicast";

// CommonJS
const { parseModule, generateCode, builders, createNode } = require("magicast");

示例

示例: 修改文件

config.js:

export default {
  foo: ["a"],
};

要修改的代码,将 b 追加到 defaultExport 的 foo 属性

import { loadFile, writeFile } from "magicast";

const mod = await loadFile("config.js");

mod.exports.default.foo.push("b");

await writeFile(mod, "config.js");

已更新的 config.js

export default {
  foo: ["a", "b"],
};

示例: 直接使用 AST 工具

import { parseModule, generateCode } from "magicast";

// Parse to AST
const mod = parseModule(`export default { }`);

// Ensure foo is an array
mod.exports.default.foo ||= [];
// Add a new array member
mod.exports.default.foo.push("b");
mod.exports.default.foo.unshift("a");

// Generate code
const { code, map } = generateCode(mod);

生成的代码

export default {
  foo: ["a", "b"],
};

示例: 直接获取 AST

import { parseModule, generateCode } from "magicast";

const mod = parseModule(`export default { }`);

const ast = mod.exports.default.$ast
// do something with ast

示例: 函数参数

import { parseModule, generateCode } from "magicast";

const mod = parseModule(`export default defineConfig({ foo: 'bar' })`);

// Support for both bare object export and `defineConfig` wrapper
const options = mod.exports.default.$type === 'function-call'
  ? mod.exports.default.$args[0]
  : mod.exports.default;

console.log(options.foo) // bar

示例: 创建函数调用

import { parseModule, generateCode, builders } from "magicast";

const mod = parseModule(`export default {}`);

const options = mod.exports.default.list = builders.functionCall('create', [1, 2, 3])

console.log(mod.generateCode()) // export default { list: create([1, 2, 3]) }

注意事项

由于 JavaScript 是一种非常动态的语言,您应该意识到 Magicast 的约定不能涵盖所有可能的情况。Magicast 作为一个简单且可维护的接口,用于更新静态化的 JavaScript 代码。与 Magicast 节点交互时,请注意每个选项都可能根据输入代码抛出错误。我们建议始终将代码包装在 try/catch 块中(最好进行一些防御性编程),例如

import { loadFile, writeFile } from "magicast";

function updateConfig() {
  try {
    const mod = await loadFile("config.js");

    mod.exports.default.foo.push("b");

    await writeFile(mod);
  } catch (e) {
    console.error('Unable to update config.js')
    console.error('Please update it manually with the following instructions: ...')
    // handle error
  }
}

高级辅助函数

我们还尝试提供一些高级辅助函数,以简化常见任务。您可以从 magicast/helpers 导入它们。它们将来可能会被移到单独的包中。

import {
  deepMergeObject,
  addNuxtModule,
  addVitePlugin,
  // ...
} from "magicast/helpers";

我们建议查看源代码测试用例以获取更多详细信息。

开发

  • 克隆此仓库
  • 安装最新 LTS 版本的 Node.js
  • 使用 Corepack 启用 corepack enable
  • 使用 pnpm install 安装依赖项
  • 使用 pnpm dev 运行交互式测试

许可

用心制作 💛

根据 MIT 许可证发布。