@passlock/node 0.9.2 → 0.9.3
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/README.md +4 -0
- package/dist/config/config.d.ts +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +2 -2
- package/dist/config/config.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/principal/principal.d.ts +14 -4
- package/dist/principal/principal.d.ts.map +1 -1
- package/dist/principal/principal.fixture.d.ts +17 -0
- package/dist/principal/principal.fixture.d.ts.map +1 -0
- package/dist/principal/principal.fixture.js +43 -0
- package/dist/principal/principal.fixture.js.map +1 -0
- package/dist/principal/principal.js +38 -23
- package/dist/principal/principal.js.map +1 -1
- package/dist/principal/principal.test.d.ts +2 -0
- package/dist/principal/principal.test.d.ts.map +1 -0
- package/dist/principal/principal.test.js +81 -0
- package/dist/principal/principal.test.js.map +1 -0
- package/package.json +11 -12
- package/src/config/config.ts +7 -7
- package/src/index.ts +33 -20
- package/src/principal/principal.fixture.ts +80 -0
- package/src/principal/principal.test.ts +111 -0
- package/src/principal/principal.ts +99 -56
package/README.md
CHANGED
|
@@ -45,6 +45,10 @@ Passkeys and the WebAuthn API are quite complex. We've taken an opinionated appr
|
|
|
45
45
|

|
|
46
46
|
<p align="center">Viewing a user's authentication activity on their profile page</p>
|
|
47
47
|
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
Node 16+
|
|
51
|
+
|
|
48
52
|
## Usage
|
|
49
53
|
|
|
50
54
|
Generate a secure token in your frontend then use this API to obtain the passkey registration or authentication details:
|
package/dist/config/config.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;;wBAKR,MAAM;qBACT,MAAM;wBACH,MAAM;;AAL9B,qBAAa,MAAO,SAAQ,WAOzB;CAAG"}
|
package/dist/config/config.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAEhC,MAAM,OAAO,MAAO,SAAQ,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAO9C;CAAG"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ErrorCode } from
|
|
2
|
-
import { type PrincipalRequest } from
|
|
1
|
+
import { ErrorCode } from '@passlock/shared/dist/error/error.js';
|
|
2
|
+
import { type PrincipalRequest } from './principal/principal.js';
|
|
3
3
|
export type { PrincipalRequest } from './principal/principal.js';
|
|
4
4
|
export { ErrorCode } from '@passlock/shared/dist/error/error.js';
|
|
5
5
|
export declare class PasslockError extends Error {
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAKV,MAAM,sCAAsC,CAAA;AAG7C,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,0BAA0B,CAAA;AAEjC,YAAY,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAEhE,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAA;AAEhE,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,mBAAkB;IAC/B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS;IAK5C,MAAM,CAAC,QAAQ,CAAC,OAAO,UAAW,OAAO,4BAOxC;CACF;AAyDD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;gBAE3C,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAW5E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAQ1B;IAED,cAAc,YAAa,gBAAgB;;;;;;;;;;;;;;;OAKxC;CACJ;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA+B;gBAE3C,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAW5E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAI1B;IAED,cAAc,YAAa,gBAAgB;;;;;;;;;;;;;;;uBAKxC;CACJ"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ErrorCode, InternalServerError } from
|
|
2
|
-
import { Effect as E, Layer as L, Runtime, Scope, pipe } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { ErrorCode, Forbidden, InternalServerError, NotFound, Unauthorized, } from '@passlock/shared/dist/error/error.js';
|
|
2
|
+
import { Effect as E, Layer as L, Runtime, Scope, pipe } from 'effect';
|
|
3
|
+
import { Config } from './config/config.js';
|
|
4
|
+
import { PrincipalService, PrincipalServiceLive, StreamResponseLive, } from './principal/principal.js';
|
|
5
5
|
export { ErrorCode } from '@passlock/shared/dist/error/error.js';
|
|
6
6
|
export class PasslockError extends Error {
|
|
7
7
|
_tag = 'PasslockError';
|
|
@@ -54,8 +54,8 @@ const transformErrors = (effect) => {
|
|
|
54
54
|
export class PasslockUnsafe {
|
|
55
55
|
runtime;
|
|
56
56
|
constructor(config) {
|
|
57
|
-
const
|
|
58
|
-
const allLayers = pipe(PrincipalServiceLive, L.provide(
|
|
57
|
+
const configLive = L.succeed(Config, Config.of(config));
|
|
58
|
+
const allLayers = pipe(PrincipalServiceLive, L.provide(configLive), L.provide(StreamResponseLive));
|
|
59
59
|
const scope = E.runSync(Scope.make());
|
|
60
60
|
this.runtime = E.runSync(L.toRuntime(allLayers).pipe(Scope.extend(scope)));
|
|
61
61
|
}
|
|
@@ -67,8 +67,8 @@ export class PasslockUnsafe {
|
|
|
67
67
|
export class Passlock {
|
|
68
68
|
runtime;
|
|
69
69
|
constructor(config) {
|
|
70
|
-
const
|
|
71
|
-
const allLayers = pipe(PrincipalServiceLive, L.provide(
|
|
70
|
+
const configLive = L.succeed(Config, Config.of(config));
|
|
71
|
+
const allLayers = pipe(PrincipalServiceLive, L.provide(configLive), L.provide(StreamResponseLive));
|
|
72
72
|
const scope = E.runSync(Scope.make());
|
|
73
73
|
this.runtime = E.runSync(L.toRuntime(allLayers).pipe(Scope.extend(scope)));
|
|
74
74
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,YAAY,GACb,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAC3C,OAAO,EAEL,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,0BAA0B,CAAA;AAIjC,OAAO,EAAE,SAAS,EAAE,MAAM,sCAAsC,CAAA;AAEhE,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,IAAI,GAAG,eAAe,CAAA;IACtB,IAAI,CAAW;IAExB,YAAY,OAAe,EAAE,IAAe;QAC1C,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAED,MAAM,CAAU,OAAO,GAAG,CAAC,KAAc,EAA0B,EAAE;QACnE,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,MAAM,IAAI,KAAK;YACf,KAAK,CAAC,MAAM,CAAC,KAAK,eAAe,CAClC,CAAA;IACH,CAAC,CAAA;;AAKH,MAAM,UAAU,GAAG,CAAC,MAAe,EAAiC,EAAE;IACpE,OAAO,CACL,OAAO,MAAM,KAAK,QAAQ;QAC1B,MAAM,KAAK,IAAI;QACf,SAAS,IAAI,MAAM;QACnB,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,QAAQ,CACtC,CAAA;AACH,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,CACtB,MAAsC,EACC,EAAE;IACzC,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE;QAC5C,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC1E,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QAClF,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;QAC5E,mBAAmB,EAAE,CAAC,CAAC,EAAE,CACvB,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAC;KACzE,CAAC,CAAA;IAEF,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAE9C,MAAM,cAAc,GAAG,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE;QAC5C,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;YAClB,OAAO,UAAU,CAAC,MAAM,CAAC;gBACvB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAC;gBAC7E,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,6BAA6B,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAChG,CAAC;QAED,SAAS,EAAE,GAAG,EAAE;YACd,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,aAAa,CAAC,mBAAmB,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAC,CAAA;QAC1F,CAAC;QAED,UAAU,EAAE,MAAM,CAAC,EAAE;YACnB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACrB,OAAO,CAAC,CAAC,OAAO,CACd,IAAI,aAAa,CAAC,6BAA6B,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAChF,CAAA;QACH,CAAC;QAED,QAAQ,EAAE,MAAM,CAAC,EAAE;YACjB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YACrB,OAAO,CAAC,CAAC,OAAO,CACd,IAAI,aAAa,CAAC,6BAA6B,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAChF,CAAA;QACH,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,CAAA;AACpC,CAAC,CAAA;AAID,MAAM,OAAO,cAAc;IACR,OAAO,CAA+B;IAEvD,YAAY,MAAgE;QAC1E,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;QACvD,MAAM,SAAS,GAAG,IAAI,CACpB,oBAAoB,EACpB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EACrB,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAC9B,CAAA;QACD,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;QACrC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5E,CAAC;IAEgB,UAAU,GAAG,CAC5B,MAAsC,EACtC,EAAE;QACF,OAAO,IAAI,CACT,eAAe,CAAC,MAAM,CAAC,EACvB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EACzF,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CACnD,CAAA;IACH,CAAC,CAAA;IAED,cAAc,GAAG,CAAC,OAAyB,EAAE,EAAE,CAC7C,IAAI,CACF,gBAAgB,EAChB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EACrD,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAClC,CAAA;CACJ;AAED,MAAM,OAAO,QAAQ;IACF,OAAO,CAA+B;IAEvD,YAAY,MAAgE;QAC1E,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;QACvD,MAAM,SAAS,GAAG,IAAI,CACpB,oBAAoB,EACpB,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EACrB,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAC9B,CAAA;QACD,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;QACrC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5E,CAAC;IAEgB,UAAU,GAAG,CAC5B,MAAsC,EACtC,EAAE;QACF,OAAO,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC1F,CAAC,CAAA;IAED,cAAc,GAAG,CAAC,OAAyB,EAAE,EAAE,CAC7C,IAAI,CACF,gBAAgB,EAChB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EACrD,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAClC,CAAA;CACJ"}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
1
3
|
import { Forbidden, InternalServerError, NotFound, Unauthorized } from '@passlock/shared/dist/error/error.js';
|
|
2
4
|
import { Principal } from '@passlock/shared/dist/schema/schema.js';
|
|
3
|
-
import { Context, Effect as E, Layer } from
|
|
4
|
-
import
|
|
5
|
+
import { Context, Effect as E, Layer, Stream } from 'effect';
|
|
6
|
+
import * as https from 'https';
|
|
7
|
+
import { Config } from '../config/config.js';
|
|
8
|
+
export type StreamResponse = (options: https.RequestOptions) => Stream.Stream<Buffer, PrincipalErrors>;
|
|
9
|
+
export declare const StreamResponse: Context.Tag<StreamResponse, StreamResponse>;
|
|
5
10
|
export type PrincipalErrors = NotFound | Unauthorized | Forbidden | InternalServerError;
|
|
6
11
|
export type PrincipalRequest = {
|
|
7
12
|
token: string;
|
|
@@ -10,6 +15,11 @@ export type PrincipalService = {
|
|
|
10
15
|
fetchPrincipal: (request: PrincipalRequest) => E.Effect<Principal, PrincipalErrors>;
|
|
11
16
|
};
|
|
12
17
|
export declare const PrincipalService: Context.Tag<PrincipalService, PrincipalService>;
|
|
13
|
-
export declare const
|
|
14
|
-
|
|
18
|
+
export declare const buildError: (res: {
|
|
19
|
+
statusCode?: number | undefined;
|
|
20
|
+
statusMessage?: string | undefined;
|
|
21
|
+
}) => NotFound | Unauthorized | Forbidden | InternalServerError;
|
|
22
|
+
export declare const fetchPrincipal: (request: PrincipalRequest) => E.Effect<Principal, PrincipalErrors, StreamResponse | Config>;
|
|
23
|
+
export declare const StreamResponseLive: Layer.Layer<StreamResponse, never, never>;
|
|
24
|
+
export declare const PrincipalServiceLive: Layer.Layer<PrincipalService, never, Config | StreamResponse>;
|
|
15
25
|
//# sourceMappingURL=principal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principal.d.ts","sourceRoot":"","sources":["../../src/principal/principal.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"principal.d.ts","sourceRoot":"","sources":["../../src/principal/principal.ts"],"names":[],"mappings":";;AAAA,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,YAAY,EACb,MAAM,sCAAsC,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAgB,MAAM,wCAAwC,CAAA;AAEhF,OAAO,EAAkB,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,EAAU,MAAM,EAAc,MAAM,QAAQ,CAAA;AAChG,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAI5C,MAAM,MAAM,cAAc,GAAG,CAC3B,OAAO,EAAE,KAAK,CAAC,cAAc,KAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;AAC3C,eAAO,MAAM,cAAc,6CAAiE,CAAA;AAM5F,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,GAAG,mBAAmB,CAAA;AACvF,MAAM,MAAM,gBAAgB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEhD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,cAAc,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;CACpF,CAAA;AAED,eAAO,MAAM,gBAAgB,iDAA8D,CAAA;AAuB3F,eAAO,MAAM,UAAU,QAAS;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC,8DAaA,CAAA;AAaD,eAAO,MAAM,cAAc,YAChB,gBAAgB,KACxB,EAAE,MAAM,CAAC,SAAS,EAAE,eAAe,EAAE,cAAc,GAAG,MAAM,CAuC9D,CAAA;AAKD,eAAO,MAAM,kBAAkB,2CAW7B,CAAA;AAEF,eAAO,MAAM,oBAAoB,+DAQhC,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import type { RequestOptions } from 'https';
|
|
3
|
+
import type { Principal } from '@passlock/shared/dist/schema/schema.js';
|
|
4
|
+
import { Context, Effect as E, Layer as L, Ref } from 'effect';
|
|
5
|
+
import { type PrincipalService } from './principal.js';
|
|
6
|
+
import { Config } from '../config/config.js';
|
|
7
|
+
export declare const principal: Principal;
|
|
8
|
+
export declare const tenancyId = "tenancyId";
|
|
9
|
+
export declare const apiKey = "apiKey";
|
|
10
|
+
export declare const configTest: L.Layer<Config, never, never>;
|
|
11
|
+
declare const State_base: Context.TagClass<State, "State", Ref.Ref<RequestOptions | undefined>>;
|
|
12
|
+
export declare class State extends State_base {
|
|
13
|
+
}
|
|
14
|
+
export declare const buildEffect: <A, E>(assertions: E.Effect<A, E, PrincipalService | State>) => E.Effect<void, E>;
|
|
15
|
+
export declare const buildErrorEffect: (statusCode: number) => <A>(assertions: E.Effect<void, A, PrincipalService>) => E.Effect<void, A>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=principal.fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal.fixture.d.ts","sourceRoot":"","sources":["../../src/principal/principal.fixture.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAA;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAoB,GAAG,EAAgB,MAAM,QAAQ,CAAA;AAC9F,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,eAAO,MAAM,SAAS,EAAE,SAevB,CAAA;AAED,eAAO,MAAM,SAAS,cAAc,CAAA;AACpC,eAAO,MAAM,MAAM,WAAW,CAAA;AAE9B,eAAO,MAAM,UAAU,+BAAsD,CAAA;;AAE7E,qBAAa,KAAM,SAAQ,UAAkE;CAAG;AAEhG,eAAO,MAAM,WAAW,qBACV,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,gBAAgB,GAAG,KAAK,CAAC,KACnD,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAsBlB,CAAA;AAED,eAAO,MAAM,gBAAgB,eACd,MAAM,qBACH,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,gBAAgB,CAAC,KAAG,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAgBrE,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Context, Effect as E, Layer as L, LogLevel, Logger, Ref, Stream, pipe } from 'effect';
|
|
2
|
+
import { PrincipalServiceLive, StreamResponse, buildError, } from './principal.js';
|
|
3
|
+
import { Config } from '../config/config.js';
|
|
4
|
+
export const principal = {
|
|
5
|
+
token: 'token',
|
|
6
|
+
subject: {
|
|
7
|
+
id: '1',
|
|
8
|
+
email: 'john.doe@gmail.com',
|
|
9
|
+
firstName: 'john',
|
|
10
|
+
lastName: 'doe',
|
|
11
|
+
emailVerified: false,
|
|
12
|
+
},
|
|
13
|
+
authStatement: {
|
|
14
|
+
authType: 'email',
|
|
15
|
+
userVerified: false,
|
|
16
|
+
authTimestamp: new Date(0),
|
|
17
|
+
},
|
|
18
|
+
expireAt: new Date(0),
|
|
19
|
+
};
|
|
20
|
+
export const tenancyId = 'tenancyId';
|
|
21
|
+
export const apiKey = 'apiKey';
|
|
22
|
+
export const configTest = L.succeed(Config, Config.of({ tenancyId, apiKey }));
|
|
23
|
+
export class State extends Context.Tag('State')() {
|
|
24
|
+
}
|
|
25
|
+
export const buildEffect = (assertions) => {
|
|
26
|
+
const responseStreamTest = L.effect(StreamResponse, E.gen(function* (_) {
|
|
27
|
+
const ref = yield* _(State);
|
|
28
|
+
const buff = Buffer.from(JSON.stringify(principal));
|
|
29
|
+
return options => pipe(Stream.fromEffect(Ref.set(ref, options)), Stream.zipRight(Stream.make(buff)));
|
|
30
|
+
}));
|
|
31
|
+
const service = pipe(PrincipalServiceLive, L.provide(responseStreamTest), L.provide(configTest));
|
|
32
|
+
const args = L.effect(State, Ref.make(undefined));
|
|
33
|
+
const effect = pipe(E.provide(assertions, service), E.provide(args), Logger.withMinimumLogLevel(LogLevel.None));
|
|
34
|
+
return effect;
|
|
35
|
+
};
|
|
36
|
+
export const buildErrorEffect = (statusCode) => (assertions) => {
|
|
37
|
+
const responseStreamTest = L.succeed(StreamResponse, () => Stream.fail(buildError({ statusCode })));
|
|
38
|
+
const service = pipe(PrincipalServiceLive, L.provide(responseStreamTest), L.provide(configTest));
|
|
39
|
+
const args = L.effect(State, Ref.make(undefined));
|
|
40
|
+
const effect = pipe(E.provide(assertions, service), E.provide(args), Logger.withMinimumLogLevel(LogLevel.None));
|
|
41
|
+
return effect;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=principal.fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal.fixture.js","sourceRoot":"","sources":["../../src/principal/principal.fixture.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC9F,OAAO,EAEL,oBAAoB,EACpB,cAAc,EACd,UAAU,GACX,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,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,SAAS,GAAG,WAAW,CAAA;AACpC,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAA;AAE9B,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;AAE7E,MAAM,OAAO,KAAM,SAAQ,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAA8C;CAAG;AAEhG,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,UAAoD,EACjC,EAAE;IACrB,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CACjC,cAAc,EACd,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAA;QACnD,OAAO,OAAO,CAAC,EAAE,CACf,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtF,CAAC,CAAC,CACH,CAAA;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhG,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAA6B,SAAS,CAAC,CAAC,CAAA;IAE7E,MAAM,MAAM,GAAG,IAAI,CACjB,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,EAC9B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EACf,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC1C,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAC3B,CAAC,UAAkB,EAAE,EAAE,CACvB,CAAI,UAA+C,EAAqB,EAAE;IACxE,MAAM,kBAAkB,GAAG,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,GAAG,EAAE,CACxD,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CACxC,CAAA;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhG,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAA6B,SAAS,CAAC,CAAC,CAAA;IAE7E,MAAM,MAAM,GAAG,IAAI,CACjB,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,EAC9B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EACf,MAAM,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC1C,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -1,29 +1,33 @@
|
|
|
1
|
-
import { Forbidden, InternalServerError, NotFound, Unauthorized } from '@passlock/shared/dist/error/error.js';
|
|
1
|
+
import { Forbidden, InternalServerError, NotFound, Unauthorized, } from '@passlock/shared/dist/error/error.js';
|
|
2
2
|
import { Principal, createParser } from '@passlock/shared/dist/schema/schema.js';
|
|
3
|
-
import { Chunk, Console, Context, Effect as E, Layer, Option, Stream,
|
|
4
|
-
import * as https from
|
|
5
|
-
import { Config } from
|
|
3
|
+
import { Chunk, Console, Context, Effect as E, Layer, Option, Stream, flow, pipe } from 'effect';
|
|
4
|
+
import * as https from 'https';
|
|
5
|
+
import { Config } from '../config/config.js';
|
|
6
|
+
export const StreamResponse = Context.GenericTag('@services/ResponseStream');
|
|
6
7
|
const parsePrincipal = createParser(Principal);
|
|
7
8
|
export const PrincipalService = Context.GenericTag('@services/Principal');
|
|
9
|
+
const buildHostname = (endpoint) => {
|
|
10
|
+
return new URL(endpoint || 'https://api.passlock.dev').hostname;
|
|
11
|
+
};
|
|
8
12
|
const buildOptions = (token) => pipe(Config, E.map(({ endpoint, tenancyId, apiKey }) => ({
|
|
9
|
-
hostname: endpoint
|
|
13
|
+
hostname: buildHostname(endpoint),
|
|
10
14
|
port: 443,
|
|
11
15
|
path: `/${tenancyId}/token/${token}`,
|
|
12
16
|
method: 'GET',
|
|
13
17
|
headers: {
|
|
14
18
|
'Accept': 'application/json',
|
|
15
|
-
'X-API-KEY': apiKey
|
|
16
|
-
}
|
|
19
|
+
'X-API-KEY': apiKey,
|
|
20
|
+
},
|
|
17
21
|
})));
|
|
18
|
-
const buildError = (res) => {
|
|
22
|
+
export const buildError = (res) => {
|
|
19
23
|
if (res.statusCode === 404)
|
|
20
|
-
return new NotFound({ message:
|
|
24
|
+
return new NotFound({ message: 'Invalid token' });
|
|
21
25
|
if (res.statusCode === 401)
|
|
22
26
|
return new Unauthorized({ message: 'Unauthorized' });
|
|
23
27
|
if (res.statusCode === 403)
|
|
24
28
|
return new Forbidden({ message: 'Forbidden' });
|
|
25
29
|
if (res.statusCode && res.statusMessage)
|
|
26
|
-
return new InternalServerError({ message: `${res.statusCode} - ${res.statusMessage}` });
|
|
30
|
+
return new InternalServerError({ message: `${String(res.statusCode)} - ${res.statusMessage}` });
|
|
27
31
|
if (res.statusCode)
|
|
28
32
|
return new InternalServerError({ message: String(res.statusCode) });
|
|
29
33
|
if (res.statusMessage)
|
|
@@ -33,26 +37,37 @@ const buildError = (res) => {
|
|
|
33
37
|
const fail = (error) => E.fail(Option.some(error));
|
|
34
38
|
const succeed = (data) => E.succeed(Chunk.of(data));
|
|
35
39
|
const close = E.fail(Option.none());
|
|
36
|
-
const buildStream = (token) => pipe(Stream.fromEffect(buildOptions(token)), Stream.
|
|
37
|
-
https.request(options, res => {
|
|
38
|
-
if (200 !== res.statusCode)
|
|
39
|
-
emit(fail(buildError(res)));
|
|
40
|
-
res.on('data', data => emit(succeed(data)));
|
|
41
|
-
res.on('close', () => emit(close));
|
|
42
|
-
res.on('error', (e) => emit(fail(new InternalServerError({ message: e.message }))));
|
|
43
|
-
}).end();
|
|
44
|
-
})));
|
|
40
|
+
const buildStream = (token) => pipe(Stream.fromEffect(buildOptions(token)), Stream.zip(StreamResponse), Stream.flatMap(([options, streamResponse]) => streamResponse(options)));
|
|
45
41
|
export const fetchPrincipal = (request) => {
|
|
46
42
|
const stream = buildStream(request.token);
|
|
47
|
-
const json = pipe(Stream.runCollect(stream), E.map(Chunk.toReadonlyArray), E.map(Buffer.concat), E.flatMap(buffer => E.try({
|
|
43
|
+
const json = pipe(Stream.runCollect(stream), E.map(Chunk.toReadonlyArray), E.map(buffers => Buffer.concat(buffers)), E.flatMap(buffer => E.try({
|
|
48
44
|
try: () => buffer.toString(),
|
|
49
|
-
catch:
|
|
45
|
+
catch: e => new InternalServerError({
|
|
46
|
+
message: 'Unable to convert response to string',
|
|
47
|
+
detail: String(e),
|
|
48
|
+
}),
|
|
50
49
|
})), E.flatMap(buffer => E.try({
|
|
51
50
|
try: () => JSON.parse(buffer),
|
|
52
|
-
catch:
|
|
53
|
-
|
|
51
|
+
catch: e => new InternalServerError({
|
|
52
|
+
message: 'Unable to parse response to json',
|
|
53
|
+
detail: String(e),
|
|
54
|
+
}),
|
|
55
|
+
})), E.flatMap(json => pipe(parsePrincipal(json), E.tapError(error => Console.error(error.detail)), E.mapError(() => new InternalServerError({ message: 'Unable to parse response as Principal' })))));
|
|
54
56
|
return json;
|
|
55
57
|
};
|
|
58
|
+
export const StreamResponseLive = Layer.succeed(StreamResponse, options => {
|
|
59
|
+
return Stream.async((emit) => {
|
|
60
|
+
https
|
|
61
|
+
.request(options, res => {
|
|
62
|
+
if (200 !== res.statusCode)
|
|
63
|
+
void emit(fail(buildError(res)));
|
|
64
|
+
res.on('data', (data) => void emit(succeed(data)));
|
|
65
|
+
res.on('close', () => void emit(close));
|
|
66
|
+
res.on('error', e => void emit(fail(new InternalServerError({ message: e.message }))));
|
|
67
|
+
})
|
|
68
|
+
.end();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
56
71
|
export const PrincipalServiceLive = Layer.effect(PrincipalService, E.gen(function* (_) {
|
|
57
72
|
const context = yield* _(E.context());
|
|
58
73
|
return PrincipalService.of({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principal.js","sourceRoot":"","sources":["../../src/principal/principal.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"principal.js","sourceRoot":"","sources":["../../src/principal/principal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal.test.d.ts","sourceRoot":"","sources":["../../src/principal/principal.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Forbidden, InternalServerError, NotFound, Unauthorized, } from '@passlock/shared/dist/error/error.js';
|
|
2
|
+
import { Effect as E, Effect, Ref } from 'effect';
|
|
3
|
+
import { describe, expect, test } from 'vitest';
|
|
4
|
+
import * as Fixture from './principal.fixture.js';
|
|
5
|
+
import { PrincipalService } from './principal.js';
|
|
6
|
+
describe('fetchPrincipal should', () => {
|
|
7
|
+
test('return a valid principal', () => {
|
|
8
|
+
const assertions = E.gen(function* (_) {
|
|
9
|
+
const service = yield* _(PrincipalService);
|
|
10
|
+
const result = yield* _(service.fetchPrincipal({ token: 'token' }));
|
|
11
|
+
expect(result).toEqual(Fixture.principal);
|
|
12
|
+
});
|
|
13
|
+
const effect = Fixture.buildEffect(assertions);
|
|
14
|
+
return E.runPromise(effect);
|
|
15
|
+
});
|
|
16
|
+
test('call the right url', () => {
|
|
17
|
+
const assertions = E.gen(function* (_) {
|
|
18
|
+
const service = yield* _(PrincipalService);
|
|
19
|
+
yield* _(service.fetchPrincipal({ token: 'myToken' }));
|
|
20
|
+
const state = yield* _(Fixture.State);
|
|
21
|
+
const args = yield* _(Ref.get(state));
|
|
22
|
+
expect(args?.hostname).toEqual('api.passlock.dev');
|
|
23
|
+
expect(args?.method).toEqual('GET');
|
|
24
|
+
expect(args?.path).toEqual(`/${Fixture.tenancyId}/token/myToken`);
|
|
25
|
+
});
|
|
26
|
+
const effect = Fixture.buildEffect(assertions);
|
|
27
|
+
return E.runPromise(effect);
|
|
28
|
+
});
|
|
29
|
+
test('pass the api key as a header', () => {
|
|
30
|
+
const assertions = E.gen(function* (_) {
|
|
31
|
+
const service = yield* _(PrincipalService);
|
|
32
|
+
yield* _(service.fetchPrincipal({ token: 'myToken' }));
|
|
33
|
+
const state = yield* _(Fixture.State);
|
|
34
|
+
const args = yield* _(Ref.get(state));
|
|
35
|
+
expect(args?.headers?.['X-API-KEY']).toEqual(Fixture.apiKey);
|
|
36
|
+
});
|
|
37
|
+
const effect = Fixture.buildEffect(assertions);
|
|
38
|
+
return E.runPromise(effect);
|
|
39
|
+
});
|
|
40
|
+
test('propagate a 401 error', () => {
|
|
41
|
+
const assertions = E.gen(function* (_) {
|
|
42
|
+
const service = yield* _(PrincipalService);
|
|
43
|
+
const result = service.fetchPrincipal({ token: 'myToken' });
|
|
44
|
+
const error = yield* _(Effect.flip(result));
|
|
45
|
+
expect(error).toBeInstanceOf(Unauthorized);
|
|
46
|
+
});
|
|
47
|
+
const effect = Fixture.buildErrorEffect(401)(assertions);
|
|
48
|
+
return E.runPromise(effect);
|
|
49
|
+
});
|
|
50
|
+
test('propagate a 403 error', () => {
|
|
51
|
+
const assertions = E.gen(function* (_) {
|
|
52
|
+
const service = yield* _(PrincipalService);
|
|
53
|
+
const result = service.fetchPrincipal({ token: 'myToken' });
|
|
54
|
+
const error = yield* _(Effect.flip(result));
|
|
55
|
+
expect(error).toBeInstanceOf(Forbidden);
|
|
56
|
+
});
|
|
57
|
+
const effect = Fixture.buildErrorEffect(403)(assertions);
|
|
58
|
+
return E.runPromise(effect);
|
|
59
|
+
});
|
|
60
|
+
test('propagate a 404 error', () => {
|
|
61
|
+
const assertions = E.gen(function* (_) {
|
|
62
|
+
const service = yield* _(PrincipalService);
|
|
63
|
+
const result = service.fetchPrincipal({ token: 'myToken' });
|
|
64
|
+
const error = yield* _(Effect.flip(result));
|
|
65
|
+
expect(error).toBeInstanceOf(NotFound);
|
|
66
|
+
});
|
|
67
|
+
const effect = Fixture.buildErrorEffect(404)(assertions);
|
|
68
|
+
return E.runPromise(effect);
|
|
69
|
+
});
|
|
70
|
+
test('propagate a 500 error', () => {
|
|
71
|
+
const assertions = E.gen(function* (_) {
|
|
72
|
+
const service = yield* _(PrincipalService);
|
|
73
|
+
const result = service.fetchPrincipal({ token: 'myToken' });
|
|
74
|
+
const error = yield* _(Effect.flip(result));
|
|
75
|
+
expect(error).toBeInstanceOf(InternalServerError);
|
|
76
|
+
});
|
|
77
|
+
const effect = Fixture.buildErrorEffect(500)(assertions);
|
|
78
|
+
return E.runPromise(effect);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=principal.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"principal.test.js","sourceRoot":"","sources":["../../src/principal/principal.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passlock/node",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.3",
|
|
5
5
|
"description": "Server side passkey library for node/express",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"passkey",
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
"email": "team@passlock.dev"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"effect": "2.4.
|
|
26
|
-
"@passlock/shared": "^0.9.
|
|
25
|
+
"effect": "2.4.17",
|
|
26
|
+
"@passlock/shared": "^0.9.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@tsconfig/
|
|
30
|
-
"@types/node": "^20.
|
|
31
|
-
"@typescript-eslint/eslint-plugin": "^7.
|
|
32
|
-
"@typescript-eslint/parser": "^7.
|
|
29
|
+
"@tsconfig/node18": "^18.2.4",
|
|
30
|
+
"@types/node": "^20.12.4",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
|
32
|
+
"@typescript-eslint/parser": "^7.5.0",
|
|
33
33
|
"@vitest/coverage-v8": "^1.4.0",
|
|
34
34
|
"@vitest/ui": "^1.4.0",
|
|
35
35
|
"eslint": "^8.57.0",
|
|
@@ -38,11 +38,10 @@
|
|
|
38
38
|
"eslint-plugin-import": "^2.29.1",
|
|
39
39
|
"prettier": "^3.2.5",
|
|
40
40
|
"rimraf": "^5.0.5",
|
|
41
|
-
"tsx": "^4.7.
|
|
42
|
-
"typescript": "^5.4.
|
|
43
|
-
"vite": "^5.2.
|
|
44
|
-
"vitest": "^1.4.0"
|
|
45
|
-
"vitest-mock-extended": "^1.3.1"
|
|
41
|
+
"tsx": "^4.7.2",
|
|
42
|
+
"typescript": "^5.4.3",
|
|
43
|
+
"vite": "^5.2.8",
|
|
44
|
+
"vitest": "^1.4.0"
|
|
46
45
|
},
|
|
47
46
|
"exports": {
|
|
48
47
|
".": {
|
package/src/config/config.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Context } from
|
|
1
|
+
import { Context } from 'effect'
|
|
2
2
|
|
|
3
|
-
export class Config extends Context.Tag(
|
|
3
|
+
export class Config extends Context.Tag('Config')<
|
|
4
4
|
Config,
|
|
5
|
-
{
|
|
6
|
-
readonly tenancyId: string
|
|
7
|
-
readonly apiKey: string
|
|
8
|
-
readonly endpoint?: string
|
|
5
|
+
{
|
|
6
|
+
readonly tenancyId: string
|
|
7
|
+
readonly apiKey: string
|
|
8
|
+
readonly endpoint?: string
|
|
9
9
|
}
|
|
10
|
-
>() {}
|
|
10
|
+
>() {}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
ErrorCode,
|
|
3
|
+
Forbidden,
|
|
4
|
+
InternalServerError,
|
|
5
|
+
NotFound,
|
|
6
|
+
Unauthorized,
|
|
7
|
+
} from '@passlock/shared/dist/error/error.js'
|
|
8
|
+
import { Effect as E, Layer as L, Runtime, Scope, pipe } from 'effect'
|
|
9
|
+
import { Config } from './config/config.js'
|
|
10
|
+
import {
|
|
11
|
+
type PrincipalRequest,
|
|
12
|
+
PrincipalService,
|
|
13
|
+
PrincipalServiceLive,
|
|
14
|
+
StreamResponseLive,
|
|
15
|
+
} from './principal/principal.js'
|
|
5
16
|
|
|
6
17
|
export type { PrincipalRequest } from './principal/principal.js'
|
|
7
18
|
|
|
8
|
-
export { ErrorCode } from '@passlock/shared/dist/error/error.js'
|
|
19
|
+
export { ErrorCode } from '@passlock/shared/dist/error/error.js'
|
|
9
20
|
|
|
10
21
|
export class PasslockError extends Error {
|
|
11
22
|
readonly _tag = 'PasslockError'
|
|
@@ -26,11 +37,7 @@ export class PasslockError extends Error {
|
|
|
26
37
|
}
|
|
27
38
|
}
|
|
28
39
|
|
|
29
|
-
type PasslockErrors =
|
|
30
|
-
| NotFound
|
|
31
|
-
| Unauthorized
|
|
32
|
-
| Forbidden
|
|
33
|
-
| InternalServerError
|
|
40
|
+
type PasslockErrors = NotFound | Unauthorized | Forbidden | InternalServerError
|
|
34
41
|
|
|
35
42
|
const hasMessage = (defect: unknown): defect is { message: string } => {
|
|
36
43
|
return (
|
|
@@ -48,7 +55,8 @@ const transformErrors = <A, R>(
|
|
|
48
55
|
NotFound: e => E.succeed(new PasslockError(e.message, ErrorCode.NotFound)),
|
|
49
56
|
Unauthorized: e => E.succeed(new PasslockError(e.message, ErrorCode.Unauthorized)),
|
|
50
57
|
Forbidden: e => E.succeed(new PasslockError(e.message, ErrorCode.Forbidden)),
|
|
51
|
-
InternalServerError: e =>
|
|
58
|
+
InternalServerError: e =>
|
|
59
|
+
E.succeed(new PasslockError(e.message, ErrorCode.InternalServerError)),
|
|
52
60
|
})
|
|
53
61
|
|
|
54
62
|
const sandboxed = E.sandbox(withErrorHandling)
|
|
@@ -88,8 +96,12 @@ export class PasslockUnsafe {
|
|
|
88
96
|
private readonly runtime: Runtime.Runtime<Requirements>
|
|
89
97
|
|
|
90
98
|
constructor(config: { tenancyId: string; apiKey: string; endpoint?: string }) {
|
|
91
|
-
const
|
|
92
|
-
const allLayers = pipe(
|
|
99
|
+
const configLive = L.succeed(Config, Config.of(config))
|
|
100
|
+
const allLayers = pipe(
|
|
101
|
+
PrincipalServiceLive,
|
|
102
|
+
L.provide(configLive),
|
|
103
|
+
L.provide(StreamResponseLive),
|
|
104
|
+
)
|
|
93
105
|
const scope = E.runSync(Scope.make())
|
|
94
106
|
this.runtime = E.runSync(L.toRuntime(allLayers).pipe(Scope.extend(scope)))
|
|
95
107
|
}
|
|
@@ -116,8 +128,12 @@ export class Passlock {
|
|
|
116
128
|
private readonly runtime: Runtime.Runtime<Requirements>
|
|
117
129
|
|
|
118
130
|
constructor(config: { tenancyId: string; apiKey: string; endpoint?: string }) {
|
|
119
|
-
const
|
|
120
|
-
const allLayers = pipe(
|
|
131
|
+
const configLive = L.succeed(Config, Config.of(config))
|
|
132
|
+
const allLayers = pipe(
|
|
133
|
+
PrincipalServiceLive,
|
|
134
|
+
L.provide(configLive),
|
|
135
|
+
L.provide(StreamResponseLive),
|
|
136
|
+
)
|
|
121
137
|
const scope = E.runSync(Scope.make())
|
|
122
138
|
this.runtime = E.runSync(L.toRuntime(allLayers).pipe(Scope.extend(scope)))
|
|
123
139
|
}
|
|
@@ -125,10 +141,7 @@ export class Passlock {
|
|
|
125
141
|
private readonly runPromise = <A, R extends Requirements>(
|
|
126
142
|
effect: E.Effect<A, PasslockErrors, R>,
|
|
127
143
|
) => {
|
|
128
|
-
return pipe(
|
|
129
|
-
transformErrors(effect),
|
|
130
|
-
effect => Runtime.runPromise(this.runtime)(effect)
|
|
131
|
-
)
|
|
144
|
+
return pipe(transformErrors(effect), effect => Runtime.runPromise(this.runtime)(effect))
|
|
132
145
|
}
|
|
133
146
|
|
|
134
147
|
fetchPrincipal = (request: PrincipalRequest) =>
|
|
@@ -137,4 +150,4 @@ export class Passlock {
|
|
|
137
150
|
E.flatMap(service => service.fetchPrincipal(request)),
|
|
138
151
|
effect => this.runPromise(effect),
|
|
139
152
|
)
|
|
140
|
-
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { RequestOptions } from 'https'
|
|
2
|
+
import type { Principal } from '@passlock/shared/dist/schema/schema.js'
|
|
3
|
+
import { Context, Effect as E, Layer as L, LogLevel, Logger, Ref, Stream, pipe } from 'effect'
|
|
4
|
+
import {
|
|
5
|
+
type PrincipalService,
|
|
6
|
+
PrincipalServiceLive,
|
|
7
|
+
StreamResponse,
|
|
8
|
+
buildError,
|
|
9
|
+
} from './principal.js'
|
|
10
|
+
import { Config } from '../config/config.js'
|
|
11
|
+
|
|
12
|
+
export const principal: Principal = {
|
|
13
|
+
token: 'token',
|
|
14
|
+
subject: {
|
|
15
|
+
id: '1',
|
|
16
|
+
email: 'john.doe@gmail.com',
|
|
17
|
+
firstName: 'john',
|
|
18
|
+
lastName: 'doe',
|
|
19
|
+
emailVerified: false,
|
|
20
|
+
},
|
|
21
|
+
authStatement: {
|
|
22
|
+
authType: 'email',
|
|
23
|
+
userVerified: false,
|
|
24
|
+
authTimestamp: new Date(0),
|
|
25
|
+
},
|
|
26
|
+
expireAt: new Date(0),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const tenancyId = 'tenancyId'
|
|
30
|
+
export const apiKey = 'apiKey'
|
|
31
|
+
|
|
32
|
+
export const configTest = L.succeed(Config, Config.of({ tenancyId, apiKey }))
|
|
33
|
+
|
|
34
|
+
export class State extends Context.Tag('State')<State, Ref.Ref<RequestOptions | undefined>>() {}
|
|
35
|
+
|
|
36
|
+
export const buildEffect = <A, E>(
|
|
37
|
+
assertions: E.Effect<A, E, PrincipalService | State>,
|
|
38
|
+
): E.Effect<void, E> => {
|
|
39
|
+
const responseStreamTest = L.effect(
|
|
40
|
+
StreamResponse,
|
|
41
|
+
E.gen(function* (_) {
|
|
42
|
+
const ref = yield* _(State)
|
|
43
|
+
const buff = Buffer.from(JSON.stringify(principal))
|
|
44
|
+
return options =>
|
|
45
|
+
pipe(Stream.fromEffect(Ref.set(ref, options)), Stream.zipRight(Stream.make(buff)))
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const service = pipe(PrincipalServiceLive, L.provide(responseStreamTest), L.provide(configTest))
|
|
50
|
+
|
|
51
|
+
const args = L.effect(State, Ref.make<RequestOptions | undefined>(undefined))
|
|
52
|
+
|
|
53
|
+
const effect = pipe(
|
|
54
|
+
E.provide(assertions, service),
|
|
55
|
+
E.provide(args),
|
|
56
|
+
Logger.withMinimumLogLevel(LogLevel.None),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return effect
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export const buildErrorEffect =
|
|
63
|
+
(statusCode: number) =>
|
|
64
|
+
<A>(assertions: E.Effect<void, A, PrincipalService>): E.Effect<void, A> => {
|
|
65
|
+
const responseStreamTest = L.succeed(StreamResponse, () =>
|
|
66
|
+
Stream.fail(buildError({ statusCode })),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
const service = pipe(PrincipalServiceLive, L.provide(responseStreamTest), L.provide(configTest))
|
|
70
|
+
|
|
71
|
+
const args = L.effect(State, Ref.make<RequestOptions | undefined>(undefined))
|
|
72
|
+
|
|
73
|
+
const effect = pipe(
|
|
74
|
+
E.provide(assertions, service),
|
|
75
|
+
E.provide(args),
|
|
76
|
+
Logger.withMinimumLogLevel(LogLevel.None),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return effect
|
|
80
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Forbidden,
|
|
3
|
+
InternalServerError,
|
|
4
|
+
NotFound,
|
|
5
|
+
Unauthorized,
|
|
6
|
+
} from '@passlock/shared/dist/error/error.js'
|
|
7
|
+
import { Effect as E, Effect, Ref } from 'effect'
|
|
8
|
+
import { describe, expect, test } from 'vitest'
|
|
9
|
+
import * as Fixture from './principal.fixture.js'
|
|
10
|
+
import { PrincipalService } from './principal.js'
|
|
11
|
+
|
|
12
|
+
describe('fetchPrincipal should', () => {
|
|
13
|
+
test('return a valid principal', () => {
|
|
14
|
+
const assertions = E.gen(function* (_) {
|
|
15
|
+
const service = yield* _(PrincipalService)
|
|
16
|
+
const result = yield* _(service.fetchPrincipal({ token: 'token' }))
|
|
17
|
+
|
|
18
|
+
expect(result).toEqual(Fixture.principal)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const effect = Fixture.buildEffect(assertions)
|
|
22
|
+
|
|
23
|
+
return E.runPromise(effect)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test('call the right url', () => {
|
|
27
|
+
const assertions = E.gen(function* (_) {
|
|
28
|
+
const service = yield* _(PrincipalService)
|
|
29
|
+
yield* _(service.fetchPrincipal({ token: 'myToken' }))
|
|
30
|
+
|
|
31
|
+
const state = yield* _(Fixture.State)
|
|
32
|
+
const args = yield* _(Ref.get(state))
|
|
33
|
+
|
|
34
|
+
expect(args?.hostname).toEqual('api.passlock.dev')
|
|
35
|
+
expect(args?.method).toEqual('GET')
|
|
36
|
+
expect(args?.path).toEqual(`/${Fixture.tenancyId}/token/myToken`)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const effect = Fixture.buildEffect(assertions)
|
|
40
|
+
|
|
41
|
+
return E.runPromise(effect)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('pass the api key as a header', () => {
|
|
45
|
+
const assertions = E.gen(function* (_) {
|
|
46
|
+
const service = yield* _(PrincipalService)
|
|
47
|
+
yield* _(service.fetchPrincipal({ token: 'myToken' }))
|
|
48
|
+
|
|
49
|
+
const state = yield* _(Fixture.State)
|
|
50
|
+
const args = yield* _(Ref.get(state))
|
|
51
|
+
|
|
52
|
+
expect(args?.headers?.['X-API-KEY']).toEqual(Fixture.apiKey)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const effect = Fixture.buildEffect(assertions)
|
|
56
|
+
|
|
57
|
+
return E.runPromise(effect)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('propagate a 401 error', () => {
|
|
61
|
+
const assertions = E.gen(function* (_) {
|
|
62
|
+
const service = yield* _(PrincipalService)
|
|
63
|
+
const result = service.fetchPrincipal({ token: 'myToken' })
|
|
64
|
+
const error = yield* _(Effect.flip(result))
|
|
65
|
+
expect(error).toBeInstanceOf(Unauthorized)
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const effect = Fixture.buildErrorEffect(401)(assertions)
|
|
69
|
+
|
|
70
|
+
return E.runPromise(effect)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('propagate a 403 error', () => {
|
|
74
|
+
const assertions = E.gen(function* (_) {
|
|
75
|
+
const service = yield* _(PrincipalService)
|
|
76
|
+
const result = service.fetchPrincipal({ token: 'myToken' })
|
|
77
|
+
const error = yield* _(Effect.flip(result))
|
|
78
|
+
expect(error).toBeInstanceOf(Forbidden)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const effect = Fixture.buildErrorEffect(403)(assertions)
|
|
82
|
+
|
|
83
|
+
return E.runPromise(effect)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test('propagate a 404 error', () => {
|
|
87
|
+
const assertions = E.gen(function* (_) {
|
|
88
|
+
const service = yield* _(PrincipalService)
|
|
89
|
+
const result = service.fetchPrincipal({ token: 'myToken' })
|
|
90
|
+
const error = yield* _(Effect.flip(result))
|
|
91
|
+
expect(error).toBeInstanceOf(NotFound)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
const effect = Fixture.buildErrorEffect(404)(assertions)
|
|
95
|
+
|
|
96
|
+
return E.runPromise(effect)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('propagate a 500 error', () => {
|
|
100
|
+
const assertions = E.gen(function* (_) {
|
|
101
|
+
const service = yield* _(PrincipalService)
|
|
102
|
+
const result = service.fetchPrincipal({ token: 'myToken' })
|
|
103
|
+
const error = yield* _(Effect.flip(result))
|
|
104
|
+
expect(error).toBeInstanceOf(InternalServerError)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
const effect = Fixture.buildErrorEffect(500)(assertions)
|
|
108
|
+
|
|
109
|
+
return E.runPromise(effect)
|
|
110
|
+
})
|
|
111
|
+
})
|
|
@@ -1,8 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Forbidden,
|
|
3
|
+
InternalServerError,
|
|
4
|
+
NotFound,
|
|
5
|
+
Unauthorized,
|
|
6
|
+
} from '@passlock/shared/dist/error/error.js'
|
|
2
7
|
import { Principal, createParser } from '@passlock/shared/dist/schema/schema.js'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
8
|
+
import type { StreamEmit } from 'effect'
|
|
9
|
+
import { Chunk, Console, Context, Effect as E, Layer, Option, Stream, flow, pipe } from 'effect'
|
|
10
|
+
import * as https from 'https'
|
|
11
|
+
import { Config } from '../config/config.js'
|
|
12
|
+
|
|
13
|
+
/* Dependencies */
|
|
14
|
+
|
|
15
|
+
export type StreamResponse = (
|
|
16
|
+
options: https.RequestOptions,
|
|
17
|
+
) => Stream.Stream<Buffer, PrincipalErrors>
|
|
18
|
+
export const StreamResponse = Context.GenericTag<StreamResponse>('@services/ResponseStream')
|
|
19
|
+
|
|
20
|
+
/* Service */
|
|
6
21
|
|
|
7
22
|
const parsePrincipal = createParser(Principal)
|
|
8
23
|
|
|
@@ -15,94 +30,122 @@ export type PrincipalService = {
|
|
|
15
30
|
|
|
16
31
|
export const PrincipalService = Context.GenericTag<PrincipalService>('@services/Principal')
|
|
17
32
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
/* Effects */
|
|
34
|
+
|
|
35
|
+
const buildHostname = (endpoint: string | undefined) => {
|
|
36
|
+
return new URL(endpoint || 'https://api.passlock.dev').hostname
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const buildOptions = (token: string) =>
|
|
40
|
+
pipe(
|
|
41
|
+
Config,
|
|
42
|
+
E.map(({ endpoint, tenancyId, apiKey }) => ({
|
|
43
|
+
hostname: buildHostname(endpoint),
|
|
44
|
+
port: 443,
|
|
45
|
+
path: `/${tenancyId}/token/${token}`,
|
|
46
|
+
method: 'GET',
|
|
47
|
+
headers: {
|
|
48
|
+
'Accept': 'application/json',
|
|
49
|
+
'X-API-KEY': apiKey,
|
|
50
|
+
},
|
|
51
|
+
})),
|
|
52
|
+
)
|
|
31
53
|
|
|
32
|
-
const buildError = (res: {
|
|
33
|
-
|
|
54
|
+
export const buildError = (res: {
|
|
55
|
+
statusCode?: number | undefined
|
|
56
|
+
statusMessage?: string | undefined
|
|
57
|
+
}) => {
|
|
58
|
+
if (res.statusCode === 404) return new NotFound({ message: 'Invalid token' })
|
|
34
59
|
if (res.statusCode === 401) return new Unauthorized({ message: 'Unauthorized' })
|
|
35
60
|
if (res.statusCode === 403) return new Forbidden({ message: 'Forbidden' })
|
|
36
61
|
|
|
37
|
-
if (res.statusCode && res.statusMessage)
|
|
38
|
-
|
|
39
|
-
|
|
62
|
+
if (res.statusCode && res.statusMessage)
|
|
63
|
+
return new InternalServerError({ message: `${String(res.statusCode)} - ${res.statusMessage}` })
|
|
64
|
+
|
|
65
|
+
if (res.statusCode) return new InternalServerError({ message: String(res.statusCode) })
|
|
66
|
+
|
|
67
|
+
if (res.statusMessage) return new InternalServerError({ message: res.statusMessage })
|
|
40
68
|
|
|
41
|
-
return new InternalServerError({ message: 'Received non 200 response'})
|
|
69
|
+
return new InternalServerError({ message: 'Received non 200 response' })
|
|
42
70
|
}
|
|
43
71
|
|
|
44
72
|
const fail = (error: PrincipalErrors) => E.fail(Option.some(error))
|
|
45
73
|
const succeed = (data: Buffer) => E.succeed(Chunk.of(data))
|
|
46
74
|
const close = E.fail(Option.none())
|
|
47
75
|
|
|
48
|
-
const buildStream = (token: string) =>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Stream.
|
|
52
|
-
|
|
53
|
-
if (200 !== res.statusCode) emit(fail(buildError(res)))
|
|
54
|
-
res.on('data', data => emit(succeed(data)))
|
|
55
|
-
res.on('close', () => emit(close))
|
|
56
|
-
res.on('error', (e) => emit(
|
|
57
|
-
fail(new InternalServerError({ message: e.message }))
|
|
58
|
-
))
|
|
59
|
-
}).end()
|
|
60
|
-
})
|
|
76
|
+
const buildStream = (token: string) =>
|
|
77
|
+
pipe(
|
|
78
|
+
Stream.fromEffect(buildOptions(token)),
|
|
79
|
+
Stream.zip(StreamResponse),
|
|
80
|
+
Stream.flatMap(([options, streamResponse]) => streamResponse(options)),
|
|
61
81
|
)
|
|
62
|
-
)
|
|
63
82
|
|
|
64
|
-
export const fetchPrincipal = (
|
|
83
|
+
export const fetchPrincipal = (
|
|
84
|
+
request: PrincipalRequest,
|
|
85
|
+
): E.Effect<Principal, PrincipalErrors, StreamResponse | Config> => {
|
|
65
86
|
const stream = buildStream(request.token)
|
|
66
87
|
|
|
67
88
|
const json = pipe(
|
|
68
|
-
Stream.runCollect(stream),
|
|
89
|
+
Stream.runCollect(stream),
|
|
69
90
|
E.map(Chunk.toReadonlyArray),
|
|
70
|
-
E.map(Buffer.concat),
|
|
71
|
-
E.flatMap(buffer =>
|
|
91
|
+
E.map(buffers => Buffer.concat(buffers)),
|
|
92
|
+
E.flatMap(buffer =>
|
|
72
93
|
E.try({
|
|
73
94
|
try: () => buffer.toString(),
|
|
74
|
-
catch:
|
|
75
|
-
|
|
95
|
+
catch: e =>
|
|
96
|
+
new InternalServerError({
|
|
97
|
+
message: 'Unable to convert response to string',
|
|
98
|
+
detail: String(e),
|
|
99
|
+
}),
|
|
100
|
+
}),
|
|
76
101
|
),
|
|
77
|
-
E.flatMap(buffer =>
|
|
102
|
+
E.flatMap(buffer =>
|
|
78
103
|
E.try({
|
|
79
|
-
try: () => JSON.parse(buffer),
|
|
80
|
-
catch:
|
|
81
|
-
|
|
104
|
+
try: () => JSON.parse(buffer) as unknown,
|
|
105
|
+
catch: e =>
|
|
106
|
+
new InternalServerError({
|
|
107
|
+
message: 'Unable to parse response to json',
|
|
108
|
+
detail: String(e),
|
|
109
|
+
}),
|
|
110
|
+
}),
|
|
82
111
|
),
|
|
83
|
-
E.
|
|
84
|
-
E.flatMap(json =>
|
|
112
|
+
E.flatMap(json =>
|
|
85
113
|
pipe(
|
|
86
|
-
parsePrincipal(json),
|
|
114
|
+
parsePrincipal(json),
|
|
87
115
|
E.tapError(error => Console.error(error.detail)),
|
|
88
|
-
E.mapError(
|
|
89
|
-
|
|
90
|
-
|
|
116
|
+
E.mapError(
|
|
117
|
+
() => new InternalServerError({ message: 'Unable to parse response as Principal' }),
|
|
118
|
+
),
|
|
119
|
+
),
|
|
120
|
+
),
|
|
91
121
|
)
|
|
92
|
-
|
|
122
|
+
|
|
93
123
|
return json
|
|
94
124
|
}
|
|
95
125
|
|
|
96
126
|
/* Live */
|
|
97
127
|
|
|
98
128
|
/* v8 ignore start */
|
|
129
|
+
export const StreamResponseLive = Layer.succeed(StreamResponse, options => {
|
|
130
|
+
return Stream.async((emit: StreamEmit.Emit<never, PrincipalErrors, Buffer, void>) => {
|
|
131
|
+
https
|
|
132
|
+
.request(options, res => {
|
|
133
|
+
if (200 !== res.statusCode) void emit(fail(buildError(res)))
|
|
134
|
+
res.on('data', (data: Buffer) => void emit(succeed(data)))
|
|
135
|
+
res.on('close', () => void emit(close))
|
|
136
|
+
res.on('error', e => void emit(fail(new InternalServerError({ message: e.message }))))
|
|
137
|
+
})
|
|
138
|
+
.end()
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
99
142
|
export const PrincipalServiceLive = Layer.effect(
|
|
100
143
|
PrincipalService,
|
|
101
144
|
E.gen(function* (_) {
|
|
102
|
-
const context = yield* _(E.context<Config>())
|
|
145
|
+
const context = yield* _(E.context<Config | StreamResponse>())
|
|
103
146
|
return PrincipalService.of({
|
|
104
147
|
fetchPrincipal: flow(fetchPrincipal, E.provide(context)),
|
|
105
148
|
})
|
|
106
149
|
}),
|
|
107
150
|
)
|
|
108
|
-
/* v8 ignore stop */
|
|
151
|
+
/* v8 ignore stop */
|