@mandujs/core 0.18.20 → 0.18.22

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 (91) hide show
  1. package/package.json +3 -1
  2. package/src/brain/architecture/analyzer.ts +3 -5
  3. package/src/brain/architecture/types.ts +4 -4
  4. package/src/brain/doctor/analyzer.ts +1 -0
  5. package/src/brain/doctor/index.ts +1 -1
  6. package/src/brain/doctor/patcher.ts +10 -6
  7. package/src/brain/doctor/reporter.ts +4 -4
  8. package/src/brain/types.ts +14 -10
  9. package/src/bundler/build.ts +17 -17
  10. package/src/bundler/css.ts +3 -2
  11. package/src/bundler/dev.ts +1 -1
  12. package/src/client/island.ts +10 -9
  13. package/src/client/router.ts +1 -1
  14. package/src/config/mcp-ref.ts +6 -6
  15. package/src/config/metadata.test.ts +1 -1
  16. package/src/config/metadata.ts +36 -16
  17. package/src/config/symbols.ts +1 -1
  18. package/src/config/validate.ts +17 -1
  19. package/src/content/content.test.ts +3 -3
  20. package/src/content/loaders/file.ts +3 -0
  21. package/src/content/loaders/glob.ts +1 -0
  22. package/src/contract/client-safe.test.ts +1 -1
  23. package/src/contract/client.test.ts +2 -1
  24. package/src/contract/client.ts +18 -18
  25. package/src/contract/define.ts +32 -17
  26. package/src/contract/handler.ts +11 -11
  27. package/src/contract/index.ts +2 -5
  28. package/src/contract/infer.test.ts +2 -1
  29. package/src/contract/normalize.test.ts +1 -1
  30. package/src/contract/normalize.ts +17 -11
  31. package/src/contract/registry.test.ts +1 -1
  32. package/src/contract/zod-utils.ts +155 -0
  33. package/src/devtools/client/catchers/error-catcher.ts +3 -3
  34. package/src/devtools/client/catchers/network-proxy.ts +5 -1
  35. package/src/devtools/client/components/kitchen-root.tsx +2 -2
  36. package/src/devtools/client/components/panel/guard-panel.tsx +3 -3
  37. package/src/devtools/client/state-manager.ts +9 -9
  38. package/src/devtools/index.ts +8 -8
  39. package/src/devtools/init.ts +2 -2
  40. package/src/devtools/protocol.ts +4 -4
  41. package/src/devtools/server/source-context.ts +9 -3
  42. package/src/devtools/types.ts +5 -5
  43. package/src/devtools/worker/redaction-worker.ts +12 -5
  44. package/src/error/index.ts +1 -1
  45. package/src/error/result.ts +14 -0
  46. package/src/filling/deps.ts +5 -2
  47. package/src/filling/filling.ts +1 -1
  48. package/src/generator/templates.ts +2 -2
  49. package/src/guard/contract-guard.test.ts +1 -0
  50. package/src/guard/file-type.test.ts +1 -1
  51. package/src/guard/index.ts +1 -1
  52. package/src/guard/negotiation.ts +29 -1
  53. package/src/guard/presets/index.ts +3 -0
  54. package/src/guard/semantic-slots.ts +4 -4
  55. package/src/index.ts +10 -1
  56. package/src/intent/index.ts +28 -17
  57. package/src/island/index.ts +8 -8
  58. package/src/openapi/generator.ts +49 -31
  59. package/src/plugins/index.ts +1 -1
  60. package/src/plugins/registry.ts +28 -18
  61. package/src/plugins/types.ts +2 -2
  62. package/src/resource/__tests__/backward-compat.test.ts +2 -2
  63. package/src/resource/__tests__/edge-cases.test.ts +14 -13
  64. package/src/resource/__tests__/fixtures.ts +2 -2
  65. package/src/resource/__tests__/generator.test.ts +1 -1
  66. package/src/resource/__tests__/performance.test.ts +8 -6
  67. package/src/resource/schema.ts +1 -1
  68. package/src/router/fs-routes.ts +34 -40
  69. package/src/router/fs-types.ts +2 -2
  70. package/src/router/index.ts +1 -1
  71. package/src/runtime/boundary.tsx +4 -4
  72. package/src/runtime/logger.test.ts +3 -3
  73. package/src/runtime/logger.ts +1 -1
  74. package/src/runtime/server.ts +18 -16
  75. package/src/runtime/ssr.ts +1 -1
  76. package/src/runtime/stable-selector.ts +1 -2
  77. package/src/runtime/streaming-ssr.ts +15 -6
  78. package/src/seo/index.ts +5 -0
  79. package/src/seo/integration/ssr.ts +4 -4
  80. package/src/seo/render/basic.ts +12 -4
  81. package/src/seo/render/opengraph.ts +12 -6
  82. package/src/seo/render/twitter.ts +3 -2
  83. package/src/seo/resolve/url.ts +7 -0
  84. package/src/seo/types.ts +13 -0
  85. package/src/spec/schema.ts +89 -61
  86. package/src/types/branded.ts +56 -0
  87. package/src/types/index.ts +1 -0
  88. package/src/utils/hasher.test.ts +6 -6
  89. package/src/utils/hasher.ts +2 -2
  90. package/src/utils/index.ts +1 -1
  91. package/src/watcher/watcher.ts +2 -2
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Branded Types - Nominal typing for string identifiers
3
+ *
4
+ * Prevents accidental mixing of different ID types at compile time.
5
+ * All branded types are structurally compatible with plain strings at runtime.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const col = collectionId("blog");
10
+ * const entry = entryId("hello-world");
11
+ * // col and entry are both strings at runtime,
12
+ * // but TypeScript treats them as distinct types.
13
+ * ```
14
+ */
15
+
16
+ declare const __brand: unique symbol;
17
+
18
+ /**
19
+ * Brand utility type - creates nominal types from structural types.
20
+ * The brand exists only at the type level and has zero runtime cost.
21
+ */
22
+ export type Brand<T, B extends string> = T & { readonly [__brand]: B };
23
+
24
+ /** Branded string identifying a content collection */
25
+ export type CollectionId = Brand<string, "CollectionId">;
26
+
27
+ /** Branded string identifying a content entry within a collection */
28
+ export type EntryId = Brand<string, "EntryId">;
29
+
30
+ /** Branded string containing sanitized HTML (XSS-safe) */
31
+ export type SafeHTML = Brand<string, "SafeHTML">;
32
+
33
+ /** Branded string identifying a route in the manifest */
34
+ export type RouteId = Brand<string, "RouteId">;
35
+
36
+ // -- Constructor functions --
37
+
38
+ /** Create a branded CollectionId from a plain string */
39
+ export function collectionId(id: string): CollectionId {
40
+ return id as CollectionId;
41
+ }
42
+
43
+ /** Create a branded EntryId from a plain string */
44
+ export function entryId(id: string): EntryId {
45
+ return id as EntryId;
46
+ }
47
+
48
+ /** Create a branded SafeHTML from a sanitized string */
49
+ export function safeHTML(html: string): SafeHTML {
50
+ return html as SafeHTML;
51
+ }
52
+
53
+ /** Create a branded RouteId from a plain string */
54
+ export function routeId(id: string): RouteId {
55
+ return id as RouteId;
56
+ }
@@ -0,0 +1 @@
1
+ export * from "./branded";
@@ -146,25 +146,25 @@ describe("normalizeForHash", () => {
146
146
  ["a", 2],
147
147
  ["m", 3],
148
148
  ]);
149
- const normalized = normalizeForHash({ data: map }) as any;
149
+ const normalized = normalizeForHash({ data: map }) as Record<string, Record<string, unknown>>;
150
150
 
151
151
  expect(normalized.data.__type__).toBe("Map");
152
- expect(normalized.data.entries[0][0]).toBe("a"); // 정렬됨
152
+ expect((normalized.data.entries as string[][])[0][0]).toBe("a"); // 정렬됨
153
153
  });
154
154
 
155
155
  it("should handle Set as sorted array", () => {
156
156
  const set = new Set([3, 1, 2]);
157
- const normalized = normalizeForHash({ data: set }) as any;
157
+ const normalized = normalizeForHash({ data: set }) as Record<string, Record<string, unknown>>;
158
158
 
159
159
  expect(normalized.data.__type__).toBe("Set");
160
160
  expect(normalized.data.items).toEqual([1, 2, 3]); // 정렬됨
161
161
  });
162
162
 
163
163
  it("should detect circular references", () => {
164
- const obj: any = { a: 1 };
164
+ const obj: Record<string, unknown> = { a: 1 };
165
165
  obj.self = obj;
166
166
 
167
- const normalized = normalizeForHash(obj) as any;
167
+ const normalized = normalizeForHash(obj) as Record<string, unknown>;
168
168
  expect(normalized.self).toBe("__circular__");
169
169
  });
170
170
 
@@ -184,7 +184,7 @@ describe("normalizeForHash", () => {
184
184
 
185
185
  it("should normalize Error objects", () => {
186
186
  const error = new TypeError("test error");
187
- const normalized = normalizeForHash({ error }) as any;
187
+ const normalized = normalizeForHash({ error }) as Record<string, Record<string, unknown>>;
188
188
 
189
189
  expect(normalized.error.__type__).toBe("Error");
190
190
  expect(normalized.error.name).toBe("TypeError");
@@ -25,7 +25,7 @@ export interface HashOptions {
25
25
  exclude?: string[];
26
26
  }
27
27
 
28
- export interface NormalizeOptions {
28
+ export interface HashNormalizeOptions {
29
29
  /** 제외할 키 패턴 */
30
30
  exclude?: string[];
31
31
  /** Date를 ISO 문자열로 변환 (기본값: true) */
@@ -59,7 +59,7 @@ export interface NormalizeOptions {
59
59
  */
60
60
  export function normalizeForHash(
61
61
  value: unknown,
62
- options: NormalizeOptions = {},
62
+ options: HashNormalizeOptions = {},
63
63
  seen: WeakSet<object> = new WeakSet()
64
64
  ): unknown {
65
65
  const {
@@ -14,7 +14,7 @@ export {
14
14
  isHashable,
15
15
  getHashInfo,
16
16
  type HashOptions,
17
- type NormalizeOptions,
17
+ type HashNormalizeOptions,
18
18
  } from "./hasher.js";
19
19
 
20
20
  // Diff
@@ -157,8 +157,8 @@ export class FileWatcher {
157
157
  this.processFileEvent("delete", filePath);
158
158
  });
159
159
 
160
- this.chokidarWatcher.on("error", (error) => {
161
- console.error(`[Watch] Error:`, error.message);
160
+ this.chokidarWatcher.on("error", (error: unknown) => {
161
+ console.error(`[Watch] Error:`, error instanceof Error ? error.message : String(error));
162
162
  });
163
163
 
164
164
  this._active = true;