@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
package/src/perf/index.ts
CHANGED
|
@@ -1,133 +1,133 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mandu Perf Module
|
|
3
|
-
*
|
|
4
|
-
* Lightweight, opt-in measurement markers built on `Bun.nanoseconds()`.
|
|
5
|
-
*
|
|
6
|
-
* Enable at process boot with `MANDU_PERF=1`. When disabled, every function is
|
|
7
|
-
* a single-branch no-op (no allocation, no Map lookups, no logging) so it is
|
|
8
|
-
* safe to sprinkle markers across hot paths.
|
|
9
|
-
*
|
|
10
|
-
* Rationale for `console.log` (not the structured logger):
|
|
11
|
-
* measurement is a cross-cutting concern and must not depend on the log
|
|
12
|
-
* pipeline it may itself be measuring. Keeping the output path trivial also
|
|
13
|
-
* preserves the "zero-overhead when disabled, minimal overhead when enabled"
|
|
14
|
-
* contract.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```ts
|
|
18
|
-
* import { mark, measure, withPerf } from "@mandujs/core/perf";
|
|
19
|
-
*
|
|
20
|
-
* mark("build:start");
|
|
21
|
-
* await doWork();
|
|
22
|
-
* measure("full build", "build:start");
|
|
23
|
-
*
|
|
24
|
-
* const result = await withPerf("ssr:render", () => render(route));
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* @module perf
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
// Module-load snapshot. `isPerfEnabled()` is a stable answer per process.
|
|
31
|
-
let enabled: boolean = process.env.MANDU_PERF === "1";
|
|
32
|
-
|
|
33
|
-
// Lazily-initialized marker table. Stays `null` when disabled so no allocation
|
|
34
|
-
// occurs on the disabled fast path.
|
|
35
|
-
let marks: Map<string, number> | null = null;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Whether perf markers are active for this process.
|
|
39
|
-
*
|
|
40
|
-
* Cached at module load from `MANDU_PERF=1`; changing the env var afterwards
|
|
41
|
-
* has no effect (see `_resetCacheForTesting` for test-only overrides).
|
|
42
|
-
*/
|
|
43
|
-
export function isPerfEnabled(): boolean {
|
|
44
|
-
return enabled;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Record a start marker. Later passed to {@link measure} as `startName`.
|
|
49
|
-
*
|
|
50
|
-
* No-op when perf is disabled.
|
|
51
|
-
*/
|
|
52
|
-
export function mark(name: string): void {
|
|
53
|
-
if (!enabled) return;
|
|
54
|
-
if (marks === null) marks = new Map<string, number>();
|
|
55
|
-
marks.set(name, Bun.nanoseconds());
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Log elapsed milliseconds since `startName` was marked and return the value.
|
|
60
|
-
*
|
|
61
|
-
* Returns `0` (and does not log or throw) if `startName` was never marked, so
|
|
62
|
-
* callers can safely remove a `mark()` without breaking a `measure()` site.
|
|
63
|
-
* No-op (returns `0`) when perf is disabled.
|
|
64
|
-
*/
|
|
65
|
-
export function measure(label: string, startName: string): number {
|
|
66
|
-
if (!enabled) return 0;
|
|
67
|
-
if (marks === null) return 0;
|
|
68
|
-
const start = marks.get(startName);
|
|
69
|
-
if (start === undefined) return 0;
|
|
70
|
-
const ms = (Bun.nanoseconds() - start) / 1_000_000;
|
|
71
|
-
console.log(`[perf] ${label}: ${ms.toFixed(2)}ms`);
|
|
72
|
-
return ms;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Measure the duration of `fn` and log on completion. Propagates the resolved
|
|
77
|
-
* value and re-throws errors (still logging the elapsed time before rethrow).
|
|
78
|
-
*
|
|
79
|
-
* When perf is disabled, `fn` is invoked directly with no wrapping overhead
|
|
80
|
-
* beyond a single branch and a `Promise.resolve`.
|
|
81
|
-
*/
|
|
82
|
-
export async function withPerf<T>(label: string, fn: () => T | Promise<T>): Promise<T> {
|
|
83
|
-
if (!enabled) return await fn();
|
|
84
|
-
const start = Bun.nanoseconds();
|
|
85
|
-
try {
|
|
86
|
-
return await fn();
|
|
87
|
-
} finally {
|
|
88
|
-
const ms = (Bun.nanoseconds() - start) / 1_000_000;
|
|
89
|
-
console.log(`[perf] ${label}: ${ms.toFixed(2)}ms`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Test-only: re-read `MANDU_PERF` from the environment and clear marker state.
|
|
95
|
-
*
|
|
96
|
-
* Not part of the public surface; intentionally prefixed with `_` and excluded
|
|
97
|
-
* from the module-level TSDoc examples. Stable across the test suite only.
|
|
98
|
-
*
|
|
99
|
-
* @internal
|
|
100
|
-
*/
|
|
101
|
-
export function _resetCacheForTesting(): void {
|
|
102
|
-
enabled = process.env.MANDU_PERF === "1";
|
|
103
|
-
marks = null;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ─── Phase 18.ψ — user-facing performance marks API ─────────────────────
|
|
107
|
-
//
|
|
108
|
-
// Re-export the ergonomic `time()` / `timeAsync()` / `createPerf()` surface
|
|
109
|
-
// (plus the `/_mandu/heap` dashboard snapshot collector) from the adjacent
|
|
110
|
-
// `user-marks.ts` module. Keeps the module-level `mark()` / `measure()` /
|
|
111
|
-
// `withPerf()` signatures untouched for framework-internal callers while
|
|
112
|
-
// giving application code a close-over end-function shape.
|
|
113
|
-
//
|
|
114
|
-
// See `docs/architect/performance-marks.md` for the full rationale.
|
|
115
|
-
|
|
116
|
-
export {
|
|
117
|
-
time,
|
|
118
|
-
timeAsync,
|
|
119
|
-
createPerf,
|
|
120
|
-
collectPerfSnapshot,
|
|
121
|
-
recordFrameworkMeasurement,
|
|
122
|
-
PERF_BUFFER_LIMIT,
|
|
123
|
-
_resetUserMarksForTesting,
|
|
124
|
-
_peekLastMarkForTesting,
|
|
125
|
-
type PerfCategory,
|
|
126
|
-
type PerfMarkOptions,
|
|
127
|
-
type PerfEndFn,
|
|
128
|
-
type PerfMarkEntry,
|
|
129
|
-
type PerfHistogramEntry,
|
|
130
|
-
type PerfDashboardSnapshot,
|
|
131
|
-
type Perf,
|
|
132
|
-
type CreatePerfOptions,
|
|
133
|
-
} from "./user-marks";
|
|
1
|
+
/**
|
|
2
|
+
* Mandu Perf Module
|
|
3
|
+
*
|
|
4
|
+
* Lightweight, opt-in measurement markers built on `Bun.nanoseconds()`.
|
|
5
|
+
*
|
|
6
|
+
* Enable at process boot with `MANDU_PERF=1`. When disabled, every function is
|
|
7
|
+
* a single-branch no-op (no allocation, no Map lookups, no logging) so it is
|
|
8
|
+
* safe to sprinkle markers across hot paths.
|
|
9
|
+
*
|
|
10
|
+
* Rationale for `console.log` (not the structured logger):
|
|
11
|
+
* measurement is a cross-cutting concern and must not depend on the log
|
|
12
|
+
* pipeline it may itself be measuring. Keeping the output path trivial also
|
|
13
|
+
* preserves the "zero-overhead when disabled, minimal overhead when enabled"
|
|
14
|
+
* contract.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { mark, measure, withPerf } from "@mandujs/core/perf";
|
|
19
|
+
*
|
|
20
|
+
* mark("build:start");
|
|
21
|
+
* await doWork();
|
|
22
|
+
* measure("full build", "build:start");
|
|
23
|
+
*
|
|
24
|
+
* const result = await withPerf("ssr:render", () => render(route));
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @module perf
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
// Module-load snapshot. `isPerfEnabled()` is a stable answer per process.
|
|
31
|
+
let enabled: boolean = process.env.MANDU_PERF === "1";
|
|
32
|
+
|
|
33
|
+
// Lazily-initialized marker table. Stays `null` when disabled so no allocation
|
|
34
|
+
// occurs on the disabled fast path.
|
|
35
|
+
let marks: Map<string, number> | null = null;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Whether perf markers are active for this process.
|
|
39
|
+
*
|
|
40
|
+
* Cached at module load from `MANDU_PERF=1`; changing the env var afterwards
|
|
41
|
+
* has no effect (see `_resetCacheForTesting` for test-only overrides).
|
|
42
|
+
*/
|
|
43
|
+
export function isPerfEnabled(): boolean {
|
|
44
|
+
return enabled;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Record a start marker. Later passed to {@link measure} as `startName`.
|
|
49
|
+
*
|
|
50
|
+
* No-op when perf is disabled.
|
|
51
|
+
*/
|
|
52
|
+
export function mark(name: string): void {
|
|
53
|
+
if (!enabled) return;
|
|
54
|
+
if (marks === null) marks = new Map<string, number>();
|
|
55
|
+
marks.set(name, Bun.nanoseconds());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Log elapsed milliseconds since `startName` was marked and return the value.
|
|
60
|
+
*
|
|
61
|
+
* Returns `0` (and does not log or throw) if `startName` was never marked, so
|
|
62
|
+
* callers can safely remove a `mark()` without breaking a `measure()` site.
|
|
63
|
+
* No-op (returns `0`) when perf is disabled.
|
|
64
|
+
*/
|
|
65
|
+
export function measure(label: string, startName: string): number {
|
|
66
|
+
if (!enabled) return 0;
|
|
67
|
+
if (marks === null) return 0;
|
|
68
|
+
const start = marks.get(startName);
|
|
69
|
+
if (start === undefined) return 0;
|
|
70
|
+
const ms = (Bun.nanoseconds() - start) / 1_000_000;
|
|
71
|
+
console.log(`[perf] ${label}: ${ms.toFixed(2)}ms`);
|
|
72
|
+
return ms;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Measure the duration of `fn` and log on completion. Propagates the resolved
|
|
77
|
+
* value and re-throws errors (still logging the elapsed time before rethrow).
|
|
78
|
+
*
|
|
79
|
+
* When perf is disabled, `fn` is invoked directly with no wrapping overhead
|
|
80
|
+
* beyond a single branch and a `Promise.resolve`.
|
|
81
|
+
*/
|
|
82
|
+
export async function withPerf<T>(label: string, fn: () => T | Promise<T>): Promise<T> {
|
|
83
|
+
if (!enabled) return await fn();
|
|
84
|
+
const start = Bun.nanoseconds();
|
|
85
|
+
try {
|
|
86
|
+
return await fn();
|
|
87
|
+
} finally {
|
|
88
|
+
const ms = (Bun.nanoseconds() - start) / 1_000_000;
|
|
89
|
+
console.log(`[perf] ${label}: ${ms.toFixed(2)}ms`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Test-only: re-read `MANDU_PERF` from the environment and clear marker state.
|
|
95
|
+
*
|
|
96
|
+
* Not part of the public surface; intentionally prefixed with `_` and excluded
|
|
97
|
+
* from the module-level TSDoc examples. Stable across the test suite only.
|
|
98
|
+
*
|
|
99
|
+
* @internal
|
|
100
|
+
*/
|
|
101
|
+
export function _resetCacheForTesting(): void {
|
|
102
|
+
enabled = process.env.MANDU_PERF === "1";
|
|
103
|
+
marks = null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ─── Phase 18.ψ — user-facing performance marks API ─────────────────────
|
|
107
|
+
//
|
|
108
|
+
// Re-export the ergonomic `time()` / `timeAsync()` / `createPerf()` surface
|
|
109
|
+
// (plus the `/_mandu/heap` dashboard snapshot collector) from the adjacent
|
|
110
|
+
// `user-marks.ts` module. Keeps the module-level `mark()` / `measure()` /
|
|
111
|
+
// `withPerf()` signatures untouched for framework-internal callers while
|
|
112
|
+
// giving application code a close-over end-function shape.
|
|
113
|
+
//
|
|
114
|
+
// See `docs/architect/performance-marks.md` for the full rationale.
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
time,
|
|
118
|
+
timeAsync,
|
|
119
|
+
createPerf,
|
|
120
|
+
collectPerfSnapshot,
|
|
121
|
+
recordFrameworkMeasurement,
|
|
122
|
+
PERF_BUFFER_LIMIT,
|
|
123
|
+
_resetUserMarksForTesting,
|
|
124
|
+
_peekLastMarkForTesting,
|
|
125
|
+
type PerfCategory,
|
|
126
|
+
type PerfMarkOptions,
|
|
127
|
+
type PerfEndFn,
|
|
128
|
+
type PerfMarkEntry,
|
|
129
|
+
type PerfHistogramEntry,
|
|
130
|
+
type PerfDashboardSnapshot,
|
|
131
|
+
type Perf,
|
|
132
|
+
type CreatePerfOptions,
|
|
133
|
+
} from "./user-marks";
|