@authsome/ui-vue 1.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.
@@ -0,0 +1,168 @@
1
+ import { AuthConfig, User, Session, AuthClient } from '@authsome/ui-core';
2
+ export { APIError, AuthConfig, AuthState, MFAEnrollment, Member, Organization, Session, TokenStorage, User } from '@authsome/ui-core';
3
+ import * as vue from 'vue';
4
+ import { App, Ref } from 'vue';
5
+
6
+ /**
7
+ * Creates a Vue plugin that provides AuthSome authentication.
8
+ *
9
+ * ```ts
10
+ * const app = createApp(App);
11
+ * app.use(createAuthPlugin({ baseURL: "https://api.example.com" }));
12
+ * ```
13
+ */
14
+ declare function createAuthPlugin(config: AuthConfig): {
15
+ install(app: App): void;
16
+ };
17
+ /**
18
+ * Main auth composable providing state and actions.
19
+ */
20
+ declare function useAuth(): {
21
+ state: Readonly<Ref<{
22
+ readonly status: "idle";
23
+ } | {
24
+ readonly status: "loading";
25
+ } | {
26
+ readonly status: "authenticated";
27
+ readonly user: {
28
+ readonly app_id: {};
29
+ readonly ban_expires?: string | undefined;
30
+ readonly ban_reason?: string | undefined;
31
+ readonly banned: boolean;
32
+ readonly created_at: string;
33
+ readonly deleted_at?: string | undefined;
34
+ readonly display_username?: string | undefined;
35
+ readonly email: string;
36
+ readonly email_verified: boolean;
37
+ readonly id: {};
38
+ readonly image?: string | undefined;
39
+ readonly metadata?: {
40
+ readonly [x: string]: Readonly<unknown>;
41
+ } | undefined;
42
+ readonly name: string;
43
+ readonly phone?: string | undefined;
44
+ readonly phone_verified: boolean;
45
+ readonly updated_at: string;
46
+ readonly username?: string | undefined;
47
+ };
48
+ readonly session: {
49
+ readonly session_token: string;
50
+ readonly refresh_token: string;
51
+ readonly expires_at: string;
52
+ };
53
+ } | {
54
+ readonly status: "unauthenticated";
55
+ } | {
56
+ readonly status: "mfa_required";
57
+ readonly session: {
58
+ readonly session_token: string;
59
+ readonly refresh_token: string;
60
+ readonly expires_at: string;
61
+ };
62
+ } | {
63
+ readonly status: "error";
64
+ readonly error: string;
65
+ }, {
66
+ readonly status: "idle";
67
+ } | {
68
+ readonly status: "loading";
69
+ } | {
70
+ readonly status: "authenticated";
71
+ readonly user: {
72
+ readonly app_id: {};
73
+ readonly ban_expires?: string | undefined;
74
+ readonly ban_reason?: string | undefined;
75
+ readonly banned: boolean;
76
+ readonly created_at: string;
77
+ readonly deleted_at?: string | undefined;
78
+ readonly display_username?: string | undefined;
79
+ readonly email: string;
80
+ readonly email_verified: boolean;
81
+ readonly id: {};
82
+ readonly image?: string | undefined;
83
+ readonly metadata?: {
84
+ readonly [x: string]: Readonly<unknown>;
85
+ } | undefined;
86
+ readonly name: string;
87
+ readonly phone?: string | undefined;
88
+ readonly phone_verified: boolean;
89
+ readonly updated_at: string;
90
+ readonly username?: string | undefined;
91
+ };
92
+ readonly session: {
93
+ readonly session_token: string;
94
+ readonly refresh_token: string;
95
+ readonly expires_at: string;
96
+ };
97
+ } | {
98
+ readonly status: "unauthenticated";
99
+ } | {
100
+ readonly status: "mfa_required";
101
+ readonly session: {
102
+ readonly session_token: string;
103
+ readonly refresh_token: string;
104
+ readonly expires_at: string;
105
+ };
106
+ } | {
107
+ readonly status: "error";
108
+ readonly error: string;
109
+ }>>;
110
+ isAuthenticated: vue.ComputedRef<boolean>;
111
+ isLoading: vue.ComputedRef<boolean>;
112
+ user: vue.ComputedRef<User | null>;
113
+ session: vue.ComputedRef<Session | null>;
114
+ error: vue.ComputedRef<string | null>;
115
+ client: AuthClient;
116
+ signIn: (email: string, password: string) => Promise<void>;
117
+ signUp: (email: string, password: string, name?: string) => Promise<void>;
118
+ signOut: () => Promise<void>;
119
+ submitMFACode: (enrollmentId: string, code: string) => Promise<void>;
120
+ submitRecoveryCode: (code: string) => Promise<void>;
121
+ };
122
+ /**
123
+ * Composable to fetch and reload the user profile.
124
+ */
125
+ declare function useUser(): {
126
+ user: vue.ComputedRef<User | null>;
127
+ isLoading: vue.ComputedRef<boolean>;
128
+ reload: () => Promise<void>;
129
+ };
130
+ /**
131
+ * Composable to list organizations.
132
+ */
133
+ declare function useOrganizations(): {
134
+ organizations: Readonly<Ref<readonly {
135
+ readonly app_id: {};
136
+ readonly created_at: string;
137
+ readonly created_by: {};
138
+ readonly id: {};
139
+ readonly logo?: string | undefined;
140
+ readonly metadata?: {
141
+ readonly [x: string]: Readonly<unknown>;
142
+ } | undefined;
143
+ readonly name: string;
144
+ readonly slug: string;
145
+ readonly updated_at: string;
146
+ }[], readonly {
147
+ readonly app_id: {};
148
+ readonly created_at: string;
149
+ readonly created_by: {};
150
+ readonly id: {};
151
+ readonly logo?: string | undefined;
152
+ readonly metadata?: {
153
+ readonly [x: string]: Readonly<unknown>;
154
+ } | undefined;
155
+ readonly name: string;
156
+ readonly slug: string;
157
+ readonly updated_at: string;
158
+ }[]>>;
159
+ total: Readonly<Ref<number, number>>;
160
+ isLoading: Readonly<Ref<boolean, boolean>>;
161
+ reload: () => Promise<void>;
162
+ };
163
+ /**
164
+ * Composable that returns the current session token.
165
+ */
166
+ declare function useSessionToken(): vue.ComputedRef<string | null>;
167
+
168
+ export { createAuthPlugin, useAuth, useOrganizations, useSessionToken, useUser };
package/dist/index.js ADDED
@@ -0,0 +1,142 @@
1
+ // src/composables.ts
2
+ import {
3
+ computed,
4
+ inject,
5
+ onMounted,
6
+ readonly,
7
+ ref
8
+ } from "vue";
9
+ import {
10
+ AuthManager
11
+ } from "@authsome/ui-core";
12
+ var AUTH_KEY = /* @__PURE__ */ Symbol("authsome");
13
+ var AUTH_STATE_KEY = /* @__PURE__ */ Symbol("authsome:state");
14
+ function createAuthPlugin(config) {
15
+ return {
16
+ install(app) {
17
+ const manager = new AuthManager(config);
18
+ const state = ref(manager.getState());
19
+ manager.subscribe((s) => {
20
+ state.value = s;
21
+ });
22
+ app.provide(AUTH_KEY, manager);
23
+ app.provide(AUTH_STATE_KEY, state);
24
+ void manager.initialize();
25
+ }
26
+ };
27
+ }
28
+ function useManager() {
29
+ const manager = inject(AUTH_KEY);
30
+ if (!manager) {
31
+ throw new Error("useAuth requires the authsome plugin. Call app.use(createAuthPlugin(...)).");
32
+ }
33
+ return manager;
34
+ }
35
+ function useAuthState() {
36
+ const state = inject(AUTH_STATE_KEY);
37
+ if (!state) {
38
+ throw new Error("useAuth requires the authsome plugin. Call app.use(createAuthPlugin(...)).");
39
+ }
40
+ return state;
41
+ }
42
+ function useAuth() {
43
+ const manager = useManager();
44
+ const state = useAuthState();
45
+ const isAuthenticated = computed(() => state.value.status === "authenticated");
46
+ const isLoading = computed(() => state.value.status === "loading");
47
+ const user = computed(
48
+ () => state.value.status === "authenticated" ? state.value.user : null
49
+ );
50
+ const session = computed(
51
+ () => state.value.status === "authenticated" ? state.value.session : null
52
+ );
53
+ const error = computed(
54
+ () => state.value.status === "error" ? state.value.error : null
55
+ );
56
+ async function signIn(email, password) {
57
+ await manager.signIn({ email, password });
58
+ }
59
+ async function signUp(email, password, name) {
60
+ await manager.signUp({ email, password, name });
61
+ }
62
+ async function signOut() {
63
+ await manager.signOut();
64
+ }
65
+ async function submitMFACode(enrollmentId, code) {
66
+ await manager.submitMFACode(enrollmentId, code);
67
+ }
68
+ async function submitRecoveryCode(code) {
69
+ await manager.submitRecoveryCode(code);
70
+ }
71
+ return {
72
+ state: readonly(state),
73
+ isAuthenticated,
74
+ isLoading,
75
+ user,
76
+ session,
77
+ error,
78
+ client: manager.getClient(),
79
+ signIn,
80
+ signUp,
81
+ signOut,
82
+ submitMFACode,
83
+ submitRecoveryCode
84
+ };
85
+ }
86
+ function useUser() {
87
+ const { user: authUser, isLoading, session } = useAuth();
88
+ const manager = useManager();
89
+ const localUser = ref(authUser.value);
90
+ const stopWatch = computed(() => authUser.value);
91
+ async function reload() {
92
+ if (!session.value) return;
93
+ const u = await manager.getClient().getMe(session.value.session_token);
94
+ localUser.value = u;
95
+ }
96
+ return {
97
+ user: computed(() => localUser.value ?? authUser.value),
98
+ isLoading,
99
+ reload
100
+ };
101
+ }
102
+ function useOrganizations() {
103
+ const { session, isAuthenticated } = useAuth();
104
+ const manager = useManager();
105
+ const organizations = ref([]);
106
+ const total = ref(0);
107
+ const isLoading = ref(false);
108
+ async function load() {
109
+ if (!session.value) return;
110
+ isLoading.value = true;
111
+ try {
112
+ const res = await manager.getClient().listOrganizations(session.value.session_token);
113
+ organizations.value = res.items;
114
+ total.value = res.total;
115
+ } finally {
116
+ isLoading.value = false;
117
+ }
118
+ }
119
+ onMounted(() => {
120
+ if (isAuthenticated.value) {
121
+ void load();
122
+ }
123
+ });
124
+ return {
125
+ organizations: readonly(organizations),
126
+ total: readonly(total),
127
+ isLoading: readonly(isLoading),
128
+ reload: load
129
+ };
130
+ }
131
+ function useSessionToken() {
132
+ const { session } = useAuth();
133
+ return computed(() => session.value?.session_token ?? null);
134
+ }
135
+ export {
136
+ createAuthPlugin,
137
+ useAuth,
138
+ useOrganizations,
139
+ useSessionToken,
140
+ useUser
141
+ };
142
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/composables.ts"],"sourcesContent":["/**\n * Vue 3 composables for AuthSome authentication.\n *\n * Usage:\n * ```ts\n * // main.ts\n * import { createAuthPlugin } from \"@authsome/ui-vue\";\n * app.use(createAuthPlugin({ baseURL: \"https://api.example.com\" }));\n *\n * // Component.vue\n * import { useAuth, useUser } from \"@authsome/ui-vue\";\n * const { signIn, isAuthenticated, user } = useAuth();\n * ```\n */\n\nimport {\n computed,\n inject,\n onMounted,\n onUnmounted,\n readonly,\n ref,\n type App,\n type InjectionKey,\n type Ref,\n} from \"vue\";\nimport {\n AuthManager,\n type AuthConfig,\n type AuthState,\n type AuthClient,\n type User,\n type Session,\n type Organization,\n type ListResponse,\n} from \"@authsome/ui-core\";\n\n/** Injection key for the AuthManager. */\nconst AUTH_KEY: InjectionKey<AuthManager> = Symbol(\"authsome\");\n\n/** Injection key for the reactive auth state. */\nconst AUTH_STATE_KEY: InjectionKey<Ref<AuthState>> = Symbol(\"authsome:state\");\n\n/**\n * Creates a Vue plugin that provides AuthSome authentication.\n *\n * ```ts\n * const app = createApp(App);\n * app.use(createAuthPlugin({ baseURL: \"https://api.example.com\" }));\n * ```\n */\nexport function createAuthPlugin(config: AuthConfig) {\n return {\n install(app: App) {\n const manager = new AuthManager(config);\n const state = ref<AuthState>(manager.getState());\n\n manager.subscribe((s) => {\n state.value = s;\n });\n\n app.provide(AUTH_KEY, manager);\n app.provide(AUTH_STATE_KEY, state);\n\n // Initialize on mount (hydrate from storage).\n void manager.initialize();\n },\n };\n}\n\nfunction useManager(): AuthManager {\n const manager = inject(AUTH_KEY);\n if (!manager) {\n throw new Error(\"useAuth requires the authsome plugin. Call app.use(createAuthPlugin(...)).\");\n }\n return manager;\n}\n\nfunction useAuthState(): Ref<AuthState> {\n const state = inject(AUTH_STATE_KEY);\n if (!state) {\n throw new Error(\"useAuth requires the authsome plugin. Call app.use(createAuthPlugin(...)).\");\n }\n return state;\n}\n\n/**\n * Main auth composable providing state and actions.\n */\nexport function useAuth() {\n const manager = useManager();\n const state = useAuthState();\n\n const isAuthenticated = computed(() => state.value.status === \"authenticated\");\n const isLoading = computed(() => state.value.status === \"loading\");\n\n const user = computed<User | null>(() =>\n state.value.status === \"authenticated\" ? state.value.user : null,\n );\n\n const session = computed<Session | null>(() =>\n state.value.status === \"authenticated\" ? state.value.session : null,\n );\n\n const error = computed<string | null>(() =>\n state.value.status === \"error\" ? state.value.error : null,\n );\n\n async function signIn(email: string, password: string) {\n await manager.signIn({ email, password });\n }\n\n async function signUp(email: string, password: string, name?: string) {\n await manager.signUp({ email, password, name });\n }\n\n async function signOut() {\n await manager.signOut();\n }\n\n async function submitMFACode(enrollmentId: string, code: string) {\n await manager.submitMFACode(enrollmentId, code);\n }\n\n async function submitRecoveryCode(code: string) {\n await manager.submitRecoveryCode(code);\n }\n\n return {\n state: readonly(state),\n isAuthenticated,\n isLoading,\n user,\n session,\n error,\n client: manager.getClient(),\n signIn,\n signUp,\n signOut,\n submitMFACode,\n submitRecoveryCode,\n };\n}\n\n/**\n * Composable to fetch and reload the user profile.\n */\nexport function useUser() {\n const { user: authUser, isLoading, session } = useAuth();\n const manager = useManager();\n const localUser = ref<User | null>(authUser.value);\n\n // Keep in sync with auth state.\n const stopWatch = computed(() => authUser.value);\n\n async function reload() {\n if (!session.value) return;\n const u = await manager.getClient().getMe(session.value.session_token);\n localUser.value = u;\n }\n\n return {\n user: computed(() => localUser.value ?? authUser.value),\n isLoading,\n reload,\n };\n}\n\n/**\n * Composable to list organizations.\n */\nexport function useOrganizations() {\n const { session, isAuthenticated } = useAuth();\n const manager = useManager();\n\n const organizations = ref<Organization[]>([]);\n const total = ref(0);\n const isLoading = ref(false);\n\n async function load() {\n if (!session.value) return;\n isLoading.value = true;\n try {\n const res = await manager\n .getClient()\n .listOrganizations(session.value.session_token) as unknown as ListResponse<Organization>;\n organizations.value = res.items;\n total.value = res.total;\n } finally {\n isLoading.value = false;\n }\n }\n\n onMounted(() => {\n if (isAuthenticated.value) {\n void load();\n }\n });\n\n return {\n organizations: readonly(organizations),\n total: readonly(total),\n isLoading: readonly(isLoading),\n reload: load,\n };\n}\n\n/**\n * Composable that returns the current session token.\n */\nexport function useSessionToken() {\n const { session } = useAuth();\n return computed(() => session.value?.session_token ?? null);\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@authsome/ui-vue",
3
+ "version": "1.0.0",
4
+ "description": "Vue.js bindings for AuthSome authentication UI",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/xraph/authsome.git",
13
+ "directory": "ui/packages/vue"
14
+ },
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "import": "./dist/index.js",
20
+ "types": "./dist/index.d.ts"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "dev": "tsup --watch",
29
+ "typecheck": "tsc --noEmit",
30
+ "clean": "rm -rf dist"
31
+ },
32
+ "dependencies": {
33
+ "@authsome/ui-core": "^1.0.0"
34
+ },
35
+ "peerDependencies": {
36
+ "vue": "^3.3.0"
37
+ },
38
+ "devDependencies": {
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.3.0",
41
+ "vue": "^3.4.0"
42
+ }
43
+ }