@clayroach/unplugin 0.1.0-source-trace.2 → 0.1.0-source-trace.3

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.
package/dist/cjs/index.js CHANGED
@@ -9,6 +9,7 @@ var _parser = require("@babel/parser");
9
9
  var _traverse2 = _interopRequireDefault(require("@babel/traverse"));
10
10
  var _unplugin = require("unplugin");
11
11
  var _sourceTrace = require("./transformers/sourceTrace.js");
12
+ var _withSpanTrace = require("./transformers/withSpanTrace.js");
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
14
  // Handle both ESM and CJS module exports for Babel packages
14
15
  const traverse = typeof _traverse2.default === "function" ? _traverse2.default : _traverse2.default.default;
@@ -51,7 +52,8 @@ const unpluginFactory = (options = {}) => {
51
52
  annotateEffects: _annotateEffects = false,
52
53
  exclude = DEFAULT_EXCLUDE,
53
54
  include = DEFAULT_INCLUDE,
54
- sourceTrace = true
55
+ sourceTrace = true,
56
+ spanTrace = true
55
57
  } = options;
56
58
  return {
57
59
  name: "@effect/unplugin",
@@ -69,6 +71,9 @@ const unpluginFactory = (options = {}) => {
69
71
  if (sourceTrace) {
70
72
  visitors.push((0, _sourceTrace.createSourceTraceVisitor)(id));
71
73
  }
74
+ if (spanTrace) {
75
+ visitors.push((0, _withSpanTrace.createWithSpanTraceVisitor)(id));
76
+ }
72
77
  // Combine visitors
73
78
  if (visitors.length === 0) {
74
79
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_generator","_interopRequireDefault","require","_parser","_traverse2","_unplugin","_sourceTrace","e","__esModule","default","traverse","_traverse","generate","_generate","DEFAULT_INCLUDE","DEFAULT_EXCLUDE","shouldTransform","id","include","exclude","pattern","includes","test","unpluginFactory","options","annotateEffects","_annotateEffects","sourceTrace","name","transformInclude","transform","code","ast","parse","sourceType","plugins","visitors","push","createSourceTraceVisitor","length","states","map","filename","hoisting","hoistedTraces","Map","counter","statements","i","undefined","output","sourceMaps","sourceFileName","unplugin","exports","createUnplugin","_default"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_generator","_interopRequireDefault","require","_parser","_traverse2","_unplugin","_sourceTrace","_withSpanTrace","e","__esModule","default","traverse","_traverse","generate","_generate","DEFAULT_INCLUDE","DEFAULT_EXCLUDE","shouldTransform","id","include","exclude","pattern","includes","test","unpluginFactory","options","annotateEffects","_annotateEffects","sourceTrace","spanTrace","name","transformInclude","transform","code","ast","parse","sourceType","plugins","visitors","push","createSourceTraceVisitor","createWithSpanTraceVisitor","length","states","map","filename","hoisting","hoistedTraces","Map","counter","statements","i","undefined","output","sourceMaps","sourceFileName","unplugin","exports","createUnplugin","_default"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createWithSpanTraceVisitor = createWithSpanTraceVisitor;
7
+ exports.withSpanTraceTransformer = withSpanTraceTransformer;
8
+ var t = _interopRequireWildcard(require("@babel/types"));
9
+ var _hoisting = require("../utils/hoisting.js");
10
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
+ /**
12
+ * Checks if a CallExpression is a withSpan call.
13
+ * Matches: Effect.withSpan(...), _.withSpan(...), or standalone withSpan(...)
14
+ */
15
+ function isWithSpanCall(node) {
16
+ const callee = node.callee;
17
+ // Match Effect.withSpan(...) or _.withSpan(...)
18
+ if (callee.type === "MemberExpression" && callee.property.type === "Identifier" && callee.property.name === "withSpan") {
19
+ return true;
20
+ }
21
+ // Match standalone withSpan(...)
22
+ if (callee.type === "Identifier" && callee.name === "withSpan") {
23
+ return true;
24
+ }
25
+ return false;
26
+ }
27
+ /**
28
+ * Determines if this is a data-first call (effect as first arg) or data-last (name as first arg).
29
+ * Data-first: withSpan(effect, "name", options?)
30
+ * Data-last: withSpan("name", options?)
31
+ */
32
+ function isDataFirstCall(node) {
33
+ // If first argument is a string literal, it's data-last
34
+ if (node.arguments.length > 0 && t.isStringLiteral(node.arguments[0])) {
35
+ return false;
36
+ }
37
+ // If second argument exists and is a string literal, it's data-first
38
+ if (node.arguments.length > 1 && t.isStringLiteral(node.arguments[1])) {
39
+ return true;
40
+ }
41
+ // Default to data-last pattern
42
+ return false;
43
+ }
44
+ /**
45
+ * Creates the attributes object with source location.
46
+ */
47
+ function createSourceAttributes(filepath, line, column) {
48
+ return t.objectExpression([t.objectProperty(t.stringLiteral("code.filepath"), t.stringLiteral(filepath)), t.objectProperty(t.stringLiteral("code.lineno"), t.numericLiteral(line)), t.objectProperty(t.stringLiteral("code.column"), t.numericLiteral(column))]);
49
+ }
50
+ /**
51
+ * Merges source attributes into an existing options object or creates a new one.
52
+ */
53
+ function mergeOrCreateOptions(existingOptions, sourceAttrs) {
54
+ if (!existingOptions || t.isSpreadElement(existingOptions) || t.isArgumentPlaceholder(existingOptions)) {
55
+ // No existing options, create new object with attributes
56
+ return t.objectExpression([t.objectProperty(t.identifier("attributes"), sourceAttrs)]);
57
+ }
58
+ if (t.isObjectExpression(existingOptions)) {
59
+ // Check if there's an existing attributes property
60
+ const existingAttrsIndex = existingOptions.properties.findIndex(prop => t.isObjectProperty(prop) && (t.isIdentifier(prop.key) && prop.key.name === "attributes" || t.isStringLiteral(prop.key) && prop.key.value === "attributes"));
61
+ if (existingAttrsIndex >= 0) {
62
+ // Merge with existing attributes using spread
63
+ const existingAttrsProp = existingOptions.properties[existingAttrsIndex];
64
+ const mergedAttrs = t.objectExpression([t.spreadElement(existingAttrsProp.value), ...sourceAttrs.properties]);
65
+ // Clone the options and replace the attributes property
66
+ const newProperties = [...existingOptions.properties];
67
+ newProperties[existingAttrsIndex] = t.objectProperty(t.identifier("attributes"), mergedAttrs);
68
+ return t.objectExpression(newProperties);
69
+ } else {
70
+ // Add new attributes property to existing object
71
+ return t.objectExpression([...existingOptions.properties, t.objectProperty(t.identifier("attributes"), sourceAttrs)]);
72
+ }
73
+ }
74
+ // If it's a variable reference, spread it and add attributes
75
+ return t.objectExpression([t.spreadElement(existingOptions), t.objectProperty(t.identifier("attributes"), sourceAttrs)]);
76
+ }
77
+ /**
78
+ * Creates a Babel visitor that injects source location attributes into Effect.withSpan calls.
79
+ */
80
+ function createWithSpanTraceVisitor(filename, _options) {
81
+ return {
82
+ Program: {
83
+ enter(_path, state) {
84
+ state.filename = filename;
85
+ state.hoisting = (0, _hoisting.createHoistingState)();
86
+ },
87
+ exit(path, state) {
88
+ // Prepend all hoisted statements to the program body
89
+ if (state.hoisting.statements.length > 0) {
90
+ path.unshiftContainer("body", state.hoisting.statements);
91
+ }
92
+ }
93
+ },
94
+ CallExpression(path, state) {
95
+ const node = path.node;
96
+ if (!isWithSpanCall(node)) {
97
+ return;
98
+ }
99
+ // Get source location
100
+ const loc = node.loc;
101
+ if (!loc) return;
102
+ const line = loc.start.line;
103
+ const column = loc.start.column;
104
+ // Create source attributes
105
+ const sourceAttrs = createSourceAttributes(state.filename, line, column);
106
+ const isDataFirst = isDataFirstCall(node);
107
+ if (isDataFirst) {
108
+ // Data-first: withSpan(effect, "name", options?)
109
+ // Options is at index 2
110
+ const optionsArg = node.arguments[2];
111
+ const newOptions = mergeOrCreateOptions(optionsArg, sourceAttrs);
112
+ if (node.arguments.length >= 3) {
113
+ // Replace existing options
114
+ node.arguments[2] = newOptions;
115
+ } else {
116
+ // Add options as third argument
117
+ node.arguments.push(newOptions);
118
+ }
119
+ } else {
120
+ // Data-last: withSpan("name", options?)
121
+ // Options is at index 1
122
+ const optionsArg = node.arguments[1];
123
+ const newOptions = mergeOrCreateOptions(optionsArg, sourceAttrs);
124
+ if (node.arguments.length >= 2) {
125
+ // Replace existing options
126
+ node.arguments[1] = newOptions;
127
+ } else {
128
+ // Add options as second argument
129
+ node.arguments.push(newOptions);
130
+ }
131
+ }
132
+ }
133
+ };
134
+ }
135
+ /**
136
+ * Creates the withSpan trace transformer plugin.
137
+ */
138
+ function withSpanTraceTransformer(options) {
139
+ return {
140
+ name: "effect-withspan-trace",
141
+ visitor: createWithSpanTraceVisitor("", options)
142
+ };
143
+ }
144
+ //# sourceMappingURL=withSpanTrace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withSpanTrace.js","names":["t","_interopRequireWildcard","require","_hoisting","e","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","isWithSpanCall","node","callee","type","property","name","isDataFirstCall","arguments","length","isStringLiteral","createSourceAttributes","filepath","line","column","objectExpression","objectProperty","stringLiteral","numericLiteral","mergeOrCreateOptions","existingOptions","sourceAttrs","isSpreadElement","isArgumentPlaceholder","identifier","isObjectExpression","existingAttrsIndex","properties","findIndex","prop","isObjectProperty","isIdentifier","key","value","existingAttrsProp","mergedAttrs","spreadElement","newProperties","createWithSpanTraceVisitor","filename","_options","Program","enter","_path","state","hoisting","createHoistingState","exit","path","statements","unshiftContainer","CallExpression","loc","start","isDataFirst","optionsArg","newOptions","push","withSpanTraceTransformer","options","visitor"],"sources":["../../../src/transformers/withSpanTrace.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -12,6 +12,13 @@ export interface EffectPluginOptions {
12
12
  * @default true
13
13
  */
14
14
  readonly sourceTrace?: boolean;
15
+ /**
16
+ * Enable source location attributes injection into Effect.withSpan() calls.
17
+ * When enabled, spans will include code.filepath, code.lineno, and code.column attributes.
18
+ *
19
+ * @default true
20
+ */
21
+ readonly spanTrace?: boolean;
15
22
  /**
16
23
  * Enable @__PURE__ annotations for tree-shaking.
17
24
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAmCtF;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAE9B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAElC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAExC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACzC;AA2GD;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAAgB,CAAC,mBAAmB,GAAG,SAAS,EAAE,OAAO,CAAmC,CAAA;AAEnH;;;;GAIG;AACH,eAAe,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAwC,KAAK,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAoCtF;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAA;IAE9B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAElC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAExC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CACzC;AAgHD;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAAgB,CAAC,mBAAmB,GAAG,SAAS,EAAE,OAAO,CAAmC,CAAA;AAEnH;;;;GAIG;AACH,eAAe,QAAQ,CAAA"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * WithSpan source location trace transformer.
3
+ *
4
+ * This transformer injects source location metadata as attributes into Effect.withSpan() calls.
5
+ * It transforms `Effect.withSpan("name")` into `Effect.withSpan("name", { attributes: { "code.filepath": ..., "code.lineno": ... }})`.
6
+ *
7
+ * @since 0.1.0
8
+ */
9
+ import type { Visitor } from "@babel/traverse";
10
+ import { type HoistingState } from "../utils/hoisting.js";
11
+ /**
12
+ * Options for the withSpan trace transformer.
13
+ */
14
+ export interface WithSpanTraceOptions {
15
+ /**
16
+ * Filter function to determine if a file should be transformed.
17
+ */
18
+ readonly filter?: (filename: string) => boolean;
19
+ }
20
+ /**
21
+ * State passed through the transformer.
22
+ */
23
+ interface TransformState {
24
+ filename: string;
25
+ hoisting: HoistingState;
26
+ }
27
+ /**
28
+ * Creates a Babel visitor that injects source location attributes into Effect.withSpan calls.
29
+ */
30
+ export declare function createWithSpanTraceVisitor(filename: string, _options?: WithSpanTraceOptions): Visitor<TransformState>;
31
+ /**
32
+ * Creates the withSpan trace transformer plugin.
33
+ */
34
+ export declare function withSpanTraceTransformer(options?: WithSpanTraceOptions): {
35
+ visitor: Visitor<TransformState>;
36
+ name: string;
37
+ };
38
+ export {};
39
+ //# sourceMappingURL=withSpanTrace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withSpanTrace.d.ts","sourceRoot":"","sources":["../../../src/transformers/withSpanTrace.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAY,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAExD,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAA;AAE7B;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAA;CAChD;AAED;;GAEG;AACH,UAAU,cAAc;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,aAAa,CAAA;CACxB;AA0HD;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,oBAAoB,GAC9B,OAAO,CAAC,cAAc,CAAC,CA+DzB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG;IACxE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;CACb,CAKA"}
package/dist/esm/index.js CHANGED
@@ -3,6 +3,7 @@ import { parse } from "@babel/parser";
3
3
  import _traverse from "@babel/traverse";
4
4
  import { createUnplugin } from "unplugin";
5
5
  import { createSourceTraceVisitor } from "./transformers/sourceTrace.js";
6
+ import { createWithSpanTraceVisitor } from "./transformers/withSpanTrace.js";
6
7
  // Handle both ESM and CJS module exports for Babel packages
7
8
  const traverse = typeof _traverse === "function"
8
9
  ? _traverse
@@ -48,7 +49,7 @@ function shouldTransform(id, include, exclude) {
48
49
  * Creates the unplugin factory.
49
50
  */
50
51
  const unpluginFactory = (options = {}) => {
51
- const { annotateEffects: _annotateEffects = false, exclude = DEFAULT_EXCLUDE, include = DEFAULT_INCLUDE, sourceTrace = true } = options;
52
+ const { annotateEffects: _annotateEffects = false, exclude = DEFAULT_EXCLUDE, include = DEFAULT_INCLUDE, sourceTrace = true, spanTrace = true } = options;
52
53
  return {
53
54
  name: "@effect/unplugin",
54
55
  transformInclude(id) {
@@ -65,6 +66,9 @@ const unpluginFactory = (options = {}) => {
65
66
  if (sourceTrace) {
66
67
  visitors.push(createSourceTraceVisitor(id));
67
68
  }
69
+ if (spanTrace) {
70
+ visitors.push(createWithSpanTraceVisitor(id));
71
+ }
68
72
  // Combine visitors
69
73
  if (visitors.length === 0) {
70
74
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,160 @@
1
+ import * as t from "@babel/types";
2
+ import { createHoistingState } from "../utils/hoisting.js";
3
+ /**
4
+ * Checks if a CallExpression is a withSpan call.
5
+ * Matches: Effect.withSpan(...), _.withSpan(...), or standalone withSpan(...)
6
+ */
7
+ function isWithSpanCall(node) {
8
+ const callee = node.callee;
9
+ // Match Effect.withSpan(...) or _.withSpan(...)
10
+ if (callee.type === "MemberExpression" &&
11
+ callee.property.type === "Identifier" &&
12
+ callee.property.name === "withSpan") {
13
+ return true;
14
+ }
15
+ // Match standalone withSpan(...)
16
+ if (callee.type === "Identifier" && callee.name === "withSpan") {
17
+ return true;
18
+ }
19
+ return false;
20
+ }
21
+ /**
22
+ * Determines if this is a data-first call (effect as first arg) or data-last (name as first arg).
23
+ * Data-first: withSpan(effect, "name", options?)
24
+ * Data-last: withSpan("name", options?)
25
+ */
26
+ function isDataFirstCall(node) {
27
+ // If first argument is a string literal, it's data-last
28
+ if (node.arguments.length > 0 && t.isStringLiteral(node.arguments[0])) {
29
+ return false;
30
+ }
31
+ // If second argument exists and is a string literal, it's data-first
32
+ if (node.arguments.length > 1 && t.isStringLiteral(node.arguments[1])) {
33
+ return true;
34
+ }
35
+ // Default to data-last pattern
36
+ return false;
37
+ }
38
+ /**
39
+ * Creates the attributes object with source location.
40
+ */
41
+ function createSourceAttributes(filepath, line, column) {
42
+ return t.objectExpression([
43
+ t.objectProperty(t.stringLiteral("code.filepath"), t.stringLiteral(filepath)),
44
+ t.objectProperty(t.stringLiteral("code.lineno"), t.numericLiteral(line)),
45
+ t.objectProperty(t.stringLiteral("code.column"), t.numericLiteral(column))
46
+ ]);
47
+ }
48
+ /**
49
+ * Merges source attributes into an existing options object or creates a new one.
50
+ */
51
+ function mergeOrCreateOptions(existingOptions, sourceAttrs) {
52
+ if (!existingOptions || t.isSpreadElement(existingOptions) || t.isArgumentPlaceholder(existingOptions)) {
53
+ // No existing options, create new object with attributes
54
+ return t.objectExpression([
55
+ t.objectProperty(t.identifier("attributes"), sourceAttrs)
56
+ ]);
57
+ }
58
+ if (t.isObjectExpression(existingOptions)) {
59
+ // Check if there's an existing attributes property
60
+ const existingAttrsIndex = existingOptions.properties.findIndex((prop) => t.isObjectProperty(prop) &&
61
+ ((t.isIdentifier(prop.key) && prop.key.name === "attributes") ||
62
+ (t.isStringLiteral(prop.key) && prop.key.value === "attributes")));
63
+ if (existingAttrsIndex >= 0) {
64
+ // Merge with existing attributes using spread
65
+ const existingAttrsProp = existingOptions.properties[existingAttrsIndex];
66
+ const mergedAttrs = t.objectExpression([
67
+ t.spreadElement(existingAttrsProp.value),
68
+ ...sourceAttrs.properties
69
+ ]);
70
+ // Clone the options and replace the attributes property
71
+ const newProperties = [...existingOptions.properties];
72
+ newProperties[existingAttrsIndex] = t.objectProperty(t.identifier("attributes"), mergedAttrs);
73
+ return t.objectExpression(newProperties);
74
+ }
75
+ else {
76
+ // Add new attributes property to existing object
77
+ return t.objectExpression([
78
+ ...existingOptions.properties,
79
+ t.objectProperty(t.identifier("attributes"), sourceAttrs)
80
+ ]);
81
+ }
82
+ }
83
+ // If it's a variable reference, spread it and add attributes
84
+ return t.objectExpression([
85
+ t.spreadElement(existingOptions),
86
+ t.objectProperty(t.identifier("attributes"), sourceAttrs)
87
+ ]);
88
+ }
89
+ /**
90
+ * Creates a Babel visitor that injects source location attributes into Effect.withSpan calls.
91
+ */
92
+ export function createWithSpanTraceVisitor(filename, _options) {
93
+ return {
94
+ Program: {
95
+ enter(_path, state) {
96
+ state.filename = filename;
97
+ state.hoisting = createHoistingState();
98
+ },
99
+ exit(path, state) {
100
+ // Prepend all hoisted statements to the program body
101
+ if (state.hoisting.statements.length > 0) {
102
+ path.unshiftContainer("body", state.hoisting.statements);
103
+ }
104
+ }
105
+ },
106
+ CallExpression(path, state) {
107
+ const node = path.node;
108
+ if (!isWithSpanCall(node)) {
109
+ return;
110
+ }
111
+ // Get source location
112
+ const loc = node.loc;
113
+ if (!loc)
114
+ return;
115
+ const line = loc.start.line;
116
+ const column = loc.start.column;
117
+ // Create source attributes
118
+ const sourceAttrs = createSourceAttributes(state.filename, line, column);
119
+ const isDataFirst = isDataFirstCall(node);
120
+ if (isDataFirst) {
121
+ // Data-first: withSpan(effect, "name", options?)
122
+ // Options is at index 2
123
+ const optionsArg = node.arguments[2];
124
+ const newOptions = mergeOrCreateOptions(optionsArg, sourceAttrs);
125
+ if (node.arguments.length >= 3) {
126
+ // Replace existing options
127
+ node.arguments[2] = newOptions;
128
+ }
129
+ else {
130
+ // Add options as third argument
131
+ node.arguments.push(newOptions);
132
+ }
133
+ }
134
+ else {
135
+ // Data-last: withSpan("name", options?)
136
+ // Options is at index 1
137
+ const optionsArg = node.arguments[1];
138
+ const newOptions = mergeOrCreateOptions(optionsArg, sourceAttrs);
139
+ if (node.arguments.length >= 2) {
140
+ // Replace existing options
141
+ node.arguments[1] = newOptions;
142
+ }
143
+ else {
144
+ // Add options as second argument
145
+ node.arguments.push(newOptions);
146
+ }
147
+ }
148
+ }
149
+ };
150
+ }
151
+ /**
152
+ * Creates the withSpan trace transformer plugin.
153
+ */
154
+ export function withSpanTraceTransformer(options) {
155
+ return {
156
+ name: "effect-withspan-trace",
157
+ visitor: createWithSpanTraceVisitor("", options)
158
+ };
159
+ }
160
+ //# sourceMappingURL=withSpanTrace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withSpanTrace.js","sourceRoot":"","sources":["../../../src/transformers/withSpanTrace.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clayroach/unplugin",
3
- "version": "0.1.0-source-trace.2",
3
+ "version": "0.1.0-source-trace.3",
4
4
  "description": "Universal bundler plugin for Effect transformations",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -18,7 +18,7 @@
18
18
  "@babel/generator": "^7.26.0"
19
19
  },
20
20
  "peerDependencies": {
21
- "@clayroach/effect": "^3.19.14-source-trace.2"
21
+ "@clayroach/effect": "^3.19.14-source-trace.3"
22
22
  },
23
23
  "publishConfig": {
24
24
  "provenance": true
package/src/index.ts CHANGED
@@ -29,6 +29,7 @@ import _traverse from "@babel/traverse"
29
29
  import type { Node } from "@babel/types"
30
30
  import { createUnplugin, type UnpluginFactory, type UnpluginInstance } from "unplugin"
31
31
  import { createSourceTraceVisitor } from "./transformers/sourceTrace.js"
32
+ import { createWithSpanTraceVisitor } from "./transformers/withSpanTrace.js"
32
33
  import type { HoistingState } from "./utils/hoisting.js"
33
34
 
34
35
  // Define function types for Babel packages (they export differently in ESM vs CJS)
@@ -76,6 +77,14 @@ export interface EffectPluginOptions {
76
77
  */
77
78
  readonly sourceTrace?: boolean
78
79
 
80
+ /**
81
+ * Enable source location attributes injection into Effect.withSpan() calls.
82
+ * When enabled, spans will include code.filepath, code.lineno, and code.column attributes.
83
+ *
84
+ * @default true
85
+ */
86
+ readonly spanTrace?: boolean
87
+
79
88
  /**
80
89
  * Enable @__PURE__ annotations for tree-shaking.
81
90
  *
@@ -145,7 +154,8 @@ const unpluginFactory: UnpluginFactory<EffectPluginOptions | undefined> = (optio
145
154
  annotateEffects: _annotateEffects = false,
146
155
  exclude = DEFAULT_EXCLUDE,
147
156
  include = DEFAULT_INCLUDE,
148
- sourceTrace = true
157
+ sourceTrace = true,
158
+ spanTrace = true
149
159
  } = options
150
160
 
151
161
  return {
@@ -169,6 +179,10 @@ const unpluginFactory: UnpluginFactory<EffectPluginOptions | undefined> = (optio
169
179
  visitors.push(createSourceTraceVisitor(id))
170
180
  }
171
181
 
182
+ if (spanTrace) {
183
+ visitors.push(createWithSpanTraceVisitor(id))
184
+ }
185
+
172
186
  // Combine visitors
173
187
  if (visitors.length === 0) {
174
188
  return null
@@ -0,0 +1,236 @@
1
+ /**
2
+ * WithSpan source location trace transformer.
3
+ *
4
+ * This transformer injects source location metadata as attributes into Effect.withSpan() calls.
5
+ * It transforms `Effect.withSpan("name")` into `Effect.withSpan("name", { attributes: { "code.filepath": ..., "code.lineno": ... }})`.
6
+ *
7
+ * @since 0.1.0
8
+ */
9
+ import type { NodePath, Visitor } from "@babel/traverse"
10
+ import * as t from "@babel/types"
11
+ import {
12
+ createHoistingState,
13
+ type HoistingState
14
+ } from "../utils/hoisting.js"
15
+
16
+ /**
17
+ * Options for the withSpan trace transformer.
18
+ */
19
+ export interface WithSpanTraceOptions {
20
+ /**
21
+ * Filter function to determine if a file should be transformed.
22
+ */
23
+ readonly filter?: (filename: string) => boolean
24
+ }
25
+
26
+ /**
27
+ * State passed through the transformer.
28
+ */
29
+ interface TransformState {
30
+ filename: string
31
+ hoisting: HoistingState
32
+ }
33
+
34
+ /**
35
+ * Checks if a CallExpression is a withSpan call.
36
+ * Matches: Effect.withSpan(...), _.withSpan(...), or standalone withSpan(...)
37
+ */
38
+ function isWithSpanCall(node: t.CallExpression): boolean {
39
+ const callee = node.callee
40
+
41
+ // Match Effect.withSpan(...) or _.withSpan(...)
42
+ if (
43
+ callee.type === "MemberExpression" &&
44
+ callee.property.type === "Identifier" &&
45
+ callee.property.name === "withSpan"
46
+ ) {
47
+ return true
48
+ }
49
+
50
+ // Match standalone withSpan(...)
51
+ if (callee.type === "Identifier" && callee.name === "withSpan") {
52
+ return true
53
+ }
54
+
55
+ return false
56
+ }
57
+
58
+ /**
59
+ * Determines if this is a data-first call (effect as first arg) or data-last (name as first arg).
60
+ * Data-first: withSpan(effect, "name", options?)
61
+ * Data-last: withSpan("name", options?)
62
+ */
63
+ function isDataFirstCall(node: t.CallExpression): boolean {
64
+ // If first argument is a string literal, it's data-last
65
+ if (node.arguments.length > 0 && t.isStringLiteral(node.arguments[0])) {
66
+ return false
67
+ }
68
+ // If second argument exists and is a string literal, it's data-first
69
+ if (node.arguments.length > 1 && t.isStringLiteral(node.arguments[1])) {
70
+ return true
71
+ }
72
+ // Default to data-last pattern
73
+ return false
74
+ }
75
+
76
+ /**
77
+ * Creates the attributes object with source location.
78
+ */
79
+ function createSourceAttributes(
80
+ filepath: string,
81
+ line: number,
82
+ column: number
83
+ ): t.ObjectExpression {
84
+ return t.objectExpression([
85
+ t.objectProperty(
86
+ t.stringLiteral("code.filepath"),
87
+ t.stringLiteral(filepath)
88
+ ),
89
+ t.objectProperty(
90
+ t.stringLiteral("code.lineno"),
91
+ t.numericLiteral(line)
92
+ ),
93
+ t.objectProperty(
94
+ t.stringLiteral("code.column"),
95
+ t.numericLiteral(column)
96
+ )
97
+ ])
98
+ }
99
+
100
+ /**
101
+ * Merges source attributes into an existing options object or creates a new one.
102
+ */
103
+ function mergeOrCreateOptions(
104
+ existingOptions: t.Expression | t.SpreadElement | t.ArgumentPlaceholder | undefined,
105
+ sourceAttrs: t.ObjectExpression
106
+ ): t.ObjectExpression {
107
+ if (!existingOptions || t.isSpreadElement(existingOptions) || t.isArgumentPlaceholder(existingOptions)) {
108
+ // No existing options, create new object with attributes
109
+ return t.objectExpression([
110
+ t.objectProperty(t.identifier("attributes"), sourceAttrs)
111
+ ])
112
+ }
113
+
114
+ if (t.isObjectExpression(existingOptions)) {
115
+ // Check if there's an existing attributes property
116
+ const existingAttrsIndex = existingOptions.properties.findIndex(
117
+ (prop) =>
118
+ t.isObjectProperty(prop) &&
119
+ ((t.isIdentifier(prop.key) && prop.key.name === "attributes") ||
120
+ (t.isStringLiteral(prop.key) && prop.key.value === "attributes"))
121
+ )
122
+
123
+ if (existingAttrsIndex >= 0) {
124
+ // Merge with existing attributes using spread
125
+ const existingAttrsProp = existingOptions.properties[existingAttrsIndex] as t.ObjectProperty
126
+ const mergedAttrs = t.objectExpression([
127
+ t.spreadElement(existingAttrsProp.value as t.Expression),
128
+ ...sourceAttrs.properties
129
+ ])
130
+
131
+ // Clone the options and replace the attributes property
132
+ const newProperties = [...existingOptions.properties]
133
+ newProperties[existingAttrsIndex] = t.objectProperty(
134
+ t.identifier("attributes"),
135
+ mergedAttrs
136
+ )
137
+ return t.objectExpression(newProperties)
138
+ } else {
139
+ // Add new attributes property to existing object
140
+ return t.objectExpression([
141
+ ...existingOptions.properties,
142
+ t.objectProperty(t.identifier("attributes"), sourceAttrs)
143
+ ])
144
+ }
145
+ }
146
+
147
+ // If it's a variable reference, spread it and add attributes
148
+ return t.objectExpression([
149
+ t.spreadElement(existingOptions),
150
+ t.objectProperty(t.identifier("attributes"), sourceAttrs)
151
+ ])
152
+ }
153
+
154
+ /**
155
+ * Creates a Babel visitor that injects source location attributes into Effect.withSpan calls.
156
+ */
157
+ export function createWithSpanTraceVisitor(
158
+ filename: string,
159
+ _options?: WithSpanTraceOptions
160
+ ): Visitor<TransformState> {
161
+ return {
162
+ Program: {
163
+ enter(_path, state) {
164
+ state.filename = filename
165
+ state.hoisting = createHoistingState()
166
+ },
167
+ exit(path, state) {
168
+ // Prepend all hoisted statements to the program body
169
+ if (state.hoisting.statements.length > 0) {
170
+ path.unshiftContainer("body", state.hoisting.statements)
171
+ }
172
+ }
173
+ },
174
+
175
+ CallExpression(path: NodePath<t.CallExpression>, state) {
176
+ const node = path.node
177
+
178
+ if (!isWithSpanCall(node)) {
179
+ return
180
+ }
181
+
182
+ // Get source location
183
+ const loc = node.loc
184
+ if (!loc) return
185
+
186
+ const line = loc.start.line
187
+ const column = loc.start.column
188
+
189
+ // Create source attributes
190
+ const sourceAttrs = createSourceAttributes(state.filename, line, column)
191
+
192
+ const isDataFirst = isDataFirstCall(node)
193
+
194
+ if (isDataFirst) {
195
+ // Data-first: withSpan(effect, "name", options?)
196
+ // Options is at index 2
197
+ const optionsArg = node.arguments[2]
198
+ const newOptions = mergeOrCreateOptions(optionsArg, sourceAttrs)
199
+
200
+ if (node.arguments.length >= 3) {
201
+ // Replace existing options
202
+ node.arguments[2] = newOptions
203
+ } else {
204
+ // Add options as third argument
205
+ node.arguments.push(newOptions)
206
+ }
207
+ } else {
208
+ // Data-last: withSpan("name", options?)
209
+ // Options is at index 1
210
+ const optionsArg = node.arguments[1]
211
+ const newOptions = mergeOrCreateOptions(optionsArg, sourceAttrs)
212
+
213
+ if (node.arguments.length >= 2) {
214
+ // Replace existing options
215
+ node.arguments[1] = newOptions
216
+ } else {
217
+ // Add options as second argument
218
+ node.arguments.push(newOptions)
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ /**
226
+ * Creates the withSpan trace transformer plugin.
227
+ */
228
+ export function withSpanTraceTransformer(options?: WithSpanTraceOptions): {
229
+ visitor: Visitor<TransformState>
230
+ name: string
231
+ } {
232
+ return {
233
+ name: "effect-withspan-trace",
234
+ visitor: createWithSpanTraceVisitor("", options)
235
+ }
236
+ }