@passlock/client 0.9.32 → 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 -23
  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 -72
  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 -25
  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 -77
  96. package/dist/registration/register.js.map +0 -1
  97. package/dist/rpc/client.d.ts +0 -30
  98. package/dist/rpc/client.js +0 -101
  99. package/dist/rpc/client.js.map +0 -1
  100. package/dist/rpc/config.d.ts +0 -15
  101. package/dist/rpc/config.js +0 -6
  102. package/dist/rpc/config.js.map +0 -1
  103. package/dist/rpc/connection.d.ts +0 -8
  104. package/dist/rpc/connection.js +0 -16
  105. package/dist/rpc/connection.js.map +0 -1
  106. package/dist/rpc/passkey/authentication.d.ts +0 -8
  107. package/dist/rpc/passkey/authentication.js +0 -17
  108. package/dist/rpc/passkey/authentication.js.map +0 -1
  109. package/dist/rpc/passkey/registration.d.ts +0 -8
  110. package/dist/rpc/passkey/registration.js +0 -17
  111. package/dist/rpc/passkey/registration.js.map +0 -1
  112. package/dist/rpc/social.d.ts +0 -10
  113. package/dist/rpc/social.js +0 -19
  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 -20
  117. package/dist/rpc/user.js.map +0 -1
  118. package/dist/social/social.d.ts +0 -23
  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 -38
  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 -37
  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 -143
  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 -156
  163. package/src/rpc/client.ts +0 -174
  164. package/src/rpc/config.ts +0 -18
  165. package/src/rpc/connection.ts +0 -32
  166. package/src/rpc/passkey/authentication.ts +0 -52
  167. package/src/rpc/passkey/registration.ts +0 -52
  168. package/src/rpc/social.ts +0 -55
  169. package/src/rpc/user.ts +0 -68
  170. package/src/social/social.fixture.ts +0 -44
  171. package/src/social/social.test.ts +0 -179
  172. package/src/social/social.ts +0 -79
  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 -71
  180. package/src/version.ts +0 -1
@@ -1,60 +0,0 @@
1
- import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect'
2
- import { describe, expect, test } from 'vitest'
3
- import { mock } from 'vitest-mock-extended'
4
-
5
- import * as Fixture from './connection.fixture.js'
6
- import { Dispatcher } from '../rpc/client.js'
7
- import { RpcConfig } from '../rpc/config.js'
8
- import { ConnectionClient } from '../rpc/connection.js'
9
- import { ConnectionService, ConnectionServiceLive } from './connection.js'
10
-
11
- describe('preConnect should', () => {
12
- test('hit the rpc endpoint', async () => {
13
- const assertions = E.gen(function* (_) {
14
- const service = yield* _(ConnectionService)
15
- yield* _(service.preConnect())
16
-
17
- const rpcClient = yield* _(ConnectionClient)
18
- expect(rpcClient.preConnect).toBeCalled()
19
-
20
- const dispatcher = yield* _(Dispatcher)
21
- expect(dispatcher.get).toBeCalledWith(`/token/token?warm=true`)
22
- })
23
-
24
- const rpcClientTest = Layer.effect(
25
- ConnectionClient,
26
- E.sync(() => {
27
- const rpcMock = mock<ConnectionClient['Type']>()
28
-
29
- rpcMock.preConnect.mockReturnValue(E.succeed(Fixture.preConnectRes))
30
-
31
- return rpcMock
32
- }),
33
- )
34
-
35
- const rpcConfigTest = Layer.succeed(RpcConfig, RpcConfig.of(Fixture.rpcConfig))
36
-
37
- const dispatcherTest = Layer.effect(
38
- Dispatcher,
39
- E.sync(() => {
40
- const dispatcherMock = mock<Dispatcher['Type']>()
41
-
42
- dispatcherMock.get.mockReturnValue(E.succeed({ status: 200, body: {} }))
43
-
44
- return dispatcherMock
45
- }),
46
- )
47
-
48
- const service = pipe(
49
- ConnectionServiceLive,
50
- L.provide(rpcClientTest),
51
- L.provide(dispatcherTest),
52
- L.provide(rpcConfigTest),
53
- )
54
-
55
- const layers = L.mergeAll(service, rpcClientTest, dispatcherTest)
56
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
57
-
58
- return E.runPromise(effect)
59
- })
60
- })
@@ -1,51 +0,0 @@
1
- /**
2
- * Hits the rpc endpoint to warm up a lambda
3
- */
4
- import { Context, Effect as E, Layer, flow, pipe } from 'effect'
5
-
6
- import { Dispatcher } from '../rpc/client.js'
7
- import type { RpcConfig } from '../rpc/config.js'
8
- import * as RPC from '../rpc/connection.js'
9
-
10
- /* Service */
11
-
12
- export class ConnectionService extends Context.Tag('@services/ConnectionService')<
13
- ConnectionService,
14
- {
15
- preConnect: () => E.Effect<void>
16
- }
17
- >() {}
18
-
19
- /* Effects */
20
-
21
- const hitPrincipal = pipe(
22
- E.logInfo('Pre-connecting to Principal endpoint'),
23
- E.zipRight(Dispatcher),
24
- E.flatMap(dispatcher => dispatcher.get('/token/token?warm=true')),
25
- E.asVoid,
26
- E.catchAll(() => E.void),
27
- )
28
-
29
- const hitRpc = pipe(
30
- E.logInfo('Pre-connecting to RPC endpoint'),
31
- E.zipRight(RPC.ConnectionClient),
32
- E.flatMap(rpcClient => rpcClient.preConnect()),
33
- E.asVoid,
34
- )
35
-
36
- export const preConnect = () => pipe(E.all([hitPrincipal, hitRpc], { concurrency: 2 }), E.asVoid)
37
-
38
- /* Live */
39
-
40
- /* v8 ignore start */
41
- export const ConnectionServiceLive = Layer.effect(
42
- ConnectionService,
43
- E.gen(function* (_) {
44
- const context = yield* _(E.context<RPC.ConnectionClient | Dispatcher | RpcConfig>())
45
-
46
- return ConnectionService.of({
47
- preConnect: flow(preConnect, E.provide(context)),
48
- })
49
- }),
50
- )
51
- /* v8 ignore stop */
package/src/effect.ts DELETED
@@ -1,280 +0,0 @@
1
- import { create, get as getCredential } from '@github/webauthn-json/browser-ponyfill'
2
- import { Effect as E, Layer as L, Layer, Schedule, pipe } from 'effect'
3
- import type { NoSuchElementException } from 'effect/Cause'
4
-
5
- import {
6
- type BadRequest,
7
- Duplicate,
8
- InternalBrowserError,
9
- } from '@passlock/shared/dist/error/error.js'
10
- import type { Principal } from '@passlock/shared/dist/schema/principal.js'
11
-
12
- import {
13
- AuthenticateServiceLive,
14
- type AuthenticationErrors,
15
- type AuthenticationRequest,
16
- AuthenticationService,
17
- GetCredential,
18
- } from './authentication/authenticate.js'
19
- import { Capabilities, capabilitiesLive } from './capabilities/capabilities.js'
20
- import { ConnectionService, ConnectionServiceLive } from './connection/connection.js'
21
- import {
22
- EmailService,
23
- EmailServiceLive,
24
- URLQueryString,
25
- type VerifyEmailErrors,
26
- type VerifyRequest,
27
- } from './email/email.js'
28
- import {
29
- CreateCredential,
30
- type RegistrationErrors,
31
- type RegistrationRequest,
32
- RegistrationService,
33
- RegistrationServiceLive,
34
- } from './registration/register.js'
35
- import { AuthenticationClientLive } from './rpc/passkey/authentication.js'
36
- import { DispatcherLive } from './rpc/client.js'
37
- import type { RpcConfig } from './rpc/config.js'
38
- import { RetrySchedule } from './rpc/config.js'
39
- import { ConnectionClientLive } from './rpc/connection.js'
40
- import { RegistrationClientLive } from './rpc/passkey/registration.js'
41
- import { SocialClientLive } from './rpc/social.js'
42
- import { UserClientLive } from './rpc/user.js'
43
- import {
44
- type AuthenticateOidcReq,
45
- type AuthenticationErrors as OidcAuthenticationErrors,
46
- type RegistrationErrors as OidcRegistrationErrors,
47
- type RegisterOidcReq,
48
- SocialService,
49
- SocialServiceLive,
50
- } from './social/social.js'
51
- import {
52
- type AuthType,
53
- BrowserStorage,
54
- StorageService,
55
- StorageServiceLive,
56
- type StoredToken,
57
- } from './storage/storage.js'
58
- import {
59
- type Email,
60
- type ResendEmail,
61
- type ResendEmailErrors,
62
- UserService,
63
- UserServiceLive,
64
- } from './user/user.js'
65
-
66
- /* Layers */
67
-
68
- const createCredentialLive = L.succeed(
69
- CreateCredential,
70
- CreateCredential.of({
71
- createCredential: options =>
72
- pipe(
73
- E.tryPromise({
74
- try: () => create(options),
75
- catch: e => {
76
- if (e instanceof Error && e.message.includes('excludeCredentials')) {
77
- return new Duplicate({
78
- message: 'Passkey already registered to this device or cloud account',
79
- })
80
- } else {
81
- return new InternalBrowserError({
82
- message: 'Unable to create credential',
83
- detail: String(e),
84
- })
85
- }
86
- },
87
- }),
88
- E.map(credential => credential.toJSON()),
89
- ),
90
- }),
91
- )
92
-
93
- const getCredentialLive = L.succeed(
94
- GetCredential,
95
- GetCredential.of({
96
- getCredential: (options: CredentialRequestOptions) =>
97
- pipe(
98
- E.tryPromise({
99
- try: () => getCredential(options),
100
- catch: e =>
101
- new InternalBrowserError({
102
- message: 'Unable to get authentication credential',
103
- detail: String(e),
104
- }),
105
- }),
106
- E.map(credential => credential.toJSON()),
107
- ),
108
- }),
109
- )
110
-
111
- const schedule = Schedule.intersect(Schedule.recurs(3), Schedule.exponential('100 millis'))
112
-
113
- const retryScheduleLive = L.succeed(RetrySchedule, RetrySchedule.of({ schedule }))
114
-
115
- /* Services */
116
- const dispatcherLive = pipe(DispatcherLive, L.provide(retryScheduleLive))
117
- const connectClientLive = pipe(ConnectionClientLive, L.provide(dispatcherLive))
118
- const registerClientLive = pipe(RegistrationClientLive, L.provide(dispatcherLive))
119
- const authenticateClientLive = pipe(AuthenticationClientLive, L.provide(dispatcherLive))
120
- const socialClientLive = pipe(SocialClientLive, L.provide(dispatcherLive))
121
- const userClientLive = pipe(UserClientLive, L.provide(dispatcherLive))
122
- const storageServiceLive = StorageServiceLive
123
- const userServiceLive = pipe(UserServiceLive, L.provide(userClientLive))
124
-
125
- const registrationServiceLive = pipe(
126
- RegistrationServiceLive,
127
- L.provide(registerClientLive),
128
- L.provide(userServiceLive),
129
- L.provide(capabilitiesLive),
130
- L.provide(createCredentialLive),
131
- L.provide(storageServiceLive),
132
- )
133
-
134
- const authenticationServiceLive = pipe(
135
- AuthenticateServiceLive,
136
- L.provide(authenticateClientLive),
137
- L.provide(capabilitiesLive),
138
- L.provide(getCredentialLive),
139
- L.provide(storageServiceLive),
140
- )
141
-
142
- const connectionServiceLive = pipe(
143
- ConnectionServiceLive,
144
- L.provide(connectClientLive),
145
- L.provide(dispatcherLive),
146
- )
147
-
148
- const urlQueryStringLive = Layer.succeed(
149
- URLQueryString,
150
- URLQueryString.of(E.sync(() => globalThis.window.location.search)),
151
- )
152
-
153
- const emailServiceLive = pipe(
154
- EmailServiceLive,
155
- L.provide(urlQueryStringLive),
156
- L.provide(userClientLive),
157
- L.provide(capabilitiesLive),
158
- L.provide(authenticationServiceLive),
159
- L.provide(storageServiceLive),
160
- )
161
-
162
- const socialServiceLive = pipe(SocialServiceLive, L.provide(socialClientLive))
163
-
164
- export const allRequirements = Layer.mergeAll(
165
- capabilitiesLive,
166
- userServiceLive,
167
- registrationServiceLive,
168
- authenticationServiceLive,
169
- connectionServiceLive,
170
- emailServiceLive,
171
- storageServiceLive,
172
- socialServiceLive,
173
- )
174
-
175
- const browserStorageLive = Layer.effect(
176
- BrowserStorage,
177
- E.sync(() => BrowserStorage.of(globalThis.localStorage)),
178
- )
179
-
180
- export const preConnect = (): E.Effect<void, never, RpcConfig> =>
181
- pipe(
182
- ConnectionService,
183
- E.flatMap(service => service.preConnect()),
184
- E.provide(connectionServiceLive),
185
- )
186
-
187
- export const isPasskeySupport: E.Effect<boolean> = pipe(
188
- Capabilities,
189
- E.flatMap(service => service.isPasskeySupport),
190
- E.provide(capabilitiesLive),
191
- )
192
-
193
- export const isExistingUser = (request: Email): E.Effect<boolean, BadRequest, RpcConfig> =>
194
- pipe(
195
- UserService,
196
- E.flatMap(service => service.isExistingUser(request)),
197
- E.provide(userServiceLive),
198
- )
199
-
200
- export const registerPasskey = (
201
- request: RegistrationRequest,
202
- ): E.Effect<Principal, RegistrationErrors, RpcConfig> =>
203
- pipe(
204
- RegistrationService,
205
- E.flatMap(service => service.registerPasskey(request)),
206
- E.provide(registrationServiceLive),
207
- E.provide(browserStorageLive),
208
- )
209
-
210
- export const authenticatePasskey = (
211
- request: AuthenticationRequest,
212
- ): E.Effect<Principal, AuthenticationErrors, RpcConfig> =>
213
- pipe(
214
- AuthenticationService,
215
- E.flatMap(service => service.authenticatePasskey(request)),
216
- E.provide(authenticationServiceLive),
217
- E.provide(browserStorageLive),
218
- )
219
-
220
- export const verifyEmailCode = (
221
- request: VerifyRequest,
222
- ): E.Effect<Principal, VerifyEmailErrors, RpcConfig> =>
223
- pipe(
224
- EmailService,
225
- E.flatMap(service => service.verifyEmailCode(request)),
226
- E.provide(emailServiceLive),
227
- E.provide(browserStorageLive),
228
- )
229
-
230
- export const verifyEmailLink: E.Effect<Principal, VerifyEmailErrors, RpcConfig> = pipe(
231
- EmailService,
232
- E.flatMap(service => service.verifyEmailLink()),
233
- E.provide(emailServiceLive),
234
- E.provide(browserStorageLive),
235
- )
236
-
237
- export const resendVerificationEmail = (
238
- request: ResendEmail,
239
- ): E.Effect<void, ResendEmailErrors, RpcConfig> =>
240
- pipe(
241
- UserService,
242
- E.flatMap(service => service.resendVerificationEmail(request)),
243
- E.provide(userServiceLive),
244
- E.provide(browserStorageLive),
245
- )
246
-
247
- export const getSessionToken = (
248
- authType: AuthType,
249
- ): E.Effect<StoredToken, NoSuchElementException> =>
250
- pipe(
251
- StorageService,
252
- E.flatMap(service => service.getToken(authType)),
253
- E.provide(storageServiceLive),
254
- E.provide(browserStorageLive),
255
- )
256
-
257
- export const clearExpiredTokens: E.Effect<void> = pipe(
258
- StorageService,
259
- E.flatMap(service => service.clearExpiredTokens),
260
- E.provide(storageServiceLive),
261
- E.provide(browserStorageLive),
262
- )
263
-
264
- export const registerOidc = (
265
- request: RegisterOidcReq,
266
- ): E.Effect<Principal, OidcRegistrationErrors, RpcConfig> =>
267
- pipe(
268
- SocialService,
269
- E.flatMap(service => service.registerOidc(request)),
270
- E.provide(socialServiceLive),
271
- )
272
-
273
- export const authenticateOidc = (
274
- request: AuthenticateOidcReq,
275
- ): E.Effect<Principal, OidcAuthenticationErrors, RpcConfig> =>
276
- pipe(
277
- SocialService,
278
- E.flatMap(service => service.authenticateOidc(request)),
279
- E.provide(socialServiceLive),
280
- )
@@ -1,44 +0,0 @@
1
- import { Effect as E, Layer as L, Option as O } from 'effect'
2
-
3
- import { VerifyEmailRequest, VerifyEmailResponse } from '@passlock/shared/dist/rpc/user.js'
4
-
5
- import * as Fixtures from '../test/fixtures.js'
6
- import { AuthenticationService } from '../authentication/authenticate.js'
7
- import { UserClient } from '../rpc/user.js'
8
- import { URLQueryString } from './email.js'
9
-
10
- export const token = 'token'
11
- export const code = 'code'
12
- export const authType = 'passkey'
13
- export const expireAt = Date.now() + 10000
14
-
15
- export const locationSearchTest = L.succeed(
16
- URLQueryString,
17
- URLQueryString.of(E.succeed(`?code=${code}`)),
18
- )
19
-
20
- export const authenticationServiceTest = L.succeed(
21
- AuthenticationService,
22
- AuthenticationService.of({
23
- authenticatePasskey: () => E.succeed(Fixtures.principal),
24
- }),
25
- )
26
-
27
- export const rpcVerifyEmailReq = new VerifyEmailRequest({ token, code })
28
-
29
- export const rpcVerifyEmailRes = new VerifyEmailResponse({ principal: Fixtures.principal })
30
-
31
- export const rpcClientTest = L.succeed(
32
- UserClient,
33
- UserClient.of({
34
- isExistingUser: () => E.succeed({ existingUser: true, detail: O.none() }),
35
- verifyEmail: () => E.succeed(rpcVerifyEmailRes),
36
- resendVerificationEmail: () => E.fail(Fixtures.notImplemented),
37
- }),
38
- )
39
-
40
- export const principal = Fixtures.principal
41
-
42
- export const storedToken = Fixtures.storedToken
43
-
44
- export const storageServiceTest = Fixtures.storageServiceTest
@@ -1,186 +0,0 @@
1
- import { Effect as E, Layer as L, LogLevel, Logger, pipe } from 'effect'
2
- import { NoSuchElementException } from 'effect/Cause'
3
- import { describe, expect, test } from 'vitest'
4
- import { mock } from 'vitest-mock-extended'
5
-
6
- import * as Fixture from './email.fixture.js'
7
- import { AuthenticationService } from '../authentication/authenticate.js'
8
- import { UserClient } from '../rpc/user.js'
9
- import { StorageService } from '../storage/storage.js'
10
- import { EmailService, EmailServiceLive } from './email.js'
11
-
12
- describe('verifyEmailCode should', () => {
13
- test('return a principal when the verification is successful', async () => {
14
- const assertions = E.gen(function* (_) {
15
- const service = yield* _(EmailService)
16
- const result = yield* _(service.verifyEmailCode({ code: '123' }))
17
-
18
- expect(result).toEqual(Fixture.principal)
19
- })
20
-
21
- const service = pipe(
22
- EmailServiceLive,
23
- L.provide(Fixture.locationSearchTest),
24
- L.provide(Fixture.authenticationServiceTest),
25
- L.provide(Fixture.storageServiceTest),
26
- L.provide(Fixture.rpcClientTest),
27
- )
28
-
29
- const effect = pipe(E.provide(assertions, service), Logger.withMinimumLogLevel(LogLevel.None))
30
-
31
- return E.runPromise(effect)
32
- })
33
-
34
- test('check for a token in local storage', async () => {
35
- const assertions = E.gen(function* (_) {
36
- const service = yield* _(EmailService)
37
- yield* _(service.verifyEmailCode({ code: '123' }))
38
-
39
- const storageService = yield* _(StorageService)
40
- expect(storageService.getToken).toHaveBeenCalledWith('passkey')
41
- })
42
-
43
- const storageServiceTest = L.effect(
44
- StorageService,
45
- E.sync(() => {
46
- const storageServiceMock = mock<StorageService['Type']>()
47
-
48
- storageServiceMock.getToken.mockReturnValue(E.succeed(Fixture.storedToken))
49
- storageServiceMock.clearToken.mockReturnValue(E.void)
50
-
51
- return storageServiceMock
52
- }),
53
- )
54
-
55
- const service = pipe(
56
- EmailServiceLive,
57
- L.provide(Fixture.locationSearchTest),
58
- L.provide(Fixture.authenticationServiceTest),
59
- L.provide(storageServiceTest),
60
- L.provide(Fixture.rpcClientTest),
61
- )
62
-
63
- const layers = L.merge(service, storageServiceTest)
64
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
65
-
66
- return E.runPromise(effect)
67
- })
68
-
69
- test('re-authenticate the user if no local token', async () => {
70
- const assertions = E.gen(function* (_) {
71
- const service = yield* _(EmailService)
72
- yield* _(service.verifyEmailCode({ code: '123' }))
73
-
74
- const authService = yield* _(AuthenticationService)
75
- expect(authService.authenticatePasskey).toHaveBeenCalled()
76
- })
77
-
78
- const storageServiceTest = L.effect(
79
- StorageService,
80
- E.sync(() => {
81
- const storageServiceMock = mock<StorageService['Type']>()
82
-
83
- storageServiceMock.getToken.mockReturnValue(E.fail(new NoSuchElementException()))
84
- storageServiceMock.clearToken.mockReturnValue(E.void)
85
-
86
- return storageServiceMock
87
- }),
88
- )
89
-
90
- const authServiceTest = L.effect(
91
- AuthenticationService,
92
- E.sync(() => {
93
- const authServiceMock = mock<AuthenticationService['Type']>()
94
-
95
- authServiceMock.authenticatePasskey.mockReturnValue(E.succeed(Fixture.principal))
96
-
97
- return authServiceMock
98
- }),
99
- )
100
-
101
- const service = pipe(
102
- EmailServiceLive,
103
- L.provide(Fixture.locationSearchTest),
104
- L.provide(authServiceTest),
105
- L.provide(storageServiceTest),
106
- L.provide(Fixture.rpcClientTest),
107
- )
108
-
109
- const layers = L.mergeAll(service, storageServiceTest, authServiceTest)
110
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
111
-
112
- return E.runPromise(effect)
113
- })
114
-
115
- test('call the backend', async () => {
116
- const assertions = E.gen(function* (_) {
117
- const service = yield* _(EmailService)
118
- yield* _(service.verifyEmailCode({ code: Fixture.code }))
119
-
120
- const rpcClient = yield* _(UserClient)
121
- expect(rpcClient.verifyEmail).toHaveBeenCalledWith(Fixture.rpcVerifyEmailReq)
122
- })
123
-
124
- const rpcClientTest = L.effect(
125
- UserClient,
126
- E.sync(() => {
127
- const rpcMock = mock<UserClient['Type']>()
128
-
129
- rpcMock.verifyEmail.mockReturnValue(E.succeed(Fixture.rpcVerifyEmailRes))
130
-
131
- return rpcMock
132
- }),
133
- )
134
-
135
- const service = pipe(
136
- EmailServiceLive,
137
- L.provide(Fixture.locationSearchTest),
138
- L.provide(Fixture.authenticationServiceTest),
139
- L.provide(Fixture.storageServiceTest),
140
- L.provide(rpcClientTest),
141
- )
142
-
143
- const layers = L.merge(service, rpcClientTest)
144
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
145
-
146
- return E.runPromise(effect)
147
- })
148
- })
149
-
150
- describe('verifyEmailLink should', () => {
151
- test('extract the code from the current url', async () => {
152
- const assertions = E.gen(function* (_) {
153
- const service = yield* _(EmailService)
154
- yield* _(service.verifyEmailLink())
155
-
156
- // LocationSearch return ?code=code
157
- // and we expect rpcClient to be called with code
158
- const rpcClient = yield* _(UserClient)
159
- expect(rpcClient.verifyEmail).toBeCalledWith(Fixture.rpcVerifyEmailReq)
160
- })
161
-
162
- const rpcClientTest = L.effect(
163
- UserClient,
164
- E.sync(() => {
165
- const rpcMock = mock<UserClient['Type']>()
166
-
167
- rpcMock.verifyEmail.mockReturnValue(E.succeed(Fixture.rpcVerifyEmailRes))
168
-
169
- return rpcMock
170
- }),
171
- )
172
-
173
- const service = pipe(
174
- EmailServiceLive,
175
- L.provide(Fixture.locationSearchTest),
176
- L.provide(Fixture.storageServiceTest),
177
- L.provide(Fixture.authenticationServiceTest),
178
- L.provide(rpcClientTest),
179
- )
180
-
181
- const layers = L.merge(service, rpcClientTest)
182
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
183
-
184
- return E.runPromise(effect)
185
- })
186
- })