@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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const LOCAL_URL_BASE = "https://better-convex-nuxt.invalid";
|
|
2
|
+
function hasUnsafePathCharacter(value) {
|
|
3
|
+
for (const character of value) {
|
|
4
|
+
const codeUnit = character.charCodeAt(0);
|
|
5
|
+
if (character === "\\" || codeUnit <= 31 || codeUnit === 127) return true;
|
|
6
|
+
}
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
export function normalizeLocalRedirectPath(value) {
|
|
10
|
+
if (!value.startsWith("/") || value.startsWith("//") || hasUnsafePathCharacter(value)) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
let decoded;
|
|
14
|
+
try {
|
|
15
|
+
decoded = decodeURIComponent(value);
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (decoded.startsWith("//") || hasUnsafePathCharacter(decoded)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const parsed = new URL(value, LOCAL_URL_BASE);
|
|
23
|
+
if (parsed.origin !== LOCAL_URL_BASE || parsed.pathname.startsWith("//")) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
27
|
+
}
|
|
28
|
+
export function resolveRouteProtectionDecision(input) {
|
|
29
|
+
const { meta, defaultRedirectTo, preserveReturnTo, currentPath } = input;
|
|
30
|
+
const currentFullPath = input.currentFullPath ?? currentPath;
|
|
31
|
+
if (meta === void 0 || meta === false) return null;
|
|
32
|
+
const redirectBase = typeof meta === "object" && meta !== null && meta.redirectTo ? meta.redirectTo : defaultRedirectTo;
|
|
33
|
+
if (!redirectBase) return null;
|
|
34
|
+
if (typeof redirectBase !== "string") {
|
|
35
|
+
if ("path" in redirectBase && typeof redirectBase.path === "string") {
|
|
36
|
+
const path = normalizeLocalRedirectPath(redirectBase.path);
|
|
37
|
+
if (!path) return null;
|
|
38
|
+
return { redirectTo: { ...redirectBase, path } };
|
|
39
|
+
}
|
|
40
|
+
return { redirectTo: redirectBase };
|
|
41
|
+
}
|
|
42
|
+
const redirectPath = normalizeLocalRedirectPath(redirectBase);
|
|
43
|
+
if (!redirectPath) return null;
|
|
44
|
+
const redirectPathOnly = redirectPath.split(/[?#]/)[0] || redirectPath;
|
|
45
|
+
if (currentPath === redirectPathOnly) return null;
|
|
46
|
+
if (!preserveReturnTo) {
|
|
47
|
+
return { redirectTo: redirectPath };
|
|
48
|
+
}
|
|
49
|
+
const returnTo = normalizeLocalRedirectPath(currentFullPath) ?? normalizeLocalRedirectPath(currentPath) ?? "/";
|
|
50
|
+
const hashIndex = redirectPath.indexOf("#");
|
|
51
|
+
const redirectWithoutHash = hashIndex === -1 ? redirectPath : redirectPath.slice(0, hashIndex);
|
|
52
|
+
const hash = hashIndex === -1 ? "" : redirectPath.slice(hashIndex);
|
|
53
|
+
const hasQuery = redirectWithoutHash.includes("?");
|
|
54
|
+
const separator = hasQuery ? "&" : "?";
|
|
55
|
+
return {
|
|
56
|
+
redirectTo: `${redirectWithoutHash}${separator}redirect=${encodeURIComponent(returnTo)}${hash}`
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ConvexCallError } from '../errors/index.js';
|
|
2
|
+
import { type ConvexIdentityKey } from './identity-key.js';
|
|
3
|
+
/**
|
|
4
|
+
* Per-query authentication mode .
|
|
5
|
+
*
|
|
6
|
+
* | Mode | Initial auth loading | Settled authenticated | Settled anonymous |
|
|
7
|
+
* | ---------- | -------------------- | --------------------- | ------------------- |
|
|
8
|
+
* | `required` | Wait | Execute with identity | Stay idle |
|
|
9
|
+
* | `optional` | Wait | Execute with identity | Execute anonymously |
|
|
10
|
+
* | `none` | Do not wait | Execute anonymously | Execute anonymously |
|
|
11
|
+
*
|
|
12
|
+
* The fixed default is `optional`. There is no `auto` mode and no per-build
|
|
13
|
+
* default override; auth policy must not change invisibly between applications.
|
|
14
|
+
*/
|
|
15
|
+
export type ConvexAuthMode = 'required' | 'optional' | 'none';
|
|
16
|
+
/**
|
|
17
|
+
* Current usable identity . Orthogonal to `isPending`, which tracks
|
|
18
|
+
* auth work in flight. A background refresh keeps `status === 'authenticated'`
|
|
19
|
+
* while `isPending === true`.
|
|
20
|
+
*/
|
|
21
|
+
export type ConvexAuthStatus = 'loading' | 'anonymous' | 'authenticated' | 'error';
|
|
22
|
+
/** Internal query gate state for a build that intentionally has no auth graph. */
|
|
23
|
+
export type ConvexQueryAuthStatus = ConvexAuthStatus | 'disabled';
|
|
24
|
+
/**
|
|
25
|
+
* The two-dimensional inputs to status derivation. `settled` is the initial
|
|
26
|
+
* auth-settlement signal; `error` is non-null only when initial resolution
|
|
27
|
+
* failed without a usable identity (see {@link ConvexCallError} placeholder).
|
|
28
|
+
*/
|
|
29
|
+
export interface ConvexAuthStatusInput {
|
|
30
|
+
authEnabled: boolean;
|
|
31
|
+
settled: boolean;
|
|
32
|
+
identityKey: ConvexIdentityKey | null;
|
|
33
|
+
error: ConvexCallError | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Derive the canonical status in the exact precedence locked by public and
|
|
37
|
+
* architecture invariant: `disabled` → `loading` → `authenticated` → `error` → `anonymous`.
|
|
38
|
+
*
|
|
39
|
+
* `authenticated` outranks `error` so a failed background refresh over a still
|
|
40
|
+
* usable identity keeps `authenticated`. `error` outranks `anonymous` so a
|
|
41
|
+
* failed initial resolution surfaces the error instead of silently downgrading
|
|
42
|
+
* to anonymous execution.
|
|
43
|
+
*/
|
|
44
|
+
export declare function deriveConvexAuthStatus(input: ConvexAuthStatusInput & {
|
|
45
|
+
authEnabled: true;
|
|
46
|
+
}): ConvexAuthStatus;
|
|
47
|
+
export declare function deriveConvexAuthStatus(input: ConvexAuthStatusInput): ConvexQueryAuthStatus;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { isAuthenticatedIdentityKey } from "./identity-key.js";
|
|
2
|
+
export function deriveConvexAuthStatus(input) {
|
|
3
|
+
if (!input.authEnabled) return "disabled";
|
|
4
|
+
if (!input.settled) return "loading";
|
|
5
|
+
if (isAuthenticatedIdentityKey(input.identityKey)) return "authenticated";
|
|
6
|
+
if (input.error) return "error";
|
|
7
|
+
return "anonymous";
|
|
8
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const CONVEX_HTTP_QUERY_TIMEOUT_MS = 8000;
|
|
2
|
+
export declare const CONVEX_HTTP_MUTATION_TIMEOUT_MS = 15000;
|
|
3
|
+
export declare const CONVEX_HTTP_ACTION_TIMEOUT_MS = 60000;
|
|
4
|
+
export declare const CONVEX_HTTP_MAX_RESPONSE_BYTES: number;
|
|
5
|
+
interface BoundedConvexFetchOptions {
|
|
6
|
+
fetchImpl?: typeof fetch;
|
|
7
|
+
maxResponseBytes?: number;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
/** Test-only fixed deadline override; production derives it from the endpoint. */
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* One bounded Convex HTTP transport for SSR queries and request-scoped public
|
|
14
|
+
* server calls. Convex owns value/protocol encoding; this boundary owns abort,
|
|
15
|
+
* operation deadlines, opaque non-UDF failures, and response bytes.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createBoundedConvexFetch(options?: BoundedConvexFetchOptions): typeof fetch;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { ConvexCallError } from "../errors/index.js";
|
|
2
|
+
export const CONVEX_HTTP_QUERY_TIMEOUT_MS = 8e3;
|
|
3
|
+
export const CONVEX_HTTP_MUTATION_TIMEOUT_MS = 15e3;
|
|
4
|
+
export const CONVEX_HTTP_ACTION_TIMEOUT_MS = 6e4;
|
|
5
|
+
export const CONVEX_HTTP_MAX_RESPONSE_BYTES = 1024 * 1024;
|
|
6
|
+
const CONVEX_UDF_FAILED_STATUS = 560;
|
|
7
|
+
const CONVEX_HTTP_UPSTREAM_FAILURE_MESSAGE = "The request to Convex failed before a usable response was received.";
|
|
8
|
+
function operationTimeoutMs(input) {
|
|
9
|
+
let pathname;
|
|
10
|
+
try {
|
|
11
|
+
pathname = new URL(input instanceof Request ? input.url : String(input)).pathname;
|
|
12
|
+
} catch {
|
|
13
|
+
return CONVEX_HTTP_QUERY_TIMEOUT_MS;
|
|
14
|
+
}
|
|
15
|
+
if (pathname.endsWith("/api/action")) return CONVEX_HTTP_ACTION_TIMEOUT_MS;
|
|
16
|
+
if (pathname.endsWith("/api/mutation")) return CONVEX_HTTP_MUTATION_TIMEOUT_MS;
|
|
17
|
+
return CONVEX_HTTP_QUERY_TIMEOUT_MS;
|
|
18
|
+
}
|
|
19
|
+
function transportError(message, status) {
|
|
20
|
+
return new ConvexCallError({ kind: "transport", message, status });
|
|
21
|
+
}
|
|
22
|
+
function boundedResponse(response, maximum, signal, cleanup) {
|
|
23
|
+
const declared = response.headers.get("content-length");
|
|
24
|
+
if (declared !== null) {
|
|
25
|
+
const length = Number(declared);
|
|
26
|
+
if (!Number.isSafeInteger(length) || length < 0 || length > maximum) {
|
|
27
|
+
cleanup();
|
|
28
|
+
void response.body?.cancel().catch(() => {
|
|
29
|
+
});
|
|
30
|
+
throw transportError("Convex HTTP response exceeded the size limit", response.status);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!response.body) {
|
|
34
|
+
cleanup();
|
|
35
|
+
return response;
|
|
36
|
+
}
|
|
37
|
+
const reader = response.body.getReader();
|
|
38
|
+
let total = 0;
|
|
39
|
+
let finished = false;
|
|
40
|
+
let bodyController;
|
|
41
|
+
const abortBody = () => {
|
|
42
|
+
if (finished) return;
|
|
43
|
+
const reason = signal.reason instanceof ConvexCallError ? signal.reason : transportError("Convex HTTP request was aborted");
|
|
44
|
+
void reader.cancel(reason).catch(() => {
|
|
45
|
+
});
|
|
46
|
+
finish();
|
|
47
|
+
bodyController?.error(reason);
|
|
48
|
+
};
|
|
49
|
+
const finish = () => {
|
|
50
|
+
if (finished) return;
|
|
51
|
+
finished = true;
|
|
52
|
+
signal.removeEventListener("abort", abortBody);
|
|
53
|
+
cleanup();
|
|
54
|
+
reader.releaseLock();
|
|
55
|
+
};
|
|
56
|
+
const body = new ReadableStream({
|
|
57
|
+
start(controller) {
|
|
58
|
+
bodyController = controller;
|
|
59
|
+
signal.addEventListener("abort", abortBody, { once: true });
|
|
60
|
+
if (signal.aborted) abortBody();
|
|
61
|
+
},
|
|
62
|
+
async pull(controller) {
|
|
63
|
+
try {
|
|
64
|
+
const next = await reader.read();
|
|
65
|
+
if (next.done) {
|
|
66
|
+
finish();
|
|
67
|
+
controller.close();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
total += next.value.byteLength;
|
|
71
|
+
if (total > maximum) {
|
|
72
|
+
const error = transportError(
|
|
73
|
+
"Convex HTTP response exceeded the size limit",
|
|
74
|
+
response.status
|
|
75
|
+
);
|
|
76
|
+
await reader.cancel(error);
|
|
77
|
+
finish();
|
|
78
|
+
controller.error(error);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
controller.enqueue(next.value);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
finish();
|
|
84
|
+
controller.error(error);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
async cancel(reason) {
|
|
88
|
+
try {
|
|
89
|
+
await reader.cancel(reason);
|
|
90
|
+
} finally {
|
|
91
|
+
finish();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return new Response(body, {
|
|
96
|
+
headers: response.headers,
|
|
97
|
+
status: response.status,
|
|
98
|
+
statusText: response.statusText
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export function createBoundedConvexFetch(options = {}) {
|
|
102
|
+
const {
|
|
103
|
+
fetchImpl = fetch,
|
|
104
|
+
maxResponseBytes = CONVEX_HTTP_MAX_RESPONSE_BYTES,
|
|
105
|
+
signal: parentSignal,
|
|
106
|
+
timeoutMs: fixedTimeoutMs
|
|
107
|
+
} = options;
|
|
108
|
+
if (!Number.isSafeInteger(maxResponseBytes) || maxResponseBytes <= 0) {
|
|
109
|
+
throw new TypeError("CONVEX_HTTP_RESPONSE_LIMIT_INVALID");
|
|
110
|
+
}
|
|
111
|
+
if (fixedTimeoutMs !== void 0 && (!Number.isFinite(fixedTimeoutMs) || fixedTimeoutMs <= 0)) {
|
|
112
|
+
throw new TypeError("CONVEX_HTTP_TIMEOUT_INVALID");
|
|
113
|
+
}
|
|
114
|
+
return async (input, init) => {
|
|
115
|
+
const timeoutMs = fixedTimeoutMs ?? operationTimeoutMs(input);
|
|
116
|
+
const controller = new AbortController();
|
|
117
|
+
const abortFromParent = () => controller.abort(parentSignal?.reason);
|
|
118
|
+
if (parentSignal?.aborted) abortFromParent();
|
|
119
|
+
else parentSignal?.addEventListener("abort", abortFromParent, { once: true });
|
|
120
|
+
const timeout = setTimeout(
|
|
121
|
+
() => controller.abort(transportError("Convex HTTP request timed out")),
|
|
122
|
+
timeoutMs
|
|
123
|
+
);
|
|
124
|
+
const cleanup = () => {
|
|
125
|
+
clearTimeout(timeout);
|
|
126
|
+
parentSignal?.removeEventListener("abort", abortFromParent);
|
|
127
|
+
};
|
|
128
|
+
try {
|
|
129
|
+
const response = await fetchImpl(input, {
|
|
130
|
+
...init,
|
|
131
|
+
cache: "no-store",
|
|
132
|
+
signal: controller.signal
|
|
133
|
+
});
|
|
134
|
+
if (!response.ok && response.status !== CONVEX_UDF_FAILED_STATUS) {
|
|
135
|
+
cleanup();
|
|
136
|
+
void response.body?.cancel().catch(() => {
|
|
137
|
+
});
|
|
138
|
+
throw transportError(CONVEX_HTTP_UPSTREAM_FAILURE_MESSAGE, response.status);
|
|
139
|
+
}
|
|
140
|
+
return boundedResponse(response, maxResponseBytes, controller.signal, cleanup);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
cleanup();
|
|
143
|
+
if (error instanceof ConvexCallError) throw error;
|
|
144
|
+
if (controller.signal.aborted) {
|
|
145
|
+
throw transportError(
|
|
146
|
+
parentSignal?.aborted ? "Convex HTTP request was aborted" : "Convex HTTP request timed out"
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
throw transportError("Convex HTTP request could not complete");
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DevtoolsSink } from '../devtools/sink.js';
|
|
2
|
+
import type { ConvexCallError } from '../errors/index.js';
|
|
3
|
+
interface CallableDevtoolsEvent {
|
|
4
|
+
sink: DevtoolsSink;
|
|
5
|
+
id: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createCallableDevtoolsEvents<Args, Result>(input: {
|
|
8
|
+
operation: 'mutation' | 'action';
|
|
9
|
+
fnName: string;
|
|
10
|
+
hasOptimisticUpdate: boolean;
|
|
11
|
+
getSink: () => DevtoolsSink | null;
|
|
12
|
+
}): {
|
|
13
|
+
startEvent(args: Args, startedAt: number): CallableDevtoolsEvent | undefined;
|
|
14
|
+
finishEvent(event: unknown, result: Result, startedAt: number): void;
|
|
15
|
+
failEvent(event: unknown, error: ConvexCallError, startedAt: number): void;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function createCallableDevtoolsEvents(input) {
|
|
2
|
+
return {
|
|
3
|
+
startEvent(args, startedAt) {
|
|
4
|
+
try {
|
|
5
|
+
const sink = input.getSink();
|
|
6
|
+
if (!sink) return void 0;
|
|
7
|
+
const id = sink.registerMutation({
|
|
8
|
+
name: input.fnName,
|
|
9
|
+
type: input.operation,
|
|
10
|
+
args,
|
|
11
|
+
state: input.operation === "mutation" && input.hasOptimisticUpdate ? "optimistic" : "pending",
|
|
12
|
+
hasOptimisticUpdate: input.hasOptimisticUpdate,
|
|
13
|
+
startedAt
|
|
14
|
+
});
|
|
15
|
+
return id ? { sink, id } : void 0;
|
|
16
|
+
} catch {
|
|
17
|
+
return void 0;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
finishEvent(rawEvent, result, startedAt) {
|
|
21
|
+
const event = rawEvent;
|
|
22
|
+
if (!event) return;
|
|
23
|
+
try {
|
|
24
|
+
const settledAt = Date.now();
|
|
25
|
+
event.sink.updateMutation(event.id, {
|
|
26
|
+
state: "success",
|
|
27
|
+
result,
|
|
28
|
+
settledAt,
|
|
29
|
+
duration: settledAt - startedAt
|
|
30
|
+
});
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
failEvent(rawEvent, error, startedAt) {
|
|
35
|
+
const event = rawEvent;
|
|
36
|
+
if (!event) return;
|
|
37
|
+
try {
|
|
38
|
+
const settledAt = Date.now();
|
|
39
|
+
event.sink.updateMutation(event.id, {
|
|
40
|
+
state: "error",
|
|
41
|
+
error: error.message,
|
|
42
|
+
settledAt,
|
|
43
|
+
duration: settledAt - startedAt
|
|
44
|
+
});
|
|
45
|
+
} catch {
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const CALLABLE_OBSERVER_KEY = Symbol.for("better-convex.callable-observer");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function assertConvexComposableScope(composable, isClient, scope) {
|
|
2
|
+
if (!isClient || scope) {
|
|
3
|
+
return;
|
|
4
|
+
}
|
|
5
|
+
throw new Error(
|
|
6
|
+
`[${composable}] Must be called within component setup/effect scope. For middleware/plugins use useConvex() (client) or serverConvex() (server).`
|
|
7
|
+
);
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const DEFAULT_AUTH_PROXY_BODY_LIMIT_BYTES = 1048576;
|
|
2
|
+
export const CONVEX_MODULE_DEFAULTS = Object.freeze({
|
|
3
|
+
logging: false,
|
|
4
|
+
authProxy: Object.freeze({
|
|
5
|
+
maxRequestBodyBytes: DEFAULT_AUTH_PROXY_BODY_LIMIT_BYTES,
|
|
6
|
+
maxResponseBodyBytes: DEFAULT_AUTH_PROXY_BODY_LIMIT_BYTES
|
|
7
|
+
})
|
|
8
|
+
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ConvexAuthMode } from './auth-status.js';
|
|
2
|
+
import type { ConvexIdentityKey } from './identity-key.js';
|
|
3
|
+
/**
|
|
4
|
+
* Append the auth/identity dimension to an identity-blind base key produced by
|
|
5
|
+
* `createConvexQueryKey`. `none` is a static, identity-independent suffix so a
|
|
6
|
+
* public query is shared across sign-in/out; every other mode is partitioned by
|
|
7
|
+
* the concrete `ConvexIdentityKey`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function withAuthDimension(baseKey: string, authMode: ConvexAuthMode, identityKey: ConvexIdentityKey): string;
|
|
10
|
+
/**
|
|
11
|
+
* A protected SSR payload may seed a browser controller only when the canonical
|
|
12
|
+
* browser identity already names the same principal. The auth adapter seeds an
|
|
13
|
+
* unsettled first generation from SSR provenance, so an anonymous snapshot is a
|
|
14
|
+
* real mismatch here rather than a reason to expose protected data speculatively.
|
|
15
|
+
*/
|
|
16
|
+
export declare function matchesConvexHydrationIdentity(authMode: ConvexAuthMode, payloadIdentity: ConvexIdentityKey, browserIdentity: {
|
|
17
|
+
readonly identityKey: ConvexIdentityKey | null;
|
|
18
|
+
} | undefined): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Read the `:auth:<mode>` segment of a payload key, or `null` when the key is
|
|
21
|
+
* not a mode-tagged Convex payload key (e.g. an `idle` key or a non-Convex key).
|
|
22
|
+
*/
|
|
23
|
+
export declare function readAuthMode(key: string): ConvexAuthMode | null;
|
|
24
|
+
/**
|
|
25
|
+
* Sign-out / identity-change purge (architecture invariant). Scans only the two Convex
|
|
26
|
+
* payload namespaces on the Nuxt payload/state and removes keys whose `:auth:`
|
|
27
|
+
* mode segment is `required` or `optional`; `none` keys are retained and keys
|
|
28
|
+
* outside these namespaces are never touched. No registry or count is consulted.
|
|
29
|
+
*
|
|
30
|
+
* This is the app-global hygiene complement to each composable clearing its own
|
|
31
|
+
* identity-owned state on an identity change; identity-partitioned keys already
|
|
32
|
+
* guarantee a new identity never reads the previous identity's payload.
|
|
33
|
+
*/
|
|
34
|
+
export declare function purgeConvexIdentityPayloadKeys(nuxtApp: {
|
|
35
|
+
payload?: {
|
|
36
|
+
data?: Record<string, unknown>;
|
|
37
|
+
state?: Record<string, unknown>;
|
|
38
|
+
};
|
|
39
|
+
}): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Remove identity-bound query errors while retaining anonymous-query errors.
|
|
42
|
+
* Error state is stored under one Nuxt useState key rather than as individual
|
|
43
|
+
* payload keys, so it needs the same auth-mode filtering explicitly.
|
|
44
|
+
*/
|
|
45
|
+
export declare function retainAnonymousConvexQueryErrors<T>(errors: Readonly<Record<string, T>>): Record<string, T>;
|
|
46
|
+
export interface FetchAuthTokenOptions {
|
|
47
|
+
/** Auth transport mode for this query. */
|
|
48
|
+
auth: ConvexAuthMode;
|
|
49
|
+
/** Cookie header from the request. */
|
|
50
|
+
cookieHeader: string;
|
|
51
|
+
/** Cached token state (must be obtained at setup time via useState). */
|
|
52
|
+
cachedToken: {
|
|
53
|
+
value: string | null;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the SSR auth token for a query.
|
|
58
|
+
*
|
|
59
|
+
* Performs NO cookie -> JWT exchange. `plugin.server.ts` runs before any route
|
|
60
|
+
* component's setup and already exchanged the session cookie once, writing the
|
|
61
|
+
* result into the canonical `useState('convex:identity')`. SSR queries reuse that single
|
|
62
|
+
* per-request exchange. `none` never attaches a token.
|
|
63
|
+
*
|
|
64
|
+
* The `cachedToken` must be obtained at component setup time via
|
|
65
|
+
* the canonical identity state; calling `useState` inside an async function loses
|
|
66
|
+
* Vue context.
|
|
67
|
+
*/
|
|
68
|
+
export declare function fetchAuthToken(options: FetchAuthTokenOptions): string | undefined;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getBetterAuthSessionToken } from "./shared-helpers.js";
|
|
2
|
+
const AUTH_SEGMENT = ":auth:";
|
|
3
|
+
export function withAuthDimension(baseKey, authMode, identityKey) {
|
|
4
|
+
if (authMode === "none") return `${baseKey}${AUTH_SEGMENT}none`;
|
|
5
|
+
return `${baseKey}${AUTH_SEGMENT}${authMode}:${identityKey}`;
|
|
6
|
+
}
|
|
7
|
+
export function matchesConvexHydrationIdentity(authMode, payloadIdentity, browserIdentity) {
|
|
8
|
+
return authMode === "none" || browserIdentity?.identityKey === payloadIdentity;
|
|
9
|
+
}
|
|
10
|
+
function isConvexPayloadKey(key) {
|
|
11
|
+
return key.startsWith("convex:") || key.startsWith("convex-paginated:");
|
|
12
|
+
}
|
|
13
|
+
export function readAuthMode(key) {
|
|
14
|
+
const idx = key.indexOf(AUTH_SEGMENT);
|
|
15
|
+
if (idx < 0) return null;
|
|
16
|
+
const rest = key.slice(idx + AUTH_SEGMENT.length);
|
|
17
|
+
const mode = rest.split(":", 1)[0];
|
|
18
|
+
if (mode === "required" || mode === "optional" || mode === "none") return mode;
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export function purgeConvexIdentityPayloadKeys(nuxtApp) {
|
|
22
|
+
const purged = [];
|
|
23
|
+
const scan = (bag) => {
|
|
24
|
+
if (!bag) return;
|
|
25
|
+
for (const key of Object.keys(bag)) {
|
|
26
|
+
const libKey = key.startsWith("$s") ? key.slice(2) : key;
|
|
27
|
+
if (!isConvexPayloadKey(libKey)) continue;
|
|
28
|
+
const mode = readAuthMode(libKey);
|
|
29
|
+
if (mode === "required" || mode === "optional") {
|
|
30
|
+
Reflect.deleteProperty(bag, key);
|
|
31
|
+
purged.push(key);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
scan(nuxtApp.payload?.data);
|
|
36
|
+
scan(nuxtApp.payload?.state);
|
|
37
|
+
return purged;
|
|
38
|
+
}
|
|
39
|
+
export function retainAnonymousConvexQueryErrors(errors) {
|
|
40
|
+
return Object.fromEntries(Object.entries(errors).filter(([key]) => readAuthMode(key) === "none"));
|
|
41
|
+
}
|
|
42
|
+
export function fetchAuthToken(options) {
|
|
43
|
+
const { auth, cookieHeader, cachedToken } = options;
|
|
44
|
+
if (auth === "none") return void 0;
|
|
45
|
+
if (!getBetterAuthSessionToken(cookieHeader)) return void 0;
|
|
46
|
+
return cachedToken.value ?? void 0;
|
|
47
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type SiteUrlResolutionSource = 'explicit' | 'derived' | 'missing' | 'invalid-derived';
|
|
2
|
+
export interface ResolveConvexSiteUrlInput {
|
|
3
|
+
url?: string | null;
|
|
4
|
+
siteUrl?: string | null;
|
|
5
|
+
}
|
|
6
|
+
export interface ResolveConvexSiteUrlResult {
|
|
7
|
+
siteUrl?: string;
|
|
8
|
+
source: SiteUrlResolutionSource;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Derive the Convex HTTP Actions host from the Convex deployment URL.
|
|
12
|
+
* Example: https://foo.convex.cloud -> https://foo.convex.site
|
|
13
|
+
*/
|
|
14
|
+
export declare function deriveConvexSiteUrl(url?: string | null): string | undefined;
|
|
15
|
+
export declare function resolveConvexSiteUrl(input: ResolveConvexSiteUrlInput): ResolveConvexSiteUrlResult;
|
|
16
|
+
export declare function getSiteUrlResolutionHint(url?: string | null): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function deriveConvexSiteUrl(url) {
|
|
2
|
+
if (!url) return void 0;
|
|
3
|
+
let parsed;
|
|
4
|
+
try {
|
|
5
|
+
parsed = new URL(url);
|
|
6
|
+
} catch {
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
if (parsed.hostname.endsWith(".convex.cloud")) {
|
|
10
|
+
parsed.hostname = parsed.hostname.replace(/\.convex\.cloud$/, ".convex.site");
|
|
11
|
+
parsed.pathname = "";
|
|
12
|
+
parsed.search = "";
|
|
13
|
+
parsed.hash = "";
|
|
14
|
+
return parsed.toString().replace(/\/$/, "");
|
|
15
|
+
}
|
|
16
|
+
const isLocalConvexDevHost = parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost";
|
|
17
|
+
if (isLocalConvexDevHost && parsed.port === "3210") {
|
|
18
|
+
parsed.port = "3211";
|
|
19
|
+
parsed.pathname = "";
|
|
20
|
+
parsed.search = "";
|
|
21
|
+
parsed.hash = "";
|
|
22
|
+
return parsed.toString().replace(/\/$/, "");
|
|
23
|
+
}
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
export function resolveConvexSiteUrl(input) {
|
|
27
|
+
if (input.siteUrl) {
|
|
28
|
+
return { siteUrl: input.siteUrl, source: "explicit" };
|
|
29
|
+
}
|
|
30
|
+
if (!input.url) {
|
|
31
|
+
return { siteUrl: void 0, source: "missing" };
|
|
32
|
+
}
|
|
33
|
+
const derived = deriveConvexSiteUrl(input.url);
|
|
34
|
+
if (derived) {
|
|
35
|
+
return { siteUrl: derived, source: "derived" };
|
|
36
|
+
}
|
|
37
|
+
return { siteUrl: void 0, source: "invalid-derived" };
|
|
38
|
+
}
|
|
39
|
+
export function getSiteUrlResolutionHint(url) {
|
|
40
|
+
if (!url) {
|
|
41
|
+
return "Set `convex.url` (or `NUXT_PUBLIC_CONVEX_URL` / `CONVEX_URL`) first, or provide `convex.siteUrl` (or `NUXT_PUBLIC_CONVEX_SITE_URL` / `CONVEX_SITE_URL`) explicitly.";
|
|
42
|
+
}
|
|
43
|
+
if (url.includes("localhost") || url.includes("127.0.0.1")) {
|
|
44
|
+
return "For local Convex dev, use `convex.url` = `http://127.0.0.1:3210` (or `http://localhost:3210`), or set `convex.siteUrl` explicitly.";
|
|
45
|
+
}
|
|
46
|
+
if (!url.includes(".convex.cloud")) {
|
|
47
|
+
return "Could not derive `siteUrl` from `convex.url` because this is not a `.convex.cloud` URL. Set `convex.siteUrl` explicitly for your custom HTTP Actions domain.";
|
|
48
|
+
}
|
|
49
|
+
return "Set `convex.siteUrl` explicitly to your Convex HTTP Actions host (for example `https://your-app.convex.site`).";
|
|
50
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { FunctionArgs, FunctionReference } from 'convex/server';
|
|
2
|
+
import type { ConvexCallStatus, ConvexUser } from './types.js';
|
|
3
|
+
/** Milliseconds before `exp` at which a locally retained token is unusable. */
|
|
4
|
+
export declare const TOKEN_EXPIRY_SAFETY_BUFFER_MS = 30000;
|
|
5
|
+
/**
|
|
6
|
+
* Decode JWT payload without verification.
|
|
7
|
+
* Returns the parsed payload object or null if decoding fails.
|
|
8
|
+
*
|
|
9
|
+
* @param token - The JWT token string
|
|
10
|
+
* @returns The decoded payload object or null
|
|
11
|
+
*/
|
|
12
|
+
export declare function decodeJwtPayload(token: string): Record<string, unknown> | null;
|
|
13
|
+
/**
|
|
14
|
+
* Returns milliseconds until JWT expiry, or null when `exp` is missing/invalid.
|
|
15
|
+
* Negative values mean the token is already expired.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getJwtTimeUntilExpiryMs(token: string, nowMs?: number): number | null;
|
|
18
|
+
/**
|
|
19
|
+
* A locally retained token must have a finite `exp` beyond the safety window.
|
|
20
|
+
* This is a lifecycle guard, not JWT verification: Convex still verifies the
|
|
21
|
+
* signature, algorithm, key, issuer, audience, subject, and temporal claims.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isJwtUsable(token: string | null, nowMs?: number): token is string;
|
|
24
|
+
/**
|
|
25
|
+
* Decode user info from JWT payload.
|
|
26
|
+
* Extracts standard user fields from the JWT claims.
|
|
27
|
+
*
|
|
28
|
+
* @param token - The JWT token string
|
|
29
|
+
* @returns The decoded user or null if decoding fails
|
|
30
|
+
*/
|
|
31
|
+
export declare function decodeUserFromJwt(token: string): ConvexUser | null;
|
|
32
|
+
/**
|
|
33
|
+
* Status computation logic for queries.
|
|
34
|
+
*
|
|
35
|
+
* Priority order:
|
|
36
|
+
* 1. Skip -> idle (always)
|
|
37
|
+
* 2. Error -> error (takes precedence over pending)
|
|
38
|
+
* 3. Pending without data -> pending
|
|
39
|
+
* 4. Everything else -> success (including pending with data for background refresh)
|
|
40
|
+
*/
|
|
41
|
+
export declare function computeQueryStatus(isSkipped: boolean, hasError: boolean, isPending: boolean, hasData: boolean): ConvexCallStatus;
|
|
42
|
+
/**
|
|
43
|
+
* Get the function name from a Convex function reference.
|
|
44
|
+
* Works with queries, mutations, and actions.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getFunctionName(fn: FunctionReference<'query'> | FunctionReference<'mutation'> | FunctionReference<'action'>): string;
|
|
47
|
+
/**
|
|
48
|
+
* Generate a stable hash for any value using ohash.
|
|
49
|
+
* Used for cache key generation and argument comparison.
|
|
50
|
+
*
|
|
51
|
+
* Benefits over custom stableStringify:
|
|
52
|
+
* - Handles circular references gracefully
|
|
53
|
+
* - Faster execution (optimized C++ implementation)
|
|
54
|
+
* - Shorter, URL-safe output
|
|
55
|
+
* - Handles Symbols, Functions, and edge cases
|
|
56
|
+
*/
|
|
57
|
+
export declare function hashArgs(args: unknown): string;
|
|
58
|
+
/**
|
|
59
|
+
* Build the identity-blind base key for a query and arguments. This is the
|
|
60
|
+
* `convex:<functionName>:<argsHash>` (or
|
|
61
|
+
* `convex-paginated:<functionName>:<argsHash>`) prefix; the auth/identity
|
|
62
|
+
* dimension is appended separately by {@link withAuthDimension} so the same base
|
|
63
|
+
* can be partitioned per identity.
|
|
64
|
+
*
|
|
65
|
+
* The base key is internal; public keys include the auth dimension.
|
|
66
|
+
*/
|
|
67
|
+
export declare function createConvexQueryKey<Query extends FunctionReference<'query'>>(query: Query, args?: FunctionArgs<Query>, namespace?: 'convex' | 'convex-paginated'): string;
|