@passlock/client 0.9.30 → 2.0.0-beta.1

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 (180) hide show
  1. package/README.md +14 -86
  2. package/README.template.md +16 -88
  3. package/dist/index.d.ts +4 -206
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +2 -158
  6. package/dist/index.js.map +1 -1
  7. package/dist/logger/index.d.ts +24 -0
  8. package/dist/logger/index.d.ts.map +1 -0
  9. package/dist/logger/index.js +47 -0
  10. package/dist/logger/index.js.map +1 -0
  11. package/dist/network.d.ts +39 -0
  12. package/dist/network.d.ts.map +1 -0
  13. package/dist/network.js +83 -0
  14. package/dist/network.js.map +1 -0
  15. package/dist/passkey/authentication/index.d.ts +21 -0
  16. package/dist/passkey/authentication/index.d.ts.map +1 -0
  17. package/dist/passkey/authentication/index.js +22 -0
  18. package/dist/passkey/authentication/index.js.map +1 -0
  19. package/dist/passkey/authentication/micro.d.ts +71 -0
  20. package/dist/passkey/authentication/micro.d.ts.map +1 -0
  21. package/dist/passkey/authentication/micro.js +107 -0
  22. package/dist/passkey/authentication/micro.js.map +1 -0
  23. package/dist/passkey/index.d.ts +7 -0
  24. package/dist/passkey/index.d.ts.map +1 -0
  25. package/dist/passkey/index.js +5 -0
  26. package/dist/passkey/index.js.map +1 -0
  27. package/dist/passkey/registration/index.d.ts +19 -0
  28. package/dist/passkey/registration/index.d.ts.map +1 -0
  29. package/dist/passkey/registration/index.js +20 -0
  30. package/dist/passkey/registration/index.js.map +1 -0
  31. package/dist/passkey/registration/micro.d.ts +101 -0
  32. package/dist/passkey/registration/micro.d.ts.map +1 -0
  33. package/dist/passkey/registration/micro.js +126 -0
  34. package/dist/passkey/registration/micro.js.map +1 -0
  35. package/dist/passkey/shared.d.ts +24 -0
  36. package/dist/passkey/shared.d.ts.map +1 -0
  37. package/dist/passkey/shared.js +10 -0
  38. package/dist/passkey/shared.js.map +1 -0
  39. package/dist/passkey/support.d.ts +3 -0
  40. package/dist/passkey/support.d.ts.map +1 -0
  41. package/dist/passkey/support.js +4 -0
  42. package/dist/passkey/support.js.map +1 -0
  43. package/dist/passkey/types.d.ts +26 -0
  44. package/dist/passkey/types.d.ts.map +1 -0
  45. package/dist/passkey/types.js +2 -0
  46. package/dist/passkey/types.js.map +1 -0
  47. package/dist/promise.d.ts +15 -0
  48. package/dist/promise.d.ts.map +1 -0
  49. package/dist/promise.js +46 -0
  50. package/dist/promise.js.map +1 -0
  51. package/dist/shared.d.ts +15 -0
  52. package/dist/shared.d.ts.map +1 -0
  53. package/dist/shared.js +2 -0
  54. package/dist/shared.js.map +1 -0
  55. package/dist/tenancy.d.ts +8 -0
  56. package/dist/tenancy.d.ts.map +1 -0
  57. package/dist/tenancy.js +4 -0
  58. package/dist/tenancy.js.map +1 -0
  59. package/package.json +52 -58
  60. package/LICENSE +0 -21
  61. package/dist/authentication/authenticate.d.ts +0 -24
  62. package/dist/authentication/authenticate.fixture.d.ts +0 -52
  63. package/dist/authentication/authenticate.fixture.js +0 -50
  64. package/dist/authentication/authenticate.fixture.js.map +0 -1
  65. package/dist/authentication/authenticate.js +0 -73
  66. package/dist/authentication/authenticate.js.map +0 -1
  67. package/dist/capabilities/capabilities.d.ts +0 -19
  68. package/dist/capabilities/capabilities.js +0 -37
  69. package/dist/capabilities/capabilities.js.map +0 -1
  70. package/dist/connection/connection.d.ts +0 -15
  71. package/dist/connection/connection.fixture.d.ts +0 -10
  72. package/dist/connection/connection.fixture.js +0 -13
  73. package/dist/connection/connection.fixture.js.map +0 -1
  74. package/dist/connection/connection.js +0 -23
  75. package/dist/connection/connection.js.map +0 -1
  76. package/dist/effect.d.ts +0 -26
  77. package/dist/effect.js +0 -78
  78. package/dist/effect.js.map +0 -1
  79. package/dist/email/email.d.ts +0 -70
  80. package/dist/email/email.fixture.d.ts +0 -46
  81. package/dist/email/email.fixture.js +0 -25
  82. package/dist/email/email.fixture.js.map +0 -1
  83. package/dist/email/email.js +0 -83
  84. package/dist/email/email.js.map +0 -1
  85. package/dist/event/event.d.ts +0 -8
  86. package/dist/event/event.js +0 -23
  87. package/dist/event/event.js.map +0 -1
  88. package/dist/logging/eventLogger.d.ts +0 -17
  89. package/dist/logging/eventLogger.js +0 -38
  90. package/dist/logging/eventLogger.js.map +0 -1
  91. package/dist/registration/register.d.ts +0 -27
  92. package/dist/registration/register.fixture.d.ts +0 -53
  93. package/dist/registration/register.fixture.js +0 -66
  94. package/dist/registration/register.fixture.js.map +0 -1
  95. package/dist/registration/register.js +0 -78
  96. package/dist/registration/register.js.map +0 -1
  97. package/dist/rpc/authentication.d.ts +0 -8
  98. package/dist/rpc/authentication.js +0 -16
  99. package/dist/rpc/authentication.js.map +0 -1
  100. package/dist/rpc/client.d.ts +0 -30
  101. package/dist/rpc/client.js +0 -101
  102. package/dist/rpc/client.js.map +0 -1
  103. package/dist/rpc/config.d.ts +0 -15
  104. package/dist/rpc/config.js +0 -6
  105. package/dist/rpc/config.js.map +0 -1
  106. package/dist/rpc/connection.d.ts +0 -8
  107. package/dist/rpc/connection.js +0 -15
  108. package/dist/rpc/connection.js.map +0 -1
  109. package/dist/rpc/registration.d.ts +0 -8
  110. package/dist/rpc/registration.js +0 -16
  111. package/dist/rpc/registration.js.map +0 -1
  112. package/dist/rpc/social.d.ts +0 -10
  113. package/dist/rpc/social.js +0 -18
  114. package/dist/rpc/social.js.map +0 -1
  115. package/dist/rpc/user.d.ts +0 -8
  116. package/dist/rpc/user.js +0 -19
  117. package/dist/rpc/user.js.map +0 -1
  118. package/dist/social/social.d.ts +0 -24
  119. package/dist/social/social.fixture.d.ts +0 -46
  120. package/dist/social/social.fixture.js +0 -31
  121. package/dist/social/social.fixture.js.map +0 -1
  122. package/dist/social/social.js +0 -39
  123. package/dist/social/social.js.map +0 -1
  124. package/dist/storage/storage.d.ts +0 -56
  125. package/dist/storage/storage.fixture.d.ts +0 -4
  126. package/dist/storage/storage.fixture.js +0 -10
  127. package/dist/storage/storage.fixture.js.map +0 -1
  128. package/dist/storage/storage.js +0 -111
  129. package/dist/storage/storage.js.map +0 -1
  130. package/dist/test/fixtures.d.ts +0 -15
  131. package/dist/test/fixtures.js +0 -56
  132. package/dist/test/fixtures.js.map +0 -1
  133. package/dist/tsconfig.tsbuildinfo +0 -1
  134. package/dist/user/user.d.ts +0 -25
  135. package/dist/user/user.fixture.d.ts +0 -12
  136. package/dist/user/user.fixture.js +0 -20
  137. package/dist/user/user.fixture.js.map +0 -1
  138. package/dist/user/user.js +0 -38
  139. package/dist/user/user.js.map +0 -1
  140. package/dist/version.d.ts +0 -1
  141. package/dist/version.js +0 -2
  142. package/dist/version.js.map +0 -1
  143. package/src/authentication/authenticate.fixture.ts +0 -73
  144. package/src/authentication/authenticate.test.ts +0 -249
  145. package/src/authentication/authenticate.ts +0 -149
  146. package/src/capabilities/capabilities.ts +0 -83
  147. package/src/connection/connection.fixture.ts +0 -20
  148. package/src/connection/connection.test.ts +0 -60
  149. package/src/connection/connection.ts +0 -51
  150. package/src/effect.ts +0 -280
  151. package/src/email/email.fixture.ts +0 -44
  152. package/src/email/email.test.ts +0 -186
  153. package/src/email/email.ts +0 -148
  154. package/src/event/event.node.test.ts +0 -21
  155. package/src/event/event.test.ts +0 -37
  156. package/src/event/event.ts +0 -25
  157. package/src/index.ts +0 -407
  158. package/src/logging/eventLogger.test.ts +0 -104
  159. package/src/logging/eventLogger.ts +0 -41
  160. package/src/registration/register.fixture.ts +0 -96
  161. package/src/registration/register.test.ts +0 -216
  162. package/src/registration/register.ts +0 -158
  163. package/src/rpc/authentication.ts +0 -43
  164. package/src/rpc/client.ts +0 -174
  165. package/src/rpc/config.ts +0 -18
  166. package/src/rpc/connection.ts +0 -30
  167. package/src/rpc/registration.ts +0 -41
  168. package/src/rpc/social.ts +0 -45
  169. package/src/rpc/user.ts +0 -57
  170. package/src/social/social.fixture.ts +0 -45
  171. package/src/social/social.test.ts +0 -179
  172. package/src/social/social.ts +0 -82
  173. package/src/storage/storage.fixture.ts +0 -16
  174. package/src/storage/storage.test.ts +0 -206
  175. package/src/storage/storage.ts +0 -168
  176. package/src/test/fixtures.ts +0 -70
  177. package/src/user/user.fixture.ts +0 -33
  178. package/src/user/user.test.ts +0 -84
  179. package/src/user/user.ts +0 -73
  180. package/src/version.ts +0 -1
@@ -1,148 +0,0 @@
1
- /**
2
- * Email verification effects
3
- */
4
- import { Context, Effect as E, Layer, Option as O, flow, identity, pipe } from 'effect'
5
-
6
- import { BadRequest } from '@passlock/shared/dist/error/error.js'
7
- import type { VerifyEmailErrors as RpcErrors } from '@passlock/shared/dist/rpc/user.js'
8
- import { VerifyEmailReq } from '@passlock/shared/dist/rpc/user.js'
9
- import type { Principal } from '@passlock/shared/dist/schema/principal.js'
10
-
11
- import { type AuthenticationErrors, AuthenticationService } from '../authentication/authenticate.js'
12
- import { UserClient } from '../rpc/user.js'
13
- import { StorageService, type StoredToken } from '../storage/storage.js'
14
-
15
- /* Requests */
16
-
17
- export type VerifyRequest = {
18
- code: string
19
- }
20
-
21
- /* Errors */
22
-
23
- export type VerifyEmailErrors = RpcErrors | AuthenticationErrors
24
-
25
- /* Dependencies */
26
-
27
- export class URLQueryString extends Context.Tag('@utils/URLQueryString')<
28
- URLQueryString,
29
- E.Effect<string>
30
- >() {}
31
-
32
- /* Service */
33
-
34
- export class EmailService extends Context.Tag('@services/EmailService')<
35
- EmailService,
36
- {
37
- verifyEmailCode: (request: VerifyRequest) => E.Effect<Principal, VerifyEmailErrors>
38
- verifyEmailLink: () => E.Effect<Principal, VerifyEmailErrors>
39
- }
40
- >() {}
41
-
42
- /* Utils */
43
-
44
- export type Dependencies = StorageService | AuthenticationService | UserClient
45
-
46
- /**
47
- * Check for existing token in sessionStorage,
48
- * otherwise force passkey re-authentication
49
- * @returns
50
- */
51
- const getToken = () => {
52
- return E.gen(function* (_) {
53
- // Check for existing token
54
- const storageService = yield* _(StorageService)
55
- const existingTokenE = storageService.getToken('passkey')
56
- const authenticationService = yield* _(AuthenticationService)
57
-
58
- const tokenE = E.matchEffect(existingTokenE, {
59
- onSuccess: token => E.succeed(token),
60
- onFailure: () =>
61
- // No token, need to authenticate the user
62
- pipe(
63
- authenticationService.authenticatePasskey({
64
- userVerification: O.some('preferred'),
65
- email: O.none(),
66
- }),
67
- E.map(
68
- principal =>
69
- ({
70
- token: principal.jti,
71
- authType: principal.authType,
72
- expiry: principal.exp.getTime(),
73
- }) as StoredToken,
74
- ),
75
- ),
76
- })
77
-
78
- const token = yield* _(tokenE)
79
- yield* _(storageService.clearToken('passkey'))
80
-
81
- return token
82
- })
83
- }
84
-
85
- /**
86
- * Look for ?code=<code> in the url
87
- * @returns
88
- */
89
- export const extractCodeFromHref = () => {
90
- return pipe(
91
- URLQueryString,
92
- E.flatMap(identity),
93
- E.map(search => new URLSearchParams(search)),
94
- E.flatMap(params => O.fromNullable(params.get('code'))),
95
- )
96
- }
97
-
98
- /* Effects */
99
-
100
- /**
101
- * Verify the mailbox using the given code
102
- * @param request
103
- * @returns
104
- */
105
- export const verifyEmail = (
106
- request: VerifyRequest,
107
- ): E.Effect<Principal, VerifyEmailErrors, Dependencies> => {
108
- return E.gen(function* (_) {
109
- // Re-authenticate the user if required
110
- const { token } = yield* _(getToken())
111
-
112
- yield* _(E.logDebug('Making request'))
113
- const client = yield* _(UserClient)
114
- const { principal } = yield* _(
115
- client.verifyEmail(new VerifyEmailReq({ token, code: request.code })),
116
- )
117
-
118
- return principal
119
- })
120
- }
121
-
122
- /**
123
- * Look for a code in the current url and verify it
124
- * @returns
125
- */
126
- export const verifyEmailLink = () =>
127
- pipe(
128
- extractCodeFromHref(),
129
- E.mapError(() => new BadRequest({ message: 'Expected ?code=xxx in window.location' })),
130
- E.flatMap(code => verifyEmail({ code })),
131
- )
132
-
133
- /* Live */
134
-
135
- /* v8 ignore start */
136
- export const EmailServiceLive = Layer.effect(
137
- EmailService,
138
- E.gen(function* (_) {
139
- const context = yield* _(
140
- E.context<UserClient | AuthenticationService | StorageService | URLQueryString>(),
141
- )
142
- return EmailService.of({
143
- verifyEmailCode: flow(verifyEmail, E.provide(context)),
144
- verifyEmailLink: flow(verifyEmailLink, E.provide(context)),
145
- })
146
- }),
147
- )
148
- /* v8 ignore stop */
@@ -1,21 +0,0 @@
1
- import { Effect, pipe } from 'effect'
2
- import { describe, expect, test } from 'vitest'
3
-
4
- import { fireEvent } from './event.js'
5
-
6
- // @vitest-environment node
7
-
8
- describe('isPasslockEvent', () => {
9
- test("return a Passlock error if custom events aren't supported", async () => {
10
- const program = pipe(
11
- fireEvent('hello world'),
12
- Effect.flip,
13
- Effect.tap(e => {
14
- expect(e._tag).toBe('InternalBrowserError')
15
- expect(e.message).toBe('Unable to fire custom event')
16
- }),
17
- )
18
-
19
- await Effect.runPromise(program)
20
- })
21
- })
@@ -1,37 +0,0 @@
1
- import { Effect } from 'effect'
2
- import { afterEach, describe, expect, test, vi } from 'vitest'
3
-
4
- import { DebugMessage, fireEvent, isPasslockEvent } from './event.js'
5
-
6
- describe('fireEvent', () => {
7
- afterEach(() => {
8
- vi.restoreAllMocks()
9
- })
10
-
11
- test('fire a custom log event', () => {
12
- const effect = fireEvent('hello world')
13
- const eventSpy = vi.spyOn(globalThis, 'dispatchEvent')
14
- Effect.runSync(effect)
15
-
16
- const expectedEvent = new CustomEvent(DebugMessage, {
17
- detail: 'hello world',
18
- })
19
-
20
- expect(eventSpy).toHaveBeenCalledWith(expectedEvent)
21
- })
22
- })
23
-
24
- describe('isPasslockEvent', () => {
25
- test('return true for our custom event', () => {
26
- const passlockEvent = new CustomEvent(DebugMessage, {
27
- detail: 'hello world',
28
- })
29
-
30
- expect(isPasslockEvent(passlockEvent)).toBe(true)
31
- })
32
-
33
- test('return false for other events', () => {
34
- const otherEvent = new MouseEvent('click')
35
- expect(isPasslockEvent(otherEvent)).toBe(false)
36
- })
37
- })
@@ -1,25 +0,0 @@
1
- /**
2
- * Fire DOM events
3
- */
4
- import { Effect } from 'effect'
5
-
6
- import { InternalBrowserError } from '@passlock/shared/dist/error/error.js'
7
-
8
- export const DebugMessage = 'PasslogDebugMessage'
9
-
10
- export const fireEvent = (message: string) => {
11
- return Effect.try({
12
- try: () => {
13
- const evt = new CustomEvent(DebugMessage, { detail: message })
14
- globalThis.dispatchEvent(evt)
15
- },
16
- catch: () => {
17
- return new InternalBrowserError({ message: 'Unable to fire custom event' })
18
- },
19
- })
20
- }
21
-
22
- export function isPasslockEvent(event: Event): event is CustomEvent {
23
- if (event.type !== DebugMessage) return false
24
- return 'detail' in event
25
- }
package/src/index.ts DELETED
@@ -1,407 +0,0 @@
1
- import { Effect as E, Layer as L, Layer, Option as O, Runtime, Scope, pipe } from 'effect'
2
- import { dual } from 'effect/Function'
3
-
4
- import type {
5
- BadRequest,
6
- Disabled,
7
- Duplicate,
8
- Forbidden,
9
- NotFound,
10
- NotSupported,
11
- Unauthorized,
12
- } from '@passlock/shared/dist/error/error.js'
13
- import { ErrorCode } from '@passlock/shared/dist/error/error.js'
14
- import type { VerifyEmail } from '@passlock/shared/dist/schema/email.js'
15
- import type { UserVerification } from '@passlock/shared/dist/schema/passkey.js'
16
- import {
17
- type Principal,
18
- type UserPrincipal,
19
- isPrincipal,
20
- isUserPrincipal,
21
- } from '@passlock/shared/dist/schema/principal.js'
22
-
23
- import type { AuthenticationService } from './authentication/authenticate.js'
24
- import type { Capabilities } from './capabilities/capabilities.js'
25
- import type { ConnectionService } from './connection/connection.js'
26
- import {
27
- allRequirements,
28
- authenticateOidc,
29
- authenticatePasskey,
30
- clearExpiredTokens,
31
- getSessionToken,
32
- isExistingUser,
33
- isPasskeySupport,
34
- preConnect,
35
- registerOidc,
36
- registerPasskey,
37
- resendVerificationEmail,
38
- verifyEmailCode,
39
- verifyEmailLink,
40
- } from './effect.js'
41
- import type { EmailService, VerifyRequest } from './email/email.js'
42
- import type { RegistrationService } from './registration/register.js'
43
- import { RpcConfig } from './rpc/config.js'
44
- import type { Provider, SocialService } from './social/social.js'
45
- import {
46
- type AuthType,
47
- BrowserStorage,
48
- StorageService,
49
- type StoredToken,
50
- } from './storage/storage.js'
51
- import type { Email, ResendEmail, UserService } from './user/user.js'
52
- import { PASSLOCK_CLIENT_VERSION } from './version.js'
53
-
54
- /* Exports */
55
-
56
- export type Options = { signal?: AbortSignal }
57
- export type { VerifyEmail } from '@passlock/shared/dist/schema/email.js'
58
- export type { UserVerification } from '@passlock/shared/dist/schema/passkey.js'
59
- export type { Principal, UserPrincipal } from '@passlock/shared/dist/schema/principal.js'
60
-
61
- export type { VerifyRequest } from './email/email.js'
62
- export type { AuthType, StoredToken } from './storage/storage.js'
63
- export type { Email } from './user/user.js'
64
-
65
- export type PasslockProps = {
66
- tenancyId: string
67
- clientId: string
68
- endpoint?: string
69
- }
70
-
71
- export type RegistrationRequest = {
72
- email: string
73
- givenName?: string
74
- familyName?: string
75
- userVerification?: UserVerification
76
- verifyEmail?: VerifyEmail
77
- }
78
-
79
- const nonEmpty = (text: string): O.Option<string> => {
80
- const trimmed = text.trim()
81
- if (trimmed.length > 0) return O.some(trimmed)
82
- return O.none()
83
- }
84
-
85
- const toRpcRegistrationRequest = (request: RegistrationRequest) => {
86
- return {
87
- email: request.email,
88
- givenName: pipe(O.fromNullable(request.givenName), O.flatMap(nonEmpty)),
89
- familyName: pipe(O.fromNullable(request.familyName), O.flatMap(nonEmpty)),
90
- userVerification: O.fromNullable(request.userVerification),
91
- verifyEmail: O.fromNullable(request.verifyEmail),
92
- }
93
- }
94
-
95
- export type AuthenticationRequest = {
96
- email?: string
97
- userVerification?: UserVerification
98
- }
99
-
100
- const toRpcAuthenticationRequest = (request: AuthenticationRequest) => {
101
- return {
102
- email: O.fromNullable(request.email),
103
- userVerification: O.fromNullable(request.userVerification),
104
- }
105
- }
106
-
107
- export type RegisterOidcReq = {
108
- provider: Provider
109
- idToken: string
110
- givenName?: string
111
- familyName?: string
112
- nonce: string
113
- }
114
-
115
- const toRpcRegisterOidcReq = (request: RegisterOidcReq) => {
116
- return {
117
- provider: request.provider,
118
- idToken: request.idToken,
119
- givenName: pipe(O.fromNullable(request.givenName), O.flatMap(nonEmpty)),
120
- familyName: pipe(O.fromNullable(request.familyName), O.flatMap(nonEmpty)),
121
- nonce: request.nonce,
122
- }
123
- }
124
-
125
- export type AuthenticateOidcReq = {
126
- provider: Provider
127
- idToken: string
128
- nonce: string
129
- }
130
-
131
- const toRpcAuthenticateOidcReq = (request: AuthenticateOidcReq) => {
132
- return {
133
- provider: request.provider,
134
- idToken: request.idToken,
135
- nonce: request.nonce,
136
- }
137
- }
138
-
139
- export { ErrorCode } from '@passlock/shared/dist/error/error.js'
140
-
141
- export class PasslockError extends Error {
142
- readonly code: ErrorCode
143
- readonly detail: string | undefined
144
-
145
- constructor(message: string, code: ErrorCode, detail?: string) {
146
- super(message)
147
- this.code = code
148
- this.detail = detail
149
- }
150
-
151
- static readonly isError = (error: unknown): error is PasslockError => {
152
- return typeof error === 'object' && error !== null && error instanceof PasslockError
153
- }
154
- }
155
-
156
- /* // Exports */
157
-
158
- type PasslockErrors =
159
- | BadRequest
160
- | NotSupported
161
- | Duplicate
162
- | Unauthorized
163
- | Forbidden
164
- | Disabled
165
- | NotFound
166
-
167
- const hasMessage = (defect: unknown): defect is { message: string } => {
168
- return (
169
- typeof defect === 'object' &&
170
- defect !== null &&
171
- 'message' in defect &&
172
- typeof defect['message'] === 'string'
173
- )
174
- }
175
-
176
- const transformErrors = <A, R>(
177
- effect: E.Effect<A, PasslockErrors, R>,
178
- ): E.Effect<A | PasslockError, never, R> => {
179
- const withErrorHandling = E.catchTags(effect, {
180
- NotSupported: e => E.succeed(new PasslockError(e.message, ErrorCode.NotSupported)),
181
- BadRequest: e => E.succeed(new PasslockError(e.message, ErrorCode.BadRequest, e.detail)),
182
- Duplicate: e => E.succeed(new PasslockError(e.message, ErrorCode.Duplicate, e.detail)),
183
- Unauthorized: e => E.succeed(new PasslockError(e.message, ErrorCode.Unauthorized, e.detail)),
184
- Forbidden: e => E.succeed(new PasslockError(e.message, ErrorCode.Forbidden, e.detail)),
185
- Disabled: e => E.succeed(new PasslockError(e.message, ErrorCode.Disabled, e.detail)),
186
- NotFound: e => E.succeed(new PasslockError(e.message, ErrorCode.NotFound, e.detail)),
187
- })
188
-
189
- const sandboxed = E.sandbox(withErrorHandling)
190
-
191
- const withSandboxing = E.catchTags(sandboxed, {
192
- Die: ({ defect }) => {
193
- return hasMessage(defect)
194
- ? E.succeed(new PasslockError(defect.message, ErrorCode.InternalServerError))
195
- : E.succeed(new PasslockError('Sorry, something went wrong', ErrorCode.InternalServerError))
196
- },
197
-
198
- Interrupt: () => {
199
- console.error('Interrupt')
200
- return E.succeed(new PasslockError('Operation aborted', ErrorCode.InternalBrowserError))
201
- },
202
-
203
- Sequential: errors => {
204
- console.error(errors)
205
-
206
- return E.succeed(
207
- new PasslockError('Sorry, something went wrong', ErrorCode.InternalServerError),
208
- )
209
- },
210
-
211
- Parallel: errors => {
212
- console.error(errors)
213
-
214
- return E.succeed(
215
- new PasslockError('Sorry, something went wrong', ErrorCode.InternalServerError),
216
- )
217
- },
218
- })
219
-
220
- return E.unsandbox(withSandboxing)
221
- }
222
-
223
- type Requirements =
224
- | UserService
225
- | RegistrationService
226
- | AuthenticationService
227
- | ConnectionService
228
- | EmailService
229
- | StorageService
230
- | Capabilities
231
- | SocialService
232
- | RpcConfig
233
-
234
- export class PasslockUnsafe {
235
- private readonly runtime: Runtime.Runtime<Requirements>
236
-
237
- constructor(props: PasslockProps) {
238
- const config = Layer.succeed(RpcConfig, RpcConfig.of(props))
239
- const storage = Layer.succeed(BrowserStorage, BrowserStorage.of(globalThis.localStorage))
240
- const allLayers = pipe(allRequirements, L.provide(config), L.provide(storage), L.merge(config))
241
- const scope = E.runSync(Scope.make())
242
-
243
- this.runtime = E.runSync(Layer.toRuntime(allLayers).pipe(Scope.extend(scope)))
244
-
245
- E.runSync(E.logDebug(`Passlock version: ${PASSLOCK_CLIENT_VERSION}`))
246
- }
247
-
248
- static isPrincipal = (value: unknown): value is Principal => isPrincipal(value)
249
- static isUserPrincipal = (value: unknown): value is UserPrincipal => isUserPrincipal(value)
250
-
251
- private readonly runPromise: {
252
- <A, R extends Requirements>(
253
- options: Options | undefined,
254
- ): (effect: E.Effect<A, PasslockErrors, R>) => Promise<A>
255
- <A, R extends Requirements>(
256
- effect: E.Effect<A, PasslockErrors, R>,
257
- options: Options | undefined,
258
- ): Promise<A>
259
- } = dual(
260
- 2,
261
- <A, R extends Requirements>(
262
- effect: E.Effect<A, PasslockErrors, R>,
263
- options: Options | undefined,
264
- ): Promise<A> =>
265
- pipe(
266
- transformErrors(effect),
267
- E.flatMap(result => (PasslockError.isError(result) ? E.fail(result) : E.succeed(result))),
268
- effect => Runtime.runPromise(this.runtime)(effect, options),
269
- ),
270
- )
271
-
272
- preConnect = (options?: Options): Promise<void> => pipe(preConnect(), this.runPromise(options))
273
-
274
- isPasskeySupport = (): Promise<boolean> =>
275
- pipe(isPasskeySupport, effect => Runtime.runPromise(this.runtime)(effect))
276
-
277
- isExistingUser = (email: Email, options?: Options): Promise<boolean> =>
278
- pipe(isExistingUser(email), this.runPromise(options))
279
-
280
- registerPasskey = (request: RegistrationRequest, options?: Options): Promise<Principal> =>
281
- pipe(registerPasskey(toRpcRegistrationRequest(request)), this.runPromise(options))
282
-
283
- authenticatePasskey = (request: AuthenticationRequest, options?: Options): Promise<Principal> =>
284
- pipe(authenticatePasskey(toRpcAuthenticationRequest(request)), this.runPromise(options))
285
-
286
- registerOidc = (request: RegisterOidcReq, options?: Options) =>
287
- pipe(registerOidc(toRpcRegisterOidcReq(request)), this.runPromise(options))
288
-
289
- authenticateOidc = (request: AuthenticateOidcReq, options?: Options) =>
290
- pipe(authenticateOidc(toRpcAuthenticateOidcReq(request)), this.runPromise(options))
291
-
292
- verifyEmailCode = (request: VerifyRequest, options?: Options): Promise<Principal> =>
293
- pipe(verifyEmailCode(request), this.runPromise(options))
294
-
295
- resendVerificationEmail = (request: ResendEmail, options?: Options): Promise<void> =>
296
- pipe(resendVerificationEmail(request), this.runPromise(options))
297
-
298
- verifyEmailLink = (options?: Options): Promise<Principal> =>
299
- pipe(verifyEmailLink, this.runPromise(options))
300
-
301
- getSessionToken = (authType: AuthType): StoredToken | undefined =>
302
- pipe(
303
- getSessionToken(authType),
304
- E.orElseSucceed(() => undefined),
305
- effect => Runtime.runSync(this.runtime)(effect),
306
- )
307
-
308
- clearExpiredTokens = (): void => {
309
- pipe(clearExpiredTokens, effect => {
310
- Runtime.runSync(this.runtime)(effect)
311
- })
312
- }
313
- }
314
-
315
- export class Passlock {
316
- private readonly runtime: Runtime.Runtime<Requirements>
317
-
318
- constructor(props: PasslockProps) {
319
- const config = Layer.succeed(RpcConfig, RpcConfig.of(props))
320
- const storage = Layer.succeed(BrowserStorage, BrowserStorage.of(globalThis.localStorage))
321
- const allLayers = pipe(allRequirements, L.provide(config), L.provide(storage), L.merge(config))
322
- const scope = E.runSync(Scope.make())
323
-
324
- this.runtime = E.runSync(Layer.toRuntime(allLayers).pipe(Scope.extend(scope)))
325
-
326
- E.runSync(E.logDebug(`Passlock version: ${PASSLOCK_CLIENT_VERSION}`))
327
- }
328
-
329
- static isPrincipal = (value: unknown): value is Principal => isPrincipal(value)
330
- static isUserPrincipal = (value: unknown): value is UserPrincipal => isUserPrincipal(value)
331
-
332
- private readonly runPromise: {
333
- <A, R extends Requirements>(
334
- options: Options | undefined,
335
- ): (effect: E.Effect<A, PasslockErrors, R>) => Promise<A | PasslockError>
336
- <A, R extends Requirements>(
337
- effect: E.Effect<A, PasslockErrors, R>,
338
- options: Options | undefined,
339
- ): Promise<A | PasslockError>
340
- } = dual(
341
- 2,
342
- <A, R extends Requirements>(
343
- effect: E.Effect<A, PasslockErrors, R>,
344
- options: Options | undefined,
345
- ): Promise<A | PasslockError> =>
346
- pipe(transformErrors(effect), effect => Runtime.runPromise(this.runtime)(effect, options)),
347
- )
348
-
349
- preConnect = async (options?: Options): Promise<boolean | PasslockError> => {
350
- return pipe(preConnect(), E.as(true), this.runPromise(options))
351
- }
352
-
353
- isPasskeySupport = (): Promise<boolean> =>
354
- pipe(isPasskeySupport, effect => Runtime.runPromise(this.runtime)(effect))
355
-
356
- isExistingUser = (email: Email, options?: Options): Promise<boolean | PasslockError> =>
357
- pipe(isExistingUser(email), this.runPromise(options))
358
-
359
- registerPasskey = (
360
- request: RegistrationRequest,
361
- options?: Options,
362
- ): Promise<Principal | PasslockError> =>
363
- pipe(registerPasskey(toRpcRegistrationRequest(request)), this.runPromise(options))
364
-
365
- authenticatePasskey = (
366
- request: AuthenticationRequest = {},
367
- options?: Options,
368
- ): Promise<Principal | PasslockError> =>
369
- pipe(toRpcAuthenticationRequest(request), authenticatePasskey, this.runPromise(options))
370
-
371
- registerOidc = (request: RegisterOidcReq, options?: Options) =>
372
- pipe(registerOidc(toRpcRegisterOidcReq(request)), this.runPromise(options))
373
-
374
- authenticateOidc = (request: AuthenticateOidcReq, options?: Options) =>
375
- pipe(authenticateOidc(request), this.runPromise(options))
376
-
377
- verifyEmailCode = (
378
- request: VerifyRequest,
379
- options?: Options,
380
- ): Promise<Principal | PasslockError> => pipe(verifyEmailCode(request), this.runPromise(options))
381
-
382
- verifyEmailLink = (options?: Options): Promise<Principal | PasslockError> =>
383
- pipe(verifyEmailLink, this.runPromise(options))
384
-
385
- resendVerificationEmail = (
386
- request: ResendEmail,
387
- options?: Options,
388
- ): Promise<boolean | PasslockError> =>
389
- pipe(resendVerificationEmail(request), E.as(true), this.runPromise(options))
390
-
391
- getSessionToken = (authType: AuthType): Promise<StoredToken | undefined> =>
392
- pipe(
393
- getSessionToken(authType),
394
- E.orElseSucceed(() => undefined),
395
- effect => E.runPromise(effect),
396
- )
397
-
398
- clearExpiredTokens = (): void => {
399
- pipe(
400
- StorageService,
401
- E.flatMap(service => service.clearExpiredTokens),
402
- effect => {
403
- Runtime.runSync(this.runtime)(effect)
404
- },
405
- )
406
- }
407
- }