@passlock/client 0.9.17 → 0.9.21

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 (137) hide show
  1. package/dist/authentication/authenticate.d.ts +5 -4
  2. package/dist/authentication/authenticate.d.ts.map +1 -1
  3. package/dist/authentication/authenticate.fixture.d.ts +4 -5
  4. package/dist/authentication/authenticate.fixture.d.ts.map +1 -1
  5. package/dist/authentication/authenticate.fixture.js +2 -11
  6. package/dist/authentication/authenticate.fixture.js.map +1 -1
  7. package/dist/authentication/authenticate.js +4 -4
  8. package/dist/authentication/authenticate.js.map +1 -1
  9. package/dist/authentication/authenticate.test.js +5 -5
  10. package/dist/authentication/authenticate.test.js.map +1 -1
  11. package/dist/connection/connection.d.ts +4 -3
  12. package/dist/connection/connection.d.ts.map +1 -1
  13. package/dist/connection/connection.fixture.d.ts +3 -5
  14. package/dist/connection/connection.fixture.d.ts.map +1 -1
  15. package/dist/connection/connection.fixture.js +3 -15
  16. package/dist/connection/connection.fixture.js.map +1 -1
  17. package/dist/connection/connection.js +3 -3
  18. package/dist/connection/connection.js.map +1 -1
  19. package/dist/connection/connection.test.js +6 -5
  20. package/dist/connection/connection.test.js.map +1 -1
  21. package/dist/effect.d.ts +4 -4
  22. package/dist/effect.d.ts.map +1 -1
  23. package/dist/effect.js +17 -8
  24. package/dist/effect.js.map +1 -1
  25. package/dist/email/email.d.ts +5 -5
  26. package/dist/email/email.d.ts.map +1 -1
  27. package/dist/email/email.fixture.d.ts +3 -4
  28. package/dist/email/email.fixture.d.ts.map +1 -1
  29. package/dist/email/email.fixture.js +2 -10
  30. package/dist/email/email.fixture.js.map +1 -1
  31. package/dist/email/email.js +2 -3
  32. package/dist/email/email.js.map +1 -1
  33. package/dist/email/email.test.js +5 -5
  34. package/dist/email/email.test.js.map +1 -1
  35. package/dist/index.d.ts +13 -11
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/logging/eventLogger.d.ts.map +1 -1
  39. package/dist/logging/eventLogger.js +15 -9
  40. package/dist/logging/eventLogger.js.map +1 -1
  41. package/dist/logging/eventLogger.test.js.map +1 -1
  42. package/dist/registration/register.d.ts +6 -4
  43. package/dist/registration/register.d.ts.map +1 -1
  44. package/dist/registration/register.fixture.d.ts +4 -5
  45. package/dist/registration/register.fixture.d.ts.map +1 -1
  46. package/dist/registration/register.fixture.js +2 -12
  47. package/dist/registration/register.fixture.js.map +1 -1
  48. package/dist/registration/register.js +5 -4
  49. package/dist/registration/register.js.map +1 -1
  50. package/dist/registration/register.test.js +6 -6
  51. package/dist/registration/register.test.js.map +1 -1
  52. package/dist/rpc/authentication.d.ts +9 -0
  53. package/dist/rpc/authentication.d.ts.map +1 -0
  54. package/dist/rpc/authentication.js +15 -0
  55. package/dist/rpc/authentication.js.map +1 -0
  56. package/dist/rpc/client.d.ts +27 -0
  57. package/dist/rpc/client.d.ts.map +1 -0
  58. package/dist/rpc/client.js +92 -0
  59. package/dist/rpc/client.js.map +1 -0
  60. package/dist/rpc/config.d.ts +16 -0
  61. package/dist/rpc/config.d.ts.map +1 -0
  62. package/dist/rpc/config.js +6 -0
  63. package/dist/rpc/config.js.map +1 -0
  64. package/dist/rpc/connection.d.ts +9 -0
  65. package/dist/rpc/connection.d.ts.map +1 -0
  66. package/dist/rpc/connection.js +14 -0
  67. package/dist/rpc/connection.js.map +1 -0
  68. package/dist/rpc/registration.d.ts +9 -0
  69. package/dist/rpc/registration.d.ts.map +1 -0
  70. package/dist/rpc/registration.js +15 -0
  71. package/dist/rpc/registration.js.map +1 -0
  72. package/dist/rpc/social.d.ts +11 -0
  73. package/dist/rpc/social.d.ts.map +1 -0
  74. package/dist/rpc/social.js +17 -0
  75. package/dist/rpc/social.js.map +1 -0
  76. package/dist/rpc/user.d.ts +9 -0
  77. package/dist/rpc/user.d.ts.map +1 -0
  78. package/dist/rpc/user.js +18 -0
  79. package/dist/rpc/user.js.map +1 -0
  80. package/dist/social/social.d.ts +22 -13
  81. package/dist/social/social.d.ts.map +1 -1
  82. package/dist/social/social.fixture.d.ts +10 -10
  83. package/dist/social/social.fixture.d.ts.map +1 -1
  84. package/dist/social/social.fixture.js +21 -19
  85. package/dist/social/social.fixture.js.map +1 -1
  86. package/dist/social/social.js +12 -6
  87. package/dist/social/social.js.map +1 -1
  88. package/dist/social/social.test.js +15 -15
  89. package/dist/social/social.test.js.map +1 -1
  90. package/dist/storage/storage.d.ts +2 -2
  91. package/dist/storage/storage.d.ts.map +1 -1
  92. package/dist/storage/storage.js +1 -0
  93. package/dist/storage/storage.js.map +1 -1
  94. package/dist/test/fixtures.d.ts +1 -3
  95. package/dist/test/fixtures.d.ts.map +1 -1
  96. package/dist/test/fixtures.js +0 -2
  97. package/dist/test/fixtures.js.map +1 -1
  98. package/dist/user/user.d.ts +4 -4
  99. package/dist/user/user.d.ts.map +1 -1
  100. package/dist/user/user.fixture.d.ts +2 -3
  101. package/dist/user/user.fixture.d.ts.map +1 -1
  102. package/dist/user/user.fixture.js +2 -10
  103. package/dist/user/user.fixture.js.map +1 -1
  104. package/dist/user/user.js +3 -4
  105. package/dist/user/user.js.map +1 -1
  106. package/dist/user/user.test.js +5 -5
  107. package/dist/user/user.test.js.map +1 -1
  108. package/dist/version.d.ts +2 -0
  109. package/dist/version.d.ts.map +1 -0
  110. package/dist/version.js +2 -0
  111. package/dist/version.js.map +1 -0
  112. package/package.json +10 -11
  113. package/src/authentication/authenticate.fixture.ts +8 -16
  114. package/src/authentication/authenticate.test.ts +7 -7
  115. package/src/authentication/authenticate.ts +13 -14
  116. package/src/connection/connection.fixture.ts +4 -16
  117. package/src/connection/connection.test.ts +7 -6
  118. package/src/connection/connection.ts +5 -5
  119. package/src/effect.ts +22 -16
  120. package/src/email/email.fixture.ts +3 -11
  121. package/src/email/email.test.ts +7 -7
  122. package/src/email/email.ts +5 -6
  123. package/src/index.ts +10 -7
  124. package/src/logging/eventLogger.test.ts +1 -0
  125. package/src/logging/eventLogger.ts +16 -10
  126. package/src/registration/register.fixture.ts +9 -18
  127. package/src/registration/register.test.ts +9 -9
  128. package/src/registration/register.ts +12 -13
  129. package/src/social/social.fixture.ts +25 -21
  130. package/src/social/social.test.ts +21 -21
  131. package/src/social/social.ts +40 -19
  132. package/src/storage/storage.ts +3 -2
  133. package/src/test/fixtures.ts +1 -3
  134. package/src/user/user.fixture.ts +3 -11
  135. package/src/user/user.test.ts +7 -7
  136. package/src/user/user.ts +6 -7
  137. package/README.md +0 -116
@@ -1,9 +1,8 @@
1
- import { PreConnectRes } from '@passlock/shared/dist/rpc/connection.js'
2
- import { RpcClient } from '@passlock/shared/dist/rpc/rpc.js'
3
- import { AuthenticateOidcReq, OidcRes, RegisterOidcReq } from '@passlock/shared/dist/rpc/social.js'
1
+ import * as Shared from '@passlock/shared/dist/rpc/social.js'
2
+ import { SocialClient } from '@passlock/shared/dist/rpc/social.js'
4
3
  import { Effect as E, Layer as L } from 'effect'
5
4
  import * as Fixtures from '../test/fixtures.js'
6
- import { type OidcRequest } from './social.js'
5
+ import type { AuthenticateOidcReq, RegisterOidcReq } from './social.js'
7
6
 
8
7
  export const session = 'session'
9
8
  export const token = 'token'
@@ -11,33 +10,38 @@ export const code = 'code'
11
10
  export const authType = 'passkey'
12
11
  export const expireAt = Date.now() + 10000
13
12
 
14
- export const oidcReq: OidcRequest = {
13
+ export const registerOidcReq: RegisterOidcReq = {
15
14
  provider: 'google',
16
- idToken: 'google-token'
15
+ idToken: 'google-token',
16
+ nonce: 'nonce',
17
+ givenName: 'john',
18
+ familyName: 'doe'
17
19
  }
18
20
 
19
- export const rpcRegisterReq = new RegisterOidcReq({ ...oidcReq })
21
+ export const authOidcReq: AuthenticateOidcReq = {
22
+ provider: 'google',
23
+ idToken: 'google-token',
24
+ nonce: 'nonce'
25
+ }
26
+
27
+ export const rpcRegisterReq = new Shared.RegisterOidcReq({
28
+ ...registerOidcReq,
29
+ ...(registerOidcReq.givenName ? { givenName: registerOidcReq.givenName } : {}),
30
+ ...(registerOidcReq.familyName ? { familyName: registerOidcReq.familyName } : {})
31
+ })
20
32
 
21
- export const rpcRegisterRes = new OidcRes({ principal: Fixtures.principal })
33
+ export const rpcRegisterRes = new Shared.PrincipalRes({ principal: Fixtures.principal })
22
34
 
23
- export const rpcAuthenticateReq = new AuthenticateOidcReq({ ...oidcReq })
35
+ export const rpcAuthenticateReq = new Shared.AuthOidcReq({ ...authOidcReq })
24
36
 
25
- export const rpcAuthenticateRes = new OidcRes({ principal: Fixtures.principal })
37
+ export const rpcAuthenticateRes = new Shared.PrincipalRes({ principal: Fixtures.principal })
26
38
 
27
39
  export const rpcClientTest = L.succeed(
28
- RpcClient,
29
- RpcClient.of({
30
- preConnect: () => E.succeed(new PreConnectRes({ warmed: true })),
31
- isExistingUser: () => E.fail(Fixtures.notImplemented),
32
- verifyEmail: () => E.fail(Fixtures.notImplemented),
33
- getRegistrationOptions: () => E.fail(Fixtures.notImplemented),
34
- verifyRegistrationCredential: () => E.fail(Fixtures.notImplemented),
35
- getAuthenticationOptions: () => E.fail(Fixtures.notImplemented),
36
- verifyAuthenticationCredential: () => E.fail(Fixtures.notImplemented),
40
+ SocialClient,
41
+ SocialClient.of({
37
42
  registerOidc: () => E.fail(Fixtures.notImplemented),
38
43
  authenticateOidc: () => E.fail(Fixtures.notImplemented),
39
- resendVerificationEmail: () => E.fail(Fixtures.notImplemented),
40
- }),
44
+ })
41
45
  )
42
46
 
43
47
  export const principal = Fixtures.principal
@@ -1,5 +1,5 @@
1
1
  import { Duplicate, NotFound } from '@passlock/shared/dist/error/error.js'
2
- import { RpcClient, type RouterOps } from '@passlock/shared/dist/rpc/rpc.js'
2
+ import { SocialClient } from '@passlock/shared/dist/rpc/social.js'
3
3
  import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect'
4
4
  import { describe, expect, test } from 'vitest'
5
5
  import { mock } from 'vitest-mock-extended'
@@ -10,14 +10,14 @@ describe('registerOidc should', () => {
10
10
  test('return a valid credential', async () => {
11
11
  const assertions = E.gen(function* (_) {
12
12
  const service = yield* _(SocialService)
13
- const result = yield* _(service.registerOidc(Fixture.oidcReq))
13
+ const result = yield* _(service.registerOidc(Fixture.registerOidcReq))
14
14
  expect(result).toEqual(Fixture.principal)
15
15
  })
16
16
 
17
17
  const rpcClientTest = L.effect(
18
- RpcClient,
18
+ SocialClient,
19
19
  E.sync(() => {
20
- const rpcMock = mock<RouterOps>()
20
+ const rpcMock = mock<SocialClient['Type']>()
21
21
 
22
22
  rpcMock.registerOidc.mockReturnValue(E.succeed(Fixture.rpcRegisterRes))
23
23
 
@@ -39,16 +39,16 @@ describe('registerOidc should', () => {
39
39
  test('pass the request to the backend', async () => {
40
40
  const assertions = E.gen(function* (_) {
41
41
  const service = yield* _(SocialService)
42
- yield* _(service.registerOidc(Fixture.oidcReq))
42
+ yield* _(service.registerOidc(Fixture.registerOidcReq))
43
43
 
44
- const rpcClient = yield* _(RpcClient)
44
+ const rpcClient = yield* _(SocialClient)
45
45
  expect(rpcClient.registerOidc).toHaveBeenCalledWith(Fixture.rpcRegisterReq)
46
46
  })
47
47
 
48
48
  const rpcClientTest = L.effect(
49
- RpcClient,
49
+ SocialClient,
50
50
  E.sync(() => {
51
- const rpcMock = mock<RouterOps>()
51
+ const rpcMock = mock<SocialClient['Type']>()
52
52
 
53
53
  rpcMock.registerOidc.mockReturnValue(E.succeed(Fixture.rpcRegisterRes))
54
54
 
@@ -71,15 +71,15 @@ describe('registerOidc should', () => {
71
71
  const assertions = E.gen(function* (_) {
72
72
  const service = yield* _(SocialService)
73
73
 
74
- const defect = yield* _(service.registerOidc(Fixture.oidcReq), E.flip)
74
+ const defect = yield* _(service.registerOidc(Fixture.registerOidcReq), E.flip)
75
75
 
76
76
  expect(defect).toBeInstanceOf(Duplicate)
77
77
  })
78
78
 
79
79
  const rpcClientTest = L.effect(
80
- RpcClient,
80
+ SocialClient,
81
81
  E.sync(() => {
82
- const rpcMock = mock<RouterOps>()
82
+ const rpcMock = mock<SocialClient['Type']>()
83
83
 
84
84
  rpcMock.registerOidc.mockReturnValue(E.fail(new Duplicate({ message: "Duplicate user" })))
85
85
 
@@ -103,14 +103,14 @@ describe('authenticateIodc should', () => {
103
103
  test('return a valid credential', async () => {
104
104
  const assertions = E.gen(function* (_) {
105
105
  const service = yield* _(SocialService)
106
- const result = yield* _(service.authenticateOidc(Fixture.oidcReq))
106
+ const result = yield* _(service.authenticateOidc(Fixture.authOidcReq))
107
107
  expect(result).toEqual(Fixture.principal)
108
108
  })
109
109
 
110
110
  const rpcClientTest = L.effect(
111
- RpcClient,
111
+ SocialClient,
112
112
  E.sync(() => {
113
- const rpcMock = mock<RouterOps>()
113
+ const rpcMock = mock<SocialClient['Type']>()
114
114
 
115
115
  rpcMock.authenticateOidc.mockReturnValue(E.succeed(Fixture.rpcRegisterRes))
116
116
 
@@ -132,16 +132,16 @@ describe('authenticateIodc should', () => {
132
132
  test('pass the request to the backend', async () => {
133
133
  const assertions = E.gen(function* (_) {
134
134
  const service = yield* _(SocialService)
135
- yield* _(service.authenticateOidc(Fixture.oidcReq))
135
+ yield* _(service.authenticateOidc(Fixture.authOidcReq))
136
136
 
137
- const rpcClient = yield* _(RpcClient)
137
+ const rpcClient = yield* _(SocialClient)
138
138
  expect(rpcClient.authenticateOidc).toHaveBeenCalledWith(Fixture.rpcAuthenticateReq)
139
139
  })
140
140
 
141
141
  const rpcClientTest = L.effect(
142
- RpcClient,
142
+ SocialClient,
143
143
  E.sync(() => {
144
- const rpcMock = mock<RouterOps>()
144
+ const rpcMock = mock<SocialClient['Type']>()
145
145
 
146
146
  rpcMock.authenticateOidc.mockReturnValue(E.succeed(Fixture.rpcAuthenticateRes))
147
147
 
@@ -164,15 +164,15 @@ describe('authenticateIodc should', () => {
164
164
  const assertions = E.gen(function* (_) {
165
165
  const service = yield* _(SocialService)
166
166
 
167
- const defect = yield* _(service.authenticateOidc(Fixture.oidcReq), E.flip)
167
+ const defect = yield* _(service.authenticateOidc(Fixture.authOidcReq), E.flip)
168
168
 
169
169
  expect(defect).toBeInstanceOf(NotFound)
170
170
  })
171
171
 
172
172
  const rpcClientTest = L.effect(
173
- RpcClient,
173
+ SocialClient,
174
174
  E.sync(() => {
175
- const rpcMock = mock<RouterOps>()
175
+ const rpcMock = mock<SocialClient['Type']>()
176
176
 
177
177
  rpcMock.authenticateOidc.mockReturnValue(E.fail(new NotFound({ message: "User not found" })))
178
178
 
@@ -2,31 +2,45 @@
2
2
  * Passkey authentication effects
3
3
  */
4
4
  import {
5
- type BadRequest,
6
- type NotSupported
5
+ type BadRequest,
6
+ type NotSupported
7
7
  } from '@passlock/shared/dist/error/error.js'
8
- import { RpcClient } from '@passlock/shared/dist/rpc/rpc.js'
9
- import { AuthenticateOidcErrors, AuthenticateOidcReq, RegisterOidcErrors, RegisterOidcReq } from '@passlock/shared/dist/rpc/social.js'
8
+ import * as Shared from '@passlock/shared/dist/rpc/social.js'
9
+ import { SocialClient } from '@passlock/shared/dist/rpc/social.js'
10
10
  import type {
11
- Principal
12
- } from '@passlock/shared/dist/schema/schema.js'
11
+ Principal
12
+ } from '@passlock/shared/dist/schema/principal.js'
13
13
  import { Context, Effect as E, Layer, flow } from 'effect'
14
14
 
15
15
  /* Requests */
16
16
 
17
- export type OidcRequest = { provider: 'google', idToken: string }
17
+ export type Provider = 'apple' | 'google'
18
+
19
+ export type RegisterOidcReq = {
20
+ provider: Provider
21
+ idToken: string
22
+ nonce: string
23
+ givenName?: string
24
+ familyName?: string
25
+ }
26
+
27
+ export type AuthenticateOidcReq = {
28
+ provider: Provider
29
+ idToken: string
30
+ nonce: string
31
+ }
18
32
 
19
33
  /* Errors */
20
34
 
21
- export type RegistrationErrors = NotSupported | BadRequest | RegisterOidcErrors
35
+ export type RegistrationErrors = NotSupported | BadRequest | Shared.RegisterOidcErrors
22
36
 
23
- export type AuthenticationErrors = NotSupported | BadRequest | AuthenticateOidcErrors
37
+ export type AuthenticationErrors = NotSupported | BadRequest | Shared.AuthOidcErrors
24
38
 
25
39
  /* Service */
26
40
 
27
41
  export type SocialService = {
28
- registerOidc: (data: OidcRequest) => E.Effect<Principal, RegistrationErrors>
29
- authenticateOidc: (data: OidcRequest) => E.Effect<Principal, AuthenticationErrors>
42
+ registerOidc: (data: RegisterOidcReq) => E.Effect<Principal, RegistrationErrors>
43
+ authenticateOidc: (data: AuthenticateOidcReq) => E.Effect<Principal, AuthenticationErrors>
30
44
  }
31
45
 
32
46
  export const SocialService = Context.GenericTag<SocialService>(
@@ -35,18 +49,24 @@ export const SocialService = Context.GenericTag<SocialService>(
35
49
 
36
50
  /* Effects */
37
51
 
38
- type Dependencies = RpcClient
52
+ type Dependencies = SocialClient
39
53
 
40
54
  export const registerOidc = (
41
- request: OidcRequest,
55
+ request: RegisterOidcReq,
42
56
  ): E.Effect<Principal, RegistrationErrors, Dependencies> => {
43
57
  return E.gen(function* (_) {
44
58
  yield* _(E.logInfo('Registering social account'))
45
59
 
46
- const rpcClient = yield* _(RpcClient)
60
+ const rpcClient = yield* _(SocialClient)
61
+
62
+ const rpcRequest = new Shared.RegisterOidcReq({
63
+ ...request,
64
+ ...(request.givenName ? { givenName: request.givenName } : {}),
65
+ ...(request.familyName ? { familyName: request.familyName } : {})
66
+ })
47
67
 
48
68
  const { principal } = yield* _(
49
- rpcClient.registerOidc(new RegisterOidcReq(request))
69
+ rpcClient.registerOidc(rpcRequest)
50
70
  )
51
71
 
52
72
  return principal
@@ -54,15 +74,16 @@ export const registerOidc = (
54
74
  }
55
75
 
56
76
  export const authenticateOidc = (
57
- request: OidcRequest,
77
+ request: AuthenticateOidcReq,
58
78
  ): E.Effect<Principal, AuthenticationErrors, Dependencies> => {
59
79
  return E.gen(function* (_) {
60
80
  yield* _(E.logInfo('Authenticating with social account'))
61
81
 
62
- const rpcClient = yield* _(RpcClient)
82
+ const rpcClient = yield* _(SocialClient)
83
+ const rpcRequest = new Shared.AuthOidcReq(request)
63
84
 
64
85
  const { principal } = yield* _(
65
- rpcClient.authenticateOidc(new AuthenticateOidcReq(request))
86
+ rpcClient.authenticateOidc(rpcRequest)
66
87
  )
67
88
 
68
89
  return principal
@@ -75,7 +96,7 @@ export const authenticateOidc = (
75
96
  export const SocialServiceLive = Layer.effect(
76
97
  SocialService,
77
98
  E.gen(function* (_) {
78
- const context = yield* _(E.context<RpcClient>())
99
+ const context = yield* _(E.context<SocialClient>())
79
100
 
80
101
  return SocialService.of({
81
102
  registerOidc: flow(registerOidc, E.provide(context)),
@@ -2,13 +2,13 @@
2
2
  * Wrapper around local storage that allows us to store
3
3
  * authentication tokens in local storage for a short period.
4
4
  */
5
- import type { Principal } from '@passlock/shared/dist/schema/schema.js'
5
+ import type { Principal } from '@passlock/shared/dist/schema/principal.js'
6
6
  import { Context, Effect as E, Layer, Option as O, flow, pipe } from 'effect'
7
7
  import type { NoSuchElementException } from 'effect/Cause'
8
8
 
9
9
  /* Requests */
10
10
 
11
- export type AuthType = 'email' | 'passkey' | 'google'
11
+ export type AuthType = 'email' | 'passkey' | 'apple' | 'google'
12
12
 
13
13
  export type StoredToken = {
14
14
  token: string
@@ -144,6 +144,7 @@ export const clearExpiredTokens: E.Effect<void, never, Storage> = E.all([
144
144
  clearExpiredToken('passkey'),
145
145
  clearExpiredToken('email'),
146
146
  clearExpiredToken('google'),
147
+ clearExpiredToken('apple'),
147
148
  ])
148
149
 
149
150
  /* Live */
@@ -1,6 +1,5 @@
1
1
  import { BadRequest } from '@passlock/shared/dist/error/error.js'
2
- import { PreConnectRes } from '@passlock/shared/dist/rpc/connection.js'
3
- import type { Principal } from '@passlock/shared/dist/schema/schema.js'
2
+ import type { Principal } from '@passlock/shared/dist/schema/principal.js'
4
3
  import { Effect as E, Layer as L } from 'effect'
5
4
  import { Capabilities } from '../capabilities/capabilities.js'
6
5
  import { StorageService, type StoredToken } from '../storage/storage.js'
@@ -51,5 +50,4 @@ export const storageServiceTest = L.succeed(
51
50
  }),
52
51
  )
53
52
 
54
- export const preConnectRes = new PreConnectRes({ warmed: true })
55
53
  export const notImplemented = new BadRequest({ message: 'Not implemented' })
@@ -1,5 +1,4 @@
1
- import { RpcClient } from '@passlock/shared/dist/rpc/rpc.js'
2
- import { IsExistingUserReq, IsExistingUserRes, ResendEmailReq, ResendEmailRes, VerifyEmailRes } from '@passlock/shared/dist/rpc/user.js'
1
+ import { IsExistingUserReq, IsExistingUserRes, ResendEmailReq, ResendEmailRes, UserClient, VerifyEmailRes } from '@passlock/shared/dist/rpc/user.js'
3
2
  import { Effect as E, Layer as L } from 'effect'
4
3
  import * as Fixtures from '../test/fixtures.js'
5
4
  import type { ResendEmail } from './user.js'
@@ -13,17 +12,10 @@ export const rpcResendEmailReq = new ResendEmailReq({ userId: '123', verifyEmail
13
12
  export const rpcResendEmailRes = new ResendEmailRes({ })
14
13
 
15
14
  export const rpcClientTest = L.succeed(
16
- RpcClient,
17
- RpcClient.of({
18
- preConnect: () => E.succeed({ warmed: true }),
15
+ UserClient,
16
+ UserClient.of({
19
17
  isExistingUser: () => E.succeed({ existingUser: true }),
20
18
  verifyEmail: () => E.succeed(verifyEmailRes),
21
- getRegistrationOptions: () => E.fail(Fixtures.notImplemented),
22
- verifyRegistrationCredential: () => E.fail(Fixtures.notImplemented),
23
- getAuthenticationOptions: () => E.fail(Fixtures.notImplemented),
24
- verifyAuthenticationCredential: () => E.fail(Fixtures.notImplemented),
25
- registerOidc: () => E.fail(Fixtures.notImplemented),
26
- authenticateOidc: () => E.fail(Fixtures.notImplemented),
27
19
  resendVerificationEmail: () => E.fail(Fixtures.notImplemented),
28
20
  }),
29
21
  )
@@ -1,4 +1,4 @@
1
- import { RpcClient, type RouterOps } from '@passlock/shared/dist/rpc/rpc.js'
1
+ import { UserClient } from '@passlock/shared/dist/rpc/user.js'
2
2
  import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect'
3
3
  import { describe, expect, test } from 'vitest'
4
4
  import { mock } from 'vitest-mock-extended'
@@ -27,14 +27,14 @@ describe('isExistingUser should', () => {
27
27
  const result = yield* _(service.isExistingUser({ email: Fixture.email }))
28
28
 
29
29
  expect(result).toBe(false)
30
- const rpcClient = yield* _(RpcClient)
30
+ const rpcClient = yield* _(UserClient)
31
31
  expect(rpcClient.isExistingUser).toBeCalledWith(Fixture.isRegisteredReq)
32
32
  })
33
33
 
34
34
  const rpcClientTest = Layer.effect(
35
- RpcClient,
35
+ UserClient,
36
36
  E.sync(() => {
37
- const rpcMock = mock<RouterOps>()
37
+ const rpcMock = mock<UserClient['Type']>()
38
38
 
39
39
  rpcMock.isExistingUser.mockReturnValue(E.succeed(Fixture.isRegisteredRes))
40
40
 
@@ -57,14 +57,14 @@ describe('resendVerificationEmail should', () => {
57
57
  const service = yield* _(UserService)
58
58
  yield* _(service.resendVerificationEmail(Fixture.resendEmailReq))
59
59
 
60
- const rpcClient = yield* _(RpcClient)
60
+ const rpcClient = yield* _(UserClient)
61
61
  expect(rpcClient.resendVerificationEmail).toBeCalledWith(Fixture.rpcResendEmailReq)
62
62
  })
63
63
 
64
64
  const rpcClientTest = Layer.effect(
65
- RpcClient,
65
+ UserClient,
66
66
  E.sync(() => {
67
- const rpcMock = mock<RouterOps>()
67
+ const rpcMock = mock<UserClient['Type']>()
68
68
 
69
69
  rpcMock.resendVerificationEmail.mockReturnValue(E.succeed(Fixture.rpcResendEmailRes))
70
70
 
package/src/user/user.ts CHANGED
@@ -2,9 +2,8 @@
2
2
  * Check for an existing user
3
3
  */
4
4
  import type { BadRequest, Disabled, NotFound } from '@passlock/shared/dist/error/error.js'
5
- import { RpcClient } from '@passlock/shared/dist/rpc/rpc.js'
6
- import { IsExistingUserReq, ResendEmailReq } from '@passlock/shared/dist/rpc/user.js'
7
- import type { VerifyEmail } from '@passlock/shared/dist/schema/schema.js'
5
+ import { IsExistingUserReq, ResendEmailReq, UserClient } from '@passlock/shared/dist/rpc/user.js'
6
+ import type { VerifyEmail } from '@passlock/shared/dist/schema/email.js'
8
7
  import { Context, Effect as E, Layer, flow } from 'effect'
9
8
 
10
9
  /* Requests */
@@ -27,12 +26,12 @@ export const UserService = Context.GenericTag<UserService>('@services/UserServic
27
26
 
28
27
  /* Effects */
29
28
 
30
- type Dependencies = RpcClient
29
+ type Dependencies = UserClient
31
30
 
32
31
  export const isExistingUser = (request: Email): E.Effect<boolean, BadRequest, Dependencies> => {
33
32
  return E.gen(function* (_) {
34
33
  yield* _(E.logInfo('Checking registration status'))
35
- const rpcClient = yield* _(RpcClient)
34
+ const rpcClient = yield* _(UserClient)
36
35
 
37
36
  yield* _(E.logDebug('Making RPC request'))
38
37
  const { existingUser } = yield* _(rpcClient.isExistingUser(new IsExistingUserReq(request)))
@@ -44,7 +43,7 @@ export const isExistingUser = (request: Email): E.Effect<boolean, BadRequest, De
44
43
  export const resendVerificationEmail = (request: ResendEmail): E.Effect<void, ResendEmailErrors, Dependencies> => {
45
44
  return E.gen(function* (_) {
46
45
  yield* _(E.logInfo('Resending verification email'))
47
- const rpcClient = yield* _(RpcClient)
46
+ const rpcClient = yield* _(UserClient)
48
47
 
49
48
  yield* _(E.logDebug('Making RPC request'))
50
49
  const { userId, ...verifyEmail } = request
@@ -58,7 +57,7 @@ export const resendVerificationEmail = (request: ResendEmail): E.Effect<void, Re
58
57
  export const UserServiceLive = Layer.effect(
59
58
  UserService,
60
59
  E.gen(function* (_) {
61
- const context = yield* _(E.context<RpcClient>())
60
+ const context = yield* _(E.context<UserClient>())
62
61
  return UserService.of({
63
62
  isExistingUser: flow(isExistingUser, E.provide(context)),
64
63
  resendVerificationEmail: flow(resendVerificationEmail, E.provide(context))
package/README.md DELETED
@@ -1,116 +0,0 @@
1
- <div align="center">
2
- <a href="https://github.com/passlock-dev/passkeys-frontend">
3
- <img src="https://github.com/passlock-dev/passkeys-frontend/assets/208345/53ee00d3-8e6c-49ea-b43c-3f901450c73b" alt="Passlock logo" width="80" height="80">
4
- </a>
5
- </div>
6
-
7
- <a name="readme-top"></a>
8
- <h1 align="center">Serverless Passkeys</h1>
9
-
10
- <p align="center">
11
- Passkey authentication for your web apps. Supports React, Angular, Vue, SvelteKit & others.
12
- <br />
13
- <a href="https://passlock.dev"><strong>Project website »</strong></a>
14
- <br />
15
- <a href="https://passlock.dev/#demo">Demo</a>
16
- ·
17
- <a href="https://docs.passlock.dev">Documentation</a>
18
- ·
19
- <a href="https://docs.passlock.dev/docs/tutorial/intro">Tutorial</a>
20
- </p>
21
- </div>
22
-
23
- <br />
24
-
25
- ## Features
26
-
27
- Passkeys and the WebAuthn API are quite complex. We've taken an opinionated approach to simplify things for you. Following the 80/20 principle we've tried to focus on the features most valuable to developers and users. We welcome feature requests so do [get in touch][contact].
28
-
29
- 1. **🔐 Primary & secondary authentication** - Replace password based logins with passkeys, or use passkeys alongside passwords for secondary authentication.
30
-
31
- 2. **☝🏻 Biometrics** - We've made it really easy to implement facial or fingerprint recognition in your webapps.
32
-
33
- 3. **🔐 Step up authentication** - Require biometric or PIN verification for some operations, whilst allowing one-tap authentication for others.
34
-
35
- 4. **🚀 Social login** - Quickly add social login to your web application.
36
-
37
- 5. **🖥️ Full management console** - Manage all security related aspects of your userbase through a web based console.
38
-
39
- 6. **🕵️ Audit trail** - View a full audit trail for each user: when they add a new passkey, when they login, verify their email address and much more.
40
-
41
- ## Screenshot
42
-
43
- ![Passlock user profile](https://github.com/passlock-dev/passkeys/assets/208345/a4a5c4b8-86cb-4076-bd26-7c29ed2151c6)
44
- <p align="center">Viewing a user's authentication activity on their profile page</p>
45
-
46
- ## Usage
47
-
48
- Use this library to generate a secure token, representing passkey registration or authentication. Send the token to your backend for verification (see below)
49
-
50
- ### Register a passkey
51
-
52
- ```typescript
53
- import { Passlock, PasslockError } from '@passlock/client'
54
-
55
- // you can find these details in the settings area of the Passlock console
56
- const tenancyId = '...'
57
- const clientId = '...'
58
-
59
- const passlock = new Passlock({ tenancyId, clientId })
60
-
61
- // to register a new passkey, call registerPasskey(). We're using placeholders for
62
- // the user data. You should grab this from an HTML form, React store, Redux etc.
63
- const [email, givenName, familyName] = ["jdoe@gmail.com", "John", "Doe"]
64
-
65
- // Passlock doesn't throw but instead returns a union: result | error
66
- const result = await passlock.registerPasskey({ email, givenName, familyName })
67
-
68
- // ensure Passlock didn't return an error
69
- if (!PasslockError.isError(result)) {
70
- // send the token to your backend (json/fetch or hidden form field etc)
71
- console.log('Token: %s', result.token)
72
- }
73
- ```
74
-
75
- ### Authenticate using a passkey
76
-
77
- ```typescript
78
- import { Passlock, PasslockError } from '@passlock/client'
79
-
80
- const tenancyId = '...'
81
- const clientId = '...'
82
-
83
- const passlock = new Passlock({ tenancyId, clientId })
84
- const result = await passlock.authenticatePasskey()
85
-
86
- if (!PasslockError.isError(result)) {
87
- // send the token to your backend for verification
88
- console.log('Token: %s', result.token)
89
- }
90
- ```
91
-
92
- ### Backend verification
93
-
94
- Verify the token and obtain the passkey registration or authentication details. You can make a simple GET request to `https://api.passlock.dev/{tenancyId}/token/{token}` or use the [@passlock/node][node] library:
95
-
96
- ```typescript
97
- import { Passlock } from '@passlock/node'
98
-
99
- // API Keys can be found in your passlock console
100
- const passlock = new Passlock({ tenancyId, apiKey })
101
-
102
- // token comes from your frontend
103
- const principal = await passlock.fetchPrincipal({ token })
104
-
105
- // get the user id
106
- console.log(principal.user.id)
107
- ```
108
-
109
- ## More information
110
-
111
- Please see the [tutorial][tutorial] and [documentation][docs]
112
-
113
- [contact]: https://passlock.dev/contact
114
- [tutorial]: https://docs.passlock.dev/docs/tutorial/intro
115
- [docs]: https://docs.passlock.dev
116
- [node]: https://www.npmjs.com/package/@passlock/node