@korajs/auth 1.0.0-beta.12 → 1.0.0-beta.13

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 (101) hide show
  1. package/README.md +52 -47
  2. package/dist/{create-org-session-RsDj9cl4.d.cts → create-org-session-ChFdulEM.d.cts} +211 -17
  3. package/dist/{create-org-session-RsDj9cl4.d.ts → create-org-session-ChFdulEM.d.ts} +211 -17
  4. package/dist/index.cjs +645 -150
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +27 -9
  7. package/dist/index.d.ts +27 -9
  8. package/dist/index.js +644 -150
  9. package/dist/index.js.map +1 -1
  10. package/dist/{operation-encryptor-DRmKNWpF.d.cts → operation-encryptor-DDdlb9bm.d.cts} +16 -0
  11. package/dist/{operation-encryptor-DRmKNWpF.d.ts → operation-encryptor-DDdlb9bm.d.ts} +16 -0
  12. package/dist/react.d.cts +2 -2
  13. package/dist/react.d.ts +2 -2
  14. package/dist/server.cjs +2852 -1675
  15. package/dist/server.cjs.map +1 -1
  16. package/dist/server.d.cts +779 -168
  17. package/dist/server.d.ts +779 -168
  18. package/dist/server.js +2831 -1665
  19. package/dist/server.js.map +1 -1
  20. package/dist/svelte.cjs +2 -2
  21. package/dist/svelte.cjs.map +1 -1
  22. package/dist/svelte.d.cts +2 -2
  23. package/dist/svelte.d.ts +2 -2
  24. package/dist/svelte.js +2 -2
  25. package/dist/svelte.js.map +1 -1
  26. package/dist/vue.d.cts +1 -1
  27. package/dist/vue.d.ts +1 -1
  28. package/package.json +7 -7
  29. package/src/admin/admin-api.ts +327 -0
  30. package/src/admin/audit-log.ts +324 -0
  31. package/src/admin/webhooks.ts +576 -0
  32. package/src/bindings/create-auth-session.ts +184 -0
  33. package/src/bindings/create-org-session.ts +130 -0
  34. package/src/client/auth-client.ts +1592 -0
  35. package/src/client/auth-sync.ts +213 -0
  36. package/src/client/device-session.ts +104 -0
  37. package/src/client/org-client.ts +399 -0
  38. package/src/client/quickstart.ts +108 -0
  39. package/src/client/storage.ts +94 -0
  40. package/src/device/device-identity.ts +330 -0
  41. package/src/device/device-store.ts +379 -0
  42. package/src/encryption/auto-lock.ts +170 -0
  43. package/src/encryption/database-encryption.ts +265 -0
  44. package/src/encryption/key-derivation.ts +149 -0
  45. package/src/encryption/operation-encryptor.ts +361 -0
  46. package/src/index.ts +132 -0
  47. package/src/mfa/totp.ts +826 -0
  48. package/src/org/org-routes.ts +758 -0
  49. package/src/org/org-store.ts +490 -0
  50. package/src/org/org-types.ts +230 -0
  51. package/src/passkey/passkey-client.ts +597 -0
  52. package/src/passkey/passkey-server.ts +779 -0
  53. package/src/postgres/ensure-schema.ts +65 -0
  54. package/src/provider/adapter.ts +246 -0
  55. package/src/provider/built-in/auth-routes.ts +1313 -0
  56. package/src/provider/built-in/email-verification.ts +303 -0
  57. package/src/provider/built-in/password-hash.ts +118 -0
  58. package/src/provider/built-in/password-reset.ts +416 -0
  59. package/src/provider/built-in/postgres-user-store.ts +328 -0
  60. package/src/provider/built-in/quickstart-server.ts +760 -0
  61. package/src/provider/built-in/sqlite-user-store.ts +322 -0
  62. package/src/provider/built-in/sync-scopes.ts +85 -0
  63. package/src/provider/built-in/user-store.ts +465 -0
  64. package/src/provider/external/clerk-adapter.ts +157 -0
  65. package/src/provider/external/external-jwt-provider.ts +491 -0
  66. package/src/provider/external/supabase-adapter.ts +163 -0
  67. package/src/provider/oauth/linked-identity-store.ts +108 -0
  68. package/src/provider/oauth/oauth-flow.ts +550 -0
  69. package/src/provider/oauth/oauth-types.ts +184 -0
  70. package/src/provider/oauth/postgres-oauth-store.ts +296 -0
  71. package/src/provider/oauth/sqlite-oauth-store.ts +272 -0
  72. package/src/rbac/rbac-engine.ts +323 -0
  73. package/src/rbac/rbac-types.ts +210 -0
  74. package/src/rbac/scope-resolver.ts +140 -0
  75. package/src/react/AuthProvider.tsx +97 -0
  76. package/src/react/OrgProvider.tsx +41 -0
  77. package/src/react/auth-context.ts +26 -0
  78. package/src/react/hooks.ts +110 -0
  79. package/src/react/org-hooks.ts +214 -0
  80. package/src/react.ts +26 -0
  81. package/src/server.ts +334 -0
  82. package/src/session/session.ts +401 -0
  83. package/src/svelte/auth-context.ts +50 -0
  84. package/src/svelte/org-context.ts +32 -0
  85. package/src/svelte/org-hooks.ts +201 -0
  86. package/src/svelte/use-auth.ts +115 -0
  87. package/src/svelte.ts +25 -0
  88. package/src/tokens/encrypted-token-store.ts +360 -0
  89. package/src/tokens/jwt.ts +236 -0
  90. package/src/tokens/postgres-token-revocation-store.ts +140 -0
  91. package/src/tokens/sqlite-token-revocation-store.ts +121 -0
  92. package/src/tokens/token-manager.ts +821 -0
  93. package/src/tokens/token-store.ts +192 -0
  94. package/src/types.ts +394 -0
  95. package/src/vue/auth-context.ts +10 -0
  96. package/src/vue/auth-provider-types.ts +5 -0
  97. package/src/vue/auth-provider.ts +76 -0
  98. package/src/vue/org-hooks.ts +193 -0
  99. package/src/vue/org-provider.ts +49 -0
  100. package/src/vue/use-auth.ts +139 -0
  101. package/src/vue.ts +10 -0
@@ -0,0 +1,193 @@
1
+ import { onScopeDispose, reactive, readonly, ref, watch } from 'vue'
2
+ import {
3
+ type OrgSnapshot,
4
+ createOrgMembersActions,
5
+ loadOrgMembers,
6
+ } from '../bindings/create-org-session'
7
+ import type { ClientInvitation, ClientMembership, ClientOrganization } from '../client/org-client'
8
+ import { useOrgContext } from './org-provider'
9
+
10
+ export interface UseOrgResult {
11
+ org: ClientOrganization | null
12
+ role: string | null
13
+ orgId: string | null
14
+ switchOrg: (orgId: string) => Promise<void>
15
+ createOrg: (params: { name: string; slug?: string }) => Promise<ClientOrganization>
16
+ leaveOrg: () => Promise<void>
17
+ clearOrg: () => void
18
+ listOrgs: () => Promise<ClientOrganization[]>
19
+ error: string | null
20
+ }
21
+
22
+ export interface UseOrgMembersResult {
23
+ members: ClientMembership[]
24
+ isLoading: boolean
25
+ refresh: () => Promise<void>
26
+ invite: (email: string, role: string) => Promise<ClientInvitation>
27
+ removeMember: (userId: string) => Promise<void>
28
+ updateRole: (userId: string, role: string) => Promise<void>
29
+ error: string | null
30
+ }
31
+
32
+ function useOrgSnapshot(session: ReturnType<typeof useOrgContext>['session']): OrgSnapshot {
33
+ const state = reactive({ ...session.getSnapshot() })
34
+
35
+ const sync = (): void => {
36
+ Object.assign(state, session.getSnapshot())
37
+ }
38
+
39
+ const unsubscribe = session.subscribe(sync)
40
+ sync()
41
+
42
+ onScopeDispose(unsubscribe)
43
+
44
+ return state
45
+ }
46
+
47
+ export function useOrg(): UseOrgResult {
48
+ const { client, session } = useOrgContext()
49
+ const snapshot = useOrgSnapshot(session)
50
+ const error = ref<string | null>(null)
51
+
52
+ const switchOrg = async (orgId: string): Promise<void> => {
53
+ error.value = null
54
+ try {
55
+ await client.switchOrg(orgId)
56
+ } catch (err) {
57
+ error.value = err instanceof Error ? err.message : String(err)
58
+ }
59
+ }
60
+
61
+ const createOrg = async (params: {
62
+ name: string
63
+ slug?: string
64
+ }): Promise<ClientOrganization> => {
65
+ error.value = null
66
+ try {
67
+ return await client.createOrg(params)
68
+ } catch (err) {
69
+ const message = err instanceof Error ? err.message : String(err)
70
+ error.value = message
71
+ throw err
72
+ }
73
+ }
74
+
75
+ const leaveOrg = async (): Promise<void> => {
76
+ if (!snapshot.orgId) return
77
+ error.value = null
78
+ try {
79
+ await client.leaveOrg(snapshot.orgId)
80
+ } catch (err) {
81
+ error.value = err instanceof Error ? err.message : String(err)
82
+ }
83
+ }
84
+
85
+ const clearOrg = (): void => {
86
+ client.clearActiveOrg()
87
+ }
88
+
89
+ const listOrgs = async (): Promise<ClientOrganization[]> => {
90
+ try {
91
+ return await client.listOrgs()
92
+ } catch (err) {
93
+ error.value = err instanceof Error ? err.message : String(err)
94
+ return []
95
+ }
96
+ }
97
+
98
+ return {
99
+ get org() {
100
+ return snapshot.org
101
+ },
102
+ get role() {
103
+ return snapshot.role
104
+ },
105
+ get orgId() {
106
+ return snapshot.orgId
107
+ },
108
+ switchOrg,
109
+ createOrg,
110
+ leaveOrg,
111
+ clearOrg,
112
+ listOrgs,
113
+ get error() {
114
+ return error.value
115
+ },
116
+ }
117
+ }
118
+
119
+ export function useOrgMembers(orgId: string): UseOrgMembersResult {
120
+ const { client } = useOrgContext()
121
+ const members = ref<ClientMembership[]>([])
122
+ const isLoading = ref(true)
123
+ const error = ref<string | null>(null)
124
+
125
+ const refresh = async (): Promise<void> => {
126
+ isLoading.value = true
127
+ error.value = null
128
+ try {
129
+ members.value = await loadOrgMembers(client, orgId)
130
+ } catch (err) {
131
+ error.value = err instanceof Error ? err.message : String(err)
132
+ } finally {
133
+ isLoading.value = false
134
+ }
135
+ }
136
+
137
+ watch(
138
+ () => orgId,
139
+ () => {
140
+ void refresh()
141
+ },
142
+ { immediate: true },
143
+ )
144
+
145
+ const actions = createOrgMembersActions(client, orgId, (message) => {
146
+ error.value = message
147
+ })
148
+
149
+ const invite = async (email: string, role: string): Promise<ClientInvitation> => {
150
+ const result = await actions.invite(email, role)
151
+ await refresh()
152
+ return result
153
+ }
154
+
155
+ const removeMember = async (userId: string): Promise<void> => {
156
+ await actions.removeMember(userId)
157
+ await refresh()
158
+ }
159
+
160
+ const updateRole = async (userId: string, role: string): Promise<void> => {
161
+ await actions.updateRole(userId, role)
162
+ await refresh()
163
+ }
164
+
165
+ return {
166
+ get members() {
167
+ return members.value
168
+ },
169
+ get isLoading() {
170
+ return isLoading.value
171
+ },
172
+ refresh,
173
+ invite,
174
+ removeMember,
175
+ updateRole,
176
+ get error() {
177
+ return error.value
178
+ },
179
+ }
180
+ }
181
+
182
+ export function usePermission(requiredRole: string): Readonly<{ value: boolean }> {
183
+ const { session } = useOrgContext()
184
+ const allowed = ref(session.checkPermission(requiredRole))
185
+
186
+ const unsubscribe = session.subscribe(() => {
187
+ allowed.value = session.checkPermission(requiredRole)
188
+ })
189
+
190
+ onScopeDispose(unsubscribe)
191
+
192
+ return readonly(allowed)
193
+ }
@@ -0,0 +1,49 @@
1
+ import type { InjectionKey } from 'vue'
2
+ import type { PropType } from 'vue'
3
+ import { defineComponent, inject, onScopeDispose, provide } from 'vue'
4
+ import { type OrgSession, createOrgSession } from '../bindings/create-org-session'
5
+ import type { OrgClient } from '../client/org-client'
6
+
7
+ export interface OrgContextValue {
8
+ client: OrgClient
9
+ session: OrgSession
10
+ }
11
+
12
+ export const orgContextKey: InjectionKey<OrgContextValue> = Symbol('korajs-org-context')
13
+
14
+ export const OrgProvider = defineComponent({
15
+ name: 'OrgProvider',
16
+ props: {
17
+ client: {
18
+ type: Object as PropType<OrgClient>,
19
+ required: true,
20
+ },
21
+ },
22
+ setup(props, { slots }) {
23
+ const session = createOrgSession(props.client)
24
+
25
+ onScopeDispose(() => {
26
+ session.destroy()
27
+ })
28
+
29
+ const contextValue: OrgContextValue = {
30
+ client: props.client,
31
+ session,
32
+ }
33
+
34
+ provide(orgContextKey, contextValue)
35
+
36
+ return () => slots.default?.()
37
+ },
38
+ })
39
+
40
+ export function useOrgContext(): OrgContextValue {
41
+ const context = inject(orgContextKey)
42
+ if (!context) {
43
+ throw new Error(
44
+ 'useOrg / useOrgMembers / usePermission must be used within an <OrgProvider>. ' +
45
+ 'Wrap your component tree with <OrgProvider :client="orgClient">.',
46
+ )
47
+ }
48
+ return context
49
+ }
@@ -0,0 +1,139 @@
1
+ import { computed, onScopeDispose, reactive } from 'vue'
2
+ import type {
3
+ AuthUser,
4
+ LinkedOAuthAccount,
5
+ OAuthAuthorizationOptions,
6
+ OAuthAuthorizationResult,
7
+ OAuthCallbackParams,
8
+ } from '../client/auth-client'
9
+ import { useAuthContext } from './auth-provider'
10
+
11
+ export interface UseAuthResult {
12
+ user: AuthUser | null
13
+ isAuthenticated: boolean
14
+ isLoading: boolean
15
+ signUp: (params: {
16
+ email: string
17
+ password: string
18
+ name?: string
19
+ deviceId?: string
20
+ devicePublicKey?: string
21
+ }) => Promise<void>
22
+ signIn: (params: {
23
+ email: string
24
+ password: string
25
+ deviceId?: string
26
+ devicePublicKey?: string
27
+ }) => Promise<void>
28
+ signInWithOAuth: (
29
+ provider: string,
30
+ options?: OAuthAuthorizationOptions,
31
+ ) => Promise<OAuthAuthorizationResult>
32
+ completeOAuthSignIn: (provider: string, params: OAuthCallbackParams) => Promise<void>
33
+ getOAuthAuthorizationUrl: (
34
+ provider: string,
35
+ options?: OAuthAuthorizationOptions,
36
+ ) => Promise<OAuthAuthorizationResult>
37
+ linkOAuth: (provider: string, params: OAuthCallbackParams) => Promise<LinkedOAuthAccount | null>
38
+ listLinkedAccounts: () => Promise<LinkedOAuthAccount[]>
39
+ unlinkOAuth: (provider: string) => Promise<void>
40
+ signOut: () => Promise<void>
41
+ error: string | null
42
+ }
43
+
44
+ export interface AuthStatus {
45
+ state: import('../client/auth-client').AuthState
46
+ isAuthenticated: boolean
47
+ isLoading: boolean
48
+ }
49
+
50
+ export function useAuth(): UseAuthResult {
51
+ const { session } = useAuthContext()
52
+ const state = reactive({ ...session.getSnapshot() })
53
+
54
+ const sync = (): void => {
55
+ Object.assign(state, session.getSnapshot())
56
+ }
57
+
58
+ const unsubscribe = session.subscribe(sync)
59
+ sync()
60
+
61
+ onScopeDispose(unsubscribe)
62
+
63
+ return {
64
+ get user() {
65
+ return state.user
66
+ },
67
+ get isAuthenticated() {
68
+ return state.isAuthenticated
69
+ },
70
+ get isLoading() {
71
+ return state.isLoading
72
+ },
73
+ get error() {
74
+ return state.error
75
+ },
76
+ signUp: (params) => session.signUp(params).then(sync),
77
+ signIn: (params) => session.signIn(params).then(sync),
78
+ signInWithOAuth: (provider, options) =>
79
+ session.signInWithOAuth(provider, options).then((result) => {
80
+ sync()
81
+ return result
82
+ }),
83
+ completeOAuthSignIn: (provider, params) =>
84
+ session.completeOAuthSignIn(provider, params).then(sync),
85
+ getOAuthAuthorizationUrl: (provider, options) =>
86
+ session.getOAuthAuthorizationUrl(provider, options).then((result) => {
87
+ sync()
88
+ return result
89
+ }),
90
+ linkOAuth: (provider, params) =>
91
+ session.linkOAuth(provider, params).then((result) => {
92
+ sync()
93
+ return result
94
+ }),
95
+ listLinkedAccounts: () =>
96
+ session.listLinkedAccounts().then((result) => {
97
+ sync()
98
+ return result
99
+ }),
100
+ unlinkOAuth: (provider) => session.unlinkOAuth(provider).then(sync),
101
+ signOut: () => session.signOut().then(sync),
102
+ }
103
+ }
104
+
105
+ export function useCurrentUser() {
106
+ const { session } = useAuthContext()
107
+ const state = reactive({ user: session.getSnapshot().user })
108
+
109
+ const sync = (): void => {
110
+ state.user = session.getSnapshot().user
111
+ }
112
+
113
+ const unsubscribe = session.subscribe(sync)
114
+ onScopeDispose(unsubscribe)
115
+
116
+ return computed(() => state.user)
117
+ }
118
+
119
+ export function useAuthStatus(): AuthStatus {
120
+ const { session } = useAuthContext()
121
+ const state = reactive({
122
+ state: session.getSnapshot().state,
123
+ isAuthenticated: session.getSnapshot().isAuthenticated,
124
+ isLoading: session.getSnapshot().isLoading,
125
+ })
126
+
127
+ const sync = (): void => {
128
+ const snapshot = session.getSnapshot()
129
+ state.state = snapshot.state
130
+ state.isAuthenticated = snapshot.isAuthenticated
131
+ state.isLoading = snapshot.isLoading
132
+ }
133
+
134
+ const unsubscribe = session.subscribe(sync)
135
+ sync()
136
+ onScopeDispose(unsubscribe)
137
+
138
+ return state
139
+ }
package/src/vue.ts ADDED
@@ -0,0 +1,10 @@
1
+ export { AuthProvider, useAuthContext } from './vue/auth-provider'
2
+ export type { AuthProviderProps } from './vue/auth-provider-types'
3
+ export { useAuth, useCurrentUser, useAuthStatus } from './vue/use-auth'
4
+ export type { UseAuthResult, AuthStatus } from './vue/use-auth'
5
+ export { authContextKey } from './vue/auth-context'
6
+ export type { AuthContextValue } from './vue/auth-context'
7
+ export { OrgProvider, useOrgContext } from './vue/org-provider'
8
+ export type { OrgContextValue } from './vue/org-provider'
9
+ export { useOrg, useOrgMembers, usePermission } from './vue/org-hooks'
10
+ export type { UseOrgResult, UseOrgMembersResult } from './vue/org-hooks'