nuxt-convex-module 0.0.0

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.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +242 -0
  3. package/dist/chunks/index.mjs +64 -0
  4. package/dist/devtools-client/200.html +1 -0
  5. package/dist/devtools-client/404.html +1 -0
  6. package/dist/devtools-client/_nuxt/B29GGJ5n.js +1 -0
  7. package/dist/devtools-client/_nuxt/BSDEpQet.js +1 -0
  8. package/dist/devtools-client/_nuxt/BY23OQOo.js +1 -0
  9. package/dist/devtools-client/_nuxt/BZYRaL-G.js +1 -0
  10. package/dist/devtools-client/_nuxt/Byw6FxnC.js +1 -0
  11. package/dist/devtools-client/_nuxt/CJJ_hcZN.js +1 -0
  12. package/dist/devtools-client/_nuxt/CS6WMFOx.js +2 -0
  13. package/dist/devtools-client/_nuxt/CZbAGcNC.js +1 -0
  14. package/dist/devtools-client/_nuxt/Cr6_aklh.js +2 -0
  15. package/dist/devtools-client/_nuxt/DNfpyBVU.js +3 -0
  16. package/dist/devtools-client/_nuxt/DPWXUmcI.js +1 -0
  17. package/dist/devtools-client/_nuxt/builds/latest.json +1 -0
  18. package/dist/devtools-client/_nuxt/builds/meta/a7708498-bd09-4de2-b5ab-19b380293c77.json +1 -0
  19. package/dist/devtools-client/_nuxt/dy_xXcv9.js +1 -0
  20. package/dist/devtools-client/_nuxt/entry.DbTJhkHT.css +1 -0
  21. package/dist/devtools-client/_nuxt/error-404.CwGGO2Kz.css +1 -0
  22. package/dist/devtools-client/_nuxt/error-500.8ZJqCQm8.css +1 -0
  23. package/dist/devtools-client/_nuxt/ncgEdbEt.js +1 -0
  24. package/dist/devtools-client/_nuxt/queries.CE_dtt9-.css +1 -0
  25. package/dist/devtools-client/auth/index.html +1 -0
  26. package/dist/devtools-client/icon.svg +6 -0
  27. package/dist/devtools-client/index.html +1 -0
  28. package/dist/devtools-client/logs/index.html +1 -0
  29. package/dist/devtools-client/queries/index.html +1 -0
  30. package/dist/module.d.ts +189 -0
  31. package/dist/module.js +489 -0
  32. package/dist/module.json +13 -0
  33. package/dist/runtime/auth0/vue/index.d.ts +58 -0
  34. package/dist/runtime/auth0/vue/index.js +33 -0
  35. package/dist/runtime/better-auth/nuxt/middleware.d.ts +14 -0
  36. package/dist/runtime/better-auth/nuxt/middleware.js +39 -0
  37. package/dist/runtime/better-auth/nuxt/proxy.d.ts +6 -0
  38. package/dist/runtime/better-auth/nuxt/proxy.js +11 -0
  39. package/dist/runtime/better-auth/nuxt/server.d.ts +106 -0
  40. package/dist/runtime/better-auth/nuxt/server.js +123 -0
  41. package/dist/runtime/better-auth/vue/auth-boundary.d.ts +131 -0
  42. package/dist/runtime/better-auth/vue/auth-boundary.js +78 -0
  43. package/dist/runtime/better-auth/vue/client.d.ts +358 -0
  44. package/dist/runtime/better-auth/vue/client.js +5 -0
  45. package/dist/runtime/better-auth/vue/cross-domain.d.ts +39 -0
  46. package/dist/runtime/better-auth/vue/cross-domain.js +45 -0
  47. package/dist/runtime/better-auth/vue/hydration.d.ts +20 -0
  48. package/dist/runtime/better-auth/vue/hydration.js +52 -0
  49. package/dist/runtime/better-auth/vue/index.d.ts +12 -0
  50. package/dist/runtime/better-auth/vue/index.js +6 -0
  51. package/dist/runtime/better-auth/vue/plugin.client.d.ts +6 -0
  52. package/dist/runtime/better-auth/vue/plugin.client.js +32 -0
  53. package/dist/runtime/better-auth/vue/plugin.server.d.ts +24 -0
  54. package/dist/runtime/better-auth/vue/plugin.server.js +42 -0
  55. package/dist/runtime/better-auth/vue/use-auth.d.ts +92 -0
  56. package/dist/runtime/better-auth/vue/use-auth.js +82 -0
  57. package/dist/runtime/clerk/vue/index.d.ts +81 -0
  58. package/dist/runtime/clerk/vue/index.js +49 -0
  59. package/dist/runtime/devtools/bridge.d.ts +12 -0
  60. package/dist/runtime/devtools/bridge.js +191 -0
  61. package/dist/runtime/devtools/plugin.client.d.ts +8 -0
  62. package/dist/runtime/devtools/plugin.client.js +34 -0
  63. package/dist/runtime/devtools/types.d.ts +78 -0
  64. package/dist/runtime/devtools/types.js +0 -0
  65. package/dist/runtime/nuxt/composables/use-async-query.d.ts +144 -0
  66. package/dist/runtime/nuxt/composables/use-async-query.js +104 -0
  67. package/dist/runtime/nuxt/config.d.ts +7 -0
  68. package/dist/runtime/nuxt/config.js +12 -0
  69. package/dist/runtime/nuxt/index.d.ts +136 -0
  70. package/dist/runtime/nuxt/index.js +91 -0
  71. package/dist/runtime/polar/vue/components.d.ts +184 -0
  72. package/dist/runtime/polar/vue/components.js +115 -0
  73. package/dist/runtime/vue/auth/helpers.d.ts +67 -0
  74. package/dist/runtime/vue/auth/helpers.js +50 -0
  75. package/dist/runtime/vue/auth/index.d.ts +125 -0
  76. package/dist/runtime/vue/auth/index.js +97 -0
  77. package/dist/runtime/vue/client.d.ts +305 -0
  78. package/dist/runtime/vue/client.js +382 -0
  79. package/dist/runtime/vue/composables/use-action.d.ts +62 -0
  80. package/dist/runtime/vue/composables/use-action.js +13 -0
  81. package/dist/runtime/vue/composables/use-connection-state.d.ts +30 -0
  82. package/dist/runtime/vue/composables/use-connection-state.js +14 -0
  83. package/dist/runtime/vue/composables/use-mutation.d.ts +76 -0
  84. package/dist/runtime/vue/composables/use-mutation.js +34 -0
  85. package/dist/runtime/vue/composables/use-paginated-query.d.ts +132 -0
  86. package/dist/runtime/vue/composables/use-paginated-query.js +513 -0
  87. package/dist/runtime/vue/composables/use-queries.d.ts +62 -0
  88. package/dist/runtime/vue/composables/use-queries.js +37 -0
  89. package/dist/runtime/vue/composables/use-query.d.ts +87 -0
  90. package/dist/runtime/vue/composables/use-query.js +53 -0
  91. package/dist/runtime/vue/composables/use-storage-url.d.ts +46 -0
  92. package/dist/runtime/vue/composables/use-storage-url.js +9 -0
  93. package/dist/runtime/vue/composables/use-subscription.d.ts +15 -0
  94. package/dist/runtime/vue/composables/use-subscription.js +33 -0
  95. package/dist/runtime/vue/composables/use-upload-queue.d.ts +117 -0
  96. package/dist/runtime/vue/composables/use-upload-queue.js +115 -0
  97. package/dist/runtime/vue/composables/use-upload.d.ts +134 -0
  98. package/dist/runtime/vue/composables/use-upload.js +114 -0
  99. package/dist/runtime/vue/hydration.d.ts +66 -0
  100. package/dist/runtime/vue/hydration.js +46 -0
  101. package/dist/runtime/vue/index.d.ts +94 -0
  102. package/dist/runtime/vue/index.js +42 -0
  103. package/dist/runtime/vue/plugin.d.ts +18 -0
  104. package/dist/runtime/vue/plugin.js +16 -0
  105. package/dist/runtime/vue/provide.d.ts +39 -0
  106. package/dist/runtime/vue/provide.js +15 -0
  107. package/dist/runtime/vue/queries-observer.d.ts +41 -0
  108. package/dist/runtime/vue/queries-observer.js +126 -0
  109. package/dist/types.d.ts +3 -0
  110. package/package.json +233 -0
@@ -0,0 +1,358 @@
1
+ export declare const authClient: import("better-auth/vue").VueAuthClient<{
2
+ plugins: {
3
+ id: "convex";
4
+ version: string;
5
+ $InferServerPlugin: ReturnType<(opts: {
6
+ authConfig: import("convex/server").AuthConfig;
7
+ jwt?: {
8
+ expirationSeconds?: number;
9
+ definePayload?: (session: {
10
+ user: import("better-auth").User & Record<string, any>;
11
+ session: import("better-auth").Session & Record<string, any>;
12
+ }) => Promise<Record<string, any>> | Record<string, any> | undefined;
13
+ };
14
+ jwtExpirationSeconds?: number;
15
+ jwks?: string;
16
+ jwksRotateOnTokenGenerationError?: boolean;
17
+ options?: import("better-auth").BetterAuthOptions;
18
+ }) => {
19
+ id: "convex";
20
+ version: string;
21
+ init: (ctx: import("better-auth").AuthContext) => void;
22
+ hooks: {
23
+ before: ({
24
+ matcher(context: import("better-auth").HookEndpointContext): boolean;
25
+ handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
26
+ context: {
27
+ headers: Headers;
28
+ };
29
+ } | undefined>;
30
+ } | {
31
+ matcher: (ctx: import("better-auth").HookEndpointContext) => boolean;
32
+ handler: (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
33
+ context: import("better-auth").MiddlewareContext<import("better-auth").MiddlewareOptions, {
34
+ returned?: unknown | undefined;
35
+ responseHeaders?: Headers | undefined;
36
+ } & import("better-auth").PluginContext<import("better-auth").BetterAuthOptions> & import("better-auth").InfoContext & {
37
+ options: import("better-auth").BetterAuthOptions;
38
+ trustedOrigins: string[];
39
+ trustedProviders: string[];
40
+ isTrustedOrigin: (url: string, settings?: {
41
+ allowRelativePaths: boolean;
42
+ }) => boolean;
43
+ oauthConfig: {
44
+ skipStateCookieCheck?: boolean | undefined;
45
+ storeStateStrategy: "database" | "cookie";
46
+ };
47
+ newSession: {
48
+ session: {
49
+ id: string;
50
+ createdAt: Date;
51
+ updatedAt: Date;
52
+ userId: string;
53
+ expiresAt: Date;
54
+ token: string;
55
+ ipAddress?: string | null | undefined;
56
+ userAgent?: string | null | undefined;
57
+ } & Record<string, any>;
58
+ user: {
59
+ id: string;
60
+ createdAt: Date;
61
+ updatedAt: Date;
62
+ email: string;
63
+ emailVerified: boolean;
64
+ name: string;
65
+ image?: string | null | undefined;
66
+ } & Record<string, any>;
67
+ } | null;
68
+ session: {
69
+ session: {
70
+ id: string;
71
+ createdAt: Date;
72
+ updatedAt: Date;
73
+ userId: string;
74
+ expiresAt: Date;
75
+ token: string;
76
+ ipAddress?: string | null | undefined;
77
+ userAgent?: string | null | undefined;
78
+ } & Record<string, any>;
79
+ user: {
80
+ id: string;
81
+ createdAt: Date;
82
+ updatedAt: Date;
83
+ email: string;
84
+ emailVerified: boolean;
85
+ name: string;
86
+ image?: string | null | undefined;
87
+ } & Record<string, any>;
88
+ } | null;
89
+ setNewSession: (session: {
90
+ session: {
91
+ id: string;
92
+ createdAt: Date;
93
+ updatedAt: Date;
94
+ userId: string;
95
+ expiresAt: Date;
96
+ token: string;
97
+ ipAddress?: string | null | undefined;
98
+ userAgent?: string | null | undefined;
99
+ } & Record<string, any>;
100
+ user: {
101
+ id: string;
102
+ createdAt: Date;
103
+ updatedAt: Date;
104
+ email: string;
105
+ emailVerified: boolean;
106
+ name: string;
107
+ image?: string | null | undefined;
108
+ } & Record<string, any>;
109
+ } | null) => void;
110
+ socialProviders: import("better-auth").OAuthProvider[];
111
+ authCookies: import("better-auth").BetterAuthCookies;
112
+ logger: ReturnType<(options?: import("better-auth").Logger | undefined) => import("better-auth").InternalLogger>;
113
+ rateLimit: {
114
+ enabled: boolean;
115
+ window: number;
116
+ max: number;
117
+ storage: "memory" | "database" | "secondary-storage";
118
+ } & Omit<import("better-auth").BetterAuthRateLimitOptions, "enabled" | "window" | "max" | "storage">;
119
+ adapter: import("better-auth").DBAdapter<import("better-auth").BetterAuthOptions>;
120
+ internalAdapter: import("better-auth").InternalAdapter<import("better-auth").BetterAuthOptions>;
121
+ createAuthCookie: (cookieName: string, overrideAttributes?: Partial<import("better-auth").CookieOptions> | undefined) => import("better-auth").BetterAuthCookie;
122
+ secret: string;
123
+ secretConfig: string | import("better-auth").SecretConfig;
124
+ sessionConfig: {
125
+ updateAge: number;
126
+ expiresIn: number;
127
+ freshAge: number;
128
+ cookieRefreshCache: false | {
129
+ enabled: true;
130
+ updateAge: number;
131
+ };
132
+ };
133
+ generateId: (options: {
134
+ model: import("better-auth").ModelNames;
135
+ size?: number | undefined;
136
+ }) => string | false;
137
+ secondaryStorage: import("better-auth").SecondaryStorage | undefined;
138
+ password: {
139
+ hash: (password: string) => Promise<string>;
140
+ verify: (data: {
141
+ password: string;
142
+ hash: string;
143
+ }) => Promise<boolean>;
144
+ config: {
145
+ minPasswordLength: number;
146
+ maxPasswordLength: number;
147
+ };
148
+ checkPassword: (userId: string, ctx: import("better-auth").GenericEndpointContext<import("better-auth").BetterAuthOptions>) => Promise<boolean>;
149
+ };
150
+ tables: import("better-auth").BetterAuthDBSchema;
151
+ runMigrations: () => Promise<void>;
152
+ publishTelemetry: (event: {
153
+ type: string;
154
+ anonymousId?: string | undefined;
155
+ payload: Record<string, any>;
156
+ }) => Promise<void>;
157
+ skipOriginCheck: boolean | string[];
158
+ skipCSRFCheck: boolean;
159
+ runInBackground: (promise: Promise<unknown>) => void;
160
+ runInBackgroundOrAwait: (promise: Promise<unknown> | void) => import("better-auth").Awaitable<unknown>;
161
+ }>;
162
+ }>;
163
+ })[];
164
+ after: {
165
+ matcher: (context: import("better-auth").HookEndpointContext) => boolean;
166
+ handler: import("better-auth/api").AuthMiddleware;
167
+ }[];
168
+ };
169
+ endpoints: {
170
+ getOpenIdConfig: import("better-auth").StrictEndpoint<"/convex/.well-known/openid-configuration", {
171
+ method: "GET";
172
+ metadata: {
173
+ isAction: false;
174
+ };
175
+ }, import("better-auth/plugins").OIDCMetadata>;
176
+ getJwks: import("better-auth").StrictEndpoint<"/convex/jwks", {
177
+ method: "GET";
178
+ metadata: {
179
+ openapi: {
180
+ description: string;
181
+ responses: {
182
+ "200": {
183
+ description: string;
184
+ content: {
185
+ "application/json": {
186
+ schema: {
187
+ type: "object";
188
+ properties: {
189
+ keys: {
190
+ type: string;
191
+ description: string;
192
+ items: {
193
+ type: string;
194
+ properties: {
195
+ kid: {
196
+ type: string;
197
+ description: string;
198
+ };
199
+ kty: {
200
+ type: string;
201
+ description: string;
202
+ };
203
+ alg: {
204
+ type: string;
205
+ description: string;
206
+ };
207
+ use: {
208
+ type: string;
209
+ description: string;
210
+ enum: string[];
211
+ nullable: boolean;
212
+ };
213
+ n: {
214
+ type: string;
215
+ description: string;
216
+ nullable: boolean;
217
+ };
218
+ e: {
219
+ type: string;
220
+ description: string;
221
+ nullable: boolean;
222
+ };
223
+ crv: {
224
+ type: string;
225
+ description: string;
226
+ nullable: boolean;
227
+ };
228
+ x: {
229
+ type: string;
230
+ description: string;
231
+ nullable: boolean;
232
+ };
233
+ y: {
234
+ type: string;
235
+ description: string;
236
+ nullable: boolean;
237
+ };
238
+ };
239
+ required: string[];
240
+ };
241
+ };
242
+ };
243
+ required: string[];
244
+ };
245
+ };
246
+ };
247
+ };
248
+ };
249
+ };
250
+ };
251
+ }, import("better-auth").JSONWebKeySet>;
252
+ getLatestJwks: import("better-auth").StrictEndpoint<"/convex/latest-jwks", {
253
+ isAction: boolean;
254
+ method: "POST";
255
+ metadata: {
256
+ SERVER_ONLY: true;
257
+ openapi: {
258
+ description: string;
259
+ };
260
+ };
261
+ }, any[]>;
262
+ rotateKeys: import("better-auth").StrictEndpoint<"/convex/rotate-keys", {
263
+ isAction: boolean;
264
+ method: "POST";
265
+ metadata: {
266
+ SERVER_ONLY: true;
267
+ openapi: {
268
+ description: string;
269
+ };
270
+ };
271
+ }, any[]>;
272
+ getToken: import("better-auth").StrictEndpoint<"/convex/token", {
273
+ method: "GET";
274
+ requireHeaders: true;
275
+ use: ((inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<{
276
+ session: {
277
+ session: Record<string, any> & {
278
+ id: string;
279
+ createdAt: Date;
280
+ updatedAt: Date;
281
+ userId: string;
282
+ expiresAt: Date;
283
+ token: string;
284
+ ipAddress?: string | null | undefined;
285
+ userAgent?: string | null | undefined;
286
+ };
287
+ user: Record<string, any> & {
288
+ id: string;
289
+ createdAt: Date;
290
+ updatedAt: Date;
291
+ email: string;
292
+ emailVerified: boolean;
293
+ name: string;
294
+ image?: string | null | undefined;
295
+ };
296
+ };
297
+ }>)[];
298
+ metadata: {
299
+ openapi: {
300
+ description: string;
301
+ responses: {
302
+ 200: {
303
+ description: string;
304
+ content: {
305
+ "application/json": {
306
+ schema: {
307
+ type: "object";
308
+ properties: {
309
+ token: {
310
+ type: string;
311
+ };
312
+ };
313
+ };
314
+ };
315
+ };
316
+ };
317
+ };
318
+ };
319
+ };
320
+ }, {
321
+ token: string;
322
+ }>;
323
+ };
324
+ schema: {
325
+ jwks: {
326
+ fields: {
327
+ publicKey: {
328
+ type: "string";
329
+ required: true;
330
+ };
331
+ privateKey: {
332
+ type: "string";
333
+ required: true;
334
+ };
335
+ createdAt: {
336
+ type: "date";
337
+ required: true;
338
+ };
339
+ expiresAt: {
340
+ type: "date";
341
+ required: false;
342
+ };
343
+ };
344
+ };
345
+ user: {
346
+ readonly fields: {
347
+ readonly userId: {
348
+ readonly type: "string";
349
+ readonly required: false;
350
+ readonly input: false;
351
+ };
352
+ };
353
+ };
354
+ };
355
+ }>;
356
+ }[];
357
+ }>;
358
+ export type AuthClient = typeof authClient;
@@ -0,0 +1,5 @@
1
+ import { convexClient } from "@convex-dev/better-auth/client/plugins";
2
+ import { createAuthClient } from "better-auth/vue";
3
+ export const authClient = createAuthClient({
4
+ plugins: [convexClient()]
5
+ });
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Options for {@link consumeCrossDomainOneTimeToken}.
3
+ *
4
+ * @public
5
+ */
6
+ export interface ConsumeCrossDomainOneTimeTokenOptions {
7
+ /**
8
+ * Only exchange the one-time token when the page URL matches this route
9
+ * (e.g. `'/auth/callback'`; trailing slashes ignored). On every other route
10
+ * the `ott` parameter is scrubbed from the URL but **not** exchanged.
11
+ *
12
+ * The cross-domain protocol cannot bind the token to the browser that
13
+ * started the sign-in flow (magic-link flows legitimately finish in another
14
+ * browsing context), so without this restriction a crafted
15
+ * `/any-page?ott=…` link silently signs the visitor into the link author's
16
+ * session — login CSRF. Restricting consumption to the one route your
17
+ * sign-in `callbackURL`s point at shrinks that surface to a single
18
+ * predictable URL.
19
+ *
20
+ * In Nuxt, set `convex.betterAuth.crossDomainCallbackRoute` instead — the
21
+ * client plugin forwards it here.
22
+ */
23
+ callbackRoute?: string;
24
+ }
25
+ /**
26
+ * Exchange a `?ott=...` one-time token (set by the Better Auth cross-domain
27
+ * plugin when redirecting from an auth origin) for a full session — the Vue
28
+ * port of `ConvexBetterAuthProvider`'s one-time-token `useEffect`.
29
+ *
30
+ * Safe to call unconditionally — returns early when the URL has no `ott`
31
+ * parameter or the cross-domain plugin is not installed on the auth client.
32
+ *
33
+ * The token is not bound to the browser that initiated sign-in (upstream
34
+ * design), so anyone holding a fresh token can mint a link that logs its
35
+ * visitor into *their* session — see
36
+ * {@link ConsumeCrossDomainOneTimeTokenOptions.callbackRoute} for the
37
+ * mitigation.
38
+ */
39
+ export declare function consumeCrossDomainOneTimeToken(options?: ConsumeCrossDomainOneTimeTokenOptions): Promise<void>;
@@ -0,0 +1,45 @@
1
+ import { authClient } from "#convex/auth-client";
2
+ const normalizePathname = (path) => {
3
+ const slashed = path.startsWith("/") ? path : `/${path}`;
4
+ const trimmed = slashed.replace(/\/+$/, "");
5
+ return trimmed === "" ? "/" : trimmed;
6
+ };
7
+ export async function consumeCrossDomainOneTimeToken(options = {}) {
8
+ if (typeof window === "undefined" || !window.location?.href) {
9
+ return;
10
+ }
11
+ const url = new URL(window.location.href);
12
+ const token = url.searchParams.get("ott");
13
+ if (token) {
14
+ const authClientWithCrossDomain = authClient;
15
+ url.searchParams.delete("ott");
16
+ window.history.replaceState({}, "", url);
17
+ if (!authClientWithCrossDomain.crossDomain) {
18
+ return;
19
+ }
20
+ if (options.callbackRoute && normalizePathname(url.pathname) !== normalizePathname(options.callbackRoute)) {
21
+ console.warn(
22
+ `[nuxt-convex-module] ignoring cross-domain one-time token on "${url.pathname}" \u2014 consumption is restricted to "${options.callbackRoute}" (convex.betterAuth.crossDomainCallbackRoute).`
23
+ );
24
+ return;
25
+ }
26
+ try {
27
+ const result = await authClientWithCrossDomain.crossDomain.oneTimeToken.verify({
28
+ token
29
+ });
30
+ const session = result.data?.session;
31
+ if (session) {
32
+ await authClient.getSession({
33
+ fetchOptions: {
34
+ headers: {
35
+ Authorization: `Bearer ${session.token}`
36
+ }
37
+ }
38
+ });
39
+ authClientWithCrossDomain.updateSession();
40
+ }
41
+ } catch (error) {
42
+ console.warn("[nuxt-convex-module] failed to consume cross-domain one-time token", error);
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,20 @@
1
+ import type { FunctionReference } from 'convex/server';
2
+ import { type ComputedRef, type MaybeRefOrGetter } from 'vue';
3
+ import { type Preloaded } from '../../vue/hydration.js';
4
+ /**
5
+ * Auth-aware version of {@link usePreloadedQuery} for payloads returned by
6
+ * `convexAuth(event).preloadAuthQuery(...)`.
7
+ *
8
+ * A Vue/Nuxt port of `@convex-dev/better-auth`'s `usePreloadedAuthQuery`
9
+ * (`src/nextjs/client.tsx`): show the preloaded server result until the preload
10
+ * "expires" — i.e. auth settles as unauthenticated, or a live authenticated
11
+ * result arrives — then follow the live query. The last committed value is held
12
+ * while auth is (re)loading so a transient loading state does not flash the
13
+ * (possibly stale) preloaded value. At runtime yields `undefined` for
14
+ * unauthenticated users (as upstream does); the declared type also includes
15
+ * `null` so code annotated against upstream's `| null` signature keeps
16
+ * compiling.
17
+ *
18
+ * @public
19
+ */
20
+ export declare const usePreloadedAuthQuery: <Query extends FunctionReference<"query">>(preloadedQuery: MaybeRefOrGetter<Preloaded<Query>>) => ComputedRef<Query["_returnType"] | null | undefined>;
@@ -0,0 +1,52 @@
1
+ import { computed, ref, watch } from "vue";
2
+ import { useConvexAuth } from "../../vue/auth/index.js";
3
+ import { usePreloadedPayload, useReactiveQuery } from "../../vue/hydration.js";
4
+ const useConvexPreloadedQuery = (preloadedQuery, { requireAuth = true } = {}) => {
5
+ const { isLoading, isAuthenticated } = useConvexAuth();
6
+ const preloadExpired = ref(false);
7
+ watch(
8
+ [isLoading, isAuthenticated],
9
+ () => {
10
+ if (requireAuth && !isLoading.value && !isAuthenticated.value) {
11
+ preloadExpired.value = true;
12
+ }
13
+ },
14
+ { immediate: true }
15
+ );
16
+ const { query, args, preloadedResult } = usePreloadedPayload(preloadedQuery);
17
+ if (import.meta.server) {
18
+ return preloadedResult;
19
+ }
20
+ const result = useReactiveQuery(
21
+ query,
22
+ computed(() => requireAuth && !isAuthenticated.value ? "skip" : args.value)
23
+ );
24
+ watch(
25
+ result,
26
+ () => {
27
+ if (result.value !== void 0) {
28
+ preloadExpired.value = true;
29
+ }
30
+ },
31
+ { immediate: true }
32
+ );
33
+ if (requireAuth) {
34
+ return computed(() => preloadExpired.value ? result.value : preloadedResult.value);
35
+ }
36
+ return computed(() => result.value === void 0 ? preloadedResult.value : result.value);
37
+ };
38
+ export const usePreloadedAuthQuery = (preloadedQuery) => {
39
+ const { isLoading } = useConvexAuth();
40
+ const latestData = useConvexPreloadedQuery(preloadedQuery);
41
+ const data = ref(latestData.value);
42
+ watch(
43
+ [latestData, isLoading],
44
+ () => {
45
+ if (!isLoading.value) {
46
+ data.value = latestData.value;
47
+ }
48
+ },
49
+ { immediate: true }
50
+ );
51
+ return computed(() => data.value);
52
+ };
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Public client-side API for the opt-in Better Auth integration — a Vue/Nuxt
3
+ * port of `@convex-dev/better-auth`'s `react` integration.
4
+ *
5
+ * @module better-auth/client
6
+ */
7
+ export { useAuth, type UseAuthService, type AuthSession, type AuthUser } from './use-auth.js';
8
+ export { authClient, type AuthClient } from '#convex/auth-client';
9
+ export { usePreloadedAuthQuery } from './hydration.js';
10
+ export { consumeCrossDomainOneTimeToken, type ConsumeCrossDomainOneTimeTokenOptions } from './cross-domain.js';
11
+ export { AuthBoundary } from './auth-boundary.js';
12
+ export { convexClient, crossDomainClient } from '@convex-dev/better-auth/client/plugins';
@@ -0,0 +1,6 @@
1
+ export { useAuth } from "./use-auth.js";
2
+ export { authClient } from "#convex/auth-client";
3
+ export { usePreloadedAuthQuery } from "./hydration.js";
4
+ export { consumeCrossDomainOneTimeToken } from "./cross-domain.js";
5
+ export { AuthBoundary } from "./auth-boundary.js";
6
+ export { convexClient, crossDomainClient } from "@convex-dev/better-auth/client/plugins";
@@ -0,0 +1,6 @@
1
+ import { ConvexVueClient } from '../../vue/client.js';
2
+ type ConvexNuxtInjection = {
3
+ convex?: ConvexVueClient;
4
+ };
5
+ declare const _default: import("nuxt/app").Plugin<ConvexNuxtInjection> & import("nuxt/app").ObjectPlugin<ConvexNuxtInjection>;
6
+ export default _default;
@@ -0,0 +1,32 @@
1
+ import { defineNuxtPlugin, useRuntimeConfig, useState } from "#app";
2
+ import { ConvexVueClient, ConvexClientKey } from "../../vue/client.js";
3
+ import { ConvexAuthStateKey, createScopedConvexAuthState } from "../../vue/auth/index.js";
4
+ import { useAuth } from "./use-auth.js";
5
+ import { consumeCrossDomainOneTimeToken } from "./cross-domain.js";
6
+ export default defineNuxtPlugin({
7
+ name: "nuxt-convex-module:better-auth:client",
8
+ async setup(nuxtApp) {
9
+ const { url, crossDomainCallbackRoute } = useRuntimeConfig().public.convex;
10
+ if (!url) {
11
+ console.warn("[nuxt-convex-module] No Convex URL configured for client plugin.");
12
+ return { provide: {} };
13
+ }
14
+ const client = new ConvexVueClient(url);
15
+ nuxtApp.vueApp.provide(ConvexClientKey, client);
16
+ await consumeCrossDomainOneTimeToken({
17
+ callbackRoute: crossDomainCallbackRoute || void 0
18
+ });
19
+ const initialToken = useState("convex:initialToken", () => null);
20
+ const { state, scope } = createScopedConvexAuthState({
21
+ client,
22
+ useAuth: () => useAuth(initialToken.value)
23
+ });
24
+ nuxtApp.vueApp.provide(ConvexAuthStateKey, state);
25
+ void scope;
26
+ return {
27
+ provide: {
28
+ convex: client
29
+ }
30
+ };
31
+ }
32
+ });
@@ -0,0 +1,24 @@
1
+ import { useState, useRequestEvent } from '#app';
2
+ import { ConvexVueClient } from '../../vue/client.js';
3
+ type ConvexNuxtInjection = {
4
+ convex?: ConvexVueClient;
5
+ };
6
+ /**
7
+ * Prefetch the Convex JWT for SSR and stash it in `initialToken`.
8
+ *
9
+ * Exported for unit testing.
10
+ */
11
+ export declare function prefetchAuthToken(event: ReturnType<typeof useRequestEvent>, initialToken: ReturnType<typeof useState<string | null>>): Promise<void>;
12
+ /**
13
+ * Server-side Better Auth bootstrap.
14
+ *
15
+ * Mirrors the Next.js parity layer that calls `getToken()` from the root
16
+ * server layout and passes it as `initialToken` to `ConvexBetterAuthProvider`.
17
+ *
18
+ * The token is stashed into a Nuxt `useState('convex:initialToken')` so the
19
+ * client plugin can hand it to `useAuth(initialToken)` before the first
20
+ * Convex `setAuth` call — avoiding an extra Better Auth round-trip on first
21
+ * paint.
22
+ */
23
+ declare const _default: import("nuxt/app").Plugin<ConvexNuxtInjection> & import("nuxt/app").ObjectPlugin<ConvexNuxtInjection>;
24
+ export default _default;
@@ -0,0 +1,42 @@
1
+ import { computed } from "vue";
2
+ import { setResponseHeader } from "h3";
3
+ import { defineNuxtPlugin, useRuntimeConfig, useState, useRequestEvent } from "#app";
4
+ import { ConvexVueClient, ConvexClientKey } from "../../vue/client.js";
5
+ import { convexAuth } from "../nuxt/server.js";
6
+ import { ConvexAuthStateKey } from "../../vue/auth/index.js";
7
+ function buildProvide(ssrClient) {
8
+ return ssrClient ? { provide: { convex: ssrClient } } : { provide: {} };
9
+ }
10
+ export async function prefetchAuthToken(event, initialToken) {
11
+ try {
12
+ const token = await convexAuth(event).getToken();
13
+ initialToken.value = token ?? null;
14
+ if (token && event) {
15
+ setResponseHeader(event, "Cache-Control", "private, no-store");
16
+ }
17
+ } catch (error) {
18
+ console.warn("[nuxt-convex-module] Failed to prefetch auth token for SSR:", error);
19
+ }
20
+ }
21
+ export default defineNuxtPlugin({
22
+ name: "nuxt-convex-module:better-auth:server",
23
+ async setup(nuxtApp) {
24
+ const initialToken = useState("convex:initialToken", () => null);
25
+ const url = useRuntimeConfig().public.convex.url;
26
+ const ssrClient = url ? new ConvexVueClient(url) : void 0;
27
+ if (ssrClient) {
28
+ nuxtApp.vueApp.provide(ConvexClientKey, ssrClient);
29
+ }
30
+ const ssrAuthState = {
31
+ isLoading: computed(() => true),
32
+ isAuthenticated: computed(() => false),
33
+ isRefreshing: computed(() => false)
34
+ };
35
+ nuxtApp.vueApp.provide(ConvexAuthStateKey, ssrAuthState);
36
+ const event = useRequestEvent();
37
+ if (event) {
38
+ await prefetchAuthToken(event, initialToken);
39
+ }
40
+ return buildProvide(ssrClient);
41
+ }
42
+ });