nuxt-convex-module 0.14.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.
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-convex-module/_nuxt/CtC_CmOY.js"}}</script><link rel="stylesheet" href="/__nuxt-convex-module/_nuxt/entry.jOWrhpYd.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-convex-module/_nuxt/CtC_CmOY.js"><script type="module" src="/__nuxt-convex-module/_nuxt/CtC_CmOY.js" crossorigin></script><link rel="prefetch" as="script" crossorigin href="/__nuxt-convex-module/_nuxt/C-J9qZjr.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-convex-module",buildId:"168fd639-55a2-4ae2-9c90-a285b0720204",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1794180177669,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-convex-module/_nuxt/CtC_CmOY.js"}}</script><link rel="stylesheet" href="/__nuxt-convex-module/_nuxt/entry.jOWrhpYd.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-convex-module/_nuxt/CtC_CmOY.js"><script type="module" src="/__nuxt-convex-module/_nuxt/CtC_CmOY.js" crossorigin></script><link rel="prefetch" as="script" crossorigin href="/__nuxt-convex-module/_nuxt/C-J9qZjr.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-convex-module",buildId:"7121d13f-7e15-4436-95a8-70fef1a171ce",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1794230621568,false]</script></body></html>
package/dist/module.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "compatibility": {
6
6
  "nuxt": ">=4.6.0"
7
7
  },
8
- "version": "0.14.0",
8
+ "version": "0.14.1",
9
9
  "builder": {
10
10
  "@nuxt/module-builder": "1.0.3",
11
11
  "unbuild": "unknown"
@@ -1,4 +1,4 @@
1
- import { loadAuthClient, onAuthClient } from "./auth-client-loader.js";
1
+ import { loadAuthClient } from "./auth-client-loader.js";
2
2
  const normalizePathname = (path) => {
3
3
  const slashed = path.startsWith("/") ? path : `/${path}`;
4
4
  let end = slashed.length;
@@ -18,18 +18,7 @@ export async function consumeCrossDomainOneTimeToken(options = {}) {
18
18
  const authClient = await loadAuthClient().catch(() => loadAuthClient()).catch((error) => {
19
19
  console.warn("[nuxt-convex-module] Failed to load the Better Auth client:", error);
20
20
  });
21
- if (!authClient) {
22
- onAuthClient((client) => void exchangeKeptToken(client, token, url, options));
23
- return;
24
- }
25
- await exchangeOneTimeToken(authClient, token, url, options);
26
- }
27
- async function exchangeKeptToken(authClient, token, url, options) {
28
- const current = await Promise.resolve().then(() => authClient.getSession()).catch(() => void 0);
29
- if (!current || current.error || current.data?.session) {
30
- if (!current?.data?.session) console.warn("[nuxt-convex-module] Failed to consume cross-domain one-time token:", current?.error ?? "the session lookup failed");
31
- return;
32
- }
21
+ if (!authClient) return;
33
22
  await exchangeOneTimeToken(authClient, token, url, options);
34
23
  }
35
24
  async function exchangeOneTimeToken(authClient, token, url, options) {
@@ -20,7 +20,13 @@ function name(error, prefix) {
20
20
  if (error.message !== `${prefix}${original}`) return;
21
21
  unnamed.set(error, { message: original, stack });
22
22
  const header = `${error.name}: ${original}`;
23
- if (original && stack?.startsWith(header)) error.stack = `${error.name}: ${error.message}${stack.slice(header.length)}`;
23
+ if (original && stack?.startsWith(header)) setStack(error, `${error.name}: ${error.message}${stack.slice(header.length)}`);
24
+ }
25
+ function setStack(error, stack) {
26
+ try {
27
+ error.stack = stack;
28
+ } catch {
29
+ }
24
30
  }
25
31
  export function withoutFunctionName(error, read) {
26
32
  const before = error instanceof Error ? unnamed.get(error) : void 0;
@@ -28,11 +34,11 @@ export function withoutFunctionName(error, read) {
28
34
  const named = error;
29
35
  const { message, stack } = named;
30
36
  named.message = before.message;
31
- named.stack = before.stack;
37
+ setStack(named, before.stack);
32
38
  try {
33
39
  return read(error);
34
40
  } finally {
35
41
  named.message = message;
36
- named.stack = stack;
42
+ setStack(named, stack);
37
43
  }
38
44
  }
@@ -91,7 +91,10 @@ export interface UseUploadQueueOptions {
91
91
  onItemSuccess?: (storageId: StorageId, item: UploadQueueItem) => void | Promise<void>;
92
92
  /** Called when an individual item fails or is refused (`item.refused` says which). */
93
93
  onItemError?: (error: Error, item: UploadQueueItem) => void;
94
- /** Called once every queued item has settled (succeeded or failed). */
94
+ /**
95
+ * Called once every queued item has settled (succeeded or failed), after
96
+ * every `onItemSuccess` has returned.
97
+ */
95
98
  onComplete?: (items: UploadQueueItem[]) => void;
96
99
  }
97
100
  /** Accepted inputs to {@link VueUploadQueue.enqueue}. @public */
@@ -114,11 +117,17 @@ export interface VueUploadQueue {
114
117
  pendingCount: Readonly<Ref<number>>;
115
118
  /** Number of items currently uploading. */
116
119
  activeCount: Readonly<Ref<number>>;
117
- /** Abort all in-flight uploads (queued items stay `pending`). */
120
+ /**
121
+ * Abort all in-flight uploads. Queued items stay `pending` until the next
122
+ * `enqueue` or `retry()`, which start them again.
123
+ */
118
124
  cancel: () => void;
119
125
  /** Remove an item by id, aborting it first if it is uploading. */
120
126
  remove: (id: string) => void;
121
- /** Abort everything and empty the queue. */
127
+ /**
128
+ * Abort everything and empty the queue. Once the aborted uploads end,
129
+ * `onComplete` gets `[]`, unless files were queued since.
130
+ */
122
131
  clear: () => void;
123
132
  /**
124
133
  * Queue an errored item again, or every errored item without an id. It
@@ -19,6 +19,10 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
19
19
  const controllers = /* @__PURE__ */ new Map();
20
20
  const afterDone = /* @__PURE__ */ new Set();
21
21
  const resend = /* @__PURE__ */ new Set();
22
+ let running = 0;
23
+ let generation = 0;
24
+ let cutOff = 0;
25
+ let held = false;
22
26
  const activeCount = computed(
23
27
  () => items.value.filter((item) => item.status === "uploading").length
24
28
  );
@@ -33,11 +37,9 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
33
37
  });
34
38
  function pump() {
35
39
  if (typeof XMLHttpRequest === "undefined") return;
36
- let slots = concurrency - activeCount.value;
37
40
  for (const item of items.value) {
38
- if (slots <= 0) break;
41
+ if (held || activeCount.value >= concurrency) break;
39
42
  if (item.status !== "pending") continue;
40
- slots--;
41
43
  void run(item);
42
44
  }
43
45
  }
@@ -80,6 +82,8 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
80
82
  options.onItemError?.(failure, item);
81
83
  }
82
84
  async function run(item) {
85
+ const own = generation;
86
+ running++;
83
87
  item.status = "uploading";
84
88
  const controller = new AbortController();
85
89
  controllers.set(item.id, controller);
@@ -89,8 +93,8 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
89
93
  if (options.after && !afterDone.has(item.id)) {
90
94
  item.stage = "after";
91
95
  await options.after(storageId, item, signal);
92
- signal.throwIfAborted();
93
96
  afterDone.add(item.id);
97
+ signal.throwIfAborted();
94
98
  }
95
99
  item.stage = null;
96
100
  item.status = "success";
@@ -98,11 +102,16 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
98
102
  } catch (caught) {
99
103
  fail(item, caught, signal);
100
104
  } finally {
101
- if (controllers.get(item.id) === controller) controllers.delete(item.id);
102
- if (pendingCount.value === 0 && activeCount.value === 0) {
103
- options.onComplete?.(items.value);
105
+ if (own !== generation) {
106
+ if (--cutOff === 0 && items.value.length === 0) options.onComplete?.([]);
104
107
  } else {
105
- pump();
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
+ }
106
115
  }
107
116
  }
108
117
  }
@@ -122,9 +131,11 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
122
131
  prepared: null
123
132
  }))
124
133
  );
134
+ held = false;
125
135
  pump();
126
136
  }
127
137
  function cancel() {
138
+ held = true;
128
139
  for (const controller of controllers.values()) {
129
140
  controller.abort();
130
141
  }
@@ -135,6 +146,7 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
135
146
  afterDone.delete(id);
136
147
  resend.delete(id);
137
148
  items.value = items.value.filter((item) => item.id !== id);
149
+ pump();
138
150
  }
139
151
  function retry(id) {
140
152
  for (const item of items.value) {
@@ -145,10 +157,14 @@ export function useUploadQueue(generateUploadUrl, options = {}) {
145
157
  if (resend.delete(item.id)) item.storageId = null;
146
158
  if (item.storageId === null) item.progress = 0;
147
159
  }
160
+ held = false;
148
161
  pump();
149
162
  }
150
163
  function clear() {
151
164
  cancel();
165
+ generation++;
166
+ cutOff += running;
167
+ running = 0;
152
168
  controllers.clear();
153
169
  afterDone.clear();
154
170
  resend.clear();
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.14.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",