@mandujs/core 0.53.3 → 0.54.1
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 +1 -1
- 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,155 +1,155 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bun bundler plugin — hard-fail on direct `__generated__/` imports.
|
|
3
|
-
*
|
|
4
|
-
* Background
|
|
5
|
-
* ──────────
|
|
6
|
-
* The Guard rule `INVALID_GENERATED_IMPORT` (see `guard/check.ts`) already
|
|
7
|
-
* scans source files for literal `import … from '…generated…'` statements,
|
|
8
|
-
* but it only runs when the user (or CI) invokes `mandu guard check`.
|
|
9
|
-
* Autonomous coding agents routinely bypass that step. This plugin closes
|
|
10
|
-
* the gap at the bundler level: every `mandu dev` / `mandu build` pass
|
|
11
|
-
* installs it by default, and any import whose specifier contains
|
|
12
|
-
* `__generated__` fails the build with a structured, actionable error.
|
|
13
|
-
*
|
|
14
|
-
* Design
|
|
15
|
-
* ──────
|
|
16
|
-
* - `onResolve({ filter: /__generated__/ })` — Bun hands us every import
|
|
17
|
-
* whose *specifier* matches the regex, along with the importer's path
|
|
18
|
-
* (`args.importer`). We never return a result; we always throw.
|
|
19
|
-
* - The error is `ForbiddenGeneratedImportError`, a named subclass of
|
|
20
|
-
* `Error`. Tests can `instanceof`-check; Bun surfaces `error.message` in
|
|
21
|
-
* its `result.logs` output for CLI display.
|
|
22
|
-
* - The message is built via the shared Guard helper
|
|
23
|
-
* (`buildForbiddenGeneratedImportMessage`) so the bundler path and the
|
|
24
|
-
* static Guard pass cannot drift out of sync.
|
|
25
|
-
*
|
|
26
|
-
* Legitimate escape hatches
|
|
27
|
-
* ─────────────────────────
|
|
28
|
-
* 1. `getGenerated()` / `tryGetGenerated()` from `@mandujs/core/runtime`
|
|
29
|
-
* read through a global manifest slot (`__MANDU_MANIFEST__`). They do
|
|
30
|
-
* NOT trigger an ESM import for the generated artifact, so they never
|
|
31
|
-
* hit this plugin. That is the officially supported API.
|
|
32
|
-
* 2. `import type` statements are allowed by the rule — TS erases them
|
|
33
|
-
* before emit, so they never become runtime imports. However, a
|
|
34
|
-
* bundler `onResolve` hook cannot distinguish `import type` from a
|
|
35
|
-
* value import because Bun strips the `type` keyword before plugin
|
|
36
|
-
* dispatch. For this reason the plugin exposes an `allowImporter`
|
|
37
|
-
* option (defaulted to recognise `@mandujs/core/runtime` internals)
|
|
38
|
-
* but deliberately does NOT try to parse the source for `type`-only
|
|
39
|
-
* imports. User type imports go through the type-checker, not the
|
|
40
|
-
* bundler, so they remain unaffected in practice.
|
|
41
|
-
* 3. The per-project opt-out lives in `ManduConfig.guard.blockGeneratedImport
|
|
42
|
-
* = false`. The plugin is simply not installed when the flag is off.
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
import type { BunPlugin } from "bun";
|
|
46
|
-
import {
|
|
47
|
-
buildForbiddenGeneratedImportMessage,
|
|
48
|
-
FORBIDDEN_GENERATED_IMPORT_SUGGESTION,
|
|
49
|
-
GENERATED_IMPORT_DOCS_URL,
|
|
50
|
-
} from "../../guard/check";
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Raised by the plugin's `onResolve` hook. Named so tests can
|
|
54
|
-
* `instanceof`-check, and so Bun's log output clearly attributes the
|
|
55
|
-
* failure to the plugin.
|
|
56
|
-
*/
|
|
57
|
-
export class ForbiddenGeneratedImportError extends Error {
|
|
58
|
-
/** The literal `from "…"` specifier that tripped the guard. */
|
|
59
|
-
readonly specifier: string;
|
|
60
|
-
/** Absolute path of the file that issued the import (best-effort). */
|
|
61
|
-
readonly importer: string;
|
|
62
|
-
/** Docs URL that explains the official replacement. */
|
|
63
|
-
readonly docsUrl: string;
|
|
64
|
-
/** Short, one-line remediation hint. */
|
|
65
|
-
readonly suggestion: string;
|
|
66
|
-
|
|
67
|
-
constructor(specifier: string, importer: string) {
|
|
68
|
-
const message =
|
|
69
|
-
`${buildForbiddenGeneratedImportMessage(specifier)}\n` +
|
|
70
|
-
` Importer: ${importer || "<unknown>"}\n` +
|
|
71
|
-
` Replacement: import { getGenerated } from "@mandujs/core/runtime";\n` +
|
|
72
|
-
` Then: const data = getGenerated(<key>);\n` +
|
|
73
|
-
` Docs: ${GENERATED_IMPORT_DOCS_URL}`;
|
|
74
|
-
super(message);
|
|
75
|
-
this.name = "ForbiddenGeneratedImportError";
|
|
76
|
-
this.specifier = specifier;
|
|
77
|
-
this.importer = importer;
|
|
78
|
-
this.docsUrl = GENERATED_IMPORT_DOCS_URL;
|
|
79
|
-
this.suggestion = FORBIDDEN_GENERATED_IMPORT_SUGGESTION;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface BlockGeneratedImportsOptions {
|
|
84
|
-
/**
|
|
85
|
-
* Predicate that returns `true` when the importer should be exempted
|
|
86
|
-
* from the rule. Default exempts `@mandujs/core/runtime` (which in
|
|
87
|
-
* principle never imports `__generated__`, but is listed here so
|
|
88
|
-
* framework boot code cannot trip over itself during upgrades).
|
|
89
|
-
*/
|
|
90
|
-
allowImporter?: (importerPath: string) => boolean;
|
|
91
|
-
/**
|
|
92
|
-
* Custom filter regex applied to the import specifier. Defaults to
|
|
93
|
-
* `/__generated__/`. Mandu ships a single default — exposing this for
|
|
94
|
-
* test harnesses that want to narrow or broaden the filter.
|
|
95
|
-
*/
|
|
96
|
-
filter?: RegExp;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Default exempt predicate — matches `@mandujs/core/runtime` internals.
|
|
101
|
-
* The runtime package reads generated artifacts via the global registry,
|
|
102
|
-
* so in practice it never imports `__generated__/*`. Kept as a belt-and-
|
|
103
|
-
* suspenders guard against self-inflicted regressions.
|
|
104
|
-
*/
|
|
105
|
-
export function defaultAllowImporter(importerPath: string): boolean {
|
|
106
|
-
if (!importerPath) return false;
|
|
107
|
-
// Normalize Windows backslashes so a single check covers both platforms.
|
|
108
|
-
const norm = importerPath.replace(/\\/g, "/");
|
|
109
|
-
return (
|
|
110
|
-
norm.includes("/@mandujs/core/runtime/") ||
|
|
111
|
-
norm.includes("/packages/core/src/runtime/") ||
|
|
112
|
-
norm.includes("packages/core/src/runtime/")
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Build a `BunPlugin` that blocks direct `__generated__/` imports.
|
|
118
|
-
*
|
|
119
|
-
* Usage — call from `defaultBundlerPlugins(config)` (see `./index.ts`).
|
|
120
|
-
* Every `safeBuild` / `Bun.build` invocation in Mandu funnels through
|
|
121
|
-
* that helper, so a single install point enforces the rule everywhere.
|
|
122
|
-
*/
|
|
123
|
-
export function blockGeneratedImports(
|
|
124
|
-
options: BlockGeneratedImportsOptions = {},
|
|
125
|
-
): BunPlugin {
|
|
126
|
-
const filter = options.filter ?? /__generated__/;
|
|
127
|
-
const allowImporter = options.allowImporter ?? defaultAllowImporter;
|
|
128
|
-
|
|
129
|
-
return {
|
|
130
|
-
name: "mandu:block-generated-imports",
|
|
131
|
-
setup(build) {
|
|
132
|
-
build.onResolve({ filter }, (args) => {
|
|
133
|
-
// Normalise the specifier so a Windows-style import (which would
|
|
134
|
-
// be exotic but technically legal in some toolchains) is still
|
|
135
|
-
// caught.
|
|
136
|
-
const specifier = args.path;
|
|
137
|
-
const importer = args.importer ?? "";
|
|
138
|
-
|
|
139
|
-
if (allowImporter(importer)) {
|
|
140
|
-
// Internal runtime code gets a pass. Return `undefined` so
|
|
141
|
-
// Bun resolves the path through its normal pipeline.
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Throw a structured error. Bun surfaces `error.message` in
|
|
146
|
-
// `BuildResult.logs` (non-success) or re-throws on an exception
|
|
147
|
-
// path; either way the message reaches the developer.
|
|
148
|
-
throw new ForbiddenGeneratedImportError(specifier, importer);
|
|
149
|
-
});
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/** Exported for unit-test convenience — keep the filter text assertable. */
|
|
155
|
-
export const DEFAULT_BLOCK_FILTER = /__generated__/;
|
|
1
|
+
/**
|
|
2
|
+
* Bun bundler plugin — hard-fail on direct `__generated__/` imports.
|
|
3
|
+
*
|
|
4
|
+
* Background
|
|
5
|
+
* ──────────
|
|
6
|
+
* The Guard rule `INVALID_GENERATED_IMPORT` (see `guard/check.ts`) already
|
|
7
|
+
* scans source files for literal `import … from '…generated…'` statements,
|
|
8
|
+
* but it only runs when the user (or CI) invokes `mandu guard check`.
|
|
9
|
+
* Autonomous coding agents routinely bypass that step. This plugin closes
|
|
10
|
+
* the gap at the bundler level: every `mandu dev` / `mandu build` pass
|
|
11
|
+
* installs it by default, and any import whose specifier contains
|
|
12
|
+
* `__generated__` fails the build with a structured, actionable error.
|
|
13
|
+
*
|
|
14
|
+
* Design
|
|
15
|
+
* ──────
|
|
16
|
+
* - `onResolve({ filter: /__generated__/ })` — Bun hands us every import
|
|
17
|
+
* whose *specifier* matches the regex, along with the importer's path
|
|
18
|
+
* (`args.importer`). We never return a result; we always throw.
|
|
19
|
+
* - The error is `ForbiddenGeneratedImportError`, a named subclass of
|
|
20
|
+
* `Error`. Tests can `instanceof`-check; Bun surfaces `error.message` in
|
|
21
|
+
* its `result.logs` output for CLI display.
|
|
22
|
+
* - The message is built via the shared Guard helper
|
|
23
|
+
* (`buildForbiddenGeneratedImportMessage`) so the bundler path and the
|
|
24
|
+
* static Guard pass cannot drift out of sync.
|
|
25
|
+
*
|
|
26
|
+
* Legitimate escape hatches
|
|
27
|
+
* ─────────────────────────
|
|
28
|
+
* 1. `getGenerated()` / `tryGetGenerated()` from `@mandujs/core/runtime`
|
|
29
|
+
* read through a global manifest slot (`__MANDU_MANIFEST__`). They do
|
|
30
|
+
* NOT trigger an ESM import for the generated artifact, so they never
|
|
31
|
+
* hit this plugin. That is the officially supported API.
|
|
32
|
+
* 2. `import type` statements are allowed by the rule — TS erases them
|
|
33
|
+
* before emit, so they never become runtime imports. However, a
|
|
34
|
+
* bundler `onResolve` hook cannot distinguish `import type` from a
|
|
35
|
+
* value import because Bun strips the `type` keyword before plugin
|
|
36
|
+
* dispatch. For this reason the plugin exposes an `allowImporter`
|
|
37
|
+
* option (defaulted to recognise `@mandujs/core/runtime` internals)
|
|
38
|
+
* but deliberately does NOT try to parse the source for `type`-only
|
|
39
|
+
* imports. User type imports go through the type-checker, not the
|
|
40
|
+
* bundler, so they remain unaffected in practice.
|
|
41
|
+
* 3. The per-project opt-out lives in `ManduConfig.guard.blockGeneratedImport
|
|
42
|
+
* = false`. The plugin is simply not installed when the flag is off.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import type { BunPlugin } from "bun";
|
|
46
|
+
import {
|
|
47
|
+
buildForbiddenGeneratedImportMessage,
|
|
48
|
+
FORBIDDEN_GENERATED_IMPORT_SUGGESTION,
|
|
49
|
+
GENERATED_IMPORT_DOCS_URL,
|
|
50
|
+
} from "../../guard/check";
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Raised by the plugin's `onResolve` hook. Named so tests can
|
|
54
|
+
* `instanceof`-check, and so Bun's log output clearly attributes the
|
|
55
|
+
* failure to the plugin.
|
|
56
|
+
*/
|
|
57
|
+
export class ForbiddenGeneratedImportError extends Error {
|
|
58
|
+
/** The literal `from "…"` specifier that tripped the guard. */
|
|
59
|
+
readonly specifier: string;
|
|
60
|
+
/** Absolute path of the file that issued the import (best-effort). */
|
|
61
|
+
readonly importer: string;
|
|
62
|
+
/** Docs URL that explains the official replacement. */
|
|
63
|
+
readonly docsUrl: string;
|
|
64
|
+
/** Short, one-line remediation hint. */
|
|
65
|
+
readonly suggestion: string;
|
|
66
|
+
|
|
67
|
+
constructor(specifier: string, importer: string) {
|
|
68
|
+
const message =
|
|
69
|
+
`${buildForbiddenGeneratedImportMessage(specifier)}\n` +
|
|
70
|
+
` Importer: ${importer || "<unknown>"}\n` +
|
|
71
|
+
` Replacement: import { getGenerated } from "@mandujs/core/runtime";\n` +
|
|
72
|
+
` Then: const data = getGenerated(<key>);\n` +
|
|
73
|
+
` Docs: ${GENERATED_IMPORT_DOCS_URL}`;
|
|
74
|
+
super(message);
|
|
75
|
+
this.name = "ForbiddenGeneratedImportError";
|
|
76
|
+
this.specifier = specifier;
|
|
77
|
+
this.importer = importer;
|
|
78
|
+
this.docsUrl = GENERATED_IMPORT_DOCS_URL;
|
|
79
|
+
this.suggestion = FORBIDDEN_GENERATED_IMPORT_SUGGESTION;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface BlockGeneratedImportsOptions {
|
|
84
|
+
/**
|
|
85
|
+
* Predicate that returns `true` when the importer should be exempted
|
|
86
|
+
* from the rule. Default exempts `@mandujs/core/runtime` (which in
|
|
87
|
+
* principle never imports `__generated__`, but is listed here so
|
|
88
|
+
* framework boot code cannot trip over itself during upgrades).
|
|
89
|
+
*/
|
|
90
|
+
allowImporter?: (importerPath: string) => boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Custom filter regex applied to the import specifier. Defaults to
|
|
93
|
+
* `/__generated__/`. Mandu ships a single default — exposing this for
|
|
94
|
+
* test harnesses that want to narrow or broaden the filter.
|
|
95
|
+
*/
|
|
96
|
+
filter?: RegExp;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Default exempt predicate — matches `@mandujs/core/runtime` internals.
|
|
101
|
+
* The runtime package reads generated artifacts via the global registry,
|
|
102
|
+
* so in practice it never imports `__generated__/*`. Kept as a belt-and-
|
|
103
|
+
* suspenders guard against self-inflicted regressions.
|
|
104
|
+
*/
|
|
105
|
+
export function defaultAllowImporter(importerPath: string): boolean {
|
|
106
|
+
if (!importerPath) return false;
|
|
107
|
+
// Normalize Windows backslashes so a single check covers both platforms.
|
|
108
|
+
const norm = importerPath.replace(/\\/g, "/");
|
|
109
|
+
return (
|
|
110
|
+
norm.includes("/@mandujs/core/runtime/") ||
|
|
111
|
+
norm.includes("/packages/core/src/runtime/") ||
|
|
112
|
+
norm.includes("packages/core/src/runtime/")
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Build a `BunPlugin` that blocks direct `__generated__/` imports.
|
|
118
|
+
*
|
|
119
|
+
* Usage — call from `defaultBundlerPlugins(config)` (see `./index.ts`).
|
|
120
|
+
* Every `safeBuild` / `Bun.build` invocation in Mandu funnels through
|
|
121
|
+
* that helper, so a single install point enforces the rule everywhere.
|
|
122
|
+
*/
|
|
123
|
+
export function blockGeneratedImports(
|
|
124
|
+
options: BlockGeneratedImportsOptions = {},
|
|
125
|
+
): BunPlugin {
|
|
126
|
+
const filter = options.filter ?? /__generated__/;
|
|
127
|
+
const allowImporter = options.allowImporter ?? defaultAllowImporter;
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
name: "mandu:block-generated-imports",
|
|
131
|
+
setup(build) {
|
|
132
|
+
build.onResolve({ filter }, (args) => {
|
|
133
|
+
// Normalise the specifier so a Windows-style import (which would
|
|
134
|
+
// be exotic but technically legal in some toolchains) is still
|
|
135
|
+
// caught.
|
|
136
|
+
const specifier = args.path;
|
|
137
|
+
const importer = args.importer ?? "";
|
|
138
|
+
|
|
139
|
+
if (allowImporter(importer)) {
|
|
140
|
+
// Internal runtime code gets a pass. Return `undefined` so
|
|
141
|
+
// Bun resolves the path through its normal pipeline.
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Throw a structured error. Bun surfaces `error.message` in
|
|
146
|
+
// `BuildResult.logs` (non-success) or re-throws on an exception
|
|
147
|
+
// path; either way the message reaches the developer.
|
|
148
|
+
throw new ForbiddenGeneratedImportError(specifier, importer);
|
|
149
|
+
});
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Exported for unit-test convenience — keep the filter text assertable. */
|
|
155
|
+
export const DEFAULT_BLOCK_FILTER = /__generated__/;
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bundler-plugin barrel.
|
|
3
|
-
*
|
|
4
|
-
* `defaultBundlerPlugins()` is the single choke point for the plugin
|
|
5
|
-
* set that Mandu installs on every `Bun.build` invocation. Adding a new
|
|
6
|
-
* default-on plugin means adding it here — every call-site in
|
|
7
|
-
* `bundler/build.ts` and `cli/src/util/bun.ts` composes the result of
|
|
8
|
-
* this helper with any build-specific plugins.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { BunPlugin } from "bun";
|
|
12
|
-
import {
|
|
13
|
-
blockGeneratedImports,
|
|
14
|
-
type BlockGeneratedImportsOptions,
|
|
15
|
-
} from "./block-generated-imports";
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
blockGeneratedImports,
|
|
19
|
-
ForbiddenGeneratedImportError,
|
|
20
|
-
defaultAllowImporter,
|
|
21
|
-
DEFAULT_BLOCK_FILTER,
|
|
22
|
-
type BlockGeneratedImportsOptions,
|
|
23
|
-
} from "./block-generated-imports";
|
|
24
|
-
|
|
25
|
-
export {
|
|
26
|
-
reactCompiler,
|
|
27
|
-
type ReactCompilerPluginOptions,
|
|
28
|
-
} from "./react-compiler";
|
|
29
|
-
|
|
30
|
-
export {
|
|
31
|
-
runReactCompilerLint,
|
|
32
|
-
formatCompilerReport,
|
|
33
|
-
type ReactCompilerDiagnostic,
|
|
34
|
-
type RunReactCompilerLintOptions,
|
|
35
|
-
type RunReactCompilerLintResult,
|
|
36
|
-
type FormatCompilerReportOptions,
|
|
37
|
-
} from "./react-compiler-lint";
|
|
38
|
-
|
|
39
|
-
export {
|
|
40
|
-
resolveReactCompilerConfig,
|
|
41
|
-
type RawReactCompilerConfig,
|
|
42
|
-
type ResolvedReactCompilerConfig,
|
|
43
|
-
} from "./react-compiler-config";
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Subset of `ManduConfig.guard` consumed by `defaultBundlerPlugins()`.
|
|
47
|
-
* We deliberately don't import the full `ManduConfig` type to keep the
|
|
48
|
-
* plugins module cycle-free.
|
|
49
|
-
*/
|
|
50
|
-
export interface DefaultBundlerPluginsConfig {
|
|
51
|
-
guard?: {
|
|
52
|
-
blockGeneratedImport?: boolean;
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface DefaultBundlerPluginsOptions {
|
|
57
|
-
/** Mandu config (only `guard.blockGeneratedImport` is consulted). */
|
|
58
|
-
config?: DefaultBundlerPluginsConfig;
|
|
59
|
-
/** Override options for the block-generated-imports plugin. */
|
|
60
|
-
blockGeneratedImports?: BlockGeneratedImportsOptions;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Compose Mandu's default plugin list. Current contents:
|
|
65
|
-
*
|
|
66
|
-
* - `mandu:block-generated-imports` — hard-fail on direct
|
|
67
|
-
* `__generated__/` imports. Opt-out via
|
|
68
|
-
* `config.guard.blockGeneratedImport = false`.
|
|
69
|
-
*
|
|
70
|
-
* Always returns a fresh array; callers are free to concat build-local
|
|
71
|
-
* plugins (e.g. `fastRefreshPlugin()` in dev) without mutating the
|
|
72
|
-
* default set.
|
|
73
|
-
*/
|
|
74
|
-
export function defaultBundlerPlugins(
|
|
75
|
-
options: DefaultBundlerPluginsOptions = {},
|
|
76
|
-
): BunPlugin[] {
|
|
77
|
-
const plugins: BunPlugin[] = [];
|
|
78
|
-
const blockEnabled = options.config?.guard?.blockGeneratedImport !== false;
|
|
79
|
-
if (blockEnabled) {
|
|
80
|
-
plugins.push(blockGeneratedImports(options.blockGeneratedImports));
|
|
81
|
-
}
|
|
82
|
-
return plugins;
|
|
83
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Bundler-plugin barrel.
|
|
3
|
+
*
|
|
4
|
+
* `defaultBundlerPlugins()` is the single choke point for the plugin
|
|
5
|
+
* set that Mandu installs on every `Bun.build` invocation. Adding a new
|
|
6
|
+
* default-on plugin means adding it here — every call-site in
|
|
7
|
+
* `bundler/build.ts` and `cli/src/util/bun.ts` composes the result of
|
|
8
|
+
* this helper with any build-specific plugins.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { BunPlugin } from "bun";
|
|
12
|
+
import {
|
|
13
|
+
blockGeneratedImports,
|
|
14
|
+
type BlockGeneratedImportsOptions,
|
|
15
|
+
} from "./block-generated-imports";
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
blockGeneratedImports,
|
|
19
|
+
ForbiddenGeneratedImportError,
|
|
20
|
+
defaultAllowImporter,
|
|
21
|
+
DEFAULT_BLOCK_FILTER,
|
|
22
|
+
type BlockGeneratedImportsOptions,
|
|
23
|
+
} from "./block-generated-imports";
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
reactCompiler,
|
|
27
|
+
type ReactCompilerPluginOptions,
|
|
28
|
+
} from "./react-compiler";
|
|
29
|
+
|
|
30
|
+
export {
|
|
31
|
+
runReactCompilerLint,
|
|
32
|
+
formatCompilerReport,
|
|
33
|
+
type ReactCompilerDiagnostic,
|
|
34
|
+
type RunReactCompilerLintOptions,
|
|
35
|
+
type RunReactCompilerLintResult,
|
|
36
|
+
type FormatCompilerReportOptions,
|
|
37
|
+
} from "./react-compiler-lint";
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
resolveReactCompilerConfig,
|
|
41
|
+
type RawReactCompilerConfig,
|
|
42
|
+
type ResolvedReactCompilerConfig,
|
|
43
|
+
} from "./react-compiler-config";
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Subset of `ManduConfig.guard` consumed by `defaultBundlerPlugins()`.
|
|
47
|
+
* We deliberately don't import the full `ManduConfig` type to keep the
|
|
48
|
+
* plugins module cycle-free.
|
|
49
|
+
*/
|
|
50
|
+
export interface DefaultBundlerPluginsConfig {
|
|
51
|
+
guard?: {
|
|
52
|
+
blockGeneratedImport?: boolean;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface DefaultBundlerPluginsOptions {
|
|
57
|
+
/** Mandu config (only `guard.blockGeneratedImport` is consulted). */
|
|
58
|
+
config?: DefaultBundlerPluginsConfig;
|
|
59
|
+
/** Override options for the block-generated-imports plugin. */
|
|
60
|
+
blockGeneratedImports?: BlockGeneratedImportsOptions;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Compose Mandu's default plugin list. Current contents:
|
|
65
|
+
*
|
|
66
|
+
* - `mandu:block-generated-imports` — hard-fail on direct
|
|
67
|
+
* `__generated__/` imports. Opt-out via
|
|
68
|
+
* `config.guard.blockGeneratedImport = false`.
|
|
69
|
+
*
|
|
70
|
+
* Always returns a fresh array; callers are free to concat build-local
|
|
71
|
+
* plugins (e.g. `fastRefreshPlugin()` in dev) without mutating the
|
|
72
|
+
* default set.
|
|
73
|
+
*/
|
|
74
|
+
export function defaultBundlerPlugins(
|
|
75
|
+
options: DefaultBundlerPluginsOptions = {},
|
|
76
|
+
): BunPlugin[] {
|
|
77
|
+
const plugins: BunPlugin[] = [];
|
|
78
|
+
const blockEnabled = options.config?.guard?.blockGeneratedImport !== false;
|
|
79
|
+
if (blockEnabled) {
|
|
80
|
+
plugins.push(blockGeneratedImports(options.blockGeneratedImports));
|
|
81
|
+
}
|
|
82
|
+
return plugins;
|
|
83
|
+
}
|