@bool-ts/guard-sdk 1.1.0-beta.1 → 1.1.0-beta.10
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/dist/decorators/index.d.ts +2 -0
- package/dist/definers/policies.d.ts +1 -1
- package/dist/definers/resources.d.ts +8 -5
- package/dist/entities/@validators.d.ts +6 -0
- package/dist/entities/guard.d.ts +7 -0
- package/dist/entities/index.d.ts +1 -2
- package/dist/entities/loader.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +36 -17
- package/dist/index.js.map +42 -40
- package/dist/types/actionGuard.d.ts +3 -3
- package/dist/types/controllerGuard.d.ts +3 -3
- package/dist/types/policies.d.ts +3 -3
- package/dist/types/resources.d.ts +1 -1
- package/dist/ultils/functions/deepFreeze.d.ts +2 -7
- package/dist/ultils/types/deepReadonly.d.ts +5 -0
- package/dist/ultils/types/enforceUnique.d.ts +1 -1
- package/dist/ultils/types/index.d.ts +1 -0
- package/dist/ultils/types/partialTuple.d.ts +4 -1
- package/dist/ultils/types/partialTurpleNonEmpty.d.ts +1 -4
- package/package.json +8 -8
- package/src/decorators/actionGuard.decorator.ts +2 -1
- package/src/decorators/index.ts +2 -0
- package/src/definers/policies.ts +1 -0
- package/src/definers/resources.ts +35 -6
- package/src/entities/@validators.ts +22 -0
- package/src/entities/guard.ts +81 -0
- package/src/entities/index.ts +1 -2
- package/src/entities/loader.ts +1 -1
- package/src/index.ts +1 -0
- package/src/interfaces/account.interface.ts +4 -1
- package/src/interfaces/base.ts +5 -1
- package/src/interfaces/client.interface.ts +1 -3
- package/src/interfaces/index.ts +6 -2
- package/src/types/actionGuard.ts +3 -3
- package/src/types/controllerGuard.ts +3 -3
- package/src/types/policies.ts +3 -3
- package/src/types/resources.ts +1 -1
- package/src/ultils/functions/deepFreeze.ts +2 -8
- package/src/ultils/types/deepReadonly.ts +7 -0
- package/src/ultils/types/enforceUnique.ts +4 -1
- package/src/ultils/types/inArray.ts +4 -4
- package/src/ultils/types/index.ts +1 -0
- package/src/ultils/types/partialTuple.ts +4 -1
- package/src/ultils/types/partialTupleUnordered.ts +6 -5
- package/src/ultils/types/partialTurpleNonEmpty.ts +4 -6
- package/src/ultils/types/permutationTuple.ts +2 -2
- package/dist/entities/interceptor.d.ts +0 -5
- package/dist/entities/middleware.d.ts +0 -19
- package/src/entities/interceptor.ts +0 -47
- package/src/entities/middleware.ts +0 -73
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { TOptionalTupleUnorderedNonEmpty } from "../ultils/types";
|
|
2
2
|
import type { TResourceDefinition } from "./resources";
|
|
3
3
|
export type TActionGuardOptions<T extends readonly TResourceDefinition[]> = {
|
|
4
|
-
[R in T[number] as R["
|
|
5
|
-
resource: R["
|
|
4
|
+
[R in T[number] as R["alias"]]: {
|
|
5
|
+
resource: R["alias"];
|
|
6
6
|
action: R["actions"][number] | TOptionalTupleUnorderedNonEmpty<R["actions"]>;
|
|
7
7
|
};
|
|
8
|
-
}[T[number]["
|
|
8
|
+
}[T[number]["alias"]];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TResourceDefinition } from "./resources";
|
|
2
2
|
export type TControllerGuardOptions<T extends readonly TResourceDefinition[]> = {
|
|
3
|
-
[R in T[number] as R["
|
|
4
|
-
resource: R["
|
|
3
|
+
[R in T[number] as R["alias"]]: {
|
|
4
|
+
resource: R["alias"];
|
|
5
5
|
};
|
|
6
|
-
}[T[number]["
|
|
6
|
+
}[T[number]["alias"]];
|
package/dist/types/policies.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export type TPolicyDefinition<T extends readonly TResourceDefinition[] = readonl
|
|
|
4
4
|
readonly effect: "permit" | "deny";
|
|
5
5
|
readonly [key: string]: unknown;
|
|
6
6
|
} & {
|
|
7
|
-
[R in T[number] as R["
|
|
8
|
-
readonly resource: R["
|
|
7
|
+
[R in T[number] as R["alias"]]: {
|
|
8
|
+
readonly resource: R["alias"];
|
|
9
9
|
readonly action: R["actions"][number];
|
|
10
10
|
};
|
|
11
|
-
}[T[number]["
|
|
11
|
+
}[T[number]["alias"]];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TNonEmptyArray } from "../ultils/types";
|
|
2
2
|
export type TResourceDefinition<T extends string = string, A extends TNonEmptyArray<string> = TNonEmptyArray<string>> = {
|
|
3
|
-
readonly
|
|
3
|
+
readonly alias: T;
|
|
4
4
|
readonly actions: A;
|
|
5
5
|
readonly [key: string]: unknown;
|
|
6
6
|
};
|
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
type
|
|
2
|
-
|
|
3
|
-
} : T extends object ? {
|
|
4
|
-
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
5
|
-
} : T;
|
|
6
|
-
export declare function deepFreeze<const T>(obj: T): DeepReadonly<T>;
|
|
7
|
-
export {};
|
|
1
|
+
import type { TDeepReadonly } from "../types";
|
|
2
|
+
export declare function deepFreeze<const T>(obj: T): TDeepReadonly<T>;
|
|
@@ -4,5 +4,5 @@ type ValuesOfKey<Arr extends any[], K extends keyof any> = Arr extends [
|
|
|
4
4
|
] ? Head extends Record<K, any> ? [Head[K], ...ValuesOfKey<Tail, K>] : ValuesOfKey<Tail, K> : [];
|
|
5
5
|
type Includes<Arr extends any[], V> = Arr extends [infer H, ...infer R] ? [V] extends [H] ? true : Includes<R, V> : false;
|
|
6
6
|
type HasDuplicate<Arr extends readonly any[], K extends keyof any> = Arr extends [infer Head, ...infer Tail] ? Head extends Record<K, any> ? Includes<ValuesOfKey<Tail, K>, Head[K]> extends true ? true : HasDuplicate<Tail, K> : HasDuplicate<Tail, K> : false;
|
|
7
|
-
export type TEnforceUnique<Arr extends readonly any[], K extends keyof Arr[number]> = HasDuplicate<Arr, K> extends true ?
|
|
7
|
+
export type TEnforceUnique<Arr extends readonly any[], K extends keyof Arr[number]> = HasDuplicate<Arr, K> extends true ? `Duplicate key "${K & string}" found` : Arr;
|
|
8
8
|
export {};
|
|
@@ -1 +1,4 @@
|
|
|
1
|
-
export type TPartialTuple<T extends readonly any[]> = T extends readonly [
|
|
1
|
+
export type TPartialTuple<T extends readonly any[]> = T extends readonly [
|
|
2
|
+
infer Head,
|
|
3
|
+
...infer Tail
|
|
4
|
+
] ? TPartialTuple<Tail> | [Head, ...TPartialTuple<Tail>] : [];
|
|
@@ -1,5 +1,2 @@
|
|
|
1
1
|
import type { TPartialTuple } from "./partialTuple";
|
|
2
|
-
export type TPartialTupleNonEmpty<T extends readonly any[]> = T extends readonly [
|
|
3
|
-
infer Head,
|
|
4
|
-
...infer Tail
|
|
5
|
-
] ? [Head, ...TPartialTuple<Tail>] | TPartialTupleNonEmpty<Tail> : never;
|
|
2
|
+
export type TPartialTupleNonEmpty<T extends readonly any[]> = T extends readonly [infer Head, ...infer Tail] ? [Head, ...TPartialTuple<Tail>] | TPartialTupleNonEmpty<Tail> : never;
|
package/package.json
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
"url": "https://github.com/BoolTS/guard-sdk/issues"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"jose": "^6.1
|
|
8
|
-
"
|
|
7
|
+
"jose": "^6.2.1",
|
|
8
|
+
"reflect-metadata": "^0.2.2",
|
|
9
|
+
"zod": "^4.3.6"
|
|
9
10
|
},
|
|
10
11
|
"devDependencies": {
|
|
12
|
+
"@bool-ts/core": "^2.3.3",
|
|
11
13
|
"@types/bun": "latest",
|
|
14
|
+
"prettier": "^3.8.1",
|
|
12
15
|
"typescript": "^5.9.3"
|
|
13
16
|
},
|
|
14
17
|
"files": [
|
|
@@ -29,10 +32,6 @@
|
|
|
29
32
|
"license": "MIT",
|
|
30
33
|
"main": "./dist/index.js",
|
|
31
34
|
"name": "@bool-ts/guard-sdk",
|
|
32
|
-
"peerDependencies": {
|
|
33
|
-
"@bool-ts/core": "^2.0.4",
|
|
34
|
-
"reflect-metadata": "^0.2.2"
|
|
35
|
-
},
|
|
36
35
|
"private": false,
|
|
37
36
|
"publishConfig": {
|
|
38
37
|
"access": "public"
|
|
@@ -42,9 +41,10 @@
|
|
|
42
41
|
"url": "git+https://github.com/BoolTS/guard-sdk.git"
|
|
43
42
|
},
|
|
44
43
|
"scripts": {
|
|
45
|
-
"build": "tsc --emitDeclarationOnly && bun run app.build.ts",
|
|
44
|
+
"build": "tsc --emitDeclarationOnly && bun run ./app.build.ts",
|
|
45
|
+
"format": "prettier \"**/*.ts\" --write",
|
|
46
46
|
"test": "bun --hot run __test/index.ts"
|
|
47
47
|
},
|
|
48
48
|
"types": "./dist/index.d.ts",
|
|
49
|
-
"version": "1.1.0-beta.
|
|
49
|
+
"version": "1.1.0-beta.10"
|
|
50
50
|
}
|
|
@@ -5,7 +5,8 @@ import { Keys } from "../constants";
|
|
|
5
5
|
|
|
6
6
|
export const ActionGuard =
|
|
7
7
|
<
|
|
8
|
-
const T extends readonly TResourceDefinition[] =
|
|
8
|
+
const T extends readonly TResourceDefinition[] =
|
|
9
|
+
readonly TResourceDefinition[],
|
|
9
10
|
K extends TConstructor<Object> | Object = Object
|
|
10
11
|
>(
|
|
11
12
|
options?: TActionGuardOptions<T>
|
package/src/decorators/index.ts
CHANGED
package/src/definers/policies.ts
CHANGED
|
@@ -1,29 +1,58 @@
|
|
|
1
1
|
import type { TPolicyDefinition, TResourceDefinition } from "../types";
|
|
2
|
-
import type { TEnforceUnique } from "../ultils/types";
|
|
2
|
+
import type { TDeepReadonly, TEnforceUnique } from "../ultils/types";
|
|
3
3
|
|
|
4
4
|
import { deepFreeze } from "../ultils/functions";
|
|
5
5
|
|
|
6
|
-
export const defineResources = <
|
|
7
|
-
|
|
6
|
+
export const defineResources = <
|
|
7
|
+
const T extends readonly TResourceDefinition[],
|
|
8
|
+
D extends TDeepReadonly<T>
|
|
9
|
+
>(
|
|
10
|
+
resources: TEnforceUnique<T, "alias">
|
|
8
11
|
) => {
|
|
9
12
|
if (
|
|
13
|
+
resources === `Duplicate key "alias" found` ||
|
|
10
14
|
new Set([
|
|
11
15
|
...resources
|
|
12
16
|
.map((resource) =>
|
|
13
|
-
typeof resource === "string" ? undefined : resource.
|
|
17
|
+
typeof resource === "string" ? undefined : resource.alias
|
|
14
18
|
)
|
|
15
19
|
.filter((resourceType) => typeof resourceType !== "undefined")
|
|
16
20
|
]).size !== resources.length
|
|
17
21
|
) {
|
|
18
|
-
throw new Error("Duplicated resource
|
|
22
|
+
throw new Error("Duplicated resource alias.");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const resourceFreezed = deepFreeze(resources);
|
|
26
|
+
|
|
27
|
+
if (resourceFreezed === `Duplicate key "alias" found`) {
|
|
28
|
+
throw new Error("Duplicated resource alias.");
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
return Object.freeze({
|
|
22
|
-
|
|
32
|
+
getResource: <
|
|
33
|
+
K extends D extends never ? never : D[number]["alias"],
|
|
34
|
+
R extends D extends never ? never : Extract<D[number], { alias: K }>
|
|
35
|
+
>(
|
|
36
|
+
alias: K
|
|
37
|
+
): R => {
|
|
38
|
+
const index = resourceFreezed.findIndex(
|
|
39
|
+
({ alias: resourceAlias }) => alias === resourceAlias
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (index === -1) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"Resource not found, intialize resources error."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return resourceFreezed[index] as R;
|
|
49
|
+
},
|
|
50
|
+
resources: resourceFreezed,
|
|
23
51
|
definePolicies: <const K extends readonly TPolicyDefinition<T>[]>(
|
|
24
52
|
policies: TEnforceUnique<K, "alias">
|
|
25
53
|
) => {
|
|
26
54
|
if (
|
|
55
|
+
policies === `Duplicate key "alias" found` ||
|
|
27
56
|
new Set([
|
|
28
57
|
...policies
|
|
29
58
|
.map((policy) =>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jwt, NEVER, object, string } from "zod/v4";
|
|
2
|
+
|
|
3
|
+
export const headersSchema = object({
|
|
4
|
+
authorization: string()
|
|
5
|
+
.startsWith("Bearer ")
|
|
6
|
+
.transform((value, ctx) => {
|
|
7
|
+
const [schema, token] = value.split(" ");
|
|
8
|
+
|
|
9
|
+
const jwtValidation = jwt().safeParse(token);
|
|
10
|
+
|
|
11
|
+
if (!jwtValidation.success) {
|
|
12
|
+
ctx.addIssue("Token must be match jsonwebtoken format.");
|
|
13
|
+
|
|
14
|
+
return NEVER;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
schema,
|
|
19
|
+
token
|
|
20
|
+
});
|
|
21
|
+
})
|
|
22
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { IContext, IGuard, THttpRouteModel } from "@bool-ts/core";
|
|
2
|
+
import type { IClient, TAuthState } from "../interfaces/client.interface";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Guard as BoolTsGuard,
|
|
6
|
+
Context,
|
|
7
|
+
Inject,
|
|
8
|
+
RequestHeaders,
|
|
9
|
+
RouteModel
|
|
10
|
+
} from "@bool-ts/core";
|
|
11
|
+
import { Keys } from "../constants";
|
|
12
|
+
import { headersSchema } from "./@validators";
|
|
13
|
+
|
|
14
|
+
@BoolTsGuard()
|
|
15
|
+
export class Guard implements IGuard {
|
|
16
|
+
constructor(
|
|
17
|
+
@Inject(Keys.guardClient)
|
|
18
|
+
private readonly clientInstance: IClient | undefined
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
async enforce(
|
|
22
|
+
@RouteModel()
|
|
23
|
+
routeModel: THttpRouteModel,
|
|
24
|
+
@RequestHeaders()
|
|
25
|
+
requestHeaders: Headers,
|
|
26
|
+
@Context()
|
|
27
|
+
context: IContext
|
|
28
|
+
) {
|
|
29
|
+
if (!this.clientInstance) {
|
|
30
|
+
throw new Error("Bool guard instance not found.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const actionMetadataKeys = Reflect.getOwnMetadataKeys(
|
|
34
|
+
routeModel.class,
|
|
35
|
+
routeModel.funcName
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const controllerMetadataKeys = Reflect.getOwnMetadataKeys(
|
|
39
|
+
routeModel.class
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const isAuthAction = actionMetadataKeys.includes(Keys.guardMetadata);
|
|
43
|
+
const isAuthController = controllerMetadataKeys.includes(
|
|
44
|
+
Keys.guardMetadata
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
if (!isAuthAction && !isAuthController) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const headersValidation = await headersSchema.safeParseAsync(
|
|
52
|
+
requestHeaders.toJSON()
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
if (!headersValidation.success) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const {
|
|
61
|
+
authorization: { token }
|
|
62
|
+
} = headersValidation.data;
|
|
63
|
+
|
|
64
|
+
const { account, credential } =
|
|
65
|
+
await this.clientInstance.verifyToken({
|
|
66
|
+
token: token
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const authState: TAuthState = Object.freeze({
|
|
70
|
+
account: account,
|
|
71
|
+
credential: credential
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
context.set(Keys.authState, authState);
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
} catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/entities/index.ts
CHANGED
package/src/entities/loader.ts
CHANGED
|
@@ -17,7 +17,7 @@ export const loader = async ({
|
|
|
17
17
|
credential,
|
|
18
18
|
definition,
|
|
19
19
|
options
|
|
20
|
-
}: TLoaderParameters) => {
|
|
20
|
+
}: TLoaderParameters): Promise<[symbol, Client]> => {
|
|
21
21
|
const boolGuardClient = new Client({ credential, definition, options });
|
|
22
22
|
|
|
23
23
|
await boolGuardClient.signToken();
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export type TDefaultAccountMetadata = Record<
|
|
1
|
+
export type TDefaultAccountMetadata = Record<
|
|
2
|
+
string,
|
|
3
|
+
string | number | Date | null | undefined
|
|
4
|
+
>;
|
|
2
5
|
|
|
3
6
|
export interface IAccount<T = TDefaultAccountMetadata> {
|
|
4
7
|
uuid: string;
|
package/src/interfaces/base.ts
CHANGED
|
@@ -50,9 +50,7 @@ export interface IClient<
|
|
|
50
50
|
account: IAccount<TAccountMetadata>;
|
|
51
51
|
credential: IAccountCredential;
|
|
52
52
|
}>;
|
|
53
|
-
verifyToken(args: {
|
|
54
|
-
token: string;
|
|
55
|
-
}): Promise<{
|
|
53
|
+
verifyToken(args: { token: string }): Promise<{
|
|
56
54
|
account: IAccount<TAccountMetadata>;
|
|
57
55
|
credential: IAccountCredential;
|
|
58
56
|
}>;
|
package/src/interfaces/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export type { IAccount } from "./account.interface";
|
|
2
2
|
export type { IAccountCredential } from "./accountCredential.interface";
|
|
3
3
|
export type { TApiResponse } from "./base";
|
|
4
|
-
export type {
|
|
5
|
-
|
|
4
|
+
export type {
|
|
5
|
+
IClient,
|
|
6
|
+
TAuthState,
|
|
7
|
+
TClientCredential as TClientConfigs,
|
|
8
|
+
TClientOptions
|
|
9
|
+
} from "./client.interface";
|
package/src/types/actionGuard.ts
CHANGED
|
@@ -2,10 +2,10 @@ import type { TOptionalTupleUnorderedNonEmpty } from "../ultils/types";
|
|
|
2
2
|
import type { TResourceDefinition } from "./resources";
|
|
3
3
|
|
|
4
4
|
export type TActionGuardOptions<T extends readonly TResourceDefinition[]> = {
|
|
5
|
-
[R in T[number] as R["
|
|
6
|
-
resource: R["
|
|
5
|
+
[R in T[number] as R["alias"]]: {
|
|
6
|
+
resource: R["alias"];
|
|
7
7
|
action:
|
|
8
8
|
| R["actions"][number]
|
|
9
9
|
| TOptionalTupleUnorderedNonEmpty<R["actions"]>;
|
|
10
10
|
};
|
|
11
|
-
}[T[number]["
|
|
11
|
+
}[T[number]["alias"]];
|
|
@@ -2,7 +2,7 @@ import type { TResourceDefinition } from "./resources";
|
|
|
2
2
|
|
|
3
3
|
export type TControllerGuardOptions<T extends readonly TResourceDefinition[]> =
|
|
4
4
|
{
|
|
5
|
-
[R in T[number] as R["
|
|
6
|
-
resource: R["
|
|
5
|
+
[R in T[number] as R["alias"]]: {
|
|
6
|
+
resource: R["alias"];
|
|
7
7
|
};
|
|
8
|
-
}[T[number]["
|
|
8
|
+
}[T[number]["alias"]];
|
package/src/types/policies.ts
CHANGED
|
@@ -7,11 +7,11 @@ export type TPolicyDefinition<
|
|
|
7
7
|
readonly effect: "permit" | "deny";
|
|
8
8
|
readonly [key: string]: unknown;
|
|
9
9
|
} & {
|
|
10
|
-
[R in T[number] as R["
|
|
11
|
-
readonly resource: R["
|
|
10
|
+
[R in T[number] as R["alias"]]: {
|
|
11
|
+
readonly resource: R["alias"];
|
|
12
12
|
readonly action: R["actions"][number];
|
|
13
13
|
};
|
|
14
|
-
}[T[number]["
|
|
14
|
+
}[T[number]["alias"]];
|
|
15
15
|
|
|
16
16
|
// export type TPolicyAttributes<
|
|
17
17
|
// T extends readonly TResourceDefinition[],
|
package/src/types/resources.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
type
|
|
2
|
-
? T
|
|
3
|
-
: T extends readonly any[]
|
|
4
|
-
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
|
|
5
|
-
: T extends object
|
|
6
|
-
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
|
|
7
|
-
: T;
|
|
1
|
+
import type { TDeepReadonly } from "../types";
|
|
8
2
|
|
|
9
|
-
export function deepFreeze<const T>(obj: T):
|
|
3
|
+
export function deepFreeze<const T>(obj: T): TDeepReadonly<T> {
|
|
10
4
|
if (typeof obj !== "object" || obj === null) return obj as any;
|
|
11
5
|
Object.freeze(obj);
|
|
12
6
|
for (const key of Object.keys(obj)) {
|
|
@@ -27,4 +27,7 @@ type HasDuplicate<
|
|
|
27
27
|
export type TEnforceUnique<
|
|
28
28
|
Arr extends readonly any[],
|
|
29
29
|
K extends keyof Arr[number]
|
|
30
|
-
> =
|
|
30
|
+
> =
|
|
31
|
+
HasDuplicate<Arr, K> extends true
|
|
32
|
+
? `Duplicate key "${K & string}" found`
|
|
33
|
+
: Arr;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type TInArray<T, X> = T extends readonly [X, ...infer _Rest]
|
|
2
2
|
? true
|
|
3
3
|
: T extends readonly [X]
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
? true
|
|
5
|
+
: T extends readonly [infer _, ...infer Rest]
|
|
6
|
+
? TInArray<Rest, X>
|
|
7
|
+
: false;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
export type TPartialTuple<T extends readonly any[]> = T extends readonly [
|
|
1
|
+
export type TPartialTuple<T extends readonly any[]> = T extends readonly [
|
|
2
|
+
infer Head,
|
|
3
|
+
...infer Tail
|
|
4
|
+
]
|
|
2
5
|
? TPartialTuple<Tail> | [Head, ...TPartialTuple<Tail>]
|
|
3
6
|
: [];
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { TPartialTuple } from "./partialTuple";
|
|
2
2
|
import type { TPermutationTuple } from "./permutationTuple";
|
|
3
3
|
|
|
4
|
-
export type TPartialTupleUnordered<T extends readonly any[]> =
|
|
5
|
-
|
|
6
|
-
?
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export type TPartialTupleUnordered<T extends readonly any[]> =
|
|
5
|
+
TPartialTuple<T> extends infer S
|
|
6
|
+
? S extends readonly any[]
|
|
7
|
+
? TPermutationTuple<S[number]>
|
|
8
|
+
: never
|
|
9
|
+
: never;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { TPartialTuple } from "./partialTuple";
|
|
2
2
|
|
|
3
|
-
export type TPartialTupleNonEmpty<T extends readonly any[]> =
|
|
4
|
-
infer Head,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
? [Head, ...TPartialTuple<Tail>] | TPartialTupleNonEmpty<Tail>
|
|
8
|
-
: never;
|
|
3
|
+
export type TPartialTupleNonEmpty<T extends readonly any[]> =
|
|
4
|
+
T extends readonly [infer Head, ...infer Tail]
|
|
5
|
+
? [Head, ...TPartialTuple<Tail>] | TPartialTupleNonEmpty<Tail>
|
|
6
|
+
: never;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { IContext, IMiddleware } from "@bool-ts/core";
|
|
2
|
-
import type { IClient } from "../interfaces/client.interface";
|
|
3
|
-
/**
|
|
4
|
-
* Bool guard middleware for Bool Typescript framework
|
|
5
|
-
*/
|
|
6
|
-
export declare class Middleware implements IMiddleware {
|
|
7
|
-
private readonly clientInstance;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* @param tenantAppModesService
|
|
11
|
-
*/
|
|
12
|
-
constructor(clientInstance: IClient);
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
* @param context
|
|
16
|
-
* @param requestHeaders
|
|
17
|
-
*/
|
|
18
|
-
start(context: IContext, requestHeaders: Headers): Promise<ThisType<IContext>>;
|
|
19
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { IInterceptor, THttpRouteModel } from "@bool-ts/core";
|
|
2
|
-
import type { TAuthState } from "../interfaces/client.interface";
|
|
3
|
-
|
|
4
|
-
import { Interceptor as BoolInterceptor, HttpClientError, RouteModel } from "@bool-ts/core";
|
|
5
|
-
import { Keys } from "../constants";
|
|
6
|
-
import { AuthState } from "../decorators/authState.decorator";
|
|
7
|
-
|
|
8
|
-
@BoolInterceptor()
|
|
9
|
-
export class Interceptor implements IInterceptor {
|
|
10
|
-
open(
|
|
11
|
-
@RouteModel()
|
|
12
|
-
routeModel: THttpRouteModel,
|
|
13
|
-
@AuthState()
|
|
14
|
-
authState: TAuthState
|
|
15
|
-
) {
|
|
16
|
-
const actionMetadataKeys = Reflect.getOwnMetadataKeys(
|
|
17
|
-
routeModel.class.prototype,
|
|
18
|
-
routeModel.funcName
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
if (actionMetadataKeys.includes(Keys.authState)) {
|
|
22
|
-
if (!authState) {
|
|
23
|
-
throw new HttpClientError({
|
|
24
|
-
httpCode: 401,
|
|
25
|
-
message: "Unauthorized",
|
|
26
|
-
data: undefined
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const controllerMetadataKeys = Reflect.getOwnMetadataKeys(routeModel.class);
|
|
34
|
-
|
|
35
|
-
if (controllerMetadataKeys.includes(Keys.authState)) {
|
|
36
|
-
if (!authState) {
|
|
37
|
-
throw new HttpClientError({
|
|
38
|
-
httpCode: 401,
|
|
39
|
-
message: "Unauthorized",
|
|
40
|
-
data: undefined
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|