@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,407 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OAuth 2.0 request handlers — initiate, callback, and logout.
|
|
3
|
-
*
|
|
4
|
-
* All three functions run inside a `runWithRequestContext` scope so
|
|
5
|
-
* `useSession()` and `useCookie()` work correctly (they read/write HTTP
|
|
6
|
-
* headers via AsyncLocalStorage).
|
|
7
|
-
*
|
|
8
|
-
* Security:
|
|
9
|
-
* - PKCE (S256) is used for all providers that support it (Google, Discord).
|
|
10
|
-
* GitHub does not support PKCE so it is omitted for that provider.
|
|
11
|
-
* - The `state` parameter is a 16-byte random value stored in a short-lived
|
|
12
|
-
* (`_oauth_pkce`) session cookie. The callback verifies it before
|
|
13
|
-
* exchanging the code, preventing CSRF.
|
|
14
|
-
* - `clientSecret` never appears in any client bundle — this file is only
|
|
15
|
-
* imported by the server-side virtual:cer-server-api module.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
19
|
-
import { useSession } from '../composables/use-session.js'
|
|
20
|
-
import { OAUTH_PROVIDERS } from './providers.js'
|
|
21
|
-
|
|
22
|
-
// ─── Types ────────────────────────────────────────────────────────────────────
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Normalised OAuth user written to the auth session cookie after a
|
|
26
|
-
* successful callback. Also exported from `composables/use-auth.ts` under
|
|
27
|
-
* the same name — both definitions are structurally identical and
|
|
28
|
-
* TypeScript treats them as compatible.
|
|
29
|
-
*/
|
|
30
|
-
export interface AuthUser {
|
|
31
|
-
/** OAuth provider name, e.g. `'google'`, `'github'`, `'discord'`. */
|
|
32
|
-
provider: string
|
|
33
|
-
/** Provider-issued user id, always coerced to a string. */
|
|
34
|
-
id: string
|
|
35
|
-
name?: string
|
|
36
|
-
email?: string
|
|
37
|
-
/** URL of the user's profile picture / avatar. */
|
|
38
|
-
avatar?: string
|
|
39
|
-
[key: string]: unknown
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Subset of `OAuthProviderConfig` that is serialised into the virtual
|
|
44
|
-
* `server-api` module at build time. Only the fields needed at request
|
|
45
|
-
* time are included — the full plugin config is NOT exposed to the server
|
|
46
|
-
* bundle.
|
|
47
|
-
*/
|
|
48
|
-
interface ResolvedProviderConfig {
|
|
49
|
-
clientId: string
|
|
50
|
-
clientSecret: string
|
|
51
|
-
scope?: string[]
|
|
52
|
-
authorizationUrl?: string
|
|
53
|
-
tokenUrl?: string
|
|
54
|
-
userInfoUrl?: string
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Shape of the `_authCfg` constant injected into the virtual server-api
|
|
59
|
-
* module by the plugin.
|
|
60
|
-
*
|
|
61
|
-
* - `providers` — map of provider name → credentials + optional overrides.
|
|
62
|
-
* Built-in providers (`google`, `github`, `discord`) only need
|
|
63
|
-
* `clientId` / `clientSecret`; custom providers must supply all three
|
|
64
|
-
* endpoint URLs.
|
|
65
|
-
* - `redirectAfterLogin` — relative or absolute URL to redirect to after a
|
|
66
|
-
* successful OAuth callback (e.g. `'/dashboard'`).
|
|
67
|
-
* - `redirectAfterLogout` — URL to redirect to after the logout endpoint
|
|
68
|
-
* clears the session cookie (e.g. `'/'`).
|
|
69
|
-
* - `sessionKey` — name of the auth session cookie; must match
|
|
70
|
-
* `auth.sessionKey` in `cer.config.ts` (defaults to `'auth'`).
|
|
71
|
-
*/
|
|
72
|
-
export interface ResolvedAuthConfig {
|
|
73
|
-
providers?: Record<string, ResolvedProviderConfig | undefined>
|
|
74
|
-
redirectAfterLogin: string
|
|
75
|
-
redirectAfterLogout: string
|
|
76
|
-
sessionKey: string
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
interface PkceSessionData {
|
|
80
|
-
state: string
|
|
81
|
-
verifier: string
|
|
82
|
-
provider: string
|
|
83
|
-
[key: string]: unknown
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ─── Web Crypto helpers ───────────────────────────────────────────────────────
|
|
87
|
-
|
|
88
|
-
const ENC = new TextEncoder()
|
|
89
|
-
|
|
90
|
-
/** Encode an ArrayBuffer as a URL-safe base64 string (no padding). */
|
|
91
|
-
function _b64u(buf: ArrayBuffer): string {
|
|
92
|
-
return btoa(String.fromCharCode(...new Uint8Array(buf)))
|
|
93
|
-
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Generate a 32-byte cryptographically random PKCE code verifier.
|
|
98
|
-
* Encoded as base64url per RFC 7636 §4.1.
|
|
99
|
-
*/
|
|
100
|
-
async function generateCodeVerifier(): Promise<string> {
|
|
101
|
-
const bytes = new Uint8Array(32)
|
|
102
|
-
crypto.getRandomValues(bytes)
|
|
103
|
-
return _b64u(bytes.buffer as ArrayBuffer)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Derive the PKCE S256 code challenge from the verifier.
|
|
108
|
-
* `code_challenge = BASE64URL(SHA-256(ASCII(code_verifier)))` — RFC 7636 §4.2.
|
|
109
|
-
*/
|
|
110
|
-
async function generateCodeChallenge(verifier: string): Promise<string> {
|
|
111
|
-
const hash = await crypto.subtle.digest('SHA-256', ENC.encode(verifier))
|
|
112
|
-
return _b64u(hash)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Generate a 16-byte cryptographically random state parameter.
|
|
117
|
-
* Used to bind the initiate and callback requests (CSRF protection).
|
|
118
|
-
*/
|
|
119
|
-
function generateState(): string {
|
|
120
|
-
const bytes = new Uint8Array(16)
|
|
121
|
-
crypto.getRandomValues(bytes)
|
|
122
|
-
return _b64u(bytes.buffer as ArrayBuffer)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// ─── URL helpers ──────────────────────────────────────────────────────────────
|
|
126
|
-
|
|
127
|
-
function getCallbackUrl(req: IncomingMessage, provider: string): string {
|
|
128
|
-
const proto = (req.headers['x-forwarded-proto'] as string | undefined) ?? 'http'
|
|
129
|
-
const host = (req.headers.host as string | undefined) ?? 'localhost'
|
|
130
|
-
return `${proto}://${host}/api/auth/callback/${provider}`
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function getQueryParam(req: IncomingMessage, name: string): string | null {
|
|
134
|
-
try {
|
|
135
|
-
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`)
|
|
136
|
-
return url.searchParams.get(name)
|
|
137
|
-
} catch {
|
|
138
|
-
return null
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// ─── Profile normalisation ────────────────────────────────────────────────────
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Map a raw provider userinfo response to the canonical {@link AuthUser}
|
|
146
|
-
* shape. Each provider uses slightly different field names:
|
|
147
|
-
*
|
|
148
|
-
* | Provider | id field | name field | avatar field |
|
|
149
|
-
* |----------|----------------|-------------------------|----------------|
|
|
150
|
-
* | google | `id` or `sub` | `name` | `picture` |
|
|
151
|
-
* | github | `id` | `name` or `login` | `avatar_url` |
|
|
152
|
-
* | discord | `id` | `global_name`/`username`| CDN avatar URL |
|
|
153
|
-
*
|
|
154
|
-
* Unknown providers fall back to a best-effort mapping using common field
|
|
155
|
-
* names (`id`, `sub`, `name`, `username`, `email`, `avatar`, `picture`,
|
|
156
|
-
* `avatar_url`). All values are coerced to strings; missing fields become
|
|
157
|
-
* empty strings.
|
|
158
|
-
*/
|
|
159
|
-
function normaliseProfile(provider: string, profile: Record<string, unknown>): AuthUser {
|
|
160
|
-
switch (provider) {
|
|
161
|
-
case 'google':
|
|
162
|
-
return {
|
|
163
|
-
provider,
|
|
164
|
-
id: String(profile.id ?? profile.sub ?? ''),
|
|
165
|
-
name: String(profile.name ?? ''),
|
|
166
|
-
email: String(profile.email ?? ''),
|
|
167
|
-
avatar: String(profile.picture ?? ''),
|
|
168
|
-
}
|
|
169
|
-
case 'github':
|
|
170
|
-
return {
|
|
171
|
-
provider,
|
|
172
|
-
id: String(profile.id ?? ''),
|
|
173
|
-
name: String(profile.name ?? profile.login ?? ''),
|
|
174
|
-
email: String(profile.email ?? ''),
|
|
175
|
-
avatar: String(profile.avatar_url ?? ''),
|
|
176
|
-
}
|
|
177
|
-
case 'discord':
|
|
178
|
-
return {
|
|
179
|
-
provider,
|
|
180
|
-
id: String(profile.id ?? ''),
|
|
181
|
-
name: String(profile.global_name ?? profile.username ?? ''),
|
|
182
|
-
email: String(profile.email ?? ''),
|
|
183
|
-
avatar: profile.avatar && profile.id
|
|
184
|
-
? `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.png`
|
|
185
|
-
: '',
|
|
186
|
-
}
|
|
187
|
-
default:
|
|
188
|
-
return {
|
|
189
|
-
provider,
|
|
190
|
-
id: String(profile.id ?? profile.sub ?? ''),
|
|
191
|
-
name: String(profile.name ?? (profile.username as string | undefined) ?? ''),
|
|
192
|
-
email: String(profile.email ?? ''),
|
|
193
|
-
avatar: String(
|
|
194
|
-
profile.avatar ?? profile.picture ?? profile.avatar_url ?? '',
|
|
195
|
-
),
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// ─── Public handlers ──────────────────────────────────────────────────────────
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* GET /api/auth/:provider
|
|
204
|
-
*
|
|
205
|
-
* Generates a PKCE code verifier + state, stores them in a short-lived session
|
|
206
|
-
* cookie, and redirects the browser to the provider's authorization URL.
|
|
207
|
-
*/
|
|
208
|
-
export async function handleOAuthInitiate(
|
|
209
|
-
req: IncomingMessage,
|
|
210
|
-
res: ServerResponse,
|
|
211
|
-
provider: string,
|
|
212
|
-
config: ResolvedAuthConfig,
|
|
213
|
-
): Promise<void> {
|
|
214
|
-
const providerConfig = config.providers?.[provider]
|
|
215
|
-
if (!providerConfig) {
|
|
216
|
-
res.statusCode = 404
|
|
217
|
-
res.end(`[cer-app] Unknown OAuth provider: ${provider}`)
|
|
218
|
-
return
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const endpoints = OAUTH_PROVIDERS[provider]
|
|
222
|
-
const authUrl = providerConfig.authorizationUrl ?? endpoints?.authorizationUrl
|
|
223
|
-
if (!authUrl) {
|
|
224
|
-
res.statusCode = 500
|
|
225
|
-
res.end(`[cer-app] OAuth provider "${provider}" is missing authorizationUrl`)
|
|
226
|
-
return
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const state = generateState()
|
|
230
|
-
const verifier = await generateCodeVerifier()
|
|
231
|
-
|
|
232
|
-
// Store state + verifier in a short-lived PKCE session (10 minutes).
|
|
233
|
-
const pkceSession = useSession<PkceSessionData>({ name: '_oauth_pkce', maxAge: 600 })
|
|
234
|
-
await pkceSession.set({ state, verifier, provider })
|
|
235
|
-
|
|
236
|
-
const usePkce = providerConfig.authorizationUrl ? true : (endpoints?.pkce ?? true)
|
|
237
|
-
const scopes = providerConfig.scope ?? endpoints?.defaultScopes ?? []
|
|
238
|
-
|
|
239
|
-
const params = new URLSearchParams({
|
|
240
|
-
client_id: providerConfig.clientId,
|
|
241
|
-
redirect_uri: getCallbackUrl(req, provider),
|
|
242
|
-
response_type: 'code',
|
|
243
|
-
scope: scopes.join(' '),
|
|
244
|
-
state,
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
if (usePkce) {
|
|
248
|
-
params.set('code_challenge', await generateCodeChallenge(verifier))
|
|
249
|
-
params.set('code_challenge_method', 'S256')
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
res.statusCode = 302
|
|
253
|
-
res.setHeader('Location', `${authUrl}?${params.toString()}`)
|
|
254
|
-
res.end()
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* GET /api/auth/callback/:provider
|
|
259
|
-
*
|
|
260
|
-
* Validates the state param, exchanges the authorisation code for tokens,
|
|
261
|
-
* fetches the user profile, normalises it, and stores the result in the
|
|
262
|
-
* auth session cookie before redirecting to `redirectAfterLogin`.
|
|
263
|
-
*/
|
|
264
|
-
export async function handleOAuthCallback(
|
|
265
|
-
req: IncomingMessage,
|
|
266
|
-
res: ServerResponse,
|
|
267
|
-
provider: string,
|
|
268
|
-
config: ResolvedAuthConfig,
|
|
269
|
-
): Promise<void> {
|
|
270
|
-
const code = getQueryParam(req, 'code')
|
|
271
|
-
const state = getQueryParam(req, 'state')
|
|
272
|
-
|
|
273
|
-
if (!code || !state) {
|
|
274
|
-
res.statusCode = 400
|
|
275
|
-
res.end('[cer-app] OAuth callback missing code or state parameter')
|
|
276
|
-
return
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Validate state to prevent CSRF.
|
|
280
|
-
const pkceSession = useSession<PkceSessionData>({ name: '_oauth_pkce', maxAge: 600 })
|
|
281
|
-
const pkceData = await pkceSession.get()
|
|
282
|
-
|
|
283
|
-
if (!pkceData || pkceData.state !== state || pkceData.provider !== provider) {
|
|
284
|
-
res.statusCode = 400
|
|
285
|
-
res.end('[cer-app] OAuth state mismatch — possible CSRF attempt')
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
|
-
await pkceSession.clear()
|
|
289
|
-
|
|
290
|
-
const providerConfig = config.providers?.[provider]
|
|
291
|
-
if (!providerConfig) {
|
|
292
|
-
res.statusCode = 404
|
|
293
|
-
res.end(`[cer-app] Unknown OAuth provider: ${provider}`)
|
|
294
|
-
return
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const endpoints = OAUTH_PROVIDERS[provider]
|
|
298
|
-
const tokenUrl = providerConfig.tokenUrl ?? endpoints?.tokenUrl
|
|
299
|
-
const userInfoUrl = providerConfig.userInfoUrl ?? endpoints?.userInfoUrl
|
|
300
|
-
|
|
301
|
-
if (!tokenUrl || !userInfoUrl) {
|
|
302
|
-
res.statusCode = 500
|
|
303
|
-
res.end(`[cer-app] OAuth provider "${provider}" is missing tokenUrl or userInfoUrl`)
|
|
304
|
-
return
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Exchange authorisation code for tokens.
|
|
308
|
-
const usePkce = providerConfig.authorizationUrl ? true : (endpoints?.pkce ?? true)
|
|
309
|
-
const tokenBody: Record<string, string> = {
|
|
310
|
-
grant_type: 'authorization_code',
|
|
311
|
-
client_id: providerConfig.clientId,
|
|
312
|
-
client_secret: providerConfig.clientSecret,
|
|
313
|
-
code,
|
|
314
|
-
redirect_uri: getCallbackUrl(req, provider),
|
|
315
|
-
}
|
|
316
|
-
if (usePkce) {
|
|
317
|
-
tokenBody.code_verifier = pkceData.verifier
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
let tokenRes: Response
|
|
321
|
-
try {
|
|
322
|
-
tokenRes = await fetch(tokenUrl, {
|
|
323
|
-
method: 'POST',
|
|
324
|
-
headers: {
|
|
325
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
326
|
-
'Accept': 'application/json',
|
|
327
|
-
},
|
|
328
|
-
body: new URLSearchParams(tokenBody).toString(),
|
|
329
|
-
})
|
|
330
|
-
} catch {
|
|
331
|
-
res.statusCode = 502
|
|
332
|
-
res.end('[cer-app] OAuth token exchange request failed')
|
|
333
|
-
return
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (!tokenRes.ok) {
|
|
337
|
-
res.statusCode = 502
|
|
338
|
-
res.end('[cer-app] OAuth token exchange returned non-OK status')
|
|
339
|
-
return
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
let tokens: { access_token: string; refresh_token?: string; expires_in?: number; token_type?: string }
|
|
343
|
-
try {
|
|
344
|
-
tokens = await tokenRes.json() as typeof tokens
|
|
345
|
-
} catch {
|
|
346
|
-
res.statusCode = 502
|
|
347
|
-
res.end('[cer-app] OAuth token exchange returned invalid JSON')
|
|
348
|
-
return
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Fetch the user's profile from the provider.
|
|
352
|
-
let userRes: Response
|
|
353
|
-
try {
|
|
354
|
-
userRes = await fetch(userInfoUrl, {
|
|
355
|
-
headers: {
|
|
356
|
-
'Authorization': `${tokens.token_type ?? 'Bearer'} ${tokens.access_token}`,
|
|
357
|
-
'Accept': 'application/json',
|
|
358
|
-
},
|
|
359
|
-
})
|
|
360
|
-
} catch {
|
|
361
|
-
res.statusCode = 502
|
|
362
|
-
res.end('[cer-app] OAuth user-info request failed')
|
|
363
|
-
return
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
if (!userRes.ok) {
|
|
367
|
-
res.statusCode = 502
|
|
368
|
-
res.end('[cer-app] OAuth user-info returned non-OK status')
|
|
369
|
-
return
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
let profile: Record<string, unknown>
|
|
373
|
-
try {
|
|
374
|
-
profile = await userRes.json() as Record<string, unknown>
|
|
375
|
-
} catch {
|
|
376
|
-
res.statusCode = 502
|
|
377
|
-
res.end('[cer-app] OAuth user-info returned invalid JSON')
|
|
378
|
-
return
|
|
379
|
-
}
|
|
380
|
-
const user: AuthUser = normaliseProfile(provider, profile)
|
|
381
|
-
|
|
382
|
-
// Store the normalised user in the auth session cookie.
|
|
383
|
-
const authSession = useSession<AuthUser>({ name: config.sessionKey })
|
|
384
|
-
await authSession.set(user)
|
|
385
|
-
|
|
386
|
-
res.statusCode = 302
|
|
387
|
-
res.setHeader('Location', config.redirectAfterLogin)
|
|
388
|
-
res.end()
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* GET /api/auth/logout
|
|
393
|
-
*
|
|
394
|
-
* Clears the auth session cookie and redirects to `redirectAfterLogout`.
|
|
395
|
-
*/
|
|
396
|
-
export async function handleOAuthLogout(
|
|
397
|
-
_req: IncomingMessage,
|
|
398
|
-
res: ServerResponse,
|
|
399
|
-
config: ResolvedAuthConfig,
|
|
400
|
-
): Promise<void> {
|
|
401
|
-
const authSession = useSession({ name: config.sessionKey })
|
|
402
|
-
await authSession.clear()
|
|
403
|
-
|
|
404
|
-
res.statusCode = 302
|
|
405
|
-
res.setHeader('Location', config.redirectAfterLogout)
|
|
406
|
-
res.end()
|
|
407
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
export { handleOAuthInitiate, handleOAuthCallback, handleOAuthLogout } from './handler.js'
|
|
2
|
-
export type { AuthUser, ResolvedAuthConfig } from './handler.js'
|
|
3
|
-
export { OAUTH_PROVIDERS } from './providers.js'
|
|
4
|
-
export type { OAuthEndpoints } from './providers.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Type-safe helper for declaring an OAuth provider in `cer.config.ts`.
|
|
8
|
-
* Returns the config unchanged — exists purely for TypeScript inference.
|
|
9
|
-
*
|
|
10
|
-
* Built-in providers (`google`, `github`, `discord`) only require `clientId`
|
|
11
|
-
* and `clientSecret`. You can override any endpoint URL or supply a custom
|
|
12
|
-
* `scope` array. For a provider not listed in `OAUTH_PROVIDERS` you must
|
|
13
|
-
* supply all three endpoint URLs (`authorizationUrl`, `tokenUrl`,
|
|
14
|
-
* `userInfoUrl`).
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```ts
|
|
18
|
-
* // cer.config.ts
|
|
19
|
-
* import { defineConfig } from '@jasonshimmy/vite-plugin-cer-app'
|
|
20
|
-
*
|
|
21
|
-
* export default defineConfig({
|
|
22
|
-
* auth: {
|
|
23
|
-
* providers: {
|
|
24
|
-
* google: defineOAuthProvider({
|
|
25
|
-
* clientId: process.env.GOOGLE_CLIENT_ID!,
|
|
26
|
-
* clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
|
27
|
-
* }),
|
|
28
|
-
* github: defineOAuthProvider({
|
|
29
|
-
* clientId: process.env.GITHUB_CLIENT_ID!,
|
|
30
|
-
* clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
31
|
-
* scope: ['read:user', 'user:email', 'read:org'],
|
|
32
|
-
* }),
|
|
33
|
-
* },
|
|
34
|
-
* redirectAfterLogin: '/dashboard',
|
|
35
|
-
* redirectAfterLogout: '/',
|
|
36
|
-
* },
|
|
37
|
-
* })
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export function defineOAuthProvider<T extends {
|
|
41
|
-
clientId: string
|
|
42
|
-
clientSecret: string
|
|
43
|
-
scope?: string[]
|
|
44
|
-
authorizationUrl?: string
|
|
45
|
-
tokenUrl?: string
|
|
46
|
-
userInfoUrl?: string
|
|
47
|
-
}>(config: T): T {
|
|
48
|
-
return config
|
|
49
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Built-in OAuth provider endpoint definitions.
|
|
3
|
-
* Users may override any of these by setting `authorizationUrl`, `tokenUrl`,
|
|
4
|
-
* or `userInfoUrl` directly on the `OAuthProviderConfig`.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export interface OAuthEndpoints {
|
|
8
|
-
authorizationUrl: string
|
|
9
|
-
tokenUrl: string
|
|
10
|
-
userInfoUrl: string
|
|
11
|
-
defaultScopes: string[]
|
|
12
|
-
/** Some providers (e.g. GitHub) do not support PKCE. */
|
|
13
|
-
pkce: boolean
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const OAUTH_PROVIDERS: Record<string, OAuthEndpoints> = {
|
|
17
|
-
google: {
|
|
18
|
-
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
19
|
-
tokenUrl: 'https://oauth2.googleapis.com/token',
|
|
20
|
-
userInfoUrl: 'https://www.googleapis.com/oauth2/v2/userinfo',
|
|
21
|
-
defaultScopes: ['openid', 'email', 'profile'],
|
|
22
|
-
pkce: true,
|
|
23
|
-
},
|
|
24
|
-
github: {
|
|
25
|
-
authorizationUrl: 'https://github.com/login/oauth/authorize',
|
|
26
|
-
tokenUrl: 'https://github.com/login/oauth/access_token',
|
|
27
|
-
userInfoUrl: 'https://api.github.com/user',
|
|
28
|
-
defaultScopes: ['read:user', 'user:email'],
|
|
29
|
-
pkce: false, // GitHub does not support PKCE
|
|
30
|
-
},
|
|
31
|
-
discord: {
|
|
32
|
-
authorizationUrl: 'https://discord.com/api/oauth2/authorize',
|
|
33
|
-
tokenUrl: 'https://discord.com/api/oauth2/token',
|
|
34
|
-
userInfoUrl: 'https://discord.com/api/users/@me',
|
|
35
|
-
defaultScopes: ['identify', 'email'],
|
|
36
|
-
pkce: true,
|
|
37
|
-
},
|
|
38
|
-
}
|
package/src/types/api.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { IncomingMessage, ServerResponse } from 'node:http'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Augmented Node.js `IncomingMessage` passed to API route handlers.
|
|
5
|
-
* Route params and query string are pre-parsed; `body` is parsed from JSON automatically.
|
|
6
|
-
*/
|
|
7
|
-
export interface ApiRequest extends IncomingMessage {
|
|
8
|
-
params: Record<string, string>
|
|
9
|
-
query: Record<string, string>
|
|
10
|
-
body: unknown
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Augmented Node.js `ServerResponse` passed to API route handlers.
|
|
15
|
-
* Adds convenience methods for JSON responses and fluent status setting.
|
|
16
|
-
*/
|
|
17
|
-
export interface ApiResponse extends ServerResponse {
|
|
18
|
-
json(data: unknown): void
|
|
19
|
-
status(code: number): ApiResponse
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Handler function for a file-based API route (`app/api/**\/*.ts`).
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```ts
|
|
27
|
-
* // app/api/posts/[id].ts
|
|
28
|
-
* export const GET: ApiHandler = async (req, res) => {
|
|
29
|
-
* const post = await fetchPost(req.params.id)
|
|
30
|
-
* res.json(post)
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export type ApiHandler = (req: ApiRequest, res: ApiResponse) => Promise<void> | void
|
|
35
|
-
|
|
36
|
-
/** Combined request/response context passed to API utility functions and composables inside API handlers. */
|
|
37
|
-
export interface ApiContext {
|
|
38
|
-
req: ApiRequest
|
|
39
|
-
res: ApiResponse
|
|
40
|
-
}
|