@reactra/babel-plugin 0.1.0-alpha.0

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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/dist/ast/index.d.ts +2 -0
  4. package/dist/ast/index.d.ts.map +1 -0
  5. package/dist/ast/index.js +3 -0
  6. package/dist/ast/index.js.map +1 -0
  7. package/dist/ast/nodes.d.ts +437 -0
  8. package/dist/ast/nodes.d.ts.map +1 -0
  9. package/dist/ast/nodes.js +35 -0
  10. package/dist/ast/nodes.js.map +1 -0
  11. package/dist/behaviours/index.d.ts +18 -0
  12. package/dist/behaviours/index.d.ts.map +1 -0
  13. package/dist/behaviours/index.js +36 -0
  14. package/dist/behaviours/index.js.map +1 -0
  15. package/dist/behaviours/plugin.d.ts +22 -0
  16. package/dist/behaviours/plugin.d.ts.map +1 -0
  17. package/dist/behaviours/plugin.js +70 -0
  18. package/dist/behaviours/plugin.js.map +1 -0
  19. package/dist/behaviours/replayable.d.ts +10 -0
  20. package/dist/behaviours/replayable.d.ts.map +1 -0
  21. package/dist/behaviours/replayable.js +86 -0
  22. package/dist/behaviours/replayable.js.map +1 -0
  23. package/dist/behaviours/types.d.ts +77 -0
  24. package/dist/behaviours/types.d.ts.map +1 -0
  25. package/dist/behaviours/types.js +10 -0
  26. package/dist/behaviours/types.js.map +1 -0
  27. package/dist/behaviours/undoable.d.ts +10 -0
  28. package/dist/behaviours/undoable.d.ts.map +1 -0
  29. package/dist/behaviours/undoable.js +62 -0
  30. package/dist/behaviours/undoable.js.map +1 -0
  31. package/dist/compile.d.ts +69 -0
  32. package/dist/compile.d.ts.map +1 -0
  33. package/dist/compile.js +75 -0
  34. package/dist/compile.js.map +1 -0
  35. package/dist/conventions/index.d.ts +110 -0
  36. package/dist/conventions/index.d.ts.map +1 -0
  37. package/dist/conventions/index.js +193 -0
  38. package/dist/conventions/index.js.map +1 -0
  39. package/dist/index.d.ts +48 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +77 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/passes/index.d.ts +5 -0
  44. package/dist/passes/index.d.ts.map +1 -0
  45. package/dist/passes/index.js +6 -0
  46. package/dist/passes/index.js.map +1 -0
  47. package/dist/passes/pass-1-parse.d.ts +3 -0
  48. package/dist/passes/pass-1-parse.d.ts.map +1 -0
  49. package/dist/passes/pass-1-parse.js +21 -0
  50. package/dist/passes/pass-1-parse.js.map +1 -0
  51. package/dist/passes/pass-2-extract.d.ts +4 -0
  52. package/dist/passes/pass-2-extract.d.ts.map +1 -0
  53. package/dist/passes/pass-2-extract.js +762 -0
  54. package/dist/passes/pass-2-extract.js.map +1 -0
  55. package/dist/passes/pass-3-readset.d.ts +11 -0
  56. package/dist/passes/pass-3-readset.d.ts.map +1 -0
  57. package/dist/passes/pass-3-readset.js +338 -0
  58. package/dist/passes/pass-3-readset.js.map +1 -0
  59. package/dist/passes/pass-9-codegen.d.ts +27 -0
  60. package/dist/passes/pass-9-codegen.d.ts.map +1 -0
  61. package/dist/passes/pass-9-codegen.js +2755 -0
  62. package/dist/passes/pass-9-codegen.js.map +1 -0
  63. package/dist/preprocess/helpers.d.ts +71 -0
  64. package/dist/preprocess/helpers.d.ts.map +1 -0
  65. package/dist/preprocess/helpers.js +342 -0
  66. package/dist/preprocess/helpers.js.map +1 -0
  67. package/dist/preprocess/index.d.ts +6 -0
  68. package/dist/preprocess/index.d.ts.map +1 -0
  69. package/dist/preprocess/index.js +11 -0
  70. package/dist/preprocess/index.js.map +1 -0
  71. package/dist/preprocess/keywords.d.ts +28 -0
  72. package/dist/preprocess/keywords.d.ts.map +1 -0
  73. package/dist/preprocess/keywords.js +99 -0
  74. package/dist/preprocess/keywords.js.map +1 -0
  75. package/dist/preprocess/lexer.d.ts +8 -0
  76. package/dist/preprocess/lexer.d.ts.map +1 -0
  77. package/dist/preprocess/lexer.js +143 -0
  78. package/dist/preprocess/lexer.js.map +1 -0
  79. package/dist/preprocess/preprocess.d.ts +3 -0
  80. package/dist/preprocess/preprocess.d.ts.map +1 -0
  81. package/dist/preprocess/preprocess.js +568 -0
  82. package/dist/preprocess/preprocess.js.map +1 -0
  83. package/dist/preprocess/rewriters.d.ts +35 -0
  84. package/dist/preprocess/rewriters.d.ts.map +1 -0
  85. package/dist/preprocess/rewriters.js +1391 -0
  86. package/dist/preprocess/rewriters.js.map +1 -0
  87. package/dist/preprocess/source-map.d.ts +70 -0
  88. package/dist/preprocess/source-map.d.ts.map +1 -0
  89. package/dist/preprocess/source-map.js +253 -0
  90. package/dist/preprocess/source-map.js.map +1 -0
  91. package/dist/preprocess/types.d.ts +57 -0
  92. package/dist/preprocess/types.d.ts.map +1 -0
  93. package/dist/preprocess/types.js +7 -0
  94. package/dist/preprocess/types.js.map +1 -0
  95. package/dist/sidecar.d.ts +137 -0
  96. package/dist/sidecar.d.ts.map +1 -0
  97. package/dist/sidecar.js +172 -0
  98. package/dist/sidecar.js.map +1 -0
  99. package/package.json +42 -0
@@ -0,0 +1,193 @@
1
+ // @reactra/babel-plugin — shared emission conventions.
2
+ //
3
+ // Owner: reactra-compiler-spec.md §4 (Pass 9 emission contract).
4
+ //
5
+ // THE single home for the naming + ordering + marker-vocabulary conventions
6
+ // that BOTH emitters depend on: Pass 9 codegen (`passes/pass-9-codegen.ts`)
7
+ // and the language-tools shadow emitter (`@reactra/language-tools`
8
+ // `shadow/emitter.ts`). Before framework-review §B1 these were re-derived
9
+ // independently in each emitter and had already drifted (the shadow's setter
10
+ // rename matched on a bare name across all containers; Pass 9 gates on
11
+ // triviality + state-membership). They agreed on the examples only by luck.
12
+ //
13
+ // Rules for this module (architect B1 conditions):
14
+ // - PURE. No module-level mutable state. `renamedStates` is computed by
15
+ // `classifyStateSetters` and passed into `setterNameFor` — the caller owns it.
16
+ // - babel-plugin owns emission conventions; language-tools imports FROM here
17
+ // (via `@reactra/babel-plugin/conventions`). This module imports only
18
+ // `@babel/types` + the same-package AST node types. It must NEVER import
19
+ // language-tools (no cycle).
20
+ // - The reconciled setter logic is the GATED (Pass 9) version. The shadow's
21
+ // looser `resolveSetterName` was deleted.
22
+ import * as t from "@babel/types";
23
+ import { CONTAINER_MARKERS } from "../ast/nodes.js";
24
+ // ---------------------------------------------------------------------------
25
+ // String helpers
26
+ // ---------------------------------------------------------------------------
27
+ /** Capitalise the first letter — used for setter names (`foo` → `Foo`). */
28
+ export const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
29
+ // ---------------------------------------------------------------------------
30
+ // `await` argument order
31
+ // ---------------------------------------------------------------------------
32
+ /**
33
+ * Positional order of the four arrows in a `__reactra_await__(resource,
34
+ * success, pending, error)` marker call. Both emitters index the call's
35
+ * `arguments` array via these constants so the resource/success/pending/error
36
+ * branches can never be wired up inconsistently across the two code paths.
37
+ *
38
+ * Pass 9: `pass-9-codegen.ts` await rewrite + the error-branch detector.
39
+ * Shadow: `shadow/emitter.ts` await lowering.
40
+ */
41
+ export const AWAIT_ARG_ORDER = {
42
+ resource: 0,
43
+ success: 1,
44
+ pending: 2,
45
+ error: 3,
46
+ };
47
+ // ---------------------------------------------------------------------------
48
+ // State-setter naming (the reconciled, GATED convention)
49
+ // ---------------------------------------------------------------------------
50
+ /**
51
+ * The identifier `state X` writes lower to (Component DSL §2.1/§2.3). Normally
52
+ * the auto-emitted public setter `set<Cap(X)>`; but when a non-trivial
53
+ * `action set<Cap(X)>` owns that public name, the `useState` setter is renamed
54
+ * `__set<Cap(X)>` so the action and the real setter don't collide (improvements
55
+ * #4). `renamedStates` holds the state names in the renamed case — compute it
56
+ * with {@link classifyStateSetters}.
57
+ */
58
+ export const setterNameFor = (stateName, renamedStates) => renamedStates.has(stateName) ? `__set${cap(stateName)}` : `set${cap(stateName)}`;
59
+ /**
60
+ * The state name an `action set<Cap(X)>` targets, or `null` if the action name
61
+ * isn't of that shape. `setFilter` → `filter` (Pascal → camel: lowercase the
62
+ * first char after `set`); `set`/`setup-with-no-tail` → `null`.
63
+ *
64
+ * Exported because the R016 warning (Pass 9) reports the targeted state name.
65
+ */
66
+ export const setterActionTarget = (actionName) => {
67
+ if (!actionName.startsWith("set"))
68
+ return null;
69
+ const rest = actionName.slice(3);
70
+ if (rest.length === 0)
71
+ return null;
72
+ return rest[0].toLowerCase() + rest.slice(1);
73
+ };
74
+ /**
75
+ * True when `action` is the exact identity passthrough for `stateName` —
76
+ * `action set<Cap(X)>(p) { X = p }` (single param, single statement assigning
77
+ * that param to that state, with or without a trailing `;`). This duplicates
78
+ * the auto-emitted setter (§2.1) and is redundant → R016 (improvements #4).
79
+ * Anything else (compound op, transformation, extra statements, multiple/zero
80
+ * params, async) is non-trivial and keeps the action.
81
+ */
82
+ const isTrivialIdentitySetter = (action, stateName) => {
83
+ if (action.isAsync)
84
+ return false;
85
+ const arrow = action.arrow;
86
+ if (arrow.params.length !== 1)
87
+ return false;
88
+ const param = arrow.params[0];
89
+ if (!t.isIdentifier(param))
90
+ return false;
91
+ if (!t.isBlockStatement(arrow.body))
92
+ return false;
93
+ const stmts = arrow.body.body.filter((s) => !t.isEmptyStatement(s));
94
+ if (stmts.length !== 1)
95
+ return false;
96
+ const stmt = stmts[0];
97
+ if (!t.isExpressionStatement(stmt))
98
+ return false;
99
+ const expr = stmt.expression;
100
+ if (!t.isAssignmentExpression(expr) || expr.operator !== "=")
101
+ return false;
102
+ return (t.isIdentifier(expr.left) &&
103
+ expr.left.name === stateName &&
104
+ t.isIdentifier(expr.right) &&
105
+ expr.right.name === param.name);
106
+ };
107
+ /**
108
+ * Classify `action set<Cap(X)>` declarations that name an existing `state X`
109
+ * (improvements #4, replacing the Day-21 hard R046 collision):
110
+ * - **trivial identity passthrough** → action **suppressed** (the auto-emitted
111
+ * `setX` already provides it); the caller emits R016 (warning);
112
+ * - **non-trivial** → the action **owns** the public `setX`; its state's
113
+ * `useState` setter is **renamed** `__setX` so they don't collide, and
114
+ * every `X = expr` write (here and elsewhere) lowers to `__setX`.
115
+ *
116
+ * Pure — returns the set of state names to rename and the set of action names
117
+ * to drop; the R016 warning is emitted by the caller (the single per-component
118
+ * emit point). Components only — store/service `state`/`action` emit through
119
+ * other paths, so a non-component container yields empty sets.
120
+ */
121
+ export const classifyStateSetters = (c) => {
122
+ const renamedStates = new Set();
123
+ const suppressedActions = new Set();
124
+ if (c.kind !== "component")
125
+ return { renamedStates, suppressedActions };
126
+ const stateNames = new Set(c.states.map((s) => s.name));
127
+ for (const action of c.actions) {
128
+ const stateName = setterActionTarget(action.name);
129
+ if (stateName === null || !stateNames.has(stateName))
130
+ continue;
131
+ if (isTrivialIdentitySetter(action, stateName))
132
+ suppressedActions.add(action.name);
133
+ else
134
+ renamedStates.add(stateName);
135
+ }
136
+ return { renamedStates, suppressedActions };
137
+ };
138
+ // ---------------------------------------------------------------------------
139
+ // Marker vocabulary (single source of truth)
140
+ // ---------------------------------------------------------------------------
141
+ /**
142
+ * Top-level container-wrapper markers, keyed to the `ContainerKind` they map to.
143
+ * Re-exported from `ast/nodes.ts` so there is exactly one home for the marker
144
+ * vocabulary (the conventions module). Pass 2 recognises these at the
145
+ * outer-decl level; the shadow emitter and parity test read them from here.
146
+ */
147
+ export { CONTAINER_MARKERS };
148
+ /**
149
+ * Body-level markers emitted by the preprocessor inside a container body and
150
+ * consumed by Pass 2's body-marker switch (`pass-2-extract.ts`). This is the
151
+ * authoritative list — the convention-parity test (language-tools) asserts that
152
+ * every key here is handled by BOTH emitters (or explicitly punted), so a NEW
153
+ * marker can't be added without a human wiring it on both sides (framework
154
+ * review §B1: stop the two emitters drifting silently).
155
+ *
156
+ * Values are the literal marker strings — kept byte-identical to the strings
157
+ * the preprocessor emits and Pass 2 switches on. The set is `as const` so the
158
+ * key type is the exact string-literal union.
159
+ *
160
+ * `__reactra_await__` is included: it is a body-level marker, but Pass 2
161
+ * handles it in a dedicated view-walk (not the flat body switch). The parity
162
+ * manifest classifies it as VIEW-HANDLED rather than switch-handled.
163
+ */
164
+ export const BODY_MARKERS = {
165
+ __reactra_state__: "state",
166
+ __reactra_derived__: "derived",
167
+ __reactra_action__: "action",
168
+ __reactra_action_async__: "action",
169
+ __reactra_resource__: "resource",
170
+ __reactra_ref__: "ref",
171
+ __reactra_mount__: "mount",
172
+ __reactra_cleanup__: "cleanup",
173
+ __reactra_effect__: "effect",
174
+ __reactra_effect_on__: "effect",
175
+ __reactra_view__: "view",
176
+ __reactra_uses__: "uses",
177
+ __reactra_inject__: "inject",
178
+ __reactra_provide__: "provide",
179
+ __reactra_param__: "param",
180
+ __reactra_query__: "query",
181
+ __reactra_meta__: "meta",
182
+ __reactra_prefetch__: "prefetch",
183
+ __reactra_transition__: "transition",
184
+ __reactra_inject_store__: "inject-store",
185
+ __reactra_inject_store_args__: "inject-store",
186
+ __reactra_inject_store_keyed__: "inject-store",
187
+ __reactra_error_boundary__: "errorBoundary",
188
+ __reactra_suspense__: "suspense",
189
+ __reactra_input__: "input",
190
+ __reactra_preserved__: "preserved",
191
+ __reactra_await__: "await",
192
+ };
193
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/conventions/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ export { preprocess, lex, skipTrivia, generatePreprocessSourceMap } from "./preprocess/index.ts";
2
+ export { ALL_RESERVED_KEYWORDS, KEYWORDS_BY_SCOPE, CONTAINER_KEYWORDS } from "./preprocess/index.ts";
3
+ export type { RawSourceMap } from "./preprocess/index.ts";
4
+ export type { Token, TokenKind, Rewrite, Span, PreprocessResult, } from "./preprocess/types.ts";
5
+ export { parsePreprocessed, extractGraph, codegen } from "./passes/index.ts";
6
+ export * from "./ast/nodes.ts";
7
+ export { compile, compileToGraph } from "./compile.ts";
8
+ export type { CompileResult, GraphResult } from "./compile.ts";
9
+ export { NATIVE_BEHAVIOURS, matchedNativeBehaviours } from "./behaviours/index.ts";
10
+ export type { BehaviourEmitCtx, CompilerNativeBehaviour } from "./behaviours/types.ts";
11
+ export { buildSidecar, sidecarPathFor } from "./sidecar.ts";
12
+ export type { ReactraSidecar, ComponentMetadata, StoreMetadata, ServiceMetadata, ParamMetadata, QueryMetadata, StateMetadata, DerivedMetadata, ActionMetadata, ResourceMetadata, UsesMetadata, StoreUseMetadata, InjectMetadata, AwaitMetadata, InputMetadata, BuildSidecarOptions, } from "./sidecar.ts";
13
+ /**
14
+ * Options accepted by the Babel plugin factory. Reserved for Phase 2;
15
+ * pagesDir / emitSidecars / devtools land with items #5b and #7 of the
16
+ * Phase 1 plan.
17
+ */
18
+ export interface ReactraBabelOptions {
19
+ /** Reserved — no options recognised in Phase 1 MVP. */
20
+ readonly _reserved?: never;
21
+ }
22
+ /**
23
+ * Cheap pre-check: does this source look like it contains Reactra DSL?
24
+ * Exported for the Vite plugin so both code paths share the same gate.
25
+ */
26
+ export declare const containsReactraDsl: (source: string) => boolean;
27
+ /** Babel plugin shape — what Babel actually receives. */
28
+ export interface ReactraBabelPlugin {
29
+ readonly name: string;
30
+ parserOverride(code: string, parserOpts: object, parse: (code: string, opts: object) => unknown): unknown;
31
+ }
32
+ /**
33
+ * Babel plugin factory. Use from a `.babelrc` / `babel.config.js`:
34
+ *
35
+ * ```js
36
+ * module.exports = { plugins: ["@reactra/babel-plugin"] }
37
+ * ```
38
+ *
39
+ * Implementation: `parserOverride` runs Reactra's `compile()` first, then
40
+ * feeds the resulting React-19 TSX into Babel's regular parser. Downstream
41
+ * plugins (e.g. `@babel/preset-react`) see only standard React output.
42
+ *
43
+ * Files that don't contain a Reactra container keyword pass through
44
+ * unmodified — the gate is a single regex test.
45
+ */
46
+ export declare const reactraBabelPlugin: (_babel: unknown, _options?: ReactraBabelOptions) => ReactraBabelPlugin;
47
+ export default reactraBabelPlugin;
48
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAGhG,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AACpG,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,YAAY,EACV,KAAK,EACL,SAAS,EACT,OAAO,EACP,IAAI,EACJ,gBAAgB,GACjB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC5E,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AACtD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAM9D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAClF,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAEtF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC3D,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,aAAa,EACb,mBAAmB,GACpB,MAAM,cAAc,CAAA;AAErB;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAA;CAC3B;AAwBD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,OACjB,CAAA;AAEnC,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,GAC7C,OAAO,CAAA;CACX;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,OAAO,EACf,WAAU,mBAAwB,KACjC,kBAOD,CAAA;AAEF,eAAe,kBAAkB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,77 @@
1
+ // @reactra/babel-plugin — Reactra DSL → React 19 compiler (Phase 1)
2
+ //
3
+ // Owner: reactra-compiler-spec.md (Spec 2.1 / Discussion v3)
4
+ //
5
+ // Public surface:
6
+ // - compile() : direct compile API (used by @reactra/vite-plugin)
7
+ // - reactraBabelPlugin : Babel plugin factory for standalone .babelrc use
8
+ // - preprocess(), lex() : pre-processor primitives (Pass 1.1)
9
+ // - AST node types : Phase 1 graph nodes
10
+ //
11
+ // The Babel plugin runs the compile pipeline via `parserOverride` so the
12
+ // rest of Babel's pipeline (including @babel/preset-react) sees the
13
+ // React-19 TSX output instead of raw DSL. See Compiler v3 §7.2.
14
+ import { compile } from "./compile.js";
15
+ export { preprocess, lex, skipTrivia, generatePreprocessSourceMap } from "./preprocess/index.js";
16
+ // Canonical keyword sets — single source of truth for tooling (LSP-0 grammar
17
+ // generator + diagnostic-suppression plugin). Requirements §3 owns the count.
18
+ export { ALL_RESERVED_KEYWORDS, KEYWORDS_BY_SCOPE, CONTAINER_KEYWORDS } from "./preprocess/index.js";
19
+ export { parsePreprocessed, extractGraph, codegen } from "./passes/index.js";
20
+ export * from "./ast/nodes.js";
21
+ export { compile, compileToGraph } from "./compile.js";
22
+ // framework-review §B1 / C3: the language-tools shadow emitter reads the
23
+ // behaviour registry. Surface it on the `.` export so language-tools imports
24
+ // `@reactra/babel-plugin` instead of a cross-package relative path. (The shared
25
+ // emission conventions live under the `./conventions` subpath export.)
26
+ export { NATIVE_BEHAVIOURS, matchedNativeBehaviours } from "./behaviours/index.js";
27
+ export { buildSidecar, sidecarPathFor } from "./sidecar.js";
28
+ // Container keywords that signal "this file contains Reactra DSL." Cheap
29
+ // regex gate so plain .tsx/.ts modules skip the compile pass entirely.
30
+ //
31
+ // Anchor: every Reactra container (`export component`, `route store`,
32
+ // `session store`, the v2 `export <lifetime> store` 3-slot form
33
+ // (`export app store`), the v1 bare `export store`, `(export) service`)
34
+ // appears at the TOP LEVEL of the file, so after any leading whitespace
35
+ // the keyword is the very first token on its line. The /m flag makes `^`
36
+ // match at every line start, so the regex naturally skips matches that
37
+ // happen inside comments (`// route store reads…`), inside template
38
+ // literals (`\`it's a route store\``), or inside JSDoc (` * Instantiate
39
+ // a route store…`) — none of those put the keyword at line-start.
40
+ //
41
+ // The store branch accepts an OPTIONAL `export` before the lifetime word
42
+ // (`export app store`) — `export` is a modifier, not a lifetime — plus the
43
+ // v1 bare `export store` form. Missing the export-prefixed lifetime form was
44
+ // a real bug: the Phase-5 codemod's `export store`→`export app store` (T2)
45
+ // produced a valid v2 container the gate didn't recognize, so esbuild's
46
+ // dep-scan saw raw DSL and bailed with "Unexpected app".
47
+ const REACTRA_CONTAINER_RE = /^\s*(?:export\s+component|(?:export\s+)?(?:app|route|session|subtree)\s+store|export\s+store|(?:export\s+)?service)\s/m;
48
+ /**
49
+ * Cheap pre-check: does this source look like it contains Reactra DSL?
50
+ * Exported for the Vite plugin so both code paths share the same gate.
51
+ */
52
+ export const containsReactraDsl = (source) => REACTRA_CONTAINER_RE.test(source);
53
+ /**
54
+ * Babel plugin factory. Use from a `.babelrc` / `babel.config.js`:
55
+ *
56
+ * ```js
57
+ * module.exports = { plugins: ["@reactra/babel-plugin"] }
58
+ * ```
59
+ *
60
+ * Implementation: `parserOverride` runs Reactra's `compile()` first, then
61
+ * feeds the resulting React-19 TSX into Babel's regular parser. Downstream
62
+ * plugins (e.g. `@babel/preset-react`) see only standard React output.
63
+ *
64
+ * Files that don't contain a Reactra container keyword pass through
65
+ * unmodified — the gate is a single regex test.
66
+ */
67
+ export const reactraBabelPlugin = (_babel, _options = {}) => ({
68
+ name: "@reactra/babel-plugin",
69
+ parserOverride(code, parserOpts, parse) {
70
+ if (!containsReactraDsl(code))
71
+ return parse(code, parserOpts);
72
+ const { code: compiled } = compile(code);
73
+ return parse(compiled, parserOpts);
74
+ },
75
+ });
76
+ export default reactraBabelPlugin;
77
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,6DAA6D;AAC7D,EAAE;AACF,kBAAkB;AAClB,8EAA8E;AAC9E,6EAA6E;AAC7E,gEAAgE;AAChE,gDAAgD;AAChD,EAAE;AACF,yEAAyE;AACzE,oEAAoE;AACpE,gEAAgE;AAEhE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAChG,6EAA6E;AAC7E,8EAA8E;AAC9E,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAUpG,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAC5E,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAGtD,yEAAyE;AACzE,6EAA6E;AAC7E,gFAAgF;AAChF,uEAAuE;AACvE,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAGlF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AA8B3D,yEAAyE;AACzE,uEAAuE;AACvE,EAAE;AACF,sEAAsE;AACtE,gEAAgE;AAChE,wEAAwE;AACxE,wEAAwE;AACxE,yEAAyE;AACzE,uEAAuE;AACvE,oEAAoE;AACpE,wEAAwE;AACxE,kEAAkE;AAClE,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,6EAA6E;AAC7E,2EAA2E;AAC3E,wEAAwE;AACxE,yDAAyD;AACzD,MAAM,oBAAoB,GACxB,wHAAwH,CAAA;AAE1H;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAW,EAAE,CAC5D,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAYnC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,MAAe,EACf,WAAgC,EAAE,EACd,EAAE,CAAC,CAAC;IACxB,IAAI,EAAE,uBAAuB;IAC7B,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK;QACpC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QAC7D,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QACxC,OAAO,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACpC,CAAC;CACF,CAAC,CAAA;AAEF,eAAe,kBAAkB,CAAA"}
@@ -0,0 +1,5 @@
1
+ export { parsePreprocessed } from "./pass-1-parse.ts";
2
+ export { extractGraph } from "./pass-2-extract.ts";
3
+ export { analyzeReadSets } from "./pass-3-readset.ts";
4
+ export { codegen } from "./pass-9-codegen.ts";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/passes/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,6 @@
1
+ // Pipeline entry points for the per-pass implementations.
2
+ export { parsePreprocessed } from "./pass-1-parse.js";
3
+ export { extractGraph } from "./pass-2-extract.js";
4
+ export { analyzeReadSets } from "./pass-3-readset.js";
5
+ export { codegen } from "./pass-9-codegen.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/passes/index.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { File } from "@babel/types";
2
+ export declare const parsePreprocessed: (preprocessed: string) => File;
3
+ //# sourceMappingURL=pass-1-parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pass-1-parse.d.ts","sourceRoot":"","sources":["../../src/passes/pass-1-parse.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAExC,eAAO,MAAM,iBAAiB,GAAI,cAAc,MAAM,KAAG,IAQxD,CAAA"}
@@ -0,0 +1,21 @@
1
+ // Pass 1 — parse the preprocessed source with @babel/parser.
2
+ //
3
+ // Input: preprocessed TSX/TS source (output of the preprocess pass).
4
+ // Output: Babel `File` AST node.
5
+ //
6
+ // The preprocessor wrap from Day 5a means the input is valid TSX, so we
7
+ // can feed it directly to @babel/parser with the `jsx` + `typescript`
8
+ // plugins enabled.
9
+ //
10
+ // Owner spec: reactra-compiler-spec.md §4 Pass 1.
11
+ import { parse } from "@babel/parser";
12
+ export const parsePreprocessed = (preprocessed) => {
13
+ return parse(preprocessed, {
14
+ sourceType: "module",
15
+ allowImportExportEverywhere: false,
16
+ allowReturnOutsideFunction: false,
17
+ plugins: ["jsx", "typescript"],
18
+ tokens: false,
19
+ });
20
+ };
21
+ //# sourceMappingURL=pass-1-parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pass-1-parse.js","sourceRoot":"","sources":["../../src/passes/pass-1-parse.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,sEAAsE;AACtE,iCAAiC;AACjC,EAAE;AACF,wEAAwE;AACxE,sEAAsE;AACtE,mBAAmB;AACnB,EAAE;AACF,kDAAkD;AAElD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAGrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,YAAoB,EAAQ,EAAE;IAC9D,OAAO,KAAK,CAAC,YAAY,EAAE;QACzB,UAAU,EAAE,QAAQ;QACpB,2BAA2B,EAAE,KAAK;QAClC,0BAA0B,EAAE,KAAK;QACjC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC;QAC9B,MAAM,EAAE,KAAK;KACd,CAAC,CAAA;AACJ,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ import * as t from "@babel/types";
2
+ import type { FileGraph } from "../ast/nodes.ts";
3
+ export declare const extractGraph: (source: string, preprocessed: string, ast: t.File) => FileGraph;
4
+ //# sourceMappingURL=pass-2-extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pass-2-extract.d.ts","sourceRoot":"","sources":["../../src/passes/pass-2-extract.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AACjC,OAAO,KAAK,EASV,SAAS,EAqBV,MAAM,iBAAiB,CAAA;AA6CxB,eAAO,MAAM,YAAY,GAAI,QAAQ,MAAM,EAAE,cAAc,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,KAAG,SAuHhF,CAAA"}