@jasonshimmy/vite-plugin-cer-app 0.23.2 → 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/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 -6
- package/dist/plugin/build-ssg.d.ts.map +1 -1
- package/dist/plugin/build-ssg.js +227 -17
- 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 +4 -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 +6 -0
- package/dist/plugin/html-post-process.d.ts.map +1 -1
- package/dist/plugin/html-post-process.js +24 -0
- package/dist/plugin/html-post-process.js.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +60 -13
- 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 -1
- package/dist/runtime/app-template.d.ts.map +1 -1
- package/dist/runtime/app-template.js +206 -36
- 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-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 +45 -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 -236
- 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 -696
- 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 -166
- 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/html-post-process.test.ts +0 -146
- package/src/__tests__/plugin/path-utils.test.ts +0 -411
- package/src/__tests__/plugin/resolve-config.test.ts +0 -233
- 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 -208
- 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 -311
- 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 -523
- 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 -403
- 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 -379
- package/src/plugin/dts-generator.ts +0 -273
- package/src/plugin/generated-dir.ts +0 -121
- package/src/plugin/html-post-process.ts +0 -96
- package/src/plugin/index.ts +0 -584
- 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 -377
- 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 -234
- 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 -379
- 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
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander'
|
|
2
|
-
import { resolve } from 'pathe'
|
|
3
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
4
|
-
import { pathToFileURL } from 'node:url'
|
|
5
|
-
import { runVercelAdapter } from '../adapters/vercel.js'
|
|
6
|
-
import { runNetlifyAdapter } from '../adapters/netlify.js'
|
|
7
|
-
import { runCloudflareAdapter } from '../adapters/cloudflare.js'
|
|
8
|
-
import type { CerAppConfig } from '../../types/config.js'
|
|
9
|
-
|
|
10
|
-
async function loadCustomAdapter(root: string): Promise<((root: string) => Promise<void>) | null> {
|
|
11
|
-
const configPath = resolve(root, 'cer.config.ts')
|
|
12
|
-
const configPathJs = resolve(root, 'cer.config.js')
|
|
13
|
-
const filePath = existsSync(configPath) ? configPath : existsSync(configPathJs) ? configPathJs : null
|
|
14
|
-
if (!filePath) return null
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
const { build: viteBuild } = await import('vite')
|
|
18
|
-
const cerDir = resolve(root, '.cer')
|
|
19
|
-
const cerTsconfig = resolve(cerDir, 'tsconfig.json')
|
|
20
|
-
if (!existsSync(cerTsconfig)) {
|
|
21
|
-
mkdirSync(cerDir, { recursive: true })
|
|
22
|
-
writeFileSync(cerTsconfig, '{"compilerOptions":{}}\n', 'utf-8')
|
|
23
|
-
}
|
|
24
|
-
await viteBuild({
|
|
25
|
-
build: {
|
|
26
|
-
lib: { entry: filePath, formats: ['es'], fileName: 'cer.config' },
|
|
27
|
-
outDir: resolve(root, 'node_modules/.cer-app-cache'),
|
|
28
|
-
write: true,
|
|
29
|
-
rollupOptions: { external: (id: string) => !id.startsWith('.') && !id.startsWith('/') },
|
|
30
|
-
},
|
|
31
|
-
logLevel: 'silent',
|
|
32
|
-
})
|
|
33
|
-
const outFile = resolve(root, 'node_modules/.cer-app-cache/cer.config.mjs')
|
|
34
|
-
if (existsSync(outFile)) {
|
|
35
|
-
const mod = await import(pathToFileURL(outFile).href + `?t=${Date.now()}`)
|
|
36
|
-
const cfg: CerAppConfig = mod.default ?? {}
|
|
37
|
-
return typeof cfg.adapter === 'function' ? cfg.adapter : null
|
|
38
|
-
}
|
|
39
|
-
} catch {
|
|
40
|
-
// ignore
|
|
41
|
-
}
|
|
42
|
-
return null
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function adaptCommand(): Command {
|
|
46
|
-
return new Command('adapt')
|
|
47
|
-
.description('Adapt the production build for a deployment platform')
|
|
48
|
-
.requiredOption(
|
|
49
|
-
'--platform <platform>',
|
|
50
|
-
'Target platform: vercel, netlify, cloudflare, or custom (reads adapter function from cer.config.ts)',
|
|
51
|
-
)
|
|
52
|
-
.option('--root <root>', 'Project root directory', process.cwd())
|
|
53
|
-
.action(async (options) => {
|
|
54
|
-
const root = resolve(options.root)
|
|
55
|
-
switch (options.platform) {
|
|
56
|
-
case 'vercel':
|
|
57
|
-
await runVercelAdapter(root)
|
|
58
|
-
break
|
|
59
|
-
case 'netlify':
|
|
60
|
-
await runNetlifyAdapter(root)
|
|
61
|
-
break
|
|
62
|
-
case 'cloudflare':
|
|
63
|
-
await runCloudflareAdapter(root)
|
|
64
|
-
break
|
|
65
|
-
case 'custom': {
|
|
66
|
-
const fn = await loadCustomAdapter(root)
|
|
67
|
-
if (!fn) {
|
|
68
|
-
console.error(
|
|
69
|
-
'[cer-app] No custom adapter function found in cer.config.ts. ' +
|
|
70
|
-
'Set `adapter: async (root) => { ... }` in your config.',
|
|
71
|
-
)
|
|
72
|
-
process.exit(1)
|
|
73
|
-
}
|
|
74
|
-
await fn(root)
|
|
75
|
-
break
|
|
76
|
-
}
|
|
77
|
-
default:
|
|
78
|
-
console.error(
|
|
79
|
-
`[cer-app] Unknown platform: "${options.platform}". Supported: vercel, netlify, cloudflare, custom`,
|
|
80
|
-
)
|
|
81
|
-
process.exit(1)
|
|
82
|
-
}
|
|
83
|
-
})
|
|
84
|
-
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander'
|
|
2
|
-
import { build } from 'vite'
|
|
3
|
-
import { resolve, join } from 'pathe'
|
|
4
|
-
import { pathToFileURL } from 'node:url'
|
|
5
|
-
import { existsSync, renameSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
6
|
-
import { cerApp, resolveConfig } from '../../plugin/index.js'
|
|
7
|
-
import { buildSSR, resolveClientEntry } from '../../plugin/build-ssr.js'
|
|
8
|
-
import { buildSSG } from '../../plugin/build-ssg.js'
|
|
9
|
-
import { writeGeneratedDir } from '../../plugin/generated-dir.js'
|
|
10
|
-
import { runVercelAdapter } from '../adapters/vercel.js'
|
|
11
|
-
import { runNetlifyAdapter } from '../adapters/netlify.js'
|
|
12
|
-
import { runCloudflareAdapter } from '../adapters/cloudflare.js'
|
|
13
|
-
import type { CerAppConfig } from '../../types/config.js'
|
|
14
|
-
|
|
15
|
-
async function loadCerConfig(root: string): Promise<CerAppConfig> {
|
|
16
|
-
const configPath = resolve(root, 'cer.config.ts')
|
|
17
|
-
const configPathJs = resolve(root, 'cer.config.js')
|
|
18
|
-
|
|
19
|
-
const filePath = existsSync(configPath)
|
|
20
|
-
? configPath
|
|
21
|
-
: existsSync(configPathJs)
|
|
22
|
-
? configPathJs
|
|
23
|
-
: null
|
|
24
|
-
|
|
25
|
-
if (!filePath) return {}
|
|
26
|
-
|
|
27
|
-
try {
|
|
28
|
-
// Bootstrap .cer/tsconfig.json so rolldown can resolve it during cer.config.ts transform
|
|
29
|
-
const cerDir = resolve(root, '.cer')
|
|
30
|
-
const cerTsconfig = resolve(cerDir, 'tsconfig.json')
|
|
31
|
-
if (!existsSync(cerTsconfig)) {
|
|
32
|
-
mkdirSync(cerDir, { recursive: true })
|
|
33
|
-
writeFileSync(cerTsconfig, '{"compilerOptions":{}}\n', 'utf-8')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const { build: viteBuild } = await import('vite')
|
|
37
|
-
await viteBuild({
|
|
38
|
-
build: {
|
|
39
|
-
lib: {
|
|
40
|
-
entry: filePath,
|
|
41
|
-
formats: ['es'],
|
|
42
|
-
fileName: 'cer.config',
|
|
43
|
-
},
|
|
44
|
-
outDir: resolve(root, 'node_modules/.cer-app-cache'),
|
|
45
|
-
write: true,
|
|
46
|
-
rollupOptions: { external: (id: string) => !id.startsWith('.') && !id.startsWith('/') },
|
|
47
|
-
},
|
|
48
|
-
logLevel: 'silent',
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const outFile = resolve(root, 'node_modules/.cer-app-cache/cer.config.mjs')
|
|
52
|
-
if (existsSync(outFile)) {
|
|
53
|
-
const mod = await import(pathToFileURL(outFile).href + `?t=${Date.now()}`)
|
|
54
|
-
return mod.default ?? {}
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
// ignore
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
const mod = await import(pathToFileURL(filePath).href + `?t=${Date.now()}`)
|
|
62
|
-
return mod.default ?? {}
|
|
63
|
-
} catch {
|
|
64
|
-
return {}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function runAdapter(adapter: CerAppConfig['adapter'], root: string): Promise<void> {
|
|
69
|
-
if (!adapter) return
|
|
70
|
-
if (typeof adapter === 'function') {
|
|
71
|
-
await adapter(root)
|
|
72
|
-
return
|
|
73
|
-
}
|
|
74
|
-
switch (adapter) {
|
|
75
|
-
case 'vercel':
|
|
76
|
-
await runVercelAdapter(root)
|
|
77
|
-
break
|
|
78
|
-
case 'netlify':
|
|
79
|
-
await runNetlifyAdapter(root)
|
|
80
|
-
break
|
|
81
|
-
case 'cloudflare':
|
|
82
|
-
await runCloudflareAdapter(root)
|
|
83
|
-
break
|
|
84
|
-
default:
|
|
85
|
-
console.warn(`[cer-app] Unknown adapter "${adapter}" — skipping.`)
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function buildCommand(): Command {
|
|
90
|
-
return new Command('build')
|
|
91
|
-
.description('Build the application for production')
|
|
92
|
-
.option('--root <root>', 'Project root directory', process.cwd())
|
|
93
|
-
.option('--mode <mode>', 'Build mode: spa, ssr, or ssg (overrides cer.config.ts)')
|
|
94
|
-
.action(async (options) => {
|
|
95
|
-
const root = resolve(options.root)
|
|
96
|
-
const userConfig = await loadCerConfig(root)
|
|
97
|
-
|
|
98
|
-
// CLI --mode flag overrides config file
|
|
99
|
-
if (options.mode) {
|
|
100
|
-
userConfig.mode = options.mode as 'spa' | 'ssr' | 'ssg'
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const config = resolveConfig(userConfig, root)
|
|
104
|
-
|
|
105
|
-
console.log(`[cer-app] Building in ${config.mode} mode...`)
|
|
106
|
-
|
|
107
|
-
switch (config.mode) {
|
|
108
|
-
case 'spa': {
|
|
109
|
-
// Write .cer/ files BEFORE resolveClientEntry checks for .cer/index.html.
|
|
110
|
-
writeGeneratedDir(config)
|
|
111
|
-
const spaEntry = resolveClientEntry(config)
|
|
112
|
-
const spaOutDir = resolve(root, 'dist')
|
|
113
|
-
await build({
|
|
114
|
-
root,
|
|
115
|
-
plugins: cerApp(userConfig),
|
|
116
|
-
build: {
|
|
117
|
-
outDir: spaOutDir,
|
|
118
|
-
rollupOptions: { input: spaEntry },
|
|
119
|
-
},
|
|
120
|
-
})
|
|
121
|
-
// If the entry was .cer/index.html, Vite outputs it as dist/.cer/index.html.
|
|
122
|
-
// Rename it to dist/index.html so the preview server can find it.
|
|
123
|
-
const generatedHtmlOut = join(spaOutDir, '.cer/index.html')
|
|
124
|
-
const rootHtmlOut = join(spaOutDir, 'index.html')
|
|
125
|
-
if (existsSync(generatedHtmlOut) && !existsSync(rootHtmlOut)) {
|
|
126
|
-
renameSync(generatedHtmlOut, rootHtmlOut)
|
|
127
|
-
}
|
|
128
|
-
console.log('[cer-app] SPA build complete.')
|
|
129
|
-
await runAdapter(userConfig.adapter, root)
|
|
130
|
-
// Force exit: Vite HTML builds may keep Node timers alive.
|
|
131
|
-
process.exit(0)
|
|
132
|
-
break
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
case 'ssr': {
|
|
136
|
-
const viteUserConfig = {
|
|
137
|
-
root,
|
|
138
|
-
plugins: cerApp(userConfig),
|
|
139
|
-
}
|
|
140
|
-
await buildSSR(config, viteUserConfig)
|
|
141
|
-
await runAdapter(userConfig.adapter, root)
|
|
142
|
-
// Force exit: the client (HTML) build may keep Node timers alive.
|
|
143
|
-
process.exit(0)
|
|
144
|
-
break
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
case 'ssg': {
|
|
148
|
-
const viteUserConfig = {
|
|
149
|
-
root,
|
|
150
|
-
plugins: cerApp(userConfig),
|
|
151
|
-
}
|
|
152
|
-
await buildSSG(config, viteUserConfig)
|
|
153
|
-
await runAdapter(userConfig.adapter, root)
|
|
154
|
-
// Force exit: the SSG path-enumeration Vite server may keep alive Node timers
|
|
155
|
-
process.exit(0)
|
|
156
|
-
break
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
default: {
|
|
160
|
-
console.error(`[cer-app] Unknown mode: ${config.mode}`)
|
|
161
|
-
process.exit(1)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
}
|
package/src/cli/commands/dev.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander'
|
|
2
|
-
import { createServer } from 'vite'
|
|
3
|
-
import { resolve } from 'pathe'
|
|
4
|
-
import { pathToFileURL } from 'node:url'
|
|
5
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
6
|
-
import { cerApp } from '../../plugin/index.js'
|
|
7
|
-
import type { CerAppConfig } from '../../types/config.js'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Loads cer.config.ts from the current working directory.
|
|
11
|
-
* Returns an empty object if no config file is found.
|
|
12
|
-
*/
|
|
13
|
-
async function loadCerConfig(root: string): Promise<CerAppConfig> {
|
|
14
|
-
const configPath = resolve(root, 'cer.config.ts')
|
|
15
|
-
const configPathJs = resolve(root, 'cer.config.js')
|
|
16
|
-
|
|
17
|
-
const filePath = existsSync(configPath)
|
|
18
|
-
? configPath
|
|
19
|
-
: existsSync(configPathJs)
|
|
20
|
-
? configPathJs
|
|
21
|
-
: null
|
|
22
|
-
|
|
23
|
-
if (!filePath) {
|
|
24
|
-
console.warn('[cer-app] No cer.config.ts found; using defaults.')
|
|
25
|
-
return {}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
const originalNodeEnv = process.env.NODE_ENV
|
|
30
|
-
const originalMode = process.env.MODE
|
|
31
|
-
// Bootstrap .cer/tsconfig.json so rolldown can resolve it during cer.config.ts transform
|
|
32
|
-
const cerDir = resolve(root, '.cer')
|
|
33
|
-
const cerTsconfig = resolve(cerDir, 'tsconfig.json')
|
|
34
|
-
if (!existsSync(cerTsconfig)) {
|
|
35
|
-
mkdirSync(cerDir, { recursive: true })
|
|
36
|
-
writeFileSync(cerTsconfig, '{"compilerOptions":{}}\n', 'utf-8')
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Use Vite's build to transpile TS config at runtime
|
|
40
|
-
try {
|
|
41
|
-
const { build } = await import('vite')
|
|
42
|
-
await build({
|
|
43
|
-
build: {
|
|
44
|
-
lib: {
|
|
45
|
-
entry: filePath,
|
|
46
|
-
formats: ['es'],
|
|
47
|
-
fileName: 'cer.config',
|
|
48
|
-
},
|
|
49
|
-
outDir: resolve(root, 'node_modules/.cer-app-cache'),
|
|
50
|
-
write: true,
|
|
51
|
-
rollupOptions: {
|
|
52
|
-
// Externalize all bare package imports (handles file: symlinks too)
|
|
53
|
-
external: (id: string) => !id.startsWith('.') && !id.startsWith('/'),
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
logLevel: 'silent',
|
|
57
|
-
})
|
|
58
|
-
} finally {
|
|
59
|
-
if (typeof originalNodeEnv === 'undefined') delete process.env.NODE_ENV
|
|
60
|
-
else process.env.NODE_ENV = originalNodeEnv
|
|
61
|
-
if (typeof originalMode === 'undefined') delete process.env.MODE
|
|
62
|
-
else process.env.MODE = originalMode
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const outFile = resolve(root, 'node_modules/.cer-app-cache/cer.config.mjs')
|
|
66
|
-
if (existsSync(outFile)) {
|
|
67
|
-
const mod = await import(pathToFileURL(outFile).href + `?t=${Date.now()}`)
|
|
68
|
-
return mod.default ?? {}
|
|
69
|
-
}
|
|
70
|
-
} catch (err) {
|
|
71
|
-
console.warn('[cer-app] Could not load cer.config.ts via build, trying dynamic import:', err)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Fallback: try direct import (works for .js configs)
|
|
75
|
-
try {
|
|
76
|
-
const mod = await import(pathToFileURL(filePath).href + `?t=${Date.now()}`)
|
|
77
|
-
return mod.default ?? {}
|
|
78
|
-
} catch {
|
|
79
|
-
return {}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function devCommand(): Command {
|
|
84
|
-
return new Command('dev')
|
|
85
|
-
.description('Start the development server')
|
|
86
|
-
.option('-p, --port <port>', 'Port to listen on', '3000')
|
|
87
|
-
.option('--host <host>', 'Host to bind to', 'localhost')
|
|
88
|
-
.option('--root <root>', 'Project root directory', process.cwd())
|
|
89
|
-
.option('--mode <mode>', 'Dev mode: spa, ssr, or ssg (overrides cer.config.ts)')
|
|
90
|
-
.action(async (options) => {
|
|
91
|
-
const root = resolve(options.root)
|
|
92
|
-
const userConfig = await loadCerConfig(root)
|
|
93
|
-
process.env.NODE_ENV = 'development'
|
|
94
|
-
process.env.MODE = 'development'
|
|
95
|
-
// CLI --mode flag overrides config file (mirrors build command behaviour)
|
|
96
|
-
if (options.mode) {
|
|
97
|
-
userConfig.mode = options.mode as 'spa' | 'ssr' | 'ssg'
|
|
98
|
-
}
|
|
99
|
-
const port = options.port ? parseInt(options.port, 10) : (userConfig.port ?? 3000)
|
|
100
|
-
|
|
101
|
-
console.log('[cer-app] Starting dev server...')
|
|
102
|
-
|
|
103
|
-
const server = await createServer({
|
|
104
|
-
root,
|
|
105
|
-
server: {
|
|
106
|
-
port,
|
|
107
|
-
host: options.host,
|
|
108
|
-
},
|
|
109
|
-
plugins: cerApp(userConfig),
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
await server.listen()
|
|
113
|
-
server.printUrls()
|
|
114
|
-
|
|
115
|
-
// Handle graceful shutdown
|
|
116
|
-
process.on('SIGTERM', async () => {
|
|
117
|
-
await server.close()
|
|
118
|
-
process.exit(0)
|
|
119
|
-
})
|
|
120
|
-
process.on('SIGINT', async () => {
|
|
121
|
-
await server.close()
|
|
122
|
-
process.exit(0)
|
|
123
|
-
})
|
|
124
|
-
})
|
|
125
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { Command } from 'commander'
|
|
2
|
-
import { resolve } from 'pathe'
|
|
3
|
-
import { pathToFileURL } from 'node:url'
|
|
4
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
5
|
-
import { resolveConfig } from '../../plugin/index.js'
|
|
6
|
-
import { buildSSG } from '../../plugin/build-ssg.js'
|
|
7
|
-
import { cerApp } from '../../plugin/index.js'
|
|
8
|
-
import type { CerAppConfig } from '../../types/config.js'
|
|
9
|
-
|
|
10
|
-
async function loadCerConfig(root: string): Promise<CerAppConfig> {
|
|
11
|
-
const configPath = resolve(root, 'cer.config.ts')
|
|
12
|
-
const configPathJs = resolve(root, 'cer.config.js')
|
|
13
|
-
|
|
14
|
-
const filePath = existsSync(configPath)
|
|
15
|
-
? configPath
|
|
16
|
-
: existsSync(configPathJs)
|
|
17
|
-
? configPathJs
|
|
18
|
-
: null
|
|
19
|
-
|
|
20
|
-
if (!filePath) return {}
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
// Bootstrap .cer/tsconfig.json so rolldown can resolve it during cer.config.ts transform
|
|
24
|
-
const cerDir = resolve(root, '.cer')
|
|
25
|
-
const cerTsconfig = resolve(cerDir, 'tsconfig.json')
|
|
26
|
-
if (!existsSync(cerTsconfig)) {
|
|
27
|
-
mkdirSync(cerDir, { recursive: true })
|
|
28
|
-
writeFileSync(cerTsconfig, '{"compilerOptions":{}}\n', 'utf-8')
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const { build } = await import('vite')
|
|
32
|
-
await build({
|
|
33
|
-
build: {
|
|
34
|
-
lib: {
|
|
35
|
-
entry: filePath,
|
|
36
|
-
formats: ['es'],
|
|
37
|
-
fileName: 'cer.config',
|
|
38
|
-
},
|
|
39
|
-
outDir: resolve(root, 'node_modules/.cer-app-cache'),
|
|
40
|
-
write: true,
|
|
41
|
-
rollupOptions: { external: (id: string) => !id.startsWith('.') && !id.startsWith('/') },
|
|
42
|
-
},
|
|
43
|
-
logLevel: 'silent',
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const outFile = resolve(root, 'node_modules/.cer-app-cache/cer.config.mjs')
|
|
47
|
-
if (existsSync(outFile)) {
|
|
48
|
-
const mod = await import(pathToFileURL(outFile).href + `?t=${Date.now()}`)
|
|
49
|
-
return mod.default ?? {}
|
|
50
|
-
}
|
|
51
|
-
} catch {
|
|
52
|
-
// ignore
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const mod = await import(pathToFileURL(filePath).href + `?t=${Date.now()}`)
|
|
57
|
-
return mod.default ?? {}
|
|
58
|
-
} catch {
|
|
59
|
-
return {}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* `cer-app generate` — runs the full SSG build pipeline.
|
|
65
|
-
* Alias for `cer-app build --mode ssg`.
|
|
66
|
-
*/
|
|
67
|
-
export function generateCommand(): Command {
|
|
68
|
-
return new Command('generate')
|
|
69
|
-
.description('Generate a static site (SSG build)')
|
|
70
|
-
.option('--root <root>', 'Project root directory', process.cwd())
|
|
71
|
-
.action(async (options) => {
|
|
72
|
-
const root = resolve(options.root)
|
|
73
|
-
const userConfig = await loadCerConfig(root)
|
|
74
|
-
|
|
75
|
-
// Force SSG mode
|
|
76
|
-
userConfig.mode = 'ssg'
|
|
77
|
-
|
|
78
|
-
const config = resolveConfig(userConfig, root)
|
|
79
|
-
|
|
80
|
-
console.log('[cer-app] Running SSG generation...')
|
|
81
|
-
|
|
82
|
-
const viteUserConfig = {
|
|
83
|
-
root,
|
|
84
|
-
plugins: cerApp(userConfig),
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
await buildSSG(config, viteUserConfig)
|
|
88
|
-
// Force exit: the SSG path-enumeration Vite server may keep alive Node timers.
|
|
89
|
-
process.exit(0)
|
|
90
|
-
})
|
|
91
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ISR (Incremental Static Regeneration) helpers for the preview server.
|
|
3
|
-
*
|
|
4
|
-
* Extracted into their own module so they can be unit-tested independently
|
|
5
|
-
* from the HTTP server wiring in preview.ts.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { resolve, join } from 'pathe'
|
|
9
|
-
import { Readable } from 'node:stream'
|
|
10
|
-
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
11
|
-
|
|
12
|
-
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
13
|
-
|
|
14
|
-
export interface IsrCacheEntry {
|
|
15
|
-
html: string
|
|
16
|
-
headers: Record<string, string>
|
|
17
|
-
statusCode: number
|
|
18
|
-
builtAt: number
|
|
19
|
-
revalidate: number
|
|
20
|
-
/** True while a background re-render is in flight (stale-while-revalidate). */
|
|
21
|
-
revalidating: boolean
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type IsrCacheStatus = 'HIT' | 'STALE' | 'MISS'
|
|
25
|
-
|
|
26
|
-
export type SsrHandlerFn = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>
|
|
27
|
-
|
|
28
|
-
// ─── Path traversal guard ─────────────────────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Returns `true` when `urlPath` joined onto `rootDir` resolves to a path that
|
|
32
|
-
* is strictly inside (or equal to) `rootDir`. A traversal attempt such as
|
|
33
|
-
* `../../../../etc/passwd` would resolve outside `rootDir` and return `false`.
|
|
34
|
-
*/
|
|
35
|
-
export function isPathBounded(rootDir: string, urlPath: string): boolean {
|
|
36
|
-
const safeRoot = resolve(rootDir)
|
|
37
|
-
const resolved = resolve(join(rootDir, urlPath))
|
|
38
|
-
return resolved === safeRoot || resolved.startsWith(safeRoot + '/')
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ─── Route pattern matching ───────────────────────────────────────────────────
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Tests whether a route path pattern matches a URL path string.
|
|
45
|
-
* Normalises trailing slashes and supports `:param` and `:param*` (catch-all)
|
|
46
|
-
* segments using a simple regex conversion — no external dependencies needed.
|
|
47
|
-
*
|
|
48
|
-
* @example
|
|
49
|
-
* matchRoutePattern('/blog/:slug', '/blog/hello') // true
|
|
50
|
-
* matchRoutePattern('/:all*', '/any/deep/path') // true
|
|
51
|
-
* matchRoutePattern('/about', '/contact') // false
|
|
52
|
-
*/
|
|
53
|
-
export function matchRoutePattern(pattern: string, urlPath: string): boolean {
|
|
54
|
-
const norm = (s: string): string => s.replace(/\/+$/, '') || '/'
|
|
55
|
-
if (norm(pattern) === norm(urlPath)) return true
|
|
56
|
-
const regexStr =
|
|
57
|
-
'^' +
|
|
58
|
-
norm(pattern)
|
|
59
|
-
.replace(/[.+?^${}()|[\]\\]/g, '\\$&') // escape regex special chars in static segments
|
|
60
|
-
.replace(/:[^/]+\*/g, '.*')
|
|
61
|
-
.replace(/:[^/]+/g, '[^/]+') +
|
|
62
|
-
'$'
|
|
63
|
-
return new RegExp(regexStr).test(norm(urlPath))
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Returns the per-route `render` strategy ('static' | 'server' | 'spa') for
|
|
68
|
-
* the route that best matches `urlPath`, or `null` when no route matches or
|
|
69
|
-
* none declares a render mode.
|
|
70
|
-
*/
|
|
71
|
-
export function findRenderMode(
|
|
72
|
-
routes: Array<{ path: string; meta?: Record<string, unknown> }>,
|
|
73
|
-
urlPath: string,
|
|
74
|
-
): 'static' | 'server' | 'spa' | null {
|
|
75
|
-
for (const route of routes) {
|
|
76
|
-
if (matchRoutePattern(route.path, urlPath)) {
|
|
77
|
-
const render = route.meta?.render
|
|
78
|
-
if (render === 'static' || render === 'server' || render === 'spa') return render
|
|
79
|
-
return null
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Looks up the `meta.ssg.revalidate` TTL (in seconds) for the route that best
|
|
87
|
-
* matches `urlPath`. Returns `null` when no route matches or none defines
|
|
88
|
-
* `revalidate`.
|
|
89
|
-
*/
|
|
90
|
-
export function findRevalidate(
|
|
91
|
-
routes: Array<{ path: string; meta?: Record<string, unknown> }>,
|
|
92
|
-
urlPath: string,
|
|
93
|
-
): number | null {
|
|
94
|
-
for (const route of routes) {
|
|
95
|
-
if (matchRoutePattern(route.path, urlPath)) {
|
|
96
|
-
const ssg = route.meta?.ssg as Record<string, unknown> | undefined
|
|
97
|
-
if (typeof ssg?.revalidate === 'number') return ssg.revalidate
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
return null
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// ─── Response capture ─────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Renders a URL path through `handler` using a synthetic IncomingMessage and a
|
|
107
|
-
* fake ServerResponse that captures the output in memory.
|
|
108
|
-
*
|
|
109
|
-
* Returns an `IsrCacheEntry` on success, or `null` if the handler throws.
|
|
110
|
-
*/
|
|
111
|
-
export async function renderForIsr(
|
|
112
|
-
urlPath: string,
|
|
113
|
-
handler: SsrHandlerFn,
|
|
114
|
-
revalidate: number,
|
|
115
|
-
): Promise<IsrCacheEntry | null> {
|
|
116
|
-
const req = Object.assign(new Readable({ read() {} }), {
|
|
117
|
-
url: urlPath,
|
|
118
|
-
method: 'GET',
|
|
119
|
-
headers: {},
|
|
120
|
-
socket: null,
|
|
121
|
-
}) as unknown as IncomingMessage
|
|
122
|
-
|
|
123
|
-
return new Promise<IsrCacheEntry | null>((resolve) => {
|
|
124
|
-
const chunks: Buffer[] = []
|
|
125
|
-
const headers: Record<string, string> = {}
|
|
126
|
-
let capturedStatus = 200
|
|
127
|
-
|
|
128
|
-
const fakeRes = {
|
|
129
|
-
get statusCode() { return capturedStatus },
|
|
130
|
-
set statusCode(v: number) { capturedStatus = v },
|
|
131
|
-
headersSent: false,
|
|
132
|
-
setHeader(name: string, value: string | string[]) {
|
|
133
|
-
headers[name.toLowerCase()] = Array.isArray(value) ? value.join(', ') : String(value)
|
|
134
|
-
return this
|
|
135
|
-
},
|
|
136
|
-
getHeader(name: string) { return headers[name.toLowerCase()] },
|
|
137
|
-
write(chunk: string | Buffer) {
|
|
138
|
-
if (chunk != null) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)))
|
|
139
|
-
return true
|
|
140
|
-
},
|
|
141
|
-
end(chunk?: string | Buffer) {
|
|
142
|
-
if (chunk != null) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)))
|
|
143
|
-
const html = Buffer.concat(chunks).toString('utf-8')
|
|
144
|
-
resolve({ html, headers, statusCode: capturedStatus, builtAt: Date.now(), revalidate, revalidating: false })
|
|
145
|
-
return this
|
|
146
|
-
},
|
|
147
|
-
} as unknown as ServerResponse
|
|
148
|
-
|
|
149
|
-
// Use Promise.resolve().then() so synchronous throws in the handler are
|
|
150
|
-
// also caught by the .catch() handler.
|
|
151
|
-
Promise.resolve().then(() => handler(req, fakeRes)).catch(() => resolve(null))
|
|
152
|
-
})
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// ─── Cache serving ────────────────────────────────────────────────────────────
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Writes a cached ISR entry to the real HTTP response, forwarding all captured
|
|
159
|
-
* headers and setting the `X-Cache` diagnostic header.
|
|
160
|
-
*/
|
|
161
|
-
export function serveFromIsrCache(
|
|
162
|
-
entry: IsrCacheEntry,
|
|
163
|
-
res: ServerResponse,
|
|
164
|
-
cacheStatus: IsrCacheStatus,
|
|
165
|
-
): void {
|
|
166
|
-
for (const [name, value] of Object.entries(entry.headers)) {
|
|
167
|
-
res.setHeader(name, value)
|
|
168
|
-
}
|
|
169
|
-
res.setHeader('X-Cache', cacheStatus)
|
|
170
|
-
res.statusCode = entry.statusCode
|
|
171
|
-
res.end(entry.html)
|
|
172
|
-
}
|