nuxt-convex-module 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/devtools-client/index.html +1 -1
- package/dist/module.d.mts +18 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +120 -36
- package/dist/runtime/better-auth/nuxt/middleware.js +8 -2
- package/dist/runtime/better-auth/nuxt/no-session-vary.d.ts +38 -0
- package/dist/runtime/better-auth/nuxt/no-session-vary.js +21 -0
- package/dist/runtime/better-auth/nuxt/server.js +2 -1
- package/dist/runtime/better-auth/nuxt/shared-render.d.ts +9 -0
- package/dist/runtime/better-auth/nuxt/shared-render.js +17 -0
- package/dist/runtime/better-auth/vue/auth-client-loader.d.ts +17 -0
- package/dist/runtime/better-auth/vue/auth-client-loader.js +186 -0
- package/dist/runtime/better-auth/vue/cross-domain.d.ts +2 -2
- package/dist/runtime/better-auth/vue/cross-domain.js +41 -35
- package/dist/runtime/better-auth/vue/index.d.ts +1 -0
- package/dist/runtime/better-auth/vue/index.js +1 -0
- package/dist/runtime/better-auth/vue/plugin.client.js +21 -2
- package/dist/runtime/better-auth/vue/plugin.server.js +23 -3
- package/dist/runtime/better-auth/vue/token-store.js +4 -0
- package/dist/runtime/better-auth/vue/use-better-auth.d.ts +7 -1
- package/dist/runtime/better-auth/vue/use-better-auth.js +78 -6
- package/dist/runtime/nuxt/function-name.d.ts +9 -0
- package/dist/runtime/nuxt/function-name.js +44 -0
- package/dist/runtime/nuxt/index.js +4 -3
- package/dist/runtime/nuxt/testing.d.ts +21 -0
- package/dist/runtime/nuxt/testing.js +1 -0
- package/dist/runtime/vue/composables/use-upload-queue.d.ts +82 -6
- package/dist/runtime/vue/composables/use-upload-queue.js +96 -25
- package/dist/runtime/vue/index.d.ts +1 -1
- package/package.json +8 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ConvexError } from "convex/values";
|
|
2
|
+
import { computed, ref, toRaw } from "vue";
|
|
2
3
|
import { useConvexOrThrow } from "../client.js";
|
|
3
4
|
import { uploadFile } from "./use-upload.js";
|
|
4
5
|
function normalizeFiles(input) {
|
|
@@ -16,6 +17,12 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
|
|
|
16
17
|
const concurrency = Math.max(1, Math.floor(options.concurrency ?? 3));
|
|
17
18
|
const items = ref([]);
|
|
18
19
|
const controllers = /* @__PURE__ */ new Map();
|
|
20
|
+
const afterDone = /* @__PURE__ */ new Set();
|
|
21
|
+
const resend = /* @__PURE__ */ new Set();
|
|
22
|
+
let running = 0;
|
|
23
|
+
let generation = 0;
|
|
24
|
+
let cutOff = 0;
|
|
25
|
+
let held = false;
|
|
19
26
|
const activeCount = computed(
|
|
20
27
|
() => items.value.filter((item) => item.status === "uploading").length
|
|
21
28
|
);
|
|
@@ -30,43 +37,81 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
|
|
|
30
37
|
});
|
|
31
38
|
function pump() {
|
|
32
39
|
if (typeof XMLHttpRequest === "undefined") return;
|
|
33
|
-
let slots = concurrency - activeCount.value;
|
|
34
40
|
for (const item of items.value) {
|
|
35
|
-
if (
|
|
41
|
+
if (held || activeCount.value >= concurrency) break;
|
|
36
42
|
if (item.status !== "pending") continue;
|
|
37
|
-
slots--;
|
|
38
43
|
void run(item);
|
|
39
44
|
}
|
|
40
45
|
}
|
|
46
|
+
const isRefusal = options.isRefusal ?? ((error) => error instanceof ConvexError);
|
|
47
|
+
async function transfer(item, signal) {
|
|
48
|
+
if (options.prepare && item.prepared === null) {
|
|
49
|
+
item.stage = "prepare";
|
|
50
|
+
const prepared = await options.prepare(toRaw(item.file), item, signal);
|
|
51
|
+
signal.throwIfAborted();
|
|
52
|
+
item.prepared = prepared;
|
|
53
|
+
}
|
|
54
|
+
item.stage = "upload";
|
|
55
|
+
const url = await convex.mutation(generateUploadUrl, {});
|
|
56
|
+
const storageId = await uploadFile({
|
|
57
|
+
url,
|
|
58
|
+
// The blob itself, not a reactive proxy of it, wherever Vue would wrap one.
|
|
59
|
+
file: toRaw(item.prepared ?? item.file),
|
|
60
|
+
signal,
|
|
61
|
+
onProgress: (value) => {
|
|
62
|
+
item.progress = value;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
item.progress = 1;
|
|
66
|
+
return storageId;
|
|
67
|
+
}
|
|
68
|
+
function refusal(failure, item) {
|
|
69
|
+
try {
|
|
70
|
+
return isRefusal(failure, item);
|
|
71
|
+
} catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function fail(item, caught, signal) {
|
|
76
|
+
const failure = caught instanceof Error ? caught : new Error(String(caught));
|
|
77
|
+
item.refused = !signal.aborted && refusal(failure, item);
|
|
78
|
+
if (item.refused && item.stage === "after") resend.add(item.id);
|
|
79
|
+
item.stage = null;
|
|
80
|
+
item.error = failure;
|
|
81
|
+
item.status = "error";
|
|
82
|
+
options.onItemError?.(failure, item);
|
|
83
|
+
}
|
|
41
84
|
async function run(item) {
|
|
85
|
+
const own = generation;
|
|
86
|
+
running++;
|
|
42
87
|
item.status = "uploading";
|
|
43
88
|
const controller = new AbortController();
|
|
44
89
|
controllers.set(item.id, controller);
|
|
90
|
+
const { signal } = controller;
|
|
45
91
|
try {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
55
|
-
item.storageId = storageId;
|
|
56
|
-
item.progress = 1;
|
|
92
|
+
const storageId = item.storageId ??= await transfer(item, signal);
|
|
93
|
+
if (options.after && !afterDone.has(item.id)) {
|
|
94
|
+
item.stage = "after";
|
|
95
|
+
await options.after(storageId, item, signal);
|
|
96
|
+
afterDone.add(item.id);
|
|
97
|
+
signal.throwIfAborted();
|
|
98
|
+
}
|
|
99
|
+
item.stage = null;
|
|
57
100
|
item.status = "success";
|
|
58
101
|
await options.onItemSuccess?.(storageId, item);
|
|
59
102
|
} catch (caught) {
|
|
60
|
-
|
|
61
|
-
item.error = failure;
|
|
62
|
-
item.status = "error";
|
|
63
|
-
options.onItemError?.(failure, item);
|
|
103
|
+
fail(item, caught, signal);
|
|
64
104
|
} finally {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
options.onComplete?.(items.value);
|
|
105
|
+
if (own !== generation) {
|
|
106
|
+
if (--cutOff === 0 && items.value.length === 0) options.onComplete?.([]);
|
|
68
107
|
} else {
|
|
69
|
-
|
|
108
|
+
running--;
|
|
109
|
+
if (controllers.get(item.id) === controller) controllers.delete(item.id);
|
|
110
|
+
if (pendingCount.value === 0 && running === 0) {
|
|
111
|
+
options.onComplete?.(items.value);
|
|
112
|
+
} else if (!signal.aborted) {
|
|
113
|
+
pump();
|
|
114
|
+
}
|
|
70
115
|
}
|
|
71
116
|
}
|
|
72
117
|
}
|
|
@@ -80,12 +125,17 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
|
|
|
80
125
|
status: "pending",
|
|
81
126
|
progress: 0,
|
|
82
127
|
storageId: null,
|
|
83
|
-
error: null
|
|
128
|
+
error: null,
|
|
129
|
+
refused: false,
|
|
130
|
+
stage: null,
|
|
131
|
+
prepared: null
|
|
84
132
|
}))
|
|
85
133
|
);
|
|
134
|
+
held = false;
|
|
86
135
|
pump();
|
|
87
136
|
}
|
|
88
137
|
function cancel() {
|
|
138
|
+
held = true;
|
|
89
139
|
for (const controller of controllers.values()) {
|
|
90
140
|
controller.abort();
|
|
91
141
|
}
|
|
@@ -93,11 +143,31 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
|
|
|
93
143
|
function remove(id) {
|
|
94
144
|
controllers.get(id)?.abort();
|
|
95
145
|
controllers.delete(id);
|
|
146
|
+
afterDone.delete(id);
|
|
147
|
+
resend.delete(id);
|
|
96
148
|
items.value = items.value.filter((item) => item.id !== id);
|
|
149
|
+
pump();
|
|
150
|
+
}
|
|
151
|
+
function retry(id) {
|
|
152
|
+
for (const item of items.value) {
|
|
153
|
+
if (item.status !== "error" || id !== void 0 && item.id !== id) continue;
|
|
154
|
+
item.status = "pending";
|
|
155
|
+
item.error = null;
|
|
156
|
+
item.refused = false;
|
|
157
|
+
if (resend.delete(item.id)) item.storageId = null;
|
|
158
|
+
if (item.storageId === null) item.progress = 0;
|
|
159
|
+
}
|
|
160
|
+
held = false;
|
|
161
|
+
pump();
|
|
97
162
|
}
|
|
98
163
|
function clear() {
|
|
99
164
|
cancel();
|
|
165
|
+
generation++;
|
|
166
|
+
cutOff += running;
|
|
167
|
+
running = 0;
|
|
100
168
|
controllers.clear();
|
|
169
|
+
afterDone.clear();
|
|
170
|
+
resend.clear();
|
|
101
171
|
items.value = [];
|
|
102
172
|
}
|
|
103
173
|
return {
|
|
@@ -109,7 +179,8 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
|
|
|
109
179
|
activeCount,
|
|
110
180
|
cancel,
|
|
111
181
|
remove,
|
|
112
|
-
clear
|
|
182
|
+
clear,
|
|
183
|
+
retry
|
|
113
184
|
};
|
|
114
185
|
}
|
|
115
186
|
export const useConvexUploadQueue = useUploadQueue;
|
|
@@ -88,6 +88,6 @@ export type { ConnectionState, OptimisticUpdate, QueryJournal, } from 'convex/br
|
|
|
88
88
|
export type { FunctionReference, FunctionReference_future, FunctionArgs, FunctionReturnType, OptionalRestArgs, ArgsAndOptions, } from 'convex/server';
|
|
89
89
|
export type { Value } from 'convex/values';
|
|
90
90
|
export { useUpload, useConvexUpload, uploadFile, type VueUpload, type UseUploadOptions, type UploadFileOptions, type GenerateUploadUrl, type StorageId, } from './composables/use-upload.js';
|
|
91
|
-
export { useUploadQueue, useConvexUploadQueue, type VueUploadQueue, type UseUploadQueueOptions, type UploadQueueItem, type UploadItemStatus, type EnqueueInput, } from './composables/use-upload-queue.js';
|
|
91
|
+
export { useUploadQueue, useConvexUploadQueue, type VueUploadQueue, type UseUploadQueueOptions, type UploadQueueItem, type UploadItemStage, type UploadItemStatus, type EnqueueInput, } from './composables/use-upload-queue.js';
|
|
92
92
|
export { useStorageUrl, useConvexStorageUrl, type GetStorageUrl, } from './composables/use-storage-url.js';
|
|
93
93
|
export { ConvexImage } from './components/convex-image.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "nuxt-convex-module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.14.1",
|
|
5
5
|
"description": "Convex backend integration with live queries, mutations, actions, pagination, file storage and SSR, auto-imported and typed against your deployment. The same Vue client runs without Nuxt; Better Auth, Clerk, Auth0 and Polar are opt-in.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -60,6 +60,10 @@
|
|
|
60
60
|
"types": "./dist/runtime/nuxt/app.d.ts",
|
|
61
61
|
"import": "./dist/runtime/nuxt/app.js"
|
|
62
62
|
},
|
|
63
|
+
"./testing": {
|
|
64
|
+
"types": "./dist/runtime/nuxt/testing.d.ts",
|
|
65
|
+
"import": "./dist/runtime/nuxt/testing.js"
|
|
66
|
+
},
|
|
63
67
|
"./better-auth/client": {
|
|
64
68
|
"types": "./dist/runtime/better-auth/vue/index.d.ts",
|
|
65
69
|
"import": "./dist/runtime/better-auth/vue/index.js"
|
|
@@ -115,6 +119,9 @@
|
|
|
115
119
|
"app": [
|
|
116
120
|
"./dist/runtime/nuxt/app.d.ts"
|
|
117
121
|
],
|
|
122
|
+
"testing": [
|
|
123
|
+
"./dist/runtime/nuxt/testing.d.ts"
|
|
124
|
+
],
|
|
118
125
|
"better-auth/client": [
|
|
119
126
|
"./dist/runtime/better-auth/vue/index.d.ts"
|
|
120
127
|
],
|