@passlock/client 0.9.22 → 0.9.24

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 (156) hide show
  1. package/README.md +10 -5
  2. package/README.template.md +130 -0
  3. package/dist/authentication/authenticate.d.ts +16 -16
  4. package/dist/authentication/authenticate.fixture.d.ts +21 -7
  5. package/dist/authentication/authenticate.fixture.js +7 -5
  6. package/dist/authentication/authenticate.fixture.js.map +1 -1
  7. package/dist/authentication/authenticate.js +19 -8
  8. package/dist/authentication/authenticate.js.map +1 -1
  9. package/dist/capabilities/capabilities.d.ts +9 -5
  10. package/dist/capabilities/capabilities.js +11 -2
  11. package/dist/capabilities/capabilities.js.map +1 -1
  12. package/dist/connection/connection.d.ts +11 -7
  13. package/dist/connection/connection.fixture.d.ts +2 -2
  14. package/dist/connection/connection.fixture.js +2 -1
  15. package/dist/connection/connection.fixture.js.map +1 -1
  16. package/dist/connection/connection.js +12 -3
  17. package/dist/connection/connection.js.map +1 -1
  18. package/dist/effect.d.ts +23 -46
  19. package/dist/effect.js +55 -51
  20. package/dist/effect.js.map +1 -1
  21. package/dist/email/email.d.ts +42 -12
  22. package/dist/email/email.fixture.d.ts +19 -5
  23. package/dist/email/email.fixture.js +5 -4
  24. package/dist/email/email.fixture.js.map +1 -1
  25. package/dist/email/email.js +44 -8
  26. package/dist/email/email.js.map +1 -1
  27. package/dist/event/event.d.ts +4 -2
  28. package/dist/event/event.js +4 -1
  29. package/dist/event/event.js.map +1 -1
  30. package/dist/index.d.ts +105 -27
  31. package/dist/index.js +101 -50
  32. package/dist/index.js.map +1 -1
  33. package/dist/logging/eventLogger.d.ts +13 -1
  34. package/dist/logging/eventLogger.js +14 -1
  35. package/dist/logging/eventLogger.js.map +1 -1
  36. package/dist/registration/register.d.ts +19 -22
  37. package/dist/registration/register.fixture.d.ts +20 -6
  38. package/dist/registration/register.fixture.js +14 -7
  39. package/dist/registration/register.fixture.js.map +1 -1
  40. package/dist/registration/register.js +18 -9
  41. package/dist/registration/register.js.map +1 -1
  42. package/dist/rpc/authentication.d.ts +1 -2
  43. package/dist/rpc/authentication.js +2 -1
  44. package/dist/rpc/authentication.js.map +1 -1
  45. package/dist/rpc/client.d.ts +5 -2
  46. package/dist/rpc/client.js +12 -3
  47. package/dist/rpc/client.js.map +1 -1
  48. package/dist/rpc/config.d.ts +0 -1
  49. package/dist/rpc/connection.d.ts +1 -2
  50. package/dist/rpc/connection.js +2 -1
  51. package/dist/rpc/connection.js.map +1 -1
  52. package/dist/rpc/registration.d.ts +1 -2
  53. package/dist/rpc/registration.js +2 -1
  54. package/dist/rpc/registration.js.map +1 -1
  55. package/dist/rpc/social.d.ts +1 -2
  56. package/dist/rpc/social.js +2 -1
  57. package/dist/rpc/social.js.map +1 -1
  58. package/dist/rpc/user.d.ts +1 -2
  59. package/dist/rpc/user.js +2 -1
  60. package/dist/rpc/user.js.map +1 -1
  61. package/dist/social/social.d.ts +17 -24
  62. package/dist/social/social.fixture.d.ts +22 -10
  63. package/dist/social/social.fixture.js +8 -14
  64. package/dist/social/social.fixture.js.map +1 -1
  65. package/dist/social/social.js +15 -11
  66. package/dist/social/social.js.map +1 -1
  67. package/dist/storage/storage.d.ts +41 -13
  68. package/dist/storage/storage.fixture.d.ts +2 -2
  69. package/dist/storage/storage.fixture.js +2 -2
  70. package/dist/storage/storage.fixture.js.map +1 -1
  71. package/dist/storage/storage.js +52 -15
  72. package/dist/storage/storage.js.map +1 -1
  73. package/dist/test/fixtures.d.ts +2 -3
  74. package/dist/test/fixtures.js +20 -5
  75. package/dist/test/fixtures.js.map +1 -1
  76. package/dist/user/user.d.ts +9 -6
  77. package/dist/user/user.fixture.d.ts +2 -2
  78. package/dist/user/user.fixture.js +9 -5
  79. package/dist/user/user.fixture.js.map +1 -1
  80. package/dist/user/user.js +12 -3
  81. package/dist/user/user.js.map +1 -1
  82. package/dist/version.d.ts +1 -2
  83. package/dist/version.js +1 -1
  84. package/dist/version.js.map +1 -1
  85. package/package.json +38 -30
  86. package/src/authentication/authenticate.fixture.ts +10 -7
  87. package/src/authentication/authenticate.test.ts +61 -18
  88. package/src/authentication/authenticate.ts +37 -33
  89. package/src/capabilities/capabilities.ts +11 -9
  90. package/src/connection/connection.fixture.ts +4 -1
  91. package/src/connection/connection.test.ts +4 -3
  92. package/src/connection/connection.ts +10 -8
  93. package/src/effect.ts +129 -134
  94. package/src/email/email.fixture.ts +7 -4
  95. package/src/email/email.test.ts +6 -5
  96. package/src/email/email.ts +27 -17
  97. package/src/event/event.node.test.ts +1 -0
  98. package/src/event/event.test.ts +1 -0
  99. package/src/event/event.ts +2 -1
  100. package/src/index.ts +235 -173
  101. package/src/logging/eventLogger.test.ts +2 -1
  102. package/src/logging/eventLogger.ts +3 -3
  103. package/src/registration/register.fixture.ts +16 -8
  104. package/src/registration/register.test.ts +16 -10
  105. package/src/registration/register.ts +37 -35
  106. package/src/rpc/authentication.ts +43 -0
  107. package/src/rpc/client.ts +174 -0
  108. package/src/rpc/config.ts +18 -0
  109. package/src/rpc/connection.ts +30 -0
  110. package/src/rpc/registration.ts +41 -0
  111. package/src/rpc/social.ts +45 -0
  112. package/src/rpc/user.ts +57 -0
  113. package/src/social/social.fixture.ts +12 -18
  114. package/src/social/social.test.ts +16 -30
  115. package/src/social/social.ts +22 -47
  116. package/src/storage/storage.fixture.ts +4 -4
  117. package/src/storage/storage.test.ts +29 -19
  118. package/src/storage/storage.ts +37 -36
  119. package/src/test/fixtures.ts +23 -6
  120. package/src/user/user.fixture.ts +19 -7
  121. package/src/user/user.test.ts +3 -5
  122. package/src/user/user.ts +16 -10
  123. package/src/version.ts +1 -0
  124. package/dist/authentication/authenticate.d.ts.map +0 -1
  125. package/dist/authentication/authenticate.fixture.d.ts.map +0 -1
  126. package/dist/capabilities/capabilities.d.ts.map +0 -1
  127. package/dist/config.d.ts +0 -18
  128. package/dist/config.d.ts.map +0 -1
  129. package/dist/config.js +0 -20
  130. package/dist/config.js.map +0 -1
  131. package/dist/connection/connection.d.ts.map +0 -1
  132. package/dist/connection/connection.fixture.d.ts.map +0 -1
  133. package/dist/effect.d.ts.map +0 -1
  134. package/dist/email/email.d.ts.map +0 -1
  135. package/dist/email/email.fixture.d.ts.map +0 -1
  136. package/dist/event/event.d.ts.map +0 -1
  137. package/dist/index.d.ts.map +0 -1
  138. package/dist/logging/eventLogger.d.ts.map +0 -1
  139. package/dist/registration/register.d.ts.map +0 -1
  140. package/dist/registration/register.fixture.d.ts.map +0 -1
  141. package/dist/rpc/authentication.d.ts.map +0 -1
  142. package/dist/rpc/client.d.ts.map +0 -1
  143. package/dist/rpc/config.d.ts.map +0 -1
  144. package/dist/rpc/connection.d.ts.map +0 -1
  145. package/dist/rpc/registration.d.ts.map +0 -1
  146. package/dist/rpc/social.d.ts.map +0 -1
  147. package/dist/rpc/user.d.ts.map +0 -1
  148. package/dist/social/social.d.ts.map +0 -1
  149. package/dist/social/social.fixture.d.ts.map +0 -1
  150. package/dist/storage/storage.d.ts.map +0 -1
  151. package/dist/storage/storage.fixture.d.ts.map +0 -1
  152. package/dist/test/fixtures.d.ts.map +0 -1
  153. package/dist/user/user.d.ts.map +0 -1
  154. package/dist/user/user.fixture.d.ts.map +0 -1
  155. package/dist/version.d.ts.map +0 -1
  156. package/src/config.ts +0 -42
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@passlock/client",
3
- "version": "0.9.22",
4
- "description": "Easy WebAuthn/FIDO Passkey authentication and social login for web apps. This library works with pretty much any frontend/backend stack including React/Next.js, Vue etc.",
3
+ "version": "0.9.24",
4
+ "description": "Passkey authentication and social login for web apps (Typescript). Framework agnostic",
5
5
  "keywords": [
6
6
  "passkey",
7
7
  "passkeys",
@@ -9,6 +9,8 @@
9
9
  "google one tap",
10
10
  "sign in with google",
11
11
  "sign in with apple",
12
+ "svelte",
13
+ "sveltekit",
12
14
  "react",
13
15
  "next",
14
16
  "vue",
@@ -19,10 +21,11 @@
19
21
  "email": "toby@passlock.dev"
20
22
  },
21
23
  "license": "MIT",
22
- "homepage": "https://github.com/passlock-dev/ts-clients",
24
+ "homepage": "https://passlock.dev",
23
25
  "repository": {
24
26
  "type": "git",
25
- "url": "git+https://github.com/passlock-dev/ts-clients.git"
27
+ "url": "git+https://github.com/passlock-dev/ts-clients.git",
28
+ "directory": "packages/client"
26
29
  },
27
30
  "bugs": {
28
31
  "url": "https://github.com/passlock-dev/ts-clients/issues",
@@ -42,45 +45,50 @@
42
45
  "!dist/**/*.spec.*"
43
46
  ],
44
47
  "dependencies": {
48
+ "@effect/schema": "0.71.0",
45
49
  "@github/webauthn-json": "^2.1.1",
46
- "effect": "3.4.8",
47
- "@passlock/shared": "0.9.22"
50
+ "effect": "3.6.4",
51
+ "@passlock/shared": "0.9.24"
48
52
  },
49
53
  "devDependencies": {
50
- "@tsconfig/node18": "^18.2.4",
51
- "@types/node": "^20.14.10",
52
- "@typescript-eslint/eslint-plugin": "^7.15.0",
53
- "@typescript-eslint/parser": "^7.15.0",
54
- "@vitest/coverage-v8": "^2.0.3",
55
- "@vitest/ui": "^2.0.3",
56
- "eslint": "^8.57.0",
54
+ "@qetza/replacetokens": "^1.7.0",
55
+ "@total-typescript/tsconfig": "^1.0.4",
56
+ "@trivago/prettier-plugin-sort-imports": "^4.3.0",
57
+ "@tsconfig/node20": "^20.1.4",
58
+ "@types/node": "^22.4.0",
59
+ "@typescript-eslint/eslint-plugin": "^8.1.0",
60
+ "@typescript-eslint/parser": "^8.1.0",
61
+ "@vitest/coverage-v8": "^2.0.5",
62
+ "@vitest/ui": "^2.0.5",
63
+ "eslint": "^9.9.0",
57
64
  "eslint-config-prettier": "^9.1.0",
58
- "eslint-import-resolver-typescript": "^3.6.1",
59
- "eslint-plugin-import": "^2.29.1",
60
- "jsdom": "^24.1.0",
61
- "prettier": "^3.3.2",
62
- "publint": "^0.1.9",
63
- "rimraf": "^5.0.8",
65
+ "globals": "^15.9.0",
66
+ "jsdom": "^24.1.1",
67
+ "prettier": "^3.3.3",
68
+ "publint": "^0.2.10",
69
+ "rimraf": "^6.0.1",
64
70
  "tslib": "^2.6.3",
65
- "typescript": "^5.5.3",
66
- "vite": "^5.3.3",
67
- "vitest": "^2.0.3",
68
- "vitest-mock-extended": "^1.3.1"
71
+ "tsx": "^4.17.0",
72
+ "typescript": "^5.5.4",
73
+ "vite": "^5.4.1",
74
+ "vitest": "^2.0.5",
75
+ "vitest-mock-extended": "^2.0.0"
69
76
  },
70
77
  "scripts": {
71
- "clean": "tsc --build --clean",
78
+ "clean": "rimraf ./dist",
72
79
  "typecheck": "tsc --noEmit",
73
80
  "test": "vitest run",
74
81
  "test:watch": "vitest dev",
75
82
  "test:ui": "vitest --coverage.enabled=true --ui",
76
83
  "test:coverage": "vitest run --coverage",
77
- "build": "tsc --build && publint",
84
+ "build": "tsc --build",
78
85
  "build:clean": "pnpm run clean && pnpm run build",
79
- "build:watch": "tsc --build --watch",
80
- "format": "prettier --write \"src/**/*.+(js|ts|json)\"",
81
- "lint": "eslint --ext .ts src",
86
+ "build:readme": "LATEST=${npm_package_version} tsx ../shared/scripts/replace-readme-tokens.ts ./packages/client",
87
+ "replaceTokens": "LATEST=${npm_package_version} tsx ../shared/scripts/replace-tokens.ts ./packages/client",
88
+ "build:production": "pnpm run build:clean && pnpm run replaceTokens && echo '' && publint",
89
+ "format": "prettier --write \"(src|scripts)/**/*.+(js|ts|json)\"",
90
+ "lint": "eslint ./src",
82
91
  "lint:fix": "pnpm run lint --fix",
83
- "ncu": "ncu --peer -x @effect/* -x effect",
84
- "ncu:save": "ncu --peer -x @effect/* -x effect -u"
92
+ "upgrade:deps": "ncu --peer -x effect -x @effect/* -i -u"
85
93
  }
86
94
  }
@@ -1,14 +1,16 @@
1
+ import { Effect as E, Layer as L, Option as O } from 'effect'
2
+
1
3
  import {
2
- AuthenticationClient,
3
4
  OptionsRes,
4
5
  VerificationReq,
5
6
  VerificationRes,
6
7
  } from '@passlock/shared/dist/rpc/authentication.js'
7
8
  import { IsExistingUserRes, VerifyEmailRes } from '@passlock/shared/dist/rpc/user.js'
8
9
  import type { AuthenticationCredential } from '@passlock/shared/dist/schema/passkey.js'
9
- import { Effect as E, Layer as L } from 'effect'
10
+
10
11
  import * as Fixtures from '../test/fixtures.js'
11
- import { GetCredential, type AuthenticationRequest } from './authenticate.js'
12
+ import { AuthenticationClient } from '../rpc/authentication.js'
13
+ import { type AuthenticationRequest, GetCredential } from './authenticate.js'
12
14
 
13
15
  export const session = 'session'
14
16
  export const token = 'token'
@@ -17,7 +19,8 @@ export const authType = 'passkey'
17
19
  export const expireAt = Date.now() + 10000
18
20
 
19
21
  export const request: AuthenticationRequest = {
20
- userVerification: 'preferred',
22
+ userVerification: O.some('preferred'),
23
+ email: O.none(),
21
24
  }
22
25
 
23
26
  export const rpcOptionsRes = new OptionsRes({
@@ -48,13 +51,13 @@ export const rpcVerificationReq = new VerificationReq({ session, credential })
48
51
 
49
52
  export const rpcVerificationRes = new VerificationRes({ principal: Fixtures.principal })
50
53
 
51
- export const rpcIsExistingUserRes = new IsExistingUserRes({ existingUser: true })
54
+ export const rpcIsExistingUserRes = new IsExistingUserRes({ existingUser: true, detail: O.none() })
52
55
 
53
56
  export const rpcVerifyEmailRes = new VerifyEmailRes({ principal: Fixtures.principal })
54
57
 
55
58
  export const getCredentialTest = L.succeed(
56
59
  GetCredential,
57
- GetCredential.of(() => E.succeed(credential)),
60
+ GetCredential.of({ getCredential: () => E.succeed(credential) }),
58
61
  )
59
62
 
60
63
  export const rpcClientTest = L.succeed(
@@ -62,7 +65,7 @@ export const rpcClientTest = L.succeed(
62
65
  AuthenticationClient.of({
63
66
  getAuthenticationOptions: () => E.succeed(rpcOptionsRes),
64
67
  verifyAuthenticationCredential: () => E.succeed(rpcVerificationRes),
65
- })
68
+ }),
66
69
  )
67
70
 
68
71
  export const principal = Fixtures.principal
@@ -1,16 +1,23 @@
1
- import { AuthenticationClient } from '@passlock/shared/dist/rpc/authentication.js'
2
- import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect'
1
+ import { Effect as E, Layer as L, Layer, LogLevel, Logger, Option as O, pipe } from 'effect'
3
2
  import { describe, expect, test, vi } from 'vitest'
4
3
  import { mock } from 'vitest-mock-extended'
5
- import { StorageService } from '../storage/storage.js'
4
+
6
5
  import * as Fixture from './authenticate.fixture.js'
6
+ import { AuthenticationClient } from '../rpc/authentication.js'
7
+ import { StorageService } from '../storage/storage.js'
7
8
  import { AuthenticateServiceLive, AuthenticationService, GetCredential } from './authenticate.js'
8
9
 
9
10
  describe('authenticate should', () => {
10
11
  test('return a valid principal', async () => {
11
12
  const assertions = E.gen(function* (_) {
12
13
  const service = yield* _(AuthenticationService)
13
- const result = yield* _(service.authenticatePasskey({ userVerification: 'preferred' }))
14
+
15
+ const result = yield* _(
16
+ service.authenticatePasskey({
17
+ email: O.none(),
18
+ userVerification: O.some('preferred'),
19
+ }),
20
+ )
14
21
 
15
22
  expect(result).toEqual(Fixture.principal)
16
23
  })
@@ -31,7 +38,13 @@ describe('authenticate should', () => {
31
38
  test('pass the authentication request to the backend', async () => {
32
39
  const assertions = E.gen(function* (_) {
33
40
  const service = yield* _(AuthenticationService)
34
- yield* _(service.authenticatePasskey({ userVerification: 'preferred' }))
41
+
42
+ yield* _(
43
+ service.authenticatePasskey({
44
+ email: O.none(),
45
+ userVerification: O.some('preferred'),
46
+ }),
47
+ )
35
48
 
36
49
  const rpcClient = yield* _(AuthenticationClient)
37
50
  expect(rpcClient.getAuthenticationOptions).toHaveBeenCalledOnce()
@@ -44,7 +57,9 @@ describe('authenticate should', () => {
44
57
  const rpcMock = mock<AuthenticationClient['Type']>()
45
58
 
46
59
  rpcMock.getAuthenticationOptions.mockReturnValue(E.succeed(Fixture.rpcOptionsRes))
47
- rpcMock.verifyAuthenticationCredential.mockReturnValue(E.succeed(Fixture.rpcVerificationRes))
60
+ rpcMock.verifyAuthenticationCredential.mockReturnValue(
61
+ E.succeed(Fixture.rpcVerificationRes),
62
+ )
48
63
 
49
64
  return rpcMock
50
65
  }),
@@ -67,11 +82,19 @@ describe('authenticate should', () => {
67
82
  test('send the credential to the backend', async () => {
68
83
  const assertions = E.gen(function* (_) {
69
84
  const service = yield* _(AuthenticationService)
70
- yield* _(service.authenticatePasskey({ userVerification: 'preferred' }))
85
+
86
+ yield* _(
87
+ service.authenticatePasskey({
88
+ email: O.none(),
89
+ userVerification: O.some('preferred'),
90
+ }),
91
+ )
71
92
 
72
93
  const rpcClient = yield* _(AuthenticationClient)
73
94
  expect(rpcClient.getAuthenticationOptions).toHaveBeenCalledOnce()
74
- expect(rpcClient.verifyAuthenticationCredential).toHaveBeenCalledWith(Fixture.rpcVerificationReq)
95
+ expect(rpcClient.verifyAuthenticationCredential).toHaveBeenCalledWith(
96
+ Fixture.rpcVerificationReq,
97
+ )
75
98
  })
76
99
 
77
100
  const rpcClientTest = L.effect(
@@ -80,7 +103,9 @@ describe('authenticate should', () => {
80
103
  const rpcMock = mock<AuthenticationClient['Type']>()
81
104
 
82
105
  rpcMock.getAuthenticationOptions.mockReturnValue(E.succeed(Fixture.rpcOptionsRes))
83
- rpcMock.verifyAuthenticationCredential.mockReturnValue(E.succeed(Fixture.rpcVerificationRes))
106
+ rpcMock.verifyAuthenticationCredential.mockReturnValue(
107
+ E.succeed(Fixture.rpcVerificationRes),
108
+ )
84
109
 
85
110
  return rpcMock
86
111
  }),
@@ -103,7 +128,13 @@ describe('authenticate should', () => {
103
128
  test('store the credential in local storage', async () => {
104
129
  const assertions = E.gen(function* (_) {
105
130
  const service = yield* _(AuthenticationService)
106
- yield* _(service.authenticatePasskey({ userVerification: 'preferred' }))
131
+
132
+ yield* _(
133
+ service.authenticatePasskey({
134
+ email: O.none(),
135
+ userVerification: O.some('preferred'),
136
+ }),
137
+ )
107
138
 
108
139
  const storageService = yield* _(StorageService)
109
140
  expect(storageService.storeToken).toHaveBeenCalledWith(Fixture.principal)
@@ -112,7 +143,7 @@ describe('authenticate should', () => {
112
143
  const storageServiceTest = L.effect(
113
144
  StorageService,
114
145
  E.sync(() => {
115
- const storageMock = mock<StorageService>()
146
+ const storageMock = mock<StorageService['Type']>()
116
147
 
117
148
  storageMock.storeToken.mockReturnValue(E.void)
118
149
  storageMock.clearExpiredToken.mockReturnValue(E.void)
@@ -138,7 +169,13 @@ describe('authenticate should', () => {
138
169
  test('schedule deletion of the local token', async () => {
139
170
  const assertions = E.gen(function* (_) {
140
171
  const service = yield* _(AuthenticationService)
141
- yield* _(service.authenticatePasskey({ userVerification: 'preferred' }))
172
+
173
+ yield* _(
174
+ service.authenticatePasskey({
175
+ email: O.none(),
176
+ userVerification: O.some('preferred'),
177
+ }),
178
+ )
142
179
 
143
180
  const storageService = yield* _(StorageService)
144
181
  expect(storageService.clearExpiredToken).toHaveBeenCalledWith('passkey')
@@ -147,7 +184,7 @@ describe('authenticate should', () => {
147
184
  const storageServiceTest = L.effect(
148
185
  StorageService,
149
186
  E.sync(() => {
150
- const storageMock = mock<StorageService>()
187
+ const storageMock = mock<StorageService['Type']>()
151
188
 
152
189
  storageMock.storeToken.mockReturnValue(E.void)
153
190
  storageMock.clearExpiredToken.mockReturnValue(E.void)
@@ -173,20 +210,26 @@ describe('authenticate should', () => {
173
210
  test("return an error if the browser can't create a credential", async () => {
174
211
  const assertions = E.gen(function* (_) {
175
212
  const service = yield* _(AuthenticationService)
176
- yield* _(service.authenticatePasskey({ userVerification: 'preferred' }))
177
213
 
178
- const getCredential = yield* _(GetCredential)
214
+ yield* _(
215
+ service.authenticatePasskey({
216
+ email: O.none(),
217
+ userVerification: O.some('preferred'),
218
+ }),
219
+ )
220
+
221
+ const { getCredential } = yield* _(GetCredential)
179
222
  expect(getCredential).toHaveBeenCalledOnce()
180
223
  })
181
224
 
182
225
  const getCredentialTest = L.effect(
183
226
  GetCredential,
184
227
  E.sync(() => {
185
- const getCredentialMock = vi.fn()
228
+ const getCredential = vi.fn()
186
229
 
187
- getCredentialMock.mockReturnValue(E.succeed(Fixture.credential))
230
+ getCredential.mockReturnValue(E.succeed(Fixture.credential))
188
231
 
189
- return getCredentialMock
232
+ return { getCredential }
190
233
  }),
191
234
  )
192
235
 
@@ -2,52 +2,53 @@
2
2
  * Passkey authentication effects
3
3
  */
4
4
  import {
5
- parseRequestOptionsFromJSON,
6
5
  type CredentialRequestOptionsJSON,
6
+ parseRequestOptionsFromJSON,
7
7
  } from '@github/webauthn-json/browser-ponyfill'
8
- import {
9
- InternalBrowserError,
10
- type NotSupported,
11
- } from '@passlock/shared/dist/error/error.js'
12
- import type { OptionsErrors, VerificationErrors } from '@passlock/shared/dist/rpc/authentication.js'
13
- import { AuthenticationClient, OptionsReq, VerificationReq } from '@passlock/shared/dist/rpc/authentication.js'
14
- import type {
15
- AuthenticationCredential,
16
- UserVerification,
17
- } from '@passlock/shared/dist/schema/passkey.js'
18
- import { Principal } from '@passlock/shared/dist/schema/principal.js'
19
8
  import { Context, Effect as E, Layer, flow, pipe } from 'effect'
9
+
10
+ import { InternalBrowserError, type NotSupported } from '@passlock/shared/dist/error/error.js'
11
+ import {
12
+ type OptionsErrors,
13
+ type OptionsReq,
14
+ type VerificationErrors,
15
+ VerificationReq,
16
+ } from '@passlock/shared/dist/rpc/authentication.js'
17
+ import type { AuthenticationCredential } from '@passlock/shared/dist/schema/passkey.js'
18
+ import type { Principal } from '@passlock/shared/dist/schema/principal.js'
19
+
20
20
  import { Capabilities } from '../capabilities/capabilities.js'
21
+ import { AuthenticationClient } from '../rpc/authentication.js'
21
22
  import { StorageService } from '../storage/storage.js'
22
23
 
23
24
  /* Requests */
24
25
 
25
- export type AuthenticationRequest = {
26
- email?: string,
27
- userVerification?: UserVerification
28
- }
29
-
26
+ export type AuthenticationRequest = OptionsReq
30
27
  /* Errors */
31
28
 
32
29
  export type AuthenticationErrors = NotSupported | OptionsErrors | VerificationErrors
33
30
 
34
31
  /* Dependencies */
35
32
 
36
- export type GetCredential = (
37
- request: CredentialRequestOptions,
38
- ) => E.Effect<AuthenticationCredential, InternalBrowserError>
39
-
40
- export const GetCredential = Context.GenericTag<GetCredential>('@services/Get')
33
+ export class GetCredential extends Context.Tag('@services/GetCredential')<
34
+ GetCredential,
35
+ {
36
+ getCredential: (
37
+ request: CredentialRequestOptions,
38
+ ) => E.Effect<AuthenticationCredential, InternalBrowserError>
39
+ }
40
+ >() {}
41
41
 
42
42
  /* Service */
43
43
 
44
- export type AuthenticationService = {
45
- authenticatePasskey: (request: AuthenticationRequest) => E.Effect<Principal, AuthenticationErrors>
46
- }
47
-
48
- export const AuthenticationService = Context.GenericTag<AuthenticationService>(
49
- '@services/AuthenticationService',
50
- )
44
+ export class AuthenticationService extends Context.Tag('@services/AuthenticationService')<
45
+ AuthenticationService,
46
+ {
47
+ authenticatePasskey: (
48
+ request: AuthenticationRequest,
49
+ ) => E.Effect<Principal, AuthenticationErrors>
50
+ }
51
+ >() {}
51
52
 
52
53
  /* Utilities */
53
54
 
@@ -102,11 +103,12 @@ export const authenticatePasskey = (
102
103
  yield* _(capabilities.passkeySupport)
103
104
 
104
105
  yield* _(E.logInfo('Fetching authentication options from Passlock'))
105
- const { options, session } = yield* _(fetchOptions(new OptionsReq(request)))
106
+
107
+ const { options, session } = yield* _(fetchOptions(request))
106
108
 
107
109
  yield* _(E.logInfo('Looking up credential'))
108
- const get = yield* _(GetCredential)
109
- const credential = yield* _(get(options))
110
+ const { getCredential } = yield* _(GetCredential)
111
+ const credential = yield* _(getCredential(options))
110
112
 
111
113
  yield* _(E.logInfo('Verifying credential with Passlock'))
112
114
  const principal = yield* _(verifyCredential(new VerificationReq({ credential, session })))
@@ -135,7 +137,9 @@ export const authenticatePasskey = (
135
137
  export const AuthenticateServiceLive = Layer.effect(
136
138
  AuthenticationService,
137
139
  E.gen(function* (_) {
138
- const context = yield* _(E.context<GetCredential | AuthenticationClient | Capabilities | StorageService>())
140
+ const context = yield* _(
141
+ E.context<GetCredential | AuthenticationClient | Capabilities | StorageService>(),
142
+ )
139
143
 
140
144
  return AuthenticationService.of({
141
145
  authenticatePasskey: flow(authenticatePasskey, E.provide(context)),
@@ -1,19 +1,21 @@
1
1
  /**
2
2
  * Test if the browser supports passkeys, conditional UI etc
3
3
  */
4
- import { NotSupported } from '@passlock/shared/dist/error/error.js'
5
4
  import { Context, Effect as E, Layer, identity, pipe } from 'effect'
6
5
 
7
- /* Service */
6
+ import { NotSupported } from '@passlock/shared/dist/error/error.js'
8
7
 
9
- export type Capabilities = {
10
- passkeySupport: E.Effect<void, NotSupported>
11
- isPasskeySupport: E.Effect<boolean>
12
- autofillSupport: E.Effect<void, NotSupported>
13
- isAutofillSupport: E.Effect<boolean>
14
- }
8
+ /* Service */
15
9
 
16
- export const Capabilities = Context.GenericTag<Capabilities>('@services/Capabilities')
10
+ export class Capabilities extends Context.Tag('@services/Capabilities')<
11
+ Capabilities,
12
+ {
13
+ passkeySupport: E.Effect<void, NotSupported>
14
+ isPasskeySupport: E.Effect<boolean>
15
+ autofillSupport: E.Effect<void, NotSupported>
16
+ isAutofillSupport: E.Effect<boolean>
17
+ }
18
+ >() {}
17
19
 
18
20
  /* Effects */
19
21
 
@@ -1,6 +1,9 @@
1
- import { ConnectionClient, ConnectRes } from '@passlock/shared/dist/rpc/connection.js'
2
1
  import { Effect as E, Layer as L } from 'effect'
3
2
 
3
+ import { ConnectRes } from '@passlock/shared/dist/rpc/connection.js'
4
+
5
+ import { ConnectionClient } from '../rpc/connection.js'
6
+
4
7
  export const preConnectRes = new ConnectRes({ warmed: true })
5
8
 
6
9
  export const rpcClientTest = L.succeed(
@@ -1,10 +1,11 @@
1
- import { RpcConfig } from '@passlock/shared/dist/rpc/config.js'
2
- import { ConnectionClient } from '@passlock/shared/dist/rpc/connection.js'
3
- import { Dispatcher } from '@passlock/shared/dist/rpc/dispatcher.js'
4
1
  import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect'
5
2
  import { describe, expect, test } from 'vitest'
6
3
  import { mock } from 'vitest-mock-extended'
4
+
7
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'
8
9
  import { ConnectionService, ConnectionServiceLive } from './connection.js'
9
10
 
10
11
  describe('preConnect should', () => {
@@ -1,18 +1,20 @@
1
1
  /**
2
2
  * Hits the rpc endpoint to warm up a lambda
3
3
  */
4
- import type { RpcConfig } from '@passlock/shared/dist/rpc/config.js'
5
- import { ConnectionClient } from '@passlock/shared/dist/rpc/connection.js'
6
- import { Dispatcher } from '@passlock/shared/dist/rpc/dispatcher.js'
7
4
  import { Context, Effect as E, Layer, flow, pipe } from 'effect'
8
5
 
9
- /* Service */
6
+ import { Dispatcher } from '../rpc/client.js'
7
+ import type { RpcConfig } from '../rpc/config.js'
8
+ import { ConnectionClient } from '../rpc/connection.js'
10
9
 
11
- export type ConnectionService = {
12
- preConnect: () => E.Effect<void>
13
- }
10
+ /* Service */
14
11
 
15
- export const ConnectionService = Context.GenericTag<ConnectionService>('@services/ConnectService')
12
+ export class ConnectionService extends Context.Tag('@services/ConnectionService')<
13
+ ConnectionService,
14
+ {
15
+ preConnect: () => E.Effect<void>
16
+ }
17
+ >() {}
16
18
 
17
19
  /* Effects */
18
20