@passlock/client 0.9.0

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 (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/authentication/authenticate.d.ts +22 -0
  4. package/dist/authentication/authenticate.d.ts.map +1 -0
  5. package/dist/authentication/authenticate.fixture.d.ts +36 -0
  6. package/dist/authentication/authenticate.fixture.d.ts.map +1 -0
  7. package/dist/authentication/authenticate.fixture.js +52 -0
  8. package/dist/authentication/authenticate.fixture.js.map +1 -0
  9. package/dist/authentication/authenticate.js +69 -0
  10. package/dist/authentication/authenticate.js.map +1 -0
  11. package/dist/authentication/authenticate.test.d.ts +2 -0
  12. package/dist/authentication/authenticate.test.d.ts.map +1 -0
  13. package/dist/authentication/authenticate.test.js +111 -0
  14. package/dist/authentication/authenticate.test.js.map +1 -0
  15. package/dist/capabilities/capabilities.d.ts +18 -0
  16. package/dist/capabilities/capabilities.d.ts.map +1 -0
  17. package/dist/capabilities/capabilities.js +35 -0
  18. package/dist/capabilities/capabilities.js.map +1 -0
  19. package/dist/config.d.ts +22 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +20 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/connection/connection.d.ts +9 -0
  24. package/dist/connection/connection.d.ts.map +1 -0
  25. package/dist/connection/connection.fixture.d.ts +12 -0
  26. package/dist/connection/connection.fixture.d.ts.map +1 -0
  27. package/dist/connection/connection.fixture.js +20 -0
  28. package/dist/connection/connection.fixture.js.map +1 -0
  29. package/dist/connection/connection.js +21 -0
  30. package/dist/connection/connection.js.map +1 -0
  31. package/dist/connection/connection.test.d.ts +2 -0
  32. package/dist/connection/connection.test.d.ts.map +1 -0
  33. package/dist/connection/connection.test.js +34 -0
  34. package/dist/connection/connection.test.js.map +1 -0
  35. package/dist/effect.d.ts +33 -0
  36. package/dist/effect.d.ts.map +1 -0
  37. package/dist/effect.js +62 -0
  38. package/dist/effect.js.map +1 -0
  39. package/dist/email/email.d.ts +37 -0
  40. package/dist/email/email.d.ts.map +1 -0
  41. package/dist/email/email.fixture.d.ts +33 -0
  42. package/dist/email/email.fixture.d.ts.map +1 -0
  43. package/dist/email/email.fixture.js +30 -0
  44. package/dist/email/email.fixture.js.map +1 -0
  45. package/dist/email/email.js +78 -0
  46. package/dist/email/email.js.map +1 -0
  47. package/dist/email/email.test.d.ts +2 -0
  48. package/dist/email/email.test.d.ts.map +1 -0
  49. package/dist/email/email.test.js +101 -0
  50. package/dist/email/email.test.js.map +1 -0
  51. package/dist/event/event.d.ts +9 -0
  52. package/dist/event/event.d.ts.map +1 -0
  53. package/dist/event/event.js +23 -0
  54. package/dist/event/event.js.map +1 -0
  55. package/dist/event/event.node.test.d.ts +2 -0
  56. package/dist/event/event.node.test.d.ts.map +1 -0
  57. package/dist/event/event.node.test.js +14 -0
  58. package/dist/event/event.node.test.js.map +1 -0
  59. package/dist/event/event.test.d.ts +2 -0
  60. package/dist/event/event.test.d.ts.map +1 -0
  61. package/dist/event/event.test.js +30 -0
  62. package/dist/event/event.test.js.map +1 -0
  63. package/dist/exit.d.ts +64 -0
  64. package/dist/exit.d.ts.map +1 -0
  65. package/dist/exit.js +106 -0
  66. package/dist/exit.js.map +1 -0
  67. package/dist/index.d.ts +110 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +108 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/logging/eventLogger.d.ts +18 -0
  72. package/dist/logging/eventLogger.d.ts.map +1 -0
  73. package/dist/logging/eventLogger.js +32 -0
  74. package/dist/logging/eventLogger.js.map +1 -0
  75. package/dist/logging/eventLogger.test.d.ts +2 -0
  76. package/dist/logging/eventLogger.test.d.ts.map +1 -0
  77. package/dist/logging/eventLogger.test.js +74 -0
  78. package/dist/logging/eventLogger.test.js.map +1 -0
  79. package/dist/registration/register.d.ts +29 -0
  80. package/dist/registration/register.d.ts.map +1 -0
  81. package/dist/registration/register.fixture.d.ts +40 -0
  82. package/dist/registration/register.fixture.d.ts.map +1 -0
  83. package/dist/registration/register.fixture.js +65 -0
  84. package/dist/registration/register.fixture.js.map +1 -0
  85. package/dist/registration/register.js +84 -0
  86. package/dist/registration/register.js.map +1 -0
  87. package/dist/registration/register.test.d.ts +2 -0
  88. package/dist/registration/register.test.d.ts.map +1 -0
  89. package/dist/registration/register.test.js +122 -0
  90. package/dist/registration/register.test.js.map +1 -0
  91. package/dist/storage/storage.d.ts +53 -0
  92. package/dist/storage/storage.d.ts.map +1 -0
  93. package/dist/storage/storage.fixture.d.ts +6 -0
  94. package/dist/storage/storage.fixture.d.ts.map +1 -0
  95. package/dist/storage/storage.fixture.js +26 -0
  96. package/dist/storage/storage.fixture.js.map +1 -0
  97. package/dist/storage/storage.js +102 -0
  98. package/dist/storage/storage.js.map +1 -0
  99. package/dist/storage/storage.test.d.ts +2 -0
  100. package/dist/storage/storage.test.d.ts.map +1 -0
  101. package/dist/storage/storage.test.js +122 -0
  102. package/dist/storage/storage.test.js.map +1 -0
  103. package/dist/test/fixtures.d.ts +14 -0
  104. package/dist/test/fixtures.d.ts.map +1 -0
  105. package/dist/test/fixtures.js +39 -0
  106. package/dist/test/fixtures.js.map +1 -0
  107. package/dist/user/user.d.ts +18 -0
  108. package/dist/user/user.d.ts.map +1 -0
  109. package/dist/user/user.fixture.d.ts +8 -0
  110. package/dist/user/user.fixture.d.ts.map +1 -0
  111. package/dist/user/user.fixture.js +17 -0
  112. package/dist/user/user.fixture.js.map +1 -0
  113. package/dist/user/user.js +23 -0
  114. package/dist/user/user.js.map +1 -0
  115. package/dist/user/user.test.d.ts +2 -0
  116. package/dist/user/user.test.d.ts.map +1 -0
  117. package/dist/user/user.test.js +37 -0
  118. package/dist/user/user.test.js.map +1 -0
  119. package/package.json +87 -0
  120. package/src/authentication/authenticate.fixture.ts +72 -0
  121. package/src/authentication/authenticate.test.ts +207 -0
  122. package/src/authentication/authenticate.ts +147 -0
  123. package/src/capabilities/capabilities.ts +81 -0
  124. package/src/config.ts +43 -0
  125. package/src/connection/connection.fixture.ts +27 -0
  126. package/src/connection/connection.test.ts +61 -0
  127. package/src/connection/connection.ts +51 -0
  128. package/src/effect.ts +278 -0
  129. package/src/email/email.fixture.ts +49 -0
  130. package/src/email/email.test.ts +186 -0
  131. package/src/email/email.ts +139 -0
  132. package/src/event/event.node.test.ts +20 -0
  133. package/src/event/event.test.ts +37 -0
  134. package/src/event/event.ts +25 -0
  135. package/src/index.ts +275 -0
  136. package/src/logging/eventLogger.test.ts +102 -0
  137. package/src/logging/eventLogger.ts +35 -0
  138. package/src/registration/register.fixture.ts +94 -0
  139. package/src/registration/register.test.ts +247 -0
  140. package/src/registration/register.ts +178 -0
  141. package/src/storage/storage.fixture.ts +33 -0
  142. package/src/storage/storage.test.ts +196 -0
  143. package/src/storage/storage.ts +165 -0
  144. package/src/test/fixtures.ts +51 -0
  145. package/src/user/user.fixture.ts +23 -0
  146. package/src/user/user.test.ts +53 -0
  147. package/src/user/user.ts +50 -0
@@ -0,0 +1,40 @@
1
+ import { OptionsReq, OptionsRes, VerificationReq, VerificationRes } from '@passlock/shared/dist/rpc/registration';
2
+ import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
3
+ import type { RegistrationCredential } from '@passlock/shared/dist/schema/schema';
4
+ import { Layer as L } from 'effect';
5
+ import { CreateCredential, type RegistrationRequest } from './register';
6
+ import { UserService } from '../user/user';
7
+ export declare const session = "session";
8
+ export declare const token = "token";
9
+ export declare const code = "code";
10
+ export declare const authType = "passkey";
11
+ export declare const expireAt: number;
12
+ export declare const registrationRequest: RegistrationRequest;
13
+ export declare const optionsReq: OptionsReq;
14
+ export declare const registrationOptions: OptionsRes;
15
+ export declare const optionsRes: OptionsRes;
16
+ export declare const credential: RegistrationCredential;
17
+ export declare const verificationReq: VerificationReq;
18
+ export declare const verificationRes: VerificationRes;
19
+ export declare const createCredentialTest: L.Layer<CreateCredential, never, never>;
20
+ export declare const userServiceTest: L.Layer<UserService, never, never>;
21
+ export declare const rpcClientTest: L.Layer<RpcClient, never, never>;
22
+ export declare const principal: {
23
+ readonly token: string;
24
+ readonly subject: {
25
+ readonly id: string;
26
+ readonly email: string;
27
+ readonly firstName: string;
28
+ readonly lastName: string;
29
+ readonly emailVerified: boolean;
30
+ };
31
+ readonly authStatement: {
32
+ readonly authType: "email" | "passkey";
33
+ readonly userVerified: boolean;
34
+ readonly authTimestamp: Date;
35
+ };
36
+ readonly expireAt: Date;
37
+ };
38
+ export declare const capabilitiesTest: L.Layer<import("../capabilities/capabilities").Capabilities, never, never>;
39
+ export declare const storageServiceTest: L.Layer<import("../storage/storage").StorageService, never, never>;
40
+ //# sourceMappingURL=register.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.fixture.d.ts","sourceRoot":"","sources":["../../src/registration/register.fixture.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,eAAe,EAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AACjF,OAAO,EAAe,KAAK,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAEvE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1C,eAAO,MAAM,OAAO,YAAY,CAAA;AAChC,eAAO,MAAM,KAAK,UAAU,CAAA;AAC5B,eAAO,MAAM,IAAI,SAAS,CAAA;AAC1B,eAAO,MAAM,QAAQ,YAAY,CAAA;AACjC,eAAO,MAAM,QAAQ,QAAqB,CAAA;AAE1C,eAAO,MAAM,mBAAmB,EAAE,mBAIjC,CAAA;AAED,eAAO,MAAM,UAAU,YAAsC,CAAA;AAE7D,eAAO,MAAM,mBAAmB,EAAE,UAejC,CAAA;AAED,eAAO,MAAM,UAAU,YAAsC,CAAA;AAE7D,eAAO,MAAM,UAAU,EAAE,sBAUxB,CAAA;AAED,eAAO,MAAM,eAAe,iBAA+C,CAAA;AAE3E,eAAO,MAAM,eAAe,iBAAyD,CAAA;AAErF,eAAO,MAAM,oBAAoB,yCAGhC,CAAA;AAED,eAAO,MAAM,eAAe,oCAK3B,CAAA;AAED,eAAO,MAAM,aAAa,kCAWzB,CAAA;AAED,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;CAAqB,CAAA;AAE3C,eAAO,MAAM,gBAAgB,4EAA4B,CAAA;AAEzD,eAAO,MAAM,kBAAkB,oEAA8B,CAAA"}
@@ -0,0 +1,65 @@
1
+ import { BadRequest } from '@passlock/shared/dist/error/error';
2
+ import { OptionsReq, OptionsRes, VerificationReq, VerificationRes, } from '@passlock/shared/dist/rpc/registration';
3
+ import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
4
+ import { Effect as E, Layer as L } from 'effect';
5
+ import { CreateCredential } from './register';
6
+ import * as Fixtures from '../test/fixtures';
7
+ import { UserService } from '../user/user';
8
+ export const session = 'session';
9
+ export const token = 'token';
10
+ export const code = 'code';
11
+ export const authType = 'passkey';
12
+ export const expireAt = Date.now() + 10000;
13
+ export const registrationRequest = {
14
+ email: 'jdoe@gmail.com',
15
+ firstName: 'john',
16
+ lastName: 'doe',
17
+ };
18
+ export const optionsReq = new OptionsReq(registrationRequest);
19
+ export const registrationOptions = {
20
+ session,
21
+ publicKey: {
22
+ rp: {
23
+ name: 'passlock',
24
+ id: 'passlock.dev',
25
+ },
26
+ user: {
27
+ name: 'john doe',
28
+ id: 'jdoe',
29
+ displayName: 'john doe',
30
+ },
31
+ challenge: 'FKZSl_saKu5OXjLLwoq8eK3wlD8XgpGiS10SszW5RiE',
32
+ pubKeyCredParams: [],
33
+ },
34
+ };
35
+ export const optionsRes = new OptionsRes(registrationOptions);
36
+ export const credential = {
37
+ type: 'public-key',
38
+ id: '1',
39
+ rawId: '1',
40
+ response: {
41
+ transports: [],
42
+ clientDataJSON: '',
43
+ attestationObject: '',
44
+ },
45
+ clientExtensionResults: {},
46
+ };
47
+ export const verificationReq = new VerificationReq({ session, credential });
48
+ export const verificationRes = new VerificationRes({ principal: Fixtures.principal });
49
+ export const createCredentialTest = L.succeed(CreateCredential, CreateCredential.of(() => E.succeed(credential)));
50
+ export const userServiceTest = L.succeed(UserService, UserService.of({
51
+ isExistingUser: () => E.succeed(false),
52
+ }));
53
+ export const rpcClientTest = L.succeed(RpcClient, RpcClient.of({
54
+ preConnect: () => E.succeed({ warmed: true }),
55
+ isExistingUser: () => E.succeed({ existingUser: true }),
56
+ verifyEmail: () => E.succeed({ verified: true }),
57
+ getRegistrationOptions: () => E.succeed(optionsRes),
58
+ verifyRegistrationCredential: () => E.succeed(verificationRes),
59
+ getAuthenticationOptions: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
60
+ verifyAuthenticationCredential: () => E.succeed({ principal: Fixtures.principal }),
61
+ }));
62
+ export const principal = Fixtures.principal;
63
+ export const capabilitiesTest = Fixtures.capabilitiesTest;
64
+ export const storageServiceTest = Fixtures.storageServiceTest;
65
+ //# sourceMappingURL=register.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.fixture.js","sourceRoot":"","sources":["../../src/registration/register.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAC9D,OAAO,EACL,UAAU,EACV,UAAU,EACV,eAAe,EACf,eAAe,GAChB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAA4B,MAAM,YAAY,CAAA;AACvE,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1C,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAChC,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAA;AAC5B,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAA;AAC1B,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,CAAA;AACjC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAA;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAwB;IACtD,KAAK,EAAE,gBAAgB;IACvB,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,KAAK;CAChB,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAA;AAE7D,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,OAAO;IACP,SAAS,EAAE;QACT,EAAE,EAAE;YACF,IAAI,EAAE,UAAU;YAChB,EAAE,EAAE,cAAc;SACnB;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,UAAU;YAChB,EAAE,EAAE,MAAM;YACV,WAAW,EAAE,UAAU;SACxB;QACD,SAAS,EAAE,6CAA6C;QACxD,gBAAgB,EAAE,EAAE;KACrB;CACF,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,CAAA;AAE7D,MAAM,CAAC,MAAM,UAAU,GAA2B;IAChD,IAAI,EAAE,YAAY;IAClB,EAAE,EAAE,GAAG;IACP,KAAK,EAAE,GAAG;IACV,QAAQ,EAAE;QACR,UAAU,EAAE,EAAE;QACd,cAAc,EAAE,EAAE;QAClB,iBAAiB,EAAE,EAAE;KACtB;IACD,sBAAsB,EAAE,EAAE;CAC3B,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAA;AAE3E,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;AAErF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,OAAO,CAC3C,gBAAgB,EAChB,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CACjD,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,OAAO,CACtC,WAAW,EACX,WAAW,CAAC,EAAE,CAAC;IACb,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;CACvC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,OAAO,CACpC,SAAS,EACT,SAAS,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC7C,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACvD,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAChD,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACnD,4BAA4B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;IAC9D,wBAAwB,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACvF,8BAA8B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC;CACnF,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAA;AAE3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAA;AAEzD,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,CAAA"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * User & passkey registration effects
3
+ */
4
+ import { parseCreationOptionsFromJSON, } from '@github/webauthn-json/browser-ponyfill';
5
+ import { Duplicate, InternalBrowserError } from '@passlock/shared/dist/error/error';
6
+ import { OptionsReq, VerificationReq, } from '@passlock/shared/dist/rpc/registration';
7
+ import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
8
+ import { Context, Effect as E, Layer, flow, pipe } from 'effect';
9
+ import { Capabilities } from '../capabilities/capabilities';
10
+ import { StorageService } from '../storage/storage';
11
+ import { UserService } from '../user/user';
12
+ export const CreateCredential = Context.GenericTag('@services/Create');
13
+ export const RegistrationService = Context.GenericTag('@services/RegistrationService');
14
+ /* Utilities */
15
+ const fetchOptions = (req) => {
16
+ return E.gen(function* (_) {
17
+ yield* _(E.logDebug('Making request'));
18
+ const rpcClient = yield* _(RpcClient);
19
+ const { publicKey, session } = yield* _(rpcClient.getRegistrationOptions(req));
20
+ yield* _(E.logDebug('Converting Passlock options to CredentialCreationOptions'));
21
+ const options = yield* _(toCreationOptions({ publicKey }));
22
+ return { options, session };
23
+ });
24
+ };
25
+ const toCreationOptions = (jsonOptions) => {
26
+ return pipe(E.try(() => parseCreationOptionsFromJSON(jsonOptions)), E.mapError(error => new InternalBrowserError({
27
+ message: 'Browser was unable to create credential creation options',
28
+ detail: String(error.error),
29
+ })));
30
+ };
31
+ const verifyCredential = (req) => {
32
+ return E.gen(function* (_) {
33
+ yield* _(E.logDebug('Making request'));
34
+ const rpcClient = yield* _(RpcClient);
35
+ const { principal } = yield* _(rpcClient.verifyRegistrationCredential(req));
36
+ return principal;
37
+ });
38
+ };
39
+ const isNewUser = (email) => {
40
+ return pipe(UserService, E.flatMap(service => service.isExistingUser({ email })), E.catchTag('BadRequest', () => E.unit), E.flatMap(isExistingUser => {
41
+ return isExistingUser
42
+ ? new Duplicate({ message: 'User already has a passkey registered' })
43
+ : E.unit;
44
+ }));
45
+ };
46
+ export const registerPasskey = (request) => {
47
+ const effect = E.gen(function* (_) {
48
+ yield* _(E.logInfo('Checking if browser supports Passkeys'));
49
+ const capabilities = yield* _(Capabilities);
50
+ yield* _(capabilities.passkeySupport);
51
+ yield* _(E.logInfo('Checking if already registered'));
52
+ yield* _(isNewUser(request.email));
53
+ yield* _(E.logInfo('Fetching registration options from Passlock'));
54
+ const { options, session } = yield* _(fetchOptions(new OptionsReq(request)));
55
+ yield* _(E.logInfo('Building new credential'));
56
+ const createCredential = yield* _(CreateCredential);
57
+ const credential = yield* _(createCredential(options));
58
+ yield* _(E.logInfo('Storing credential public key in Passlock'));
59
+ const verificationRequest = new VerificationReq({
60
+ ...request,
61
+ credential,
62
+ session,
63
+ });
64
+ const principal = yield* _(verifyCredential(verificationRequest));
65
+ const storageService = yield* _(StorageService);
66
+ yield* _(storageService.storeToken(principal));
67
+ yield* _(E.logDebug('Storing token in local storage'));
68
+ yield* _(E.logDebug('Defering local token deletion'));
69
+ const delayedClearTokenE = pipe(storageService.clearExpiredToken('passkey'), E.delay('6 minutes'), E.fork);
70
+ yield* _(delayedClearTokenE);
71
+ return principal;
72
+ });
73
+ return E.catchTag(effect, 'InternalBrowserError', e => E.die(e));
74
+ };
75
+ /* Live */
76
+ /* v8 ignore start */
77
+ export const RegistrationServiceLive = Layer.effect(RegistrationService, E.gen(function* (_) {
78
+ const context = yield* _(E.context());
79
+ return RegistrationService.of({
80
+ registerPasskey: flow(registerPasskey, E.provide(context)),
81
+ });
82
+ }));
83
+ /* v8 ignore stop */
84
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/registration/register.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=register.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.test.d.ts","sourceRoot":"","sources":["../../src/registration/register.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,122 @@
1
+ import { Duplicate, InternalBrowserError } from '@passlock/shared/dist/error/error';
2
+ import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
3
+ import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect';
4
+ import { describe, expect, test, vi } from 'vitest';
5
+ import { mock } from 'vitest-mock-extended';
6
+ import { CreateCredential, RegistrationService, RegistrationServiceLive } from './register';
7
+ import * as Fixture from './register.fixture';
8
+ import { UserService } from '../user/user';
9
+ describe('register should', () => {
10
+ test('return a valid credential', async () => {
11
+ const assertions = E.gen(function* (_) {
12
+ const service = yield* _(RegistrationService);
13
+ const result = yield* _(service.registerPasskey(Fixture.registrationRequest));
14
+ expect(result).toEqual(Fixture.principal);
15
+ });
16
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.createCredentialTest), L.provide(Fixture.userServiceTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.rpcClientTest));
17
+ const effect = pipe(E.provide(assertions, service), Logger.withMinimumLogLevel(LogLevel.None));
18
+ return E.runPromise(effect);
19
+ });
20
+ test('check if the user is already registered', async () => {
21
+ const assertions = E.gen(function* (_) {
22
+ const service = yield* _(RegistrationService);
23
+ yield* _(service.registerPasskey(Fixture.registrationRequest));
24
+ const userService = yield* _(UserService);
25
+ expect(userService.isExistingUser).toHaveBeenCalled();
26
+ });
27
+ const userServiceTest = L.effect(UserService, E.sync(() => {
28
+ const userMock = mock();
29
+ userMock.isExistingUser.mockReturnValue(E.succeed(false));
30
+ return userMock;
31
+ }));
32
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.createCredentialTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.rpcClientTest), L.provide(userServiceTest));
33
+ const layers = Layer.merge(service, userServiceTest);
34
+ const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
35
+ return E.runPromise(effect);
36
+ });
37
+ test('pass the registration data to the backend', async () => {
38
+ const assertions = E.gen(function* (_) {
39
+ const service = yield* _(RegistrationService);
40
+ yield* _(service.registerPasskey(Fixture.registrationRequest));
41
+ const rpcClient = yield* _(RpcClient);
42
+ expect(rpcClient.getRegistrationOptions).toHaveBeenCalledWith(Fixture.optionsReq);
43
+ });
44
+ const rpcClientTest = L.effect(RpcClient, E.sync(() => {
45
+ const rpcMock = mock();
46
+ rpcMock.getRegistrationOptions.mockReturnValue(E.succeed(Fixture.optionsRes));
47
+ rpcMock.verifyRegistrationCredential.mockReturnValue(E.succeed(Fixture.verificationRes));
48
+ return rpcMock;
49
+ }));
50
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.createCredentialTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.userServiceTest), L.provide(rpcClientTest));
51
+ const layers = Layer.merge(service, rpcClientTest);
52
+ const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
53
+ return E.runPromise(effect);
54
+ });
55
+ test('send the new credential to the backend', async () => {
56
+ const assertions = E.gen(function* (_) {
57
+ const service = yield* _(RegistrationService);
58
+ yield* _(service.registerPasskey(Fixture.registrationRequest));
59
+ const rpcClient = yield* _(RpcClient);
60
+ expect(rpcClient.verifyRegistrationCredential).toHaveBeenCalledWith(Fixture.verificationReq);
61
+ });
62
+ const rpcClientTest = L.effect(RpcClient, E.sync(() => {
63
+ const rpcMock = mock();
64
+ rpcMock.getRegistrationOptions.mockReturnValue(E.succeed(Fixture.optionsRes));
65
+ rpcMock.verifyRegistrationCredential.mockReturnValue(E.succeed(Fixture.verificationRes));
66
+ return rpcMock;
67
+ }));
68
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.createCredentialTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.userServiceTest), L.provide(rpcClientTest));
69
+ const layers = Layer.merge(service, rpcClientTest);
70
+ const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
71
+ return E.runPromise(effect);
72
+ });
73
+ test('short-circuit if the user is already registered', async () => {
74
+ const assertions = E.gen(function* (_) {
75
+ const service = yield* _(RegistrationService);
76
+ const error = yield* _(service.registerPasskey(Fixture.registrationRequest), E.flip);
77
+ expect(error).toBeInstanceOf(Duplicate);
78
+ });
79
+ const userServiceTest = L.effect(UserService, E.sync(() => {
80
+ const userMock = mock();
81
+ userMock.isExistingUser.mockReturnValue(E.succeed(true));
82
+ return userMock;
83
+ }));
84
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.createCredentialTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.rpcClientTest), L.provide(userServiceTest));
85
+ const layers = Layer.merge(service, userServiceTest);
86
+ const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
87
+ return E.runPromise(effect);
88
+ });
89
+ test('return an error if we try to re-register a credential', async () => {
90
+ const assertions = E.gen(function* (_) {
91
+ const service = yield* _(RegistrationService);
92
+ const defect = yield* _(service.registerPasskey(Fixture.registrationRequest), E.flip);
93
+ expect(defect).toBeInstanceOf(Duplicate);
94
+ });
95
+ const createTest = L.effect(CreateCredential, E.sync(() => {
96
+ const createTest = vi.fn();
97
+ createTest.mockReturnValue(E.fail(new Duplicate({ message: 'boom!' })));
98
+ return createTest;
99
+ }));
100
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.userServiceTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.rpcClientTest), L.provide(createTest));
101
+ const layers = Layer.merge(service, createTest);
102
+ const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
103
+ return E.runPromise(effect);
104
+ });
105
+ test("throw an error if the browser can't create a credential", async () => {
106
+ const assertions = E.gen(function* (_) {
107
+ const service = yield* _(RegistrationService);
108
+ const defect = yield* _(service.registerPasskey(Fixture.registrationRequest), E.catchAllDefect(defect => E.succeed(defect)));
109
+ expect(defect).toBeInstanceOf(InternalBrowserError);
110
+ });
111
+ const createTest = L.effect(CreateCredential, E.sync(() => {
112
+ const createTest = vi.fn();
113
+ createTest.mockReturnValue(E.fail(new InternalBrowserError({ message: 'boom!' })));
114
+ return createTest;
115
+ }));
116
+ const service = pipe(RegistrationServiceLive, L.provide(Fixture.userServiceTest), L.provide(Fixture.capabilitiesTest), L.provide(Fixture.storageServiceTest), L.provide(Fixture.rpcClientTest), L.provide(createTest));
117
+ const layers = Layer.merge(service, createTest);
118
+ const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
119
+ return E.runPromise(effect);
120
+ });
121
+ });
122
+ //# sourceMappingURL=register.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.test.js","sourceRoot":"","sources":["../../src/registration/register.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Wrapper around local storage that allows us to store
3
+ * authentication tokens in local storage for a short period.
4
+ */
5
+ import type { Principal } from '@passlock/shared/dist/schema/schema';
6
+ import { Context, Effect as E, Layer, Option as O } from 'effect';
7
+ import type { NoSuchElementException } from 'effect/Cause';
8
+ export type AuthType = 'email' | 'passkey';
9
+ export type StoredToken = {
10
+ token: string;
11
+ authType: AuthType;
12
+ expireAt: number;
13
+ };
14
+ export type StorageService = {
15
+ storeToken: (principal: Principal) => E.Effect<void>;
16
+ getToken: (authType: AuthType) => E.Effect<StoredToken, NoSuchElementException>;
17
+ clearToken: (authType: AuthType) => E.Effect<void>;
18
+ clearExpiredToken: (authType: AuthType) => E.Effect<void>;
19
+ clearExpiredTokens: E.Effect<void>;
20
+ };
21
+ export declare const StorageService: Context.Tag<StorageService, StorageService>;
22
+ export declare const Storage: Context.Tag<Storage, Storage>;
23
+ export declare const buildKey: (authType: AuthType) => string;
24
+ export declare const compressToken: (principal: Principal) => string;
25
+ export declare const expandToken: (authType: AuthType) => (s: string) => O.Option<StoredToken>;
26
+ /**
27
+ * Store compressed token in local storage
28
+ * @param principal
29
+ * @returns
30
+ */
31
+ export declare const storeToken: (principal: Principal) => E.Effect<void, never, Storage>;
32
+ /**
33
+ * Get stored token from local storage
34
+ * @param authType
35
+ * @returns
36
+ */
37
+ export declare const getToken: (authType: AuthType) => E.Effect<StoredToken, NoSuchElementException, Storage>;
38
+ /**
39
+ * Remove token from local storage
40
+ * @param authType
41
+ * @returns
42
+ */
43
+ export declare const clearToken: (authType: AuthType) => E.Effect<void, never, Storage>;
44
+ /**
45
+ * Only clear if now > token.expireAt
46
+ * @param authType
47
+ * @param defer
48
+ * @returns
49
+ */
50
+ export declare const clearExpiredToken: (authType: AuthType) => E.Effect<void, never, Storage>;
51
+ export declare const clearExpiredTokens: E.Effect<void, never, Storage>;
52
+ export declare const StorageServiceLive: Layer.Layer<StorageService, never, Storage>;
53
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/storage/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC,EAAc,MAAM,QAAQ,CAAA;AAC7E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAI1D,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;AAE1C,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAID,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACpD,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAA;IAC/E,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAClD,iBAAiB,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACzD,kBAAkB,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CACnC,CAAA;AAID,eAAO,MAAM,cAAc,6CAAiE,CAAA;AAG5F,eAAO,MAAM,OAAO,+BAAmD,CAAA;AAEvE,eAAO,MAAM,QAAQ,aAAc,QAAQ,WAAiC,CAAA;AAG5E,eAAO,MAAM,aAAa,cAAe,SAAS,KAAG,MAIpD,CAAA;AAGD,eAAO,MAAM,WAAW,aACX,QAAQ,SACf,MAAM,KAAG,QAAQ,CAAC,WAAW,CAShC,CAAA;AAIH;;;;GAIG;AACH,eAAO,MAAM,UAAU,cAAe,SAAS,KAAG,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAY9E,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,QAAQ,aACT,QAAQ,KACjB,EAAE,MAAM,CAAC,WAAW,EAAE,sBAAsB,EAAE,OAAO,CAavD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,aAAc,QAAQ,KAAG,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAK5E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,aAAc,QAAQ,KAAG,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAqBnF,CAAA;AAED,eAAO,MAAM,kBAAkB,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAG5D,CAAA;AAKF,eAAO,MAAM,kBAAkB,6CAa9B,CAAA"}
@@ -0,0 +1,6 @@
1
+ import type { Principal } from '@passlock/shared/dist/schema/schema';
2
+ import { Layer } from 'effect';
3
+ import { Storage } from './storage';
4
+ export declare const principal: Principal;
5
+ export declare const testLayers: (storage?: Layer.Layer<Storage>) => Layer.Layer<Storage | import("./storage").StorageService, never, never>;
6
+ //# sourceMappingURL=storage.fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.fixture.d.ts","sourceRoot":"","sources":["../../src/storage/storage.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,EAAe,KAAK,EAAQ,MAAM,QAAQ,CAAA;AAEjD,OAAO,EAAE,OAAO,EAAsB,MAAM,WAAW,CAAA;AAGvD,eAAO,MAAM,SAAS,EAAE,SAevB,CAAA;AAOD,eAAO,MAAM,UAAU,aAAa,WAAW,CAAC,OAAO,CAAC,4EAIvD,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { Effect as E, Layer, pipe } from 'effect';
2
+ import { mock } from 'vitest-mock-extended';
3
+ import { Storage, StorageServiceLive } from './storage';
4
+ // Frontend receives dates as objects
5
+ export const principal = {
6
+ token: 'token',
7
+ subject: {
8
+ id: '1',
9
+ email: 'john.doe@gmail.com',
10
+ firstName: 'john',
11
+ lastName: 'doe',
12
+ emailVerified: false,
13
+ },
14
+ authStatement: {
15
+ authType: 'passkey',
16
+ userVerified: false,
17
+ authTimestamp: new Date(0),
18
+ },
19
+ expireAt: new Date(100),
20
+ };
21
+ const storageTest = Layer.effect(Storage, E.sync(() => mock()));
22
+ export const testLayers = (storage = storageTest) => {
23
+ const storageService = pipe(StorageServiceLive, Layer.provide(storage));
24
+ return Layer.merge(storage, storageService);
25
+ };
26
+ //# sourceMappingURL=storage.fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.fixture.js","sourceRoot":"","sources":["../../src/storage/storage.fixture.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAC3C,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAEvD,qCAAqC;AACrC,MAAM,CAAC,MAAM,SAAS,GAAc;IAClC,KAAK,EAAE,OAAO;IACd,OAAO,EAAE;QACP,EAAE,EAAE,GAAG;QACP,KAAK,EAAE,oBAAoB;QAC3B,SAAS,EAAE,MAAM;QACjB,QAAQ,EAAE,KAAK;QACf,aAAa,EAAE,KAAK;KACrB;IACD,aAAa,EAAE;QACb,QAAQ,EAAE,SAAS;QACnB,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;KAC3B;IACD,QAAQ,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC;CACxB,CAAA;AAED,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAC9B,OAAO,EACP,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAW,CAAC,CAC9B,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAAgC,WAAW,EAAE,EAAE;IACxE,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAEvE,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAA;AAC7C,CAAC,CAAA"}
@@ -0,0 +1,102 @@
1
+ import { Context, Effect as E, Layer, Option as O, flow, pipe } from 'effect';
2
+ /* Utilities */
3
+ export const StorageService = Context.GenericTag('@services/StorageService');
4
+ // inject window.localStorage to make testing easier
5
+ export const Storage = Context.GenericTag('@services/Storage');
6
+ export const buildKey = (authType) => `passlock:${authType}:token`;
7
+ // principal => token:expireAt
8
+ export const compressToken = (principal) => {
9
+ const expireAt = principal.expireAt.getTime();
10
+ const token = principal.token;
11
+ return `${token}:${expireAt}`;
12
+ };
13
+ // token:expireAt => { authType, token, expireAt }
14
+ export const expandToken = (authType) => (s) => {
15
+ const tokens = s.split(':');
16
+ if (tokens.length !== 2)
17
+ return O.none();
18
+ const [token, expireAtString] = tokens;
19
+ const parse = O.liftThrowable(Number.parseInt);
20
+ const expireAt = parse(expireAtString);
21
+ return O.map(expireAt, expireAt => ({ authType, token, expireAt }));
22
+ };
23
+ /* Effects */
24
+ /**
25
+ * Store compressed token in local storage
26
+ * @param principal
27
+ * @returns
28
+ */
29
+ export const storeToken = (principal) => {
30
+ return E.gen(function* (_) {
31
+ const localStorage = yield* _(Storage);
32
+ const storeEffect = E.try(() => {
33
+ const compressed = compressToken(principal);
34
+ const key = buildKey(principal.authStatement.authType);
35
+ localStorage.setItem(key, compressed);
36
+ }).pipe(E.orElse(() => E.unit)); // We dont care if it fails
37
+ return yield* _(storeEffect);
38
+ });
39
+ };
40
+ /**
41
+ * Get stored token from local storage
42
+ * @param authType
43
+ * @returns
44
+ */
45
+ export const getToken = (authType) => {
46
+ return E.gen(function* (_) {
47
+ const localStorage = yield* _(Storage);
48
+ const getEffect = pipe(O.some(buildKey(authType)), O.flatMap(key => pipe(localStorage.getItem(key), O.fromNullable)), O.flatMap(expandToken(authType)), O.filter(({ expireAt: expireAt }) => expireAt > Date.now()));
49
+ return yield* _(getEffect);
50
+ });
51
+ };
52
+ /**
53
+ * Remove token from local storage
54
+ * @param authType
55
+ * @returns
56
+ */
57
+ export const clearToken = (authType) => {
58
+ return E.gen(function* (_) {
59
+ const localStorage = yield* _(Storage);
60
+ localStorage.removeItem(buildKey(authType));
61
+ });
62
+ };
63
+ /**
64
+ * Only clear if now > token.expireAt
65
+ * @param authType
66
+ * @param defer
67
+ * @returns
68
+ */
69
+ export const clearExpiredToken = (authType) => {
70
+ const key = buildKey(authType);
71
+ const effect = E.gen(function* (_) {
72
+ const storage = yield* _(Storage);
73
+ const item = yield* _(O.fromNullable(storage.getItem(key)));
74
+ const token = yield* _(expandToken(authType)(item));
75
+ if (token.expireAt < Date.now()) {
76
+ storage.removeItem(key);
77
+ }
78
+ });
79
+ // we don't care if it fails
80
+ return pipe(effect, E.match({
81
+ onSuccess: () => E.unit,
82
+ onFailure: () => E.unit,
83
+ }));
84
+ };
85
+ export const clearExpiredTokens = E.all([
86
+ clearExpiredToken('passkey'),
87
+ clearExpiredToken('email'),
88
+ ]);
89
+ /* Live */
90
+ /* v8 ignore start */
91
+ export const StorageServiceLive = Layer.effect(StorageService, E.gen(function* (_) {
92
+ const context = yield* _(E.context());
93
+ return {
94
+ storeToken: flow(storeToken, E.provide(context)),
95
+ getToken: flow(getToken, E.provide(context)),
96
+ clearToken: flow(clearToken, E.provide(context)),
97
+ clearExpiredToken: flow(clearExpiredToken, E.provide(context)),
98
+ clearExpiredTokens: pipe(clearExpiredTokens, E.provide(context)),
99
+ };
100
+ }));
101
+ /* v8 ignore stop */
102
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/storage/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=storage.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.test.d.ts","sourceRoot":"","sources":["../../src/storage/storage.test.ts"],"names":[],"mappings":""}