@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.
- package/README.md +14 -86
- package/README.template.md +16 -88
- package/dist/index.d.ts +4 -206
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -158
- package/dist/index.js.map +1 -1
- package/dist/logger/index.d.ts +24 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +47 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/network.d.ts +39 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +83 -0
- package/dist/network.js.map +1 -0
- package/dist/passkey/authentication/index.d.ts +21 -0
- package/dist/passkey/authentication/index.d.ts.map +1 -0
- package/dist/passkey/authentication/index.js +22 -0
- package/dist/passkey/authentication/index.js.map +1 -0
- package/dist/passkey/authentication/micro.d.ts +71 -0
- package/dist/passkey/authentication/micro.d.ts.map +1 -0
- package/dist/passkey/authentication/micro.js +107 -0
- package/dist/passkey/authentication/micro.js.map +1 -0
- package/dist/passkey/index.d.ts +7 -0
- package/dist/passkey/index.d.ts.map +1 -0
- package/dist/passkey/index.js +5 -0
- package/dist/passkey/index.js.map +1 -0
- package/dist/passkey/registration/index.d.ts +19 -0
- package/dist/passkey/registration/index.d.ts.map +1 -0
- package/dist/passkey/registration/index.js +20 -0
- package/dist/passkey/registration/index.js.map +1 -0
- package/dist/passkey/registration/micro.d.ts +101 -0
- package/dist/passkey/registration/micro.d.ts.map +1 -0
- package/dist/passkey/registration/micro.js +126 -0
- package/dist/passkey/registration/micro.js.map +1 -0
- package/dist/passkey/shared.d.ts +24 -0
- package/dist/passkey/shared.d.ts.map +1 -0
- package/dist/passkey/shared.js +10 -0
- package/dist/passkey/shared.js.map +1 -0
- package/dist/passkey/support.d.ts +3 -0
- package/dist/passkey/support.d.ts.map +1 -0
- package/dist/passkey/support.js +4 -0
- package/dist/passkey/support.js.map +1 -0
- package/dist/passkey/types.d.ts +26 -0
- package/dist/passkey/types.d.ts.map +1 -0
- package/dist/passkey/types.js +2 -0
- package/dist/passkey/types.js.map +1 -0
- package/dist/promise.d.ts +15 -0
- package/dist/promise.d.ts.map +1 -0
- package/dist/promise.js +46 -0
- package/dist/promise.js.map +1 -0
- package/dist/shared.d.ts +15 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +2 -0
- package/dist/shared.js.map +1 -0
- package/dist/tenancy.d.ts +8 -0
- package/dist/tenancy.d.ts.map +1 -0
- package/dist/tenancy.js +4 -0
- package/dist/tenancy.js.map +1 -0
- package/package.json +52 -58
- package/LICENSE +0 -21
- package/dist/authentication/authenticate.d.ts +0 -23
- package/dist/authentication/authenticate.fixture.d.ts +0 -52
- package/dist/authentication/authenticate.fixture.js +0 -50
- package/dist/authentication/authenticate.fixture.js.map +0 -1
- package/dist/authentication/authenticate.js +0 -72
- package/dist/authentication/authenticate.js.map +0 -1
- package/dist/capabilities/capabilities.d.ts +0 -19
- package/dist/capabilities/capabilities.js +0 -37
- package/dist/capabilities/capabilities.js.map +0 -1
- package/dist/connection/connection.d.ts +0 -15
- package/dist/connection/connection.fixture.d.ts +0 -10
- package/dist/connection/connection.fixture.js +0 -13
- package/dist/connection/connection.fixture.js.map +0 -1
- package/dist/connection/connection.js +0 -23
- package/dist/connection/connection.js.map +0 -1
- package/dist/effect.d.ts +0 -26
- package/dist/effect.js +0 -78
- package/dist/effect.js.map +0 -1
- package/dist/email/email.d.ts +0 -70
- package/dist/email/email.fixture.d.ts +0 -46
- package/dist/email/email.fixture.js +0 -25
- package/dist/email/email.fixture.js.map +0 -1
- package/dist/email/email.js +0 -83
- package/dist/email/email.js.map +0 -1
- package/dist/event/event.d.ts +0 -8
- package/dist/event/event.js +0 -23
- package/dist/event/event.js.map +0 -1
- package/dist/logging/eventLogger.d.ts +0 -17
- package/dist/logging/eventLogger.js +0 -38
- package/dist/logging/eventLogger.js.map +0 -1
- package/dist/registration/register.d.ts +0 -25
- package/dist/registration/register.fixture.d.ts +0 -53
- package/dist/registration/register.fixture.js +0 -66
- package/dist/registration/register.fixture.js.map +0 -1
- package/dist/registration/register.js +0 -77
- package/dist/registration/register.js.map +0 -1
- package/dist/rpc/client.d.ts +0 -30
- package/dist/rpc/client.js +0 -101
- package/dist/rpc/client.js.map +0 -1
- package/dist/rpc/config.d.ts +0 -15
- package/dist/rpc/config.js +0 -6
- package/dist/rpc/config.js.map +0 -1
- package/dist/rpc/connection.d.ts +0 -8
- package/dist/rpc/connection.js +0 -16
- package/dist/rpc/connection.js.map +0 -1
- package/dist/rpc/passkey/authentication.d.ts +0 -8
- package/dist/rpc/passkey/authentication.js +0 -17
- package/dist/rpc/passkey/authentication.js.map +0 -1
- package/dist/rpc/passkey/registration.d.ts +0 -8
- package/dist/rpc/passkey/registration.js +0 -17
- package/dist/rpc/passkey/registration.js.map +0 -1
- package/dist/rpc/social.d.ts +0 -10
- package/dist/rpc/social.js +0 -19
- package/dist/rpc/social.js.map +0 -1
- package/dist/rpc/user.d.ts +0 -8
- package/dist/rpc/user.js +0 -20
- package/dist/rpc/user.js.map +0 -1
- package/dist/social/social.d.ts +0 -23
- package/dist/social/social.fixture.d.ts +0 -46
- package/dist/social/social.fixture.js +0 -31
- package/dist/social/social.fixture.js.map +0 -1
- package/dist/social/social.js +0 -38
- package/dist/social/social.js.map +0 -1
- package/dist/storage/storage.d.ts +0 -56
- package/dist/storage/storage.fixture.d.ts +0 -4
- package/dist/storage/storage.fixture.js +0 -10
- package/dist/storage/storage.fixture.js.map +0 -1
- package/dist/storage/storage.js +0 -111
- package/dist/storage/storage.js.map +0 -1
- package/dist/test/fixtures.d.ts +0 -15
- package/dist/test/fixtures.js +0 -56
- package/dist/test/fixtures.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/user/user.d.ts +0 -25
- package/dist/user/user.fixture.d.ts +0 -12
- package/dist/user/user.fixture.js +0 -20
- package/dist/user/user.fixture.js.map +0 -1
- package/dist/user/user.js +0 -37
- package/dist/user/user.js.map +0 -1
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -2
- package/dist/version.js.map +0 -1
- package/src/authentication/authenticate.fixture.ts +0 -73
- package/src/authentication/authenticate.test.ts +0 -249
- package/src/authentication/authenticate.ts +0 -143
- package/src/capabilities/capabilities.ts +0 -83
- package/src/connection/connection.fixture.ts +0 -20
- package/src/connection/connection.test.ts +0 -60
- package/src/connection/connection.ts +0 -51
- package/src/effect.ts +0 -280
- package/src/email/email.fixture.ts +0 -44
- package/src/email/email.test.ts +0 -186
- package/src/email/email.ts +0 -148
- package/src/event/event.node.test.ts +0 -21
- package/src/event/event.test.ts +0 -37
- package/src/event/event.ts +0 -25
- package/src/index.ts +0 -407
- package/src/logging/eventLogger.test.ts +0 -104
- package/src/logging/eventLogger.ts +0 -41
- package/src/registration/register.fixture.ts +0 -96
- package/src/registration/register.test.ts +0 -216
- package/src/registration/register.ts +0 -156
- package/src/rpc/client.ts +0 -174
- package/src/rpc/config.ts +0 -18
- package/src/rpc/connection.ts +0 -32
- package/src/rpc/passkey/authentication.ts +0 -52
- package/src/rpc/passkey/registration.ts +0 -52
- package/src/rpc/social.ts +0 -55
- package/src/rpc/user.ts +0 -68
- package/src/social/social.fixture.ts +0 -44
- package/src/social/social.test.ts +0 -179
- package/src/social/social.ts +0 -79
- package/src/storage/storage.fixture.ts +0 -16
- package/src/storage/storage.test.ts +0 -206
- package/src/storage/storage.ts +0 -168
- package/src/test/fixtures.ts +0 -70
- package/src/user/user.fixture.ts +0 -33
- package/src/user/user.test.ts +0 -84
- package/src/user/user.ts +0 -71
- 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
|
package/src/email/email.test.ts
DELETED
|
@@ -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
|
-
})
|