Skip to content

meta ​

Minified562 BMinzipped279 B

Tools to attach metadata to call expressions.

This is an unplugin that transforms source code by finding call expressions and decorating them with metadata that can be accessed in their respective function declarations, for the purpose of aiding in debugging or building devtools.

Example ​

ts
import { getMeta } from "@monstermann/meta";
import { signal } from "alien-signals";

function createSignal(value) {
    const s = signal(value);
    // Retrieve information from `createSignal(_)` call sites:
    s.meta = getMeta();
    return s;
}
source.ts
ts
const count = createSignal(0);

// Prints: { path: "source.ts", line: 1, name: "count" }
console.log(count.meta);

Implicit ​

The wrapWithMeta preset can be used to implicitly pass metadata as shown above:

createExample.ts
ts
import { getMeta } from "@monstermann/meta";
import { signal } from "alien-signals";

function createExample() {
    getMeta();
}
source.ts (Before)
ts
import { createExample } from "./createExample";
const example = createExample();
source.ts (After)
ts
import { createExample } from "./createExample";
import { withMeta } from "@monstermann/meta";
const path = "source.ts";
const meta = { path, line: 2, name: "example" };
const example = withMeta(meta, () => createExample());

Explicit ​

The addMetaParam and setMetaParam can be used to explicitly pass meta as arguments:

createExample.ts
ts
import type { Meta } from "@monstermann/meta";
import { signal } from "alien-signals";

function createExample(meta?: Meta) {}
source.ts (Before)
ts
import { createExample } from "./createExample";
const example = createExample();
source.ts (After)
ts
import { createExample } from "./createExample";
const path = "source.ts";
const meta = { path, line: 2, name: "example" };
const example = createExample(meta);

Custom ​

The plugin also exposes lower level utilities to transform source code on your own, see the Custom documentation.

Meta ​

ts
interface Meta {
    readonly name: string;
    readonly path: string;
    readonly line: number;
    readonly hmr?: Set<() => void>;
}

name ​

The plugin will try to extract meaningful identifiers for each decorated call expression, for example:

ts
// const meta = { name: "count", ... }
const count = createSignal(0);

// const meta = { name: "createCount", ... }
function createCount() {
    return createSignal(0);
}

// const meta = { name: "createState.count", ... }
function createState() {
    return {
        count: createSignal(0),
    };
}

path ​

The path to the call expression, relative to process.cwd():

source.ts
ts
// const meta = { path: "source.ts", ... }
const count = createSignal(0);

line ​

The line number of the call expression, from the original source code:

source.ts
ts
// const meta = { line: 1, ... }
const count = createSignal(0);

hmr ​

An additional property that is currently only available when using Vite's dev server.

A Set<() => void> that can be used to (un)register hot-module-reload callback functions:

createEventListener.ts
ts
import { getMeta } from "@monstermann/meta";

export function createEventListener(event, callback) {
    window.addEventListener(event, callback);
    const detach = () => window.removeEventListener(event, callback);
    getMeta().hmr?.add(detach);
}
example.ts
ts
import { createEventListener } from "./createEventListener";

createEventListener("resize", callback);

When the above example.ts is hot reloaded, the detach callback from createEventListener.ts will execute.

Installation ​

sh
npm install @monstermann/meta
npm install -D @monstermann/unplugin-meta
sh
pnpm add @monstermann/meta
pnpm add -D @monstermann/unplugin-meta
sh
yarn add @monstermann/meta
yarn add -D @monstermann/unplugin-meta
sh
bun add @monstermann/meta
bun add -D @monstermann/unplugin-meta

Usage ​

ts
import meta from "@monstermann/unplugin-meta/vite";

export default defineConfig({
    plugins: [meta(options)],
});
ts
import meta from "@monstermann/unplugin-meta/rollup";

export default {
    plugins: [meta(options)],
};
ts
import meta from "@monstermann/unplugin-meta/rolldown";

export default {
    plugins: [meta(options)],
};
ts
module.exports = {
    plugins: [require("@monstermann/unplugin-meta/rspack")(options)],
};
ts
import { build } from "esbuild";
import meta from "@monstermann/unplugin-meta/esbuild";

build({
    plugins: [meta(options)],
});

Options ​

ts
export interface TransformMetaResolver {
    (node: Node, meta: Meta): void;
}

interface MetaPluginOptions {
    resolve: TransformMetaResolver | TransformMetaResolver[];
    hmr?: boolean;
    getName?: (name: string, node: Node, meta: Meta) => string;
    getPath?: (path: string, meta: Meta) => string;
    enforce?: "post" | "pre" | undefined;
    include?: string | string[] | RegExp | RegExp[];
    exclude?: string | string[] | RegExp | RegExp[];
}

resolve ​

A function that receives every node of a file's AST, as parsed by the Oxidation Compiler, and a helper class containing code transformation utilities.

Rolldown
ts
import meta, {
    addMetaParam,
    setMetaParam,
    wrapWithMeta,
} from "@monstermann/unplugin-meta/rolldown";

export default {
    plugins: [
        meta({
            resolve: [
                // Use the presets:
                addMetaParam(["foo"]),
                setMetaParam({ bar: 1 }),
                wrapWithMeta(["baz"]),
                // Or do your own code transformations:
                function (node, meta) {},
            ],
        }),
    ],
};

hmr ​

Enables/disables the hmr property of Meta records and its related hot-module-reloading related setup code.

Enabled by default when running Vite's dev server.

getName ​

Allows you to transform the name property of all Meta records.

source.ts
ts
const foo = bar();
Rolldown
ts
import meta, { addMetaParam } from "@monstermann/unplugin-meta/rolldown";

export default {
    plugins: [
        meta({
            resolve: addMetaParam(["foo"]),
            getName: (name) => name.toUpperCase(),
        }),
    ],
};
Output
ts
const path = "source.ts";
const meta = { path, line: 1, name: "FOO" };
const foo = bar(meta);

getPath ​

Allows you to transform the path property of all Meta records.

source.ts
ts
const foo = bar();
Rolldown
ts
import meta, { addMetaParam } from "@monstermann/unplugin-meta/rolldown";

export default {
    plugins: [
        meta({
            resolve: addMetaParam(["foo"]),
            getPath: (path) => `@package/${path}`,
        }),
    ],
};
Output
ts
const path = "@package/source.ts";
const meta = { path, line: 1, name: "foo" };
const foo = bar(meta);

enforce ​

Enforces plugin order in bundlers that support this option.

include ​

Glob(s) or RegExp(s) to specifiy which file paths to include when transforming.

exclude ​

Glob(s) or RegExp(s) to specifiy which file paths to exclude when transforming.