@mandujs/core 0.22.0 → 0.23.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.
- package/package.json +8 -1
- package/src/config/mandu.ts +172 -110
- package/src/config/validate.ts +357 -290
- package/src/desktop/__tests__/webview-fallback.test.ts +254 -0
- package/src/desktop/__tests__/window.test.ts +79 -3
- package/src/desktop/webview-fallback.ts +583 -0
- package/src/desktop/window.ts +527 -492
- package/src/perf/hmr-markers.ts +12 -0
- package/src/runtime/server.ts +133 -8
- package/src/testing/db.ts +157 -0
- package/src/testing/index.ts +59 -1
- package/src/testing/mocks.ts +203 -0
- package/src/testing/server.ts +196 -0
- package/src/testing/session.ts +190 -0
- package/src/testing/snapshot.ts +444 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mandujs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -28,9 +28,16 @@
|
|
|
28
28
|
"./id": "./src/id/index.ts",
|
|
29
29
|
"./observability": "./src/observability/index.ts",
|
|
30
30
|
"./perf": "./src/perf/index.ts",
|
|
31
|
+
"./perf/hmr-markers": "./src/perf/hmr-markers.ts",
|
|
31
32
|
"./scheduler": "./src/scheduler/index.ts",
|
|
32
33
|
"./storage/s3": "./src/storage/s3/index.ts",
|
|
33
34
|
"./bundler/prerender": "./src/bundler/prerender.ts",
|
|
35
|
+
"./bundler/safe-build": "./src/bundler/safe-build.ts",
|
|
36
|
+
"./bundler/hmr-types": "./src/bundler/hmr-types.ts",
|
|
37
|
+
"./bundler/scenario-matrix": "./src/bundler/scenario-matrix.ts",
|
|
38
|
+
"./bundler/vendor-cache-types": "./src/bundler/vendor-cache-types.ts",
|
|
39
|
+
"./bundler/manifest-schema": "./src/bundler/manifest-schema.ts",
|
|
40
|
+
"./runtime/fast-refresh-types": "./src/runtime/fast-refresh-types.ts",
|
|
34
41
|
"./*": "./src/*"
|
|
35
42
|
},
|
|
36
43
|
"files": [
|
package/src/config/mandu.ts
CHANGED
|
@@ -1,110 +1,172 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import { readJsonFile } from "../utils/bun";
|
|
3
|
-
import type { ManduAdapter } from "../runtime/adapter";
|
|
4
|
-
import type { ManduPlugin, ManduHooks } from "../plugins/hooks";
|
|
5
|
-
|
|
6
|
-
export type GuardRuleSeverity = "error" | "warn" | "warning" | "off";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { readJsonFile } from "../utils/bun";
|
|
3
|
+
import type { ManduAdapter } from "../runtime/adapter";
|
|
4
|
+
import type { ManduPlugin, ManduHooks } from "../plugins/hooks";
|
|
5
|
+
|
|
6
|
+
export type GuardRuleSeverity = "error" | "warn" | "warning" | "off";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Test block configuration (Phase 12.1 — testing ecosystem).
|
|
10
|
+
*
|
|
11
|
+
* Shapes the CLI `mandu test` command's discovery, fixture, and reporter
|
|
12
|
+
* behaviour. All fields are optional; omitting the block yields sensible
|
|
13
|
+
* defaults that match Next.js / SvelteKit user expectations:
|
|
14
|
+
*
|
|
15
|
+
* - unit → `**\/*.test.ts` / `**\/*.test.tsx`, 30s timeout
|
|
16
|
+
* - integration → `tests/integration/**\/*.test.ts`, in-memory fixtures
|
|
17
|
+
* - e2e → reserved for Phase 12.2 (ATE integration)
|
|
18
|
+
* - coverage → reserved for Phase 12.3 (bun + playwright merge)
|
|
19
|
+
*/
|
|
20
|
+
export interface TestUnitConfig {
|
|
21
|
+
/** Glob patterns for unit test files. Default: `["**\/*.test.ts", "**\/*.test.tsx"]`. */
|
|
22
|
+
include?: string[];
|
|
23
|
+
/** Glob patterns to exclude (applied after `include`). Default: `["node_modules/**", ".mandu/**", "dist/**"]`. */
|
|
24
|
+
exclude?: string[];
|
|
25
|
+
/** Per-test timeout in milliseconds. Default: `30_000` (30s). */
|
|
26
|
+
timeout?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TestIntegrationConfig {
|
|
30
|
+
/** Glob patterns for integration test files. Default: `["tests/integration/**\/*.test.ts"]`. */
|
|
31
|
+
include?: string[];
|
|
32
|
+
/** Glob patterns to exclude. Default: same as unit defaults. */
|
|
33
|
+
exclude?: string[];
|
|
34
|
+
/**
|
|
35
|
+
* Database URL for fixtures. Default: `"sqlite::memory:"` (in-memory SQLite).
|
|
36
|
+
* Accepts any Bun.sql-compatible URL — see `@mandujs/core/db` for the schema matrix.
|
|
37
|
+
*/
|
|
38
|
+
dbUrl?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Session storage strategy for `createTestSession`.
|
|
41
|
+
* - `"memory"` (default): CookieSessionStorage with ephemeral secret
|
|
42
|
+
* - `"sqlite"`: bun:sqlite-backed (Phase 2.5 storage, requires Phase 4)
|
|
43
|
+
*/
|
|
44
|
+
sessionStore?: "memory" | "sqlite";
|
|
45
|
+
/** Per-test timeout. Default: `60_000` (60s — integration work is slower). */
|
|
46
|
+
timeout?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface TestE2EConfig {
|
|
50
|
+
/** Reserved for Phase 12.2. Currently a typed placeholder. */
|
|
51
|
+
reserved?: true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface TestCoverageConfig {
|
|
55
|
+
/** Minimum line coverage percentage (0-100). Reserved for Phase 12.3. */
|
|
56
|
+
lines?: number;
|
|
57
|
+
/** Minimum branch coverage percentage (0-100). Reserved for Phase 12.3. */
|
|
58
|
+
branches?: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface TestConfig {
|
|
62
|
+
unit?: TestUnitConfig;
|
|
63
|
+
integration?: TestIntegrationConfig;
|
|
64
|
+
e2e?: TestE2EConfig;
|
|
65
|
+
coverage?: TestCoverageConfig;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ManduConfig {
|
|
69
|
+
adapter?: ManduAdapter;
|
|
70
|
+
server?: {
|
|
71
|
+
port?: number;
|
|
72
|
+
hostname?: string;
|
|
73
|
+
cors?:
|
|
74
|
+
| boolean
|
|
75
|
+
| {
|
|
76
|
+
origin?: string | string[];
|
|
77
|
+
methods?: string[];
|
|
78
|
+
credentials?: boolean;
|
|
79
|
+
};
|
|
80
|
+
streaming?: boolean;
|
|
81
|
+
rateLimit?:
|
|
82
|
+
| boolean
|
|
83
|
+
| {
|
|
84
|
+
windowMs?: number;
|
|
85
|
+
max?: number;
|
|
86
|
+
message?: string;
|
|
87
|
+
statusCode?: number;
|
|
88
|
+
headers?: boolean;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
guard?: {
|
|
92
|
+
preset?: "mandu" | "fsd" | "clean" | "hexagonal" | "atomic" | "cqrs";
|
|
93
|
+
srcDir?: string;
|
|
94
|
+
exclude?: string[];
|
|
95
|
+
realtime?: boolean;
|
|
96
|
+
rules?: Record<string, GuardRuleSeverity>;
|
|
97
|
+
contractRequired?: GuardRuleSeverity;
|
|
98
|
+
};
|
|
99
|
+
build?: {
|
|
100
|
+
outDir?: string;
|
|
101
|
+
minify?: boolean;
|
|
102
|
+
sourcemap?: boolean;
|
|
103
|
+
splitting?: boolean;
|
|
104
|
+
};
|
|
105
|
+
dev?: {
|
|
106
|
+
hmr?: boolean;
|
|
107
|
+
watchDirs?: string[];
|
|
108
|
+
/** Observability SQLite 영구 저장 (기본: true) */
|
|
109
|
+
observability?: boolean;
|
|
110
|
+
};
|
|
111
|
+
fsRoutes?: {
|
|
112
|
+
routesDir?: string;
|
|
113
|
+
extensions?: string[];
|
|
114
|
+
exclude?: string[];
|
|
115
|
+
islandSuffix?: string;
|
|
116
|
+
};
|
|
117
|
+
seo?: {
|
|
118
|
+
enabled?: boolean;
|
|
119
|
+
defaultTitle?: string;
|
|
120
|
+
titleTemplate?: string;
|
|
121
|
+
};
|
|
122
|
+
/** Phase 12.1 — `mandu test` configuration block. */
|
|
123
|
+
test?: TestConfig;
|
|
124
|
+
plugins?: ManduPlugin[];
|
|
125
|
+
hooks?: Partial<ManduHooks>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export const CONFIG_FILES = [
|
|
129
|
+
"mandu.config.ts",
|
|
130
|
+
"mandu.config.js",
|
|
131
|
+
"mandu.config.json",
|
|
132
|
+
path.join(".mandu", "guard.json"),
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
export function coerceConfig(raw: unknown, source: string): ManduConfig {
|
|
136
|
+
if (!raw || typeof raw !== "object") return {};
|
|
137
|
+
|
|
138
|
+
// .mandu/guard.json can be guard-only
|
|
139
|
+
if (source.endsWith("guard.json") && !("guard" in (raw as Record<string, unknown>))) {
|
|
140
|
+
return { guard: raw as ManduConfig["guard"] };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return raw as ManduConfig;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export async function loadManduConfig(rootDir: string): Promise<ManduConfig> {
|
|
147
|
+
for (const fileName of CONFIG_FILES) {
|
|
148
|
+
const filePath = path.join(rootDir, fileName);
|
|
149
|
+
if (!(await Bun.file(filePath).exists())) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (fileName.endsWith(".json")) {
|
|
154
|
+
try {
|
|
155
|
+
const parsed = await readJsonFile(filePath);
|
|
156
|
+
return coerceConfig(parsed, fileName);
|
|
157
|
+
} catch {
|
|
158
|
+
return {};
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const module = await import(filePath);
|
|
164
|
+
const raw = module?.default ?? module;
|
|
165
|
+
return coerceConfig(raw, fileName);
|
|
166
|
+
} catch {
|
|
167
|
+
return {};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {};
|
|
172
|
+
}
|