@reactra/vite-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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-cache.js","sourceRoot":"","sources":["../src/graph-cache.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,yEAAyE;AACzE,iFAAiF;AACjF,EAAE;AACF,0EAA0E;AAC1E,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,6EAA6E;AAC7E,mCAAmC;AACnC,EAAE;AACF,kFAAkF;AAClF,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,gDAAgD;AAChD,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,iEAAiE;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAkBtD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAe,EAAE;IAC/C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoC,CAAA;IAE1D,MAAM,aAAa,GAAG,CAAC,IAAY,EAA4B,EAAE;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAC/B,IAAI,MAAM;YAAE,OAAO,MAAM,CAAA;QACzB,IAAI,UAAoC,CAAA;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACzC,qEAAqE;YACrE,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,CAAA;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,kEAAkE;YAClE,oEAAoE;YACpE,UAAU,GAAG,EAAE,CAAA;QACjB,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QAC5B,OAAO,UAAU,CAAA;IACnB,CAAC,CAAA;IAED,OAAO,EAAE,aAAa,EAAE,CAAA;AAC1B,CAAC,CAAA"}
@@ -0,0 +1,84 @@
1
+ import type { Plugin } from "vite";
2
+ import { type EsbuildPlugin } from "./esbuild-prescan.ts";
3
+ /**
4
+ * Options accepted by the Vite plugin factory. Reserved for Phase 2 —
5
+ * pagesDir / storesDir / servicesDir / emitSidecars / devtools per
6
+ * Compiler §7.1 land alongside items #7 and #5c.
7
+ */
8
+ export interface ReactraVitePluginOptions {
9
+ /** Reserved — no options recognised in the Phase 1 MVP. */
10
+ readonly _reserved?: never;
11
+ }
12
+ interface ResolvedConfigLike {
13
+ readonly root: string;
14
+ }
15
+ interface FSWatcherLike {
16
+ on(event: "add" | "unlink" | "change", listener: (path: string) => void): unknown;
17
+ }
18
+ interface ViteDevServerLike {
19
+ readonly watcher: FSWatcherLike;
20
+ }
21
+ interface ViteSourceMap {
22
+ version: 3;
23
+ file: string;
24
+ sources: string[];
25
+ sourcesContent: string[];
26
+ names: string[];
27
+ mappings: string;
28
+ }
29
+ /**
30
+ * Vite plugin shape used by Reactra. Structurally a subset of Vite's
31
+ * `Plugin` interface — we don't import Vite types so the plugin source
32
+ * resolves under Bun without Vite installed (matches the test environment).
33
+ */
34
+ export interface ReactraVitePlugin {
35
+ readonly name: string;
36
+ readonly enforce: "pre";
37
+ /**
38
+ * Day 24 / `#15`: contributes
39
+ * `optimizeDeps.esbuildOptions.plugins` so esbuild's dep-scan pass
40
+ * can preprocess Reactra DSL files before its parser sees them.
41
+ * Returns a partial UserConfig — Vite shallow-merges with the
42
+ * user's `vite.config.ts`.
43
+ */
44
+ config(): {
45
+ optimizeDeps: {
46
+ esbuildOptions: {
47
+ plugins: EsbuildPlugin[];
48
+ };
49
+ };
50
+ };
51
+ configResolved(config: ResolvedConfigLike): void;
52
+ buildStart(): void;
53
+ configureServer(server: ViteDevServerLike): void;
54
+ transform(code: string, id: string): {
55
+ code: string;
56
+ map: ViteSourceMap | null;
57
+ } | null;
58
+ }
59
+ /**
60
+ * Vite plugin factory.
61
+ *
62
+ * ```ts
63
+ * // vite.config.ts
64
+ * import { defineConfig } from "vite"
65
+ * import reactra from "@reactra/vite-plugin"
66
+ * import react from "@vitejs/plugin-react"
67
+ *
68
+ * export default defineConfig({
69
+ * plugins: [reactra(), react()],
70
+ * })
71
+ * ```
72
+ *
73
+ * Reactra MUST run before @vitejs/plugin-react. The enforce: "pre" hint
74
+ * pins us to the head of the pipeline; downstream plugins see standard
75
+ * React 19 TSX, never the DSL.
76
+ */
77
+ export declare const reactraVitePlugin: (_options?: ReactraVitePluginOptions) => Plugin;
78
+ export default reactraVitePlugin;
79
+ export { chainsForRoutes, collectServiceInjectionDiagnostics, deriveRoutePath, emitRouteManifest, emitRouterMiddleware, scanMiddleware, scanPages, scanServices, scanStores, type DiscoveredMiddleware, type DiscoveredRoute, type DiscoveredService, type DiscoveredStore, type ServiceInjectionDiagnostic, } from "./walker.ts";
80
+ export { MANIFEST_RELATIVE_PATH, ROUTER_MIDDLEWARE_RELATIVE_PATH, regenerateRouteManifest, type RegenerateResult, } from "./manifest.ts";
81
+ export { RESOURCE_NAMES_RELATIVE_PATH, collectResourceNames, emitResourceNames, regenerateResourceNames, type ResourceNamesResult, } from "./resource-names.ts";
82
+ export { deleteSidecar, isEmptyForIndex, writeSidecar, type DeleteSidecarResult, type WriteSidecarResult, } from "./sidecar-writer.ts";
83
+ export { reactraEsbuildPlugin } from "./esbuild-prescan.ts";
84
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAkBlC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAmC/E;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAA;CAC3B;AAID,UAAU,kBAAkB;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAID,UAAU,aAAa;IACrB,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAA;CAClF;AACD,UAAU,iBAAiB;IACzB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAChC;AAQD,UAAU,aAAa;IACrB,OAAO,EAAE,CAAC,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAA;IACvB;;;;;;OAMG;IACH,MAAM,IAAI;QACR,YAAY,EAAE;YACZ,cAAc,EAAE;gBAGd,OAAO,EAAE,aAAa,EAAE,CAAA;aACzB,CAAA;SACF,CAAA;KACF,CAAA;IACD,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAAA;IAChD,UAAU,IAAI,IAAI,CAAA;IAClB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChD,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAA;CACtD;AAmDD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,GAC5B,WAAU,wBAA6B,KACtC,MA2OF,CAAA;AAED,eAAe,iBAAiB,CAAA;AAIhC,OAAO,EACL,eAAe,EACf,kCAAkC,EAClC,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACT,YAAY,EACZ,UAAU,EACV,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,GAChC,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,uBAAuB,EACvB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,iBAAiB,EACjB,uBAAuB,EACvB,KAAK,mBAAmB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,EACZ,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,379 @@
1
+ // @reactra/vite-plugin — Vite integration for the Reactra compiler.
2
+ //
3
+ // Owner: reactra-compiler-spec.md §7.1
4
+ //
5
+ // Phase 1 surface — what ships today:
6
+ // - enforce: "pre" — Reactra's transform runs before @vitejs/plugin-react.
7
+ // - transform(code, id): calls @reactra/babel-plugin's compile() on any
8
+ // .tsx / .ts / .jsx / .js file whose source contains a Reactra container
9
+ // keyword. compile() short-circuits cheaply on non-DSL files via the
10
+ // containsReactraDsl gate.
11
+ // - configResolved(config): captures the project root for the walker.
12
+ // - buildStart: scan src/pages/ and emit routeManifest.generated.ts.
13
+ // Phase 1 #5b — file-based route discovery (Router §5.1).
14
+ // - configureServer({ watcher }): re-emit on src/pages/ add/unlink/change.
15
+ // - Source maps return null (Vite falls back to a 1-to-1 line map).
16
+ //
17
+ // Deferred (still tracked in phase-1.md):
18
+ // - Typed RouteId / RouteParams / RouteQuery / TypedNavigate exports
19
+ // in the manifest (item #5c — needs compiler to surface query schemas)
20
+ // - HMR boundary injection via import.meta.hot.accept(...) (item #11)
21
+ // - Source maps (item #10)
22
+ //
23
+ // Day 14b (#7 writer): every successful transform also drops a
24
+ // `.reactra.json` sidecar under node_modules/.reactra/sidecars/ per
25
+ // Compiler §6. Cross-file `use storeX` resolution (the consumer side)
26
+ // is a follow-up — this commit only emits.
27
+ import { buildSidecar, compile, containsReactraDsl, } from "@reactra/babel-plugin";
28
+ import { createGraphCache } from "./graph-cache.js";
29
+ import { fingerprintOf, fingerprintsEqual, isPagesFile, } from "./fingerprint.js";
30
+ import { regenerateRouteManifest } from "./manifest.js";
31
+ import { regenerateResourceNames } from "./resource-names.js";
32
+ import { reactraEsbuildPlugin } from "./esbuild-prescan.js";
33
+ import { deleteSidecar, isEmptyForIndex, writeSidecar } from "./sidecar-writer.js";
34
+ /** File-level opt-out for the co-located-store HMR advisory (improvements #5). */
35
+ const COLOCATION_OPT_OUT = "// reactra-allow-colocated-route-store";
36
+ const STORE_KINDS = new Set([
37
+ "route-store",
38
+ "session-store",
39
+ "export-store",
40
+ ]);
41
+ /**
42
+ * improvements #5 — advise when a store is co-located with a component in one
43
+ * file. The emitted store binding is a non-component export, which makes the
44
+ * whole module ineligible for React Fast Refresh, so HMR full-reloads. A
45
+ * co-located `route store` loses its per-route state on every edit (the
46
+ * painful case); `session`/`export` stores are registry-preserved, so only
47
+ * in-progress Fast Refresh is disrupted. Advisory only — never fails the
48
+ * build (same-file stores are legal; Store v4.2 §2.5). Opt out per file with
49
+ * the {@link COLOCATION_OPT_OUT} comment.
50
+ */
51
+ const warnIfColocatedStore = (graph, source) => {
52
+ if (source.includes(COLOCATION_OPT_OUT))
53
+ return;
54
+ const stores = graph.containers.filter((c) => STORE_KINDS.has(c.kind));
55
+ if (stores.length === 0 || !graph.containers.some((c) => c.kind === "component"))
56
+ return;
57
+ const names = stores.map((c) => `\`${c.name}\``).join(", ");
58
+ const note = stores.some((c) => c.kind === "route-store")
59
+ ? " — per-route store state is lost on every edit"
60
+ : " (store state is registry-preserved; only in-progress Fast Refresh is disrupted)";
61
+ console.warn(`[@reactra/vite-plugin] Store(s) ${names} co-located with a component — HMR will full-reload${note}. ` +
62
+ `Extract to src/stores/ for fast HMR, or add \`${COLOCATION_OPT_OUT}\` to this file to silence. (Store §2.5)`);
63
+ };
64
+ const SUPPORTED_EXT_RE = /\.(?:tsx|ts|jsx|js)(?:\?.*)?$/;
65
+ const stripQuery = (id) => {
66
+ const q = id.indexOf("?");
67
+ return q === -1 ? id : id.slice(0, q);
68
+ };
69
+ /**
70
+ * Relabel a compiled module's source map so DevTools doesn't list the DSL
71
+ * original under the same name as the served compiled module (devtools-debugging
72
+ * backlog issue A). The compiled module is served at its real http URL; the map's
73
+ * `sources[0]` (the DSL leaf the user authored) is moved under a distinct
74
+ * `reactra://` virtual URL so the two appear as clearly different Sources entries.
75
+ * `sourcesContent` is untouched — devtools still shows the DSL you wrote — and
76
+ * `file` keeps the real path, since it names the generated output. Only the first
77
+ * source (Reactra always emits exactly one) is relabelled.
78
+ */
79
+ const labelDslSource = (map, sourcePath) => {
80
+ if (map.sources.length === 0)
81
+ return map;
82
+ // Drive letter + backslashes → a clean POSIX-ish path under the virtual host.
83
+ const rel = sourcePath
84
+ .replace(/^[A-Za-z]:/, "")
85
+ .replace(/\\/g, "/")
86
+ .replace(/^\/+/, "");
87
+ return { ...map, sources: [`reactra:///${rel}`, ...map.sources.slice(1)] };
88
+ };
89
+ // True when `path` (absolute or project-relative) refers to a file under
90
+ // `<projectRoot>/src/`. Day 20 / `#5c` widened from `src/pages/` only —
91
+ // store-file changes anywhere under `src/` need to regen the manifest
92
+ // so `STORES` picks up adds / removes. Filter still excludes the generated
93
+ // manifest itself to avoid feedback loops (Vite watcher fires `change`
94
+ // on its own write).
95
+ const isInsideSrc = (projectRoot, eventPath) => {
96
+ const root = projectRoot.replace(/\\/g, "/");
97
+ const target = eventPath.replace(/\\/g, "/");
98
+ const prefix = root.endsWith("/") ? root + "src/" : root + "/src/";
99
+ if (!target.startsWith(prefix))
100
+ return false;
101
+ // Skip the generated manifest's own writes (Day-20 added the loop
102
+ // risk because store-file detection now walks src/, and the manifest
103
+ // lives under src/).
104
+ if (target.endsWith("/routeManifest.generated.ts"))
105
+ return false;
106
+ // Same skip for the Wave-3 / Stage-2 middleware companion. Without it,
107
+ // regenerateRouteManifest's own write-out would re-fire this watcher
108
+ // and loop indefinitely.
109
+ if (target.endsWith("/router-middleware.generated.ts"))
110
+ return false;
111
+ return true;
112
+ };
113
+ /**
114
+ * Vite plugin factory.
115
+ *
116
+ * ```ts
117
+ * // vite.config.ts
118
+ * import { defineConfig } from "vite"
119
+ * import reactra from "@reactra/vite-plugin"
120
+ * import react from "@vitejs/plugin-react"
121
+ *
122
+ * export default defineConfig({
123
+ * plugins: [reactra(), react()],
124
+ * })
125
+ * ```
126
+ *
127
+ * Reactra MUST run before @vitejs/plugin-react. The enforce: "pre" hint
128
+ * pins us to the head of the pipeline; downstream plugins see standard
129
+ * React 19 TSX, never the DSL.
130
+ */
131
+ export const reactraVitePlugin = (_options = {}) => {
132
+ // Captured in configResolved; consumed by buildStart + configureServer.
133
+ // Starts empty so the type stays narrow; the plugin never reads it
134
+ // before configResolved fires (Vite guarantees the call order).
135
+ let projectRoot = "";
136
+ // A3 increment 2 — the per-file declaration fingerprint map. The ONLY mutable
137
+ // watcher state (C1 exempts it). Scoped to this plugin instance (not a
138
+ // module-level global) so two projects building in one process don't share
139
+ // it. A `change` whose recomputed fingerprint matches the stored one means
140
+ // no store/service/resource decl was added/renamed/removed → the src/-wide
141
+ // rescan can be skipped (a non-pages/ change can skip the regen entirely).
142
+ // Entries are added/refreshed on every full regen and removed on `unlink`.
143
+ const fingerprints = new Map();
144
+ /**
145
+ * Run BOTH regens (manifest + resource-names) over one shared per-event
146
+ * cache, then refresh the fingerprint for `eventPath` from that same cache
147
+ * (no extra compile). `eventPath` is absolute; pass `null` for build-time
148
+ * regens that don't carry a single triggering file.
149
+ */
150
+ const regenAll = (eventPath) => {
151
+ const cache = createGraphCache();
152
+ try {
153
+ regenerateRouteManifest(projectRoot, cache);
154
+ }
155
+ catch (err) {
156
+ console.error("[@reactra/vite-plugin] manifest regen failed:", err);
157
+ }
158
+ try {
159
+ regenerateResourceNames(projectRoot, cache);
160
+ }
161
+ catch (err) {
162
+ console.error("[@reactra/vite-plugin] resource-names regen failed:", err);
163
+ }
164
+ if (eventPath) {
165
+ fingerprints.set(eventPath, fingerprintOf(cache.containersFor(eventPath)));
166
+ }
167
+ };
168
+ const plugin = {
169
+ name: "@reactra/vite-plugin",
170
+ enforce: "pre",
171
+ config() {
172
+ // Day 24 / `#15`: hand esbuild a Reactra-aware onLoad so the
173
+ // dep-scan phase can preprocess DSL files before its parser
174
+ // sees them. Without this, esbuild prints "Unexpected
175
+ // component" / "Expected ';' but found 'store'" + the
176
+ // umbrella "Failed to run dependency scan" warning at first
177
+ // dev-server boot. On-demand serving still works because the
178
+ // transform() hook below catches each per-request compile.
179
+ return {
180
+ optimizeDeps: {
181
+ esbuildOptions: {
182
+ plugins: [reactraEsbuildPlugin],
183
+ },
184
+ },
185
+ };
186
+ },
187
+ configResolved(config) {
188
+ projectRoot = config.root;
189
+ },
190
+ buildStart() {
191
+ // First emission of the manifest. Walker tolerates a missing
192
+ // src/pages/ directory (returns [] and we write an empty manifest)
193
+ // so this is safe even on a fresh-clone with no pages yet.
194
+ if (projectRoot) {
195
+ // A3: one shared cache across both build-time regens (regenAll), so a
196
+ // file read by both compiles once. QW-5: this also emits
197
+ // `.reactra/resource-names.d.ts` so `useMutation`'s `invalidate` is
198
+ // typed against the project's resource set (degrades to `string` when
199
+ // no resource is declared). regenAll swallows generator failures so a
200
+ // bad file never fails the build.
201
+ regenAll(null);
202
+ }
203
+ },
204
+ configureServer(server) {
205
+ // Day 20 / `#5c`: watch all of src/ (was src/pages/ only). Page
206
+ // adds/removes still regen ROUTES; store file adds/removes regen
207
+ // STORES. The generated manifest itself is filtered out by
208
+ // `isInsideSrc` to avoid feedback loops.
209
+ // `add` / `unlink` ALWAYS full-regen + refresh fingerprints — the file-
210
+ // set membership changed, so ROUTES/STORES/SERVICES/resources may all
211
+ // shift (regenAll shares one per-event cache between both generators).
212
+ const onAdd = (path) => {
213
+ if (!projectRoot || !isInsideSrc(projectRoot, path))
214
+ return;
215
+ regenAll(path);
216
+ };
217
+ // A3 increment 2 — `change` is the hot path (every keystroke-save). Compile
218
+ // the changed file ONCE, diff its declaration fingerprint against the
219
+ // stored one:
220
+ // - decl set DIFFERENT (store/service renamed, added, removed, or a
221
+ // service modifier flipped) → full regen + refresh fingerprint.
222
+ // - decl set UNCHANGED (body-only edit) → the src/-wide store/service/
223
+ // resource scan can't change the output, so SKIP it. A pages/ change
224
+ // still needs scanPages (routes/queries/prefetch can change), so we
225
+ // regen there; a non-pages/ body-only change skips the regen entirely.
226
+ const onChange = (path) => {
227
+ if (!projectRoot || !isInsideSrc(projectRoot, path))
228
+ return;
229
+ const cache = createGraphCache();
230
+ const next = fingerprintOf(cache.containersFor(path));
231
+ const prev = fingerprints.get(path);
232
+ const declUnchanged = prev !== undefined && fingerprintsEqual(prev, next);
233
+ fingerprints.set(path, next);
234
+ if (declUnchanged && !isPagesFile(projectRoot, path)) {
235
+ // Body-only edit to a non-pages/ file — nothing the manifest or
236
+ // resource-names depend on changed. Skip the whole regen.
237
+ return;
238
+ }
239
+ if (declUnchanged) {
240
+ // Body-only edit to a pages/ file: routes/queries/prefetch could
241
+ // still change, so regen the manifest (reusing the cache that already
242
+ // compiled this file). The src/-wide store/service walk still runs
243
+ // inside regenerateRouteManifest but reads cached compiles — cheap.
244
+ // resource-names also reuses the cache.
245
+ try {
246
+ regenerateRouteManifest(projectRoot, cache);
247
+ }
248
+ catch (err) {
249
+ console.error("[@reactra/vite-plugin] manifest regen failed:", err);
250
+ }
251
+ try {
252
+ regenerateResourceNames(projectRoot, cache);
253
+ }
254
+ catch (err) {
255
+ console.error("[@reactra/vite-plugin] resource-names regen failed:", err);
256
+ }
257
+ return;
258
+ }
259
+ // Decl set changed (or first-ever sighting of this file) → full regen.
260
+ // Reuse the cache that already compiled the changed file.
261
+ try {
262
+ regenerateRouteManifest(projectRoot, cache);
263
+ }
264
+ catch (err) {
265
+ console.error("[@reactra/vite-plugin] manifest regen failed:", err);
266
+ }
267
+ try {
268
+ regenerateResourceNames(projectRoot, cache);
269
+ }
270
+ catch (err) {
271
+ console.error("[@reactra/vite-plugin] resource-names regen failed:", err);
272
+ }
273
+ };
274
+ // Day 25 / sidecar-on-unlink: when a Reactra source file is
275
+ // DELETED (not just edited), Vite never re-fires `transform()`
276
+ // for it — the file is gone — so `#7c`'s sidecar GC path inside
277
+ // transform() doesn't get a chance to run. Result: the deleted
278
+ // file's stale sidecar lingers under
279
+ // `node_modules/.reactra/sidecars/` and the next
280
+ // `loadSidecarIndex` call still sees its `stores[]` entries,
281
+ // potentially triggering duplicate-store-across-files against a
282
+ // new home file the user moved the store to. Fix: hook the
283
+ // watcher's unlink event directly to delete the sidecar by path.
284
+ // ENOENT-as-no-op in `deleteSidecar` means we don't need to gate
285
+ // by file extension — the call is harmless on non-Reactra files
286
+ // that never had a sidecar to begin with.
287
+ const onUnlink = (path) => {
288
+ if (!projectRoot || !isInsideSrc(projectRoot, path))
289
+ return;
290
+ // File removed → drop its fingerprint so a later re-create is treated
291
+ // as a fresh sighting (full regen), and full-regen now that the
292
+ // file-set membership changed.
293
+ fingerprints.delete(path);
294
+ regenAll(null);
295
+ try {
296
+ deleteSidecar(projectRoot, path);
297
+ }
298
+ catch (err) {
299
+ console.error("[@reactra/vite-plugin] sidecar unlink failed:", err);
300
+ }
301
+ };
302
+ server.watcher.on("add", onAdd);
303
+ server.watcher.on("unlink", onUnlink);
304
+ // `change` is needed too — renaming a [param] segment from
305
+ // [id] → [customerId] surfaces as change(rename source) on some
306
+ // platforms rather than add+unlink (the fingerprint differ in onChange
307
+ // still forces a regen because the file's queries/route change).
308
+ server.watcher.on("change", onChange);
309
+ },
310
+ transform(code, id) {
311
+ // Skip files Reactra doesn't own (node_modules, virtual modules).
312
+ if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) {
313
+ return null;
314
+ }
315
+ if (id.startsWith("\0") || id.startsWith("virtual:"))
316
+ return null;
317
+ if (!SUPPORTED_EXT_RE.test(stripQuery(id)))
318
+ return null;
319
+ if (!containsReactraDsl(code))
320
+ return null;
321
+ const sourcePath = stripQuery(id);
322
+ // Backlog 1a: `inject store X` binds via `import type` / same-file decl,
323
+ // so Pass 9 no longer needs `projectRoot` to resolve store names — the
324
+ // sidecar reader is gone. We still pass `sourceFile: id` (Day 22 / `#10`)
325
+ // so the returned source map's `sources[0]` + `file` carry the Vite
326
+ // module id; devtools shows the original DSL in the Sources panel.
327
+ const { code: compiled, graph, map } = compile(code, {
328
+ sourceFile: sourcePath,
329
+ });
330
+ warnIfColocatedStore(graph, code);
331
+ if (projectRoot) {
332
+ // Best-effort write — failures log but never break the transform.
333
+ // Day 18 / `#7c`: if the recompile produced a sidecar with no
334
+ // stores+services (e.g. a route store was moved out to its own
335
+ // file and what's left in this source is a pure-component page),
336
+ // DELETE the prior sidecar instead of overwriting it with an
337
+ // empty one. Leaving the stale sidecar around would let
338
+ // loadSidecarIndex keep seeing the moved-away store name and
339
+ // throw duplicate-store-across-files against the new home file.
340
+ try {
341
+ const sidecar = buildSidecar(graph, sourcePath);
342
+ if (isEmptyForIndex(sidecar)) {
343
+ deleteSidecar(projectRoot, sourcePath);
344
+ }
345
+ else {
346
+ writeSidecar(projectRoot, sourcePath, sidecar);
347
+ }
348
+ }
349
+ catch (err) {
350
+ console.error("[@reactra/vite-plugin] sidecar write failed:", err);
351
+ }
352
+ }
353
+ // `#10-followup` (Compiler §8): the returned map is now the full composed
354
+ // source→compiled map — both hops mapped, one segment per user-code slice
355
+ // (state/derived/action/resource/view) — so a breakpoint on a DSL line
356
+ // binds to the matching compiled line. `sourcesContent` carries the DSL.
357
+ //
358
+ // devtools-debugging backlog issue A: relabel the DSL leaf so DevTools
359
+ // doesn't list it under the same name as the served compiled module.
360
+ // Cast the readonly RawSourceMap to the mutable boundary type — same
361
+ // object, only the array element types differ in readonly-ness.
362
+ return { code: compiled, map: (map && labelDslSource(map, sourcePath)) };
363
+ },
364
+ };
365
+ // `ReactraVitePlugin` is a hand-rolled structural subset of Vite's `Plugin`
366
+ // (we don't import Vite at runtime). Vite's richer esbuild/source-map hook
367
+ // types don't bidirectionally match our minimal ones, so cast at the public
368
+ // boundary — the object is still type-checked against ReactraVitePlugin above.
369
+ return plugin;
370
+ };
371
+ export default reactraVitePlugin;
372
+ // Re-exports so consumers (tests, integrations) can reach the walker and
373
+ // the manifest helpers without a second package boundary.
374
+ export { chainsForRoutes, collectServiceInjectionDiagnostics, deriveRoutePath, emitRouteManifest, emitRouterMiddleware, scanMiddleware, scanPages, scanServices, scanStores, } from "./walker.js";
375
+ export { MANIFEST_RELATIVE_PATH, ROUTER_MIDDLEWARE_RELATIVE_PATH, regenerateRouteManifest, } from "./manifest.js";
376
+ export { RESOURCE_NAMES_RELATIVE_PATH, collectResourceNames, emitResourceNames, regenerateResourceNames, } from "./resource-names.js";
377
+ export { deleteSidecar, isEmptyForIndex, writeSidecar, } from "./sidecar-writer.js";
378
+ export { reactraEsbuildPlugin } from "./esbuild-prescan.js";
379
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type DiscoveredMiddleware, type DiscoveredRoute, type DiscoveredService, type DiscoveredStore } from "./walker.ts";
2
+ /**
3
+ * The on-disk location of the generated manifest, relative to the project
4
+ * root. Exported for tests + so the vite plugin can `import` from a stable
5
+ * path in the demo / app config.
6
+ */
7
+ export declare const MANIFEST_RELATIVE_PATH = "src/routeManifest.generated.ts";
8
+ /**
9
+ * The on-disk location of the generated middleware chains module (Wave 3,
10
+ * Stage 2). Sits next to the route manifest in `src/` so importers can
11
+ * pull `import { middlewareChains } from "./router-middleware.generated.ts"`
12
+ * with the same relative-path convention. Spec §6.4 names this file.
13
+ */
14
+ export declare const ROUTER_MIDDLEWARE_RELATIVE_PATH = "src/router-middleware.generated.ts";
15
+ /**
16
+ * Result of a regeneration attempt. `wrote: true` means the file changed
17
+ * and we wrote new bytes; `wrote: false` means the content was already
18
+ * up-to-date and we left the file alone.
19
+ */
20
+ export interface RegenerateResult {
21
+ readonly wrote: boolean;
22
+ readonly routes: readonly DiscoveredRoute[];
23
+ /**
24
+ * Stores discovered via the sidecar index — surfaced in the result for
25
+ * tests + diagnostics. Day 20 / `#5c`.
26
+ */
27
+ readonly stores: readonly DiscoveredStore[];
28
+ /**
29
+ * Services discovered via the `preprocess()`-based scan of `src/` —
30
+ * surfaced in the result for tests + diagnostics. Phase 3.
31
+ */
32
+ readonly services: readonly DiscoveredService[];
33
+ readonly content: string;
34
+ readonly path: string;
35
+ /**
36
+ * Wave 3 / Stage 2 — middleware files discovered + the per-route chains
37
+ * resolved against them. Surfaced for tests + so the vite plugin can
38
+ * detect "no middleware exists anywhere" and skip the second write.
39
+ */
40
+ readonly middleware: readonly DiscoveredMiddleware[];
41
+ /**
42
+ * Whether the middleware companion file `<projectRoot>/src/
43
+ * router-middleware.generated.ts` was rewritten this call. Same
44
+ * change-check semantics as `wrote` — true only when bytes differ.
45
+ */
46
+ readonly wroteMiddleware: boolean;
47
+ }
48
+ /**
49
+ * Scan + emit + write-if-changed. Idempotent — calling twice with no
50
+ * page-tree change is a no-op for the filesystem.
51
+ *
52
+ * The walker tolerates a missing `src/pages/` directory (returns []); we
53
+ * still write the empty manifest so importers don't ImportError before
54
+ * any pages exist. Mirrors the placeholder a fresh-clone commits.
55
+ */
56
+ export declare const regenerateRouteManifest: (projectRoot: string, cache?: import("./graph-cache.ts").GraphCache) => RegenerateResult;
57
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,EASL,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,aAAa,CAAA;AAEpB;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,mCAAmC,CAAA;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,uCACN,CAAA;AAEtC;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAC3C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAC/C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACpD;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;CAClC;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,EACnB,6CAA0B,KACzB,gBA4GF,CAAA"}