@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.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/dist/authentication/authenticate.d.ts +22 -0
- package/dist/authentication/authenticate.d.ts.map +1 -0
- package/dist/authentication/authenticate.fixture.d.ts +36 -0
- package/dist/authentication/authenticate.fixture.d.ts.map +1 -0
- package/dist/authentication/authenticate.fixture.js +52 -0
- package/dist/authentication/authenticate.fixture.js.map +1 -0
- package/dist/authentication/authenticate.js +69 -0
- package/dist/authentication/authenticate.js.map +1 -0
- package/dist/authentication/authenticate.test.d.ts +2 -0
- package/dist/authentication/authenticate.test.d.ts.map +1 -0
- package/dist/authentication/authenticate.test.js +111 -0
- package/dist/authentication/authenticate.test.js.map +1 -0
- package/dist/capabilities/capabilities.d.ts +18 -0
- package/dist/capabilities/capabilities.d.ts.map +1 -0
- package/dist/capabilities/capabilities.js +35 -0
- package/dist/capabilities/capabilities.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +20 -0
- package/dist/config.js.map +1 -0
- package/dist/connection/connection.d.ts +9 -0
- package/dist/connection/connection.d.ts.map +1 -0
- package/dist/connection/connection.fixture.d.ts +12 -0
- package/dist/connection/connection.fixture.d.ts.map +1 -0
- package/dist/connection/connection.fixture.js +20 -0
- package/dist/connection/connection.fixture.js.map +1 -0
- package/dist/connection/connection.js +21 -0
- package/dist/connection/connection.js.map +1 -0
- package/dist/connection/connection.test.d.ts +2 -0
- package/dist/connection/connection.test.d.ts.map +1 -0
- package/dist/connection/connection.test.js +34 -0
- package/dist/connection/connection.test.js.map +1 -0
- package/dist/effect.d.ts +33 -0
- package/dist/effect.d.ts.map +1 -0
- package/dist/effect.js +62 -0
- package/dist/effect.js.map +1 -0
- package/dist/email/email.d.ts +37 -0
- package/dist/email/email.d.ts.map +1 -0
- package/dist/email/email.fixture.d.ts +33 -0
- package/dist/email/email.fixture.d.ts.map +1 -0
- package/dist/email/email.fixture.js +30 -0
- package/dist/email/email.fixture.js.map +1 -0
- package/dist/email/email.js +78 -0
- package/dist/email/email.js.map +1 -0
- package/dist/email/email.test.d.ts +2 -0
- package/dist/email/email.test.d.ts.map +1 -0
- package/dist/email/email.test.js +101 -0
- package/dist/email/email.test.js.map +1 -0
- package/dist/event/event.d.ts +9 -0
- package/dist/event/event.d.ts.map +1 -0
- package/dist/event/event.js +23 -0
- package/dist/event/event.js.map +1 -0
- package/dist/event/event.node.test.d.ts +2 -0
- package/dist/event/event.node.test.d.ts.map +1 -0
- package/dist/event/event.node.test.js +14 -0
- package/dist/event/event.node.test.js.map +1 -0
- package/dist/event/event.test.d.ts +2 -0
- package/dist/event/event.test.d.ts.map +1 -0
- package/dist/event/event.test.js +30 -0
- package/dist/event/event.test.js.map +1 -0
- package/dist/exit.d.ts +64 -0
- package/dist/exit.d.ts.map +1 -0
- package/dist/exit.js +106 -0
- package/dist/exit.js.map +1 -0
- package/dist/index.d.ts +110 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +108 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/eventLogger.d.ts +18 -0
- package/dist/logging/eventLogger.d.ts.map +1 -0
- package/dist/logging/eventLogger.js +32 -0
- package/dist/logging/eventLogger.js.map +1 -0
- package/dist/logging/eventLogger.test.d.ts +2 -0
- package/dist/logging/eventLogger.test.d.ts.map +1 -0
- package/dist/logging/eventLogger.test.js +74 -0
- package/dist/logging/eventLogger.test.js.map +1 -0
- package/dist/registration/register.d.ts +29 -0
- package/dist/registration/register.d.ts.map +1 -0
- package/dist/registration/register.fixture.d.ts +40 -0
- package/dist/registration/register.fixture.d.ts.map +1 -0
- package/dist/registration/register.fixture.js +65 -0
- package/dist/registration/register.fixture.js.map +1 -0
- package/dist/registration/register.js +84 -0
- package/dist/registration/register.js.map +1 -0
- package/dist/registration/register.test.d.ts +2 -0
- package/dist/registration/register.test.d.ts.map +1 -0
- package/dist/registration/register.test.js +122 -0
- package/dist/registration/register.test.js.map +1 -0
- package/dist/storage/storage.d.ts +53 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.fixture.d.ts +6 -0
- package/dist/storage/storage.fixture.d.ts.map +1 -0
- package/dist/storage/storage.fixture.js +26 -0
- package/dist/storage/storage.fixture.js.map +1 -0
- package/dist/storage/storage.js +102 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/storage.test.d.ts +2 -0
- package/dist/storage/storage.test.d.ts.map +1 -0
- package/dist/storage/storage.test.js +122 -0
- package/dist/storage/storage.test.js.map +1 -0
- package/dist/test/fixtures.d.ts +14 -0
- package/dist/test/fixtures.d.ts.map +1 -0
- package/dist/test/fixtures.js +39 -0
- package/dist/test/fixtures.js.map +1 -0
- package/dist/user/user.d.ts +18 -0
- package/dist/user/user.d.ts.map +1 -0
- package/dist/user/user.fixture.d.ts +8 -0
- package/dist/user/user.fixture.d.ts.map +1 -0
- package/dist/user/user.fixture.js +17 -0
- package/dist/user/user.fixture.js.map +1 -0
- package/dist/user/user.js +23 -0
- package/dist/user/user.js.map +1 -0
- package/dist/user/user.test.d.ts +2 -0
- package/dist/user/user.test.d.ts.map +1 -0
- package/dist/user/user.test.js +37 -0
- package/dist/user/user.test.js.map +1 -0
- package/package.json +87 -0
- package/src/authentication/authenticate.fixture.ts +72 -0
- package/src/authentication/authenticate.test.ts +207 -0
- package/src/authentication/authenticate.ts +147 -0
- package/src/capabilities/capabilities.ts +81 -0
- package/src/config.ts +43 -0
- package/src/connection/connection.fixture.ts +27 -0
- package/src/connection/connection.test.ts +61 -0
- package/src/connection/connection.ts +51 -0
- package/src/effect.ts +278 -0
- package/src/email/email.fixture.ts +49 -0
- package/src/email/email.test.ts +186 -0
- package/src/email/email.ts +139 -0
- package/src/event/event.node.test.ts +20 -0
- package/src/event/event.test.ts +37 -0
- package/src/event/event.ts +25 -0
- package/src/index.ts +275 -0
- package/src/logging/eventLogger.test.ts +102 -0
- package/src/logging/eventLogger.ts +35 -0
- package/src/registration/register.fixture.ts +94 -0
- package/src/registration/register.test.ts +247 -0
- package/src/registration/register.ts +178 -0
- package/src/storage/storage.fixture.ts +33 -0
- package/src/storage/storage.test.ts +196 -0
- package/src/storage/storage.ts +165 -0
- package/src/test/fixtures.ts +51 -0
- package/src/user/user.fixture.ts +23 -0
- package/src/user/user.test.ts +53 -0
- package/src/user/user.ts +50 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Effect as E, Layer, LogLevel, Logger, identity, pipe } from 'effect';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
import { mock } from 'vitest-mock-extended';
|
|
4
|
+
import { Storage, StorageService, clearExpiredToken, clearToken, getToken } from './storage';
|
|
5
|
+
import { principal, testLayers } from './storage.fixture';
|
|
6
|
+
// eslint chokes on expect(storage.setItem) etc
|
|
7
|
+
/* eslint @typescript-eslint/unbound-method: 0 */
|
|
8
|
+
describe('storeToken should', () => {
|
|
9
|
+
test('set the token in local storage', () => {
|
|
10
|
+
const assertions = E.gen(function* (_) {
|
|
11
|
+
const service = yield* _(StorageService);
|
|
12
|
+
yield* _(service.storeToken(principal));
|
|
13
|
+
const storage = yield* _(Storage);
|
|
14
|
+
expect(storage.setItem).toHaveBeenCalled();
|
|
15
|
+
});
|
|
16
|
+
const effect = pipe(E.provide(assertions, testLayers()), Logger.withMinimumLogLevel(LogLevel.None));
|
|
17
|
+
E.runSync(effect);
|
|
18
|
+
});
|
|
19
|
+
test('with the key passlock:passkey:token', () => {
|
|
20
|
+
const assertions = E.gen(function* (_) {
|
|
21
|
+
const service = yield* _(StorageService);
|
|
22
|
+
yield* _(service.storeToken(principal));
|
|
23
|
+
const storage = yield* _(Storage);
|
|
24
|
+
expect(storage.setItem).toHaveBeenCalledWith('passlock:passkey:token', expect.any(String));
|
|
25
|
+
});
|
|
26
|
+
const effect = pipe(E.provide(assertions, testLayers()), Logger.withMinimumLogLevel(LogLevel.None));
|
|
27
|
+
E.runSync(effect);
|
|
28
|
+
});
|
|
29
|
+
test('with the value token:expiry', () => {
|
|
30
|
+
const assertions = E.gen(function* (_) {
|
|
31
|
+
const service = yield* _(StorageService);
|
|
32
|
+
yield* _(service.storeToken(principal));
|
|
33
|
+
const storage = yield* _(Storage);
|
|
34
|
+
const token = principal.token;
|
|
35
|
+
const expiry = principal.expireAt.getTime();
|
|
36
|
+
expect(storage.setItem).toHaveBeenCalledWith('passlock:passkey:token', `${token}:${expiry}`);
|
|
37
|
+
});
|
|
38
|
+
const effect = pipe(E.provide(assertions, testLayers()), Logger.withMinimumLogLevel(LogLevel.None));
|
|
39
|
+
E.runSync(effect);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('getToken should', () => {
|
|
43
|
+
test('get the token from local storage', () => {
|
|
44
|
+
const assertions = E.gen(function* (_) {
|
|
45
|
+
const service = yield* _(StorageService);
|
|
46
|
+
yield* _(service.getToken('passkey'));
|
|
47
|
+
const storage = yield* _(Storage);
|
|
48
|
+
expect(storage.getItem).toHaveBeenCalled();
|
|
49
|
+
expect(storage.getItem).toHaveBeenCalledWith('passlock:passkey:token');
|
|
50
|
+
});
|
|
51
|
+
const storageTest = Layer.effect(Storage, E.sync(() => {
|
|
52
|
+
const mockStorage = mock();
|
|
53
|
+
const expiry = Date.now() + 1000;
|
|
54
|
+
mockStorage.getItem.mockReturnValue(`token:${expiry}`);
|
|
55
|
+
return mockStorage;
|
|
56
|
+
}));
|
|
57
|
+
const effect = pipe(E.provide(assertions, testLayers(storageTest)), Logger.withMinimumLogLevel(LogLevel.None));
|
|
58
|
+
E.runSync(effect);
|
|
59
|
+
});
|
|
60
|
+
test('filter out expired tokens', () => {
|
|
61
|
+
const assertions = pipe(getToken('passkey'), E.match({
|
|
62
|
+
onSuccess: identity,
|
|
63
|
+
onFailure: () => undefined,
|
|
64
|
+
}), E.flatMap(result => E.sync(() => {
|
|
65
|
+
expect(result).toBeUndefined();
|
|
66
|
+
})));
|
|
67
|
+
const storageTest = Layer.effect(Storage, E.sync(() => {
|
|
68
|
+
const mockStorage = mock();
|
|
69
|
+
const expiry = Date.now() - 1000;
|
|
70
|
+
mockStorage.getItem.mockReturnValue(`token:${expiry}`);
|
|
71
|
+
return mockStorage;
|
|
72
|
+
}));
|
|
73
|
+
const effect = pipe(E.provide(assertions, testLayers(storageTest)), Logger.withMinimumLogLevel(LogLevel.None));
|
|
74
|
+
E.runSync(effect);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe('clearToken should', () => {
|
|
78
|
+
test('clear the token in local storage', () => {
|
|
79
|
+
const assertions = E.gen(function* (_) {
|
|
80
|
+
const storage = yield* _(Storage);
|
|
81
|
+
yield* _(clearToken('passkey'));
|
|
82
|
+
expect(storage.removeItem).toHaveBeenCalledWith('passlock:passkey:token');
|
|
83
|
+
});
|
|
84
|
+
const effect = pipe(E.provide(assertions, testLayers()), Logger.withMinimumLogLevel(LogLevel.None));
|
|
85
|
+
E.runSync(effect);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('clearExpiredToken should', () => {
|
|
89
|
+
test('clear an expired token from local storage', () => {
|
|
90
|
+
const assertions = E.gen(function* (_) {
|
|
91
|
+
const storage = yield* _(Storage);
|
|
92
|
+
yield* _(clearExpiredToken('passkey'));
|
|
93
|
+
expect(storage.getItem).toHaveBeenCalledWith('passlock:passkey:token');
|
|
94
|
+
expect(storage.removeItem).toHaveBeenCalledWith('passlock:passkey:token');
|
|
95
|
+
});
|
|
96
|
+
const storageTest = Layer.effect(Storage, E.sync(() => {
|
|
97
|
+
const mockStorage = mock();
|
|
98
|
+
const expiry = Date.now() - 1000;
|
|
99
|
+
mockStorage.getItem.mockReturnValue(`token:${expiry}`);
|
|
100
|
+
return mockStorage;
|
|
101
|
+
}));
|
|
102
|
+
const effect = pipe(E.provide(assertions, testLayers(storageTest)), Logger.withMinimumLogLevel(LogLevel.None));
|
|
103
|
+
E.runSync(effect);
|
|
104
|
+
});
|
|
105
|
+
test('leave a live token in local storage', () => {
|
|
106
|
+
const assertions = E.gen(function* (_) {
|
|
107
|
+
const storage = yield* _(Storage);
|
|
108
|
+
yield* _(clearExpiredToken('passkey'));
|
|
109
|
+
expect(storage.getItem).toHaveBeenCalledWith('passlock:passkey:token');
|
|
110
|
+
expect(storage.removeItem).not.toHaveBeenCalled();
|
|
111
|
+
});
|
|
112
|
+
const storageTest = Layer.effect(Storage, E.sync(() => {
|
|
113
|
+
const mockStorage = mock();
|
|
114
|
+
const expiry = Date.now() + 1000;
|
|
115
|
+
mockStorage.getItem.mockReturnValue(`token:${expiry}`);
|
|
116
|
+
return mockStorage;
|
|
117
|
+
}));
|
|
118
|
+
const effect = pipe(E.provide(assertions, testLayers(storageTest)), Logger.withMinimumLogLevel(LogLevel.None));
|
|
119
|
+
E.runSync(effect);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=storage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.test.js","sourceRoot":"","sources":["../../src/storage/storage.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Principal } from '@passlock/shared/dist/schema/schema';
|
|
2
|
+
import { Layer as L } from 'effect';
|
|
3
|
+
import { Capabilities } from '../capabilities/capabilities';
|
|
4
|
+
import { StorageService, type StoredToken } from '../storage/storage';
|
|
5
|
+
export declare const session = "session";
|
|
6
|
+
export declare const token = "token";
|
|
7
|
+
export declare const code = "code";
|
|
8
|
+
export declare const authType = "passkey";
|
|
9
|
+
export declare const expireAt: number;
|
|
10
|
+
export declare const principal: Principal;
|
|
11
|
+
export declare const capabilitiesTest: L.Layer<Capabilities, never, never>;
|
|
12
|
+
export declare const storedToken: StoredToken;
|
|
13
|
+
export declare const storageServiceTest: L.Layer<StorageService, never, never>;
|
|
14
|
+
//# sourceMappingURL=fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/test/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AACpE,OAAO,EAAe,KAAK,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGrE,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,SAAS,EAAE,SAevB,CAAA;AAED,eAAO,MAAM,gBAAgB,qCAQ5B,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,WAA2C,CAAA;AAErE,eAAO,MAAM,kBAAkB,uCAS9B,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Effect as E, Layer as L } from 'effect';
|
|
2
|
+
import { Capabilities } from '../capabilities/capabilities';
|
|
3
|
+
import { StorageService } from '../storage/storage';
|
|
4
|
+
export const session = 'session';
|
|
5
|
+
export const token = 'token';
|
|
6
|
+
export const code = 'code';
|
|
7
|
+
export const authType = 'passkey';
|
|
8
|
+
export const expireAt = Date.now() + 10000;
|
|
9
|
+
export const principal = {
|
|
10
|
+
token: 'token',
|
|
11
|
+
subject: {
|
|
12
|
+
id: '1',
|
|
13
|
+
email: 'john.doe@gmail.com',
|
|
14
|
+
firstName: 'john',
|
|
15
|
+
lastName: 'doe',
|
|
16
|
+
emailVerified: false,
|
|
17
|
+
},
|
|
18
|
+
authStatement: {
|
|
19
|
+
authType: 'email',
|
|
20
|
+
userVerified: false,
|
|
21
|
+
authTimestamp: new Date(0),
|
|
22
|
+
},
|
|
23
|
+
expireAt: new Date(0),
|
|
24
|
+
};
|
|
25
|
+
export const capabilitiesTest = L.succeed(Capabilities, Capabilities.of({
|
|
26
|
+
passkeySupport: E.unit,
|
|
27
|
+
isPasskeySupport: E.succeed(true),
|
|
28
|
+
autofillSupport: E.unit,
|
|
29
|
+
isAutofillSupport: E.succeed(true),
|
|
30
|
+
}));
|
|
31
|
+
export const storedToken = { token, authType, expireAt };
|
|
32
|
+
export const storageServiceTest = L.succeed(StorageService, StorageService.of({
|
|
33
|
+
storeToken: () => E.unit,
|
|
34
|
+
getToken: () => E.succeed(storedToken),
|
|
35
|
+
clearToken: () => E.unit,
|
|
36
|
+
clearExpiredToken: () => E.unit,
|
|
37
|
+
clearExpiredTokens: E.unit,
|
|
38
|
+
}));
|
|
39
|
+
//# sourceMappingURL=fixtures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/test/fixtures.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAoB,MAAM,oBAAoB,CAAA;AAGrE,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,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,OAAO;QACjB,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;KAC3B;IACD,QAAQ,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC;CACtB,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,OAAO,CACvC,YAAY,EACZ,YAAY,CAAC,EAAE,CAAC;IACd,cAAc,EAAE,CAAC,CAAC,IAAI;IACtB,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACjC,eAAe,EAAE,CAAC,CAAC,IAAI;IACvB,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;CACnC,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;AAErE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,OAAO,CACzC,cAAc,EACd,cAAc,CAAC,EAAE,CAAC;IAChB,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;IACxB,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IACtC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;IACxB,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI;IAC/B,kBAAkB,EAAE,CAAC,CAAC,IAAI;CAC3B,CAAC,CACH,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check for an existing user
|
|
3
|
+
*/
|
|
4
|
+
import type { BadRequest } from '@passlock/shared/dist/error/error';
|
|
5
|
+
import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
|
|
6
|
+
import { Context, Effect as E, Layer } from 'effect';
|
|
7
|
+
export type Email = {
|
|
8
|
+
email: string;
|
|
9
|
+
};
|
|
10
|
+
export type UserService = {
|
|
11
|
+
isExistingUser: (email: Email) => E.Effect<boolean, BadRequest>;
|
|
12
|
+
};
|
|
13
|
+
export declare const UserService: Context.Tag<UserService, UserService>;
|
|
14
|
+
type Dependencies = RpcClient;
|
|
15
|
+
export declare const isExistingUser: (request: Email) => E.Effect<boolean, BadRequest, Dependencies>;
|
|
16
|
+
export declare const UserServiceLive: Layer.Layer<UserService, never, RpcClient>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=user.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/user/user.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AAEzD,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,EAAQ,MAAM,QAAQ,CAAA;AAK1D,MAAM,MAAM,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAIrC,MAAM,MAAM,WAAW,GAAG;IACxB,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;CAChE,CAAA;AAED,eAAO,MAAM,WAAW,uCAA2D,CAAA;AAInF,KAAK,YAAY,GAAG,SAAS,CAAA;AAE7B,eAAO,MAAM,cAAc,YAAa,KAAK,KAAG,EAAE,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAUzF,CAAA;AAKD,eAAO,MAAM,eAAe,4CAQ3B,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
|
|
2
|
+
import { IsExistingUserReq, IsExistingUserRes } from '@passlock/shared/dist/rpc/user';
|
|
3
|
+
import { Layer as L } from 'effect';
|
|
4
|
+
export declare const email = "jdoe@gmail.com";
|
|
5
|
+
export declare const rpcClientTest: L.Layer<RpcClient, never, never>;
|
|
6
|
+
export declare const isRegisteredReq: IsExistingUserReq;
|
|
7
|
+
export declare const isRegisteredRes: IsExistingUserRes;
|
|
8
|
+
//# sourceMappingURL=user.fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.fixture.d.ts","sourceRoot":"","sources":["../../src/user/user.fixture.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AACrF,OAAO,EAAe,KAAK,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAGhD,eAAO,MAAM,KAAK,mBAAmB,CAAA;AAErC,eAAO,MAAM,aAAa,kCAWzB,CAAA;AAED,eAAO,MAAM,eAAe,mBAAmC,CAAA;AAC/D,eAAO,MAAM,eAAe,mBAAiD,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BadRequest } from '@passlock/shared/dist/error/error';
|
|
2
|
+
import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
|
|
3
|
+
import { IsExistingUserReq, IsExistingUserRes } from '@passlock/shared/dist/rpc/user';
|
|
4
|
+
import { Effect as E, Layer as L } from 'effect';
|
|
5
|
+
export const email = 'jdoe@gmail.com';
|
|
6
|
+
export const rpcClientTest = L.succeed(RpcClient, RpcClient.of({
|
|
7
|
+
preConnect: () => E.succeed({ warmed: true }),
|
|
8
|
+
isExistingUser: () => E.succeed({ existingUser: true }),
|
|
9
|
+
verifyEmail: () => E.succeed({ verified: true }),
|
|
10
|
+
getRegistrationOptions: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
|
|
11
|
+
verifyRegistrationCredential: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
|
|
12
|
+
getAuthenticationOptions: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
|
|
13
|
+
verifyAuthenticationCredential: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
|
|
14
|
+
}));
|
|
15
|
+
export const isRegisteredReq = new IsExistingUserReq({ email });
|
|
16
|
+
export const isRegisteredRes = new IsExistingUserRes({ existingUser: false });
|
|
17
|
+
//# sourceMappingURL=user.fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.fixture.js","sourceRoot":"","sources":["../../src/user/user.fixture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AACrF,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAGhD,MAAM,CAAC,MAAM,KAAK,GAAG,gBAAgB,CAAA;AAErC,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,IAAI,CAAC,IAAI,UAAU,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACrF,4BAA4B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC3F,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,IAAI,CAAC,IAAI,UAAU,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;CAC9F,CAAC,CACH,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;AAC/D,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,iBAAiB,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
|
|
2
|
+
import { IsExistingUserReq } from '@passlock/shared/dist/rpc/user';
|
|
3
|
+
import { Context, Effect as E, Layer, flow } from 'effect';
|
|
4
|
+
export const UserService = Context.GenericTag('@services/UserService');
|
|
5
|
+
export const isExistingUser = (request) => {
|
|
6
|
+
return E.gen(function* (_) {
|
|
7
|
+
yield* _(E.logInfo('Checking registration status'));
|
|
8
|
+
const rpcClient = yield* _(RpcClient);
|
|
9
|
+
yield* _(E.logDebug('Making RPC request'));
|
|
10
|
+
const { existingUser } = yield* _(rpcClient.isExistingUser(new IsExistingUserReq(request)));
|
|
11
|
+
return existingUser;
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
/* Live */
|
|
15
|
+
/* v8 ignore start */
|
|
16
|
+
export const UserServiceLive = Layer.effect(UserService, E.gen(function* (_) {
|
|
17
|
+
const context = yield* _(E.context());
|
|
18
|
+
return UserService.of({
|
|
19
|
+
isExistingUser: flow(isExistingUser, E.provide(context)),
|
|
20
|
+
});
|
|
21
|
+
}));
|
|
22
|
+
/* v8 ignore stop */
|
|
23
|
+
//# sourceMappingURL=user.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/user/user.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAa1D,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAc,uBAAuB,CAAC,CAAA;AAMnF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAc,EAA+C,EAAE;IAC5F,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvB,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,CAAA;QACnD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAErC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAA;QAC1C,MAAM,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAE3F,OAAO,YAAY,CAAA;IACrB,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,UAAU;AAEV,qBAAqB;AACrB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CACzC,WAAW,EACX,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAa,CAAC,CAAA;IAChD,OAAO,WAAW,CAAC,EAAE,CAAC;QACpB,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;KACzD,CAAC,CAAA;AACJ,CAAC,CAAC,CACH,CAAA;AACD,oBAAoB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.test.d.ts","sourceRoot":"","sources":["../../src/user/user.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RpcClient } from '@passlock/shared/dist/rpc/rpc';
|
|
2
|
+
import { Effect as E, Layer as L, Layer, LogLevel, Logger, pipe } from 'effect';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import { mock } from 'vitest-mock-extended';
|
|
5
|
+
import { UserService, UserServiceLive } from './user';
|
|
6
|
+
import * as Fixture from './user.fixture';
|
|
7
|
+
describe('isExistingUser should', () => {
|
|
8
|
+
test('return true when the user already has a passkey', async () => {
|
|
9
|
+
const assertions = E.gen(function* (_) {
|
|
10
|
+
const service = yield* _(UserService);
|
|
11
|
+
const result = yield* _(service.isExistingUser({ email: Fixture.email }));
|
|
12
|
+
expect(result).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
const service = pipe(UserServiceLive, L.provide(Fixture.rpcClientTest));
|
|
15
|
+
const effect = pipe(E.provide(assertions, service), Logger.withMinimumLogLevel(LogLevel.None));
|
|
16
|
+
return E.runPromise(effect);
|
|
17
|
+
});
|
|
18
|
+
test('send the email to the backend', async () => {
|
|
19
|
+
const assertions = E.gen(function* (_) {
|
|
20
|
+
const service = yield* _(UserService);
|
|
21
|
+
const result = yield* _(service.isExistingUser({ email: Fixture.email }));
|
|
22
|
+
expect(result).toBe(false);
|
|
23
|
+
const rpcClient = yield* _(RpcClient);
|
|
24
|
+
expect(rpcClient.isExistingUser).toBeCalledWith(Fixture.isRegisteredReq);
|
|
25
|
+
});
|
|
26
|
+
const rpcClientTest = Layer.effect(RpcClient, E.sync(() => {
|
|
27
|
+
const rpcMock = mock();
|
|
28
|
+
rpcMock.isExistingUser.mockReturnValue(E.succeed(Fixture.isRegisteredRes));
|
|
29
|
+
return rpcMock;
|
|
30
|
+
}));
|
|
31
|
+
const service = pipe(UserServiceLive, L.provide(rpcClientTest));
|
|
32
|
+
const layers = L.merge(service, rpcClientTest);
|
|
33
|
+
const effect = pipe(E.provide(assertions, layers), Logger.withMinimumLogLevel(LogLevel.None));
|
|
34
|
+
return E.runPromise(effect);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=user.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.test.js","sourceRoot":"","sources":["../../src/user/user.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@passlock/client",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Framework agnostic Passkey library for React/Next.js, Vue/Nuxt.js, SvelteKit and others. Passlock works with pretty much any frontend/backend stack - check out the tutorial",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"passkey",
|
|
7
|
+
"passkeys",
|
|
8
|
+
"webauthn",
|
|
9
|
+
"react",
|
|
10
|
+
"next",
|
|
11
|
+
"vue",
|
|
12
|
+
"nuxt",
|
|
13
|
+
"svelte"
|
|
14
|
+
],
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Toby Hobson",
|
|
17
|
+
"email": "toby@passlock.dev"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"homepage": "https://passlock.dev",
|
|
21
|
+
"repository": "github.com/passlock-dev/passkeys",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/passlock-dev/passkeys/issues",
|
|
24
|
+
"email": "team@passlock.dev"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"import": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts"
|
|
31
|
+
},
|
|
32
|
+
"./effect": {
|
|
33
|
+
"import": "./dist/effect.js",
|
|
34
|
+
"types": "./dist/effect.d.ts"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"src",
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@effect/platform": "^0.47.1",
|
|
43
|
+
"effect": "2.4.3",
|
|
44
|
+
"nanoid": "^5.0.6",
|
|
45
|
+
"valibot": "^0.30.0",
|
|
46
|
+
"@passlock/shared": "0.9.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@github/webauthn-json": "^2.1.1",
|
|
50
|
+
"@tsconfig/node20": "^20.1.2",
|
|
51
|
+
"@types/node": "^20.11.25",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
|
53
|
+
"@typescript-eslint/parser": "^7.1.1",
|
|
54
|
+
"@vitest/coverage-v8": "^1.3.1",
|
|
55
|
+
"@vitest/ui": "^1.3.1",
|
|
56
|
+
"dts-bundle-generator": "^9.3.1",
|
|
57
|
+
"eslint": "^8.57.0",
|
|
58
|
+
"eslint-config-prettier": "^9.1.0",
|
|
59
|
+
"eslint-import-resolver-typescript": "^3.6.1",
|
|
60
|
+
"eslint-plugin-import": "^2.29.1",
|
|
61
|
+
"jsdom": "^24.0.0",
|
|
62
|
+
"prettier": "^3.2.5",
|
|
63
|
+
"rimraf": "^5.0.5",
|
|
64
|
+
"ts-node": "^10.9.2",
|
|
65
|
+
"tslib": "^2.6.2",
|
|
66
|
+
"typescript": "^5.4.2",
|
|
67
|
+
"vite": "^5.1.6",
|
|
68
|
+
"vitest": "^1.3.1",
|
|
69
|
+
"vitest-mock-extended": "^1.3.1"
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"clean": "tsc --build --clean",
|
|
73
|
+
"dev": "vite dev",
|
|
74
|
+
"test": "vitest run",
|
|
75
|
+
"test:watch": "vitest dev",
|
|
76
|
+
"test:ui": "vitest --coverage.enabled=true --ui",
|
|
77
|
+
"test:coverage": "vitest run --coverage",
|
|
78
|
+
"build": "tsc --build",
|
|
79
|
+
"watch": "tsc --build --watch",
|
|
80
|
+
"typecheck": "tsc --noEmit",
|
|
81
|
+
"lint": "eslint --ext .ts src",
|
|
82
|
+
"lint:fix": "pnpm run lint --fix",
|
|
83
|
+
"format": "prettier --write \"src/**/*.+(js|ts|json)\"",
|
|
84
|
+
"ncu": "ncu -x @passlock/shared",
|
|
85
|
+
"ncu:save": "ncu -u -x @passlock/shared"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { BadRequest } from '@passlock/shared/dist/error/error'
|
|
2
|
+
import {
|
|
3
|
+
OptionsRes,
|
|
4
|
+
VerificationReq,
|
|
5
|
+
VerificationRes,
|
|
6
|
+
} from '@passlock/shared/dist/rpc/authentication'
|
|
7
|
+
import { RpcClient } from '@passlock/shared/dist/rpc/rpc'
|
|
8
|
+
import type { AuthenticationCredential } from '@passlock/shared/dist/schema/schema'
|
|
9
|
+
import { Effect as E, Layer as L } from 'effect'
|
|
10
|
+
import { type AuthenticationRequest, GetCredential } from './authenticate'
|
|
11
|
+
import * as Fixtures from '../test/fixtures'
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export const session = 'session'
|
|
15
|
+
export const token = 'token'
|
|
16
|
+
export const code = 'code'
|
|
17
|
+
export const authType = 'passkey'
|
|
18
|
+
export const expireAt = Date.now() + 10000
|
|
19
|
+
|
|
20
|
+
export const request: AuthenticationRequest = {
|
|
21
|
+
userVerification: 'preferred',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const optionsRes = new OptionsRes({
|
|
25
|
+
session,
|
|
26
|
+
publicKey: {
|
|
27
|
+
rpId: 'passlock.dev',
|
|
28
|
+
challenge: 'FKZSl_saKu5OXjLLwoq8eK3wlD8XgpGiS10SszW5RiE',
|
|
29
|
+
timeout: 60000,
|
|
30
|
+
userVerification: 'preferred',
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
export const credential: AuthenticationCredential = {
|
|
35
|
+
id: '1',
|
|
36
|
+
type: 'public-key',
|
|
37
|
+
rawId: 'id',
|
|
38
|
+
response: {
|
|
39
|
+
clientDataJSON: '',
|
|
40
|
+
authenticatorData: '',
|
|
41
|
+
signature: '',
|
|
42
|
+
userHandle: null,
|
|
43
|
+
},
|
|
44
|
+
clientExtensionResults: {},
|
|
45
|
+
authenticatorAttachment: null,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const verificationReq = new VerificationReq({ session, credential })
|
|
49
|
+
|
|
50
|
+
export const verificationRes = new VerificationRes({ principal: Fixtures.principal })
|
|
51
|
+
|
|
52
|
+
export const getCredentialTest = L.succeed(
|
|
53
|
+
GetCredential,
|
|
54
|
+
GetCredential.of(() => E.succeed(credential)),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
export const rpcClientTest = L.succeed(
|
|
58
|
+
RpcClient,
|
|
59
|
+
RpcClient.of({
|
|
60
|
+
preConnect: () => E.succeed({ warmed: true }),
|
|
61
|
+
isExistingUser: () => E.succeed({ existingUser: true }),
|
|
62
|
+
verifyEmail: () => E.succeed({ verified: true }),
|
|
63
|
+
getRegistrationOptions: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
|
|
64
|
+
verifyRegistrationCredential: () => E.fail(new BadRequest({ message: 'Not implemeneted' })),
|
|
65
|
+
getAuthenticationOptions: () => E.succeed(optionsRes),
|
|
66
|
+
verifyAuthenticationCredential: () => E.succeed(verificationRes),
|
|
67
|
+
}),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
export const principal = Fixtures.principal
|
|
71
|
+
export const capabilitiesTest = Fixtures.capabilitiesTest
|
|
72
|
+
export const storageServiceTest = Fixtures.storageServiceTest
|