@lupinum/better-convex-nuxt 0.8.0-beta.40
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/LICENSE +21 -0
- package/LICENSES/Apache-2.0.txt +201 -0
- package/README.md +151 -0
- package/THIRD_PARTY_NOTICES.md +38 -0
- package/dist/module.d.mts +55 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +309 -0
- package/dist/runtime/auth/auth-identity.d.ts +31 -0
- package/dist/runtime/auth/auth-identity.js +21 -0
- package/dist/runtime/auth/better-auth-browser-adapter.d.ts +33 -0
- package/dist/runtime/auth/better-auth-browser-adapter.js +215 -0
- package/dist/runtime/auth/client-engine-types.d.ts +4 -0
- package/dist/runtime/auth/client-engine-types.js +0 -0
- package/dist/runtime/auth/integrated-client.d.ts +25 -0
- package/dist/runtime/auth/integrated-client.js +132 -0
- package/dist/runtime/auth/operation-tracker.d.ts +7 -0
- package/dist/runtime/auth/operation-tracker.js +14 -0
- package/dist/runtime/auth/session-synchronization.d.ts +23 -0
- package/dist/runtime/auth/session-synchronization.js +156 -0
- package/dist/runtime/auth/token-fetcher.d.ts +66 -0
- package/dist/runtime/auth/token-fetcher.js +131 -0
- package/dist/runtime/auth/validate-auth-client-definition.d.ts +12 -0
- package/dist/runtime/auth/validate-auth-client-definition.js +47 -0
- package/dist/runtime/auth-client/convex-client-plugin.d.ts +31 -0
- package/dist/runtime/auth-client/convex-client-plugin.js +14 -0
- package/dist/runtime/auth-client/definition-types.d.ts +6 -0
- package/dist/runtime/auth-client/definition-types.js +0 -0
- package/dist/runtime/auth-client/empty-definition.d.ts +2 -0
- package/dist/runtime/auth-client/empty-definition.js +2 -0
- package/dist/runtime/auth-client/index.d.ts +71 -0
- package/dist/runtime/auth-client/index.js +3 -0
- package/dist/runtime/cli/auth-schema.d.ts +2 -0
- package/dist/runtime/cli/auth-schema.js +169 -0
- package/dist/runtime/cli/convex.d.ts +11 -0
- package/dist/runtime/cli/convex.js +274 -0
- package/dist/runtime/composables/useConvex.d.ts +4 -0
- package/dist/runtime/composables/useConvex.js +9 -0
- package/dist/runtime/composables/useConvexAction.d.ts +4 -0
- package/dist/runtime/composables/useConvexAction.js +18 -0
- package/dist/runtime/composables/useConvexAttachment.d.ts +9 -0
- package/dist/runtime/composables/useConvexAttachment.js +14 -0
- package/dist/runtime/composables/useConvexAuth.d.ts +10 -0
- package/dist/runtime/composables/useConvexAuth.js +37 -0
- package/dist/runtime/composables/useConvexConfig.d.ts +12 -0
- package/dist/runtime/composables/useConvexConfig.js +7 -0
- package/dist/runtime/composables/useConvexConnectionState.d.ts +33 -0
- package/dist/runtime/composables/useConvexConnectionState.js +24 -0
- package/dist/runtime/composables/useConvexFileUpload.d.ts +169 -0
- package/dist/runtime/composables/useConvexFileUpload.js +198 -0
- package/dist/runtime/composables/useConvexMutation.d.ts +13 -0
- package/dist/runtime/composables/useConvexMutation.js +24 -0
- package/dist/runtime/composables/useConvexPaginatedQuery.d.ts +13 -0
- package/dist/runtime/composables/useConvexPaginatedQuery.js +256 -0
- package/dist/runtime/composables/useConvexQuery.d.ts +19 -0
- package/dist/runtime/composables/useConvexQuery.js +308 -0
- package/dist/runtime/convex-auth/adapter/create-adapter.d.ts +33 -0
- package/dist/runtime/convex-auth/adapter/create-adapter.js +308 -0
- package/dist/runtime/convex-auth/adapter/define-functions.d.ts +160 -0
- package/dist/runtime/convex-auth/adapter/define-functions.js +497 -0
- package/dist/runtime/convex-auth/adapter/generate-schema.d.ts +16 -0
- package/dist/runtime/convex-auth/adapter/generate-schema.js +332 -0
- package/dist/runtime/convex-auth/adapter/metadata.d.ts +44 -0
- package/dist/runtime/convex-auth/adapter/metadata.js +91 -0
- package/dist/runtime/convex-auth/adapter/query.d.ts +32 -0
- package/dist/runtime/convex-auth/adapter/query.js +275 -0
- package/dist/runtime/convex-auth/adapter/relationships.d.ts +20 -0
- package/dist/runtime/convex-auth/adapter/relationships.js +128 -0
- package/dist/runtime/convex-auth/component/_generated/api.js +5 -0
- package/dist/runtime/convex-auth/component/_generated/component.d.ts +116 -0
- package/dist/runtime/convex-auth/component/_generated/component.js +0 -0
- package/dist/runtime/convex-auth/component/_generated/dataModel.js +0 -0
- package/dist/runtime/convex-auth/component/_generated/server.js +16 -0
- package/dist/runtime/convex-auth/component/adapter.d.ts +142 -0
- package/dist/runtime/convex-auth/component/adapter.js +16 -0
- package/dist/runtime/convex-auth/component/convex.config.d.ts +2 -0
- package/dist/runtime/convex-auth/component/convex.config.js +3 -0
- package/dist/runtime/convex-auth/component/schema.d.ts +799 -0
- package/dist/runtime/convex-auth/component/schema.js +180 -0
- package/dist/runtime/convex-auth/component/schemaMetadata.d.ts +2094 -0
- package/dist/runtime/convex-auth/component/schemaMetadata.js +2161 -0
- package/dist/runtime/convex-auth/context.d.ts +5 -0
- package/dist/runtime/convex-auth/context.js +8 -0
- package/dist/runtime/convex-auth/create-auth-component.d.ts +41 -0
- package/dist/runtime/convex-auth/create-auth-component.js +157 -0
- package/dist/runtime/convex-auth/index.d.ts +11 -0
- package/dist/runtime/convex-auth/index.js +7 -0
- package/dist/runtime/convex-auth/internal-session.d.ts +2 -0
- package/dist/runtime/convex-auth/internal-session.js +1 -0
- package/dist/runtime/convex-auth/jwks-rotation.d.ts +58 -0
- package/dist/runtime/convex-auth/jwks-rotation.js +163 -0
- package/dist/runtime/convex-auth/oauth-live-access.d.ts +17 -0
- package/dist/runtime/convex-auth/oauth-live-access.js +78 -0
- package/dist/runtime/convex-auth/oauth-provider-compat.d.ts +10 -0
- package/dist/runtime/convex-auth/oauth-provider-compat.js +170 -0
- package/dist/runtime/convex-auth/oauth-resource.d.ts +39 -0
- package/dist/runtime/convex-auth/oauth-resource.js +118 -0
- package/dist/runtime/convex-auth/oauth-security.d.ts +82 -0
- package/dist/runtime/convex-auth/oauth-security.js +454 -0
- package/dist/runtime/convex-auth/origin.d.ts +4 -0
- package/dist/runtime/convex-auth/origin.js +9 -0
- package/dist/runtime/convex-auth/plugin.d.ts +18 -0
- package/dist/runtime/convex-auth/plugin.js +605 -0
- package/dist/runtime/convex-auth/provider.d.ts +2 -0
- package/dist/runtime/convex-auth/provider.js +11 -0
- package/dist/runtime/convex-auth/test.d.ts +410 -0
- package/dist/runtime/convex-auth/test.js +9 -0
- package/dist/runtime/convex-auth/types.d.ts +18 -0
- package/dist/runtime/convex-auth/types.js +0 -0
- package/dist/runtime/convex-auth/user-projection.d.ts +106 -0
- package/dist/runtime/convex-auth/user-projection.js +128 -0
- package/dist/runtime/devtools/auth-proxy-registry.d.ts +4 -0
- package/dist/runtime/devtools/auth-proxy-registry.js +47 -0
- package/dist/runtime/devtools/bridge-setup.d.ts +21 -0
- package/dist/runtime/devtools/bridge-setup.js +165 -0
- package/dist/runtime/devtools/path-utils.d.ts +2 -0
- package/dist/runtime/devtools/path-utils.js +12 -0
- package/dist/runtime/devtools/server.d.ts +2 -0
- package/dist/runtime/devtools/server.js +108 -0
- package/dist/runtime/devtools/setup-client.d.ts +16 -0
- package/dist/runtime/devtools/setup-client.js +43 -0
- package/dist/runtime/devtools/sink.d.ts +18 -0
- package/dist/runtime/devtools/sink.js +110 -0
- package/dist/runtime/devtools/transport.d.ts +16 -0
- package/dist/runtime/devtools/transport.js +149 -0
- package/dist/runtime/devtools/types.d.ts +167 -0
- package/dist/runtime/devtools/types.js +1 -0
- package/dist/runtime/devtools/ui/dist/200.html +1 -0
- package/dist/runtime/devtools/ui/dist/404.html +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/C4MASuCh.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DJHkqtZq.js +3 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DWwrCltl.js +2 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DZ_UiYoH.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/_m9ujb-i.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/builds/latest.json +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/builds/meta/better-convex-nuxt-devtools.json +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/entry.DpFDKYZ5.css +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/error-404.DYUJo5xt.css +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/error-500.DQdoJJXg.css +1 -0
- package/dist/runtime/devtools/ui/dist/convex-logo.svg +5 -0
- package/dist/runtime/devtools/ui/dist/index.html +1 -0
- package/dist/runtime/errors/index.d.ts +7 -0
- package/dist/runtime/errors/index.js +5 -0
- package/dist/runtime/middleware/convex-auth.global.d.ts +2 -0
- package/dist/runtime/middleware/convex-auth.global.js +31 -0
- package/dist/runtime/plugin.auth.client.d.ts +3 -0
- package/dist/runtime/plugin.auth.client.js +217 -0
- package/dist/runtime/plugin.client.d.ts +3 -0
- package/dist/runtime/plugin.client.js +43 -0
- package/dist/runtime/plugin.server.d.ts +12 -0
- package/dist/runtime/plugin.server.js +98 -0
- package/dist/runtime/plugins/convex-call-error-payload.d.ts +14 -0
- package/dist/runtime/plugins/convex-call-error-payload.js +12 -0
- package/dist/runtime/runtime-context.d.ts +26 -0
- package/dist/runtime/runtime-context.js +48 -0
- package/dist/runtime/server/api/auth/[...].d.ts +10 -0
- package/dist/runtime/server/api/auth/[...].js +509 -0
- package/dist/runtime/server/api/auth/authorization-server-metadata.d.ts +2 -0
- package/dist/runtime/server/api/auth/authorization-server-metadata.js +6 -0
- package/dist/runtime/server/api/auth/body-size.d.ts +15 -0
- package/dist/runtime/server/api/auth/body-size.js +179 -0
- package/dist/runtime/server/api/auth/headers.d.ts +6 -0
- package/dist/runtime/server/api/auth/headers.js +98 -0
- package/dist/runtime/server/api/auth/jwks.d.ts +2 -0
- package/dist/runtime/server/api/auth/jwks.js +6 -0
- package/dist/runtime/server/api/auth/security.d.ts +14 -0
- package/dist/runtime/server/api/auth/security.js +85 -0
- package/dist/runtime/server/api/release-fingerprint.d.ts +2 -0
- package/dist/runtime/server/api/release-fingerprint.js +36 -0
- package/dist/runtime/server/index.d.ts +1 -0
- package/dist/runtime/server/index.js +3 -0
- package/dist/runtime/server/plugins/runtime-config.d.ts +7 -0
- package/dist/runtime/server/plugins/runtime-config.js +7 -0
- package/dist/runtime/server/utils/auth-snapshot.d.ts +26 -0
- package/dist/runtime/server/utils/auth-snapshot.js +165 -0
- package/dist/runtime/server/utils/http.d.ts +16 -0
- package/dist/runtime/server/utils/http.js +133 -0
- package/dist/runtime/server/utils/server-convex-caller.d.ts +31 -0
- package/dist/runtime/server/utils/server-convex-caller.js +151 -0
- package/dist/runtime/server/utils/server-convex-options.d.ts +83 -0
- package/dist/runtime/server/utils/server-convex-options.js +69 -0
- package/dist/runtime/server/utils/signed-client-ip.d.ts +6 -0
- package/dist/runtime/server/utils/signed-client-ip.js +29 -0
- package/dist/runtime/server/utils/ssr-auth-headers.d.ts +26 -0
- package/dist/runtime/server/utils/ssr-auth-headers.js +49 -0
- package/dist/runtime/server/utils/token-exchange.d.ts +27 -0
- package/dist/runtime/server/utils/token-exchange.js +96 -0
- package/dist/runtime/shared/auth-cookie.d.ts +4 -0
- package/dist/runtime/shared/auth-cookie.js +25 -0
- package/dist/runtime/shared/auth-origin.d.ts +15 -0
- package/dist/runtime/shared/auth-origin.js +42 -0
- package/dist/runtime/shared/bounded-stream.d.ts +2 -0
- package/dist/runtime/shared/bounded-stream.js +50 -0
- package/dist/runtime/shared/client-ip.d.ts +21 -0
- package/dist/runtime/shared/client-ip.js +123 -0
- package/dist/runtime/shared/release-fingerprint.d.ts +5 -0
- package/dist/runtime/shared/release-fingerprint.js +17 -0
- package/dist/runtime/types.d.ts +19 -0
- package/dist/runtime/utils/auth-config.d.ts +24 -0
- package/dist/runtime/utils/auth-config.js +45 -0
- package/dist/runtime/utils/auth-contract.d.ts +22 -0
- package/dist/runtime/utils/auth-contract.js +0 -0
- package/dist/runtime/utils/auth-errors.d.ts +5 -0
- package/dist/runtime/utils/auth-errors.js +22 -0
- package/dist/runtime/utils/auth-identity-state.d.ts +4 -0
- package/dist/runtime/utils/auth-identity-state.js +8 -0
- package/dist/runtime/utils/auth-pending-state.d.ts +13 -0
- package/dist/runtime/utils/auth-pending-state.js +4 -0
- package/dist/runtime/utils/auth-pending.d.ts +10 -0
- package/dist/runtime/utils/auth-pending.js +30 -0
- package/dist/runtime/utils/auth-route-protection.d.ts +16 -0
- package/dist/runtime/utils/auth-route-protection.js +58 -0
- package/dist/runtime/utils/auth-status.d.ts +47 -0
- package/dist/runtime/utils/auth-status.js +8 -0
- package/dist/runtime/utils/bounded-convex-fetch.d.ts +18 -0
- package/dist/runtime/utils/bounded-convex-fetch.js +152 -0
- package/dist/runtime/utils/callable-devtools.d.ts +17 -0
- package/dist/runtime/utils/callable-devtools.js +49 -0
- package/dist/runtime/utils/callable-observer.d.ts +2 -0
- package/dist/runtime/utils/callable-observer.js +1 -0
- package/dist/runtime/utils/composable-scope.d.ts +2 -0
- package/dist/runtime/utils/composable-scope.js +8 -0
- package/dist/runtime/utils/config-defaults.d.ts +8 -0
- package/dist/runtime/utils/config-defaults.js +8 -0
- package/dist/runtime/utils/convex-cache.d.ts +68 -0
- package/dist/runtime/utils/convex-cache.js +47 -0
- package/dist/runtime/utils/convex-config.d.ts +16 -0
- package/dist/runtime/utils/convex-config.js +50 -0
- package/dist/runtime/utils/convex-shared.d.ts +67 -0
- package/dist/runtime/utils/convex-shared.js +134 -0
- package/dist/runtime/utils/identity-changed-error.d.ts +4 -0
- package/dist/runtime/utils/identity-changed-error.js +12 -0
- package/dist/runtime/utils/identity-key.d.ts +19 -0
- package/dist/runtime/utils/identity-key.js +10 -0
- package/dist/runtime/utils/integrated-auth-client.d.ts +5 -0
- package/dist/runtime/utils/integrated-auth-client.js +0 -0
- package/dist/runtime/utils/logger.d.ts +42 -0
- package/dist/runtime/utils/logger.js +190 -0
- package/dist/runtime/utils/mime-type.d.ts +33 -0
- package/dist/runtime/utils/mime-type.js +10 -0
- package/dist/runtime/utils/query-execution-gate.d.ts +47 -0
- package/dist/runtime/utils/query-execution-gate.js +63 -0
- package/dist/runtime/utils/query-execution.d.ts +8 -0
- package/dist/runtime/utils/query-execution.js +19 -0
- package/dist/runtime/utils/query-foundation.d.ts +20 -0
- package/dist/runtime/utils/query-foundation.js +39 -0
- package/dist/runtime/utils/query-state.d.ts +12 -0
- package/dist/runtime/utils/query-state.js +12 -0
- package/dist/runtime/utils/reactive-args.d.ts +5 -0
- package/dist/runtime/utils/reactive-args.js +42 -0
- package/dist/runtime/utils/runtime-config-normalize.d.ts +22 -0
- package/dist/runtime/utils/runtime-config-normalize.js +28 -0
- package/dist/runtime/utils/runtime-config.d.ts +4 -0
- package/dist/runtime/utils/runtime-config.js +8 -0
- package/dist/runtime/utils/sanitize-diagnostic.d.ts +6 -0
- package/dist/runtime/utils/sanitize-diagnostic.js +81 -0
- package/dist/runtime/utils/shared-helpers.d.ts +46 -0
- package/dist/runtime/utils/shared-helpers.js +139 -0
- package/dist/runtime/utils/site-url.d.ts +4 -0
- package/dist/runtime/utils/site-url.js +15 -0
- package/dist/runtime/utils/ssr-pagination-state.d.ts +3 -0
- package/dist/runtime/utils/ssr-pagination-state.js +3 -0
- package/dist/runtime/utils/types.d.ts +29 -0
- package/dist/runtime/utils/types.js +0 -0
- package/dist/runtime/utils/upload-core.d.ts +16 -0
- package/dist/runtime/utils/upload-core.js +116 -0
- package/dist/types.d.mts +21 -0
- package/package.json +253 -0
- package/security/upstream-convex-better-auth.json +477 -0
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { useLogger, defineNuxtModule, createResolver, addTemplate, addServerPlugin, addServerHandler, addPlugin, addTypeTemplate, addRouteMiddleware, addImports, addServerImports, resolvePath } from '@nuxt/kit';
|
|
3
|
+
import { defu } from 'defu';
|
|
4
|
+
import { getPackedRuntimeFingerprint } from '../dist/runtime/shared/release-fingerprint.js';
|
|
5
|
+
import { normalizeConvexAuthConfig, isConvexAuthEnabled } from '../dist/runtime/utils/auth-config.js';
|
|
6
|
+
import { CONVEX_MODULE_DEFAULTS } from '../dist/runtime/utils/config-defaults.js';
|
|
7
|
+
import { resolveConvexSiteUrl, getSiteUrlResolutionHint } from '../dist/runtime/utils/convex-config.js';
|
|
8
|
+
import { normalizeConvexDeploymentUrl, normalizeConvexSiteUrl } from '../dist/runtime/utils/site-url.js';
|
|
9
|
+
|
|
10
|
+
function registerConvexAliases(options) {
|
|
11
|
+
const { nuxt, resolver, convexApiAlias } = options;
|
|
12
|
+
const convexServerAlias = resolver.resolve("./runtime/server/index");
|
|
13
|
+
nuxt.options.alias["#convex/api"] = convexApiAlias;
|
|
14
|
+
nuxt.options.alias["#convex/server"] = convexServerAlias;
|
|
15
|
+
nuxt.hook("prepare:types", (opts) => {
|
|
16
|
+
opts.references.push({
|
|
17
|
+
path: resolver.resolve(nuxt.options.buildDir, "types/better-convex-nuxt.d.ts")
|
|
18
|
+
});
|
|
19
|
+
opts.tsConfig.compilerOptions ??= {};
|
|
20
|
+
opts.tsConfig.compilerOptions.paths ??= {};
|
|
21
|
+
opts.tsConfig.compilerOptions.paths["#convex/api"] = [convexApiAlias];
|
|
22
|
+
opts.tsConfig.compilerOptions.paths["#convex/server"] = [convexServerAlias];
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const composableAutoImports = [
|
|
27
|
+
{ name: "useConvex", from: "./runtime/composables/useConvex" },
|
|
28
|
+
{
|
|
29
|
+
name: "useConvexAttachment",
|
|
30
|
+
from: "./runtime/composables/useConvexAttachment"
|
|
31
|
+
},
|
|
32
|
+
{ name: "useConvexConfig", from: "./runtime/composables/useConvexConfig" },
|
|
33
|
+
{
|
|
34
|
+
name: "useConvexMutation",
|
|
35
|
+
from: "./runtime/composables/useConvexMutation"
|
|
36
|
+
},
|
|
37
|
+
{ name: "useConvexAction", from: "./runtime/composables/useConvexAction" },
|
|
38
|
+
{ name: "useConvexQuery", from: "./runtime/composables/useConvexQuery" },
|
|
39
|
+
{
|
|
40
|
+
name: "useConvexPaginatedQuery",
|
|
41
|
+
from: "./runtime/composables/useConvexPaginatedQuery"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: "useConvexConnectionState",
|
|
45
|
+
from: "./runtime/composables/useConvexConnectionState"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "useConvexFileUpload",
|
|
49
|
+
from: "./runtime/composables/useConvexFileUpload"
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
const authAutoImports = [
|
|
53
|
+
{ name: "useConvexAuth", from: "./runtime/composables/useConvexAuth" }
|
|
54
|
+
];
|
|
55
|
+
const serverAutoImports = [
|
|
56
|
+
{ name: "serverConvex", from: "./runtime/server/utils/server-convex-caller" }
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
function getMissingConvexApiTemplateContents() {
|
|
60
|
+
return `
|
|
61
|
+
type MissingConvexGeneratedApi = {
|
|
62
|
+
/**
|
|
63
|
+
* The generated Convex API was not found.
|
|
64
|
+
* Run the file-bound Convex dev command or \`pnpm exec better-convex-nuxt-convex codegen\` to create \`convex/_generated/api\`.
|
|
65
|
+
*/
|
|
66
|
+
readonly __betterConvexNuxtError: 'Missing generated Convex API. Run the file-bound Convex dev command or pnpm exec better-convex-nuxt-convex codegen.'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function createMissingConvexApiProxy(path: string[]): MissingConvexGeneratedApi {
|
|
70
|
+
return new Proxy({} as MissingConvexGeneratedApi, {
|
|
71
|
+
get(_target, prop) {
|
|
72
|
+
if (typeof prop === 'symbol') return undefined
|
|
73
|
+
if (prop === '__betterConvexNuxtError') {
|
|
74
|
+
return 'Missing generated Convex API. Run the file-bound Convex dev command or pnpm exec better-convex-nuxt-convex codegen.'
|
|
75
|
+
}
|
|
76
|
+
const accessPath = [...path, String(prop)].join('.')
|
|
77
|
+
throw new Error(
|
|
78
|
+
'[better-convex-nuxt] #convex/api points to a placeholder because convex/_generated/api was not found. ' +
|
|
79
|
+
'Run the file-bound Convex dev command or \`pnpm exec better-convex-nuxt-convex codegen\` to generate your Convex API. ' +
|
|
80
|
+
'Attempted to access ' + accessPath + '.',
|
|
81
|
+
)
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const api = createMissingConvexApiProxy([])
|
|
87
|
+
export const internal = createMissingConvexApiProxy(['internal'])
|
|
88
|
+
export const components = createMissingConvexApiProxy(['components'])
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
function getTypeAugmentationTemplateContents(authPageMetaTypeImport) {
|
|
92
|
+
const authPageMetaImportSpecifier = JSON.stringify(authPageMetaTypeImport);
|
|
93
|
+
return `
|
|
94
|
+
import type { ConvexAuthPageMeta } from ${authPageMetaImportSpecifier}
|
|
95
|
+
|
|
96
|
+
// Consumers use the stable \`useConvex()\` handle and auth composables instead
|
|
97
|
+
// of raw replaceable clients. Only route-protection page metadata needs a
|
|
98
|
+
// generated type augmentation.
|
|
99
|
+
declare module '#app' {
|
|
100
|
+
interface PageMeta {
|
|
101
|
+
/**
|
|
102
|
+
* Opt-in route protection powered by better-convex-nuxt.
|
|
103
|
+
* true = require auth (default redirect), object = custom redirect.
|
|
104
|
+
*/
|
|
105
|
+
convexAuth?: ConvexAuthPageMeta
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export {}
|
|
110
|
+
`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const releaseRuntimeFingerprint = getPackedRuntimeFingerprint();
|
|
114
|
+
const logger = useLogger("@lupinum/better-convex-nuxt");
|
|
115
|
+
function hasGeneratedConvexApi(aliasPath) {
|
|
116
|
+
return existsSync(aliasPath) || existsSync(`${aliasPath}.ts`) || existsSync(`${aliasPath}.js`) || existsSync(`${aliasPath}.d.ts`);
|
|
117
|
+
}
|
|
118
|
+
function resolveModuleImports(resolver, imports) {
|
|
119
|
+
return imports.map((entry) => ({
|
|
120
|
+
name: entry.name,
|
|
121
|
+
from: resolver.resolve(entry.from)
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
const AUTH_CLIENT_CONVENTION_FILENAME = "convex-auth.ts";
|
|
125
|
+
async function resolveAuthClientDefinitionPath(authOptions, nuxt, resolver) {
|
|
126
|
+
const explicit = typeof authOptions.client === "string" ? authOptions.client.trim() : "";
|
|
127
|
+
if (explicit) {
|
|
128
|
+
const resolved = await resolvePath(explicit, {
|
|
129
|
+
cwd: nuxt.options.rootDir,
|
|
130
|
+
alias: nuxt.options.alias
|
|
131
|
+
});
|
|
132
|
+
if (!existsSync(resolved)) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`[better-convex-nuxt] auth.client "${explicit}" could not be resolved to an existing file (resolved to "${resolved}"). Provide a path or alias to a module that default-exports a defineConvexAuthClient(...) definition.`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return resolved;
|
|
138
|
+
}
|
|
139
|
+
const conventionPath = resolver.resolve(nuxt.options.srcDir, AUTH_CLIENT_CONVENTION_FILENAME);
|
|
140
|
+
if (existsSync(conventionPath)) {
|
|
141
|
+
return conventionPath;
|
|
142
|
+
}
|
|
143
|
+
return resolver.resolve("./runtime/auth-client/empty-definition");
|
|
144
|
+
}
|
|
145
|
+
const module$1 = defineNuxtModule({
|
|
146
|
+
meta: {
|
|
147
|
+
name: "@lupinum/better-convex-nuxt",
|
|
148
|
+
configKey: "convex",
|
|
149
|
+
compatibility: {
|
|
150
|
+
nuxt: "4.5.1"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
defaults: {
|
|
154
|
+
url: process.env.NUXT_PUBLIC_CONVEX_URL || process.env.CONVEX_URL,
|
|
155
|
+
siteUrl: process.env.NUXT_PUBLIC_CONVEX_SITE_URL || process.env.CONVEX_SITE_URL,
|
|
156
|
+
// Auth is intentionally omitted: an ordinary Convex application has no
|
|
157
|
+
// Better Auth build graph unless it opts in with an auth object.
|
|
158
|
+
logging: CONVEX_MODULE_DEFAULTS.logging
|
|
159
|
+
},
|
|
160
|
+
async setup(options, nuxt) {
|
|
161
|
+
const resolver = createResolver(import.meta.url);
|
|
162
|
+
const generatedConvexApiAlias = resolver.resolve(nuxt.options.rootDir, "convex/_generated/api");
|
|
163
|
+
const missingConvexApiTemplate = addTemplate({
|
|
164
|
+
filename: "@lupinum/better-convex-nuxt/convex-api-missing.ts",
|
|
165
|
+
write: true,
|
|
166
|
+
getContents: getMissingConvexApiTemplateContents
|
|
167
|
+
});
|
|
168
|
+
const convexApiAlias = hasGeneratedConvexApi(generatedConvexApiAlias) ? generatedConvexApiAlias : missingConvexApiTemplate.dst;
|
|
169
|
+
const resolvedUrl = options.url ? normalizeConvexDeploymentUrl(options.url) : void 0;
|
|
170
|
+
const siteUrlResolution = resolveConvexSiteUrl({
|
|
171
|
+
url: resolvedUrl,
|
|
172
|
+
siteUrl: options.siteUrl
|
|
173
|
+
});
|
|
174
|
+
const resolvedSiteUrl = siteUrlResolution.siteUrl;
|
|
175
|
+
if (resolvedSiteUrl) normalizeConvexSiteUrl(resolvedSiteUrl);
|
|
176
|
+
const normalizedAuthConfig = normalizeConvexAuthConfig(options.auth);
|
|
177
|
+
const isAuthEnabled = isConvexAuthEnabled(normalizedAuthConfig);
|
|
178
|
+
if (isAuthEnabled && !resolvedSiteUrl) {
|
|
179
|
+
logger.warn(
|
|
180
|
+
`Authentication is enabled but no usable siteUrl was resolved. ${getSiteUrlResolutionHint(resolvedUrl)}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
const convexConfig = {
|
|
184
|
+
...defu(nuxt.options.runtimeConfig.public.convex, {
|
|
185
|
+
url: resolvedUrl || "",
|
|
186
|
+
siteUrl: resolvedSiteUrl || "",
|
|
187
|
+
logging: options.logging ?? CONVEX_MODULE_DEFAULTS.logging
|
|
188
|
+
}),
|
|
189
|
+
// Auth is build policy, not a deploy-time/public runtime override.
|
|
190
|
+
auth: normalizedAuthConfig
|
|
191
|
+
};
|
|
192
|
+
nuxt.options.runtimeConfig.public.convex = convexConfig;
|
|
193
|
+
registerConvexAliases({ nuxt, resolver, convexApiAlias });
|
|
194
|
+
addServerPlugin(resolver.resolve("./runtime/server/plugins/runtime-config"));
|
|
195
|
+
if (releaseRuntimeFingerprint) {
|
|
196
|
+
addServerHandler({
|
|
197
|
+
route: "/api/_better-convex-nuxt/release-fingerprint",
|
|
198
|
+
handler: resolver.resolve("./runtime/server/api/release-fingerprint")
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (!isAuthEnabled) addPlugin(resolver.resolve("./runtime/plugin.client"));
|
|
202
|
+
addPlugin({
|
|
203
|
+
src: resolver.resolve("./runtime/plugins/convex-call-error-payload"),
|
|
204
|
+
mode: "all",
|
|
205
|
+
order: -50
|
|
206
|
+
});
|
|
207
|
+
if (isAuthEnabled) {
|
|
208
|
+
const authClientDefinitionPath = await resolveAuthClientDefinitionPath(
|
|
209
|
+
options.auth,
|
|
210
|
+
nuxt,
|
|
211
|
+
resolver
|
|
212
|
+
);
|
|
213
|
+
const authClientTemplate = addTemplate({
|
|
214
|
+
filename: "@lupinum/better-convex-nuxt/auth-client.mjs",
|
|
215
|
+
write: true,
|
|
216
|
+
getContents: () => `export { default } from ${JSON.stringify(authClientDefinitionPath)}
|
|
217
|
+
`
|
|
218
|
+
});
|
|
219
|
+
nuxt.options.alias["#convex/auth-client"] = authClientTemplate.dst;
|
|
220
|
+
addTypeTemplate({
|
|
221
|
+
filename: "types/better-convex-nuxt-auth-client.d.ts",
|
|
222
|
+
getContents: () => [
|
|
223
|
+
`import type definition from ${JSON.stringify(authClientDefinitionPath)}`,
|
|
224
|
+
``,
|
|
225
|
+
`declare module '@lupinum/better-convex-nuxt/auth-client' {`,
|
|
226
|
+
` interface ConvexAuthClientRegistry {`,
|
|
227
|
+
` definition: typeof definition`,
|
|
228
|
+
` }`,
|
|
229
|
+
`}`,
|
|
230
|
+
``
|
|
231
|
+
].join("\n")
|
|
232
|
+
});
|
|
233
|
+
nuxt.hook("prepare:types", (opts) => {
|
|
234
|
+
opts.tsConfig.compilerOptions ??= {};
|
|
235
|
+
opts.tsConfig.compilerOptions.paths ??= {};
|
|
236
|
+
opts.tsConfig.compilerOptions.paths["#convex/auth-client"] = [authClientTemplate.dst];
|
|
237
|
+
});
|
|
238
|
+
addPlugin({
|
|
239
|
+
src: resolver.resolve("./runtime/plugin.server"),
|
|
240
|
+
mode: "server"
|
|
241
|
+
});
|
|
242
|
+
addPlugin({
|
|
243
|
+
src: resolver.resolve("./runtime/plugin.auth.client"),
|
|
244
|
+
mode: "client"
|
|
245
|
+
});
|
|
246
|
+
addRouteMiddleware({
|
|
247
|
+
name: "convex-auth",
|
|
248
|
+
path: resolver.resolve("./runtime/middleware/convex-auth.global"),
|
|
249
|
+
global: true
|
|
250
|
+
});
|
|
251
|
+
addServerHandler({
|
|
252
|
+
route: "/api/auth",
|
|
253
|
+
handler: resolver.resolve("./runtime/server/api/auth/[...]")
|
|
254
|
+
});
|
|
255
|
+
addServerHandler({
|
|
256
|
+
route: "/api/auth/jwks",
|
|
257
|
+
handler: resolver.resolve("./runtime/server/api/auth/jwks")
|
|
258
|
+
});
|
|
259
|
+
addServerHandler({
|
|
260
|
+
route: "/api/auth/**",
|
|
261
|
+
handler: resolver.resolve("./runtime/server/api/auth/[...]")
|
|
262
|
+
});
|
|
263
|
+
addServerHandler({
|
|
264
|
+
route: "/.well-known/oauth-authorization-server/api/auth",
|
|
265
|
+
handler: resolver.resolve("./runtime/server/api/auth/authorization-server-metadata")
|
|
266
|
+
});
|
|
267
|
+
addTemplate({
|
|
268
|
+
filename: "types/better-convex-nuxt-auth.d.ts",
|
|
269
|
+
getContents: () => getTypeAugmentationTemplateContents(
|
|
270
|
+
resolver.resolve("./runtime/utils/auth-route-protection")
|
|
271
|
+
)
|
|
272
|
+
});
|
|
273
|
+
addImports(resolveModuleImports(resolver, authAutoImports));
|
|
274
|
+
}
|
|
275
|
+
addImports(resolveModuleImports(resolver, composableAutoImports));
|
|
276
|
+
addServerImports(resolveModuleImports(resolver, serverAutoImports));
|
|
277
|
+
if (nuxt.options.dev) {
|
|
278
|
+
setupDevTools(nuxt, resolver);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
function setupDevTools(nuxt, resolver) {
|
|
283
|
+
const devtoolsOutputPath = resolver.resolve("./runtime/devtools/ui/dist");
|
|
284
|
+
nuxt.options.runtimeConfig.convexDevtoolsPath = devtoolsOutputPath;
|
|
285
|
+
nuxt.hook("devtools:customTabs", (tabs) => {
|
|
286
|
+
tabs.push({
|
|
287
|
+
name: "convex",
|
|
288
|
+
title: "Convex",
|
|
289
|
+
icon: "/__convex_devtools__/convex-logo.svg",
|
|
290
|
+
category: "app",
|
|
291
|
+
view: {
|
|
292
|
+
type: "iframe",
|
|
293
|
+
src: "/__convex_devtools__",
|
|
294
|
+
persistent: true
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
addServerHandler({
|
|
299
|
+
route: "/__convex_devtools__",
|
|
300
|
+
handler: resolver.resolve("./runtime/devtools/server")
|
|
301
|
+
});
|
|
302
|
+
addServerHandler({
|
|
303
|
+
route: "/__convex_devtools__/**",
|
|
304
|
+
handler: resolver.resolve("./runtime/devtools/server")
|
|
305
|
+
});
|
|
306
|
+
logger.info("Nuxt DevTools integration enabled");
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export { module$1 as default };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ConvexIdentityKey } from '../utils/identity-key.js';
|
|
2
|
+
import type { ConvexUser } from '../utils/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Identity as ONE discriminated value (architecture invariant). Never independent booleans
|
|
5
|
+
* for token/user/authenticated/loading, and never a manufactured empty-string
|
|
6
|
+
* user field. `key` is always the stable Better Auth `user.id`.
|
|
7
|
+
*/
|
|
8
|
+
export type AuthIdentity = {
|
|
9
|
+
status: 'loading';
|
|
10
|
+
} | {
|
|
11
|
+
status: 'anonymous';
|
|
12
|
+
} | {
|
|
13
|
+
status: 'authenticated';
|
|
14
|
+
token: string;
|
|
15
|
+
user: ConvexUser;
|
|
16
|
+
key: `user:${string}`;
|
|
17
|
+
};
|
|
18
|
+
export declare const LOADING_IDENTITY: AuthIdentity;
|
|
19
|
+
export declare const ANONYMOUS_IDENTITY: AuthIdentity;
|
|
20
|
+
/**
|
|
21
|
+
* Build an authenticated identity from a confirmed token + user, or fall back to
|
|
22
|
+
* anonymous when the user has no stable id. A token without a resolved user is
|
|
23
|
+
* not a settled identity. Pure.
|
|
24
|
+
*/
|
|
25
|
+
export declare function toAuthenticatedIdentity(token: string, user: ConvexUser): AuthIdentity;
|
|
26
|
+
/** The stable identity key for any identity value. Settled values only. */
|
|
27
|
+
export declare function identityKeyOf(identity: AuthIdentity): ConvexIdentityKey;
|
|
28
|
+
/** The published token, or null for any non-authenticated identity. */
|
|
29
|
+
export declare function identityToken(identity: AuthIdentity): string | null;
|
|
30
|
+
/** The published user, or null for any non-authenticated identity. */
|
|
31
|
+
export declare function identityUser(identity: AuthIdentity): ConvexUser | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getConvexIdentityKey } from "../utils/identity-key.js";
|
|
2
|
+
export const LOADING_IDENTITY = { status: "loading" };
|
|
3
|
+
export const ANONYMOUS_IDENTITY = { status: "anonymous" };
|
|
4
|
+
export function toAuthenticatedIdentity(token, user) {
|
|
5
|
+
try {
|
|
6
|
+
const key = getConvexIdentityKey(user);
|
|
7
|
+
if (key === "anonymous") return ANONYMOUS_IDENTITY;
|
|
8
|
+
return { status: "authenticated", token, user, key };
|
|
9
|
+
} catch {
|
|
10
|
+
return ANONYMOUS_IDENTITY;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function identityKeyOf(identity) {
|
|
14
|
+
return identity.status === "authenticated" ? identity.key : "anonymous";
|
|
15
|
+
}
|
|
16
|
+
export function identityToken(identity) {
|
|
17
|
+
return identity.status === "authenticated" ? identity.token : null;
|
|
18
|
+
}
|
|
19
|
+
export function identityUser(identity) {
|
|
20
|
+
return identity.status === "authenticated" ? identity.user : null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { BetterConvexAuthAdapter } from '@lupinum/better-convex-vue';
|
|
2
|
+
import { type Ref } from 'vue';
|
|
3
|
+
import type { ConvexUser } from '../utils/types.js';
|
|
4
|
+
import { type ConvexTokenSource } from './token-fetcher.js';
|
|
5
|
+
interface BetterAuthSessionState {
|
|
6
|
+
data?: {
|
|
7
|
+
session?: {
|
|
8
|
+
token?: unknown;
|
|
9
|
+
};
|
|
10
|
+
user?: {
|
|
11
|
+
id?: unknown;
|
|
12
|
+
};
|
|
13
|
+
} | null;
|
|
14
|
+
isPending?: boolean;
|
|
15
|
+
isRefetching?: boolean;
|
|
16
|
+
error?: unknown;
|
|
17
|
+
refetch?: () => Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
interface BetterAuthBrowserSource extends ConvexTokenSource {
|
|
20
|
+
useSession(): Readonly<Ref<BetterAuthSessionState>>;
|
|
21
|
+
}
|
|
22
|
+
/** Private first-party adapter proof. It becomes a Nuxt adapter only after the atomic package cut. */
|
|
23
|
+
export declare function createBetterAuthBrowserAdapter(source: BetterAuthBrowserSource, callbacks?: {
|
|
24
|
+
authenticated(token: string, user: ConvexUser): void;
|
|
25
|
+
anonymous(error: string | null): void;
|
|
26
|
+
sessionChanged?(sessionToken: string | null, error: string | null, sessionGeneration: number): void;
|
|
27
|
+
}, options?: {
|
|
28
|
+
initialIdentityKey?: string;
|
|
29
|
+
}): BetterConvexAuthAdapter & {
|
|
30
|
+
failClosed(message: string): void;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { watch } from "vue";
|
|
2
|
+
import { fetchConvexToken, isTokenUsable } from "./token-fetcher.js";
|
|
3
|
+
const UNAVAILABLE = "Authentication is temporarily unavailable";
|
|
4
|
+
const SESSION_SETTLEMENT_TIMEOUT_MS = 5e3;
|
|
5
|
+
function isUnauthorized(error) {
|
|
6
|
+
return Boolean(
|
|
7
|
+
error && typeof error === "object" && "status" in error && error.status === 401
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
export function createBetterAuthBrowserAdapter(source, callbacks = { authenticated: () => {
|
|
11
|
+
}, anonymous: () => {
|
|
12
|
+
} }, options = {}) {
|
|
13
|
+
const session = source.useSession();
|
|
14
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
15
|
+
const cancelSessionSettlement = /* @__PURE__ */ new Set();
|
|
16
|
+
let disposed = false;
|
|
17
|
+
let sessionGeneration = 0;
|
|
18
|
+
let observedSessionToken;
|
|
19
|
+
let observedIdentityKey = options.initialIdentityKey;
|
|
20
|
+
let cachedToken = null;
|
|
21
|
+
let snapshot = options.initialIdentityKey ? {
|
|
22
|
+
status: "authenticated",
|
|
23
|
+
identityKey: options.initialIdentityKey,
|
|
24
|
+
sessionGeneration,
|
|
25
|
+
error: null
|
|
26
|
+
} : {
|
|
27
|
+
status: "loading",
|
|
28
|
+
identityKey: null,
|
|
29
|
+
sessionGeneration,
|
|
30
|
+
error: null
|
|
31
|
+
};
|
|
32
|
+
const notify = () => {
|
|
33
|
+
for (const listener of [...listeners]) {
|
|
34
|
+
try {
|
|
35
|
+
listener();
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const publishFromSession = (value) => {
|
|
41
|
+
const rawSessionToken = value.data?.session?.token;
|
|
42
|
+
const sessionToken = typeof rawSessionToken === "string" && rawSessionToken.length > 0 ? rawSessionToken : null;
|
|
43
|
+
const rawUserId = value.data?.user?.id;
|
|
44
|
+
const userId = typeof rawUserId === "string" && rawUserId.length > 0 ? rawUserId : null;
|
|
45
|
+
const key = userId;
|
|
46
|
+
if (value.isPending === true) {
|
|
47
|
+
if (observedSessionToken === void 0 && observedIdentityKey !== void 0 && snapshot.status === "authenticated") {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
snapshot = {
|
|
51
|
+
status: "loading",
|
|
52
|
+
identityKey: null,
|
|
53
|
+
sessionGeneration,
|
|
54
|
+
error: null
|
|
55
|
+
};
|
|
56
|
+
notify();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const malformed = value.data?.session !== void 0 && sessionToken === null || sessionToken !== null && key === null;
|
|
60
|
+
const retainsEstablishedSession = Boolean(value.error) && !isUnauthorized(value.error) && snapshot.status === "authenticated" && observedSessionToken === sessionToken && observedIdentityKey === key;
|
|
61
|
+
if (retainsEstablishedSession) return;
|
|
62
|
+
if (value.error || malformed) {
|
|
63
|
+
cachedToken = null;
|
|
64
|
+
sessionGeneration += 1;
|
|
65
|
+
observedSessionToken = null;
|
|
66
|
+
observedIdentityKey = null;
|
|
67
|
+
snapshot = {
|
|
68
|
+
status: "error",
|
|
69
|
+
identityKey: null,
|
|
70
|
+
sessionGeneration,
|
|
71
|
+
error: new Error(UNAVAILABLE)
|
|
72
|
+
};
|
|
73
|
+
callbacks.anonymous(UNAVAILABLE);
|
|
74
|
+
callbacks.sessionChanged?.(null, UNAVAILABLE, sessionGeneration);
|
|
75
|
+
notify();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const establishesMatchingProvisionalIdentity = observedSessionToken === void 0 && observedIdentityKey !== void 0 && observedIdentityKey === key;
|
|
79
|
+
const changed = !establishesMatchingProvisionalIdentity && (observedSessionToken !== sessionToken || observedIdentityKey !== key);
|
|
80
|
+
if (changed) {
|
|
81
|
+
sessionGeneration += 1;
|
|
82
|
+
cachedToken = null;
|
|
83
|
+
}
|
|
84
|
+
observedSessionToken = sessionToken;
|
|
85
|
+
observedIdentityKey = key;
|
|
86
|
+
snapshot = sessionToken && key ? {
|
|
87
|
+
status: "authenticated",
|
|
88
|
+
identityKey: key,
|
|
89
|
+
sessionGeneration,
|
|
90
|
+
error: null
|
|
91
|
+
} : {
|
|
92
|
+
status: "anonymous",
|
|
93
|
+
identityKey: null,
|
|
94
|
+
sessionGeneration,
|
|
95
|
+
error: null
|
|
96
|
+
};
|
|
97
|
+
if (!sessionToken) callbacks.anonymous(null);
|
|
98
|
+
callbacks.sessionChanged?.(sessionToken, null, sessionGeneration);
|
|
99
|
+
notify();
|
|
100
|
+
};
|
|
101
|
+
const stop = watch(
|
|
102
|
+
[
|
|
103
|
+
() => session.value.isPending === true,
|
|
104
|
+
() => session.value.data,
|
|
105
|
+
() => session.value.error
|
|
106
|
+
],
|
|
107
|
+
([isPending, data, error]) => publishFromSession({ isPending, data, error }),
|
|
108
|
+
{
|
|
109
|
+
immediate: true,
|
|
110
|
+
deep: false,
|
|
111
|
+
// Identity observation is a security boundary: retire the old identity
|
|
112
|
+
// in the same turn rather than after Vue's render queue flushes.
|
|
113
|
+
flush: "sync"
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
const waitForSessionSettlement = async () => {
|
|
117
|
+
const isUnsettled = () => session.value.isPending === true || session.value.isRefetching === true;
|
|
118
|
+
if (!isUnsettled()) return;
|
|
119
|
+
await new Promise((resolve, reject) => {
|
|
120
|
+
let settled = false;
|
|
121
|
+
let stopPending = () => {
|
|
122
|
+
};
|
|
123
|
+
const finish = (error) => {
|
|
124
|
+
if (settled) return;
|
|
125
|
+
settled = true;
|
|
126
|
+
stopPending();
|
|
127
|
+
clearTimeout(timer);
|
|
128
|
+
cancelSessionSettlement.delete(cancel);
|
|
129
|
+
if (error) reject(error);
|
|
130
|
+
else resolve();
|
|
131
|
+
};
|
|
132
|
+
const cancel = () => finish(new Error(UNAVAILABLE));
|
|
133
|
+
cancelSessionSettlement.add(cancel);
|
|
134
|
+
stopPending = watch(
|
|
135
|
+
isUnsettled,
|
|
136
|
+
(unsettled) => {
|
|
137
|
+
if (!unsettled) finish();
|
|
138
|
+
},
|
|
139
|
+
{ flush: "sync" }
|
|
140
|
+
);
|
|
141
|
+
const timer = setTimeout(cancel, SESSION_SETTLEMENT_TIMEOUT_MS);
|
|
142
|
+
if (disposed) cancel();
|
|
143
|
+
else if (!isUnsettled()) finish();
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
return Object.freeze({
|
|
147
|
+
snapshot: () => snapshot,
|
|
148
|
+
subscribe(listener) {
|
|
149
|
+
if (disposed) return () => {
|
|
150
|
+
};
|
|
151
|
+
listeners.add(listener);
|
|
152
|
+
return () => listeners.delete(listener);
|
|
153
|
+
},
|
|
154
|
+
async fetchToken() {
|
|
155
|
+
if (disposed || snapshot.status !== "authenticated") return null;
|
|
156
|
+
const expectedKey = snapshot.identityKey;
|
|
157
|
+
const outcome = await fetchConvexToken(source);
|
|
158
|
+
if (disposed || snapshot.status !== "authenticated" || snapshot.identityKey !== expectedKey) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
if (outcome.identity) {
|
|
162
|
+
const fetchedKey = outcome.identity.user.id;
|
|
163
|
+
if (fetchedKey !== expectedKey) {
|
|
164
|
+
cachedToken = null;
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
cachedToken = outcome.identity.token;
|
|
168
|
+
callbacks.authenticated(outcome.identity.token, outcome.identity.user);
|
|
169
|
+
return cachedToken;
|
|
170
|
+
}
|
|
171
|
+
if (!outcome.definitive && isTokenUsable(cachedToken)) return cachedToken;
|
|
172
|
+
cachedToken = null;
|
|
173
|
+
callbacks.anonymous(outcome.authError);
|
|
174
|
+
return null;
|
|
175
|
+
},
|
|
176
|
+
async refreshSession() {
|
|
177
|
+
if (disposed) return;
|
|
178
|
+
const refetch = session.value.refetch;
|
|
179
|
+
if (typeof refetch !== "function") throw new Error(UNAVAILABLE);
|
|
180
|
+
try {
|
|
181
|
+
await refetch();
|
|
182
|
+
await waitForSessionSettlement();
|
|
183
|
+
} catch {
|
|
184
|
+
throw new Error(UNAVAILABLE);
|
|
185
|
+
}
|
|
186
|
+
if (disposed || session.value.error) throw new Error(UNAVAILABLE);
|
|
187
|
+
},
|
|
188
|
+
failClosed(message) {
|
|
189
|
+
if (disposed) return;
|
|
190
|
+
cachedToken = null;
|
|
191
|
+
sessionGeneration += 1;
|
|
192
|
+
snapshot = {
|
|
193
|
+
status: "error",
|
|
194
|
+
identityKey: null,
|
|
195
|
+
sessionGeneration,
|
|
196
|
+
error: new Error(UNAVAILABLE)
|
|
197
|
+
};
|
|
198
|
+
observedSessionToken = null;
|
|
199
|
+
observedIdentityKey = null;
|
|
200
|
+
callbacks.anonymous(message);
|
|
201
|
+
callbacks.sessionChanged?.(null, UNAVAILABLE, sessionGeneration);
|
|
202
|
+
notify();
|
|
203
|
+
},
|
|
204
|
+
dispose() {
|
|
205
|
+
if (disposed) return;
|
|
206
|
+
disposed = true;
|
|
207
|
+
stop();
|
|
208
|
+
for (const cancel of [...cancelSessionSettlement]) cancel();
|
|
209
|
+
cancelSessionSettlement.clear();
|
|
210
|
+
listeners.clear();
|
|
211
|
+
cachedToken = null;
|
|
212
|
+
observedSessionToken = null;
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { createAuthClient } from 'better-auth/vue';
|
|
2
|
+
import type { ConvexTokenSource } from './token-fetcher.js';
|
|
3
|
+
/** Better Auth client augmented with the prepended Convex token plugin. */
|
|
4
|
+
export type AuthClientWithConvex = ReturnType<typeof createAuthClient> & ConvexTokenSource;
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IntegratedAuthClient } from '../auth-client/index.js';
|
|
2
|
+
export interface SessionCheckpoint {
|
|
3
|
+
readonly revision: number;
|
|
4
|
+
}
|
|
5
|
+
export interface CanonicalSessionReconciler {
|
|
6
|
+
checkpoint(): SessionCheckpoint;
|
|
7
|
+
/**
|
|
8
|
+
* Finish a synchronous call. This deliberately may throw when that call
|
|
9
|
+
* changed the provider session: such a plugin operation cannot be reconciled
|
|
10
|
+
* without changing its synchronous contract.
|
|
11
|
+
*/
|
|
12
|
+
cancel(checkpoint: SessionCheckpoint): void;
|
|
13
|
+
/** Re-read the canonical provider session, then await its Convex acceptance. */
|
|
14
|
+
reconcile(checkpoint: SessionCheckpoint): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Integrates Better Auth without inventing a second action list.
|
|
18
|
+
*
|
|
19
|
+
* The apply trap is intentionally synchronous. Better Auth 1.7 exposes both
|
|
20
|
+
* synchronous APIs (`useSession()` and plugin permission checks) and
|
|
21
|
+
* Promise-returning actions through recursive callable proxies. Synchronous
|
|
22
|
+
* values pass through unchanged; only actual PromiseLike results cross the
|
|
23
|
+
* canonical session reconciliation barrier.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createIntegratedAuthClient<Client extends object>(client: Client, reconciler: CanonicalSessionReconciler, track?: <Value>(operation: Promise<Value>) => Promise<Value>): IntegratedAuthClient<Client>;
|