@korajs/auth 1.0.0-beta.11 → 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,184 @@
1
+ import type {
2
+ AuthClient,
3
+ AuthState,
4
+ AuthUser,
5
+ LinkedOAuthAccount,
6
+ OAuthAuthorizationOptions,
7
+ OAuthAuthorizationResult,
8
+ OAuthCallbackParams,
9
+ } from '../client/auth-client'
10
+
11
+ export interface AuthSessionSnapshot {
12
+ state: AuthState
13
+ user: AuthUser | null
14
+ isAuthenticated: boolean
15
+ isLoading: boolean
16
+ initError: Error | null
17
+ error: string | null
18
+ }
19
+
20
+ export interface AuthSession {
21
+ readonly client: AuthClient
22
+ getSnapshot(): AuthSessionSnapshot
23
+ subscribe(listener: () => void): () => void
24
+ signUp(params: {
25
+ email: string
26
+ password: string
27
+ name?: string
28
+ deviceId?: string
29
+ devicePublicKey?: string
30
+ }): Promise<void>
31
+ signIn(params: {
32
+ email: string
33
+ password: string
34
+ deviceId?: string
35
+ devicePublicKey?: string
36
+ }): Promise<void>
37
+ signInWithOAuth(
38
+ provider: string,
39
+ options?: OAuthAuthorizationOptions,
40
+ ): Promise<OAuthAuthorizationResult>
41
+ completeOAuthSignIn(provider: string, params: OAuthCallbackParams): Promise<void>
42
+ getOAuthAuthorizationUrl(
43
+ provider: string,
44
+ options?: OAuthAuthorizationOptions,
45
+ ): Promise<OAuthAuthorizationResult>
46
+ linkOAuth(provider: string, params: OAuthCallbackParams): Promise<LinkedOAuthAccount | null>
47
+ listLinkedAccounts(): Promise<LinkedOAuthAccount[]>
48
+ unlinkOAuth(provider: string): Promise<void>
49
+ signOut(): Promise<void>
50
+ destroy(): void
51
+ }
52
+
53
+ /**
54
+ * Framework-agnostic auth session: initialization, reactive snapshot, and client methods.
55
+ */
56
+ export function createAuthSession(client: AuthClient): AuthSession {
57
+ let state: AuthState = client.state
58
+ let isLoading = true
59
+ let initError: Error | null = null
60
+ let lastError: string | null = null
61
+
62
+ const listeners = new Set<() => void>()
63
+ let snapshot = buildSnapshot()
64
+
65
+ const refreshSnapshot = (): void => {
66
+ snapshot = buildSnapshot()
67
+ }
68
+
69
+ const notify = (): void => {
70
+ refreshSnapshot()
71
+ for (const listener of listeners) {
72
+ listener()
73
+ }
74
+ }
75
+
76
+ function buildSnapshot(): AuthSessionSnapshot {
77
+ return {
78
+ state,
79
+ user: client.currentUser,
80
+ isAuthenticated: state === 'authenticated',
81
+ isLoading,
82
+ initError,
83
+ error: lastError,
84
+ }
85
+ }
86
+
87
+ const captureError = (error: unknown): void => {
88
+ lastError = error instanceof Error ? error.message : String(error)
89
+ notify()
90
+ }
91
+
92
+ const run = async (action: () => Promise<void>): Promise<void> => {
93
+ lastError = null
94
+ try {
95
+ await action()
96
+ } catch (error) {
97
+ captureError(error)
98
+ }
99
+ }
100
+
101
+ const runWithResult = async <T>(action: () => Promise<T>): Promise<T | null> => {
102
+ lastError = null
103
+ try {
104
+ return await action()
105
+ } catch (error) {
106
+ captureError(error)
107
+ return null
108
+ }
109
+ }
110
+
111
+ const unsubscribeAuth = client.onAuthChange((nextState) => {
112
+ state = nextState
113
+ notify()
114
+ })
115
+
116
+ void client
117
+ .initialize()
118
+ .then(() => {
119
+ state = client.state
120
+ isLoading = false
121
+ notify()
122
+ })
123
+ .catch((error: unknown) => {
124
+ initError = error instanceof Error ? error : new Error(String(error))
125
+ isLoading = false
126
+ notify()
127
+ })
128
+
129
+ return {
130
+ client,
131
+ getSnapshot: () => snapshot,
132
+ subscribe(listener) {
133
+ listeners.add(listener)
134
+ return () => {
135
+ listeners.delete(listener)
136
+ }
137
+ },
138
+ signUp: (params) =>
139
+ run(async () => {
140
+ await client.signUp(params)
141
+ }),
142
+ signIn: (params) =>
143
+ run(async () => {
144
+ await client.signIn(params)
145
+ }),
146
+ signInWithOAuth: async (provider, options) => {
147
+ lastError = null
148
+ try {
149
+ return await client.signInWithOAuth(provider, options)
150
+ } catch (error) {
151
+ captureError(error)
152
+ throw error instanceof Error ? error : new Error(String(error))
153
+ }
154
+ },
155
+ completeOAuthSignIn: (provider, params) =>
156
+ run(async () => {
157
+ await client.completeOAuthSignIn(provider, params)
158
+ }),
159
+ getOAuthAuthorizationUrl: async (provider, options) => {
160
+ lastError = null
161
+ try {
162
+ return await client.getOAuthAuthorizationUrl(provider, options)
163
+ } catch (error) {
164
+ captureError(error)
165
+ throw error instanceof Error ? error : new Error(String(error))
166
+ }
167
+ },
168
+ linkOAuth: (provider, params) => runWithResult(async () => client.linkOAuth(provider, params)),
169
+ listLinkedAccounts: () =>
170
+ runWithResult(async () => client.listLinkedAccounts()).then((value) => value ?? []),
171
+ unlinkOAuth: (provider) =>
172
+ run(async () => {
173
+ await client.unlinkOAuth(provider)
174
+ }),
175
+ signOut: () =>
176
+ run(async () => {
177
+ await client.signOut()
178
+ }),
179
+ destroy() {
180
+ unsubscribeAuth()
181
+ listeners.clear()
182
+ },
183
+ }
184
+ }
@@ -0,0 +1,130 @@
1
+ import type {
2
+ ClientInvitation,
3
+ ClientMembership,
4
+ ClientOrganization,
5
+ OrgClient,
6
+ } from '../client/org-client'
7
+
8
+ export interface OrgSnapshot {
9
+ orgId: string | null
10
+ org: ClientOrganization | null
11
+ role: string | null
12
+ }
13
+
14
+ export interface OrgSession {
15
+ readonly client: OrgClient
16
+ getSnapshot(): OrgSnapshot
17
+ subscribe(listener: () => void): () => void
18
+ checkPermission(requiredRole: string): boolean
19
+ destroy(): void
20
+ }
21
+
22
+ const ROLE_LEVELS: Record<string, number> = {
23
+ viewer: 10,
24
+ billing: 15,
25
+ member: 20,
26
+ admin: 30,
27
+ owner: 40,
28
+ }
29
+
30
+ export function checkOrgPermission(currentRole: string | null, requiredRole: string): boolean {
31
+ if (!currentRole) return false
32
+ const currentLevel = ROLE_LEVELS[currentRole] ?? 0
33
+ const requiredLevel = ROLE_LEVELS[requiredRole] ?? 0
34
+ return currentLevel >= requiredLevel
35
+ }
36
+
37
+ /**
38
+ * Framework-agnostic org session with reactive snapshot subscription.
39
+ */
40
+ export function createOrgSession(client: OrgClient): OrgSession {
41
+ let snapshot = buildSnapshot(client)
42
+ const listeners = new Set<() => void>()
43
+
44
+ const notify = (): void => {
45
+ snapshot = buildSnapshot(client)
46
+ for (const listener of listeners) {
47
+ listener()
48
+ }
49
+ }
50
+
51
+ const unsubscribeOrgChange = client.onOrgChange(notify)
52
+
53
+ return {
54
+ client,
55
+ getSnapshot: () => snapshot,
56
+ subscribe(listener: () => void): () => void {
57
+ listeners.add(listener)
58
+ return () => {
59
+ listeners.delete(listener)
60
+ }
61
+ },
62
+ checkPermission(requiredRole: string): boolean {
63
+ return checkOrgPermission(snapshot.role, requiredRole)
64
+ },
65
+ destroy(): void {
66
+ unsubscribeOrgChange()
67
+ listeners.clear()
68
+ },
69
+ }
70
+ }
71
+
72
+ function buildSnapshot(client: OrgClient): OrgSnapshot {
73
+ return {
74
+ orgId: client.activeOrgId,
75
+ org: client.activeOrg,
76
+ role: client.activeRole,
77
+ }
78
+ }
79
+
80
+ export interface UseOrgMembersActions {
81
+ refresh: () => Promise<void>
82
+ invite: (email: string, role: string) => Promise<ClientInvitation>
83
+ removeMember: (userId: string) => Promise<void>
84
+ updateRole: (userId: string, role: string) => Promise<void>
85
+ }
86
+
87
+ /**
88
+ * Shared org member management actions (loading state remains framework-specific).
89
+ */
90
+ export function createOrgMembersActions(
91
+ client: OrgClient,
92
+ orgId: string,
93
+ onError: (message: string) => void,
94
+ ): UseOrgMembersActions {
95
+ return {
96
+ async refresh(): Promise<void> {
97
+ await client.listMembers(orgId)
98
+ },
99
+ async invite(email: string, role: string): Promise<ClientInvitation> {
100
+ try {
101
+ return await client.inviteMember(orgId, { email, role })
102
+ } catch (error) {
103
+ const message = error instanceof Error ? error.message : String(error)
104
+ onError(message)
105
+ throw error
106
+ }
107
+ },
108
+ async removeMember(userId: string): Promise<void> {
109
+ try {
110
+ await client.removeMember(orgId, userId)
111
+ } catch (error) {
112
+ onError(error instanceof Error ? error.message : String(error))
113
+ }
114
+ },
115
+ async updateRole(userId: string, role: string): Promise<void> {
116
+ try {
117
+ await client.updateMemberRole(orgId, userId, role)
118
+ } catch (error) {
119
+ onError(error instanceof Error ? error.message : String(error))
120
+ }
121
+ },
122
+ }
123
+ }
124
+
125
+ export async function loadOrgMembers(
126
+ client: OrgClient,
127
+ orgId: string,
128
+ ): Promise<ClientMembership[]> {
129
+ return client.listMembers(orgId)
130
+ }