@bool-ts/guard-sdk 1.0.2-beta.3 → 1.1.0-beta.1

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.
Files changed (68) hide show
  1. package/dist/decorators/actionGuard.decorator.d.ts +3 -1
  2. package/dist/decorators/controllerGuard.decorator.d.ts +2 -1
  3. package/dist/decorators/index.d.ts +0 -2
  4. package/dist/definers/index.d.ts +1 -0
  5. package/dist/definers/policies.d.ts +5 -0
  6. package/dist/definers/resources.d.ts +8 -0
  7. package/dist/entities/loader.d.ts +7 -2
  8. package/dist/index.js +12 -12
  9. package/dist/index.js.map +10 -12
  10. package/dist/instances/client.d.ts +7 -4
  11. package/dist/interfaces/client.interface.d.ts +9 -4
  12. package/dist/interfaces/index.d.ts +1 -1
  13. package/dist/types/actionGuard.d.ts +8 -0
  14. package/dist/types/controllerGuard.d.ts +6 -0
  15. package/dist/types/index.d.ts +3 -0
  16. package/dist/types/policies.d.ts +11 -0
  17. package/dist/types/resources.d.ts +6 -0
  18. package/dist/ultils/functions/deepFreeze.d.ts +7 -0
  19. package/dist/ultils/functions/index.d.ts +1 -0
  20. package/dist/ultils/types/constructor.d.ts +1 -0
  21. package/dist/ultils/types/enforceUnique.d.ts +8 -0
  22. package/dist/ultils/types/error.d.ts +3 -0
  23. package/dist/ultils/types/extractTuple.d.ts +1 -0
  24. package/dist/ultils/types/inArray.d.ts +1 -0
  25. package/dist/ultils/types/index.d.ts +14 -0
  26. package/dist/ultils/types/mergeTuple.d.ts +3 -0
  27. package/dist/ultils/types/noneEmptyArray.d.ts +1 -0
  28. package/dist/ultils/types/partialTuple.d.ts +1 -0
  29. package/dist/ultils/types/partialTupleUnordered.d.ts +3 -0
  30. package/dist/ultils/types/partialTupleUnorderedNonEmpty.d.ts +3 -0
  31. package/dist/ultils/types/partialTurpleNonEmpty.d.ts +5 -0
  32. package/dist/ultils/types/permutationTuple.d.ts +1 -0
  33. package/dist/ultils/types/shuffleTuple.d.ts +5 -0
  34. package/dist/ultils/types/strictPartial.d.ts +5 -0
  35. package/package.json +4 -4
  36. package/src/decorators/actionGuard.decorator.ts +18 -3
  37. package/src/decorators/controllerGuard.decorator.ts +7 -3
  38. package/src/decorators/index.ts +0 -2
  39. package/src/definers/index.ts +1 -0
  40. package/src/definers/policies.ts +24 -0
  41. package/src/definers/resources.ts +47 -0
  42. package/src/entities/loader.ts +17 -3
  43. package/src/entities/middleware.ts +1 -2
  44. package/src/instances/client.ts +135 -57
  45. package/src/interfaces/client.interface.ts +18 -6
  46. package/src/interfaces/index.ts +2 -1
  47. package/src/types/actionGuard.ts +11 -0
  48. package/src/types/controllerGuard.ts +8 -0
  49. package/src/types/index.ts +3 -0
  50. package/src/types/policies.ts +36 -0
  51. package/src/types/resources.ts +10 -0
  52. package/src/ultils/functions/deepFreeze.ts +19 -0
  53. package/src/ultils/functions/index.ts +1 -0
  54. package/src/ultils/types/constructor.ts +1 -0
  55. package/src/ultils/types/enforceUnique.ts +30 -0
  56. package/src/ultils/types/error.ts +1 -0
  57. package/src/ultils/types/extractTuple.ts +1 -0
  58. package/src/ultils/types/inArray.ts +7 -0
  59. package/src/ultils/types/index.ts +14 -0
  60. package/src/ultils/types/mergeTuple.ts +3 -0
  61. package/src/ultils/types/noneEmptyArray.ts +1 -0
  62. package/src/ultils/types/partialTuple.ts +3 -0
  63. package/src/ultils/types/partialTupleUnordered.ts +8 -0
  64. package/src/ultils/types/partialTupleUnorderedNonEmpty.ts +9 -0
  65. package/src/ultils/types/partialTurpleNonEmpty.ts +8 -0
  66. package/src/ultils/types/permutationTuple.ts +5 -0
  67. package/src/ultils/types/shuffleTuple.ts +7 -0
  68. package/src/ultils/types/strictPartial.ts +5 -0
@@ -1,15 +1,18 @@
1
- import type { IClient, TClientConfigs, TClientOptions } from "../interfaces/client.interface";
1
+ import type { IClient, TClientCredential, TClientDefinition, TClientOptions } from "../interfaces/client.interface";
2
2
  export declare class Client implements IClient {
3
3
  #private;
4
- private readonly configs;
5
- private readonly options?;
4
+ private readonly params;
6
5
  private token;
7
6
  /**
8
7
  * Initialize BoolGuard client instance
9
8
  * @param configs
10
9
  * @param options
11
10
  */
12
- constructor(configs: TClientConfigs, options?: TClientOptions | undefined);
11
+ constructor(params: Readonly<{
12
+ credential: TClientCredential;
13
+ definition?: TClientDefinition;
14
+ options?: TClientOptions;
15
+ }>);
13
16
  /**
14
17
  * Sign JWT token with Ed25519 algorithm
15
18
  * @returns
@@ -1,15 +1,20 @@
1
+ import type { defineResources } from "../definers";
1
2
  import type { IAccount, TDefaultAccountMetadata } from "./account.interface";
2
3
  import type { IAccountCredential } from "./accountCredential.interface";
3
- export type TClientConfigs = {
4
+ export type TClientCredential = Readonly<{
4
5
  tenantId: string;
5
6
  appId: string;
6
7
  modeId: string;
7
8
  secretKey: string;
8
- };
9
- export type TClientOptions = {
9
+ }>;
10
+ export type TClientDefinition = Readonly<{
11
+ resources: ReturnType<typeof defineResources>["resources"];
12
+ policies: ReturnType<ReturnType<typeof defineResources>["definePolicies"]>;
13
+ }>;
14
+ export type TClientOptions = Readonly<{
10
15
  version?: 1;
11
16
  logs?: boolean;
12
- };
17
+ }>;
13
18
  export interface IClient<TAccountMetadata extends TDefaultAccountMetadata = TDefaultAccountMetadata> {
14
19
  createPlainAccount(args: {
15
20
  identity: string;
@@ -1,4 +1,4 @@
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 { IClient, TAuthState, TClientConfigs, TClientOptions } from "./client.interface";
4
+ export type { IClient, TAuthState, TClientCredential as TClientConfigs, TClientOptions } from "./client.interface";
@@ -0,0 +1,8 @@
1
+ import type { TOptionalTupleUnorderedNonEmpty } from "../ultils/types";
2
+ import type { TResourceDefinition } from "./resources";
3
+ export type TActionGuardOptions<T extends readonly TResourceDefinition[]> = {
4
+ [R in T[number] as R["type"]]: {
5
+ resource: R["type"];
6
+ action: R["actions"][number] | TOptionalTupleUnorderedNonEmpty<R["actions"]>;
7
+ };
8
+ }[T[number]["type"]];
@@ -0,0 +1,6 @@
1
+ import type { TResourceDefinition } from "./resources";
2
+ export type TControllerGuardOptions<T extends readonly TResourceDefinition[]> = {
3
+ [R in T[number] as R["type"]]: {
4
+ resource: R["type"];
5
+ };
6
+ }[T[number]["type"]];
@@ -0,0 +1,3 @@
1
+ export * from "./actionGuard";
2
+ export * from "./policies";
3
+ export * from "./resources";
@@ -0,0 +1,11 @@
1
+ import type { TResourceDefinition } from "./resources";
2
+ export type TPolicyDefinition<T extends readonly TResourceDefinition[] = readonly TResourceDefinition[]> = {
3
+ readonly alias: string;
4
+ readonly effect: "permit" | "deny";
5
+ readonly [key: string]: unknown;
6
+ } & {
7
+ [R in T[number] as R["type"]]: {
8
+ readonly resource: R["type"];
9
+ readonly action: R["actions"][number];
10
+ };
11
+ }[T[number]["type"]];
@@ -0,0 +1,6 @@
1
+ import type { TNonEmptyArray } from "../ultils/types";
2
+ export type TResourceDefinition<T extends string = string, A extends TNonEmptyArray<string> = TNonEmptyArray<string>> = {
3
+ readonly type: T;
4
+ readonly actions: A;
5
+ readonly [key: string]: unknown;
6
+ };
@@ -0,0 +1,7 @@
1
+ type DeepReadonly<T> = T extends (...args: any[]) => any ? T : T extends readonly any[] ? {
2
+ readonly [K in keyof T]: DeepReadonly<T[K]>;
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 {};
@@ -0,0 +1 @@
1
+ export { deepFreeze } from "./deepFreeze";
@@ -0,0 +1 @@
1
+ export type TConstructor<T, K extends any[] = any[]> = new (...args: K) => T;
@@ -0,0 +1,8 @@
1
+ type ValuesOfKey<Arr extends any[], K extends keyof any> = Arr extends [
2
+ infer Head,
3
+ ...infer Tail
4
+ ] ? Head extends Record<K, any> ? [Head[K], ...ValuesOfKey<Tail, K>] : ValuesOfKey<Tail, K> : [];
5
+ type Includes<Arr extends any[], V> = Arr extends [infer H, ...infer R] ? [V] extends [H] ? true : Includes<R, V> : false;
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 ? ["Duplicate key found"] : Arr;
8
+ export {};
@@ -0,0 +1,3 @@
1
+ export type TError<Message extends string> = {
2
+ __error__: Message;
3
+ };
@@ -0,0 +1 @@
1
+ export type ExtractTuple<T> = T extends readonly [...infer U] ? U : never;
@@ -0,0 +1 @@
1
+ export type TInArray<T, X> = T extends readonly [X, ...infer _Rest] ? true : T extends readonly [X] ? true : T extends readonly [infer _, ...infer Rest] ? TInArray<Rest, X> : false;
@@ -0,0 +1,14 @@
1
+ export type { TConstructor } from "./constructor";
2
+ export type { TEnforceUnique } from "./enforceUnique";
3
+ export type { TError } from "./error";
4
+ export type { ExtractTuple } from "./extractTuple";
5
+ export type { TInArray } from "./inArray";
6
+ export type { MergeTuple } from "./mergeTuple";
7
+ export type { TNonEmptyArray } from "./noneEmptyArray";
8
+ export type { TPartialTuple } from "./partialTuple";
9
+ export type { TPartialTupleUnordered as TOptionalTupleUnordered } from "./partialTupleUnordered";
10
+ export type { TOptionalTupleUnorderedNonEmpty } from "./partialTupleUnorderedNonEmpty";
11
+ export type { TPartialTupleNonEmpty } from "./partialTurpleNonEmpty";
12
+ export type { TPermutationTuple } from "./permutationTuple";
13
+ export type { TShuffleTuple } from "./shuffleTuple";
14
+ export type { TStrictPartial } from "./strictPartial";
@@ -0,0 +1,3 @@
1
+ export type MergeTuple<T extends readonly any[], U> = {
2
+ [K in keyof T]: T[K] & U;
3
+ };
@@ -0,0 +1 @@
1
+ export type TNonEmptyArray<T> = readonly [T, ...T[]];
@@ -0,0 +1 @@
1
+ export type TPartialTuple<T extends readonly any[]> = T extends readonly [infer Head, ...infer Tail] ? TPartialTuple<Tail> | [Head, ...TPartialTuple<Tail>] : [];
@@ -0,0 +1,3 @@
1
+ import type { TPartialTuple } from "./partialTuple";
2
+ import type { TPermutationTuple } from "./permutationTuple";
3
+ export type TPartialTupleUnordered<T extends readonly any[]> = TPartialTuple<T> extends infer S ? S extends readonly any[] ? TPermutationTuple<S[number]> : never : never;
@@ -0,0 +1,3 @@
1
+ import type { TPartialTupleNonEmpty } from "./partialTurpleNonEmpty";
2
+ import type { TPermutationTuple } from "./permutationTuple";
3
+ export type TOptionalTupleUnorderedNonEmpty<T extends readonly any[]> = TPartialTupleNonEmpty<T> extends infer S ? S extends readonly any[] ? TPermutationTuple<S[number]> : never : never;
@@ -0,0 +1,5 @@
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;
@@ -0,0 +1 @@
1
+ export type TPermutationTuple<T, K = T> = [T] extends [never] ? [] : T extends any ? [T, ...TPermutationTuple<Exclude<K, T>>] : never;
@@ -0,0 +1,5 @@
1
+ type Values<T> = T[keyof T];
2
+ export type TShuffleTuple<U extends string | number> = [U] extends [never] ? [] : Values<{
3
+ [K in U]: [K, ...TShuffleTuple<Exclude<U, K>>];
4
+ }>;
5
+ export {};
@@ -0,0 +1,5 @@
1
+ export type TStrictPartial<T> = {
2
+ [K in keyof T]?: T[K];
3
+ } & {
4
+ [K in keyof T as K extends string ? never : never]: never;
5
+ };
package/package.json CHANGED
@@ -5,11 +5,11 @@
5
5
  },
6
6
  "dependencies": {
7
7
  "jose": "^6.1.0",
8
- "zod": "^4.1.9"
8
+ "zod": "^4.1.12"
9
9
  },
10
10
  "devDependencies": {
11
11
  "@types/bun": "latest",
12
- "typescript": "^5.9.2"
12
+ "typescript": "^5.9.3"
13
13
  },
14
14
  "files": [
15
15
  "./dist",
@@ -46,5 +46,5 @@
46
46
  "test": "bun --hot run __test/index.ts"
47
47
  },
48
48
  "types": "./dist/index.d.ts",
49
- "version": "1.0.2-beta.3"
50
- }
49
+ "version": "1.1.0-beta.1"
50
+ }
@@ -1,5 +1,20 @@
1
+ import type { TActionGuardOptions, TResourceDefinition } from "../types";
2
+ import type { TConstructor } from "../ultils/types";
3
+
1
4
  import { Keys } from "../constants";
2
5
 
3
- export const ActionGuard = () => (target: Object, methodName: string) => {
4
- Reflect.defineMetadata(Keys.guardMetadata, undefined, target, methodName);
5
- };
6
+ export const ActionGuard =
7
+ <
8
+ const T extends readonly TResourceDefinition[] = readonly TResourceDefinition[],
9
+ K extends TConstructor<Object> | Object = Object
10
+ >(
11
+ options?: TActionGuardOptions<T>
12
+ ) =>
13
+ (target: K, methodName: string) => {
14
+ Reflect.defineMetadata(
15
+ Keys.guardMetadata,
16
+ options,
17
+ target.constructor,
18
+ methodName
19
+ );
20
+ };
@@ -1,5 +1,9 @@
1
+ import type { TConstructor } from "../ultils/types";
2
+
1
3
  import { Keys } from "../constants";
2
4
 
3
- export const ControllerGuard = () => (target: Object) => {
4
- Reflect.defineMetadata(Keys.guardMetadata, undefined, target);
5
- };
5
+ export const ControllerGuard =
6
+ <T extends TConstructor<Object>>() =>
7
+ (target: T) => {
8
+ Reflect.defineMetadata(Keys.guardMetadata, undefined, target);
9
+ };
@@ -1,3 +1 @@
1
- export { ActionGuard } from "./actionGuard.decorator";
2
1
  export { AuthState } from "./authState.decorator";
3
- export { ControllerGuard } from "./controllerGuard.decorator";
@@ -0,0 +1 @@
1
+ export { defineResources } from "./resources";
@@ -0,0 +1,24 @@
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 K extends readonly TPolicyDefinition[]>(
7
+ policies: TEnforceUnique<K, "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
+ };
@@ -0,0 +1,47 @@
1
+ import type { TPolicyDefinition, TResourceDefinition } from "../types";
2
+ import type { TEnforceUnique } from "../ultils/types";
3
+
4
+ import { deepFreeze } from "../ultils/functions";
5
+
6
+ export const defineResources = <const T extends readonly TResourceDefinition[]>(
7
+ resources: TEnforceUnique<T, "type">
8
+ ) => {
9
+ if (
10
+ new Set([
11
+ ...resources
12
+ .map((resource) =>
13
+ typeof resource === "string" ? undefined : resource.type
14
+ )
15
+ .filter((resourceType) => typeof resourceType !== "undefined")
16
+ ]).size !== resources.length
17
+ ) {
18
+ throw new Error("Duplicated resource type.");
19
+ }
20
+
21
+ return Object.freeze({
22
+ resources: deepFreeze(resources),
23
+ definePolicies: <const K extends readonly TPolicyDefinition<T>[]>(
24
+ policies: TEnforceUnique<K, "alias">
25
+ ) => {
26
+ if (
27
+ new Set([
28
+ ...policies
29
+ .map((policy) =>
30
+ typeof policy === "string"
31
+ ? undefined
32
+ : policy.alias
33
+ )
34
+ .filter(
35
+ (policyAlias) => typeof policyAlias !== "undefined"
36
+ )
37
+ ]).size !== policies.length
38
+ ) {
39
+ throw new Error("Duplicated policy alias.");
40
+ }
41
+
42
+ return Object.freeze({
43
+ policies: deepFreeze(policies)
44
+ });
45
+ }
46
+ });
47
+ };
@@ -1,10 +1,24 @@
1
- import type { TClientConfigs, TClientOptions } from "../interfaces/client.interface";
1
+ import type {
2
+ TClientCredential,
3
+ TClientDefinition,
4
+ TClientOptions
5
+ } from "../interfaces/client.interface";
2
6
 
3
7
  import { Keys } from "../constants";
4
8
  import { Client } from "../instances/client";
5
9
 
6
- export const loader = async (clientConfigs: TClientConfigs, clientOptions?: TClientOptions) => {
7
- const boolGuardClient = new Client(clientConfigs, clientOptions);
10
+ export type TLoaderParameters = {
11
+ credential: TClientCredential;
12
+ definition?: TClientDefinition;
13
+ options?: TClientOptions;
14
+ };
15
+
16
+ export const loader = async ({
17
+ credential,
18
+ definition,
19
+ options
20
+ }: TLoaderParameters) => {
21
+ const boolGuardClient = new Client({ credential, definition, options });
8
22
 
9
23
  await boolGuardClient.signToken();
10
24
 
@@ -4,7 +4,6 @@ import type { IClient, TAuthState } from "../interfaces/client.interface";
4
4
  import { Middleware as BoolMiddleware, Context, Inject, RequestHeaders } from "@bool-ts/core";
5
5
  import { object, string } from "zod/v4";
6
6
  import { Keys } from "../constants";
7
- import { Client } from "../instances";
8
7
 
9
8
  const headersSchema = object({
10
9
  authorization: string()
@@ -30,7 +29,7 @@ export class Middleware implements IMiddleware {
30
29
  * @param tenantAppModesService
31
30
  */
32
31
  constructor(
33
- @Inject(Client)
32
+ @Inject(Keys.guardClient)
34
33
  private readonly clientInstance: IClient
35
34
  ) {}
36
35