@mandujs/core 0.12.1 → 0.13.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/README.ko.md +304 -304
- package/README.md +653 -653
- package/package.json +8 -8
- package/src/brain/architecture/analyzer.ts +28 -26
- package/src/brain/doctor/analyzer.ts +1 -1
- package/src/bundler/build.ts +91 -91
- package/src/bundler/css.ts +302 -302
- package/src/bundler/dev.ts +0 -1
- package/src/change/history.ts +3 -3
- package/src/change/snapshot.ts +10 -9
- package/src/change/transaction.ts +2 -2
- package/src/client/Link.tsx +227 -227
- package/src/client/globals.ts +44 -44
- package/src/client/hooks.ts +267 -267
- package/src/client/index.ts +5 -5
- package/src/client/island.ts +8 -8
- package/src/client/router.ts +435 -435
- package/src/client/runtime.ts +23 -23
- package/src/client/serialize.ts +404 -404
- package/src/client/window-state.ts +101 -101
- package/src/config/mandu.ts +94 -96
- package/src/config/validate.ts +213 -215
- package/src/config/watcher.ts +311 -311
- package/src/constants.ts +40 -40
- package/src/content/content-layer.ts +314 -314
- package/src/content/content.test.ts +433 -433
- package/src/content/data-store.ts +245 -245
- package/src/content/digest.ts +133 -133
- package/src/content/index.ts +164 -164
- package/src/content/loader-context.ts +172 -172
- package/src/content/loaders/api.ts +216 -216
- package/src/content/loaders/file.ts +169 -169
- package/src/content/loaders/glob.ts +252 -252
- package/src/content/loaders/index.ts +34 -34
- package/src/content/loaders/types.ts +137 -137
- package/src/content/meta-store.ts +209 -209
- package/src/content/types.ts +282 -282
- package/src/content/watcher.ts +135 -135
- package/src/contract/client-safe.test.ts +42 -42
- package/src/contract/client-safe.ts +114 -114
- package/src/contract/client.ts +16 -16
- package/src/contract/define.ts +459 -459
- package/src/contract/handler.ts +10 -10
- package/src/contract/normalize.test.ts +276 -276
- package/src/contract/normalize.ts +404 -404
- package/src/contract/registry.test.ts +206 -206
- package/src/contract/registry.ts +568 -568
- package/src/contract/schema.ts +48 -48
- package/src/contract/types.ts +58 -58
- package/src/contract/validator.ts +32 -32
- package/src/devtools/ai/context-builder.ts +375 -375
- package/src/devtools/ai/index.ts +25 -25
- package/src/devtools/ai/mcp-connector.ts +465 -465
- package/src/devtools/client/catchers/error-catcher.ts +327 -327
- package/src/devtools/client/catchers/index.ts +18 -18
- package/src/devtools/client/catchers/network-proxy.ts +363 -363
- package/src/devtools/client/components/index.ts +39 -39
- package/src/devtools/client/components/kitchen-root.tsx +362 -362
- package/src/devtools/client/components/mandu-character.tsx +241 -241
- package/src/devtools/client/components/overlay.tsx +368 -368
- package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
- package/src/devtools/client/components/panel/guard-panel.tsx +244 -244
- package/src/devtools/client/components/panel/index.ts +32 -32
- package/src/devtools/client/components/panel/islands-panel.tsx +304 -304
- package/src/devtools/client/components/panel/network-panel.tsx +292 -292
- package/src/devtools/client/components/panel/panel-container.tsx +259 -259
- package/src/devtools/client/filters/context-filters.ts +282 -282
- package/src/devtools/client/filters/index.ts +16 -16
- package/src/devtools/client/index.ts +63 -63
- package/src/devtools/client/persistence.ts +335 -335
- package/src/devtools/client/state-manager.ts +478 -478
- package/src/devtools/design-tokens.ts +263 -263
- package/src/devtools/hook/create-hook.ts +207 -207
- package/src/devtools/hook/index.ts +13 -13
- package/src/devtools/index.ts +439 -439
- package/src/devtools/init.ts +266 -266
- package/src/devtools/protocol.ts +237 -237
- package/src/devtools/server/index.ts +17 -17
- package/src/devtools/server/source-context.ts +444 -444
- package/src/devtools/types.ts +319 -319
- package/src/devtools/worker/index.ts +25 -25
- package/src/devtools/worker/redaction-worker.ts +222 -222
- package/src/devtools/worker/worker-manager.ts +409 -409
- package/src/error/classifier.ts +2 -2
- package/src/error/domains.ts +265 -265
- package/src/error/formatter.ts +32 -32
- package/src/error/result.ts +46 -46
- package/src/error/stack-analyzer.ts +5 -0
- package/src/error/types.ts +6 -6
- package/src/errors/extractor.ts +409 -409
- package/src/errors/index.ts +19 -19
- package/src/filling/auth.ts +308 -308
- package/src/filling/context.ts +569 -569
- package/src/filling/deps.ts +238 -238
- package/src/generator/contract-glue.ts +2 -1
- package/src/generator/generate.ts +12 -10
- package/src/generator/index.ts +3 -3
- package/src/generator/templates.ts +80 -79
- package/src/guard/analyzer.ts +360 -360
- package/src/guard/ast-analyzer.ts +806 -806
- package/src/guard/auto-correct.ts +1 -1
- package/src/guard/check.ts +128 -128
- package/src/guard/contract-guard.ts +9 -9
- package/src/guard/file-type.test.ts +24 -24
- package/src/guard/healing.ts +2 -0
- package/src/guard/index.ts +2 -0
- package/src/guard/negotiation.ts +430 -4
- package/src/guard/presets/atomic.ts +70 -70
- package/src/guard/presets/clean.ts +77 -77
- package/src/guard/presets/cqrs.test.ts +175 -0
- package/src/guard/presets/cqrs.ts +107 -0
- package/src/guard/presets/fsd.ts +79 -79
- package/src/guard/presets/hexagonal.ts +68 -68
- package/src/guard/presets/index.ts +291 -288
- package/src/guard/reporter.ts +445 -445
- package/src/guard/rules.ts +12 -12
- package/src/guard/statistics.ts +578 -578
- package/src/guard/suggestions.ts +358 -352
- package/src/guard/types.ts +348 -347
- package/src/guard/validator.ts +834 -834
- package/src/guard/watcher.ts +404 -404
- package/src/index.ts +1 -0
- package/src/intent/index.ts +310 -310
- package/src/island/index.ts +304 -304
- package/src/logging/index.ts +22 -22
- package/src/logging/transports.ts +365 -365
- package/src/paths.test.ts +47 -0
- package/src/paths.ts +47 -0
- package/src/plugins/index.ts +38 -38
- package/src/plugins/registry.ts +377 -377
- package/src/plugins/types.ts +363 -363
- package/src/report/build.ts +1 -1
- package/src/report/index.ts +1 -1
- package/src/router/fs-patterns.ts +387 -387
- package/src/router/fs-routes.ts +344 -401
- package/src/router/fs-scanner.ts +497 -497
- package/src/router/fs-types.ts +270 -278
- package/src/router/index.ts +81 -81
- package/src/runtime/boundary.tsx +232 -232
- package/src/runtime/compose.ts +222 -222
- package/src/runtime/lifecycle.ts +381 -381
- package/src/runtime/logger.test.ts +345 -345
- package/src/runtime/logger.ts +677 -677
- package/src/runtime/router.test.ts +476 -476
- package/src/runtime/router.ts +105 -105
- package/src/runtime/security.ts +155 -155
- package/src/runtime/server.ts +24 -24
- package/src/runtime/session-key.ts +328 -328
- package/src/runtime/ssr.ts +367 -367
- package/src/runtime/streaming-ssr.ts +1245 -1245
- package/src/runtime/trace.ts +144 -144
- package/src/seo/index.ts +214 -214
- package/src/seo/integration/ssr.ts +307 -307
- package/src/seo/render/basic.ts +427 -427
- package/src/seo/render/index.ts +143 -143
- package/src/seo/render/jsonld.ts +539 -539
- package/src/seo/render/opengraph.ts +191 -191
- package/src/seo/render/robots.ts +116 -116
- package/src/seo/render/sitemap.ts +137 -137
- package/src/seo/render/twitter.ts +126 -126
- package/src/seo/resolve/index.ts +353 -353
- package/src/seo/resolve/opengraph.ts +143 -143
- package/src/seo/resolve/robots.ts +73 -73
- package/src/seo/resolve/title.ts +94 -94
- package/src/seo/resolve/twitter.ts +73 -73
- package/src/seo/resolve/url.ts +97 -97
- package/src/seo/routes/index.ts +290 -290
- package/src/seo/types.ts +575 -575
- package/src/slot/validator.ts +39 -39
- package/src/spec/index.ts +3 -3
- package/src/spec/load.ts +76 -76
- package/src/spec/lock.ts +56 -56
- package/src/utils/bun.ts +8 -8
- package/src/utils/lru-cache.ts +75 -75
- package/src/utils/safe-io.ts +188 -188
- package/src/utils/string-safe.ts +298 -298
- package/src/watcher/rules.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mandujs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"src/**/*"
|
|
15
15
|
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "bun test tests/streaming-ssr && bun test tests/hydration tests/typing src",
|
|
18
|
+
"test:hydration": "bun test tests/hydration",
|
|
19
|
+
"test:streaming": "bun test tests/streaming-ssr",
|
|
20
|
+
"test:watch": "bun test --watch"
|
|
21
|
+
},
|
|
16
22
|
"devDependencies": {
|
|
17
23
|
"@happy-dom/global-registrator": "^15.0.0"
|
|
18
24
|
},
|
|
@@ -47,11 +53,5 @@
|
|
|
47
53
|
"glob": "^13.0.0",
|
|
48
54
|
"minimatch": "^10.1.1",
|
|
49
55
|
"ollama": "^0.6.3"
|
|
50
|
-
},
|
|
51
|
-
"scripts": {
|
|
52
|
-
"test": "bun test tests/streaming-ssr && bun test tests/hydration tests/typing src",
|
|
53
|
-
"test:hydration": "bun test tests/hydration",
|
|
54
|
-
"test:streaming": "bun test tests/streaming-ssr",
|
|
55
|
-
"test:watch": "bun test --watch"
|
|
56
56
|
}
|
|
57
|
-
}
|
|
57
|
+
}
|
|
@@ -46,22 +46,24 @@ export const DEFAULT_ARCHITECTURE_CONFIG: ArchitectureConfig = {
|
|
|
46
46
|
description: "자동 생성 파일. 직접 수정 금지",
|
|
47
47
|
readonly: true,
|
|
48
48
|
},
|
|
49
|
-
"
|
|
50
|
-
pattern: "
|
|
51
|
-
description: "
|
|
49
|
+
".mandu/generated/server/": {
|
|
50
|
+
pattern: ".mandu/generated/server/**",
|
|
51
|
+
description: "서버 생성 파일",
|
|
52
52
|
allowedFiles: ["*.ts"],
|
|
53
|
+
readonly: true,
|
|
53
54
|
},
|
|
54
|
-
"
|
|
55
|
-
pattern: "
|
|
56
|
-
description: "
|
|
55
|
+
".mandu/generated/web/": {
|
|
56
|
+
pattern: ".mandu/generated/web/**",
|
|
57
|
+
description: "웹 생성 파일",
|
|
57
58
|
allowedFiles: ["*.ts", "*.tsx"],
|
|
59
|
+
readonly: true,
|
|
58
60
|
},
|
|
59
61
|
},
|
|
60
62
|
imports: [
|
|
61
63
|
{
|
|
62
|
-
source: "
|
|
64
|
+
source: ".mandu/generated/web/**",
|
|
63
65
|
forbid: ["fs", "child_process", "path", "crypto"],
|
|
64
|
-
reason: "
|
|
66
|
+
reason: "프론트엔드 생성 파일에서 Node.js 내장 모듈 사용 금지",
|
|
65
67
|
},
|
|
66
68
|
{
|
|
67
69
|
source: "**/generated/**",
|
|
@@ -87,7 +89,7 @@ export const DEFAULT_ARCHITECTURE_CONFIG: ArchitectureConfig = {
|
|
|
87
89
|
},
|
|
88
90
|
{
|
|
89
91
|
name: "app",
|
|
90
|
-
folders: ["
|
|
92
|
+
folders: ["app/**", "src/**"],
|
|
91
93
|
canDependOn: ["spec", "generated"],
|
|
92
94
|
},
|
|
93
95
|
],
|
|
@@ -173,9 +175,9 @@ export class ArchitectureAnalyzer {
|
|
|
173
175
|
/**
|
|
174
176
|
* 파일 위치 검증
|
|
175
177
|
*/
|
|
176
|
-
async checkLocation(request: CheckLocationRequest): Promise<CheckLocationResult> {
|
|
177
|
-
const violations: ArchitectureViolation[] = [];
|
|
178
|
-
const normalizedPath = this.toRelativePath(request.path);
|
|
178
|
+
async checkLocation(request: CheckLocationRequest): Promise<CheckLocationResult> {
|
|
179
|
+
const violations: ArchitectureViolation[] = [];
|
|
180
|
+
const normalizedPath = this.toRelativePath(request.path);
|
|
179
181
|
|
|
180
182
|
// 1. readonly 폴더 검사
|
|
181
183
|
for (const [key, rule] of Object.entries(this.config.folders || {})) {
|
|
@@ -288,14 +290,14 @@ export class ArchitectureAnalyzer {
|
|
|
288
290
|
/**
|
|
289
291
|
* Import 검증
|
|
290
292
|
*/
|
|
291
|
-
async checkImports(request: CheckImportRequest): Promise<CheckImportResult> {
|
|
293
|
+
async checkImports(request: CheckImportRequest): Promise<CheckImportResult> {
|
|
292
294
|
const violations: Array<{
|
|
293
295
|
import: string;
|
|
294
296
|
reason: string;
|
|
295
297
|
suggestion?: string;
|
|
296
298
|
}> = [];
|
|
297
299
|
|
|
298
|
-
const normalizedSource = this.toRelativePath(request.sourceFile);
|
|
300
|
+
const normalizedSource = this.toRelativePath(request.sourceFile);
|
|
299
301
|
|
|
300
302
|
for (const importPath of request.imports) {
|
|
301
303
|
for (const rule of this.config.imports || []) {
|
|
@@ -368,7 +370,7 @@ export class ArchitectureAnalyzer {
|
|
|
368
370
|
/**
|
|
369
371
|
* 코드에서 import 문 추출
|
|
370
372
|
*/
|
|
371
|
-
private extractImports(content: string): string[] {
|
|
373
|
+
private extractImports(content: string): string[] {
|
|
372
374
|
const imports: string[] = [];
|
|
373
375
|
|
|
374
376
|
// ES6 import
|
|
@@ -385,15 +387,15 @@ export class ArchitectureAnalyzer {
|
|
|
385
387
|
}
|
|
386
388
|
|
|
387
389
|
return imports;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
private toRelativePath(filePath: string): string {
|
|
391
|
-
const normalized = filePath.replace(/\\/g, "/");
|
|
392
|
-
if (path.isAbsolute(normalized)) {
|
|
393
|
-
return path.relative(this.rootDir, normalized).replace(/\\/g, "/");
|
|
394
|
-
}
|
|
395
|
-
return normalized;
|
|
396
|
-
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private toRelativePath(filePath: string): string {
|
|
393
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
394
|
+
if (path.isAbsolute(normalized)) {
|
|
395
|
+
return path.relative(this.rootDir, normalized).replace(/\\/g, "/");
|
|
396
|
+
}
|
|
397
|
+
return normalized;
|
|
398
|
+
}
|
|
397
399
|
|
|
398
400
|
/**
|
|
399
401
|
* 폴더 스캔
|
|
@@ -449,7 +451,7 @@ export class ArchitectureAnalyzer {
|
|
|
449
451
|
*/
|
|
450
452
|
private getImportSuggestion(importPath: string, sourceFile: string): string {
|
|
451
453
|
if (importPath === "fs") {
|
|
452
|
-
if (sourceFile.includes("
|
|
454
|
+
if (sourceFile.includes(".mandu/generated/web") || sourceFile.includes("client")) {
|
|
453
455
|
return "프론트엔드에서는 fetch API를 사용하세요";
|
|
454
456
|
}
|
|
455
457
|
return "Bun.file() 또는 Bun.write()를 사용하세요";
|
|
@@ -513,7 +515,7 @@ ${JSON.stringify(this.config.folders, null, 2)}
|
|
|
513
515
|
]);
|
|
514
516
|
|
|
515
517
|
// 응답에서 경로 추출 시도
|
|
516
|
-
const pathMatch = result.content.match(/(?:spec\/|
|
|
518
|
+
const pathMatch = result.content.match(/(?:spec\/|\.mandu\/|app\/|src\/|packages\/)[^\s,)]+/);
|
|
517
519
|
|
|
518
520
|
return {
|
|
519
521
|
suggestion: result.content,
|
|
@@ -140,7 +140,7 @@ export function generateTemplatePatches(
|
|
|
140
140
|
switch (violation.ruleId) {
|
|
141
141
|
case GUARD_RULES.SPEC_HASH_MISMATCH?.id:
|
|
142
142
|
patches.push({
|
|
143
|
-
file: "
|
|
143
|
+
file: ".mandu/spec.lock.json",
|
|
144
144
|
description: "Spec lock 파일 갱신",
|
|
145
145
|
type: "command",
|
|
146
146
|
command: "bunx mandu spec-upsert",
|
package/src/bundler/build.ts
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
* Bun.build 기반 클라이언트 번들 빌드
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { RoutesManifest, RouteSpec } from "../spec/schema";
|
|
7
|
-
import { needsHydration, getRouteHydration } from "../spec/schema";
|
|
8
|
-
import type {
|
|
9
|
-
BundleResult,
|
|
10
|
-
BundleOutput,
|
|
11
|
-
BundleManifest,
|
|
12
|
-
BundleStats,
|
|
13
|
-
BundlerOptions,
|
|
14
|
-
} from "./types";
|
|
15
|
-
import { HYDRATION } from "../constants";
|
|
16
|
-
import path from "path";
|
|
17
|
-
import fs from "fs/promises";
|
|
6
|
+
import type { RoutesManifest, RouteSpec } from "../spec/schema";
|
|
7
|
+
import { needsHydration, getRouteHydration } from "../spec/schema";
|
|
8
|
+
import type {
|
|
9
|
+
BundleResult,
|
|
10
|
+
BundleOutput,
|
|
11
|
+
BundleManifest,
|
|
12
|
+
BundleStats,
|
|
13
|
+
BundlerOptions,
|
|
14
|
+
} from "./types";
|
|
15
|
+
import { HYDRATION } from "../constants";
|
|
16
|
+
import path from "path";
|
|
17
|
+
import fs from "fs/promises";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* 빈 매니페스트 생성
|
|
@@ -282,7 +282,7 @@ function hydrateIslands() {
|
|
|
282
282
|
for (const el of islands) {
|
|
283
283
|
const id = el.getAttribute('data-mandu-island');
|
|
284
284
|
const src = el.getAttribute('data-mandu-src');
|
|
285
|
-
const priority = el.getAttribute('data-mandu-priority') || '${HYDRATION.DEFAULT_PRIORITY}';
|
|
285
|
+
const priority = el.getAttribute('data-mandu-priority') || '${HYDRATION.DEFAULT_PRIORITY}';
|
|
286
286
|
|
|
287
287
|
if (!id || !src) {
|
|
288
288
|
console.warn('[Mandu] Island missing id or src:', el);
|
|
@@ -855,21 +855,21 @@ interface VendorBuildResult {
|
|
|
855
855
|
* Vendor shim 번들 빌드
|
|
856
856
|
* React, ReactDOM, ReactDOMClient를 각각의 shim으로 빌드
|
|
857
857
|
*/
|
|
858
|
-
async function buildVendorShims(
|
|
859
|
-
outDir: string,
|
|
860
|
-
options: BundlerOptions
|
|
861
|
-
): Promise<VendorBuildResult> {
|
|
862
|
-
const errors: string[] = [];
|
|
863
|
-
type VendorShimKey = "react" | "reactDom" | "reactDomClient" | "jsxRuntime" | "jsxDevRuntime";
|
|
864
|
-
const results: Record<VendorShimKey, string> = {
|
|
865
|
-
react: "",
|
|
866
|
-
reactDom: "",
|
|
867
|
-
reactDomClient: "",
|
|
868
|
-
jsxRuntime: "",
|
|
869
|
-
jsxDevRuntime: "",
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
const shims: Array<{ name: string; source: string; key: VendorShimKey }> = [
|
|
858
|
+
async function buildVendorShims(
|
|
859
|
+
outDir: string,
|
|
860
|
+
options: BundlerOptions
|
|
861
|
+
): Promise<VendorBuildResult> {
|
|
862
|
+
const errors: string[] = [];
|
|
863
|
+
type VendorShimKey = "react" | "reactDom" | "reactDomClient" | "jsxRuntime" | "jsxDevRuntime";
|
|
864
|
+
const results: Record<VendorShimKey, string> = {
|
|
865
|
+
react: "",
|
|
866
|
+
reactDom: "",
|
|
867
|
+
reactDomClient: "",
|
|
868
|
+
jsxRuntime: "",
|
|
869
|
+
jsxDevRuntime: "",
|
|
870
|
+
};
|
|
871
|
+
|
|
872
|
+
const shims: Array<{ name: string; source: string; key: VendorShimKey }> = [
|
|
873
873
|
{ name: "_react", source: generateReactShimSource(), key: "react" },
|
|
874
874
|
{ name: "_react-dom", source: generateReactDOMShimSource(), key: "reactDom" },
|
|
875
875
|
{ name: "_react-dom-client", source: generateReactDOMClientShimSource(), key: "reactDomClient" },
|
|
@@ -877,68 +877,68 @@ async function buildVendorShims(
|
|
|
877
877
|
{ name: "_jsx-dev-runtime", source: generateJsxDevRuntimeShimSource(), key: "jsxDevRuntime" },
|
|
878
878
|
];
|
|
879
879
|
|
|
880
|
-
const buildShim = async (
|
|
881
|
-
shim: { name: string; source: string; key: VendorShimKey }
|
|
882
|
-
): Promise<{ key: VendorShimKey; outputPath?: string; error?: string }> => {
|
|
883
|
-
const srcPath = path.join(outDir, `${shim.name}.src.js`);
|
|
884
|
-
const outputName = `${shim.name}.js`;
|
|
885
|
-
|
|
886
|
-
try {
|
|
887
|
-
await Bun.write(srcPath, shim.source);
|
|
888
|
-
|
|
889
|
-
// _react.js는 external 없이 React 전체를 번들링
|
|
890
|
-
// _react-dom*, jsx-runtime은 react를 external로 처리하여 동일한 React 인스턴스 공유
|
|
891
|
-
let shimExternal: string[] = [];
|
|
892
|
-
if (shim.name === "_react-dom" || shim.name === "_react-dom-client") {
|
|
893
|
-
shimExternal = ["react"];
|
|
894
|
-
} else if (shim.name === "_jsx-runtime" || shim.name === "_jsx-dev-runtime") {
|
|
895
|
-
shimExternal = ["react"];
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
const result = await Bun.build({
|
|
899
|
-
entrypoints: [srcPath],
|
|
900
|
-
outdir: outDir,
|
|
901
|
-
naming: outputName,
|
|
902
|
-
minify: options.minify ?? process.env.NODE_ENV === "production",
|
|
903
|
-
sourcemap: options.sourcemap ? "external" : "none",
|
|
904
|
-
target: "browser",
|
|
905
|
-
external: shimExternal,
|
|
906
|
-
define: {
|
|
907
|
-
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
|
|
908
|
-
...options.define,
|
|
909
|
-
},
|
|
910
|
-
});
|
|
911
|
-
|
|
912
|
-
await fs.unlink(srcPath).catch(() => {});
|
|
913
|
-
|
|
914
|
-
if (!result.success) {
|
|
915
|
-
return {
|
|
916
|
-
key: shim.key,
|
|
917
|
-
error: `[${shim.name}] ${result.logs.map((l) => l.message).join(", ")}`,
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
return {
|
|
922
|
-
key: shim.key,
|
|
923
|
-
outputPath: `/.mandu/client/${outputName}`,
|
|
924
|
-
};
|
|
925
|
-
} catch (error) {
|
|
926
|
-
await fs.unlink(srcPath).catch(() => {});
|
|
927
|
-
return {
|
|
928
|
-
key: shim.key,
|
|
929
|
-
error: `[${shim.name}] ${String(error)}`,
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
};
|
|
933
|
-
|
|
934
|
-
const buildResults = await Promise.all(shims.map((shim) => buildShim(shim)));
|
|
935
|
-
for (const result of buildResults) {
|
|
936
|
-
if (result.error) {
|
|
937
|
-
errors.push(result.error);
|
|
938
|
-
} else if (result.outputPath) {
|
|
939
|
-
results[result.key] = result.outputPath;
|
|
940
|
-
}
|
|
941
|
-
}
|
|
880
|
+
const buildShim = async (
|
|
881
|
+
shim: { name: string; source: string; key: VendorShimKey }
|
|
882
|
+
): Promise<{ key: VendorShimKey; outputPath?: string; error?: string }> => {
|
|
883
|
+
const srcPath = path.join(outDir, `${shim.name}.src.js`);
|
|
884
|
+
const outputName = `${shim.name}.js`;
|
|
885
|
+
|
|
886
|
+
try {
|
|
887
|
+
await Bun.write(srcPath, shim.source);
|
|
888
|
+
|
|
889
|
+
// _react.js는 external 없이 React 전체를 번들링
|
|
890
|
+
// _react-dom*, jsx-runtime은 react를 external로 처리하여 동일한 React 인스턴스 공유
|
|
891
|
+
let shimExternal: string[] = [];
|
|
892
|
+
if (shim.name === "_react-dom" || shim.name === "_react-dom-client") {
|
|
893
|
+
shimExternal = ["react"];
|
|
894
|
+
} else if (shim.name === "_jsx-runtime" || shim.name === "_jsx-dev-runtime") {
|
|
895
|
+
shimExternal = ["react"];
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const result = await Bun.build({
|
|
899
|
+
entrypoints: [srcPath],
|
|
900
|
+
outdir: outDir,
|
|
901
|
+
naming: outputName,
|
|
902
|
+
minify: options.minify ?? process.env.NODE_ENV === "production",
|
|
903
|
+
sourcemap: options.sourcemap ? "external" : "none",
|
|
904
|
+
target: "browser",
|
|
905
|
+
external: shimExternal,
|
|
906
|
+
define: {
|
|
907
|
+
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
|
|
908
|
+
...options.define,
|
|
909
|
+
},
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
await fs.unlink(srcPath).catch(() => {});
|
|
913
|
+
|
|
914
|
+
if (!result.success) {
|
|
915
|
+
return {
|
|
916
|
+
key: shim.key,
|
|
917
|
+
error: `[${shim.name}] ${result.logs.map((l) => l.message).join(", ")}`,
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
return {
|
|
922
|
+
key: shim.key,
|
|
923
|
+
outputPath: `/.mandu/client/${outputName}`,
|
|
924
|
+
};
|
|
925
|
+
} catch (error) {
|
|
926
|
+
await fs.unlink(srcPath).catch(() => {});
|
|
927
|
+
return {
|
|
928
|
+
key: shim.key,
|
|
929
|
+
error: `[${shim.name}] ${String(error)}`,
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
|
|
934
|
+
const buildResults = await Promise.all(shims.map((shim) => buildShim(shim)));
|
|
935
|
+
for (const result of buildResults) {
|
|
936
|
+
if (result.error) {
|
|
937
|
+
errors.push(result.error);
|
|
938
|
+
} else if (result.outputPath) {
|
|
939
|
+
results[result.key] = result.outputPath;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
942
|
|
|
943
943
|
return {
|
|
944
944
|
success: errors.length === 0,
|
|
@@ -1052,7 +1052,7 @@ function createBundleManifest(
|
|
|
1052
1052
|
bundles[output.routeId] = {
|
|
1053
1053
|
js: output.outputPath,
|
|
1054
1054
|
dependencies: ["_runtime", "_react"],
|
|
1055
|
-
priority: hydration?.priority || HYDRATION.DEFAULT_PRIORITY,
|
|
1055
|
+
priority: hydration?.priority || HYDRATION.DEFAULT_PRIORITY,
|
|
1056
1056
|
};
|
|
1057
1057
|
}
|
|
1058
1058
|
|