@jasonshimmy/vite-plugin-cer-app 0.23.1 → 0.24.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/dist/cli/checks/lighthouse.d.ts +26 -0
- package/dist/cli/checks/lighthouse.d.ts.map +1 -0
- package/dist/cli/checks/lighthouse.js +121 -0
- package/dist/cli/checks/lighthouse.js.map +1 -0
- package/dist/cli/checks/links.d.ts +12 -0
- package/dist/cli/checks/links.d.ts.map +1 -0
- package/dist/cli/checks/links.js +89 -0
- package/dist/cli/checks/links.js.map +1 -0
- package/dist/cli/checks/performance.d.ts +17 -0
- package/dist/cli/checks/performance.d.ts.map +1 -0
- package/dist/cli/checks/performance.js +61 -0
- package/dist/cli/checks/performance.js.map +1 -0
- package/dist/cli/commands/check.d.ts +3 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +85 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/preview.d.ts.map +1 -1
- package/dist/cli/commands/preview.js +37 -4
- package/dist/cli/commands/preview.js.map +1 -1
- package/dist/cli/create/index.d.ts +11 -1
- package/dist/cli/create/index.d.ts.map +1 -1
- package/dist/cli/create/index.js +135 -65
- package/dist/cli/create/index.js.map +1 -1
- package/dist/cli/create/templates/spa/package.json.tpl +5 -3
- package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
- package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
- package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/plugin/build-ssg.d.ts +22 -4
- package/dist/plugin/build-ssg.d.ts.map +1 -1
- package/dist/plugin/build-ssg.js +273 -13
- package/dist/plugin/build-ssg.js.map +1 -1
- package/dist/plugin/content/parser.d.ts.map +1 -1
- package/dist/plugin/content/parser.js +54 -10
- package/dist/plugin/content/parser.js.map +1 -1
- package/dist/plugin/dev-server.d.ts +6 -1
- package/dist/plugin/dev-server.d.ts.map +1 -1
- package/dist/plugin/dev-server.js.map +1 -1
- package/dist/plugin/dts-generator.d.ts.map +1 -1
- package/dist/plugin/dts-generator.js +50 -8
- package/dist/plugin/dts-generator.js.map +1 -1
- package/dist/plugin/generated-dir.d.ts +2 -0
- package/dist/plugin/generated-dir.d.ts.map +1 -1
- package/dist/plugin/generated-dir.js +17 -6
- package/dist/plugin/generated-dir.js.map +1 -1
- package/dist/plugin/html-post-process.d.ts +35 -0
- package/dist/plugin/html-post-process.d.ts.map +1 -0
- package/dist/plugin/html-post-process.js +112 -0
- package/dist/plugin/html-post-process.js.map +1 -0
- package/dist/plugin/index.d.ts +9 -0
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +89 -14
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
- package/dist/plugin/transforms/auto-import.js +7 -0
- package/dist/plugin/transforms/auto-import.js.map +1 -1
- package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
- package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
- package/dist/plugin/transforms/prune-runtime-css.js +40 -0
- package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
- package/dist/runtime/app-template.d.ts +1 -4
- package/dist/runtime/app-template.d.ts.map +1 -1
- package/dist/runtime/app-template.js +211 -40
- package/dist/runtime/app-template.js.map +1 -1
- package/dist/runtime/composables/index.d.ts +4 -0
- package/dist/runtime/composables/index.d.ts.map +1 -1
- package/dist/runtime/composables/index.js +2 -0
- package/dist/runtime/composables/index.js.map +1 -1
- package/dist/runtime/composables/use-active-headings.d.ts +24 -0
- package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
- package/dist/runtime/composables/use-active-headings.js +112 -0
- package/dist/runtime/composables/use-active-headings.js.map +1 -0
- package/dist/runtime/composables/use-content-page.d.ts +45 -0
- package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
- package/dist/runtime/composables/use-content-page.js +179 -0
- package/dist/runtime/composables/use-content-page.js.map +1 -0
- package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
- package/dist/runtime/composables/use-content-search.js +1 -5
- package/dist/runtime/composables/use-content-search.js.map +1 -1
- package/dist/runtime/composables/use-fetch.d.ts +2 -1
- package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
- package/dist/runtime/composables/use-fetch.js +112 -43
- package/dist/runtime/composables/use-fetch.js.map +1 -1
- package/dist/runtime/composables/use-head.d.ts.map +1 -1
- package/dist/runtime/composables/use-head.js +30 -6
- package/dist/runtime/composables/use-head.js.map +1 -1
- package/dist/runtime/composables/use-route.d.ts.map +1 -1
- package/dist/runtime/composables/use-route.js +39 -11
- package/dist/runtime/composables/use-route.js.map +1 -1
- package/dist/runtime/content/client.js +2 -2
- package/dist/runtime/content/client.js.map +1 -1
- package/dist/runtime/entry-server-template.d.ts +16 -1
- package/dist/runtime/entry-server-template.d.ts.map +1 -1
- package/dist/runtime/entry-server-template.js +120 -13
- package/dist/runtime/entry-server-template.js.map +1 -1
- package/dist/types/config.d.ts +53 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/middleware.d.ts +2 -2
- package/dist/types/middleware.d.ts.map +1 -1
- package/package.json +22 -19
- package/.github/copilot-instructions.md +0 -169
- package/.github/workflows/publish.yml +0 -257
- package/.nvmrc +0 -1
- package/CHANGELOG.md +0 -232
- package/CLAUDE.md +0 -113
- package/commits.txt +0 -1
- package/cypress.config.ts +0 -16
- package/docs/authentication.md +0 -285
- package/docs/cli.md +0 -324
- package/docs/components.md +0 -237
- package/docs/composables.md +0 -907
- package/docs/configuration.md +0 -667
- package/docs/content.md +0 -570
- package/docs/data-loading.md +0 -336
- package/docs/getting-started.md +0 -237
- package/docs/head-management.md +0 -212
- package/docs/i18n.md +0 -159
- package/docs/layouts.md +0 -224
- package/docs/middleware.md +0 -234
- package/docs/plugins.md +0 -170
- package/docs/rendering-modes.md +0 -377
- package/docs/routing.md +0 -485
- package/docs/server-api.md +0 -253
- package/docs/testing.md +0 -455
- package/docs/use-fetch.md +0 -183
- package/e2e/cypress/e2e/api.cy.ts +0 -123
- package/e2e/cypress/e2e/async-component.cy.ts +0 -27
- package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
- package/e2e/cypress/e2e/content.cy.ts +0 -425
- package/e2e/cypress/e2e/cookie.cy.ts +0 -85
- package/e2e/cypress/e2e/data.cy.ts +0 -158
- package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
- package/e2e/cypress/e2e/fouc.cy.ts +0 -254
- package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
- package/e2e/cypress/e2e/head.cy.ts +0 -89
- package/e2e/cypress/e2e/i18n.cy.ts +0 -79
- package/e2e/cypress/e2e/interactive.cy.ts +0 -137
- package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
- package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
- package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
- package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
- package/e2e/cypress/e2e/middleware.cy.ts +0 -45
- package/e2e/cypress/e2e/navigate.cy.ts +0 -39
- package/e2e/cypress/e2e/observability.cy.ts +0 -77
- package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
- package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
- package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
- package/e2e/cypress/e2e/routes.cy.ts +0 -128
- package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
- package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
- package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
- package/e2e/cypress/e2e/session.cy.ts +0 -73
- package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
- package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
- package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
- package/e2e/cypress/e2e/use-state.cy.ts +0 -138
- package/e2e/cypress/support/commands.ts +0 -120
- package/e2e/cypress/support/e2e.ts +0 -10
- package/e2e/cypress/tsconfig.json +0 -14
- package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
- package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
- package/e2e/kitchen-sink/app/error.ts +0 -18
- package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
- package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
- package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
- package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
- package/e2e/kitchen-sink/app/loading.ts +0 -9
- package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
- package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
- package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
- package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
- package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
- package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
- package/e2e/kitchen-sink/app/pages/404.ts +0 -9
- package/e2e/kitchen-sink/app/pages/about.ts +0 -17
- package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
- package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
- package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
- package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
- package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
- package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
- package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
- package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
- package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
- package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
- package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
- package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
- package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
- package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
- package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
- package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
- package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
- package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
- package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
- package/e2e/kitchen-sink/app/pages/head.ts +0 -20
- package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
- package/e2e/kitchen-sink/app/pages/index.ts +0 -27
- package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
- package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
- package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
- package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
- package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
- package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
- package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
- package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
- package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
- package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
- package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
- package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
- package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
- package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
- package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
- package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
- package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
- package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
- package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
- package/e2e/kitchen-sink/cer-env.d.ts +0 -35
- package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
- package/e2e/kitchen-sink/cer.config.ts +0 -43
- package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
- package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
- package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
- package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
- package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
- package/e2e/kitchen-sink/content/blog/index.md +0 -8
- package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
- package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
- package/e2e/kitchen-sink/content/index.md +0 -16
- package/e2e/kitchen-sink/server/api/echo.ts +0 -12
- package/e2e/kitchen-sink/server/api/health.ts +0 -3
- package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
- package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
- package/e2e/kitchen-sink/server/api/session.ts +0 -23
- package/e2e/kitchen-sink/server/data/posts.ts +0 -21
- package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
- package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
- package/e2e/kitchen-sink/tsconfig.json +0 -3
- package/e2e/scripts/clean.mjs +0 -14
- package/eslint.config.ts +0 -22
- package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
- package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
- package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
- package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
- package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
- package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
- package/src/__tests__/cli/preview-hardening.test.ts +0 -265
- package/src/__tests__/cli/preview-isr.test.ts +0 -320
- package/src/__tests__/index.test.ts +0 -21
- package/src/__tests__/plugin/app-template.test.ts +0 -112
- package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
- package/src/__tests__/plugin/build-ssg.test.ts +0 -598
- package/src/__tests__/plugin/build-ssr.test.ts +0 -192
- package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
- package/src/__tests__/plugin/content/emitter.test.ts +0 -117
- package/src/__tests__/plugin/content/loader.test.ts +0 -154
- package/src/__tests__/plugin/content/parser.test.ts +0 -381
- package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
- package/src/__tests__/plugin/content/search.test.ts +0 -119
- package/src/__tests__/plugin/dev-server.test.ts +0 -813
- package/src/__tests__/plugin/dts-generator.test.ts +0 -394
- package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
- package/src/__tests__/plugin/generated-dir.test.ts +0 -144
- package/src/__tests__/plugin/path-utils.test.ts +0 -411
- package/src/__tests__/plugin/resolve-config.test.ts +0 -200
- package/src/__tests__/plugin/scanner.test.ts +0 -186
- package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
- package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
- package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
- package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
- package/src/__tests__/plugin/virtual/error.test.ts +0 -71
- package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
- package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
- package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
- package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
- package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
- package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
- package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
- package/src/__tests__/runtime/app-template.test.ts +0 -198
- package/src/__tests__/runtime/define-middleware.test.ts +0 -64
- package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
- package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
- package/src/__tests__/runtime/isr-handler.test.ts +0 -338
- package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
- package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
- package/src/__tests__/runtime/oauth-index.test.ts +0 -43
- package/src/__tests__/runtime/use-auth.test.ts +0 -169
- package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
- package/src/__tests__/runtime/use-content-search.test.ts +0 -163
- package/src/__tests__/runtime/use-content.test.ts +0 -226
- package/src/__tests__/runtime/use-cookie.test.ts +0 -277
- package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
- package/src/__tests__/runtime/use-fetch.test.ts +0 -377
- package/src/__tests__/runtime/use-head.test.ts +0 -266
- package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
- package/src/__tests__/runtime/use-inject.test.ts +0 -66
- package/src/__tests__/runtime/use-locale.test.ts +0 -152
- package/src/__tests__/runtime/use-navigate.test.ts +0 -121
- package/src/__tests__/runtime/use-page-data.test.ts +0 -298
- package/src/__tests__/runtime/use-route.test.ts +0 -156
- package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
- package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
- package/src/__tests__/runtime/use-session.test.ts +0 -320
- package/src/__tests__/runtime/use-state.test.ts +0 -340
- package/src/__tests__/types/config.test.ts +0 -18
- package/src/cli/adapters/cloudflare.ts +0 -335
- package/src/cli/adapters/netlify.ts +0 -326
- package/src/cli/adapters/vercel.ts +0 -311
- package/src/cli/commands/adapt.ts +0 -84
- package/src/cli/commands/build.ts +0 -165
- package/src/cli/commands/dev.ts +0 -125
- package/src/cli/commands/generate.ts +0 -91
- package/src/cli/commands/preview-isr.ts +0 -172
- package/src/cli/commands/preview.ts +0 -489
- package/src/cli/create/index.ts +0 -275
- package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
- package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
- package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
- package/src/cli/create/templates/shared/index.html.tpl +0 -12
- package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
- package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
- package/src/cli/create/templates/spa/package.json.tpl +0 -18
- package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
- package/src/cli/create/templates/ssg/package.json.tpl +0 -19
- package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
- package/src/cli/create/templates/ssr/package.json.tpl +0 -18
- package/src/cli/index.ts +0 -22
- package/src/index.ts +0 -20
- package/src/plugin/build-ssg.ts +0 -336
- package/src/plugin/build-ssr.ts +0 -134
- package/src/plugin/content/emitter.ts +0 -50
- package/src/plugin/content/index.ts +0 -233
- package/src/plugin/content/parser.ts +0 -259
- package/src/plugin/content/path-utils.ts +0 -55
- package/src/plugin/content/scanner.ts +0 -26
- package/src/plugin/content/search.ts +0 -28
- package/src/plugin/dev-server.ts +0 -377
- package/src/plugin/dts-generator.ts +0 -273
- package/src/plugin/generated-dir.ts +0 -121
- package/src/plugin/index.ts +0 -553
- package/src/plugin/path-utils.ts +0 -186
- package/src/plugin/scanner.ts +0 -65
- package/src/plugin/transforms/auto-import.ts +0 -206
- package/src/plugin/transforms/head-inject.ts +0 -161
- package/src/plugin/virtual/composables.ts +0 -28
- package/src/plugin/virtual/content-components.ts +0 -83
- package/src/plugin/virtual/error.ts +0 -34
- package/src/plugin/virtual/layouts.ts +0 -41
- package/src/plugin/virtual/loading.ts +0 -32
- package/src/plugin/virtual/middleware.ts +0 -45
- package/src/plugin/virtual/plugins.ts +0 -46
- package/src/plugin/virtual/routes.ts +0 -514
- package/src/plugin/virtual/server-api.ts +0 -85
- package/src/plugin/virtual/server-middleware.ts +0 -44
- package/src/runtime/app-template.ts +0 -380
- package/src/runtime/composables/define-middleware.ts +0 -17
- package/src/runtime/composables/define-server-middleware.ts +0 -18
- package/src/runtime/composables/index.ts +0 -27
- package/src/runtime/composables/use-auth.ts +0 -125
- package/src/runtime/composables/use-content-search.ts +0 -205
- package/src/runtime/composables/use-content.ts +0 -146
- package/src/runtime/composables/use-cookie.ts +0 -135
- package/src/runtime/composables/use-fetch.ts +0 -438
- package/src/runtime/composables/use-head.ts +0 -212
- package/src/runtime/composables/use-inject.ts +0 -49
- package/src/runtime/composables/use-locale.ts +0 -109
- package/src/runtime/composables/use-navigate.ts +0 -58
- package/src/runtime/composables/use-page-data.ts +0 -93
- package/src/runtime/composables/use-route.ts +0 -71
- package/src/runtime/composables/use-runtime-config.ts +0 -123
- package/src/runtime/composables/use-seo-meta.ts +0 -80
- package/src/runtime/composables/use-session.ts +0 -186
- package/src/runtime/composables/use-state.ts +0 -92
- package/src/runtime/content/client.ts +0 -168
- package/src/runtime/entry-client-template.ts +0 -39
- package/src/runtime/entry-server-template.ts +0 -493
- package/src/runtime/isr-handler.ts +0 -184
- package/src/runtime/oauth/handler.ts +0 -407
- package/src/runtime/oauth/index.ts +0 -49
- package/src/runtime/oauth/providers.ts +0 -38
- package/src/types/api.ts +0 -40
- package/src/types/config.ts +0 -371
- package/src/types/content.ts +0 -66
- package/src/types/index.ts +0 -7
- package/src/types/middleware.ts +0 -63
- package/src/types/page.ts +0 -117
- package/src/types/plugin.ts +0 -34
- package/tsconfig.build.json +0 -10
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -33
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const LIGHTHOUSE_CATEGORIES: readonly ["performance", "accessibility", "best-practices", "seo"];
|
|
2
|
+
export declare function median(values: readonly number[]): number;
|
|
3
|
+
export interface LighthouseAuditOptions {
|
|
4
|
+
root?: string;
|
|
5
|
+
urls: string[];
|
|
6
|
+
runs?: number;
|
|
7
|
+
attempts?: number;
|
|
8
|
+
preset?: 'desktop';
|
|
9
|
+
categories?: string[];
|
|
10
|
+
/** Chromium-family executable. Defaults to CHROME_PATH or a known platform installation. */
|
|
11
|
+
chromePath?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface LighthouseUrlReport {
|
|
14
|
+
url: string;
|
|
15
|
+
medians: Record<string, number>;
|
|
16
|
+
}
|
|
17
|
+
export interface ChromiumDiscoveryOptions {
|
|
18
|
+
environment?: Record<string, string | undefined>;
|
|
19
|
+
platform?: NodeJS.Platform;
|
|
20
|
+
exists?: (path: string) => boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Resolve Chrome, Chromium, Edge, or Brave without requiring a global Chrome install. */
|
|
23
|
+
export declare function findChromiumExecutable(options?: ChromiumDiscoveryOptions): string | undefined;
|
|
24
|
+
/** Run repeatable Lighthouse audits using the application's optional local dependency. */
|
|
25
|
+
export declare function runLighthouseAudit(options: LighthouseAuditOptions): Promise<LighthouseUrlReport[]>;
|
|
26
|
+
//# sourceMappingURL=lighthouse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse.d.ts","sourceRoot":"","sources":["../../../src/cli/checks/lighthouse.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,oEAKxB,CAAA;AAEV,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAIxD;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,4FAA4F;IAC5F,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAA;IAC1B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAA;CACnC;AAED,0FAA0F;AAC1F,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,wBAA6B,GAAG,MAAM,GAAG,SAAS,CA8BjG;AAaD,0FAA0F;AAC1F,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,mBAAmB,EAAE,CAAC,CA4DhC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join, resolve } from 'node:path';
|
|
6
|
+
export const LIGHTHOUSE_CATEGORIES = [
|
|
7
|
+
'performance',
|
|
8
|
+
'accessibility',
|
|
9
|
+
'best-practices',
|
|
10
|
+
'seo',
|
|
11
|
+
];
|
|
12
|
+
export function median(values) {
|
|
13
|
+
if (values.length === 0)
|
|
14
|
+
return 0;
|
|
15
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
16
|
+
return sorted[Math.floor(sorted.length / 2)];
|
|
17
|
+
}
|
|
18
|
+
/** Resolve Chrome, Chromium, Edge, or Brave without requiring a global Chrome install. */
|
|
19
|
+
export function findChromiumExecutable(options = {}) {
|
|
20
|
+
const environment = options.environment ?? process.env;
|
|
21
|
+
const platform = options.platform ?? process.platform;
|
|
22
|
+
const exists = options.exists ?? existsSync;
|
|
23
|
+
const explicit = environment.CHROME_PATH?.trim();
|
|
24
|
+
if (explicit)
|
|
25
|
+
return explicit;
|
|
26
|
+
const candidates = platform === 'darwin'
|
|
27
|
+
? [
|
|
28
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
29
|
+
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
|
|
30
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
31
|
+
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
|
|
32
|
+
'/Applications/Brave Browser.app/Contents/MacOS/Brave Browser',
|
|
33
|
+
]
|
|
34
|
+
: platform === 'win32'
|
|
35
|
+
? [
|
|
36
|
+
`${environment.PROGRAMFILES ?? 'C:\\Program Files'}\\Google\\Chrome\\Application\\chrome.exe`,
|
|
37
|
+
`${environment.PROGRAMFILES ?? 'C:\\Program Files'}\\Microsoft\\Edge\\Application\\msedge.exe`,
|
|
38
|
+
`${environment.LOCALAPPDATA ?? ''}\\BraveSoftware\\Brave-Browser\\Application\\brave.exe`,
|
|
39
|
+
]
|
|
40
|
+
: [
|
|
41
|
+
'/usr/bin/google-chrome',
|
|
42
|
+
'/usr/bin/google-chrome-stable',
|
|
43
|
+
'/usr/bin/chromium',
|
|
44
|
+
'/usr/bin/chromium-browser',
|
|
45
|
+
'/usr/bin/microsoft-edge',
|
|
46
|
+
'/usr/bin/brave-browser',
|
|
47
|
+
];
|
|
48
|
+
return candidates.find((candidate) => exists(candidate));
|
|
49
|
+
}
|
|
50
|
+
function run(command, args, environment) {
|
|
51
|
+
return new Promise((resolveRun, reject) => {
|
|
52
|
+
const child = spawn(command, args, { stdio: 'inherit', env: environment });
|
|
53
|
+
child.once('error', reject);
|
|
54
|
+
child.once('exit', (code, signal) => {
|
|
55
|
+
if (code === 0)
|
|
56
|
+
resolveRun();
|
|
57
|
+
else
|
|
58
|
+
reject(new Error(`${command} exited with ${code ?? signal}`));
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Run repeatable Lighthouse audits using the application's optional local dependency. */
|
|
63
|
+
export async function runLighthouseAudit(options) {
|
|
64
|
+
const root = resolve(options.root ?? process.cwd());
|
|
65
|
+
const cli = join(root, 'node_modules/lighthouse/cli/index.js');
|
|
66
|
+
const categories = options.categories ?? [...LIGHTHOUSE_CATEGORIES];
|
|
67
|
+
const runs = Math.max(1, options.runs ?? 3);
|
|
68
|
+
const attempts = Math.max(1, options.attempts ?? 3);
|
|
69
|
+
const chromePath = options.chromePath?.trim() || findChromiumExecutable();
|
|
70
|
+
const environment = chromePath ? { ...process.env, CHROME_PATH: chromePath } : process.env;
|
|
71
|
+
const reportsDir = await mkdtemp(join(tmpdir(), 'cer-lighthouse-'));
|
|
72
|
+
const result = [];
|
|
73
|
+
try {
|
|
74
|
+
for (const [urlIndex, url] of options.urls.entries()) {
|
|
75
|
+
const scores = Object.fromEntries(categories.map((category) => [category, []]));
|
|
76
|
+
for (let runIndex = 0; runIndex < runs; runIndex += 1) {
|
|
77
|
+
const outputPath = join(reportsDir, `${urlIndex}-${runIndex}.json`);
|
|
78
|
+
const args = [
|
|
79
|
+
cli,
|
|
80
|
+
url,
|
|
81
|
+
'--quiet',
|
|
82
|
+
'--chrome-flags=--headless --no-sandbox',
|
|
83
|
+
`--only-categories=${categories.join(',')}`,
|
|
84
|
+
'--output=json',
|
|
85
|
+
`--output-path=${outputPath}`,
|
|
86
|
+
];
|
|
87
|
+
if (options.preset)
|
|
88
|
+
args.push(`--preset=${options.preset}`);
|
|
89
|
+
let lastError;
|
|
90
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
91
|
+
try {
|
|
92
|
+
await run(process.execPath, args, environment);
|
|
93
|
+
lastError = undefined;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
lastError = error;
|
|
98
|
+
if (attempt < attempts) {
|
|
99
|
+
await new Promise((resolveWait) => setTimeout(resolveWait, attempt * 250));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (lastError)
|
|
104
|
+
throw lastError;
|
|
105
|
+
const report = JSON.parse(await readFile(outputPath, 'utf8'));
|
|
106
|
+
for (const category of categories) {
|
|
107
|
+
scores[category].push(report.categories[category]?.score ?? 0);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
result.push({
|
|
111
|
+
url,
|
|
112
|
+
medians: Object.fromEntries(categories.map((category) => [category, median(scores[category])])),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await rm(reportsDir, { recursive: true, force: true });
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=lighthouse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lighthouse.js","sourceRoot":"","sources":["../../../src/cli/checks/lighthouse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface BuiltLinksOptions {
|
|
2
|
+
outputDir?: string;
|
|
3
|
+
skipTopLevel?: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
export interface BuiltLinksReport {
|
|
6
|
+
pages: number;
|
|
7
|
+
links: number;
|
|
8
|
+
failures: string[];
|
|
9
|
+
}
|
|
10
|
+
/** Validate every internal href and fragment emitted by an SSG build. */
|
|
11
|
+
export declare function checkBuiltLinks(options?: BuiltLinksOptions): Promise<BuiltLinksReport>;
|
|
12
|
+
//# sourceMappingURL=links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/cli/checks/links.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AA8BD,yEAAyE;AACzE,wBAAsB,eAAe,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA+ChG"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { access, readFile, readdir, stat } from 'node:fs/promises';
|
|
2
|
+
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
3
|
+
async function collectHtml(directory, skipped, depth = 0) {
|
|
4
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
5
|
+
const files = [];
|
|
6
|
+
for (const entry of entries) {
|
|
7
|
+
if (depth === 0 && entry.isDirectory() && skipped.has(entry.name))
|
|
8
|
+
continue;
|
|
9
|
+
const path = join(directory, entry.name);
|
|
10
|
+
if (entry.isDirectory())
|
|
11
|
+
files.push(...await collectHtml(path, skipped, depth + 1));
|
|
12
|
+
else if (entry.name === 'index.html')
|
|
13
|
+
files.push(path);
|
|
14
|
+
}
|
|
15
|
+
return files;
|
|
16
|
+
}
|
|
17
|
+
async function exists(path) {
|
|
18
|
+
try {
|
|
19
|
+
await access(path);
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function isFile(path) {
|
|
27
|
+
try {
|
|
28
|
+
return (await stat(path)).isFile();
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function escapeRegExp(value) {
|
|
35
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
36
|
+
}
|
|
37
|
+
/** Validate every internal href and fragment emitted by an SSG build. */
|
|
38
|
+
export async function checkBuiltLinks(options = {}) {
|
|
39
|
+
const outputDir = resolve(options.outputDir ?? 'dist');
|
|
40
|
+
const skipped = new Set(options.skipTopLevel ?? ['client', 'server', '_content', 'assets']);
|
|
41
|
+
const pages = await collectHtml(outputDir, skipped);
|
|
42
|
+
const failures = [];
|
|
43
|
+
let links = 0;
|
|
44
|
+
for (const page of pages) {
|
|
45
|
+
const html = await readFile(page, 'utf8');
|
|
46
|
+
const relativeDirectory = relative(outputDir, dirname(page)).split(sep).filter(Boolean).join('/');
|
|
47
|
+
const pageRoute = relativeDirectory ? `/${relativeDirectory}` : '/';
|
|
48
|
+
const base = new URL(pageRoute.endsWith('/') ? pageRoute : `${pageRoute}/`, 'https://local.test');
|
|
49
|
+
const hrefs = [...html.matchAll(/\bhref=(?:"([^"]*)"|'([^']*)')/gi)]
|
|
50
|
+
.map((match) => match[1] ?? match[2]);
|
|
51
|
+
for (const href of hrefs) {
|
|
52
|
+
if (!href || /^(?:https?:|mailto:|tel:|data:|javascript:|\/\/)/i.test(href))
|
|
53
|
+
continue;
|
|
54
|
+
const url = new URL(href, base);
|
|
55
|
+
if (url.origin !== base.origin)
|
|
56
|
+
continue;
|
|
57
|
+
links += 1;
|
|
58
|
+
let pathname = url.pathname;
|
|
59
|
+
try {
|
|
60
|
+
pathname = decodeURIComponent(pathname);
|
|
61
|
+
}
|
|
62
|
+
catch { /* retain encoded path */ }
|
|
63
|
+
const relativeTarget = pathname.replace(/^\/+/, '');
|
|
64
|
+
const directTarget = join(outputDir, relativeTarget);
|
|
65
|
+
const routeTarget = pathname === '/'
|
|
66
|
+
? join(outputDir, 'index.html')
|
|
67
|
+
: join(outputDir, relativeTarget, 'index.html');
|
|
68
|
+
const target = await isFile(directTarget) ? directTarget : routeTarget;
|
|
69
|
+
if (!(await exists(target))) {
|
|
70
|
+
failures.push(`${relative(outputDir, page)} -> ${href} (missing ${relative(outputDir, target)})`);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (url.hash && target.endsWith('.html')) {
|
|
74
|
+
let id = url.hash.slice(1);
|
|
75
|
+
try {
|
|
76
|
+
id = decodeURIComponent(id);
|
|
77
|
+
}
|
|
78
|
+
catch { /* retain encoded id */ }
|
|
79
|
+
const targetHtml = target === page ? html : await readFile(target, 'utf8');
|
|
80
|
+
const quotedId = escapeRegExp(id);
|
|
81
|
+
const hasId = new RegExp(`\\bid=(?:"${quotedId}"|'${quotedId}')`, 'i').test(targetHtml);
|
|
82
|
+
if (!hasId)
|
|
83
|
+
failures.push(`${relative(outputDir, page)} -> ${href} (missing #${id})`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { pages: pages.length, links, failures };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../../../src/cli/checks/links.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface PerformanceBudgetOptions {
|
|
2
|
+
outputDir?: string;
|
|
3
|
+
page?: string;
|
|
4
|
+
maxHtmlBytes?: number;
|
|
5
|
+
maxInitialJsGzipBytes?: number;
|
|
6
|
+
maxEntryJsGzipBytes?: number;
|
|
7
|
+
expectedPages?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PerformanceBudgetReport {
|
|
10
|
+
htmlBytes: number;
|
|
11
|
+
initialJsGzipBytes: number;
|
|
12
|
+
entryJsGzipBytes: number;
|
|
13
|
+
failures: string[];
|
|
14
|
+
}
|
|
15
|
+
/** Measure framework-neutral SSG output budgets and build-integrity signals. */
|
|
16
|
+
export declare function checkPerformanceBudgets(options?: PerformanceBudgetOptions): Promise<PerformanceBudgetReport>;
|
|
17
|
+
//# sourceMappingURL=performance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../../src/cli/checks/performance.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,wBAAwB;IACvC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,gFAAgF;AAChF,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,uBAAuB,CAAC,CAkElC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { gzipSync } from 'node:zlib';
|
|
2
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
3
|
+
import { basename, join, resolve } from 'node:path';
|
|
4
|
+
/** Measure framework-neutral SSG output budgets and build-integrity signals. */
|
|
5
|
+
export async function checkPerformanceBudgets(options = {}) {
|
|
6
|
+
const outputDir = resolve(options.outputDir ?? 'dist');
|
|
7
|
+
const page = (options.page ?? '/').replace(/^\/+|\/+$/g, '');
|
|
8
|
+
const htmlPath = page ? join(outputDir, page, 'index.html') : join(outputDir, 'index.html');
|
|
9
|
+
const assetsDir = join(outputDir, 'assets');
|
|
10
|
+
const html = await readFile(htmlPath, 'utf8');
|
|
11
|
+
const htmlBytes = (await stat(htmlPath)).size;
|
|
12
|
+
const failures = [];
|
|
13
|
+
const assetNames = new Set([...html.matchAll(/(?:src|href)=(?:"([^"]+\.js)"|'([^']+\.js)')/g)]
|
|
14
|
+
.map((match) => match[1] ?? match[2])
|
|
15
|
+
.map((url) => url.slice(url.lastIndexOf('/') + 1)));
|
|
16
|
+
let initialJsGzipBytes = 0;
|
|
17
|
+
let entryJsGzipBytes = 0;
|
|
18
|
+
for (const name of assetNames) {
|
|
19
|
+
try {
|
|
20
|
+
const bytes = gzipSync(await readFile(join(assetsDir, name))).byteLength;
|
|
21
|
+
initialJsGzipBytes += bytes;
|
|
22
|
+
if (name.startsWith('index-'))
|
|
23
|
+
entryJsGzipBytes += bytes;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
failures.push(`homepage references missing JavaScript asset ${name}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (options.maxHtmlBytes !== undefined && htmlBytes > options.maxHtmlBytes) {
|
|
30
|
+
failures.push(`homepage is ${htmlBytes.toLocaleString()} bytes (budget: ${options.maxHtmlBytes.toLocaleString()})`);
|
|
31
|
+
}
|
|
32
|
+
if (options.maxInitialJsGzipBytes !== undefined &&
|
|
33
|
+
initialJsGzipBytes > options.maxInitialJsGzipBytes) {
|
|
34
|
+
failures.push(`initial JavaScript is ${initialJsGzipBytes.toLocaleString()} gzip bytes (budget: ${options.maxInitialJsGzipBytes.toLocaleString()})`);
|
|
35
|
+
}
|
|
36
|
+
if (options.maxEntryJsGzipBytes !== undefined &&
|
|
37
|
+
entryJsGzipBytes > options.maxEntryJsGzipBytes) {
|
|
38
|
+
failures.push(`entry JavaScript is ${entryJsGzipBytes.toLocaleString()} gzip bytes (budget: ${options.maxEntryJsGzipBytes.toLocaleString()})`);
|
|
39
|
+
}
|
|
40
|
+
const assets = await readdir(assetsDir);
|
|
41
|
+
const browserExternals = assets.filter((name) => name.startsWith('__vite-browser-external'));
|
|
42
|
+
if (browserExternals.length > 0) {
|
|
43
|
+
failures.push(`client build contains browser-external shims: ${browserExternals.join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
const manifest = JSON.parse(await readFile(join(outputDir, 'ssg-manifest.json'), 'utf8'));
|
|
47
|
+
if ((manifest.errors?.length ?? 0) > 0) {
|
|
48
|
+
failures.push(`SSG manifest contains ${manifest.errors.length} render error(s)`);
|
|
49
|
+
}
|
|
50
|
+
if (options.expectedPages !== undefined && manifest.paths?.length !== options.expectedPages) {
|
|
51
|
+
failures.push(`SSG manifest contains ${manifest.paths?.length ?? 0} pages (expected: ${options.expectedPages})`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
if (options.expectedPages !== undefined) {
|
|
56
|
+
failures.push(`missing ${basename(join(outputDir, 'ssg-manifest.json'))}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { htmlBytes, initialJsGzipBytes, entryJsGzipBytes, failures };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=performance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance.js","sourceRoot":"","sources":["../../../src/cli/checks/performance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAkBnC,wBAAgB,YAAY,IAAI,OAAO,CA0FtC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { checkBuiltLinks } from '../checks/links.js';
|
|
4
|
+
import { checkPerformanceBudgets } from '../checks/performance.js';
|
|
5
|
+
import { LIGHTHOUSE_CATEGORIES, runLighthouseAudit } from '../checks/lighthouse.js';
|
|
6
|
+
function numberOption(value) {
|
|
7
|
+
const parsed = Number(value);
|
|
8
|
+
if (!Number.isFinite(parsed) || parsed < 0)
|
|
9
|
+
throw new Error(`Invalid non-negative number: ${value}`);
|
|
10
|
+
return parsed;
|
|
11
|
+
}
|
|
12
|
+
function printFailures(label, failures) {
|
|
13
|
+
if (failures.length === 0)
|
|
14
|
+
return;
|
|
15
|
+
console.error(`${label} failed:\n- ${failures.join('\n- ')}`);
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
}
|
|
18
|
+
export function checkCommand() {
|
|
19
|
+
const command = new Command('check').description('Validate production build quality');
|
|
20
|
+
command.addCommand(new Command('links')
|
|
21
|
+
.description('Validate all internal SSG links and fragments')
|
|
22
|
+
.option('--root <root>', 'Project root directory', process.cwd())
|
|
23
|
+
.option('--output <directory>', 'Build output directory', 'dist')
|
|
24
|
+
.action(async (options) => {
|
|
25
|
+
const report = await checkBuiltLinks({ outputDir: resolve(options.root, options.output) });
|
|
26
|
+
printFailures('Built-link validation', report.failures);
|
|
27
|
+
if (report.failures.length === 0) {
|
|
28
|
+
console.log(`Built-link validation passed: ${report.links} links across ${report.pages} pages.`);
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
command.addCommand(new Command('performance')
|
|
32
|
+
.description('Validate HTML and JavaScript production budgets')
|
|
33
|
+
.option('--root <root>', 'Project root directory', process.cwd())
|
|
34
|
+
.option('--output <directory>', 'Build output directory', 'dist')
|
|
35
|
+
.option('--page <path>', 'Route to budget', '/')
|
|
36
|
+
.option('--max-html <bytes>', 'Maximum HTML bytes', numberOption, 250_000)
|
|
37
|
+
.option('--max-initial-js <bytes>', 'Maximum initial JavaScript gzip bytes', numberOption, 85_000)
|
|
38
|
+
.option('--max-entry-js <bytes>', 'Maximum entry JavaScript gzip bytes', numberOption, 50_000)
|
|
39
|
+
.option('--expected-pages <count>', 'Expected SSG manifest page count', numberOption)
|
|
40
|
+
.action(async (options) => {
|
|
41
|
+
const report = await checkPerformanceBudgets({
|
|
42
|
+
outputDir: resolve(options.root, options.output),
|
|
43
|
+
page: options.page,
|
|
44
|
+
maxHtmlBytes: options.maxHtml,
|
|
45
|
+
maxInitialJsGzipBytes: options.maxInitialJs,
|
|
46
|
+
maxEntryJsGzipBytes: options.maxEntryJs,
|
|
47
|
+
expectedPages: options.expectedPages,
|
|
48
|
+
});
|
|
49
|
+
printFailures('Performance budget', report.failures);
|
|
50
|
+
if (report.failures.length === 0) {
|
|
51
|
+
console.log(`Performance budgets passed: HTML ${report.htmlBytes.toLocaleString()} bytes; initial JS ${report.initialJsGzipBytes.toLocaleString()} gzip bytes.`);
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
54
|
+
command.addCommand(new Command('lighthouse')
|
|
55
|
+
.description('Require perfect median Lighthouse scores using a local lighthouse dependency')
|
|
56
|
+
.requiredOption('--url <urls...>', 'One or more preview URLs to audit')
|
|
57
|
+
.option('--root <root>', 'Project root directory', process.cwd())
|
|
58
|
+
.option('--runs <count>', 'Runs per URL', numberOption, 3)
|
|
59
|
+
.option('--attempts <count>', 'Launch attempts per run', numberOption, 3)
|
|
60
|
+
.option('--desktop', 'Use the Lighthouse desktop preset')
|
|
61
|
+
.option('--chrome-path <path>', 'Chrome, Chromium, Edge, or Brave executable')
|
|
62
|
+
.action(async (options) => {
|
|
63
|
+
const reports = await runLighthouseAudit({
|
|
64
|
+
root: options.root,
|
|
65
|
+
urls: options.url,
|
|
66
|
+
runs: options.runs,
|
|
67
|
+
attempts: options.attempts,
|
|
68
|
+
preset: options.desktop ? 'desktop' : undefined,
|
|
69
|
+
chromePath: options.chromePath,
|
|
70
|
+
});
|
|
71
|
+
const failures = [];
|
|
72
|
+
for (const report of reports) {
|
|
73
|
+
const summary = LIGHTHOUSE_CATEGORIES.map((category) => {
|
|
74
|
+
const score = report.medians[category] ?? 0;
|
|
75
|
+
if (score !== 1)
|
|
76
|
+
failures.push(`${report.url}: ${category}=${Math.round(score * 100)}`);
|
|
77
|
+
return `${category}=${Math.round(score * 100)}`;
|
|
78
|
+
});
|
|
79
|
+
console.log(`[lighthouse] ${report.url}: ${summary.join(' ')}`);
|
|
80
|
+
}
|
|
81
|
+
printFailures('Lighthouse audit', failures);
|
|
82
|
+
}));
|
|
83
|
+
return command;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/cli/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAA;AAClE,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEnF,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAA;IACpG,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,aAAa,CAAC,KAAa,EAAE,QAAkB;IACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IACjC,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,eAAe,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAC7D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;AACtB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,mCAAmC,CAAC,CAAA;IAErF,OAAO,CAAC,UAAU,CAChB,IAAI,OAAO,CAAC,OAAO,CAAC;SACjB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,MAAM,CAAC,eAAe,EAAE,wBAAwB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SAChE,MAAM,CAAC,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,CAAC;SAChE,MAAM,CAAC,KAAK,EAAE,OAAyC,EAAE,EAAE;QAC1D,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QAC1F,aAAa,CAAC,uBAAuB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACvD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,iCAAiC,MAAM,CAAC,KAAK,iBAAiB,MAAM,CAAC,KAAK,SAAS,CAAC,CAAA;QAClG,CAAC;IACH,CAAC,CAAC,CACL,CAAA;IAED,OAAO,CAAC,UAAU,CAChB,IAAI,OAAO,CAAC,aAAa,CAAC;SACvB,WAAW,CAAC,iDAAiD,CAAC;SAC9D,MAAM,CAAC,eAAe,EAAE,wBAAwB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SAChE,MAAM,CAAC,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,CAAC;SAChE,MAAM,CAAC,eAAe,EAAE,iBAAiB,EAAE,GAAG,CAAC;SAC/C,MAAM,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,YAAY,EAAE,OAAO,CAAC;SACzE,MAAM,CAAC,0BAA0B,EAAE,uCAAuC,EAAE,YAAY,EAAE,MAAM,CAAC;SACjG,MAAM,CAAC,wBAAwB,EAAE,qCAAqC,EAAE,YAAY,EAAE,MAAM,CAAC;SAC7F,MAAM,CAAC,0BAA0B,EAAE,kCAAkC,EAAE,YAAY,CAAC;SACpF,MAAM,CAAC,KAAK,EAAE,OAQd,EAAE,EAAE;QACH,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC;YAC3C,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC;YAChD,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,YAAY,EAAE,OAAO,CAAC,OAAO;YAC7B,qBAAqB,EAAE,OAAO,CAAC,YAAY;YAC3C,mBAAmB,EAAE,OAAO,CAAC,UAAU;YACvC,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC,CAAA;QACF,aAAa,CAAC,oBAAoB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;QACpD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,oCAAoC,MAAM,CAAC,SAAS,CAAC,cAAc,EAAE,sBAAsB,MAAM,CAAC,kBAAkB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;QAClK,CAAC;IACH,CAAC,CAAC,CACL,CAAA;IAED,OAAO,CAAC,UAAU,CAChB,IAAI,OAAO,CAAC,YAAY,CAAC;SACtB,WAAW,CAAC,8EAA8E,CAAC;SAC3F,cAAc,CAAC,iBAAiB,EAAE,mCAAmC,CAAC;SACtE,MAAM,CAAC,eAAe,EAAE,wBAAwB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SAChE,MAAM,CAAC,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC,CAAC;SACzD,MAAM,CAAC,oBAAoB,EAAE,yBAAyB,EAAE,YAAY,EAAE,CAAC,CAAC;SACxE,MAAM,CAAC,WAAW,EAAE,mCAAmC,CAAC;SACxD,MAAM,CAAC,sBAAsB,EAAE,6CAA6C,CAAC;SAC7E,MAAM,CAAC,KAAK,EAAE,OAOd,EAAE,EAAE;QACH,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;YACvC,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,OAAO,CAAC,GAAG;YACjB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC/C,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CAAA;QACF,MAAM,QAAQ,GAAa,EAAE,CAAA;QAC7B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;gBACrD,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBAC3C,IAAI,KAAK,KAAK,CAAC;oBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC,CAAA;gBACvF,OAAO,GAAG,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,EAAE,CAAA;YACjD,CAAC,CAAC,CAAA;YACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjE,CAAC;QACD,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAA;IAC7C,CAAC,CAAC,CACL,CAAA;IAED,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/preview.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA6NnC,wBAAgB,cAAc,IAAI,OAAO,CA6SxC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { createServer as createHttpServer } from 'node:http';
|
|
3
3
|
import { createReadStream, existsSync, statSync } from 'node:fs';
|
|
4
|
+
import { createGzip } from 'node:zlib';
|
|
4
5
|
import { resolve, join, extname } from 'pathe';
|
|
5
6
|
import { pathToFileURL } from 'node:url';
|
|
6
7
|
import { isPathBounded, findRevalidate, findRenderMode, renderForIsr, serveFromIsrCache, } from './preview-isr.js';
|
|
@@ -103,6 +104,20 @@ function getMimeType(filePath) {
|
|
|
103
104
|
const ext = extname(filePath).toLowerCase();
|
|
104
105
|
return MIME_TYPES[ext] ?? 'application/octet-stream';
|
|
105
106
|
}
|
|
107
|
+
// MIME types that benefit from gzip compression. Binary formats (woff2, images)
|
|
108
|
+
// are already compressed and should not be re-compressed.
|
|
109
|
+
const GZIP_TYPES = new Set([
|
|
110
|
+
'text/html; charset=utf-8',
|
|
111
|
+
'application/javascript; charset=utf-8',
|
|
112
|
+
'text/css; charset=utf-8',
|
|
113
|
+
'application/json; charset=utf-8',
|
|
114
|
+
'image/svg+xml',
|
|
115
|
+
'application/json',
|
|
116
|
+
]);
|
|
117
|
+
function acceptsGzip(req) {
|
|
118
|
+
const ae = req.headers['accept-encoding'] ?? '';
|
|
119
|
+
return ae.includes('gzip');
|
|
120
|
+
}
|
|
106
121
|
/**
|
|
107
122
|
* Returns the appropriate Cache-Control header value for a file.
|
|
108
123
|
* Vite content-hashes assets placed in the /assets/ directory, so they
|
|
@@ -123,6 +138,8 @@ function setSecurityHeaders(res) {
|
|
|
123
138
|
}
|
|
124
139
|
/**
|
|
125
140
|
* Serves a static file from the dist directory.
|
|
141
|
+
* Applies gzip compression for compressible text types when the client
|
|
142
|
+
* signals support via the Accept-Encoding request header.
|
|
126
143
|
* Returns true if the file was served, false otherwise.
|
|
127
144
|
*/
|
|
128
145
|
function serveStaticFile(req, res, distDir) {
|
|
@@ -149,10 +166,18 @@ function serveStaticFile(req, res, distDir) {
|
|
|
149
166
|
return false;
|
|
150
167
|
}
|
|
151
168
|
}
|
|
152
|
-
|
|
169
|
+
const mimeType = getMimeType(filePath);
|
|
170
|
+
res.setHeader('Content-Type', mimeType);
|
|
153
171
|
res.setHeader('Cache-Control', getCacheControl(filePath));
|
|
154
172
|
setSecurityHeaders(res);
|
|
155
|
-
createReadStream(filePath)
|
|
173
|
+
const stream = createReadStream(filePath);
|
|
174
|
+
if (GZIP_TYPES.has(mimeType) && acceptsGzip(req)) {
|
|
175
|
+
res.setHeader('Content-Encoding', 'gzip');
|
|
176
|
+
stream.pipe(createGzip()).pipe(res);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
stream.pipe(res);
|
|
180
|
+
}
|
|
156
181
|
return true;
|
|
157
182
|
}
|
|
158
183
|
/**
|
|
@@ -418,9 +443,17 @@ export function previewCommand() {
|
|
|
418
443
|
const assetPath = join(clientDist, urlPath);
|
|
419
444
|
if (isPathBounded(clientDist, urlPath) &&
|
|
420
445
|
existsSync(assetPath) && !statSync(assetPath).isDirectory()) {
|
|
421
|
-
|
|
446
|
+
const mimeType = getMimeType(assetPath);
|
|
447
|
+
res.setHeader('Content-Type', mimeType);
|
|
422
448
|
res.setHeader('Cache-Control', getCacheControl(assetPath));
|
|
423
|
-
createReadStream(assetPath)
|
|
449
|
+
const stream = createReadStream(assetPath);
|
|
450
|
+
if (GZIP_TYPES.has(mimeType) && acceptsGzip(req)) {
|
|
451
|
+
res.setHeader('Content-Encoding', 'gzip');
|
|
452
|
+
stream.pipe(createGzip()).pipe(res);
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
stream.pipe(res);
|
|
456
|
+
}
|
|
424
457
|
return;
|
|
425
458
|
}
|
|
426
459
|
}
|