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.
- package/LICENSE +21 -0
- package/README.md +242 -0
- package/dist/chunks/index.mjs +64 -0
- package/dist/devtools-client/200.html +1 -0
- package/dist/devtools-client/404.html +1 -0
- package/dist/devtools-client/_nuxt/B29GGJ5n.js +1 -0
- package/dist/devtools-client/_nuxt/BSDEpQet.js +1 -0
- package/dist/devtools-client/_nuxt/BY23OQOo.js +1 -0
- package/dist/devtools-client/_nuxt/BZYRaL-G.js +1 -0
- package/dist/devtools-client/_nuxt/Byw6FxnC.js +1 -0
- package/dist/devtools-client/_nuxt/CJJ_hcZN.js +1 -0
- package/dist/devtools-client/_nuxt/CS6WMFOx.js +2 -0
- package/dist/devtools-client/_nuxt/CZbAGcNC.js +1 -0
- package/dist/devtools-client/_nuxt/Cr6_aklh.js +2 -0
- package/dist/devtools-client/_nuxt/DNfpyBVU.js +3 -0
- package/dist/devtools-client/_nuxt/DPWXUmcI.js +1 -0
- package/dist/devtools-client/_nuxt/builds/latest.json +1 -0
- package/dist/devtools-client/_nuxt/builds/meta/a7708498-bd09-4de2-b5ab-19b380293c77.json +1 -0
- package/dist/devtools-client/_nuxt/dy_xXcv9.js +1 -0
- package/dist/devtools-client/_nuxt/entry.DbTJhkHT.css +1 -0
- package/dist/devtools-client/_nuxt/error-404.CwGGO2Kz.css +1 -0
- package/dist/devtools-client/_nuxt/error-500.8ZJqCQm8.css +1 -0
- package/dist/devtools-client/_nuxt/ncgEdbEt.js +1 -0
- package/dist/devtools-client/_nuxt/queries.CE_dtt9-.css +1 -0
- package/dist/devtools-client/auth/index.html +1 -0
- package/dist/devtools-client/icon.svg +6 -0
- package/dist/devtools-client/index.html +1 -0
- package/dist/devtools-client/logs/index.html +1 -0
- package/dist/devtools-client/queries/index.html +1 -0
- package/dist/module.d.ts +189 -0
- package/dist/module.js +489 -0
- package/dist/module.json +13 -0
- package/dist/runtime/auth0/vue/index.d.ts +58 -0
- package/dist/runtime/auth0/vue/index.js +33 -0
- package/dist/runtime/better-auth/nuxt/middleware.d.ts +14 -0
- package/dist/runtime/better-auth/nuxt/middleware.js +39 -0
- package/dist/runtime/better-auth/nuxt/proxy.d.ts +6 -0
- package/dist/runtime/better-auth/nuxt/proxy.js +11 -0
- package/dist/runtime/better-auth/nuxt/server.d.ts +106 -0
- package/dist/runtime/better-auth/nuxt/server.js +123 -0
- package/dist/runtime/better-auth/vue/auth-boundary.d.ts +131 -0
- package/dist/runtime/better-auth/vue/auth-boundary.js +78 -0
- package/dist/runtime/better-auth/vue/client.d.ts +358 -0
- package/dist/runtime/better-auth/vue/client.js +5 -0
- package/dist/runtime/better-auth/vue/cross-domain.d.ts +39 -0
- package/dist/runtime/better-auth/vue/cross-domain.js +45 -0
- package/dist/runtime/better-auth/vue/hydration.d.ts +20 -0
- package/dist/runtime/better-auth/vue/hydration.js +52 -0
- package/dist/runtime/better-auth/vue/index.d.ts +12 -0
- package/dist/runtime/better-auth/vue/index.js +6 -0
- package/dist/runtime/better-auth/vue/plugin.client.d.ts +6 -0
- package/dist/runtime/better-auth/vue/plugin.client.js +32 -0
- package/dist/runtime/better-auth/vue/plugin.server.d.ts +24 -0
- package/dist/runtime/better-auth/vue/plugin.server.js +42 -0
- package/dist/runtime/better-auth/vue/use-auth.d.ts +92 -0
- package/dist/runtime/better-auth/vue/use-auth.js +82 -0
- package/dist/runtime/clerk/vue/index.d.ts +81 -0
- package/dist/runtime/clerk/vue/index.js +49 -0
- package/dist/runtime/devtools/bridge.d.ts +12 -0
- package/dist/runtime/devtools/bridge.js +191 -0
- package/dist/runtime/devtools/plugin.client.d.ts +8 -0
- package/dist/runtime/devtools/plugin.client.js +34 -0
- package/dist/runtime/devtools/types.d.ts +78 -0
- package/dist/runtime/devtools/types.js +0 -0
- package/dist/runtime/nuxt/composables/use-async-query.d.ts +144 -0
- package/dist/runtime/nuxt/composables/use-async-query.js +104 -0
- package/dist/runtime/nuxt/config.d.ts +7 -0
- package/dist/runtime/nuxt/config.js +12 -0
- package/dist/runtime/nuxt/index.d.ts +136 -0
- package/dist/runtime/nuxt/index.js +91 -0
- package/dist/runtime/polar/vue/components.d.ts +184 -0
- package/dist/runtime/polar/vue/components.js +115 -0
- package/dist/runtime/vue/auth/helpers.d.ts +67 -0
- package/dist/runtime/vue/auth/helpers.js +50 -0
- package/dist/runtime/vue/auth/index.d.ts +125 -0
- package/dist/runtime/vue/auth/index.js +97 -0
- package/dist/runtime/vue/client.d.ts +305 -0
- package/dist/runtime/vue/client.js +382 -0
- package/dist/runtime/vue/composables/use-action.d.ts +62 -0
- package/dist/runtime/vue/composables/use-action.js +13 -0
- package/dist/runtime/vue/composables/use-connection-state.d.ts +30 -0
- package/dist/runtime/vue/composables/use-connection-state.js +14 -0
- package/dist/runtime/vue/composables/use-mutation.d.ts +76 -0
- package/dist/runtime/vue/composables/use-mutation.js +34 -0
- package/dist/runtime/vue/composables/use-paginated-query.d.ts +132 -0
- package/dist/runtime/vue/composables/use-paginated-query.js +513 -0
- package/dist/runtime/vue/composables/use-queries.d.ts +62 -0
- package/dist/runtime/vue/composables/use-queries.js +37 -0
- package/dist/runtime/vue/composables/use-query.d.ts +87 -0
- package/dist/runtime/vue/composables/use-query.js +53 -0
- package/dist/runtime/vue/composables/use-storage-url.d.ts +46 -0
- package/dist/runtime/vue/composables/use-storage-url.js +9 -0
- package/dist/runtime/vue/composables/use-subscription.d.ts +15 -0
- package/dist/runtime/vue/composables/use-subscription.js +33 -0
- package/dist/runtime/vue/composables/use-upload-queue.d.ts +117 -0
- package/dist/runtime/vue/composables/use-upload-queue.js +115 -0
- package/dist/runtime/vue/composables/use-upload.d.ts +134 -0
- package/dist/runtime/vue/composables/use-upload.js +114 -0
- package/dist/runtime/vue/hydration.d.ts +66 -0
- package/dist/runtime/vue/hydration.js +46 -0
- package/dist/runtime/vue/index.d.ts +94 -0
- package/dist/runtime/vue/index.js +42 -0
- package/dist/runtime/vue/plugin.d.ts +18 -0
- package/dist/runtime/vue/plugin.js +16 -0
- package/dist/runtime/vue/provide.d.ts +39 -0
- package/dist/runtime/vue/provide.js +15 -0
- package/dist/runtime/vue/queries-observer.d.ts +41 -0
- package/dist/runtime/vue/queries-observer.js +126 -0
- package/dist/types.d.ts +3 -0
- package/package.json +233 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { defineComponent, h, mergeProps, ref, watch } from "vue";
|
|
2
|
+
import { useAction } from "../../vue/composables/use-action.js";
|
|
3
|
+
import { useConvexNamespace } from "../../vue/provide.js";
|
|
4
|
+
export const CustomerPortalLink = defineComponent({
|
|
5
|
+
name: "CustomerPortalLink",
|
|
6
|
+
inheritAttrs: false,
|
|
7
|
+
props: {
|
|
8
|
+
// Optional in the port: defaults to the auto-provided `api.billing` namespace.
|
|
9
|
+
polarApi: { type: Object, default: void 0 },
|
|
10
|
+
returnUrl: { type: String, default: void 0 }
|
|
11
|
+
},
|
|
12
|
+
setup(props, { slots, attrs }) {
|
|
13
|
+
const polarApi = props.polarApi ?? useConvexNamespace("billing");
|
|
14
|
+
const generateCustomerPortalUrl = polarApi?.generateCustomerPortalUrl ? useAction(polarApi.generateCustomerPortalUrl) : void 0;
|
|
15
|
+
const portalUrl = ref();
|
|
16
|
+
if (import.meta.client && generateCustomerPortalUrl) {
|
|
17
|
+
watch(
|
|
18
|
+
() => props.returnUrl,
|
|
19
|
+
(returnUrl) => {
|
|
20
|
+
void generateCustomerPortalUrl({ returnUrl }).then((result) => {
|
|
21
|
+
if (result) {
|
|
22
|
+
portalUrl.value = result.url;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
{ immediate: true }
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return () => {
|
|
30
|
+
if (!portalUrl.value) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return h("a", { ...attrs, href: portalUrl.value, target: "_blank" }, slots.default?.());
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
export const CheckoutLink = defineComponent({
|
|
38
|
+
name: "CheckoutLink",
|
|
39
|
+
inheritAttrs: false,
|
|
40
|
+
props: {
|
|
41
|
+
// Optional in the port: defaults to the auto-provided `api.billing` namespace.
|
|
42
|
+
polarApi: { type: Object, default: void 0 },
|
|
43
|
+
productIds: { type: Array, required: true },
|
|
44
|
+
subscriptionId: { type: String, default: void 0 },
|
|
45
|
+
metadata: { type: Object, default: void 0 },
|
|
46
|
+
trialInterval: { type: String, default: void 0 },
|
|
47
|
+
trialIntervalCount: { type: Number, default: void 0 },
|
|
48
|
+
locale: { type: String, default: void 0 },
|
|
49
|
+
theme: { type: String, default: "dark" },
|
|
50
|
+
embed: { type: Boolean, default: true },
|
|
51
|
+
lazy: { type: Boolean, default: false }
|
|
52
|
+
},
|
|
53
|
+
setup(props, { slots, attrs }) {
|
|
54
|
+
const polarApi = props.polarApi ?? useConvexNamespace("billing");
|
|
55
|
+
const generateCheckoutLink = polarApi?.generateCheckoutLink ? useAction(polarApi.generateCheckoutLink) : void 0;
|
|
56
|
+
const checkoutLink = ref();
|
|
57
|
+
const isLoading = ref(false);
|
|
58
|
+
if (import.meta.client && generateCheckoutLink) {
|
|
59
|
+
watch(
|
|
60
|
+
() => [props.lazy, props.productIds, props.subscriptionId, props.metadata, props.embed, props.trialInterval, props.trialIntervalCount, props.locale],
|
|
61
|
+
async () => {
|
|
62
|
+
if (props.lazy) return;
|
|
63
|
+
if (props.embed) {
|
|
64
|
+
const { PolarEmbedCheckout } = await import("@polar-sh/checkout/embed");
|
|
65
|
+
PolarEmbedCheckout.init();
|
|
66
|
+
}
|
|
67
|
+
void generateCheckoutLink({
|
|
68
|
+
productIds: props.productIds,
|
|
69
|
+
subscriptionId: props.subscriptionId,
|
|
70
|
+
metadata: props.metadata,
|
|
71
|
+
origin: window.location.origin,
|
|
72
|
+
successUrl: window.location.href,
|
|
73
|
+
trialInterval: props.trialInterval,
|
|
74
|
+
trialIntervalCount: props.trialIntervalCount,
|
|
75
|
+
locale: props.locale
|
|
76
|
+
}).then(({ url }) => {
|
|
77
|
+
checkoutLink.value = url;
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
{ immediate: true }
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
const handleClick = generateCheckoutLink ? async (e) => {
|
|
84
|
+
e.preventDefault();
|
|
85
|
+
if (isLoading.value) return;
|
|
86
|
+
isLoading.value = true;
|
|
87
|
+
try {
|
|
88
|
+
const { url } = await generateCheckoutLink({
|
|
89
|
+
productIds: props.productIds,
|
|
90
|
+
subscriptionId: props.subscriptionId,
|
|
91
|
+
metadata: props.metadata,
|
|
92
|
+
origin: window.location.origin,
|
|
93
|
+
successUrl: window.location.href,
|
|
94
|
+
trialInterval: props.trialInterval,
|
|
95
|
+
trialIntervalCount: props.trialIntervalCount,
|
|
96
|
+
locale: props.locale
|
|
97
|
+
});
|
|
98
|
+
if (props.embed) {
|
|
99
|
+
const { PolarEmbedCheckout } = await import("@polar-sh/checkout/embed");
|
|
100
|
+
await PolarEmbedCheckout.create(url, { theme: props.theme });
|
|
101
|
+
} else {
|
|
102
|
+
window.open(url, "_blank");
|
|
103
|
+
}
|
|
104
|
+
} finally {
|
|
105
|
+
isLoading.value = false;
|
|
106
|
+
}
|
|
107
|
+
} : void 0;
|
|
108
|
+
return () => h("a", mergeProps(attrs, {
|
|
109
|
+
"href": checkoutLink.value ?? (props.lazy ? "#" : void 0),
|
|
110
|
+
"onClick": props.lazy ? handleClick : void 0,
|
|
111
|
+
"data-polar-checkout-theme": props.theme,
|
|
112
|
+
...!props.lazy && props.embed ? { "data-polar-checkout": true } : {}
|
|
113
|
+
}), slots.default?.());
|
|
114
|
+
}
|
|
115
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the default slot if the client is authenticated.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```vue
|
|
6
|
+
* <Authenticated>
|
|
7
|
+
* <p>You are logged in!</p>
|
|
8
|
+
* </Authenticated>
|
|
9
|
+
* ```
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export declare const Authenticated: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
}>[] | null | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
16
|
+
/**
|
|
17
|
+
* Renders the default slot if the client is using authentication but is not authenticated.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```vue
|
|
21
|
+
* <Unauthenticated>
|
|
22
|
+
* <p>Please log in.</p>
|
|
23
|
+
* </Unauthenticated>
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare const Unauthenticated: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
}>[] | null | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
31
|
+
/**
|
|
32
|
+
* Renders the default slot if the client isn't using authentication or is in the process
|
|
33
|
+
* of authenticating.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```vue
|
|
37
|
+
* <AuthLoading>
|
|
38
|
+
* <p>Checking authentication...</p>
|
|
39
|
+
* </AuthLoading>
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export declare const AuthLoading: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
}>[] | null | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
47
|
+
/**
|
|
48
|
+
* Renders the default slot while the client is refreshing the auth token for an
|
|
49
|
+
* already-authenticated session (the server rejected the current token and
|
|
50
|
+
* the socket is paused while a new one is fetched). Routine background
|
|
51
|
+
* token rotation does not trigger this state.
|
|
52
|
+
*
|
|
53
|
+
* Whether used inside of `<Authenticated>` or not, the default slot will only be
|
|
54
|
+
* rendered if the user is authenticated.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```vue
|
|
58
|
+
* <AuthRefreshing>
|
|
59
|
+
* <p>Refreshing token...</p>
|
|
60
|
+
* </AuthRefreshing>
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
export declare const AuthRefreshing: import("vue").DefineComponent<{}, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
66
|
+
[key: string]: any;
|
|
67
|
+
}>[] | null | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineComponent } from "vue";
|
|
2
|
+
import { useConvexAuth } from "./index.js";
|
|
3
|
+
export const Authenticated = defineComponent({
|
|
4
|
+
name: "Authenticated",
|
|
5
|
+
setup(_, { slots }) {
|
|
6
|
+
const { isLoading, isAuthenticated } = useConvexAuth();
|
|
7
|
+
return () => {
|
|
8
|
+
if (isLoading.value || !isAuthenticated.value) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
return slots.default?.();
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
export const Unauthenticated = defineComponent({
|
|
16
|
+
name: "Unauthenticated",
|
|
17
|
+
setup(_, { slots }) {
|
|
18
|
+
const { isLoading, isAuthenticated } = useConvexAuth();
|
|
19
|
+
return () => {
|
|
20
|
+
if (isLoading.value || isAuthenticated.value) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return slots.default?.();
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
export const AuthLoading = defineComponent({
|
|
28
|
+
name: "AuthLoading",
|
|
29
|
+
setup(_, { slots }) {
|
|
30
|
+
const { isLoading } = useConvexAuth();
|
|
31
|
+
return () => {
|
|
32
|
+
if (!isLoading.value) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return slots.default?.();
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
export const AuthRefreshing = defineComponent({
|
|
40
|
+
name: "AuthRefreshing",
|
|
41
|
+
setup(_, { slots }) {
|
|
42
|
+
const { isAuthenticated, isRefreshing } = useConvexAuth();
|
|
43
|
+
return () => {
|
|
44
|
+
if (!isAuthenticated.value || !isRefreshing.value) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return slots.default?.();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { AuthTokenFetcher } from 'convex/browser';
|
|
2
|
+
import { type ComputedRef, type EffectScope, type InjectionKey, type MaybeRef, type MaybeRefOrGetter } from 'vue';
|
|
3
|
+
export type IConvexVueClient = {
|
|
4
|
+
setAuth(fetchToken: AuthTokenFetcher, onChange: (isAuthenticated: boolean) => void, onRefreshChange?: (isRefreshing: boolean) => void): void;
|
|
5
|
+
clearAuth(): void;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Type representing the state of an auth integration with Convex.
|
|
9
|
+
*
|
|
10
|
+
* - `isLoading`: the client is still resolving the initial auth state and
|
|
11
|
+
* waiting for the server to confirm the current token.
|
|
12
|
+
* - `isAuthenticated`: the server has confirmed the current token.
|
|
13
|
+
* - `isRefreshing`: the server rejected a previously-confirmed token and the
|
|
14
|
+
* socket is paused while a replacement is fetched. Only ever `true` when
|
|
15
|
+
* `isAuthenticated` is also `true`. Routine background token rotation does
|
|
16
|
+
* not trigger this state.
|
|
17
|
+
*
|
|
18
|
+
* Each field is a `ComputedRef` (the Vue translation of upstream's re-rendered
|
|
19
|
+
* plain booleans), so the upstream destructuring idiom stays reactive:
|
|
20
|
+
* `const { isLoading, isAuthenticated } = useConvexAuth()`.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export type ConvexAuthState = {
|
|
25
|
+
isLoading: ComputedRef<boolean>;
|
|
26
|
+
isAuthenticated: ComputedRef<boolean>;
|
|
27
|
+
isRefreshing: ComputedRef<boolean>;
|
|
28
|
+
};
|
|
29
|
+
export declare const ConvexAuthStateKey: InjectionKey<ConvexAuthState>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the {@link ConvexAuthState} within a Vue component.
|
|
32
|
+
*
|
|
33
|
+
* This relies on a Convex auth integration provider being above in the Vue
|
|
34
|
+
* component tree. See {@link ConvexAuthState} for the meaning of each field.
|
|
35
|
+
*
|
|
36
|
+
* @returns The current {@link ConvexAuthState}.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export declare function useConvexAuth(): {
|
|
41
|
+
isLoading: ComputedRef<boolean>;
|
|
42
|
+
isAuthenticated: ComputedRef<boolean>;
|
|
43
|
+
isRefreshing: ComputedRef<boolean>;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Options for {@link provideConvexAuth} — the Vue translation of the props of
|
|
47
|
+
* upstream's `ConvexProviderWithAuth` component.
|
|
48
|
+
*/
|
|
49
|
+
export interface ConvexAuthProviderOptions {
|
|
50
|
+
client: IConvexVueClient;
|
|
51
|
+
useAuth: () => {
|
|
52
|
+
isLoading: MaybeRefOrGetter<boolean>;
|
|
53
|
+
isAuthenticated: MaybeRefOrGetter<boolean>;
|
|
54
|
+
/**
|
|
55
|
+
* The token fetcher. May be a `Ref`/`ComputedRef` whose *identity* changes
|
|
56
|
+
* when re-authentication is needed — the Vue translation of upstream
|
|
57
|
+
* re-running its `setAuth` effect when the `useAuth` prop returns a new
|
|
58
|
+
* `fetchAccessToken` function between renders (e.g. Clerk's `useCallback`
|
|
59
|
+
* deps `[orgId, orgRole]`). A plain function never re-triggers.
|
|
60
|
+
*
|
|
61
|
+
* (A getter is deliberately not accepted here: the fetcher is itself a
|
|
62
|
+
* function, so a getter would be indistinguishable from the value.)
|
|
63
|
+
*/
|
|
64
|
+
fetchAccessToken: MaybeRef<AuthTokenFetcher>;
|
|
65
|
+
/**
|
|
66
|
+
* Alternative re-authentication trigger for providers that hand out a
|
|
67
|
+
* stable fetcher function: when this value changes, auth state transitions
|
|
68
|
+
* back to loading, `clearAuth` runs, and `fetchAccessToken` is called
|
|
69
|
+
* again against the new auth context.
|
|
70
|
+
*/
|
|
71
|
+
authVersion?: MaybeRefOrGetter<unknown>;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A replacement for the plain Convex client provide (upstream's
|
|
76
|
+
* `ConvexProvider`) which additionally provides {@link ConvexAuthState} to
|
|
77
|
+
* descendants of the calling component.
|
|
78
|
+
*
|
|
79
|
+
* Use this to integrate any auth provider with Convex. The `useAuth` option
|
|
80
|
+
* should be a Vue composable that returns the provider's authentication state
|
|
81
|
+
* and a function to fetch a JWT access token.
|
|
82
|
+
*
|
|
83
|
+
* If the returned `fetchAccessToken` ref identity (or the optional
|
|
84
|
+
* `authVersion` value) updates then auth state
|
|
85
|
+
* will transition to loading and the `fetchAccessToken()` function called again.
|
|
86
|
+
*
|
|
87
|
+
* See [Custom Auth Integration](https://docs.convex.dev/auth/advanced/custom-auth) for more information.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```vue
|
|
91
|
+
* <script setup lang="ts">
|
|
92
|
+
* import { useAuth } from '~/composables/useAuth' // your auth provider
|
|
93
|
+
*
|
|
94
|
+
* const { client } = useNuxtApp().$convex
|
|
95
|
+
* const authState = provideConvexAuth({ client, useAuth })
|
|
96
|
+
* </script>
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @param options - Auth integration options including the Convex client and
|
|
100
|
+
* an `useAuth` factory that returns loading state and a token fetcher.
|
|
101
|
+
* @returns The reactive auth state.
|
|
102
|
+
*
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
export declare function provideConvexAuth(options: ConvexAuthProviderOptions): ConvexAuthState;
|
|
106
|
+
/**
|
|
107
|
+
* Build reactive {@link ConvexAuthState} and wire watchers between the
|
|
108
|
+
* external auth provider and the Convex client, without calling `provide()` —
|
|
109
|
+
* the body of upstream's `ConvexProviderWithAuth` component.
|
|
110
|
+
*
|
|
111
|
+
* Use this when you need to install the state at the Nuxt app level
|
|
112
|
+
* (`nuxtApp.vueApp.provide`) rather than from a component's setup function.
|
|
113
|
+
*
|
|
114
|
+
* When `scope` is provided, all watchers are created inside that
|
|
115
|
+
* {@link EffectScope} so callers can dispose them later.
|
|
116
|
+
*/
|
|
117
|
+
export declare function createConvexAuthState(options: ConvexAuthProviderOptions, scope?: EffectScope): ConvexAuthState;
|
|
118
|
+
/**
|
|
119
|
+
* Create a fresh {@link EffectScope} and build a Convex auth state inside it.
|
|
120
|
+
* The scope is returned so the caller can `.stop()` it on teardown.
|
|
121
|
+
*/
|
|
122
|
+
export declare function createScopedConvexAuthState(options: ConvexAuthProviderOptions): {
|
|
123
|
+
state: ConvexAuthState;
|
|
124
|
+
scope: EffectScope;
|
|
125
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { computed, effectScope, inject, provide, ref, toValue, unref, watch, watchEffect } from "vue";
|
|
2
|
+
export const ConvexAuthStateKey = Symbol("ConvexAuthState");
|
|
3
|
+
export function useConvexAuth() {
|
|
4
|
+
const authContext = inject(ConvexAuthStateKey);
|
|
5
|
+
if (authContext === void 0) {
|
|
6
|
+
throw new Error(
|
|
7
|
+
"Could not find Convex auth context. Ensure `provideConvexAuth` has been called in an ancestor component or that the Convex auth plugin is installed, or you might have two instances of the `nuxt-convex-module` runtime loaded in your project."
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
return authContext;
|
|
11
|
+
}
|
|
12
|
+
export function provideConvexAuth(options) {
|
|
13
|
+
const authState = createConvexAuthState(options);
|
|
14
|
+
provide(ConvexAuthStateKey, authState);
|
|
15
|
+
return authState;
|
|
16
|
+
}
|
|
17
|
+
export function createConvexAuthState(options, scope) {
|
|
18
|
+
const { client, useAuth } = options;
|
|
19
|
+
const {
|
|
20
|
+
isLoading: authProviderLoading,
|
|
21
|
+
isAuthenticated: authProviderAuthenticated,
|
|
22
|
+
fetchAccessToken,
|
|
23
|
+
authVersion
|
|
24
|
+
} = useAuth();
|
|
25
|
+
const isConvexAuthenticated = ref(null);
|
|
26
|
+
const isRefreshing = ref(false);
|
|
27
|
+
const register = () => {
|
|
28
|
+
watch(
|
|
29
|
+
() => [
|
|
30
|
+
toValue(authProviderLoading),
|
|
31
|
+
toValue(authProviderAuthenticated),
|
|
32
|
+
isConvexAuthenticated.value
|
|
33
|
+
],
|
|
34
|
+
([authProviderLoading2, authProviderAuthenticated2]) => {
|
|
35
|
+
if (authProviderLoading2 && isConvexAuthenticated.value !== null) {
|
|
36
|
+
isConvexAuthenticated.value = null;
|
|
37
|
+
isRefreshing.value = false;
|
|
38
|
+
}
|
|
39
|
+
if (!authProviderLoading2 && !authProviderAuthenticated2 && isConvexAuthenticated.value !== false) {
|
|
40
|
+
isConvexAuthenticated.value = false;
|
|
41
|
+
isRefreshing.value = false;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{ immediate: true }
|
|
45
|
+
);
|
|
46
|
+
watchEffect((onCleanup) => {
|
|
47
|
+
if (import.meta.server) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
let isThisEffectRelevant = true;
|
|
51
|
+
void toValue(authProviderLoading);
|
|
52
|
+
void toValue(authVersion);
|
|
53
|
+
const fetchToken = unref(fetchAccessToken);
|
|
54
|
+
if (toValue(authProviderAuthenticated)) {
|
|
55
|
+
client.setAuth(
|
|
56
|
+
fetchToken,
|
|
57
|
+
(convexReportsIsAuthenticated) => {
|
|
58
|
+
if (isThisEffectRelevant) {
|
|
59
|
+
isConvexAuthenticated.value = convexReportsIsAuthenticated;
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
// Upstream names this callback's parameter `isRefreshing` too; that
|
|
63
|
+
// would shadow the ref here.
|
|
64
|
+
(refreshing) => {
|
|
65
|
+
if (isThisEffectRelevant) {
|
|
66
|
+
isRefreshing.value = refreshing;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
onCleanup(() => {
|
|
71
|
+
isThisEffectRelevant = false;
|
|
72
|
+
client.clearAuth();
|
|
73
|
+
isConvexAuthenticated.value = null;
|
|
74
|
+
isRefreshing.value = false;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
if (scope) {
|
|
80
|
+
scope.run(register);
|
|
81
|
+
} else {
|
|
82
|
+
register();
|
|
83
|
+
}
|
|
84
|
+
const isAuthenticated = computed(
|
|
85
|
+
() => toValue(authProviderAuthenticated) && (isConvexAuthenticated.value ?? false)
|
|
86
|
+
);
|
|
87
|
+
return {
|
|
88
|
+
isLoading: computed(() => isConvexAuthenticated.value === null),
|
|
89
|
+
isAuthenticated,
|
|
90
|
+
isRefreshing: computed(() => isRefreshing.value && isAuthenticated.value)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
export function createScopedConvexAuthState(options) {
|
|
94
|
+
const scope = effectScope(true);
|
|
95
|
+
const state = createConvexAuthState(options, scope);
|
|
96
|
+
return { state, scope };
|
|
97
|
+
}
|