@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,33 @@
|
|
|
1
|
+
export type { ConnectionState } from 'convex/browser';
|
|
2
|
+
/** Deterministic SSR projection around the shared Vue connection store. */
|
|
3
|
+
export declare function useConvexConnectionState(): Readonly<{
|
|
4
|
+
state: import("vue").ComputedRef<import("convex/browser").ConnectionState>;
|
|
5
|
+
isConnected: import("vue").ComputedRef<boolean>;
|
|
6
|
+
isReconnecting: import("vue").ComputedRef<boolean>;
|
|
7
|
+
pendingMutations: import("vue").ComputedRef<number>;
|
|
8
|
+
pendingActions: import("vue").ComputedRef<number>;
|
|
9
|
+
}> | Readonly<{
|
|
10
|
+
state: Readonly<import("vue").Ref<{
|
|
11
|
+
readonly hasInflightRequests: boolean;
|
|
12
|
+
readonly isWebSocketConnected: boolean;
|
|
13
|
+
readonly timeOfOldestInflightRequest: null;
|
|
14
|
+
readonly hasEverConnected: boolean;
|
|
15
|
+
readonly connectionCount: number;
|
|
16
|
+
readonly connectionRetries: number;
|
|
17
|
+
readonly inflightMutations: number;
|
|
18
|
+
readonly inflightActions: number;
|
|
19
|
+
}, {
|
|
20
|
+
readonly hasInflightRequests: boolean;
|
|
21
|
+
readonly isWebSocketConnected: boolean;
|
|
22
|
+
readonly timeOfOldestInflightRequest: null;
|
|
23
|
+
readonly hasEverConnected: boolean;
|
|
24
|
+
readonly connectionCount: number;
|
|
25
|
+
readonly connectionRetries: number;
|
|
26
|
+
readonly inflightMutations: number;
|
|
27
|
+
readonly inflightActions: number;
|
|
28
|
+
}>>;
|
|
29
|
+
isConnected: import("vue").ComputedRef<boolean>;
|
|
30
|
+
isReconnecting: import("vue").ComputedRef<boolean>;
|
|
31
|
+
pendingMutations: import("vue").ComputedRef<number>;
|
|
32
|
+
pendingActions: import("vue").ComputedRef<number>;
|
|
33
|
+
}>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useConvexConnectionState as useVueConvexConnectionState } from "@lupinum/better-convex-vue";
|
|
2
|
+
import { computed, readonly, ref } from "vue";
|
|
3
|
+
export function useConvexConnectionState() {
|
|
4
|
+
if (import.meta.client) return useVueConvexConnectionState();
|
|
5
|
+
const state = readonly(
|
|
6
|
+
ref({
|
|
7
|
+
hasInflightRequests: false,
|
|
8
|
+
isWebSocketConnected: false,
|
|
9
|
+
timeOfOldestInflightRequest: null,
|
|
10
|
+
hasEverConnected: false,
|
|
11
|
+
connectionCount: 0,
|
|
12
|
+
connectionRetries: 0,
|
|
13
|
+
inflightMutations: 0,
|
|
14
|
+
inflightActions: 0
|
|
15
|
+
})
|
|
16
|
+
);
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
state,
|
|
19
|
+
isConnected: computed(() => false),
|
|
20
|
+
isReconnecting: computed(() => false),
|
|
21
|
+
pendingMutations: computed(() => 0),
|
|
22
|
+
pendingActions: computed(() => 0)
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File upload composable for Convex storage.
|
|
3
|
+
*
|
|
4
|
+
* Inspired by nuxt-convex by @onmax (https://github.com/onmax/nuxt-convex)
|
|
5
|
+
*/
|
|
6
|
+
import type { FunctionReference, OptionalRestArgs } from 'convex/server';
|
|
7
|
+
import type { GenericId } from 'convex/values';
|
|
8
|
+
import { type ComputedRef } from 'vue';
|
|
9
|
+
import { ConvexCallError } from '../errors/index.js';
|
|
10
|
+
import { type UploadProgressInfo } from '../utils/upload-core.js';
|
|
11
|
+
export type { UploadProgressInfo } from '../utils/upload-core.js';
|
|
12
|
+
/** A public Convex mutation that generates a browser upload URL. */
|
|
13
|
+
export type UploadUrlMutation = FunctionReference<'mutation', 'public', Record<string, unknown>, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Upload status representing the current state of the upload
|
|
16
|
+
* - 'idle': not yet called or reset
|
|
17
|
+
* - 'pending': upload in progress
|
|
18
|
+
* - 'success': upload completed successfully
|
|
19
|
+
* - 'error': upload failed
|
|
20
|
+
*/
|
|
21
|
+
export type UploadStatus = 'idle' | 'pending' | 'success' | 'error';
|
|
22
|
+
/**
|
|
23
|
+
* Return value from useConvexFileUpload
|
|
24
|
+
*/
|
|
25
|
+
export interface UseConvexFileUploadReturn<Mutation extends UploadUrlMutation> {
|
|
26
|
+
/**
|
|
27
|
+
* Upload a file. Returns the storageId on success.
|
|
28
|
+
* Automatically tracks status, error, progress, and data.
|
|
29
|
+
* Throws on error (use try/catch or check error ref after).
|
|
30
|
+
*
|
|
31
|
+
* @param file - The file to upload
|
|
32
|
+
* @param args - Validator-derived args for the generateUploadUrl mutation
|
|
33
|
+
*/
|
|
34
|
+
upload: (file: File, ...args: OptionalRestArgs<Mutation>) => Promise<GenericId<'_storage'>>;
|
|
35
|
+
/**
|
|
36
|
+
* StorageId from the last successful upload.
|
|
37
|
+
* undefined if upload hasn't succeeded yet.
|
|
38
|
+
*/
|
|
39
|
+
readonly data: ComputedRef<GenericId<'_storage'> | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Upload status for explicit state management.
|
|
42
|
+
*/
|
|
43
|
+
readonly status: ComputedRef<UploadStatus>;
|
|
44
|
+
/**
|
|
45
|
+
* True when upload is in progress.
|
|
46
|
+
* Equivalent to status === 'pending'.
|
|
47
|
+
*/
|
|
48
|
+
readonly pending: ComputedRef<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* Byte-level progress for the current upload.
|
|
51
|
+
*/
|
|
52
|
+
readonly progress: ComputedRef<UploadProgressInfo>;
|
|
53
|
+
/**
|
|
54
|
+
* Error from the last upload attempt as the normalized {@link ConvexCallError}.
|
|
55
|
+
* undefined if no error or upload hasn't been called.
|
|
56
|
+
*/
|
|
57
|
+
readonly error: ComputedRef<ConvexCallError | undefined>;
|
|
58
|
+
/**
|
|
59
|
+
* Cancel any in-progress upload and reset state.
|
|
60
|
+
* Aborts XHR, clears error, data, and progress.
|
|
61
|
+
*/
|
|
62
|
+
readonly cancel: () => void;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Options for useConvexFileUpload
|
|
66
|
+
*/
|
|
67
|
+
export interface UseConvexFileUploadOptions {
|
|
68
|
+
/**
|
|
69
|
+
* Maximum file size in bytes.
|
|
70
|
+
* Files exceeding this size will be rejected before upload starts.
|
|
71
|
+
* @example 5 * 1024 * 1024 // 5MB
|
|
72
|
+
*/
|
|
73
|
+
readonly maxSize?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Allowed MIME types.
|
|
76
|
+
* Files not matching these types will be rejected before upload starts.
|
|
77
|
+
*
|
|
78
|
+
* Supports wildcards: `image/*` matches any image type, `video/*` matches any video, etc.
|
|
79
|
+
*
|
|
80
|
+
* @example ['image/jpeg', 'image/png'] // Exact types only
|
|
81
|
+
* @example ['image/*'] // Any image type
|
|
82
|
+
* @example ['image/*', 'application/pdf'] // Any image or PDF
|
|
83
|
+
*/
|
|
84
|
+
readonly allowedTypes?: readonly string[];
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Composable for uploading files to Convex file storage with progress tracking.
|
|
88
|
+
*
|
|
89
|
+
* Handles the complete upload flow:
|
|
90
|
+
* 1. Generating an upload URL via mutation
|
|
91
|
+
* 2. POSTing the file to that URL (with progress tracking via XHR)
|
|
92
|
+
* 3. Returning the resulting storageId
|
|
93
|
+
*
|
|
94
|
+
* API designed to match useConvexMutation for consistency:
|
|
95
|
+
* - `data` - storageId from last successful upload
|
|
96
|
+
* - `status` - 'idle' | 'pending' | 'success' | 'error'
|
|
97
|
+
* - `pending` - boolean shorthand for status === 'pending'
|
|
98
|
+
* - `progress` - byte-level upload progress
|
|
99
|
+
* - `error` - Error | undefined
|
|
100
|
+
*
|
|
101
|
+
* Note: File uploads only work on the client side.
|
|
102
|
+
*
|
|
103
|
+
* @example Basic usage with progress tracking
|
|
104
|
+
* ```vue
|
|
105
|
+
* <script setup>
|
|
106
|
+
* import { api } from '#convex/api'
|
|
107
|
+
*
|
|
108
|
+
* const {
|
|
109
|
+
* upload,
|
|
110
|
+
* pending,
|
|
111
|
+
* progress,
|
|
112
|
+
* error,
|
|
113
|
+
* data: storageId,
|
|
114
|
+
* } = useConvexFileUpload(api.files.generateUploadUrl)
|
|
115
|
+
*
|
|
116
|
+
* async function handleFile(event: Event) {
|
|
117
|
+
* const input = event.target as HTMLInputElement
|
|
118
|
+
* if (!input.files?.[0]) return
|
|
119
|
+
*
|
|
120
|
+
* try {
|
|
121
|
+
* const id = await upload(input.files[0])
|
|
122
|
+
* console.log('Uploaded:', id)
|
|
123
|
+
* } catch {
|
|
124
|
+
* // error is automatically tracked
|
|
125
|
+
* }
|
|
126
|
+
* }
|
|
127
|
+
* </script>
|
|
128
|
+
*
|
|
129
|
+
* <template>
|
|
130
|
+
* <input type="file" @change="handleFile" :disabled="pending" />
|
|
131
|
+
* <div v-if="pending">Uploading: {{ progress.percent }}%</div>
|
|
132
|
+
* <p v-if="error" class="error">{{ error.message }}</p>
|
|
133
|
+
* </template>
|
|
134
|
+
* ```
|
|
135
|
+
*
|
|
136
|
+
* @example With cancel support
|
|
137
|
+
* ```vue
|
|
138
|
+
* <script setup>
|
|
139
|
+
* import { api } from '#convex/api'
|
|
140
|
+
*
|
|
141
|
+
* const { upload, pending, progress, cancel } = useConvexFileUpload(
|
|
142
|
+
* api.files.generateUploadUrl
|
|
143
|
+
* )
|
|
144
|
+
* </script>
|
|
145
|
+
*
|
|
146
|
+
* <template>
|
|
147
|
+
* <div v-if="pending">
|
|
148
|
+
* Uploading: {{ progress.percent }}%
|
|
149
|
+
* <button @click="cancel">Cancel</button>
|
|
150
|
+
* </div>
|
|
151
|
+
* </template>
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @example Saving storageId to a document
|
|
155
|
+
* ```vue
|
|
156
|
+
* <script setup>
|
|
157
|
+
* import { api } from '#convex/api'
|
|
158
|
+
*
|
|
159
|
+
* const { upload, pending, progress } = useConvexFileUpload(api.files.generateUploadUrl)
|
|
160
|
+
* const saveDocument = useConvexMutation(api.documents.create)
|
|
161
|
+
*
|
|
162
|
+
* async function handleUpload(file: File, title: string) {
|
|
163
|
+
* const storageId = await upload(file)
|
|
164
|
+
* await saveDocument({ title, fileId: storageId })
|
|
165
|
+
* }
|
|
166
|
+
* </script>
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
export declare function useConvexFileUpload<Mutation extends UploadUrlMutation>(generateUploadUrlMutation: Mutation, options?: UseConvexFileUploadOptions): UseConvexFileUploadReturn<Mutation>;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { computed, getCurrentScope, onScopeDispose, shallowRef } from "vue";
|
|
2
|
+
import { useNuxtApp } from "#imports";
|
|
3
|
+
import { ConvexCallError, normalizeConvexError } from "../errors/index.js";
|
|
4
|
+
import { readConvexRuntimeContext } from "../runtime-context.js";
|
|
5
|
+
import { assertConvexComposableScope } from "../utils/composable-scope.js";
|
|
6
|
+
import { getFunctionName } from "../utils/convex-shared.js";
|
|
7
|
+
import { createIdentityChangedError, isIdentityChangedError } from "../utils/identity-changed-error.js";
|
|
8
|
+
import { createLogger } from "../utils/logger.js";
|
|
9
|
+
import { isFileTypeAllowed } from "../utils/mime-type.js";
|
|
10
|
+
import { getConvexRuntimeConfig } from "../utils/runtime-config.js";
|
|
11
|
+
import {
|
|
12
|
+
executeFileUpload,
|
|
13
|
+
isUploadAbortError
|
|
14
|
+
} from "../utils/upload-core.js";
|
|
15
|
+
const INITIAL_UPLOAD_VIEW_STATE = {
|
|
16
|
+
status: "idle",
|
|
17
|
+
error: void 0,
|
|
18
|
+
data: void 0,
|
|
19
|
+
progress: Object.freeze({ loaded: 0, total: 0, percent: 0 })
|
|
20
|
+
};
|
|
21
|
+
export function useConvexFileUpload(generateUploadUrlMutation, options) {
|
|
22
|
+
const fnName = getFunctionName(generateUploadUrlMutation);
|
|
23
|
+
const currentScope = getCurrentScope();
|
|
24
|
+
assertConvexComposableScope("useConvexFileUpload", import.meta.client, currentScope);
|
|
25
|
+
const nuxtApp = useNuxtApp();
|
|
26
|
+
const runtime = readConvexRuntimeContext(nuxtApp);
|
|
27
|
+
const attachment = runtime?.attachment;
|
|
28
|
+
const identityObserver = attachment?.identity;
|
|
29
|
+
const logger = runtime?.logger ?? createLogger(getConvexRuntimeConfig().logging);
|
|
30
|
+
const getIdentityGeneration = () => identityObserver?.snapshot().identityGeneration ?? 0;
|
|
31
|
+
const viewState = shallowRef(INITIAL_UPLOAD_VIEW_STATE);
|
|
32
|
+
let currentAttempt = null;
|
|
33
|
+
let observedIdentityGeneration = getIdentityGeneration();
|
|
34
|
+
const status = computed(() => viewState.value.status);
|
|
35
|
+
const pending = computed(() => viewState.value.status === "pending");
|
|
36
|
+
const error = computed(() => viewState.value.error);
|
|
37
|
+
const data = computed(() => viewState.value.data);
|
|
38
|
+
const progress = computed(() => viewState.value.progress);
|
|
39
|
+
const clearUploadState = (error2 = new DOMException("Upload cancelled", "AbortError")) => {
|
|
40
|
+
const attempt = currentAttempt;
|
|
41
|
+
viewState.value = INITIAL_UPLOAD_VIEW_STATE;
|
|
42
|
+
if (currentAttempt === attempt) currentAttempt = null;
|
|
43
|
+
attempt?.abort(error2);
|
|
44
|
+
};
|
|
45
|
+
const cancel = clearUploadState;
|
|
46
|
+
if (currentScope) {
|
|
47
|
+
const stopIdentitySubscription = identityObserver?.subscribe(() => {
|
|
48
|
+
const generation = getIdentityGeneration();
|
|
49
|
+
if (generation === observedIdentityGeneration) return;
|
|
50
|
+
observedIdentityGeneration = generation;
|
|
51
|
+
clearUploadState(createIdentityChangedError("upload"));
|
|
52
|
+
});
|
|
53
|
+
onScopeDispose(() => {
|
|
54
|
+
stopIdentitySubscription?.();
|
|
55
|
+
clearUploadState();
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const upload = async (file, ...mutationArgs) => {
|
|
59
|
+
const startTime = Date.now();
|
|
60
|
+
const identityGeneration = getIdentityGeneration();
|
|
61
|
+
const identityChanged = () => getIdentityGeneration() !== identityGeneration;
|
|
62
|
+
if (viewState.value.status === "pending") {
|
|
63
|
+
const err = new ConvexCallError({
|
|
64
|
+
kind: "unknown",
|
|
65
|
+
message: "Upload already in progress for this composable instance"
|
|
66
|
+
});
|
|
67
|
+
logger.upload({
|
|
68
|
+
name: fnName,
|
|
69
|
+
event: "error",
|
|
70
|
+
filename: file.name,
|
|
71
|
+
size: file.size,
|
|
72
|
+
error: err
|
|
73
|
+
});
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
const requireCurrentIdentity = () => {
|
|
77
|
+
if (identityChanged()) throw createIdentityChangedError("upload");
|
|
78
|
+
};
|
|
79
|
+
const publishTerminalState = (next) => {
|
|
80
|
+
requireCurrentIdentity();
|
|
81
|
+
viewState.value = next;
|
|
82
|
+
requireCurrentIdentity();
|
|
83
|
+
};
|
|
84
|
+
const publishConvexError = (err) => {
|
|
85
|
+
publishTerminalState({
|
|
86
|
+
...viewState.value,
|
|
87
|
+
status: "error",
|
|
88
|
+
error: err
|
|
89
|
+
});
|
|
90
|
+
logger.upload({
|
|
91
|
+
name: fnName,
|
|
92
|
+
event: "error",
|
|
93
|
+
filename: file.name,
|
|
94
|
+
size: file.size,
|
|
95
|
+
duration: Date.now() - startTime,
|
|
96
|
+
error: err
|
|
97
|
+
});
|
|
98
|
+
requireCurrentIdentity();
|
|
99
|
+
return err;
|
|
100
|
+
};
|
|
101
|
+
const publishError = (rawError) => publishConvexError(normalizeConvexError(rawError));
|
|
102
|
+
let validationError;
|
|
103
|
+
if (options?.maxSize && file.size > options.maxSize) {
|
|
104
|
+
validationError = new ConvexCallError({
|
|
105
|
+
kind: "unknown",
|
|
106
|
+
message: `File size ${file.size} bytes exceeds maximum ${options.maxSize} bytes`
|
|
107
|
+
});
|
|
108
|
+
} else if (options?.allowedTypes && !isFileTypeAllowed(file.type, options.allowedTypes)) {
|
|
109
|
+
validationError = new ConvexCallError({
|
|
110
|
+
kind: "unknown",
|
|
111
|
+
message: `File type "${file.type}" not allowed. Allowed: ${options.allowedTypes.join(", ")}`
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (validationError) throw publishConvexError(validationError);
|
|
115
|
+
if (import.meta.server || !attachment || typeof attachment.client.mutation !== "function") {
|
|
116
|
+
throw publishConvexError(
|
|
117
|
+
new ConvexCallError({
|
|
118
|
+
kind: "unknown",
|
|
119
|
+
message: "[useConvexFileUpload] Convex client is unavailable. Upload files from the browser after configuring a Convex URL."
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const attempt = new AbortController();
|
|
124
|
+
currentAttempt = attempt;
|
|
125
|
+
const isCurrentUpload = () => currentAttempt === attempt && !identityChanged() && !attempt.signal.aborted;
|
|
126
|
+
const requireCurrentUpload = () => {
|
|
127
|
+
requireCurrentIdentity();
|
|
128
|
+
if (!isCurrentUpload()) throw new DOMException("Upload cancelled", "AbortError");
|
|
129
|
+
};
|
|
130
|
+
try {
|
|
131
|
+
requireCurrentUpload();
|
|
132
|
+
viewState.value = {
|
|
133
|
+
...viewState.value,
|
|
134
|
+
status: "pending",
|
|
135
|
+
error: void 0,
|
|
136
|
+
progress: { loaded: 0, total: file.size, percent: 0 }
|
|
137
|
+
};
|
|
138
|
+
requireCurrentUpload();
|
|
139
|
+
const storageId = await executeFileUpload(
|
|
140
|
+
attachment.client,
|
|
141
|
+
generateUploadUrlMutation,
|
|
142
|
+
mutationArgs[0] ?? {},
|
|
143
|
+
file,
|
|
144
|
+
{
|
|
145
|
+
signal: attempt.signal,
|
|
146
|
+
onProgress: (info) => {
|
|
147
|
+
if (!isCurrentUpload()) return;
|
|
148
|
+
viewState.value = {
|
|
149
|
+
...viewState.value,
|
|
150
|
+
progress: info
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
requireCurrentUpload();
|
|
156
|
+
publishTerminalState({
|
|
157
|
+
...viewState.value,
|
|
158
|
+
status: "success",
|
|
159
|
+
data: storageId
|
|
160
|
+
});
|
|
161
|
+
const duration = Date.now() - startTime;
|
|
162
|
+
logger.upload({
|
|
163
|
+
name: fnName,
|
|
164
|
+
event: "success",
|
|
165
|
+
filename: file.name,
|
|
166
|
+
size: file.size,
|
|
167
|
+
duration
|
|
168
|
+
});
|
|
169
|
+
requireCurrentIdentity();
|
|
170
|
+
return storageId;
|
|
171
|
+
} catch (e) {
|
|
172
|
+
if (identityChanged() || isIdentityChangedError(e)) {
|
|
173
|
+
if (currentAttempt === attempt) {
|
|
174
|
+
clearUploadState(createIdentityChangedError("upload"));
|
|
175
|
+
}
|
|
176
|
+
throw isIdentityChangedError(e) ? e : createIdentityChangedError("upload");
|
|
177
|
+
}
|
|
178
|
+
if (currentAttempt !== attempt) {
|
|
179
|
+
throw isUploadAbortError(e) ? e : new DOMException("Upload cancelled", "AbortError");
|
|
180
|
+
}
|
|
181
|
+
if (isUploadAbortError(e)) {
|
|
182
|
+
throw e;
|
|
183
|
+
}
|
|
184
|
+
throw publishError(e);
|
|
185
|
+
} finally {
|
|
186
|
+
if (currentAttempt === attempt) currentAttempt = null;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
upload,
|
|
191
|
+
data,
|
|
192
|
+
status,
|
|
193
|
+
pending,
|
|
194
|
+
progress,
|
|
195
|
+
error,
|
|
196
|
+
cancel
|
|
197
|
+
};
|
|
198
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type UseConvexCall, type UseConvexMutationOptions as VueMutationOptions } from '@lupinum/better-convex-vue';
|
|
2
|
+
import type { OptimisticLocalStore } from 'convex/browser';
|
|
3
|
+
import type { FunctionArgs, FunctionReference } from 'convex/server';
|
|
4
|
+
export type UseConvexMutationOptions<Args extends Record<string, unknown>> = VueMutationOptions<Args>;
|
|
5
|
+
type OptimisticUpdateCandidate<Args> = (store: OptimisticLocalStore, args: Args) => unknown;
|
|
6
|
+
type ReturnHasThen<Result> = Result extends unknown ? 'then' extends keyof Result ? true : false : never;
|
|
7
|
+
type SynchronousOptimisticUpdate<Update extends (...args: never[]) => unknown> = true extends ReturnHasThen<ReturnType<Update>> ? 'Optimistic update handlers must be synchronous' : unknown;
|
|
8
|
+
/** Nuxt auto-import facade over the one shared Vue callable lifecycle. */
|
|
9
|
+
export declare function useConvexMutation<Mutation extends FunctionReference<'mutation'>>(mutation: Mutation, options?: UseConvexMutationOptions<FunctionArgs<Mutation>>): UseConvexCall<Mutation>;
|
|
10
|
+
export declare function useConvexMutation<Mutation extends FunctionReference<'mutation'>, Update extends OptimisticUpdateCandidate<FunctionArgs<Mutation>>>(mutation: Mutation, options: Readonly<{
|
|
11
|
+
optimisticUpdate: Update;
|
|
12
|
+
}> & SynchronousOptimisticUpdate<Update>): UseConvexCall<Mutation>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useConvexMutation as useVueConvexMutation
|
|
3
|
+
} from "@lupinum/better-convex-vue";
|
|
4
|
+
import { getFunctionName } from "convex/server";
|
|
5
|
+
import { useNuxtApp } from "#imports";
|
|
6
|
+
import { readConvexRuntimeContext } from "../runtime-context.js";
|
|
7
|
+
import { createCallableDevtoolsEvents } from "../utils/callable-devtools.js";
|
|
8
|
+
import { CALLABLE_OBSERVER_KEY } from "../utils/callable-observer.js";
|
|
9
|
+
export function useConvexMutation(mutation, options) {
|
|
10
|
+
const runtime = readConvexRuntimeContext(useNuxtApp());
|
|
11
|
+
const events = createCallableDevtoolsEvents(
|
|
12
|
+
{
|
|
13
|
+
operation: "mutation",
|
|
14
|
+
fnName: getFunctionName(mutation),
|
|
15
|
+
hasOptimisticUpdate: Boolean(options?.optimisticUpdate),
|
|
16
|
+
getSink: () => runtime?.getDevtoolsSink() ?? null
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
const internalOptions = {
|
|
20
|
+
...options,
|
|
21
|
+
[CALLABLE_OBSERVER_KEY]: events
|
|
22
|
+
};
|
|
23
|
+
return useVueConvexMutation(mutation, internalOptions);
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type PaginatedQueryArgs, type PaginatedQueryItem, type PaginatedQueryReference, type UseConvexPaginatedQueryOptions, type UseConvexPaginatedQueryState } from '@lupinum/better-convex-vue';
|
|
2
|
+
import { type MaybeRefOrGetter } from 'vue';
|
|
3
|
+
export type { PaginatedQueryArgs, PaginatedQueryItem, PaginatedQueryReference, UseConvexPaginatedQueryState, };
|
|
4
|
+
export interface UseNuxtConvexPaginatedQueryOptions extends UseConvexPaginatedQueryOptions {
|
|
5
|
+
readonly server?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export type NuxtConvexPaginatedQuery<Item> = UseConvexPaginatedQueryState<Item> & Promise<UseConvexPaginatedQueryState<Item>>;
|
|
8
|
+
interface BuildConvexPaginatedQueryResult<Item> {
|
|
9
|
+
resultData: UseConvexPaginatedQueryState<Item>;
|
|
10
|
+
resolvePromise: Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createConvexPaginatedQueryState<Query extends PaginatedQueryReference>(query: Query, args: MaybeRefOrGetter<PaginatedQueryArgs<Query> | 'skip'>, options: UseNuxtConvexPaginatedQueryOptions, resolveImmediately?: boolean): BuildConvexPaginatedQueryResult<PaginatedQueryItem<Query>>;
|
|
13
|
+
export declare function useConvexPaginatedQuery<Query extends PaginatedQueryReference>(query: Query, args: MaybeRefOrGetter<PaginatedQueryArgs<Query> | 'skip'>, options: UseNuxtConvexPaginatedQueryOptions): NuxtConvexPaginatedQuery<PaginatedQueryItem<Query>>;
|