@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.
@@ -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
  };
@@ -1,3 +1,4 @@
1
1
  export * from "./actionGuard";
2
2
  export * from "./policies";
3
3
  export * from "./resources";
4
+ export * from "./roles";
@@ -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<Arr extends readonly any[], K extends string, CurrentValue, Index extends string> = {
2
- [I in keyof Arr]: I extends Index ? never : Arr[I] extends Record<K, any> ? Arr[I][K] extends CurrentValue ? true : never : never;
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<Arr extends readonly any[], K extends keyof Arr[number]> = {
5
- [I in keyof Arr]: IsDuplicated<Arr, K & string, Arr[I] extends Record<K, any> ? Arr[I][K] : never, I & string> extends true ? `❌ ERROR: Duplicate value "${Arr[I][K] & string}" found at key "${K & string}"` : Arr[I];
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 --emitDeclarationOnly && bun run ./app.build.ts",
45
- "format": "prettier \"**/*.ts\" --write",
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.11"
49
+ "version": "1.1.0-beta.13"
50
50
  }
@@ -1,4 +1,8 @@
1
- import type { TPolicyDefinition, TResourceDefinition } from "../types";
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: K & TEnforceUnique<K, "alias">
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
@@ -1,4 +1,5 @@
1
1
  export type * from "./interfaces";
2
+ export type * from "./types";
2
3
 
3
4
  export * from "./constants";
4
5
  export * from "./decorators";
@@ -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<T extends readonly TResourceDefinition[]> = {
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<T extends readonly TResourceDefinition[]> =
4
- {
5
- [R in T[number] as R["alias"]]: {
6
- resource: R["alias"];
7
- };
8
- }[T[number]["alias"]];
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"]];
@@ -1,3 +1,4 @@
1
1
  export * from "./actionGuard";
2
2
  export * from "./policies";
3
3
  export * from "./resources";
4
+ export * from "./roles";
@@ -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
- Arr extends readonly any[],
2
+ P extends readonly any[],
3
3
  K extends string,
4
- CurrentValue,
5
4
  Index extends string
6
5
  > = {
7
- [I in keyof Arr]: I extends Index
6
+ [I in keyof P]: I extends Index
8
7
  ? never
9
- : Arr[I] extends Record<K, any>
10
- ? Arr[I][K] extends CurrentValue
11
- ? true
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
- Arr extends readonly any[],
20
- K extends keyof Arr[number]
21
- > = {
22
- [I in keyof Arr]: IsDuplicated<
23
- Arr,
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
- }>;
@@ -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
- };