@bool-ts/guard-sdk 1.1.0-beta.11 → 1.1.0-beta.13
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/definers/resources.d.ts +14 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -17
- package/dist/index.js.map +3 -3
- package/dist/types/actionGuard.d.ts +1 -1
- package/dist/types/controllerGuard.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/roles.d.ts +14 -0
- package/dist/ultils/types/enforceUnique.d.ts +6 -4
- package/package.json +3 -3
- package/src/definers/resources.ts +60 -3
- package/src/index.ts +1 -0
- package/src/types/actionGuard.ts +3 -1
- package/src/types/controllerGuard.ts +7 -6
- package/src/types/index.ts +1 -0
- package/src/types/policies.ts +0 -22
- package/src/types/roles.ts +26 -0
- package/src/ultils/types/enforceUnique.ts +15 -18
- package/dist/definers/policies.d.ts +0 -5
- package/src/definers/policies.ts +0 -24
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TOptionalTupleUnorderedNonEmpty } from "../ultils/types";
|
|
2
2
|
import type { TResourceDefinition } from "./resources";
|
|
3
|
-
export type TActionGuardOptions<T extends readonly TResourceDefinition[]> = {
|
|
3
|
+
export type TActionGuardOptions<T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]> = {
|
|
4
4
|
[R in T[number] as R["alias"]]: {
|
|
5
5
|
resource: R["alias"];
|
|
6
6
|
action: R["actions"][number] | TOptionalTupleUnorderedNonEmpty<R["actions"]>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TResourceDefinition } from "./resources";
|
|
2
|
-
export type TControllerGuardOptions<T extends readonly TResourceDefinition[]> = {
|
|
2
|
+
export type TControllerGuardOptions<T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]> = {
|
|
3
3
|
[R in T[number] as R["alias"]]: {
|
|
4
4
|
resource: R["alias"];
|
|
5
5
|
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TEnforceUnique, TOptionalTupleUnorderedNonEmpty } from "../ultils/types";
|
|
2
|
+
import type { TResourceDefinition } from "./resources";
|
|
3
|
+
export type TRolePermissionDefinition<T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]> = {
|
|
4
|
+
[R in T[number] as R["alias"]]: {
|
|
5
|
+
readonly resource: R["alias"];
|
|
6
|
+
readonly actions: TOptionalTupleUnorderedNonEmpty<R["actions"]>;
|
|
7
|
+
};
|
|
8
|
+
}[T[number]["alias"]];
|
|
9
|
+
export type TRoleDefinition<T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]> = {
|
|
10
|
+
readonly alias: string;
|
|
11
|
+
readonly [key: string]: unknown;
|
|
12
|
+
} & {
|
|
13
|
+
readonly permissions: TEnforceUnique<Array<TRolePermissionDefinition<T>>, "resource">;
|
|
14
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
type IsDuplicated<
|
|
2
|
-
[I in keyof
|
|
1
|
+
type IsDuplicated<P extends readonly any[], K extends string, Index extends string> = {
|
|
2
|
+
[I in keyof P]: I extends Index ? never : P[I] extends Record<K, any> ? Index extends keyof P ? P[Index] extends Record<K, any> ? P[I][K] extends P[Index][K] ? true : never : never : never : never;
|
|
3
3
|
}[number] extends never ? false : true;
|
|
4
|
-
export type TEnforceUnique<
|
|
5
|
-
[I in keyof
|
|
4
|
+
export type TEnforceUnique<A extends readonly any[], K extends string> = {
|
|
5
|
+
[I in keyof A]: IsDuplicated<A, K, I & string> extends true ? A[I] & {
|
|
6
|
+
readonly __error: `Error: Duplicate value "${A[I] extends Record<K, any> ? A[I][K] : ""}" at key "${K}"`;
|
|
7
|
+
} : A[I];
|
|
6
8
|
};
|
|
7
9
|
export {};
|
package/package.json
CHANGED
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"url": "git+https://github.com/BoolTS/guard-sdk.git"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
|
-
"build": "tsc --
|
|
45
|
-
"format": "prettier \"
|
|
44
|
+
"build": "tsc --noEmit && bun run ./app.build.ts && tsc --emitDeclarationOnly",
|
|
45
|
+
"format": "prettier \"./src/**/*.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.13"
|
|
50
50
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TPolicyDefinition,
|
|
3
|
+
TResourceDefinition,
|
|
4
|
+
TRoleDefinition
|
|
5
|
+
} from "../types";
|
|
2
6
|
import type { TDeepReadonly, TEnforceUnique } from "../ultils/types";
|
|
3
7
|
|
|
4
8
|
import { deepFreeze } from "../ultils/functions";
|
|
@@ -24,6 +28,7 @@ export const defineResources = <
|
|
|
24
28
|
const resourceFreezed = deepFreeze(resources);
|
|
25
29
|
|
|
26
30
|
return Object.freeze({
|
|
31
|
+
resources: resourceFreezed,
|
|
27
32
|
getResource: <
|
|
28
33
|
K extends D extends never ? never : D[number]["alias"],
|
|
29
34
|
R extends Extract<D[number], { alias: K }>
|
|
@@ -42,9 +47,8 @@ export const defineResources = <
|
|
|
42
47
|
|
|
43
48
|
return resourceFreezed[index] as R;
|
|
44
49
|
},
|
|
45
|
-
resources: resourceFreezed,
|
|
46
50
|
definePolicies: <const K extends readonly TPolicyDefinition<T>[]>(
|
|
47
|
-
policies:
|
|
51
|
+
policies: TEnforceUnique<K, "alias">
|
|
48
52
|
) => {
|
|
49
53
|
if (
|
|
50
54
|
new Set([
|
|
@@ -65,6 +69,59 @@ export const defineResources = <
|
|
|
65
69
|
return Object.freeze({
|
|
66
70
|
policies: deepFreeze(policies)
|
|
67
71
|
});
|
|
72
|
+
},
|
|
73
|
+
defineRoles: <
|
|
74
|
+
const R extends readonly TRoleDefinition<T>[] =
|
|
75
|
+
readonly TRoleDefinition<T>[],
|
|
76
|
+
L extends TDeepReadonly<R> = TDeepReadonly<R>
|
|
77
|
+
>(
|
|
78
|
+
roles: TEnforceUnique<
|
|
79
|
+
{
|
|
80
|
+
[K in keyof R]: R[K] & {
|
|
81
|
+
readonly permissions: R[K]["permissions"] &
|
|
82
|
+
TEnforceUnique<R[K]["permissions"], "resource">;
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
"alias"
|
|
86
|
+
>
|
|
87
|
+
) => {
|
|
88
|
+
if (
|
|
89
|
+
new Set([
|
|
90
|
+
...roles
|
|
91
|
+
.map((role) =>
|
|
92
|
+
typeof role === "string" ? undefined : role.alias
|
|
93
|
+
)
|
|
94
|
+
.filter(
|
|
95
|
+
(policyAlias) => typeof policyAlias !== "undefined"
|
|
96
|
+
)
|
|
97
|
+
]).size !== roles.length
|
|
98
|
+
) {
|
|
99
|
+
throw new Error("Duplicated role alias.");
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const rolesFreezed = deepFreeze(roles);
|
|
103
|
+
|
|
104
|
+
return Object.freeze({
|
|
105
|
+
roles: rolesFreezed,
|
|
106
|
+
getRole: <
|
|
107
|
+
K extends L extends never ? never : L[number]["alias"],
|
|
108
|
+
R extends Extract<L[number], { alias: K }>
|
|
109
|
+
>(
|
|
110
|
+
alias: K
|
|
111
|
+
): R => {
|
|
112
|
+
const index = rolesFreezed.findIndex(
|
|
113
|
+
({ alias: roleAlias }) => alias === roleAlias
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (index === -1) {
|
|
117
|
+
throw new Error(
|
|
118
|
+
"Role not found, intialize roles error."
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return rolesFreezed[index] as R;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
68
125
|
}
|
|
69
126
|
});
|
|
70
127
|
};
|
package/src/index.ts
CHANGED
package/src/types/actionGuard.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { TOptionalTupleUnorderedNonEmpty } from "../ultils/types";
|
|
2
2
|
import type { TResourceDefinition } from "./resources";
|
|
3
3
|
|
|
4
|
-
export type TActionGuardOptions<
|
|
4
|
+
export type TActionGuardOptions<
|
|
5
|
+
T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]
|
|
6
|
+
> = {
|
|
5
7
|
[R in T[number] as R["alias"]]: {
|
|
6
8
|
resource: R["alias"];
|
|
7
9
|
action:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { TResourceDefinition } from "./resources";
|
|
2
2
|
|
|
3
|
-
export type TControllerGuardOptions<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
3
|
+
export type TControllerGuardOptions<
|
|
4
|
+
T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]
|
|
5
|
+
> = {
|
|
6
|
+
[R in T[number] as R["alias"]]: {
|
|
7
|
+
resource: R["alias"];
|
|
8
|
+
};
|
|
9
|
+
}[T[number]["alias"]];
|
package/src/types/index.ts
CHANGED
package/src/types/policies.ts
CHANGED
|
@@ -12,25 +12,3 @@ export type TPolicyDefinition<
|
|
|
12
12
|
readonly action: R["actions"][number];
|
|
13
13
|
};
|
|
14
14
|
}[T[number]["alias"]];
|
|
15
|
-
|
|
16
|
-
// export type TPolicyAttributes<
|
|
17
|
-
// T extends readonly TResourceDefinition[],
|
|
18
|
-
// K extends readonly TPolicyDefinition[] = readonly TPolicyDefinition[]
|
|
19
|
-
// > = {
|
|
20
|
-
// [R in K[number] as R["alias"]]: {
|
|
21
|
-
// readonly alias: string;
|
|
22
|
-
// readonly effect: "permit" | "deny";
|
|
23
|
-
// } & {
|
|
24
|
-
// [R in T[number] as R["type"]]: {
|
|
25
|
-
// readonly resource: R["type"];
|
|
26
|
-
// readonly action: R["actions"][number];
|
|
27
|
-
// };
|
|
28
|
-
// }[T[number]["type"]];
|
|
29
|
-
// }[K[number]["alias"]];
|
|
30
|
-
|
|
31
|
-
// {
|
|
32
|
-
// [R in K[number] as R["type"]]: {
|
|
33
|
-
// readonly resource: R["type"];
|
|
34
|
-
// readonly action: R["actions"][number];
|
|
35
|
-
// };
|
|
36
|
-
// }[K[number]["type"]];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TEnforceUnique,
|
|
3
|
+
TOptionalTupleUnorderedNonEmpty
|
|
4
|
+
} from "../ultils/types";
|
|
5
|
+
import type { TResourceDefinition } from "./resources";
|
|
6
|
+
|
|
7
|
+
export type TRolePermissionDefinition<
|
|
8
|
+
T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]
|
|
9
|
+
> = {
|
|
10
|
+
[R in T[number] as R["alias"]]: {
|
|
11
|
+
readonly resource: R["alias"];
|
|
12
|
+
readonly actions: TOptionalTupleUnorderedNonEmpty<R["actions"]>;
|
|
13
|
+
};
|
|
14
|
+
}[T[number]["alias"]];
|
|
15
|
+
|
|
16
|
+
export type TRoleDefinition<
|
|
17
|
+
T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]
|
|
18
|
+
> = {
|
|
19
|
+
readonly alias: string;
|
|
20
|
+
readonly [key: string]: unknown;
|
|
21
|
+
} & {
|
|
22
|
+
readonly permissions: TEnforceUnique<
|
|
23
|
+
Array<TRolePermissionDefinition<T>>,
|
|
24
|
+
"resource"
|
|
25
|
+
>;
|
|
26
|
+
};
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
type IsDuplicated<
|
|
2
|
-
|
|
2
|
+
P extends readonly any[],
|
|
3
3
|
K extends string,
|
|
4
|
-
CurrentValue,
|
|
5
4
|
Index extends string
|
|
6
5
|
> = {
|
|
7
|
-
[I in keyof
|
|
6
|
+
[I in keyof P]: I extends Index
|
|
8
7
|
? never
|
|
9
|
-
:
|
|
10
|
-
?
|
|
11
|
-
?
|
|
8
|
+
: P[I] extends Record<K, any>
|
|
9
|
+
? Index extends keyof P
|
|
10
|
+
? P[Index] extends Record<K, any>
|
|
11
|
+
? P[I][K] extends P[Index][K]
|
|
12
|
+
? true
|
|
13
|
+
: never
|
|
14
|
+
: never
|
|
12
15
|
: never
|
|
13
16
|
: never;
|
|
14
17
|
}[number] extends never
|
|
15
18
|
? false
|
|
16
19
|
: true;
|
|
17
20
|
|
|
18
|
-
export type TEnforceUnique<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
K & string,
|
|
25
|
-
Arr[I] extends Record<K, any> ? Arr[I][K] : never,
|
|
26
|
-
I & string
|
|
27
|
-
> extends true
|
|
28
|
-
? `❌ ERROR: Duplicate value "${Arr[I][K] & string}" found at key "${K & string}"`
|
|
29
|
-
: Arr[I];
|
|
21
|
+
export type TEnforceUnique<A extends readonly any[], K extends string> = {
|
|
22
|
+
[I in keyof A]: IsDuplicated<A, K, I & string> extends true
|
|
23
|
+
? A[I] & {
|
|
24
|
+
readonly __error: `Error: Duplicate value "${A[I] extends Record<K, any> ? A[I][K] : ""}" at key "${K}"`;
|
|
25
|
+
}
|
|
26
|
+
: A[I];
|
|
30
27
|
};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { TPolicyDefinition } from "../types";
|
|
2
|
-
import type { TEnforceUnique } from "../ultils/types";
|
|
3
|
-
export declare const definePolicies: <const T extends readonly TPolicyDefinition[]>(policies: T & TEnforceUnique<T, "alias">) => Readonly<{
|
|
4
|
-
policies: import("../ultils/types").TDeepReadonly<T & TEnforceUnique<T, "alias">>;
|
|
5
|
-
}>;
|
package/src/definers/policies.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { TPolicyDefinition } from "../types";
|
|
2
|
-
import type { TEnforceUnique } from "../ultils/types";
|
|
3
|
-
|
|
4
|
-
import { deepFreeze } from "../ultils/functions";
|
|
5
|
-
|
|
6
|
-
export const definePolicies = <const T extends readonly TPolicyDefinition[]>(
|
|
7
|
-
policies: T & TEnforceUnique<T, "alias">
|
|
8
|
-
) => {
|
|
9
|
-
if (
|
|
10
|
-
new Set([
|
|
11
|
-
...policies
|
|
12
|
-
.map((policy) =>
|
|
13
|
-
typeof policy === "string" ? undefined : policy.alias
|
|
14
|
-
)
|
|
15
|
-
.filter((policyAlias) => typeof policyAlias !== "undefined")
|
|
16
|
-
]).size !== policies.length
|
|
17
|
-
) {
|
|
18
|
-
throw new Error("Duplicated policy alias.");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return Object.freeze({
|
|
22
|
-
policies: deepFreeze(policies)
|
|
23
|
-
});
|
|
24
|
-
};
|