@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 +6 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/transformers/withSpanTrace.js +144 -0
- package/dist/cjs/transformers/withSpanTrace.js.map +1 -0
- package/dist/dts/index.d.ts +7 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/transformers/withSpanTrace.d.ts +39 -0
- package/dist/dts/transformers/withSpanTrace.d.ts.map +1 -0
- package/dist/esm/index.js +5 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/transformers/withSpanTrace.js +160 -0
- package/dist/esm/transformers/withSpanTrace.js.map +1 -0
- package/package.json +2 -2
- package/src/index.ts +15 -1
- package/src/transformers/withSpanTrace.ts +236 -0
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;
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -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":";;;;;;AAwBA,IAAAA,UAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AAEA,IAAAE,UAAA,GAAAH,sBAAA,CAAAC,OAAA;AAEA,IAAAG,SAAA,GAAAH,OAAA;AACA,IAAAI,YAAA,GAAAJ,OAAA;
|
|
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":[]}
|
package/dist/dts/index.d.ts
CHANGED
|
@@ -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
|
*
|
package/dist/dts/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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;
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAwBA,OAAO,SAAS,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAErC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AAEvC,OAAO,EAAE,cAAc,EAA+C,MAAM,UAAU,CAAA;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAwBA,OAAO,SAAS,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAErC,OAAO,SAAS,MAAM,iBAAiB,CAAA;AAEvC,OAAO,EAAE,cAAc,EAA+C,MAAM,UAAU,CAAA;AACtF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAiB5E,4DAA4D;AAC5D,MAAM,QAAQ,GAAe,OAAO,SAAS,KAAK,UAAU;IAC1D,CAAC,CAAC,SAAuB;IACzB,CAAC,CAAE,SAAgD,CAAC,OAAO,CAAA;AAE7D,MAAM,QAAQ,GAAe,OAAO,SAAS,KAAK,UAAU;IAC1D,CAAC,CAAC,SAAuB;IACzB,CAAC,CAAE,SAAgD,CAAC,OAAO,CAAA;AAsD7D;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,YAAY,CAAC,CAAA;AAEtC;;GAEG;AACH,MAAM,eAAe,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,CAAA;AAEpD;;GAEG;AACH,SAAS,eAAe,CACtB,EAAU,EACV,OAAuC,EACvC,OAAuC;IAEvC,uBAAuB;IACvB,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,OAAO,KAAK,CAAA;QACxC,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,iBAAiB;IACjB,KAAK,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;QAC9B,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,OAAO,IAAI,CAAA;QACvC,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;GAEG;AACH,MAAM,eAAe,GAAqD,CAAC,OAAO,GAAG,EAAE,EAAE,EAAE;IACzF,MAAM,EACJ,eAAe,EAAE,gBAAgB,GAAG,KAAK,EACzC,OAAO,GAAG,eAAe,EACzB,OAAO,GAAG,eAAe,EACzB,WAAW,GAAG,IAAI,EAClB,SAAS,GAAG,IAAI,EACjB,GAAG,OAAO,CAAA;IAEX,OAAO;QACL,IAAI,EAAE,kBAAkB;QAExB,gBAAgB,CAAC,EAAE;YACjB,OAAO,eAAe,CAAC,EAAE,EAAE,OAAiC,EAAE,OAAiC,CAAC,CAAA;QAClG,CAAC;QAED,SAAS,CAAC,IAAI,EAAE,EAAE;YAChB,wBAAwB;YACxB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE;gBACtB,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,CAAC,YAAY,EAAE,KAAK,CAAC;aAC/B,CAAC,CAAA;YAEF,mBAAmB;YACnB,MAAM,QAAQ,GAAmC,EAAE,CAAA;YAEnD,IAAI,WAAW,EAAE,CAAC;gBAChB,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAA;YAC7C,CAAC;YAED,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC,CAAA;YAC/C,CAAC;YAED,mBAAmB;YACnB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,OAAO,IAAI,CAAA;YACb,CAAC;YAED,oCAAoC;YACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;gBACjC,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE;oBACR,aAAa,EAAE,IAAI,GAAG,EAAE;oBACxB,OAAO,EAAE,CAAC;oBACV,UAAU,EAAE,EAAE;iBACf;aACF,CAAC,CAAC,CAAA;YAEH,mBAAmB;YACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACzC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;YAClD,CAAC;YAED,kBAAkB;YAClB,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE;gBAC3B,UAAU,EAAE,IAAI;gBAChB,cAAc,EAAE,EAAE;aACnB,EAAE,IAAI,CAAC,CAAA;YAER,OAAO;gBACL,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,GAAG,EAAE,MAAM,CAAC,GAAG;aAChB,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAA+D,cAAc,CAAC,eAAe,CAAC,CAAA;AAEnH;;;;GAIG;AACH,eAAe,QAAQ,CAAA"}
|
|
@@ -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.
|
|
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.
|
|
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
|
+
}
|