@clayroach/unplugin 0.1.0-source-trace.2

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.
Files changed (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/cjs/esbuild.js +34 -0
  4. package/dist/cjs/esbuild.js.map +1 -0
  5. package/dist/cjs/index.js +113 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/cjs/rollup.js +33 -0
  8. package/dist/cjs/rollup.js.map +1 -0
  9. package/dist/cjs/rspack.js +33 -0
  10. package/dist/cjs/rspack.js.map +1 -0
  11. package/dist/cjs/transformers/index.js +17 -0
  12. package/dist/cjs/transformers/index.js.map +1 -0
  13. package/dist/cjs/transformers/sourceTrace.js +57 -0
  14. package/dist/cjs/transformers/sourceTrace.js.map +1 -0
  15. package/dist/cjs/utils/effectDetection.js +58 -0
  16. package/dist/cjs/utils/effectDetection.js.map +1 -0
  17. package/dist/cjs/utils/hoisting.js +71 -0
  18. package/dist/cjs/utils/hoisting.js.map +1 -0
  19. package/dist/cjs/vite.js +33 -0
  20. package/dist/cjs/vite.js.map +1 -0
  21. package/dist/cjs/webpack.js +33 -0
  22. package/dist/cjs/webpack.js.map +1 -0
  23. package/dist/dts/esbuild.d.ts +30 -0
  24. package/dist/dts/esbuild.d.ts.map +1 -0
  25. package/dist/dts/index.d.ts +46 -0
  26. package/dist/dts/index.d.ts.map +1 -0
  27. package/dist/dts/rollup.d.ts +29 -0
  28. package/dist/dts/rollup.d.ts.map +1 -0
  29. package/dist/dts/rspack.d.ts +29 -0
  30. package/dist/dts/rspack.d.ts.map +1 -0
  31. package/dist/dts/transformers/index.d.ts +7 -0
  32. package/dist/dts/transformers/index.d.ts.map +1 -0
  33. package/dist/dts/transformers/sourceTrace.d.ts +41 -0
  34. package/dist/dts/transformers/sourceTrace.d.ts.map +1 -0
  35. package/dist/dts/utils/effectDetection.d.ts +35 -0
  36. package/dist/dts/utils/effectDetection.d.ts.map +1 -0
  37. package/dist/dts/utils/hoisting.d.ts +41 -0
  38. package/dist/dts/utils/hoisting.d.ts.map +1 -0
  39. package/dist/dts/vite.d.ts +29 -0
  40. package/dist/dts/vite.d.ts.map +1 -0
  41. package/dist/dts/webpack.d.ts +29 -0
  42. package/dist/dts/webpack.d.ts.map +1 -0
  43. package/dist/esm/esbuild.js +28 -0
  44. package/dist/esm/esbuild.js.map +1 -0
  45. package/dist/esm/index.js +109 -0
  46. package/dist/esm/index.js.map +1 -0
  47. package/dist/esm/package.json +4 -0
  48. package/dist/esm/rollup.js +27 -0
  49. package/dist/esm/rollup.js.map +1 -0
  50. package/dist/esm/rspack.js +27 -0
  51. package/dist/esm/rspack.js.map +1 -0
  52. package/dist/esm/transformers/index.js +7 -0
  53. package/dist/esm/transformers/index.js.map +1 -0
  54. package/dist/esm/transformers/sourceTrace.js +50 -0
  55. package/dist/esm/transformers/sourceTrace.js.map +1 -0
  56. package/dist/esm/utils/effectDetection.js +59 -0
  57. package/dist/esm/utils/effectDetection.js.map +1 -0
  58. package/dist/esm/utils/hoisting.js +70 -0
  59. package/dist/esm/utils/hoisting.js.map +1 -0
  60. package/dist/esm/vite.js +27 -0
  61. package/dist/esm/vite.js.map +1 -0
  62. package/dist/esm/webpack.js +27 -0
  63. package/dist/esm/webpack.js.map +1 -0
  64. package/esbuild/package.json +6 -0
  65. package/package.json +81 -0
  66. package/rollup/package.json +6 -0
  67. package/rspack/package.json +6 -0
  68. package/src/esbuild.ts +30 -0
  69. package/src/index.ts +218 -0
  70. package/src/rollup.ts +29 -0
  71. package/src/rspack.ts +29 -0
  72. package/src/transformers/index.ts +6 -0
  73. package/src/transformers/sourceTrace.ts +102 -0
  74. package/src/utils/effectDetection.ts +81 -0
  75. package/src/utils/hoisting.ts +132 -0
  76. package/src/vite.ts +29 -0
  77. package/src/webpack.ts +29 -0
  78. package/vite/package.json +6 -0
  79. package/webpack/package.json +6 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Checks if a CallExpression is `Effect.gen(...)`.
3
+ */
4
+ export function isEffectGenCall(node) {
5
+ if (node.type !== "CallExpression")
6
+ return false;
7
+ const callee = node.callee;
8
+ // Match Effect.gen(...)
9
+ if (callee.type === "MemberExpression" &&
10
+ callee.object.type === "Identifier" &&
11
+ callee.object.name === "Effect" &&
12
+ callee.property.type === "Identifier" &&
13
+ callee.property.name === "gen") {
14
+ return true;
15
+ }
16
+ // Match _.gen(...) where _ is an alias for Effect
17
+ if (callee.type === "MemberExpression" &&
18
+ callee.property.type === "Identifier" &&
19
+ callee.property.name === "gen") {
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ /**
25
+ * Checks if a node is inside an Effect.gen generator function.
26
+ * This walks up the AST to find if there's an enclosing generator function
27
+ * that is an argument to Effect.gen.
28
+ */
29
+ export function isInsideEffectGen(path) {
30
+ let current = path.parentPath;
31
+ while (current) {
32
+ const node = current.parent;
33
+ if (node && isEffectGenCall(node)) {
34
+ return true;
35
+ }
36
+ current = current.parentPath;
37
+ }
38
+ return false;
39
+ }
40
+ /**
41
+ * Checks if a CallExpression is a call to the adapter function `_()`.
42
+ * The adapter is the first argument passed to the generator function.
43
+ */
44
+ export function isAdapterCall(node) {
45
+ return node.callee.type === "Identifier" && node.callee.name === "_";
46
+ }
47
+ /**
48
+ * Checks if a YieldExpression is a `yield* _(effect)` pattern.
49
+ */
50
+ export function isYieldAdapterCall(node) {
51
+ if (!node.delegate)
52
+ return false; // Must be yield*, not yield
53
+ if (!node.argument)
54
+ return false;
55
+ if (node.argument.type !== "CallExpression")
56
+ return false;
57
+ return isAdapterCall(node.argument);
58
+ }
59
+ //# sourceMappingURL=effectDetection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effectDetection.js","sourceRoot":"","sources":["../../../src/utils/effectDetection.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB;QAAE,OAAO,KAAK,CAAA;IAEhD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAE1B,wBAAwB;IACxB,IACE,MAAM,CAAC,IAAI,KAAK,kBAAkB;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ;QAC/B,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;QACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAC9B,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,kDAAkD;IAClD,IACE,MAAM,CAAC,IAAI,KAAK,kBAAkB;QAClC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;QACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,KAAK,EAC9B,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,IAAc;IAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,UAAU,CAAA;IAC7B,OAAO,OAAO,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,OAAO,CAAC,MAA4B,CAAA;QACjD,IAAI,IAAI,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,UAAU,CAAA;IAC9B,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAsB;IAClD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,GAAG,CAAA;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAuB;IACxD,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA,CAAC,4BAA4B;IAC7D,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAA;IAChC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,KAAK,gBAAgB;QAAE,OAAO,KAAK,CAAA;IACzD,OAAO,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AACrC,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Utilities for hoisting trace metadata to module scope.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ import * as t from "@babel/types";
7
+ /**
8
+ * Creates a new hoisting state.
9
+ */
10
+ export function createHoistingState() {
11
+ return {
12
+ hoistedTraces: new Map(),
13
+ counter: 0,
14
+ statements: []
15
+ };
16
+ }
17
+ /**
18
+ * Creates a unique deduplication key for a source location.
19
+ * Uses line:column to disambiguate multiple yields on the same line.
20
+ */
21
+ export function createDedupKey(filename, line, column) {
22
+ return `${filename}:${line}:${column}`;
23
+ }
24
+ /**
25
+ * Gets or creates a hoisted trace identifier for the given source location.
26
+ */
27
+ export function getOrCreateTraceIdentifier(state, filename, line, column, label) {
28
+ const key = createDedupKey(filename, line, column);
29
+ let identifier = state.hoistedTraces.get(key);
30
+ if (identifier) {
31
+ return identifier;
32
+ }
33
+ // Create new identifier
34
+ identifier = t.identifier(`_trace${state.counter++}`);
35
+ state.hoistedTraces.set(key, identifier);
36
+ // Create the SourceLocation object literal
37
+ const properties = [
38
+ t.objectProperty(t.identifier("_tag"), t.stringLiteral("SourceLocation")),
39
+ t.objectProperty(t.identifier("path"), t.stringLiteral(filename)),
40
+ t.objectProperty(t.identifier("line"), t.numericLiteral(line)),
41
+ t.objectProperty(t.identifier("column"), t.numericLiteral(column))
42
+ ];
43
+ if (label) {
44
+ properties.push(t.objectProperty(t.identifier("label"), t.stringLiteral(label)));
45
+ }
46
+ // Wrap in Symbol.for call to add the type tag
47
+ const traceObject = t.objectExpression([
48
+ t.objectProperty(t.callExpression(t.memberExpression(t.identifier("Symbol"), t.identifier("for")), [t.stringLiteral("effect/SourceLocation")]), t.callExpression(t.memberExpression(t.identifier("Symbol"), t.identifier("for")), [t.stringLiteral("effect/SourceLocation")]), true // computed property
49
+ ),
50
+ ...properties
51
+ ]);
52
+ // Create variable declaration
53
+ const declaration = t.variableDeclaration("const", [
54
+ t.variableDeclarator(identifier, traceObject)
55
+ ]);
56
+ state.statements.push(declaration);
57
+ return identifier;
58
+ }
59
+ /**
60
+ * Extracts a label from a VariableDeclarator if the yield is part of an assignment.
61
+ * For example: `const user = yield* _(fetchUser(id))` extracts "user"
62
+ */
63
+ export function extractLabelFromParent(path) {
64
+ const parent = path.parent;
65
+ if (parent?.type === "VariableDeclarator" && parent.id.type === "Identifier") {
66
+ return parent.id.name;
67
+ }
68
+ return undefined;
69
+ }
70
+ //# sourceMappingURL=hoisting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hoisting.js","sourceRoot":"","sources":["../../../src/utils/hoisting.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Vite plugin export for @effect/unplugin.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // vite.config.ts
7
+ * import effectPlugin from "@effect/unplugin/vite"
8
+ *
9
+ * export default {
10
+ * plugins: [
11
+ * effectPlugin({
12
+ * sourceTrace: true
13
+ * })
14
+ * ]
15
+ * }
16
+ * ```
17
+ *
18
+ * @since 0.1.0
19
+ */
20
+ import { unplugin } from "./index.js";
21
+ /**
22
+ * Vite plugin for Effect transformations.
23
+ *
24
+ * @since 0.1.0
25
+ */
26
+ export default unplugin.vite;
27
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../src/vite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAA4B,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE/D;;;;GAIG;AACH,eAAe,QAAQ,CAAC,IAAI,CAAA"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Webpack plugin export for @effect/unplugin.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // webpack.config.js
7
+ * const effectPlugin = require("@effect/unplugin/webpack").default
8
+ *
9
+ * module.exports = {
10
+ * plugins: [
11
+ * effectPlugin({
12
+ * sourceTrace: true
13
+ * })
14
+ * ]
15
+ * }
16
+ * ```
17
+ *
18
+ * @since 0.1.0
19
+ */
20
+ import { unplugin } from "./index.js";
21
+ /**
22
+ * Webpack plugin for Effect transformations.
23
+ *
24
+ * @since 0.1.0
25
+ */
26
+ export default unplugin.webpack;
27
+ //# sourceMappingURL=webpack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webpack.js","sourceRoot":"","sources":["../../src/webpack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAA4B,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE/D;;;;GAIG;AACH,eAAe,QAAQ,CAAC,OAAO,CAAA"}
@@ -0,0 +1,6 @@
1
+ {
2
+ "sideEffects": [],
3
+ "main": "../dist/cjs/esbuild.js",
4
+ "module": "../dist/esm/esbuild.js",
5
+ "types": "../dist/dts/esbuild.d.ts"
6
+ }
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@clayroach/unplugin",
3
+ "version": "0.1.0-source-trace.2",
4
+ "description": "Universal bundler plugin for Effect transformations",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/Effect-TS/effect.git",
9
+ "directory": "packages/unplugin"
10
+ },
11
+ "sideEffects": [],
12
+ "homepage": "https://effect.website",
13
+ "dependencies": {
14
+ "unplugin": "^2.3.2",
15
+ "@babel/types": "^7.26.0",
16
+ "@babel/parser": "^7.26.0",
17
+ "@babel/traverse": "^7.26.0",
18
+ "@babel/generator": "^7.26.0"
19
+ },
20
+ "peerDependencies": {
21
+ "@clayroach/effect": "^3.19.14-source-trace.2"
22
+ },
23
+ "publishConfig": {
24
+ "provenance": true
25
+ },
26
+ "main": "./dist/cjs/index.js",
27
+ "module": "./dist/esm/index.js",
28
+ "types": "./dist/dts/index.d.ts",
29
+ "exports": {
30
+ "./package.json": "./package.json",
31
+ ".": {
32
+ "types": "./dist/dts/index.d.ts",
33
+ "import": "./dist/esm/index.js",
34
+ "default": "./dist/cjs/index.js"
35
+ },
36
+ "./vite": {
37
+ "types": "./dist/dts/vite.d.ts",
38
+ "import": "./dist/esm/vite.js",
39
+ "default": "./dist/cjs/vite.js"
40
+ },
41
+ "./rollup": {
42
+ "types": "./dist/dts/rollup.d.ts",
43
+ "import": "./dist/esm/rollup.js",
44
+ "default": "./dist/cjs/rollup.js"
45
+ },
46
+ "./webpack": {
47
+ "types": "./dist/dts/webpack.d.ts",
48
+ "import": "./dist/esm/webpack.js",
49
+ "default": "./dist/cjs/webpack.js"
50
+ },
51
+ "./esbuild": {
52
+ "types": "./dist/dts/esbuild.d.ts",
53
+ "import": "./dist/esm/esbuild.js",
54
+ "default": "./dist/cjs/esbuild.js"
55
+ },
56
+ "./rspack": {
57
+ "types": "./dist/dts/rspack.d.ts",
58
+ "import": "./dist/esm/rspack.js",
59
+ "default": "./dist/cjs/rspack.js"
60
+ }
61
+ },
62
+ "typesVersions": {
63
+ "*": {
64
+ "vite": [
65
+ "./dist/dts/vite.d.ts"
66
+ ],
67
+ "rollup": [
68
+ "./dist/dts/rollup.d.ts"
69
+ ],
70
+ "webpack": [
71
+ "./dist/dts/webpack.d.ts"
72
+ ],
73
+ "esbuild": [
74
+ "./dist/dts/esbuild.d.ts"
75
+ ],
76
+ "rspack": [
77
+ "./dist/dts/rspack.d.ts"
78
+ ]
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "sideEffects": [],
3
+ "main": "../dist/cjs/rollup.js",
4
+ "module": "../dist/esm/rollup.js",
5
+ "types": "../dist/dts/rollup.d.ts"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "sideEffects": [],
3
+ "main": "../dist/cjs/rspack.js",
4
+ "module": "../dist/esm/rspack.js",
5
+ "types": "../dist/dts/rspack.d.ts"
6
+ }
package/src/esbuild.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * esbuild plugin export for @effect/unplugin.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // build.js
7
+ * import * as esbuild from "esbuild"
8
+ * import effectPlugin from "@effect/unplugin/esbuild"
9
+ *
10
+ * await esbuild.build({
11
+ * plugins: [
12
+ * effectPlugin({
13
+ * sourceTrace: true
14
+ * })
15
+ * ]
16
+ * })
17
+ * ```
18
+ *
19
+ * @since 0.1.0
20
+ */
21
+ import { type EffectPluginOptions, unplugin } from "./index.js"
22
+
23
+ /**
24
+ * esbuild plugin for Effect transformations.
25
+ *
26
+ * @since 0.1.0
27
+ */
28
+ export default unplugin.esbuild
29
+
30
+ export type { EffectPluginOptions }
package/src/index.ts ADDED
@@ -0,0 +1,218 @@
1
+ /**
2
+ * @effect/unplugin - Universal bundler plugin for Effect transformations.
3
+ *
4
+ * This plugin provides build-time transformations for Effect code:
5
+ * - Source trace injection for automatic log prefixing and debugging
6
+ * - Pure call annotations for tree-shaking optimization
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * // vite.config.ts
11
+ * import effectPlugin from "@effect/unplugin/vite"
12
+ *
13
+ * export default {
14
+ * plugins: [
15
+ * effectPlugin({
16
+ * sourceTrace: true
17
+ * })
18
+ * ]
19
+ * }
20
+ * ```
21
+ *
22
+ * @since 0.1.0
23
+ */
24
+ import type { GeneratorResult } from "@babel/generator"
25
+ import _generate from "@babel/generator"
26
+ import { parse } from "@babel/parser"
27
+ import type { Scope, TraverseOptions, Visitor } from "@babel/traverse"
28
+ import _traverse from "@babel/traverse"
29
+ import type { Node } from "@babel/types"
30
+ import { createUnplugin, type UnpluginFactory, type UnpluginInstance } from "unplugin"
31
+ import { createSourceTraceVisitor } from "./transformers/sourceTrace.js"
32
+ import type { HoistingState } from "./utils/hoisting.js"
33
+
34
+ // Define function types for Babel packages (they export differently in ESM vs CJS)
35
+ type TraverseFn = <S>(
36
+ parent: Node,
37
+ opts: TraverseOptions<S>,
38
+ scope: Scope | undefined,
39
+ state: S
40
+ ) => void
41
+
42
+ type GenerateFn = (
43
+ ast: Node,
44
+ opts?: { sourceMaps?: boolean; sourceFileName?: string },
45
+ code?: string
46
+ ) => GeneratorResult
47
+
48
+ // Handle both ESM and CJS module exports for Babel packages
49
+ const traverse: TraverseFn = typeof _traverse === "function"
50
+ ? _traverse as TraverseFn
51
+ : (_traverse as unknown as { default: TraverseFn }).default
52
+
53
+ const generate: GenerateFn = typeof _generate === "function"
54
+ ? _generate as GenerateFn
55
+ : (_generate as unknown as { default: GenerateFn }).default
56
+
57
+ /**
58
+ * Internal state used by transformers during AST traversal.
59
+ */
60
+ interface TransformState {
61
+ filename: string
62
+ hoisting: HoistingState
63
+ }
64
+
65
+ /**
66
+ * Configuration options for the Effect plugin.
67
+ *
68
+ * @since 0.1.0
69
+ */
70
+ export interface EffectPluginOptions {
71
+ /**
72
+ * Enable source trace injection into Effect.gen yields.
73
+ * When enabled, logs will automatically include source locations.
74
+ *
75
+ * @default true
76
+ */
77
+ readonly sourceTrace?: boolean
78
+
79
+ /**
80
+ * Enable @__PURE__ annotations for tree-shaking.
81
+ *
82
+ * @default false
83
+ */
84
+ readonly annotateEffects?: boolean
85
+
86
+ /**
87
+ * Glob patterns to include in transformation.
88
+ *
89
+ * @default ["**\/*.ts", "**\/*.tsx"]
90
+ */
91
+ readonly include?: ReadonlyArray<string>
92
+
93
+ /**
94
+ * Glob patterns to exclude from transformation.
95
+ *
96
+ * @default ["**\/node_modules/**", "**\/*.d.ts"]
97
+ */
98
+ readonly exclude?: ReadonlyArray<string>
99
+ }
100
+
101
+ /**
102
+ * Default file patterns to include.
103
+ */
104
+ const DEFAULT_INCLUDE = [/\.[jt]sx?$/]
105
+
106
+ /**
107
+ * Default file patterns to exclude.
108
+ */
109
+ const DEFAULT_EXCLUDE = [/node_modules/, /\.d\.ts$/]
110
+
111
+ /**
112
+ * Checks if a file should be transformed based on include/exclude patterns.
113
+ */
114
+ function shouldTransform(
115
+ id: string,
116
+ include: ReadonlyArray<string | RegExp>,
117
+ exclude: ReadonlyArray<string | RegExp>
118
+ ): boolean {
119
+ // Check excludes first
120
+ for (const pattern of exclude) {
121
+ if (typeof pattern === "string") {
122
+ if (id.includes(pattern)) return false
123
+ } else if (pattern.test(id)) {
124
+ return false
125
+ }
126
+ }
127
+
128
+ // Check includes
129
+ for (const pattern of include) {
130
+ if (typeof pattern === "string") {
131
+ if (id.includes(pattern)) return true
132
+ } else if (pattern.test(id)) {
133
+ return true
134
+ }
135
+ }
136
+
137
+ return false
138
+ }
139
+
140
+ /**
141
+ * Creates the unplugin factory.
142
+ */
143
+ const unpluginFactory: UnpluginFactory<EffectPluginOptions | undefined> = (options = {}) => {
144
+ const {
145
+ annotateEffects: _annotateEffects = false,
146
+ exclude = DEFAULT_EXCLUDE,
147
+ include = DEFAULT_INCLUDE,
148
+ sourceTrace = true
149
+ } = options
150
+
151
+ return {
152
+ name: "@effect/unplugin",
153
+
154
+ transformInclude(id) {
155
+ return shouldTransform(id, include as Array<string | RegExp>, exclude as Array<string | RegExp>)
156
+ },
157
+
158
+ transform(code, id) {
159
+ // Parse the source code
160
+ const ast = parse(code, {
161
+ sourceType: "module",
162
+ plugins: ["typescript", "jsx"]
163
+ })
164
+
165
+ // Collect visitors
166
+ const visitors: Array<Visitor<TransformState>> = []
167
+
168
+ if (sourceTrace) {
169
+ visitors.push(createSourceTraceVisitor(id))
170
+ }
171
+
172
+ // Combine visitors
173
+ if (visitors.length === 0) {
174
+ return null
175
+ }
176
+
177
+ // Initialize state for each visitor
178
+ const states = visitors.map(() => ({
179
+ filename: id,
180
+ hoisting: {
181
+ hoistedTraces: new Map(),
182
+ counter: 0,
183
+ statements: []
184
+ }
185
+ }))
186
+
187
+ // Run each visitor
188
+ for (let i = 0; i < visitors.length; i++) {
189
+ traverse(ast, visitors[i], undefined, states[i])
190
+ }
191
+
192
+ // Generate output
193
+ const output = generate(ast, {
194
+ sourceMaps: true,
195
+ sourceFileName: id
196
+ }, code)
197
+
198
+ return {
199
+ code: output.code,
200
+ map: output.map
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ /**
207
+ * The unplugin instance.
208
+ *
209
+ * @since 0.1.0
210
+ */
211
+ export const unplugin: UnpluginInstance<EffectPluginOptions | undefined, boolean> = createUnplugin(unpluginFactory)
212
+
213
+ /**
214
+ * Default export for convenience.
215
+ *
216
+ * @since 0.1.0
217
+ */
218
+ export default unplugin
package/src/rollup.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Rollup plugin export for @effect/unplugin.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // rollup.config.js
7
+ * import effectPlugin from "@effect/unplugin/rollup"
8
+ *
9
+ * export default {
10
+ * plugins: [
11
+ * effectPlugin({
12
+ * sourceTrace: true
13
+ * })
14
+ * ]
15
+ * }
16
+ * ```
17
+ *
18
+ * @since 0.1.0
19
+ */
20
+ import { type EffectPluginOptions, unplugin } from "./index.js"
21
+
22
+ /**
23
+ * Rollup plugin for Effect transformations.
24
+ *
25
+ * @since 0.1.0
26
+ */
27
+ export default unplugin.rollup
28
+
29
+ export type { EffectPluginOptions }
package/src/rspack.ts ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Rspack plugin export for @effect/unplugin.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // rspack.config.js
7
+ * const effectPlugin = require("@effect/unplugin/rspack").default
8
+ *
9
+ * module.exports = {
10
+ * plugins: [
11
+ * effectPlugin({
12
+ * sourceTrace: true
13
+ * })
14
+ * ]
15
+ * }
16
+ * ```
17
+ *
18
+ * @since 0.1.0
19
+ */
20
+ import { type EffectPluginOptions, unplugin } from "./index.js"
21
+
22
+ /**
23
+ * Rspack plugin for Effect transformations.
24
+ *
25
+ * @since 0.1.0
26
+ */
27
+ export default unplugin.rspack
28
+
29
+ export type { EffectPluginOptions }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Transformer registry for @effect/unplugin.
3
+ *
4
+ * @since 0.1.0
5
+ */
6
+ export * from "./sourceTrace.js"