@fluojs/cli 1.1.0 → 3.0.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 (137) hide show
  1. package/README.ko.md +183 -22
  2. package/README.md +186 -22
  3. package/dist/cli.d.ts +5 -4
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +128 -35
  6. package/dist/commands/diagnostics.d.ts +35 -0
  7. package/dist/commands/diagnostics.d.ts.map +1 -1
  8. package/dist/commands/diagnostics.js +60 -0
  9. package/dist/commands/generate.d.ts +1 -49
  10. package/dist/commands/generate.d.ts.map +1 -1
  11. package/dist/commands/generate.js +1 -214
  12. package/dist/commands/inspect.d.ts +5 -7
  13. package/dist/commands/inspect.d.ts.map +1 -1
  14. package/dist/commands/inspect.js +85 -65
  15. package/dist/commands/migrate.d.ts.map +1 -1
  16. package/dist/commands/migrate.js +27 -15
  17. package/dist/commands/migration-transform-tokens.d.ts +15 -0
  18. package/dist/commands/migration-transform-tokens.d.ts.map +1 -0
  19. package/dist/commands/migration-transform-tokens.js +41 -0
  20. package/dist/commands/new.d.ts +0 -6
  21. package/dist/commands/new.d.ts.map +1 -1
  22. package/dist/commands/new.js +42 -96
  23. package/dist/commands/output-path-safety.d.ts +14 -0
  24. package/dist/commands/output-path-safety.d.ts.map +1 -0
  25. package/dist/commands/output-path-safety.js +34 -0
  26. package/dist/commands/scripts.d.ts +1 -1
  27. package/dist/commands/scripts.d.ts.map +1 -1
  28. package/dist/commands/scripts.js +13 -7
  29. package/dist/commands/typegen-artifact.d.ts +54 -0
  30. package/dist/commands/typegen-artifact.d.ts.map +1 -0
  31. package/dist/commands/typegen-artifact.js +117 -0
  32. package/dist/commands/typegen-generation-child.d.ts +2 -0
  33. package/dist/commands/typegen-generation-child.d.ts.map +1 -0
  34. package/dist/commands/typegen-generation-child.js +59 -0
  35. package/dist/commands/typegen-generation-process.d.ts +46 -0
  36. package/dist/commands/typegen-generation-process.d.ts.map +1 -0
  37. package/dist/commands/typegen-generation-process.js +131 -0
  38. package/dist/commands/typegen-generation-protocol.d.ts +16 -0
  39. package/dist/commands/typegen-generation-protocol.d.ts.map +1 -0
  40. package/dist/commands/typegen-generation-protocol.js +35 -0
  41. package/dist/commands/typegen-isolated-source.d.ts +10 -0
  42. package/dist/commands/typegen-isolated-source.d.ts.map +1 -0
  43. package/dist/commands/typegen-isolated-source.js +75 -0
  44. package/dist/commands/typegen-options.d.ts +20 -0
  45. package/dist/commands/typegen-options.d.ts.map +1 -0
  46. package/dist/commands/typegen-options.js +71 -0
  47. package/dist/commands/typegen-source.d.ts +59 -0
  48. package/dist/commands/typegen-source.d.ts.map +1 -0
  49. package/dist/commands/typegen-source.js +183 -0
  50. package/dist/commands/typegen-watch.d.ts +46 -0
  51. package/dist/commands/typegen-watch.d.ts.map +1 -0
  52. package/dist/commands/typegen-watch.js +212 -0
  53. package/dist/commands/typegen.d.ts +29 -0
  54. package/dist/commands/typegen.d.ts.map +1 -0
  55. package/dist/commands/typegen.js +119 -0
  56. package/dist/dev-runner/node-restart-runner.d.ts +6 -0
  57. package/dist/dev-runner/node-restart-runner.d.ts.map +1 -1
  58. package/dist/dev-runner/node-restart-runner.js +64 -13
  59. package/dist/fixtures/inspect-react-app.module.d.ts +4 -0
  60. package/dist/fixtures/inspect-react-app.module.d.ts.map +1 -0
  61. package/dist/fixtures/inspect-react-app.module.js +32 -0
  62. package/dist/fixtures/typegen-react-app.module.d.ts +4 -0
  63. package/dist/fixtures/typegen-react-app.module.d.ts.map +1 -0
  64. package/dist/fixtures/typegen-react-app.module.js +33 -0
  65. package/dist/generate-command.d.ts +50 -0
  66. package/dist/generate-command.d.ts.map +1 -0
  67. package/dist/generate-command.js +214 -0
  68. package/dist/index.d.ts +6 -5
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +6 -5
  71. package/dist/new/install.js +1 -1
  72. package/dist/new/package-spec-resolver.d.ts.map +1 -1
  73. package/dist/new/package-spec-resolver.js +50 -59
  74. package/dist/new/prompt.d.ts +1 -0
  75. package/dist/new/prompt.d.ts.map +1 -1
  76. package/dist/new/prompt.js +40 -12
  77. package/dist/new/published-internal-dependencies.d.ts +20 -0
  78. package/dist/new/published-internal-dependencies.d.ts.map +1 -0
  79. package/dist/new/published-internal-dependencies.js +20 -0
  80. package/dist/new/react-vite-ssr-scaffold.d.ts +19 -0
  81. package/dist/new/react-vite-ssr-scaffold.d.ts.map +1 -0
  82. package/dist/new/react-vite-ssr-scaffold.js +108 -0
  83. package/dist/new/resolver.d.ts +2 -2
  84. package/dist/new/resolver.d.ts.map +1 -1
  85. package/dist/new/resolver.js +5 -1
  86. package/dist/new/scaffold.d.ts.map +1 -1
  87. package/dist/new/scaffold.js +177 -54
  88. package/dist/new/starter-profiles.d.ts +8 -4
  89. package/dist/new/starter-profiles.d.ts.map +1 -1
  90. package/dist/new/starter-profiles.js +52 -18
  91. package/dist/new/templates/react-vite-ssr/README.md.ejs +74 -0
  92. package/dist/new/templates/react-vite-ssr/playwright.config.ts.ejs +26 -0
  93. package/dist/new/templates/react-vite-ssr/src/app.test.ts.ejs +82 -0
  94. package/dist/new/templates/react-vite-ssr/src/app.ts.ejs +91 -0
  95. package/dist/new/templates/react-vite-ssr/src/entry-client.tsx.ejs +29 -0
  96. package/dist/new/templates/react-vite-ssr/src/entry-server.tsx.ejs +52 -0
  97. package/dist/new/templates/react-vite-ssr/src/load-manifest.test.ts.ejs +55 -0
  98. package/dist/new/templates/react-vite-ssr/src/load-manifest.ts.ejs +53 -0
  99. package/dist/new/templates/react-vite-ssr/src/main.ts.ejs +18 -0
  100. package/dist/new/templates/react-vite-ssr/src/page.tsx.ejs +43 -0
  101. package/dist/new/templates/react-vite-ssr/src/react-app.test.tsx.ejs +67 -0
  102. package/dist/new/templates/react-vite-ssr/src/react-app.tsx.ejs +46 -0
  103. package/dist/new/templates/react-vite-ssr/src/styles.css.ejs +25 -0
  104. package/dist/new/templates/react-vite-ssr/src/styles.d.ts.ejs +1 -0
  105. package/dist/new/templates/react-vite-ssr/tests/production-hydration.spec.ts.ejs +54 -0
  106. package/dist/new/templates/react-vite-ssr/tsconfig.json.ejs +16 -0
  107. package/dist/new/templates/react-vite-ssr/vite.client.config.ts.ejs +24 -0
  108. package/dist/new/templates/react-vite-ssr/vite.server.config.ts.ejs +17 -0
  109. package/dist/new/templates/react-vite-ssr/vitest.config.ts.ejs +10 -0
  110. package/dist/new/types.d.ts +4 -2
  111. package/dist/new/types.d.ts.map +1 -1
  112. package/dist/public-generate.d.ts +2 -0
  113. package/dist/public-generate.d.ts.map +1 -0
  114. package/dist/public-generate.js +1 -0
  115. package/dist/public-inspect.d.ts +13 -0
  116. package/dist/public-inspect.d.ts.map +1 -0
  117. package/dist/public-inspect.js +16 -0
  118. package/dist/public-new.d.ts +13 -0
  119. package/dist/public-new.d.ts.map +1 -0
  120. package/dist/public-new.js +16 -0
  121. package/dist/public-typegen.d.ts +14 -0
  122. package/dist/public-typegen.d.ts.map +1 -0
  123. package/dist/public-typegen.js +17 -0
  124. package/dist/run-cli.d.ts +2 -1
  125. package/dist/run-cli.d.ts.map +1 -1
  126. package/dist/studio/sidecar.d.ts.map +1 -1
  127. package/dist/studio/sidecar.js +106 -14
  128. package/dist/transforms/nestjs-migrate.d.ts +4 -1
  129. package/dist/transforms/nestjs-migrate.d.ts.map +1 -1
  130. package/dist/transforms/nestjs-migrate.js +625 -65
  131. package/dist/typegen-contract.d.ts +10 -0
  132. package/dist/typegen-contract.d.ts.map +1 -0
  133. package/dist/typegen-contract.js +9 -0
  134. package/dist/usage.d.ts +19 -0
  135. package/dist/usage.d.ts.map +1 -0
  136. package/dist/usage.js +178 -0
  137. package/package.json +19 -10
@@ -0,0 +1,46 @@
1
+ /** Scheduler used to debounce typegen filesystem bursts deterministically. */
2
+ export type TypegenWatchScheduler = {
3
+ readonly clear: (handle: number) => void;
4
+ readonly set: (callback: () => void, delayMs: number) => number;
5
+ };
6
+ /** Signal registration boundary owned by one typegen watch invocation. */
7
+ export type TypegenWatchSignalTarget = {
8
+ readonly off: (signal: 'SIGINT' | 'SIGTERM', listener: () => void) => unknown;
9
+ readonly once: (signal: 'SIGINT' | 'SIGTERM', listener: () => void) => unknown;
10
+ };
11
+ /** Minimal watcher resource acquired by typegen watch mode. */
12
+ export type TypegenWatcher = {
13
+ close(): void;
14
+ on(event: 'error', listener: (error: Error) => void): TypegenWatcher;
15
+ };
16
+ /** One child generation owned by a typegen watch coordinator. */
17
+ export type TypegenWatchGeneration = {
18
+ cancel(): void;
19
+ readonly result: Promise<string>;
20
+ };
21
+ type TypegenWatchTarget = (target: string, options: {
22
+ readonly persistent: boolean;
23
+ readonly recursive: boolean;
24
+ }, listener: (event: string, filename: string | Buffer | null) => void) => TypegenWatcher;
25
+ /** Dependencies and callbacks for one bounded typegen watch lifecycle. */
26
+ export type TypegenWatchOptions = {
27
+ readonly commit: (source: string, signal: AbortSignal) => Promise<void>;
28
+ readonly debounceMs?: number;
29
+ readonly modulePath: string;
30
+ readonly onError?: (error: unknown) => void;
31
+ readonly onReady?: (watchRoot: string) => void;
32
+ readonly outputPath: string;
33
+ readonly scheduler?: TypegenWatchScheduler;
34
+ readonly signalTarget?: TypegenWatchSignalTarget;
35
+ readonly startGeneration: () => TypegenWatchGeneration;
36
+ readonly watchTarget?: TypegenWatchTarget;
37
+ };
38
+ /**
39
+ * Watches the application module directory while generating an initial current artifact.
40
+ *
41
+ * @param options Generation, watcher, scheduler, and signal lifecycle dependencies.
42
+ * @returns Exit code `0` after signal shutdown or `1` after an asynchronous watcher failure.
43
+ */
44
+ export declare function runTypegenWatch(options: TypegenWatchOptions): Promise<number>;
45
+ export {};
46
+ //# sourceMappingURL=typegen-watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typegen-watch.d.ts","sourceRoot":"","sources":["../../src/commands/typegen-watch.ts"],"names":[],"mappings":"AAGA,8EAA8E;AAC9E,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACjE,CAAC;AAEF,0EAA0E;AAC1E,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAC;IAC9E,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,OAAO,CAAC;CAChF,CAAC;AAEF,+DAA+D;AAC/D,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,IAAI,IAAI,CAAC;IACd,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,cAAc,CAAC;CACtE,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF,KAAK,kBAAkB,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,EACtE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAChE,cAAc,CAAC;AAEpB,0EAA0E;AAC1E,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,sBAAsB,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAC3C,CAAC;AAwCF;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0KnF"}
@@ -0,0 +1,212 @@
1
+ import { watch } from 'node:fs';
2
+ import { basename, dirname, resolve } from 'node:path';
3
+
4
+ /** Scheduler used to debounce typegen filesystem bursts deterministically. */
5
+
6
+ /** Signal registration boundary owned by one typegen watch invocation. */
7
+
8
+ /** Minimal watcher resource acquired by typegen watch mode. */
9
+
10
+ /** One child generation owned by a typegen watch coordinator. */
11
+
12
+ /** Dependencies and callbacks for one bounded typegen watch lifecycle. */
13
+
14
+ const DEFAULT_DEBOUNCE_MS = 100;
15
+ function createDefaultScheduler() {
16
+ let sequence = 0;
17
+ const timers = new Map();
18
+ return {
19
+ clear(handle) {
20
+ const timer = timers.get(handle);
21
+ if (timer !== undefined) {
22
+ clearTimeout(timer);
23
+ timers.delete(handle);
24
+ }
25
+ },
26
+ set(callback, delayMs) {
27
+ sequence += 1;
28
+ const handle = sequence;
29
+ const timer = setTimeout(() => {
30
+ timers.delete(handle);
31
+ callback();
32
+ }, delayMs);
33
+ timers.set(handle, timer);
34
+ return handle;
35
+ }
36
+ };
37
+ }
38
+ const defaultWatchTarget = (target, options, listener) => watch(target, options, listener);
39
+ function isOwnArtifactEvent(changedPath, outputPath) {
40
+ if (changedPath === outputPath) {
41
+ return true;
42
+ }
43
+ const changedName = basename(changedPath);
44
+ const outputName = basename(outputPath);
45
+ return changedName.startsWith(`.${outputName}.`) && changedName.endsWith('.tmp');
46
+ }
47
+
48
+ /**
49
+ * Watches the application module directory while generating an initial current artifact.
50
+ *
51
+ * @param options Generation, watcher, scheduler, and signal lifecycle dependencies.
52
+ * @returns Exit code `0` after signal shutdown or `1` after an asynchronous watcher failure.
53
+ */
54
+ export async function runTypegenWatch(options) {
55
+ const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
56
+ const onError = options.onError ?? (() => undefined);
57
+ const scheduler = options.scheduler ?? createDefaultScheduler();
58
+ const signalTarget = options.signalTarget ?? process;
59
+ const watchTarget = options.watchTarget ?? defaultWatchTarget;
60
+ const watchRoot = dirname(options.modulePath);
61
+ let activeCommit;
62
+ let activeGeneration;
63
+ let cleanedUp = false;
64
+ let rerunRequested = false;
65
+ let resolved = false;
66
+ let restartTimer;
67
+ let stopping = false;
68
+ let stopCode = 0;
69
+ let watcher;
70
+ let startupComplete = false;
71
+ let resolveResult = () => undefined;
72
+ const result = new Promise(resolvePromise => {
73
+ resolveResult = resolvePromise;
74
+ });
75
+ const cleanup = () => {
76
+ if (cleanedUp) {
77
+ return;
78
+ }
79
+ cleanedUp = true;
80
+ if (restartTimer !== undefined) {
81
+ scheduler.clear(restartTimer);
82
+ restartTimer = undefined;
83
+ }
84
+ watcher?.close();
85
+ signalTarget.off('SIGINT', stopForSignal);
86
+ signalTarget.off('SIGTERM', stopForSignal);
87
+ };
88
+ const settleIfIdle = () => {
89
+ if (!stopping || activeGeneration !== undefined || resolved) {
90
+ return;
91
+ }
92
+ resolved = true;
93
+ resolveResult(stopCode);
94
+ };
95
+ const stop = code => {
96
+ stopCode = Math.max(stopCode, code);
97
+ if (!stopping) {
98
+ stopping = true;
99
+ cleanup();
100
+ activeCommit?.abort();
101
+ activeGeneration?.cancel();
102
+ }
103
+ settleIfIdle();
104
+ };
105
+ function stopForSignal() {
106
+ stop(0);
107
+ }
108
+ const runGeneration = async reportError => {
109
+ let generation;
110
+ try {
111
+ generation = options.startGeneration();
112
+ activeGeneration = generation;
113
+ const source = await generation.result;
114
+ if (!stopping && !rerunRequested) {
115
+ const commit = new AbortController();
116
+ activeCommit = commit;
117
+ try {
118
+ await options.commit(source, commit.signal);
119
+ } finally {
120
+ if (activeCommit === commit) {
121
+ activeCommit = undefined;
122
+ }
123
+ }
124
+ }
125
+ } catch (error) {
126
+ if (stopping || rerunRequested) {
127
+ return;
128
+ }
129
+ if (reportError) {
130
+ onError(error);
131
+ return;
132
+ }
133
+ throw error;
134
+ } finally {
135
+ if (activeGeneration === generation) {
136
+ activeGeneration = undefined;
137
+ settleIfIdle();
138
+ }
139
+ }
140
+ };
141
+ const regenerate = () => {
142
+ if (stopping) {
143
+ return;
144
+ }
145
+ if (activeGeneration !== undefined) {
146
+ rerunRequested = true;
147
+ return;
148
+ }
149
+ void (async () => {
150
+ do {
151
+ rerunRequested = false;
152
+ await runGeneration(true);
153
+ } while (rerunRequested && !stopping);
154
+ })();
155
+ };
156
+ const scheduleRegeneration = changedPath => {
157
+ if (stopping || isOwnArtifactEvent(changedPath, options.outputPath)) {
158
+ return;
159
+ }
160
+ if (activeGeneration !== undefined) {
161
+ rerunRequested = true;
162
+ activeCommit?.abort();
163
+ return;
164
+ }
165
+ if (!startupComplete) {
166
+ rerunRequested = true;
167
+ return;
168
+ }
169
+ if (restartTimer !== undefined) {
170
+ scheduler.clear(restartTimer);
171
+ }
172
+ restartTimer = scheduler.set(() => {
173
+ restartTimer = undefined;
174
+ regenerate();
175
+ }, debounceMs);
176
+ };
177
+ try {
178
+ watcher = watchTarget(watchRoot, {
179
+ persistent: true,
180
+ recursive: true
181
+ }, (_event, filename) => {
182
+ const changedPath = filename === null ? watchRoot : resolve(watchRoot, String(filename));
183
+ scheduleRegeneration(changedPath);
184
+ });
185
+ watcher.on('error', error => {
186
+ onError(error);
187
+ stop(1);
188
+ });
189
+ } catch (error) {
190
+ watcher?.close();
191
+ throw error;
192
+ }
193
+ try {
194
+ signalTarget.once('SIGINT', stopForSignal);
195
+ signalTarget.once('SIGTERM', stopForSignal);
196
+ await (async () => {
197
+ do {
198
+ rerunRequested = false;
199
+ await runGeneration(false);
200
+ } while (rerunRequested && !stopping);
201
+ })();
202
+ startupComplete = true;
203
+ if (stopping) {
204
+ return result;
205
+ }
206
+ options.onReady?.(watchRoot);
207
+ } catch (error) {
208
+ cleanup();
209
+ throw error;
210
+ }
211
+ return result;
212
+ }
@@ -0,0 +1,29 @@
1
+ import { type ReactTypegenModules } from './typegen-source.js';
2
+ type CliStream = {
3
+ write(message: string): unknown;
4
+ };
5
+ /** Runtime options for the React page typegen command. */
6
+ export interface TypegenCommandRuntimeOptions {
7
+ /** Current working directory for module and output path resolution. */
8
+ readonly cwd?: string;
9
+ /**
10
+ * Optional build-tooling module loader override for tests and editor integrations.
11
+ * Supplying it keeps application evaluation in the caller process and uses the returned
12
+ * namespaces for TypeScript and native modules; omitting it uses isolated generation children.
13
+ */
14
+ readonly loadReactTypegenModules?: (cwd: string) => Promise<ReactTypegenModules>;
15
+ /** Custom stream for error output. */
16
+ readonly stderr?: CliStream;
17
+ /** Custom stream for standard output. */
18
+ readonly stdout?: CliStream;
19
+ }
20
+ /**
21
+ * Generates, checks, or watches one application-owned React page type artifact.
22
+ *
23
+ * @param argv Command arguments after `typegen`.
24
+ * @param runtime Runtime overrides for module loading and output streams.
25
+ * @returns Process-style command exit code.
26
+ */
27
+ export declare function runTypegenCommand(argv: readonly string[], runtime?: TypegenCommandRuntimeOptions): Promise<number>;
28
+ export {};
29
+ //# sourceMappingURL=typegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typegen.d.ts","sourceRoot":"","sources":["../../src/commands/typegen.ts"],"names":[],"mappings":"AAcA,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAI7B,KAAK,SAAS,GAAG;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,0DAA0D;AAC1D,MAAM,WAAW,4BAA4B;IAC3C,uEAAuE;IACvE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACjF,sCAAsC;IACtC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;CAC7B;AA+BD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,MAAM,CAAC,CA2EjB"}
@@ -0,0 +1,119 @@
1
+ import { resolve } from 'node:path';
2
+ import { TYPEGEN_EXIT_CODES } from '../typegen-contract.js';
3
+ import { typegenUsage } from '../usage.js';
4
+ import { checkTypegenArtifact, writeTypegenArtifact } from './typegen-artifact.js';
5
+ import { runTypegenGenerationProcess, startTypegenGenerationProcess } from './typegen-generation-process.js';
6
+ import { parseTypegenArgs, TypegenCommandError } from './typegen-options.js';
7
+ import { createTypegenSource, inspectReactTypegenArtifact, loadReactTypegenModules } from './typegen-source.js';
8
+ import { runTypegenWatch } from './typegen-watch.js';
9
+ import { assertOutputDoesNotAliasModule } from './output-path-safety.js';
10
+
11
+ /** Runtime options for the React page typegen command. */
12
+
13
+ function reportCheckResult(check, outputPath, stdout, stderr) {
14
+ switch (check.status) {
15
+ case 'UNCHANGED':
16
+ stdout.write(`UNCHANGED ${outputPath}\n`);
17
+ return TYPEGEN_EXIT_CODES.SUCCESS;
18
+ case 'MISSING':
19
+ stderr.write(`MISSING ${outputPath}: run fluo typegen without --check to create the artifact.\n`);
20
+ return TYPEGEN_EXIT_CODES.MISSING;
21
+ case 'STALE':
22
+ stderr.write(`STALE ${outputPath}: generated React page types differ from the authoritative compiled catalog.\n`);
23
+ return TYPEGEN_EXIT_CODES.STALE;
24
+ case 'MALFORMED':
25
+ stderr.write(`MALFORMED ${outputPath}: the target is not a complete React page typegen artifact.\n`);
26
+ return TYPEGEN_EXIT_CODES.MALFORMED;
27
+ case 'UNSUPPORTED_VERSION':
28
+ stderr.write(`UNSUPPORTED_VERSION ${outputPath}: artifact version ${String(check.version)} is not supported by this CLI.\n`);
29
+ return TYPEGEN_EXIT_CODES.UNSUPPORTED_VERSION;
30
+ default:
31
+ {
32
+ const unreachable = check;
33
+ throw new TypegenCommandError(`Unexpected typegen check result: ${String(unreachable)}`);
34
+ }
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Generates, checks, or watches one application-owned React page type artifact.
40
+ *
41
+ * @param argv Command arguments after `typegen`.
42
+ * @param runtime Runtime overrides for module loading and output streams.
43
+ * @returns Process-style command exit code.
44
+ */
45
+ export async function runTypegenCommand(argv, runtime = {}) {
46
+ const cwd = runtime.cwd ?? process.cwd();
47
+ const stdout = runtime.stdout ?? process.stdout;
48
+ const stderr = runtime.stderr ?? process.stderr;
49
+ try {
50
+ if (argv.some(argument => argument === '--help' || argument === '-h')) {
51
+ stdout.write(`${typegenUsage()}\n`);
52
+ return 0;
53
+ }
54
+ const parsed = parseTypegenArgs(argv);
55
+ const modulePath = resolve(cwd, parsed.modulePath);
56
+ const outputPath = resolve(cwd, parsed.outputPath);
57
+ await assertOutputDoesNotAliasModule(modulePath, outputPath);
58
+ const customModules = runtime.loadReactTypegenModules?.(cwd);
59
+ const generateSource = async () => customModules === undefined ? runTypegenGenerationProcess({
60
+ cwd,
61
+ exportName: parsed.exportName,
62
+ modulePath: parsed.modulePath
63
+ }) : createTypegenSource({
64
+ cwd,
65
+ modules: await customModules,
66
+ parsed
67
+ });
68
+ if (parsed.watch) {
69
+ return await runTypegenWatch({
70
+ async commit(source, signal) {
71
+ const action = await writeTypegenArtifact(outputPath, source, undefined, signal);
72
+ stdout.write(`${action} ${outputPath}\n`);
73
+ },
74
+ modulePath,
75
+ onError(error) {
76
+ stderr.write(`ERROR ${outputPath}: ${error instanceof Error ? error.message : String(error)}\n`);
77
+ },
78
+ onReady(watchRoot) {
79
+ stdout.write(`WATCHING ${watchRoot}\n`);
80
+ },
81
+ outputPath,
82
+ startGeneration: customModules === undefined ? () => startTypegenGenerationProcess({
83
+ cwd,
84
+ exportName: parsed.exportName,
85
+ modulePath: parsed.modulePath
86
+ }) : () => {
87
+ let cancelled = false;
88
+ const result = generateSource().then(source => {
89
+ if (cancelled) {
90
+ throw new TypegenCommandError('Typegen generation was cancelled.');
91
+ }
92
+ return source;
93
+ });
94
+ return {
95
+ cancel() {
96
+ if (cancelled) {
97
+ return;
98
+ }
99
+ cancelled = true;
100
+ },
101
+ result
102
+ };
103
+ }
104
+ });
105
+ }
106
+ const source = await generateSource();
107
+ if (parsed.check) {
108
+ const modules = customModules === undefined ? await loadReactTypegenModules(cwd) : await customModules;
109
+ const check = await checkTypegenArtifact(outputPath, source, existingSource => inspectReactTypegenArtifact(modules, existingSource));
110
+ return reportCheckResult(check, outputPath, stdout, stderr);
111
+ }
112
+ const action = await writeTypegenArtifact(outputPath, source);
113
+ stdout.write(`${action} ${outputPath}\n`);
114
+ return TYPEGEN_EXIT_CODES.SUCCESS;
115
+ } catch (error) {
116
+ stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
117
+ return TYPEGEN_EXIT_CODES.ERROR;
118
+ }
119
+ }
@@ -19,6 +19,11 @@ type RestartSignalTarget = {
19
19
  type RestartWatcherFactory = (target: string, optionsOrListener: {
20
20
  recursive: boolean;
21
21
  } | ((event: string, filename: string | Buffer | null) => void), listener?: (event: string, filename: string | Buffer | null) => void) => FSWatcher;
22
+ type RestartSchedulerHandle = ReturnType<typeof setTimeout> | number;
23
+ type RestartScheduler = {
24
+ clear(handle: RestartSchedulerHandle): void;
25
+ set(callback: () => void, delayMs: number): RestartSchedulerHandle;
26
+ };
22
27
  type ContentChangeGate = {
23
28
  commitBaseline(paths: Iterable<string>): void;
24
29
  hasMeaningfulChange(paths: Iterable<string>): boolean;
@@ -33,6 +38,7 @@ export type NodeRestartRunnerOptions = {
33
38
  signalTarget?: RestartSignalTarget;
34
39
  spawnChild?: RestartChildSpawner;
35
40
  stderr?: RestartRunnerStream;
41
+ restartScheduler?: RestartScheduler;
36
42
  stdout?: RestartRunnerStream;
37
43
  watchTarget?: RestartWatcherFactory;
38
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"node-restart-runner.d.ts","sourceRoot":"","sources":["../../src/dev-runner/node-restart-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAA0D,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAKjG,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,KAAK,YAAY,CAAC;AACjJ,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,oBAAoB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9E,KAAK,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1C,KAAK,mBAAmB,GAAG;IACzB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IAC1D,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,KAAK,qBAAqB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,SAAS,CAAC;AAE1O,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CACvD,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC,CAAC;AA6NF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,gBAAgB,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAoB,GAAG,iBAAiB,CAuB/H;AAkFD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmP7F"}
1
+ {"version":3,"file":"node-restart-runner.d.ts","sourceRoot":"","sources":["../../src/dev-runner/node-restart-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAAc,KAAK,SAAS,EAA8C,MAAM,SAAS,CAAC;AAKjG,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEF,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,KAAK,YAAY,CAAC;AACjJ,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,oBAAoB,GAAG,MAAM,GAAG,MAAM,CAAC;AAE9E,KAAK,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1C,KAAK,mBAAmB,GAAG;IACzB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IAC1D,IAAI,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;CAC5D,CAAC;AAEF,KAAK,qBAAqB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,KAAK,IAAI,KAAK,SAAS,CAAC;AAE1O,KAAK,sBAAsB,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,MAAM,CAAC;AAErE,KAAK,gBAAgB,GAAG;IACtB,KAAK,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC5C,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAAC;CACpE,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC9C,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CACvD,CAAC;AAEF,uFAAuF;AACvF,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IACjC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC,CAAC;AA6NF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,gBAAgB,EAAE,MAAM,EAAE,cAAc,GAAE,MAAM,EAAoB,GAAG,iBAAiB,CAuB/H;AAkFD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwS7F"}
@@ -100,7 +100,7 @@ function parseIgnorePatterns(env) {
100
100
  return normalizeIgnorePatterns([...DEFAULT_IGNORES, ...configured]);
101
101
  }
102
102
  function matchesSegmentPattern(segment, pattern) {
103
- if (pattern.startsWith('*.')) {
103
+ if (pattern.startsWith('*')) {
104
104
  return segment.endsWith(pattern.slice(1));
105
105
  }
106
106
  if (pattern.endsWith('*')) {
@@ -205,7 +205,7 @@ export function createContentChangeGate(projectDirectory, ignorePatterns = DEFAU
205
205
  };
206
206
  }
207
207
  function getWatchTargets(projectDirectory) {
208
- return [join(projectDirectory, 'src'), ...WATCH_FILES.map(fileName => join(projectDirectory, fileName))].filter(target => existsSync(target));
208
+ return [join(projectDirectory, 'src'), ...WATCH_FILES.map(fileName => join(projectDirectory, fileName)).filter(target => existsSync(target))];
209
209
  }
210
210
  function stopChild(child, shutdownTimeoutMs = DEFAULT_CHILD_SHUTDOWN_TIMEOUT_MS) {
211
211
  if (child && child.exitCode === null) {
@@ -293,12 +293,17 @@ export async function runNodeRestartRunner(options) {
293
293
  const spawnChild = options.spawnChild ?? spawn;
294
294
  const stdout = options.stdout ?? process.stdout;
295
295
  const stderr = options.stderr ?? process.stderr;
296
+ const restartScheduler = options.restartScheduler ?? {
297
+ clear: clearTimeout,
298
+ set: setTimeout
299
+ };
296
300
  const watchTarget = options.watchTarget ?? watch;
297
301
  const appArgs = options.appArgs ?? [];
298
302
  const debounceMs = options.debounceMs ?? Number(env.FLUO_DEV_RELOAD_DEBOUNCE_MS ?? DEFAULT_DEBOUNCE_MS);
299
303
  const childShutdownTimeoutMs = Number(env.FLUO_DEV_CHILD_SHUTDOWN_TIMEOUT_MS ?? DEFAULT_CHILD_SHUTDOWN_TIMEOUT_MS);
300
304
  const ignorePatterns = parseIgnorePatterns(env);
301
305
  const gate = createContentChangeGate(projectDirectory, ignorePatterns);
306
+ const sourceDirectory = join(projectDirectory, 'src');
302
307
  const watchTargets = getWatchTargets(projectDirectory);
303
308
  let child;
304
309
  const pendingRestartPaths = new Set();
@@ -306,6 +311,7 @@ export async function runNodeRestartRunner(options) {
306
311
  let restartTimer;
307
312
  let restarting = false;
308
313
  let stopping = false;
314
+ let terminalExitCode;
309
315
  const startChild = (resolveExitCode, cleanup) => {
310
316
  ensureStudioEpoch(env);
311
317
  const appCommand = buildAppCommand(runnerRuntime, env, appArgs);
@@ -346,7 +352,7 @@ export async function runNodeRestartRunner(options) {
346
352
  reason: 'fluo dev runner stopped'
347
353
  });
348
354
  cleanup();
349
- resolveExitCode(code ?? 0);
355
+ resolveExitCode(terminalExitCode ?? code ?? 0);
350
356
  return;
351
357
  }
352
358
  publishStudioLifecycleEvent(env, runnerRuntime, 'disconnect', {
@@ -358,10 +364,10 @@ export async function runNodeRestartRunner(options) {
358
364
  };
359
365
  const scheduleRestart = (filePath, resolveExitCode, cleanup) => {
360
366
  pendingRestartPaths.add(filePath);
361
- if (restartTimer) {
362
- clearTimeout(restartTimer);
367
+ if (restartTimer !== undefined) {
368
+ restartScheduler.clear(restartTimer);
363
369
  }
364
- restartTimer = setTimeout(() => {
370
+ restartTimer = restartScheduler.set(() => {
365
371
  const restartPaths = [...pendingRestartPaths];
366
372
  pendingRestartPaths.clear();
367
373
  restartTimer = undefined;
@@ -445,8 +451,8 @@ export async function runNodeRestartRunner(options) {
445
451
  return;
446
452
  }
447
453
  cleanedUp = true;
448
- if (restartTimer) {
449
- clearTimeout(restartTimer);
454
+ if (restartTimer !== undefined) {
455
+ restartScheduler.clear(restartTimer);
450
456
  restartTimer = undefined;
451
457
  }
452
458
  pendingRestartPaths.clear();
@@ -457,11 +463,33 @@ export async function runNodeRestartRunner(options) {
457
463
  signalTarget.off('SIGINT', stop);
458
464
  signalTarget.off('SIGTERM', stop);
459
465
  };
466
+ const failFromWatcher = (target, error) => {
467
+ if (stopping || resolved) {
468
+ return;
469
+ }
470
+ terminalExitCode = 1;
471
+ stopping = true;
472
+ stderr.write(`[fluo] watcher failed for ${target}: ${error.message}\n`);
473
+ cleanup();
474
+ const stoppingChild = child;
475
+ if (!stoppingChild || stoppingChild.exitCode !== null) {
476
+ resolveOnce(terminalExitCode);
477
+ return;
478
+ }
479
+ stoppingChild.once('close', () => resolveOnce(1));
480
+ if (!restarting) {
481
+ stopChild(stoppingChild, childShutdownTimeoutMs);
482
+ }
483
+ };
484
+ const registerWatcher = (target, watcher) => {
485
+ watchers.push(watcher);
486
+ watcher.on?.('error', error => failFromWatcher(target, error));
487
+ };
460
488
  startChild(resolveExitCode, cleanup);
461
489
  const watchedFallbackDirectories = new Set();
462
490
  const watchFallbackDirectory = directoryPath => {
463
491
  if (watchedFallbackDirectories.has(directoryPath) || shouldIgnorePath(directoryPath, projectDirectory, ignorePatterns)) {
464
- return;
492
+ return false;
465
493
  }
466
494
  watchedFallbackDirectories.add(directoryPath);
467
495
  const listener = (_event, filename) => {
@@ -469,14 +497,22 @@ export async function runNodeRestartRunner(options) {
469
497
  const changedPath = filename ? join(directoryPath, fileName) : directoryPath;
470
498
  scheduleRestart(changedPath, resolveExitCode, cleanup);
471
499
  for (const nextDirectoryPath of getFallbackWatchDirectories(changedPath, projectDirectory, ignorePatterns)) {
472
- watchFallbackDirectory(nextDirectoryPath);
500
+ if (watchedFallbackDirectories.has(nextDirectoryPath) || shouldIgnorePath(nextDirectoryPath, projectDirectory, ignorePatterns)) {
501
+ continue;
502
+ }
503
+ if (!watchFallbackDirectory(nextDirectoryPath)) {
504
+ failFromWatcher(nextDirectoryPath, new Error('required fallback watcher could not be acquired'));
505
+ return;
506
+ }
473
507
  }
474
508
  };
475
509
  try {
476
- watchers.push(watchTarget(directoryPath, listener));
510
+ registerWatcher(directoryPath, watchTarget(directoryPath, listener));
511
+ return true;
477
512
  } catch (error) {
478
513
  watchedFallbackDirectories.delete(directoryPath);
479
514
  stderr.write(`[fluo] unable to watch ${directoryPath}: ${error instanceof Error ? error.message : String(error)}\n`);
515
+ return false;
480
516
  }
481
517
  };
482
518
  for (const target of watchTargets) {
@@ -490,16 +526,31 @@ export async function runNodeRestartRunner(options) {
490
526
  scheduleRestart(stats.isDirectory() ? join(target, fileName) : target, resolveExitCode, cleanup);
491
527
  };
492
528
  try {
493
- watchers.push(watchTarget(target, watchOptions, listener));
529
+ registerWatcher(target, watchTarget(target, watchOptions, listener));
494
530
  } catch (error) {
495
531
  if (!stats.isDirectory()) {
496
532
  throw error;
497
533
  }
534
+ let sourceCoverageAcquired = false;
498
535
  for (const directoryPath of getFallbackWatchDirectories(target, projectDirectory, ignorePatterns)) {
499
- watchFallbackDirectory(directoryPath);
536
+ if (!watchFallbackDirectory(directoryPath)) {
537
+ const message = error instanceof Error ? error.message : String(error);
538
+ failFromWatcher(target, new Error(`${message}; required fallback watcher could not be acquired`));
539
+ return;
540
+ }
541
+ sourceCoverageAcquired ||= directoryPath === target;
542
+ }
543
+ if (!sourceCoverageAcquired) {
544
+ const message = error instanceof Error ? error.message : String(error);
545
+ failFromWatcher(target, new Error(`${message}; required fallback watcher could not be acquired`));
546
+ return;
500
547
  }
501
548
  }
502
549
  } catch (error) {
550
+ if (target === sourceDirectory) {
551
+ failFromWatcher(target, error instanceof Error ? error : new Error(String(error)));
552
+ return;
553
+ }
503
554
  stderr.write(`[fluo] unable to watch ${target}: ${error instanceof Error ? error.message : String(error)}\n`);
504
555
  }
505
556
  }
@@ -0,0 +1,4 @@
1
+ /** Fixture application module used by build-less React route inspection tests. */
2
+ export declare class AppModule {
3
+ }
4
+ //# sourceMappingURL=inspect-react-app.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-react-app.module.d.ts","sourceRoot":"","sources":["../../src/fixtures/inspect-react-app.module.ts"],"names":[],"mappings":"AASA,kFAAkF;AAClF,qBAAa,SAAS;CAAG"}
@@ -0,0 +1,32 @@
1
+ let _initProto, _initClass;
2
+ function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
4
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
+ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
6
+ function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
7
+ import { defineModule } from '@fluojs/runtime';
8
+ import { Path, ReactModule, Router } from '@fluojs/react';
9
+ let _ProductRouter;
10
+ class ProductRouter {
11
+ static {
12
+ ({
13
+ e: [_initProto],
14
+ c: [_ProductRouter, _initClass]
15
+ } = _applyDecs(this, [Router('/products')], [[Path('/:productId'), 2, "show"]]));
16
+ }
17
+ constructor() {
18
+ _initProto(this);
19
+ }
20
+ show() {}
21
+ static {
22
+ _initClass();
23
+ }
24
+ }
25
+
26
+ /** Fixture application module used by build-less React route inspection tests. */
27
+ export class AppModule {}
28
+ defineModule(AppModule, {
29
+ imports: [ReactModule.forRoot({
30
+ controllers: [_ProductRouter]
31
+ })]
32
+ });
@@ -0,0 +1,4 @@
1
+ /** Fixture root module used by CLI React page typegen tests. */
2
+ export declare class AppModule {
3
+ }
4
+ //# sourceMappingURL=typegen-react-app.module.d.ts.map