@mandujs/core 0.41.2 → 0.43.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 +21 -4
- package/src/auth/__tests__/login.test.ts +420 -419
- package/src/auth/__tests__/reset.test.ts +296 -296
- package/src/brain/adapters/anthropic-oauth.ts +421 -420
- package/src/brain/adapters/index.ts +2 -1
- package/src/brain/adapters/ollama.ts +1 -1
- package/src/brain/adapters/openai-oauth.ts +534 -533
- package/src/brain/brain.ts +2 -1
- package/src/brain/redactor.ts +196 -196
- package/src/bundler/__tests__/cli-bench-utils.test.ts +149 -149
- package/src/bundler/__tests__/cold-start.test.ts +504 -504
- package/src/bundler/__tests__/fast-refresh.test.ts +607 -606
- package/src/bundler/__tests__/hdr.test.ts +1 -1
- package/src/bundler/analyzer.ts +958 -958
- package/src/bundler/build.ts +104 -14
- package/src/bundler/dev.ts +125 -0
- package/src/bundler/hmr-types.ts +1 -0
- package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -0
- package/src/bundler/plugins/index.ts +14 -0
- package/src/bundler/plugins/react-compiler-lint.ts +253 -0
- package/src/bundler/plugins/react-compiler.ts +162 -0
- package/src/bundler/types.ts +12 -0
- package/src/change/integrity.ts +2 -1
- package/src/client/index.ts +10 -0
- package/src/client/island.ts +38 -11
- package/src/client/router.ts +6 -1
- package/src/config/mandu.ts +57 -0
- package/src/config/validate.ts +42 -0
- package/src/content/collection.ts +844 -809
- package/src/content/content-layer.ts +316 -314
- package/src/content/content.test.ts +433 -433
- package/src/content/digest.ts +133 -133
- package/src/content/generate-types.ts +168 -168
- package/src/content/index.ts +6 -1
- package/src/content/llms-txt.ts +277 -277
- package/src/contract/define.ts +474 -474
- package/src/contract/route-helpers.ts +2 -1
- package/src/contract/zod-utils.ts +158 -155
- package/src/db/index.ts +513 -513
- package/src/desktop/__tests__/smoke.test.ts +100 -100
- package/src/desktop/webview-fallback.ts +583 -583
- package/src/desktop/window.ts +3 -1
- package/src/dev-error-overlay/overlay-client.ts +300 -300
- package/src/devtools/ai/mcp-connector.ts +499 -498
- package/src/devtools/client/components/kitchen-root.tsx +7 -2
- package/src/email/resend.ts +163 -163
- package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -0
- package/src/guard/ast-analyzer.ts +806 -806
- package/src/guard/graph.ts +898 -898
- package/src/guard/index.ts +16 -0
- package/src/guard/statistics.ts +578 -578
- package/src/guard/tsgolint-bridge.ts +512 -0
- package/src/i18n/locale-resolver.ts +214 -214
- package/src/id/__tests__/id.test.ts +120 -120
- package/src/intent/index.ts +321 -321
- package/src/island/index.ts +39 -23
- package/src/kitchen/api/contract-api.ts +15 -8
- package/src/kitchen/kitchen-ui.ts +2137 -2137
- package/src/lockfile/index.ts +3 -2
- package/src/middleware/oauth/__tests__/oauth.test.ts +575 -574
- package/src/middleware/rate-limit/__tests__/rate-limit.test.ts +642 -642
- package/src/middleware/secure/index.ts +417 -417
- package/src/observability/event-bus.ts +2 -2
- package/src/observability/metrics.ts +334 -334
- package/src/observability/tracing.ts +694 -694
- package/src/openapi/generator.ts +1 -1
- package/src/perf/user-marks.ts +553 -553
- package/src/plugins/registry.ts +387 -387
- package/src/resource/ddl/diff.ts +392 -392
- package/src/resource/ddl/snapshot.ts +448 -447
- package/src/resource/generator-schema.ts +477 -476
- package/src/resource/parser.ts +4 -2
- package/src/resource/schema.ts +1 -1
- package/src/router/fs-patterns.ts +422 -422
- package/src/runtime/fast-refresh-types.ts +126 -128
- package/src/runtime/image-handler.ts +206 -195
- package/src/runtime/router.test.ts +476 -476
- package/src/runtime/security.ts +155 -155
- package/src/runtime/server.ts +36 -19
- package/src/runtime/session-key.ts +328 -328
- package/src/scheduler/__tests__/scheduler.test.ts +514 -514
- package/src/seo/resolve/index.ts +353 -353
- package/src/spec/load.ts +1 -1
- package/src/testing/reporter.ts +676 -676
- package/src/testing/server.ts +196 -196
- package/src/testing/snapshot.ts +444 -444
- package/src/utils/__tests__/lru-cache.test.ts +186 -186
- package/src/utils/bun.ts +8 -8
package/src/island/index.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import type { ComponentType, ReactNode } from 'react';
|
|
16
|
-
import { z } from 'zod';
|
|
16
|
+
import type { z } from 'zod';
|
|
17
17
|
|
|
18
18
|
// ============================================================================
|
|
19
19
|
// Types
|
|
@@ -58,20 +58,30 @@ export type IslandComponent<P = unknown> = ComponentType<P> & IslandMeta;
|
|
|
58
58
|
// Island Registry (서버/클라이언트 공용)
|
|
59
59
|
// ============================================================================
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
// Registry bag for heterogeneous React components. React's `ComponentType<P>`
|
|
62
|
+
// is contravariant on `P` — a `ComponentType<{id:string}>` is NOT assignable
|
|
63
|
+
// to `ComponentType<Record<string, unknown>>`. The correct bag type for a
|
|
64
|
+
// heterogeneous component map is `ComponentType<any>`; narrowing happens at
|
|
65
|
+
// call sites via each island's own typed `IslandComponent<P>` signature.
|
|
66
|
+
// Same pattern used in client/island.ts `createPartialGroup()`.
|
|
67
|
+
// oxlint-disable no-explicit-any -- heterogeneous React component registry
|
|
68
|
+
type AnyIslandComponent = IslandComponent<any>;
|
|
69
|
+
|
|
70
|
+
const islandRegistry = new Map<string, AnyIslandComponent>();
|
|
62
71
|
let islandCounter = 0;
|
|
63
72
|
|
|
64
|
-
export function registerIsland(name: string, component:
|
|
73
|
+
export function registerIsland(name: string, component: AnyIslandComponent): void {
|
|
65
74
|
islandRegistry.set(name, component);
|
|
66
75
|
}
|
|
67
76
|
|
|
68
|
-
export function getIsland(name: string):
|
|
77
|
+
export function getIsland(name: string): AnyIslandComponent | undefined {
|
|
69
78
|
return islandRegistry.get(name);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
export function getAllIslands(): Map<string,
|
|
81
|
+
export function getAllIslands(): Map<string, AnyIslandComponent> {
|
|
73
82
|
return islandRegistry;
|
|
74
83
|
}
|
|
84
|
+
// oxlint-enable no-explicit-any
|
|
75
85
|
|
|
76
86
|
// ============================================================================
|
|
77
87
|
// Client Island Types (setup/render 패턴)
|
|
@@ -98,14 +108,10 @@ export interface CompiledClientIsland<TServerData, TSetupResult> {
|
|
|
98
108
|
|
|
99
109
|
/** Type guard: is this a ClientIslandDefinition? */
|
|
100
110
|
function isClientIslandDefinition(arg: unknown): arg is ClientIslandDefinition<unknown, unknown> {
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
'render' in arg &&
|
|
106
|
-
typeof (arg as any).setup === 'function' &&
|
|
107
|
-
typeof (arg as any).render === 'function'
|
|
108
|
-
);
|
|
111
|
+
if (arg === null || typeof arg !== 'object') return false;
|
|
112
|
+
if (!('setup' in arg) || !('render' in arg)) return false;
|
|
113
|
+
const candidate = arg as { setup?: unknown; render?: unknown };
|
|
114
|
+
return typeof candidate.setup === 'function' && typeof candidate.render === 'function';
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
// ============================================================================
|
|
@@ -140,6 +146,15 @@ function isClientIslandDefinition(arg: unknown): arg is ClientIslandDefinition<u
|
|
|
140
146
|
* });
|
|
141
147
|
*/
|
|
142
148
|
|
|
149
|
+
// Using `unknown` generic arguments on the internal impl types keeps the
|
|
150
|
+
// overloads below as the single source of truth for external type inference
|
|
151
|
+
// while avoiding `any` in the implementation. Callers always hit one of
|
|
152
|
+
// the overloads and never see this input/output type.
|
|
153
|
+
type IslandImplInput =
|
|
154
|
+
| IslandHydrationStrategy
|
|
155
|
+
| IslandOptions<unknown>
|
|
156
|
+
| ClientIslandDefinition<unknown, unknown>;
|
|
157
|
+
|
|
143
158
|
// Overload 1: Setup/Render client island pattern
|
|
144
159
|
export function island<TServerData, TSetupResult = TServerData>(
|
|
145
160
|
definition: ClientIslandDefinition<TServerData, TSetupResult>
|
|
@@ -159,9 +174,9 @@ export function island<P extends Record<string, unknown>>(
|
|
|
159
174
|
|
|
160
175
|
// Implementation
|
|
161
176
|
export function island(
|
|
162
|
-
strategyOrOptionsOrDefinition:
|
|
163
|
-
Component?: ComponentType<
|
|
164
|
-
):
|
|
177
|
+
strategyOrOptionsOrDefinition: IslandImplInput,
|
|
178
|
+
Component?: ComponentType<unknown>,
|
|
179
|
+
): AnyIslandComponent | CompiledClientIsland<unknown, unknown> {
|
|
165
180
|
// Pattern 2: Setup/Render client island
|
|
166
181
|
if (Component === undefined && isClientIslandDefinition(strategyOrOptionsOrDefinition)) {
|
|
167
182
|
return {
|
|
@@ -175,20 +190,21 @@ export function island(
|
|
|
175
190
|
throw new Error('[Mandu Island] Component is required for declarative island pattern');
|
|
176
191
|
}
|
|
177
192
|
|
|
178
|
-
const options: IslandOptions<
|
|
193
|
+
const options: IslandOptions<unknown> = typeof strategyOrOptionsOrDefinition === 'string'
|
|
179
194
|
? { hydrate: strategyOrOptionsOrDefinition }
|
|
180
|
-
: strategyOrOptionsOrDefinition as IslandOptions<
|
|
195
|
+
: (strategyOrOptionsOrDefinition as IslandOptions<unknown>);
|
|
181
196
|
|
|
182
197
|
const name = options.name || `island_${++islandCounter}_${Component.name || 'Anonymous'}`;
|
|
183
198
|
|
|
184
|
-
// Island 메타데이터 부착
|
|
185
|
-
|
|
199
|
+
// Island 메타데이터 부착 — mutate the component in-place so the caller's
|
|
200
|
+
// reference carries the attached `IslandMeta` fields.
|
|
201
|
+
const IslandWrapper = Component as unknown as AnyIslandComponent;
|
|
186
202
|
IslandWrapper.__island = true;
|
|
187
203
|
IslandWrapper.__hydrate = options.hydrate;
|
|
188
204
|
IslandWrapper.__media = options.media;
|
|
189
205
|
IslandWrapper.__fallback = options.fallback;
|
|
190
206
|
IslandWrapper.__name = name;
|
|
191
|
-
IslandWrapper.__propsSchema = options.props;
|
|
207
|
+
IslandWrapper.__propsSchema = options.props as IslandMeta['__propsSchema'];
|
|
192
208
|
|
|
193
209
|
// 레지스트리에 등록
|
|
194
210
|
registerIsland(name, IslandWrapper);
|
|
@@ -200,10 +216,10 @@ export function island(
|
|
|
200
216
|
// isIsland() - Island 컴포넌트 체크
|
|
201
217
|
// ============================================================================
|
|
202
218
|
|
|
203
|
-
export function isIsland(component: unknown): component is
|
|
219
|
+
export function isIsland(component: unknown): component is AnyIslandComponent {
|
|
204
220
|
return (
|
|
205
221
|
typeof component === 'function' &&
|
|
206
|
-
(component as
|
|
222
|
+
(component as Partial<IslandMeta>).__island === true
|
|
207
223
|
);
|
|
208
224
|
}
|
|
209
225
|
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import type { RoutesManifest, RouteSpec } from "../../spec/schema";
|
|
12
|
+
import type { ContractSchema, ResponseSchemaWithExamples } from "../../contract/schema";
|
|
13
|
+
import type { z } from "zod";
|
|
12
14
|
import {
|
|
13
15
|
generateOpenAPIDocument,
|
|
14
16
|
zodToOpenAPISchema,
|
|
@@ -93,13 +95,18 @@ export class ContractPlaygroundAPI {
|
|
|
93
95
|
schemas[method] = schema;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
// Response schemas
|
|
98
|
+
// Response schemas. Contract response entries are either a raw Zod
|
|
99
|
+
// schema or a `ResponseSchemaWithExamples` wrapper; narrow on the
|
|
100
|
+
// presence of `.schema` rather than widening to `any`.
|
|
97
101
|
const responseSchemas: Record<string, unknown> = {};
|
|
98
102
|
for (const [status, resSchema] of Object.entries(contract.response || {})) {
|
|
99
|
-
if (resSchema
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
if (!resSchema) continue;
|
|
104
|
+
if (typeof resSchema === "object" && "schema" in resSchema) {
|
|
105
|
+
responseSchemas[status] = zodToOpenAPISchema(
|
|
106
|
+
(resSchema as ResponseSchemaWithExamples).schema,
|
|
107
|
+
);
|
|
108
|
+
} else {
|
|
109
|
+
responseSchemas[status] = zodToOpenAPISchema(resSchema as z.ZodTypeAny);
|
|
103
110
|
}
|
|
104
111
|
}
|
|
105
112
|
|
|
@@ -212,12 +219,12 @@ export class ContractPlaygroundAPI {
|
|
|
212
219
|
|
|
213
220
|
// ────────────────────────────────────────────────
|
|
214
221
|
|
|
215
|
-
private async loadContract(route: RouteSpec): Promise<
|
|
222
|
+
private async loadContract(route: RouteSpec): Promise<ContractSchema | null> {
|
|
216
223
|
if (!route.contractModule) return null;
|
|
217
224
|
try {
|
|
218
225
|
const fullPath = path.join(this.rootDir, route.contractModule);
|
|
219
|
-
const module = await import(fullPath);
|
|
220
|
-
return module.default;
|
|
226
|
+
const module = (await import(fullPath)) as { default?: ContractSchema };
|
|
227
|
+
return module.default ?? null;
|
|
221
228
|
} catch {
|
|
222
229
|
return null;
|
|
223
230
|
}
|