@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
package/src/rpc/client.ts DELETED
@@ -1,174 +0,0 @@
1
- import * as S from '@effect/schema/Schema'
2
- import { Context, Effect as E, Layer, pipe } from 'effect'
3
-
4
- import { NetworkError } from '@passlock/shared/dist/error/error.js'
5
-
6
- import { PASSLOCK_CLIENT_VERSION } from '../version.js'
7
- import { RetrySchedule, RpcConfig } from './config.js'
8
-
9
- export type DispatcherResponse = {
10
- status: number
11
- body: object
12
- }
13
-
14
- /** To send the JSON to the backend */
15
- export class Dispatcher extends Context.Tag('@rpc/Dispatcher')<
16
- Dispatcher,
17
- {
18
- get: (path: string) => E.Effect<DispatcherResponse, NetworkError>
19
- post: (path: string, body: string) => E.Effect<DispatcherResponse, NetworkError>
20
- }
21
- >() {}
22
-
23
- /** Fires off client requests using fetch */
24
- /** TODO: Write tests */
25
- /** TODO: Evaluate platform/http client (if now stable) */
26
- export const DispatcherLive = Layer.effect(
27
- Dispatcher,
28
- E.gen(function* (_) {
29
- const { schedule } = yield* _(RetrySchedule)
30
- const { tenancyId, clientId, endpoint: maybeEndpoint } = yield* _(RpcConfig)
31
-
32
- const parseJson = (res: Response, url: string) =>
33
- E.tryPromise({
34
- try: () => res.json() as Promise<unknown>,
35
- catch: e =>
36
- new NetworkError({
37
- message: 'Unable to extract json response from ' + url,
38
- detail: String(e),
39
- }),
40
- })
41
-
42
- // 400 errors are reflected in the RPC response error channel
43
- // so in network terms they're still "ok"
44
- const assertNo500s = (res: Response, url: string) => {
45
- if (res.status >= 500) {
46
- return E.fail(
47
- new NetworkError({
48
- message: 'Received 500 response code from ' + url,
49
- }),
50
- )
51
- } else return E.void
52
- }
53
-
54
- const parseJsonObject = (json: unknown) => {
55
- return typeof json === 'object' && json !== null
56
- ? E.succeed(json)
57
- : E.fail(
58
- new NetworkError({
59
- message: `Expected JSON object to be returned from RPC endpoint, actual ${typeof json}`,
60
- }),
61
- )
62
- }
63
-
64
- const buildUrl = (_path: string) => {
65
- const endpoint = maybeEndpoint || 'https://api.passlock.dev'
66
- // drop leading /
67
- const path = _path.replace(/^\//, '')
68
- return `${endpoint}/${tenancyId}/${path}`
69
- }
70
-
71
- return {
72
- get: (path: string) => {
73
- const effect = E.gen(function* (_) {
74
- const headers = {
75
- 'Accept': 'application/json',
76
- 'X-CLIENT-ID': clientId,
77
- 'X-PASSLOCK-CLIENT-VERSION': PASSLOCK_CLIENT_VERSION,
78
- }
79
-
80
- const url = buildUrl(path)
81
-
82
- const res = yield* _(
83
- E.tryPromise({
84
- try: () => fetch(url, { method: 'GET', headers }),
85
- catch: e =>
86
- new NetworkError({ message: 'Unable to fetch from ' + url, detail: String(e) }),
87
- }),
88
- )
89
-
90
- const json = yield* _(parseJson(res, url))
91
- yield* _(assertNo500s(res, url))
92
- const jsonObject = yield* _(parseJsonObject(json))
93
-
94
- return { status: res.status, body: jsonObject }
95
- })
96
-
97
- return E.retry(effect, { schedule })
98
- },
99
-
100
- post: (_path: string, body: string) => {
101
- const effect = E.gen(function* (_) {
102
- const headers = {
103
- 'Content-Type': 'application/json',
104
- 'Accept': 'application/json',
105
- 'X-CLIENT-ID': clientId,
106
- 'X-PASSLOCK-CLIENT-VERSION': PASSLOCK_CLIENT_VERSION,
107
- }
108
-
109
- // drop leading /
110
- const url = buildUrl(_path)
111
-
112
- const res = yield* _(
113
- E.tryPromise({
114
- try: () => fetch(url, { method: 'POST', headers, body }),
115
- catch: e =>
116
- new NetworkError({ message: 'Unable to fetch from ' + url, detail: String(e) }),
117
- }),
118
- )
119
-
120
- const json = yield* _(parseJson(res, url))
121
- yield* _(assertNo500s(res, url))
122
- const jsonObject = yield* _(parseJsonObject(json))
123
-
124
- return { status: res.status, body: jsonObject }
125
- })
126
-
127
- return E.retry(effect, { schedule })
128
- },
129
- }
130
- }),
131
- )
132
-
133
- export const makeGetRequest =
134
- <Res, ResEnc, Err, ErrEnc>(
135
- responseSchema: S.Schema<Res, ResEnc, never>,
136
- errorSchema: S.Schema<Err, ErrEnc, never>,
137
- dispatcher: Dispatcher['Type'],
138
- ) =>
139
- (path: string) =>
140
- pipe(
141
- dispatcher.get(path),
142
- E.flatMap(res => {
143
- if (res.status === 200) return S.decodeUnknown(responseSchema)(res.body)
144
- return pipe(
145
- S.decodeUnknown(errorSchema)(res.body),
146
- E.flatMap(err => E.fail(err)),
147
- )
148
- }),
149
- E.catchTag('ParseError', e => E.die(e)),
150
- E.catchTag('NetworkError', e => E.die(e)),
151
- )
152
-
153
- export const makePostRequest =
154
- <Req, ReqEnc, Res, ResEnc, Err, ErrEnc>(
155
- requestSchema: S.Schema<Req, ReqEnc, never>,
156
- responseSchema: S.Schema<Res, ResEnc, never>,
157
- errorSchema: S.Schema<Err, ErrEnc, never>,
158
- dispatcher: Dispatcher['Type'],
159
- ) =>
160
- (path: string, request: Req) => {
161
- return pipe(
162
- S.encode(requestSchema)(request),
163
- E.flatMap(request => dispatcher.post(path, JSON.stringify(request))),
164
- E.flatMap(res => {
165
- if (res.status === 200) return S.decodeUnknown(responseSchema)(res.body)
166
- return pipe(
167
- S.decodeUnknown(errorSchema)(res.body),
168
- E.flatMap(err => E.fail(err)),
169
- )
170
- }),
171
- E.catchTag('ParseError', e => E.die(e)),
172
- E.catchTag('NetworkError', e => E.die(e)),
173
- )
174
- }
package/src/rpc/config.ts DELETED
@@ -1,18 +0,0 @@
1
- import type { Schedule } from 'effect'
2
- import { Context } from 'effect'
3
-
4
- export class RpcConfig extends Context.Tag('@rpc/RpcConfig')<
5
- RpcConfig,
6
- {
7
- endpoint?: string
8
- tenancyId: string
9
- clientId: string
10
- }
11
- >() {}
12
-
13
- export class RetrySchedule extends Context.Tag('@rpc/RetrySchedule')<
14
- RetrySchedule,
15
- {
16
- schedule: Schedule.Schedule<unknown>
17
- }
18
- >() {}
@@ -1,30 +0,0 @@
1
- import * as S from '@effect/schema/Schema'
2
- import { Context, Effect as E, Layer } from 'effect'
3
-
4
- import {
5
- CONNECT_ENDPOINT,
6
- ConnectRes,
7
- type ConnectionService,
8
- } from '@passlock/shared/dist/rpc/connection.js'
9
-
10
- import { Dispatcher, makeGetRequest } from './client.js'
11
-
12
- /* Client */
13
-
14
- export class ConnectionClient extends Context.Tag('@connection/client')<
15
- ConnectionClient,
16
- ConnectionService
17
- >() {}
18
-
19
- export const ConnectionClientLive = Layer.effect(
20
- ConnectionClient,
21
- E.gen(function* (_) {
22
- const dispatcher = yield* _(Dispatcher)
23
-
24
- const preConnectResolver = makeGetRequest(ConnectRes, S.Never, dispatcher)
25
-
26
- return {
27
- preConnect: () => preConnectResolver(CONNECT_ENDPOINT),
28
- }
29
- }),
30
- )
@@ -1,41 +0,0 @@
1
- import { Context, Effect as E, Layer } from 'effect'
2
-
3
- import {
4
- OptionsErrors,
5
- OptionsReq,
6
- OptionsRes,
7
- type RegistrationService,
8
- VerificationErrors,
9
- VerificationReq,
10
- VerificationRes,
11
- } from '@passlock/shared/dist/rpc/registration.js'
12
-
13
- import { Dispatcher, makePostRequest } from './client.js'
14
-
15
- /* Client */
16
-
17
- export class RegistrationClient extends Context.Tag('@passkey/register/client')<
18
- RegistrationClient,
19
- RegistrationService
20
- >() {}
21
-
22
- export const RegistrationClientLive = Layer.effect(
23
- RegistrationClient,
24
- E.gen(function* (_) {
25
- const dispatcher = yield* _(Dispatcher)
26
-
27
- const optionsResolver = makePostRequest(OptionsReq, OptionsRes, OptionsErrors, dispatcher)
28
-
29
- const verifyResolver = makePostRequest(
30
- VerificationReq,
31
- VerificationRes,
32
- VerificationErrors,
33
- dispatcher,
34
- )
35
-
36
- return {
37
- getRegistrationOptions: req => optionsResolver('/passkey/register/options', req),
38
- verifyRegistrationCredential: req => verifyResolver('/passkey/register/verify', req),
39
- }
40
- }),
41
- )
package/src/rpc/social.ts DELETED
@@ -1,45 +0,0 @@
1
- import { Context, Effect as E, Layer } from 'effect'
2
-
3
- import {
4
- AuthOidcErrors,
5
- AuthOidcReq,
6
- PrincipalRes,
7
- RegisterOidcErrors,
8
- RegisterOidcReq,
9
- type SocialService,
10
- } from '@passlock/shared/dist/rpc/social.js'
11
-
12
- import { Dispatcher, makePostRequest } from './client.js'
13
-
14
- /* Client */
15
-
16
- export const OIDC_REGISTER_ENDPOINT = '/social/oidc/register'
17
- export const OIDC_AUTH_ENDPOINT = '/social/oidc/auth'
18
-
19
- export class SocialClient extends Context.Tag('@social/client')<SocialClient, SocialService>() {}
20
-
21
- export const SocialClientLive = Layer.effect(
22
- SocialClient,
23
- E.gen(function* (_) {
24
- const dispatcher = yield* _(Dispatcher)
25
-
26
- const registerResolver = makePostRequest(
27
- RegisterOidcReq,
28
- PrincipalRes,
29
- RegisterOidcErrors,
30
- dispatcher,
31
- )
32
-
33
- const authenticateResolver = makePostRequest(
34
- AuthOidcReq,
35
- PrincipalRes,
36
- AuthOidcErrors,
37
- dispatcher,
38
- )
39
-
40
- return {
41
- registerOidc: req => registerResolver(OIDC_REGISTER_ENDPOINT, req),
42
- authenticateOidc: req => authenticateResolver(OIDC_AUTH_ENDPOINT, req),
43
- }
44
- }),
45
- )
package/src/rpc/user.ts DELETED
@@ -1,57 +0,0 @@
1
- import * as S from '@effect/schema/Schema'
2
- import { Context, Effect as E, Layer } from 'effect'
3
-
4
- import {
5
- IsExistingUserReq,
6
- IsExistingUserRes,
7
- RESEND_EMAIL_ENDPOINT,
8
- ResendEmailErrors,
9
- ResendEmailReq,
10
- ResendEmailRes,
11
- USER_STATUS_ENDPOINT,
12
- type UserService,
13
- VERIFY_EMAIL_ENDPOINT,
14
- VerifyEmailErrors,
15
- VerifyEmailReq,
16
- VerifyEmailRes,
17
- } from '@passlock/shared/dist/rpc/user.js'
18
-
19
- import { Dispatcher, makePostRequest } from './client.js'
20
-
21
- /* Client */
22
-
23
- export class UserClient extends Context.Tag('@user/client')<UserClient, UserService>() {}
24
-
25
- export const UserClientLive = Layer.effect(
26
- UserClient,
27
- E.gen(function* (_) {
28
- const dispatcher = yield* _(Dispatcher)
29
-
30
- const isExistingUserResolver = makePostRequest(
31
- IsExistingUserReq,
32
- IsExistingUserRes,
33
- S.Never,
34
- dispatcher,
35
- )
36
-
37
- const verifyEmailResolver = makePostRequest(
38
- VerifyEmailReq,
39
- VerifyEmailRes,
40
- VerifyEmailErrors,
41
- dispatcher,
42
- )
43
-
44
- const resendEmailResolver = makePostRequest(
45
- ResendEmailReq,
46
- ResendEmailRes,
47
- ResendEmailErrors,
48
- dispatcher,
49
- )
50
-
51
- return {
52
- isExistingUser: req => isExistingUserResolver(USER_STATUS_ENDPOINT, req),
53
- verifyEmail: req => verifyEmailResolver(VERIFY_EMAIL_ENDPOINT, req),
54
- resendVerificationEmail: req => resendEmailResolver(RESEND_EMAIL_ENDPOINT, req),
55
- }
56
- }),
57
- )
@@ -1,45 +0,0 @@
1
- import { Effect as E, Layer as L, Option as O } from 'effect'
2
-
3
- import * as Shared from '@passlock/shared/dist/rpc/social.js'
4
-
5
- import * as Fixtures from '../test/fixtures.js'
6
- import { SocialClient } from '../rpc/social.js'
7
- import type { AuthenticateOidcReq } from './social.js'
8
-
9
- export const session = 'session'
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 registerOidcReq = new Shared.RegisterOidcReq({
16
- provider: 'google',
17
- idToken: 'google-token',
18
- nonce: 'nonce',
19
- givenName: O.some('john'),
20
- familyName: O.some('doe'),
21
- })
22
-
23
- export const authOidcReq: AuthenticateOidcReq = new Shared.AuthOidcReq({
24
- provider: 'google',
25
- idToken: 'google-token',
26
- nonce: 'nonce',
27
- })
28
-
29
- export const rpcRegisterRes = new Shared.PrincipalRes({ principal: Fixtures.principal })
30
-
31
- export const rpcAuthenticateRes = new Shared.PrincipalRes({ principal: Fixtures.principal })
32
-
33
- export const rpcClientTest = L.succeed(
34
- SocialClient,
35
- SocialClient.of({
36
- registerOidc: () => E.fail(Fixtures.notImplemented),
37
- authenticateOidc: () => E.fail(Fixtures.notImplemented),
38
- }),
39
- )
40
-
41
- export const principal = Fixtures.principal
42
-
43
- export const capabilitiesTest = Fixtures.capabilitiesTest
44
-
45
- export const storageServiceTest = Fixtures.storageServiceTest
@@ -1,179 +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 { Duplicate, NotFound } from '@passlock/shared/dist/error/error.js'
6
-
7
- import * as Fixture from './social.fixture.js'
8
- import { SocialClient } from '../rpc/social.js'
9
- import { SocialService, SocialServiceLive } from './social.js'
10
-
11
- describe('registerOidc should', () => {
12
- test('return a valid credential', async () => {
13
- const assertions = E.gen(function* (_) {
14
- const service = yield* _(SocialService)
15
- const result = yield* _(service.registerOidc(Fixture.registerOidcReq))
16
- expect(result).toEqual(Fixture.principal)
17
- })
18
-
19
- const rpcClientTest = L.effect(
20
- SocialClient,
21
- E.sync(() => {
22
- const rpcMock = mock<SocialClient['Type']>()
23
-
24
- rpcMock.registerOidc.mockReturnValue(E.succeed(Fixture.rpcRegisterRes))
25
-
26
- return rpcMock
27
- }),
28
- )
29
-
30
- const service = pipe(SocialServiceLive, L.provide(rpcClientTest))
31
-
32
- const layers = Layer.merge(service, rpcClientTest)
33
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
34
-
35
- return E.runPromise(effect)
36
- })
37
-
38
- test('pass the request to the backend', async () => {
39
- const assertions = E.gen(function* (_) {
40
- const service = yield* _(SocialService)
41
- yield* _(service.registerOidc(Fixture.registerOidcReq))
42
-
43
- const rpcClient = yield* _(SocialClient)
44
- expect(rpcClient.registerOidc).toHaveBeenCalledWith(Fixture.registerOidcReq)
45
- })
46
-
47
- const rpcClientTest = L.effect(
48
- SocialClient,
49
- E.sync(() => {
50
- const rpcMock = mock<SocialClient['Type']>()
51
-
52
- rpcMock.registerOidc.mockReturnValue(E.succeed(Fixture.rpcRegisterRes))
53
-
54
- return rpcMock
55
- }),
56
- )
57
-
58
- const service = pipe(SocialServiceLive, L.provide(rpcClientTest))
59
-
60
- const layers = Layer.merge(service, rpcClientTest)
61
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
62
-
63
- return E.runPromise(effect)
64
- })
65
-
66
- test('return an error if we try to register an existing user', async () => {
67
- const assertions = E.gen(function* (_) {
68
- const service = yield* _(SocialService)
69
-
70
- const defect = yield* _(service.registerOidc(Fixture.registerOidcReq), E.flip)
71
-
72
- expect(defect).toBeInstanceOf(Duplicate)
73
- })
74
-
75
- const rpcClientTest = L.effect(
76
- SocialClient,
77
- E.sync(() => {
78
- const rpcMock = mock<SocialClient['Type']>()
79
-
80
- rpcMock.registerOidc.mockReturnValue(E.fail(new Duplicate({ message: 'Duplicate user' })))
81
-
82
- return rpcMock
83
- }),
84
- )
85
-
86
- const service = pipe(SocialServiceLive, L.provide(rpcClientTest))
87
-
88
- const layers = Layer.merge(service, rpcClientTest)
89
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
90
-
91
- return E.runPromise(effect)
92
- })
93
- })
94
-
95
- describe('authenticateIodc should', () => {
96
- test('return a valid credential', async () => {
97
- const assertions = E.gen(function* (_) {
98
- const service = yield* _(SocialService)
99
- const result = yield* _(service.authenticateOidc(Fixture.authOidcReq))
100
- expect(result).toEqual(Fixture.principal)
101
- })
102
-
103
- const rpcClientTest = L.effect(
104
- SocialClient,
105
- E.sync(() => {
106
- const rpcMock = mock<SocialClient['Type']>()
107
-
108
- rpcMock.authenticateOidc.mockReturnValue(E.succeed(Fixture.rpcRegisterRes))
109
-
110
- return rpcMock
111
- }),
112
- )
113
-
114
- const service = pipe(SocialServiceLive, L.provide(rpcClientTest))
115
-
116
- const layers = Layer.merge(service, rpcClientTest)
117
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
118
-
119
- return E.runPromise(effect)
120
- })
121
-
122
- test('pass the request to the backend', async () => {
123
- const assertions = E.gen(function* (_) {
124
- const service = yield* _(SocialService)
125
- yield* _(service.authenticateOidc(Fixture.authOidcReq))
126
-
127
- const rpcClient = yield* _(SocialClient)
128
- expect(rpcClient.authenticateOidc).toHaveBeenCalledWith(Fixture.authOidcReq)
129
- })
130
-
131
- const rpcClientTest = L.effect(
132
- SocialClient,
133
- E.sync(() => {
134
- const rpcMock = mock<SocialClient['Type']>()
135
-
136
- rpcMock.authenticateOidc.mockReturnValue(E.succeed(Fixture.rpcAuthenticateRes))
137
-
138
- return rpcMock
139
- }),
140
- )
141
-
142
- const service = pipe(SocialServiceLive, L.provide(rpcClientTest))
143
-
144
- const layers = Layer.merge(service, rpcClientTest)
145
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
146
-
147
- return E.runPromise(effect)
148
- })
149
-
150
- test('return an error if we try to authenticate a non-existing user', async () => {
151
- const assertions = E.gen(function* (_) {
152
- const service = yield* _(SocialService)
153
-
154
- const defect = yield* _(service.authenticateOidc(Fixture.authOidcReq), E.flip)
155
-
156
- expect(defect).toBeInstanceOf(NotFound)
157
- })
158
-
159
- const rpcClientTest = L.effect(
160
- SocialClient,
161
- E.sync(() => {
162
- const rpcMock = mock<SocialClient['Type']>()
163
-
164
- rpcMock.authenticateOidc.mockReturnValue(
165
- E.fail(new NotFound({ message: 'User not found' })),
166
- )
167
-
168
- return rpcMock
169
- }),
170
- )
171
-
172
- const service = pipe(SocialServiceLive, L.provide(rpcClientTest))
173
-
174
- const layers = Layer.merge(service, rpcClientTest)
175
- const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None))
176
-
177
- return E.runPromise(effect)
178
- })
179
- })
@@ -1,82 +0,0 @@
1
- /**
2
- * Passkey authentication effects
3
- */
4
- import { Context, Effect as E, Layer, flow } from 'effect'
5
-
6
- import * as RPC from '@passlock/shared/dist/rpc/social.js'
7
- import { type BadRequest, type NotSupported } from '@passlock/shared/dist/error/error.js'
8
- import type { Principal } from '@passlock/shared/dist/schema/principal.js'
9
-
10
- import { SocialClient } from '../rpc/social.js'
11
-
12
- /* Requests */
13
-
14
- export type Provider = 'apple' | 'google'
15
-
16
- export type RegisterOidcReq = RPC.RegisterOidcReq
17
-
18
- export type AuthenticateOidcReq = RPC.AuthOidcReq
19
-
20
- /* Errors */
21
-
22
- export type RegistrationErrors = NotSupported | BadRequest | RPC.RegisterOidcErrors
23
-
24
- export type AuthenticationErrors = NotSupported | BadRequest | RPC.AuthOidcErrors
25
-
26
- /* Service */
27
-
28
- export class SocialService extends Context.Tag('@services/SocialService')<
29
- SocialService,
30
- {
31
- registerOidc: (req: RegisterOidcReq) => E.Effect<Principal, RegistrationErrors>
32
- authenticateOidc: (req: AuthenticateOidcReq) => E.Effect<Principal, AuthenticationErrors>
33
- }
34
- >() {}
35
-
36
- /* Effects */
37
-
38
- type Dependencies = SocialClient
39
-
40
- export const registerOidc = (
41
- request: RegisterOidcReq,
42
- ): E.Effect<Principal, RegistrationErrors, Dependencies> => {
43
- return E.gen(function* (_) {
44
- yield* _(E.logInfo('Registering social account'))
45
-
46
- const rpcClient = yield* _(SocialClient)
47
- const rpcRequest = new RPC.RegisterOidcReq(request)
48
- const { principal } = yield* _(rpcClient.registerOidc(rpcRequest))
49
-
50
- return principal
51
- })
52
- }
53
-
54
- export const authenticateOidc = (
55
- request: AuthenticateOidcReq,
56
- ): E.Effect<Principal, AuthenticationErrors, Dependencies> => {
57
- return E.gen(function* (_) {
58
- yield* _(E.logInfo('Authenticating with social account'))
59
-
60
- const rpcClient = yield* _(SocialClient)
61
- const rpcRequest = new RPC.AuthOidcReq(request)
62
- const { principal } = yield* _(rpcClient.authenticateOidc(rpcRequest))
63
-
64
- return principal
65
- })
66
- }
67
-
68
- /* Live */
69
-
70
- /* v8 ignore start */
71
- export const SocialServiceLive = Layer.effect(
72
- SocialService,
73
- E.gen(function* (_) {
74
- const context = yield* _(E.context<SocialClient>())
75
-
76
- return SocialService.of({
77
- registerOidc: flow(registerOidc, E.provide(context)),
78
- authenticateOidc: flow(authenticateOidc, E.provide(context)),
79
- })
80
- }),
81
- )
82
- /* v8 ignore stop */
@@ -1,16 +0,0 @@
1
- import { Effect as E, Layer, pipe } from 'effect'
2
- import { mock } from 'vitest-mock-extended'
3
-
4
- import { BrowserStorage, StorageServiceLive } from './storage.js'
5
-
6
- const storageTest = Layer.effect(
7
- BrowserStorage,
8
- E.sync(() => mock<Storage>()),
9
- )
10
-
11
- export const testLayers = (storage: Layer.Layer<BrowserStorage> = storageTest) => {
12
- const storageService = pipe(StorageServiceLive, Layer.provide(storage))
13
- return Layer.merge(storage, storageService)
14
- }
15
-
16
- export { principal } from '../test/fixtures.js'