@mandujs/core 0.53.3 → 0.54.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.md +654 -654
- package/package.json +2 -2
- package/src/a11y/__tests__/run-audit.test.ts +333 -333
- package/src/a11y/fix-hints.ts +76 -76
- package/src/a11y/index.ts +18 -18
- package/src/a11y/run-audit.ts +394 -394
- package/src/a11y/types.ts +125 -125
- package/src/auth/__tests__/login.test.ts +1 -1
- package/src/auth/__tests__/password.test.ts +122 -122
- package/src/auth/__tests__/tokens.test.ts +274 -274
- package/src/auth/__tests__/verification.test.ts +274 -274
- package/src/auth/index.ts +76 -76
- package/src/auth/login.ts +225 -225
- package/src/auth/password.ts +120 -120
- package/src/auth/reset.ts +243 -243
- package/src/auth/tokens.ts +612 -612
- package/src/auth/verification.ts +253 -253
- package/src/brain/__tests__/redactor.test.ts +94 -94
- package/src/brain/adapters/__tests__/_helpers.ts +83 -83
- package/src/brain/adapters/__tests__/anthropic-oauth.test.ts +196 -196
- package/src/brain/adapters/__tests__/chatgpt-auth.test.ts +193 -193
- package/src/brain/adapters/__tests__/openai-oauth.test.ts +209 -209
- package/src/brain/adapters/__tests__/resolver.test.ts +143 -143
- package/src/brain/adapters/anthropic-oauth.ts +1 -1
- package/src/brain/adapters/chatgpt-auth.ts +300 -300
- package/src/brain/adapters/index.ts +319 -319
- package/src/brain/adapters/oauth-flow.ts +439 -439
- package/src/brain/consent.ts +240 -240
- package/src/brain/credentials.ts +396 -396
- package/src/bundler/__tests__/build-runner.ts +113 -113
- package/src/bundler/__tests__/dev-reliability.test.ts +619 -619
- package/src/bundler/__tests__/extended-watch.test.ts +711 -711
- package/src/bundler/__tests__/fast-refresh.test.ts +10 -10
- package/src/bundler/__tests__/hdr.test.ts +353 -353
- package/src/bundler/__tests__/hmr-client.test.ts +532 -532
- package/src/bundler/__tests__/manifest-schema.test.ts +266 -266
- package/src/bundler/__tests__/prod-smoke.test.ts +138 -138
- package/src/bundler/__tests__/reverse-import-graph.test.ts +519 -519
- package/src/bundler/__tests__/slot-dispatch.test.ts +573 -573
- package/src/bundler/__tests__/url-cap-and-slot-regex.test.ts +286 -286
- package/src/bundler/__tests__/vendor-cache.test.ts +455 -455
- package/src/bundler/budget.ts +404 -404
- package/src/bundler/build.test.ts +179 -179
- package/src/bundler/build.ts +55 -55
- package/src/bundler/dev.ts +42 -42
- package/src/bundler/manifest-schema.ts +301 -301
- package/src/bundler/plugins/__tests__/block-generated-imports.test.ts +263 -263
- package/src/bundler/plugins/__tests__/react-compiler-config.test.ts +83 -83
- package/src/bundler/plugins/__tests__/react-compiler-lint.test.ts +110 -110
- package/src/bundler/plugins/block-generated-imports.ts +155 -155
- package/src/bundler/plugins/index.ts +83 -83
- package/src/bundler/plugins/react-compiler-config.ts +108 -108
- package/src/bundler/plugins/react-compiler-lint.ts +253 -253
- package/src/bundler/plugins/react-compiler.ts +162 -162
- package/src/bundler/reverse-import-graph.ts +339 -339
- package/src/bundler/safe-build.test.ts +201 -201
- package/src/bundler/safe-build.ts +103 -103
- package/src/bundler/scenario-matrix.ts +229 -229
- package/src/bundler/types.ts +10 -10
- package/src/bundler/vendor-cache-types.ts +130 -130
- package/src/bundler/vendor-cache.ts +526 -526
- package/src/change/snapshot.ts +18 -18
- package/src/client/Form.tsx +105 -105
- package/src/client/Link.tsx +9 -9
- package/src/client/__tests__/use-sse.test.ts +153 -153
- package/src/client/globals.ts +1 -1
- package/src/client/hooks.ts +362 -362
- package/src/client/hydrate.ts +340 -340
- package/src/client/prefetch-helper.ts +55 -55
- package/src/client/router.ts +11 -11
- package/src/client/runtime.ts +47 -47
- package/src/client/serialize.ts +404 -404
- package/src/client/use-fetch.ts +6 -6
- package/src/client/use-head.ts +197 -197
- package/src/client/use-sse.ts +378 -378
- package/src/client/window-state.ts +101 -101
- package/src/components/Image.tsx +162 -162
- package/src/config/validate.ts +3 -3
- package/src/config/watcher.ts +311 -311
- package/src/constants.ts +40 -40
- package/src/content/collection.ts +8 -8
- package/src/content/content-layer.ts +7 -7
- package/src/content/data-store.ts +245 -245
- package/src/content/frontmatter.ts +189 -189
- package/src/content/loader-context.ts +171 -171
- package/src/content/loaders/api.ts +216 -216
- package/src/content/loaders/file.ts +172 -172
- package/src/content/loaders/glob.ts +253 -253
- 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/prebuild.test.ts +571 -571
- package/src/content/prebuild.ts +636 -636
- package/src/content/schema.ts +20 -20
- package/src/content/sidebar.ts +630 -630
- package/src/content/slug.ts +110 -110
- 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/define.ts +11 -11
- package/src/contract/index.ts +1 -1
- package/src/contract/normalize.test.ts +276 -276
- package/src/contract/normalize.ts +410 -410
- package/src/contract/registry.test.ts +206 -206
- package/src/contract/route-helpers.ts +1 -1
- package/src/contract/rpc.ts +443 -443
- package/src/contract/schema.ts +48 -48
- package/src/contract/types.ts +58 -58
- package/src/db/__tests__/db.test.ts +482 -482
- package/src/db/index.ts +138 -138
- package/src/db/migrations/history-table.ts +345 -345
- package/src/db/migrations/index.ts +3 -3
- package/src/db/migrations/lock.ts +324 -324
- package/src/db/migrations/runner.ts +650 -650
- package/src/deploy/cache.ts +140 -140
- package/src/deploy/compile/vercel.ts +344 -344
- package/src/deploy/index.ts +87 -87
- package/src/deploy/inference/brain.ts +268 -268
- package/src/deploy/inference/context.ts +182 -182
- package/src/deploy/inference/filling-extract.ts +245 -245
- package/src/deploy/inference/heuristic.ts +182 -182
- package/src/deploy/intent.ts +173 -173
- package/src/deploy/plan.ts +178 -178
- package/src/design/__tests__/agents-link.test.ts +109 -109
- package/src/design/__tests__/extract-patch-diff.test.ts +265 -265
- package/src/design/__tests__/lint.test.ts +110 -110
- package/src/design/__tests__/parser.test.ts +195 -195
- package/src/design/__tests__/tailwind-theme.test.ts +229 -229
- package/src/design/agents-link.ts +165 -165
- package/src/design/diff.ts +138 -138
- package/src/design/extract.ts +285 -285
- package/src/design/index.ts +102 -102
- package/src/design/lint.ts +209 -209
- package/src/design/parser.ts +555 -555
- package/src/design/patch.ts +241 -241
- package/src/design/scaffold.ts +147 -147
- package/src/design/tailwind-theme.ts +441 -441
- package/src/design/types.ts +210 -210
- package/src/desktop/__tests__/webview-fallback.test.ts +254 -254
- package/src/desktop/__tests__/window.test.ts +248 -248
- package/src/desktop/__tests__/worker.test.ts +266 -266
- package/src/desktop/index.ts +43 -43
- package/src/desktop/types.ts +158 -158
- package/src/desktop/worker.ts +180 -180
- package/src/dev-error-overlay/__tests__/overlay-injector.test.ts +241 -241
- package/src/dev-error-overlay/index.ts +30 -30
- package/src/dev-error-overlay/overlay-injector.ts +243 -243
- package/src/dev-error-overlay/overlay-styles.ts +52 -52
- package/src/dev-error-overlay/types.ts +66 -66
- package/src/devtools/ai/context-builder.ts +375 -375
- package/src/devtools/ai/index.ts +25 -25
- package/src/devtools/ai/mcp-connector.ts +25 -25
- package/src/devtools/client/catchers/error-catcher.ts +344 -344
- package/src/devtools/client/catchers/index.ts +18 -18
- package/src/devtools/client/components/index.ts +39 -39
- package/src/devtools/client/components/mandu-character.tsx +331 -331
- 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 +30 -30
- package/src/devtools/client/components/panel/islands-panel.tsx +320 -320
- package/src/devtools/client/components/panel/network-panel.tsx +291 -291
- package/src/devtools/client/components/panel/panel-container.tsx +500 -500
- package/src/devtools/client/components/panel/preview-panel.tsx +46 -46
- 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/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 +265 -265
- package/src/devtools/protocol.ts +237 -237
- package/src/devtools/server/index.ts +17 -17
- package/src/devtools/server/source-context.ts +450 -450
- package/src/devtools/types.ts +35 -35
- package/src/devtools/worker/index.ts +25 -25
- package/src/devtools/worker/redaction-worker.ts +233 -233
- package/src/devtools/worker/worker-manager.ts +410 -410
- package/src/diagnose/__tests__/checks.test.ts +451 -451
- package/src/diagnose/checks.ts +832 -832
- package/src/diagnose/index.ts +17 -17
- package/src/diagnose/run.ts +93 -93
- package/src/diagnose/types.ts +53 -53
- package/src/email/__tests__/email.test.ts +355 -355
- package/src/email/index.ts +282 -282
- package/src/email/smtp.ts +64 -64
- package/src/error/domains.ts +265 -265
- package/src/error/result.ts +60 -60
- package/src/error/types.ts +6 -6
- package/src/errors/extractor.ts +409 -409
- package/src/errors/index.ts +19 -19
- package/src/filling/__tests__/session-sqlite.test.ts +454 -454
- package/src/filling/auth.ts +308 -308
- package/src/filling/cookie-codec.ts +299 -299
- package/src/filling/deps.ts +265 -265
- package/src/filling/session-sqlite.ts +617 -617
- package/src/filling/sse.ts +5 -5
- package/src/filling/ws.ts +78 -78
- package/src/generator/index.ts +3 -3
- package/src/guard/__tests__/design-inline-class.test.ts +219 -219
- package/src/guard/__tests__/tsgolint-bridge.test.ts +347 -347
- package/src/guard/analyzer.ts +360 -360
- package/src/guard/auto-correct.ts +1 -1
- package/src/guard/contract-guard.ts +9 -9
- package/src/guard/define-rule.ts +243 -243
- package/src/guard/design-inline-class.ts +393 -393
- package/src/guard/file-type.test.ts +24 -24
- package/src/guard/graph.ts +1 -1
- package/src/guard/healing.ts +36 -36
- package/src/guard/presets/atomic.ts +70 -70
- package/src/guard/presets/clean.ts +77 -77
- package/src/guard/presets/fsd.ts +79 -79
- package/src/guard/presets/hexagonal.ts +68 -68
- package/src/guard/reporter.ts +442 -442
- package/src/guard/rule-presets.ts +379 -379
- package/src/guard/semantic-slots.ts +1 -1
- package/src/guard/suggestions.ts +358 -358
- package/src/guard/tsgolint-bridge.ts +512 -512
- package/src/guard/types.ts +348 -348
- package/src/guard/watcher.ts +405 -405
- package/src/i18n/define.ts +126 -126
- package/src/i18n/index.ts +52 -52
- package/src/i18n/message-registry.ts +173 -173
- package/src/i18n/types.ts +112 -112
- package/src/id/index.ts +105 -105
- package/src/index.ts +2 -2
- package/src/kitchen/api/agent-devtools-api.ts +779 -544
- package/src/kitchen/api/errors-grouping.ts +126 -0
- package/src/kitchen/kitchen-handler.ts +192 -63
- package/src/kitchen/kitchen-ui.ts +842 -464
- package/src/logging/index.ts +22 -22
- package/src/logging/transports.ts +365 -365
- package/src/middleware/bridge.ts +147 -147
- package/src/middleware/compose.ts +134 -134
- package/src/middleware/compress.ts +62 -62
- package/src/middleware/cors.ts +47 -47
- package/src/middleware/csrf.ts +328 -328
- package/src/middleware/define.ts +132 -132
- package/src/middleware/jwt.ts +134 -134
- package/src/middleware/logger.ts +58 -58
- package/src/middleware/oauth/__tests__/oauth.test.ts +1 -1
- package/src/middleware/oauth/index.ts +505 -505
- package/src/middleware/oauth/providers.ts +115 -115
- package/src/middleware/rate-limit/index.ts +522 -522
- package/src/middleware/rate-limit/sqlite-store.ts +382 -382
- package/src/middleware/scheduler-cron.ts +96 -96
- package/src/middleware/secure/__tests__/secure.test.ts +360 -360
- package/src/middleware/secure/csp.ts +193 -193
- package/src/middleware/session.ts +174 -174
- package/src/middleware/timeout.ts +55 -55
- package/src/observability/logger-adapter.ts +36 -36
- package/src/observability/sqlite-store.ts +254 -254
- package/src/openapi/generator.ts +1 -1
- package/src/openapi/openapi.test.ts +43 -43
- package/src/perf/__tests__/user-marks.test.ts +354 -354
- package/src/perf/index.ts +133 -133
- package/src/plugins/__tests__/lifecycle-integration.test.ts +272 -272
- package/src/plugins/__tests__/runner.test.ts +409 -409
- package/src/plugins/define.ts +124 -124
- package/src/plugins/examples/dep-check-plugin.ts +80 -80
- package/src/plugins/examples/prerender-cache-plugin.ts +111 -111
- package/src/plugins/examples/sitemap-plugin.ts +65 -65
- package/src/plugins/runner.ts +361 -361
- package/src/plugins/types.ts +368 -368
- package/src/report/index.ts +1 -1
- package/src/resource/__tests__/generator.test.ts +32 -32
- package/src/resource/ddl/__tests__/diff.test.ts +639 -639
- package/src/resource/ddl/__tests__/emit.test.ts +823 -823
- package/src/resource/ddl/__tests__/snapshot.test.ts +499 -499
- package/src/resource/ddl/emit.ts +559 -559
- package/src/resource/ddl/persistence-types.ts +218 -218
- package/src/resource/ddl/type-map.ts +223 -223
- package/src/resource/ddl/types.ts +232 -232
- package/src/resource/generator-repo.ts +630 -630
- package/src/resource/schema.ts +1 -1
- package/src/router/fs-patterns.test.ts +96 -96
- package/src/router/fs-routes.ts +6 -6
- package/src/routes/index.ts +74 -74
- package/src/routes/metadata-routes.ts +427 -427
- package/src/routes/types.ts +341 -341
- package/src/runtime/__tests__/error-boundary-redaction.test.ts +141 -141
- package/src/runtime/__tests__/hdr-client.test.ts +223 -223
- package/src/runtime/__tests__/http-errors.test.ts +117 -117
- package/src/runtime/__tests__/not-found.test.ts +152 -152
- package/src/runtime/adapter.ts +47 -47
- package/src/runtime/boundary.tsx +252 -252
- package/src/runtime/cache.ts +494 -494
- package/src/runtime/compose.ts +222 -222
- package/src/runtime/fast-refresh-runtime.ts +322 -322
- package/src/runtime/handler.ts +65 -65
- package/src/runtime/handlers.ts +300 -300
- package/src/runtime/http-errors.ts +113 -113
- package/src/runtime/image-handler.ts +1 -1
- package/src/runtime/lifecycle.ts +381 -381
- package/src/runtime/logger.test.ts +345 -345
- package/src/runtime/middleware.ts +264 -264
- package/src/runtime/not-found.ts +93 -93
- package/src/runtime/openapi-endpoint.ts +236 -236
- package/src/runtime/ppr.ts +74 -74
- package/src/runtime/registry.ts +171 -171
- package/src/runtime/router.ts +105 -105
- package/src/runtime/server.ts +67 -67
- package/src/runtime/shims.ts +48 -48
- package/src/runtime/trace.ts +144 -144
- package/src/scheduler/validate.ts +169 -169
- package/src/seo/index.ts +219 -219
- package/src/seo/integration/ssr.ts +306 -306
- package/src/seo/render/basic.ts +435 -435
- package/src/seo/render/index.ts +143 -143
- package/src/seo/render/jsonld.ts +539 -539
- package/src/seo/render/opengraph.ts +197 -197
- package/src/seo/render/robots.ts +116 -116
- package/src/seo/render/sitemap.ts +137 -137
- package/src/seo/render/twitter.ts +127 -127
- 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 +104 -104
- package/src/seo/routes/index.ts +290 -290
- package/src/seo/types.ts +588 -588
- package/src/slot/validator.ts +39 -39
- package/src/storage/s3/__tests__/s3.test.ts +479 -479
- package/src/storage/s3/index.ts +412 -412
- package/src/testing/__tests__/assertions.test.ts +632 -632
- package/src/testing/__tests__/reporter.test.ts +454 -454
- package/src/testing/assertions.ts +986 -986
- package/src/testing/db.ts +157 -157
- package/src/testing/mocks.ts +203 -203
- package/src/testing/session.ts +190 -190
- package/src/types/branded.ts +56 -56
- package/src/types/index.ts +1 -1
- package/src/utils/safe-io.ts +188 -188
- package/src/utils/string-safe.ts +298 -298
- package/src/watcher/watcher.ts +18 -18
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `resolveReactCompilerConfig` — #240 Phase 2 auto-detect tests.
|
|
3
|
-
*
|
|
4
|
-
* The probe only fires when `enabled` is undefined. Explicit `true` /
|
|
5
|
-
* `false` veto the probe so user intent always wins.
|
|
6
|
-
*
|
|
7
|
-
* Cache lifetime is per-process; we reset it between cases so a probe
|
|
8
|
-
* from one fixture doesn't leak to the next.
|
|
9
|
-
*/
|
|
10
|
-
import { describe, it, expect, beforeEach } from "bun:test";
|
|
11
|
-
import fs from "node:fs/promises";
|
|
12
|
-
import os from "node:os";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
resolveReactCompilerConfig,
|
|
17
|
-
_resetReactCompilerConfigCache,
|
|
18
|
-
} from "../react-compiler-config";
|
|
19
|
-
|
|
20
|
-
async function makeRoot(prefix: string): Promise<string> {
|
|
21
|
-
return fs.mkdtemp(path.join(os.tmpdir(), `mandu-rc-${prefix}-`));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
_resetReactCompilerConfigCache();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
describe("resolveReactCompilerConfig", () => {
|
|
29
|
-
it("explicit enabled:true honours the user even when peers are missing", async () => {
|
|
30
|
-
const root = await makeRoot("explicit-on");
|
|
31
|
-
const result = resolveReactCompilerConfig({ enabled: true }, root);
|
|
32
|
-
expect(result.enabled).toBe(true);
|
|
33
|
-
expect(result.autoDetected).toBe(false);
|
|
34
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("explicit enabled:false vetos the probe", async () => {
|
|
38
|
-
const root = await makeRoot("explicit-off");
|
|
39
|
-
const result = resolveReactCompilerConfig({ enabled: false }, root);
|
|
40
|
-
expect(result.enabled).toBe(false);
|
|
41
|
-
expect(result.autoDetected).toBe(false);
|
|
42
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it("undefined enabled + missing peers → disabled silently", async () => {
|
|
46
|
-
const root = await makeRoot("auto-no-peers");
|
|
47
|
-
// Empty rootDir — no node_modules, no package.json, no peer deps.
|
|
48
|
-
const result = resolveReactCompilerConfig(undefined, root);
|
|
49
|
-
expect(result.enabled).toBe(false);
|
|
50
|
-
expect(result.autoDetected).toBe(false);
|
|
51
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it("forwards compilerConfig regardless of enabled state", async () => {
|
|
55
|
-
const root = await makeRoot("compiler-config");
|
|
56
|
-
const cfg = { compilationMode: "annotation" };
|
|
57
|
-
const result = resolveReactCompilerConfig(
|
|
58
|
-
{ enabled: true, compilerConfig: cfg },
|
|
59
|
-
root,
|
|
60
|
-
);
|
|
61
|
-
expect(result.compilerConfig).toBe(cfg);
|
|
62
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("caches by (rootDir, explicit-enabled) — second call hits cache", async () => {
|
|
66
|
-
const root = await makeRoot("cache");
|
|
67
|
-
const a = resolveReactCompilerConfig(undefined, root);
|
|
68
|
-
const b = resolveReactCompilerConfig(undefined, root);
|
|
69
|
-
// Same identity — cache hit returns the stored object.
|
|
70
|
-
expect(a).toBe(b);
|
|
71
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("treats explicit-true vs auto as separate cache keys", async () => {
|
|
75
|
-
const root = await makeRoot("cache-key");
|
|
76
|
-
const auto = resolveReactCompilerConfig(undefined, root);
|
|
77
|
-
const explicit = resolveReactCompilerConfig({ enabled: true }, root);
|
|
78
|
-
expect(auto).not.toBe(explicit);
|
|
79
|
-
expect(auto.enabled).toBe(false);
|
|
80
|
-
expect(explicit.enabled).toBe(true);
|
|
81
|
-
await fs.rm(root, { recursive: true, force: true });
|
|
82
|
-
});
|
|
83
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* `resolveReactCompilerConfig` — #240 Phase 2 auto-detect tests.
|
|
3
|
+
*
|
|
4
|
+
* The probe only fires when `enabled` is undefined. Explicit `true` /
|
|
5
|
+
* `false` veto the probe so user intent always wins.
|
|
6
|
+
*
|
|
7
|
+
* Cache lifetime is per-process; we reset it between cases so a probe
|
|
8
|
+
* from one fixture doesn't leak to the next.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach } from "bun:test";
|
|
11
|
+
import fs from "node:fs/promises";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
resolveReactCompilerConfig,
|
|
17
|
+
_resetReactCompilerConfigCache,
|
|
18
|
+
} from "../react-compiler-config";
|
|
19
|
+
|
|
20
|
+
async function makeRoot(prefix: string): Promise<string> {
|
|
21
|
+
return fs.mkdtemp(path.join(os.tmpdir(), `mandu-rc-${prefix}-`));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
_resetReactCompilerConfigCache();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("resolveReactCompilerConfig", () => {
|
|
29
|
+
it("explicit enabled:true honours the user even when peers are missing", async () => {
|
|
30
|
+
const root = await makeRoot("explicit-on");
|
|
31
|
+
const result = resolveReactCompilerConfig({ enabled: true }, root);
|
|
32
|
+
expect(result.enabled).toBe(true);
|
|
33
|
+
expect(result.autoDetected).toBe(false);
|
|
34
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("explicit enabled:false vetos the probe", async () => {
|
|
38
|
+
const root = await makeRoot("explicit-off");
|
|
39
|
+
const result = resolveReactCompilerConfig({ enabled: false }, root);
|
|
40
|
+
expect(result.enabled).toBe(false);
|
|
41
|
+
expect(result.autoDetected).toBe(false);
|
|
42
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("undefined enabled + missing peers → disabled silently", async () => {
|
|
46
|
+
const root = await makeRoot("auto-no-peers");
|
|
47
|
+
// Empty rootDir — no node_modules, no package.json, no peer deps.
|
|
48
|
+
const result = resolveReactCompilerConfig(undefined, root);
|
|
49
|
+
expect(result.enabled).toBe(false);
|
|
50
|
+
expect(result.autoDetected).toBe(false);
|
|
51
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("forwards compilerConfig regardless of enabled state", async () => {
|
|
55
|
+
const root = await makeRoot("compiler-config");
|
|
56
|
+
const cfg = { compilationMode: "annotation" };
|
|
57
|
+
const result = resolveReactCompilerConfig(
|
|
58
|
+
{ enabled: true, compilerConfig: cfg },
|
|
59
|
+
root,
|
|
60
|
+
);
|
|
61
|
+
expect(result.compilerConfig).toBe(cfg);
|
|
62
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("caches by (rootDir, explicit-enabled) — second call hits cache", async () => {
|
|
66
|
+
const root = await makeRoot("cache");
|
|
67
|
+
const a = resolveReactCompilerConfig(undefined, root);
|
|
68
|
+
const b = resolveReactCompilerConfig(undefined, root);
|
|
69
|
+
// Same identity — cache hit returns the stored object.
|
|
70
|
+
expect(a).toBe(b);
|
|
71
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("treats explicit-true vs auto as separate cache keys", async () => {
|
|
75
|
+
const root = await makeRoot("cache-key");
|
|
76
|
+
const auto = resolveReactCompilerConfig(undefined, root);
|
|
77
|
+
const explicit = resolveReactCompilerConfig({ enabled: true }, root);
|
|
78
|
+
expect(auto).not.toBe(explicit);
|
|
79
|
+
expect(auto.enabled).toBe(false);
|
|
80
|
+
expect(explicit.enabled).toBe(true);
|
|
81
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
runReactCompilerLint,
|
|
5
|
-
formatCompilerReport,
|
|
6
|
-
type ReactCompilerDiagnostic,
|
|
7
|
-
} from "../react-compiler-lint";
|
|
8
|
-
|
|
9
|
-
describe("runReactCompilerLint", () => {
|
|
10
|
-
test("returns empty result with no targets without invoking ESLint", async () => {
|
|
11
|
-
const result = await runReactCompilerLint({
|
|
12
|
-
projectRoot: process.cwd(),
|
|
13
|
-
targetFiles: [],
|
|
14
|
-
});
|
|
15
|
-
expect(result.diagnostics).toEqual([]);
|
|
16
|
-
expect(result.skipped).toBe(false);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("degrades gracefully when ESLint peer dep is missing", async () => {
|
|
20
|
-
// In a clean Mandu checkout `eslint` and
|
|
21
|
-
// `eslint-plugin-react-compiler` are not installed. The runner
|
|
22
|
-
// must report `skipped: true` + empty diagnostics + a skipReason.
|
|
23
|
-
const result = await runReactCompilerLint({
|
|
24
|
-
projectRoot: process.cwd(),
|
|
25
|
-
targetFiles: [path.resolve(__filename)],
|
|
26
|
-
});
|
|
27
|
-
// If ESLint happens to be installed in this env, diagnostics is
|
|
28
|
-
// either empty (this file has no bailouts) or the runner ran
|
|
29
|
-
// successfully. Either shape is valid — the contract we care
|
|
30
|
-
// about is "no throw + typed result."
|
|
31
|
-
expect(Array.isArray(result.diagnostics)).toBe(true);
|
|
32
|
-
expect(typeof result.skipped).toBe("boolean");
|
|
33
|
-
if (result.skipped) {
|
|
34
|
-
expect(typeof result.skipReason).toBe("string");
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe("formatCompilerReport", () => {
|
|
40
|
-
test("returns the no-bailouts sentinel for empty input", () => {
|
|
41
|
-
expect(formatCompilerReport([])).toContain("no bailouts detected");
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("summarises bailouts with file counts + bullet list", () => {
|
|
45
|
-
const diagnostics: ReactCompilerDiagnostic[] = [
|
|
46
|
-
{
|
|
47
|
-
file: "/app/todos/todo.island.tsx",
|
|
48
|
-
line: 42,
|
|
49
|
-
column: 5,
|
|
50
|
-
message: "Cannot memoize: ref escape in closure.",
|
|
51
|
-
ruleId: "react-compiler/react-compiler",
|
|
52
|
-
severity: "warning",
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
file: "/app/todos/todo.island.tsx",
|
|
56
|
-
line: 87,
|
|
57
|
-
column: 3,
|
|
58
|
-
message: "Cannot memoize: conditional hook call.",
|
|
59
|
-
ruleId: "react-compiler/react-compiler",
|
|
60
|
-
severity: "warning",
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
file: "/app/dashboard/chart.client.tsx",
|
|
64
|
-
line: 14,
|
|
65
|
-
column: 9,
|
|
66
|
-
message: "Cannot memoize: mutation of a shared value.",
|
|
67
|
-
ruleId: "react-compiler/react-compiler",
|
|
68
|
-
severity: "warning",
|
|
69
|
-
},
|
|
70
|
-
];
|
|
71
|
-
const out = formatCompilerReport(diagnostics);
|
|
72
|
-
expect(out).toContain("3 bailout(s) in 2 file(s)");
|
|
73
|
-
expect(out).toContain("todo.island.tsx:42:5");
|
|
74
|
-
expect(out).toContain("chart.client.tsx:14:9");
|
|
75
|
-
expect(out).toContain("https://react.dev");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("truncates past the limit with a '... N more' tail", () => {
|
|
79
|
-
const diagnostics: ReactCompilerDiagnostic[] = Array.from(
|
|
80
|
-
{ length: 30 },
|
|
81
|
-
(_, i) => ({
|
|
82
|
-
file: `/app/x/c${i}.island.tsx`,
|
|
83
|
-
line: i + 1,
|
|
84
|
-
column: 1,
|
|
85
|
-
message: "bailout",
|
|
86
|
-
ruleId: "react-compiler/react-compiler",
|
|
87
|
-
severity: "warning" as const,
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
const out = formatCompilerReport(diagnostics, { limit: 5 });
|
|
91
|
-
expect(out).toContain("30 bailout(s)");
|
|
92
|
-
expect(out).toContain("… and 25 more");
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
test("uses relative paths when projectRoot is provided", () => {
|
|
96
|
-
const diagnostic: ReactCompilerDiagnostic = {
|
|
97
|
-
file: path.resolve("/project/app/todo.island.tsx"),
|
|
98
|
-
line: 1,
|
|
99
|
-
column: 1,
|
|
100
|
-
message: "bailout",
|
|
101
|
-
ruleId: "react-compiler/react-compiler",
|
|
102
|
-
severity: "warning",
|
|
103
|
-
};
|
|
104
|
-
const out = formatCompilerReport([diagnostic], {
|
|
105
|
-
projectRoot: path.resolve("/project"),
|
|
106
|
-
});
|
|
107
|
-
expect(out).toContain(path.join("app", "todo.island.tsx"));
|
|
108
|
-
expect(out).not.toContain(path.resolve("/project/app"));
|
|
109
|
-
});
|
|
110
|
-
});
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
runReactCompilerLint,
|
|
5
|
+
formatCompilerReport,
|
|
6
|
+
type ReactCompilerDiagnostic,
|
|
7
|
+
} from "../react-compiler-lint";
|
|
8
|
+
|
|
9
|
+
describe("runReactCompilerLint", () => {
|
|
10
|
+
test("returns empty result with no targets without invoking ESLint", async () => {
|
|
11
|
+
const result = await runReactCompilerLint({
|
|
12
|
+
projectRoot: process.cwd(),
|
|
13
|
+
targetFiles: [],
|
|
14
|
+
});
|
|
15
|
+
expect(result.diagnostics).toEqual([]);
|
|
16
|
+
expect(result.skipped).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("degrades gracefully when ESLint peer dep is missing", async () => {
|
|
20
|
+
// In a clean Mandu checkout `eslint` and
|
|
21
|
+
// `eslint-plugin-react-compiler` are not installed. The runner
|
|
22
|
+
// must report `skipped: true` + empty diagnostics + a skipReason.
|
|
23
|
+
const result = await runReactCompilerLint({
|
|
24
|
+
projectRoot: process.cwd(),
|
|
25
|
+
targetFiles: [path.resolve(__filename)],
|
|
26
|
+
});
|
|
27
|
+
// If ESLint happens to be installed in this env, diagnostics is
|
|
28
|
+
// either empty (this file has no bailouts) or the runner ran
|
|
29
|
+
// successfully. Either shape is valid — the contract we care
|
|
30
|
+
// about is "no throw + typed result."
|
|
31
|
+
expect(Array.isArray(result.diagnostics)).toBe(true);
|
|
32
|
+
expect(typeof result.skipped).toBe("boolean");
|
|
33
|
+
if (result.skipped) {
|
|
34
|
+
expect(typeof result.skipReason).toBe("string");
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("formatCompilerReport", () => {
|
|
40
|
+
test("returns the no-bailouts sentinel for empty input", () => {
|
|
41
|
+
expect(formatCompilerReport([])).toContain("no bailouts detected");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("summarises bailouts with file counts + bullet list", () => {
|
|
45
|
+
const diagnostics: ReactCompilerDiagnostic[] = [
|
|
46
|
+
{
|
|
47
|
+
file: "/app/todos/todo.island.tsx",
|
|
48
|
+
line: 42,
|
|
49
|
+
column: 5,
|
|
50
|
+
message: "Cannot memoize: ref escape in closure.",
|
|
51
|
+
ruleId: "react-compiler/react-compiler",
|
|
52
|
+
severity: "warning",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
file: "/app/todos/todo.island.tsx",
|
|
56
|
+
line: 87,
|
|
57
|
+
column: 3,
|
|
58
|
+
message: "Cannot memoize: conditional hook call.",
|
|
59
|
+
ruleId: "react-compiler/react-compiler",
|
|
60
|
+
severity: "warning",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
file: "/app/dashboard/chart.client.tsx",
|
|
64
|
+
line: 14,
|
|
65
|
+
column: 9,
|
|
66
|
+
message: "Cannot memoize: mutation of a shared value.",
|
|
67
|
+
ruleId: "react-compiler/react-compiler",
|
|
68
|
+
severity: "warning",
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
const out = formatCompilerReport(diagnostics);
|
|
72
|
+
expect(out).toContain("3 bailout(s) in 2 file(s)");
|
|
73
|
+
expect(out).toContain("todo.island.tsx:42:5");
|
|
74
|
+
expect(out).toContain("chart.client.tsx:14:9");
|
|
75
|
+
expect(out).toContain("https://react.dev");
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("truncates past the limit with a '... N more' tail", () => {
|
|
79
|
+
const diagnostics: ReactCompilerDiagnostic[] = Array.from(
|
|
80
|
+
{ length: 30 },
|
|
81
|
+
(_, i) => ({
|
|
82
|
+
file: `/app/x/c${i}.island.tsx`,
|
|
83
|
+
line: i + 1,
|
|
84
|
+
column: 1,
|
|
85
|
+
message: "bailout",
|
|
86
|
+
ruleId: "react-compiler/react-compiler",
|
|
87
|
+
severity: "warning" as const,
|
|
88
|
+
}),
|
|
89
|
+
);
|
|
90
|
+
const out = formatCompilerReport(diagnostics, { limit: 5 });
|
|
91
|
+
expect(out).toContain("30 bailout(s)");
|
|
92
|
+
expect(out).toContain("… and 25 more");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("uses relative paths when projectRoot is provided", () => {
|
|
96
|
+
const diagnostic: ReactCompilerDiagnostic = {
|
|
97
|
+
file: path.resolve("/project/app/todo.island.tsx"),
|
|
98
|
+
line: 1,
|
|
99
|
+
column: 1,
|
|
100
|
+
message: "bailout",
|
|
101
|
+
ruleId: "react-compiler/react-compiler",
|
|
102
|
+
severity: "warning",
|
|
103
|
+
};
|
|
104
|
+
const out = formatCompilerReport([diagnostic], {
|
|
105
|
+
projectRoot: path.resolve("/project"),
|
|
106
|
+
});
|
|
107
|
+
expect(out).toContain(path.join("app", "todo.island.tsx"));
|
|
108
|
+
expect(out).not.toContain(path.resolve("/project/app"));
|
|
109
|
+
});
|
|
110
|
+
});
|