@mandujs/core 0.54.12 → 0.54.13

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 (76) hide show
  1. package/package.json +9 -1
  2. package/scripts/postinstall-lock.ts +153 -153
  3. package/src/a11y/run-audit.ts +15 -15
  4. package/src/agent/__tests__/context.test.ts +49 -1
  5. package/src/agent/context.ts +535 -535
  6. package/src/agent/index.ts +6 -6
  7. package/src/agent/plan.ts +282 -282
  8. package/src/agent/repair.ts +171 -171
  9. package/src/agent/sync.ts +200 -200
  10. package/src/agent/types.ts +8 -0
  11. package/src/agent/verify.ts +100 -2
  12. package/src/brain/doctor/analyzer.ts +7 -7
  13. package/src/bundler/__tests__/build-runner.ts +5 -4
  14. package/src/bundler/__tests__/cold-start.test.ts +60 -60
  15. package/src/bundler/__tests__/css.test.ts +20 -20
  16. package/src/bundler/analyzer.ts +15 -15
  17. package/src/bundler/build.test.ts +66 -15
  18. package/src/bundler/build.ts +165 -103
  19. package/src/bundler/css.ts +42 -42
  20. package/src/bundler/manifest-schema.ts +21 -21
  21. package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +13 -13
  22. package/src/bundler/plugins/block-generated-imports.ts +13 -13
  23. package/src/bundler/types.ts +31 -31
  24. package/src/client/island.ts +79 -79
  25. package/src/config/validate.ts +1 -1
  26. package/src/contract/schema.ts +7 -0
  27. package/src/deploy/inference/context.ts +82 -82
  28. package/src/devtools/client/components/panel/islands-panel.tsx +16 -16
  29. package/src/devtools/client/components/panel/panel-container.tsx +1 -1
  30. package/src/error/formatter.ts +10 -1
  31. package/src/experimental/index.ts +10 -0
  32. package/src/filling/context.ts +17 -17
  33. package/src/filling/filling.ts +22 -1
  34. package/src/filling/index.ts +15 -1
  35. package/src/generator/generate.ts +30 -30
  36. package/src/generator/index.ts +3 -3
  37. package/src/generator/templates.ts +210 -210
  38. package/src/guard/check.ts +9 -9
  39. package/src/guard/config-guard.ts +13 -13
  40. package/src/guard/fs-routes-policy.ts +51 -51
  41. package/src/guard/index.ts +11 -11
  42. package/src/index.ts +0 -10
  43. package/src/internal/index.ts +25 -0
  44. package/src/kitchen/api/file-api.ts +11 -11
  45. package/src/report/index.ts +1 -1
  46. package/src/resource/__tests__/generator.test.ts +6 -6
  47. package/src/resource/__tests__/schema.test.ts +14 -14
  48. package/src/resource/ddl/__tests__/emit.test.ts +165 -165
  49. package/src/resource/ddl/emit.ts +146 -146
  50. package/src/resource/generator-schema.ts +11 -11
  51. package/src/resource/generators/slot.ts +72 -72
  52. package/src/resource/schema.ts +21 -21
  53. package/src/router/client-entry.test.ts +69 -33
  54. package/src/router/client-entry.ts +134 -74
  55. package/src/router/fs-routes.ts +24 -22
  56. package/src/router/fs-scanner.ts +21 -17
  57. package/src/router/fs-types.ts +8 -5
  58. package/src/runtime/__tests__/devtools-adapter.test.ts +68 -68
  59. package/src/runtime/__tests__/observability-lifecycle.test.ts +103 -103
  60. package/src/runtime/__tests__/page-render-response.test.ts +103 -103
  61. package/src/runtime/__tests__/request-middleware.test.ts +70 -70
  62. package/src/runtime/devtools-adapter.ts +68 -68
  63. package/src/runtime/escape.ts +34 -34
  64. package/src/runtime/image-feature.ts +15 -0
  65. package/src/runtime/observability-lifecycle.ts +290 -290
  66. package/src/runtime/page-render-response.ts +106 -106
  67. package/src/runtime/rate-limit.ts +231 -0
  68. package/src/runtime/request-middleware.ts +31 -31
  69. package/src/runtime/scheduler-lifecycle.ts +64 -0
  70. package/src/runtime/server.ts +27 -295
  71. package/src/runtime/ssr.ts +59 -59
  72. package/src/runtime/static-files.ts +289 -289
  73. package/src/runtime/streaming-ssr.ts +22 -22
  74. package/src/spec/schema.ts +4 -3
  75. package/src/watcher/__tests__/watcher.test.ts +59 -59
  76. package/src/watcher/watcher.ts +61 -61
@@ -1,59 +1,59 @@
1
- import { afterEach, expect, test } from "bun:test";
2
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "fs";
3
- import { tmpdir } from "os";
4
- import { join } from "path";
5
- import { hasRecentGenerateStamp } from "../watcher";
6
-
7
- const tmpRoots: string[] = [];
8
-
9
- function makeRoot(): string {
10
- const root = mkdtempSync(join(tmpdir(), "mandu-watch-"));
11
- tmpRoots.push(root);
12
- return root;
13
- }
14
-
15
- afterEach(() => {
16
- for (const root of tmpRoots.splice(0)) {
17
- rmSync(root, { recursive: true, force: true });
18
- }
19
- });
20
-
21
- test("hasRecentGenerateStamp suppresses generated events using the root stamp", () => {
22
- const root = makeRoot();
23
- const now = 1_700_000_000_000;
24
- mkdirSync(join(root, ".mandu"), { recursive: true });
25
- writeFileSync(join(root, ".mandu", "generate.stamp"), String(now - 500));
26
-
27
- const generatedFile = join(
28
- root,
29
- ".mandu",
30
- "generated",
31
- "server",
32
- "repos",
33
- "notification.repo.ts",
34
- );
35
-
36
- expect(hasRecentGenerateStamp(root, generatedFile, now)).toBe(true);
37
- });
38
-
39
- test("hasRecentGenerateStamp does not suppress stale generated events", () => {
40
- const root = makeRoot();
41
- const now = 1_700_000_000_000;
42
- mkdirSync(join(root, ".mandu"), { recursive: true });
43
- writeFileSync(join(root, ".mandu", "generate.stamp"), String(now - 30_000));
44
-
45
- const generatedFile = join(root, ".mandu", "generated", "server", "old.route.ts");
46
-
47
- expect(hasRecentGenerateStamp(root, generatedFile, now)).toBe(false);
48
- });
49
-
50
- test("hasRecentGenerateStamp does not suppress source files after generation", () => {
51
- const root = makeRoot();
52
- const now = 1_700_000_000_000;
53
- mkdirSync(join(root, ".mandu"), { recursive: true });
54
- writeFileSync(join(root, ".mandu", "generate.stamp"), String(now - 500));
55
-
56
- const sourceFile = join(root, "app", "page.tsx");
57
-
58
- expect(hasRecentGenerateStamp(root, sourceFile, now)).toBe(false);
59
- });
1
+ import { afterEach, expect, test } from "bun:test";
2
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "fs";
3
+ import { tmpdir } from "os";
4
+ import { join } from "path";
5
+ import { hasRecentGenerateStamp } from "../watcher";
6
+
7
+ const tmpRoots: string[] = [];
8
+
9
+ function makeRoot(): string {
10
+ const root = mkdtempSync(join(tmpdir(), "mandu-watch-"));
11
+ tmpRoots.push(root);
12
+ return root;
13
+ }
14
+
15
+ afterEach(() => {
16
+ for (const root of tmpRoots.splice(0)) {
17
+ rmSync(root, { recursive: true, force: true });
18
+ }
19
+ });
20
+
21
+ test("hasRecentGenerateStamp suppresses generated events using the root stamp", () => {
22
+ const root = makeRoot();
23
+ const now = 1_700_000_000_000;
24
+ mkdirSync(join(root, ".mandu"), { recursive: true });
25
+ writeFileSync(join(root, ".mandu", "generate.stamp"), String(now - 500));
26
+
27
+ const generatedFile = join(
28
+ root,
29
+ ".mandu",
30
+ "generated",
31
+ "server",
32
+ "repos",
33
+ "notification.repo.ts",
34
+ );
35
+
36
+ expect(hasRecentGenerateStamp(root, generatedFile, now)).toBe(true);
37
+ });
38
+
39
+ test("hasRecentGenerateStamp does not suppress stale generated events", () => {
40
+ const root = makeRoot();
41
+ const now = 1_700_000_000_000;
42
+ mkdirSync(join(root, ".mandu"), { recursive: true });
43
+ writeFileSync(join(root, ".mandu", "generate.stamp"), String(now - 30_000));
44
+
45
+ const generatedFile = join(root, ".mandu", "generated", "server", "old.route.ts");
46
+
47
+ expect(hasRecentGenerateStamp(root, generatedFile, now)).toBe(false);
48
+ });
49
+
50
+ test("hasRecentGenerateStamp does not suppress source files after generation", () => {
51
+ const root = makeRoot();
52
+ const now = 1_700_000_000_000;
53
+ mkdirSync(join(root, ".mandu"), { recursive: true });
54
+ writeFileSync(join(root, ".mandu", "generate.stamp"), String(now - 500));
55
+
56
+ const sourceFile = join(root, "app", "page.tsx");
57
+
58
+ expect(hasRecentGenerateStamp(root, sourceFile, now)).toBe(false);
59
+ });
@@ -61,63 +61,63 @@ const DEFAULT_CONFIG: Partial<WatcherConfig> = {
61
61
  * These cause EISDIR/ENOENT errors when file watchers try to access them.
62
62
  * See: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
63
63
  */
64
- const WINDOWS_RESERVED_NAMES = new Set([
65
- "CON", "PRN", "AUX", "NUL",
66
- "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
67
- "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
68
- ]);
69
-
70
- const GENERATE_STAMP_SUPPRESS_MS = 10_000;
71
-
72
- function readGenerateStamp(stampFile: string): number | null {
73
- try {
74
- const stamp = Number.parseInt(fs.readFileSync(stampFile, "utf-8"), 10);
75
- return Number.isFinite(stamp) ? stamp : null;
76
- } catch {
77
- return null;
78
- }
79
- }
80
-
81
- function isManduGeneratedPath(rootDir: string, filePath: string): boolean {
82
- const relativePath = path.relative(rootDir, filePath).replace(/\\/g, "/");
83
- return relativePath === ".mandu/generated" || relativePath.startsWith(".mandu/generated/");
84
- }
85
-
86
- export function hasRecentGenerateStamp(
87
- rootDir: string,
88
- filePath: string,
89
- now: number = Date.now()
90
- ): boolean {
91
- if (!isManduGeneratedPath(rootDir, filePath)) {
92
- return false;
93
- }
94
-
95
- const candidates = new Set<string>([
96
- path.join(rootDir, ".mandu", "generate.stamp"),
97
- ]);
98
- const resolvedRoot = path.resolve(rootDir);
99
- let stampDir = path.dirname(path.resolve(filePath));
100
-
101
- while (stampDir !== path.dirname(stampDir)) {
102
- candidates.add(path.join(stampDir, ".mandu", "generate.stamp"));
103
- if (stampDir === resolvedRoot) break;
104
- stampDir = path.dirname(stampDir);
105
- }
106
-
107
- for (const stampFile of candidates) {
108
- const stamp = readGenerateStamp(stampFile);
109
- if (stamp === null) continue;
110
-
111
- const ageMs = now - stamp;
112
- if (ageMs >= 0 && ageMs < GENERATE_STAMP_SUPPRESS_MS) {
113
- return true;
114
- }
115
- }
116
-
117
- return false;
118
- }
119
-
120
- export class FileWatcher {
64
+ const WINDOWS_RESERVED_NAMES = new Set([
65
+ "CON", "PRN", "AUX", "NUL",
66
+ "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
67
+ "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
68
+ ]);
69
+
70
+ const GENERATE_STAMP_SUPPRESS_MS = 10_000;
71
+
72
+ function readGenerateStamp(stampFile: string): number | null {
73
+ try {
74
+ const stamp = Number.parseInt(fs.readFileSync(stampFile, "utf-8"), 10);
75
+ return Number.isFinite(stamp) ? stamp : null;
76
+ } catch {
77
+ return null;
78
+ }
79
+ }
80
+
81
+ function isManduGeneratedPath(rootDir: string, filePath: string): boolean {
82
+ const relativePath = path.relative(rootDir, filePath).replace(/\\/g, "/");
83
+ return relativePath === ".mandu/generated" || relativePath.startsWith(".mandu/generated/");
84
+ }
85
+
86
+ export function hasRecentGenerateStamp(
87
+ rootDir: string,
88
+ filePath: string,
89
+ now: number = Date.now()
90
+ ): boolean {
91
+ if (!isManduGeneratedPath(rootDir, filePath)) {
92
+ return false;
93
+ }
94
+
95
+ const candidates = new Set<string>([
96
+ path.join(rootDir, ".mandu", "generate.stamp"),
97
+ ]);
98
+ const resolvedRoot = path.resolve(rootDir);
99
+ let stampDir = path.dirname(path.resolve(filePath));
100
+
101
+ while (stampDir !== path.dirname(stampDir)) {
102
+ candidates.add(path.join(stampDir, ".mandu", "generate.stamp"));
103
+ if (stampDir === resolvedRoot) break;
104
+ stampDir = path.dirname(stampDir);
105
+ }
106
+
107
+ for (const stampFile of candidates) {
108
+ const stamp = readGenerateStamp(stampFile);
109
+ if (stamp === null) continue;
110
+
111
+ const ageMs = now - stamp;
112
+ if (ageMs >= 0 && ageMs < GENERATE_STAMP_SUPPRESS_MS) {
113
+ return true;
114
+ }
115
+ }
116
+
117
+ return false;
118
+ }
119
+
120
+ export class FileWatcher {
121
121
  private config: WatcherConfig;
122
122
  private chokidarWatcher: FSWatcher | null = null;
123
123
  private handlers: Set<WatchEventHandler> = new Set();
@@ -361,10 +361,10 @@ export class FileWatcher {
361
361
 
362
362
  const { rootDir } = this.config;
363
363
 
364
- // Cross-process: skip generated-file churn from a recent mandu generate.
365
- if (hasRecentGenerateStamp(rootDir, filePath)) return;
366
-
367
- // Validate file against rules
364
+ // Cross-process: skip generated-file churn from a recent mandu generate.
365
+ if (hasRecentGenerateStamp(rootDir, filePath)) return;
366
+
367
+ // Validate file against rules
368
368
  try {
369
369
  const warnings = await validateFile(filePath, event, rootDir);
370
370