@cfast/permissions 0.0.1 → 0.2.0

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,62 +0,0 @@
1
- type DrizzleTable = {
2
- _: {
3
- name: string;
4
- };
5
- };
6
- type DrizzleSQL = {
7
- getSQL(): unknown;
8
- };
9
- type PermissionAction = "read" | "create" | "update" | "delete" | "manage";
10
- type CrudAction = Exclude<PermissionAction, "manage">;
11
- declare const CRUD_ACTIONS: readonly CrudAction[];
12
- type WhereClause = (columns: Record<string, unknown>, user: any) => DrizzleSQL | undefined;
13
- type Grant = {
14
- action: PermissionAction;
15
- subject: DrizzleTable | "all";
16
- where?: WhereClause;
17
- };
18
- type GrantFn<TUser> = (action: PermissionAction, subject: DrizzleTable | "all", options?: {
19
- where?: (columns: Record<string, unknown>, user: TUser) => DrizzleSQL | undefined;
20
- }) => Grant;
21
- type PermissionDescriptor = {
22
- action: PermissionAction;
23
- table: DrizzleTable;
24
- };
25
- type PermissionCheckResult = {
26
- permitted: boolean;
27
- denied: PermissionDescriptor[];
28
- reasons: string[];
29
- };
30
- type PermissionsConfig<TRoles extends readonly string[], TUser = unknown> = {
31
- roles: TRoles;
32
- grants: Record<TRoles[number], Grant[]> | ((grant: GrantFn<TUser>) => Record<TRoles[number], Grant[]>);
33
- hierarchy?: Partial<Record<TRoles[number], TRoles[number][]>>;
34
- };
35
- type Permissions<TRoles extends readonly string[] = readonly string[]> = {
36
- roles: TRoles;
37
- grants: Record<TRoles[number], Grant[]>;
38
- resolvedGrants: Record<TRoles[number], Grant[]>;
39
- };
40
-
41
- type ForbiddenErrorOptions = {
42
- action: PermissionAction;
43
- table: DrizzleTable;
44
- role: string;
45
- descriptors?: PermissionDescriptor[];
46
- };
47
- declare class ForbiddenError extends Error {
48
- readonly action: PermissionAction;
49
- readonly table: DrizzleTable;
50
- readonly role: string;
51
- readonly descriptors: PermissionDescriptor[];
52
- constructor(options: ForbiddenErrorOptions);
53
- toJSON(): {
54
- name: string;
55
- message: string;
56
- action: PermissionAction;
57
- table: string;
58
- role: string;
59
- };
60
- }
61
-
62
- export { CRUD_ACTIONS as C, type DrizzleTable as D, ForbiddenError as F, type Grant as G, type PermissionsConfig as P, type WhereClause as W, type Permissions as a, type PermissionAction as b, type PermissionDescriptor as c, type PermissionCheckResult as d, type CrudAction as e, type GrantFn as f };
@@ -1,195 +0,0 @@
1
- /**
2
- * Minimal structural type for a Drizzle ORM table reference.
3
- *
4
- * Drizzle stores table metadata via Symbols (e.g., `Symbol('drizzle:Name')`).
5
- * This loose type avoids importing `drizzle-orm` directly into the permissions package.
6
- */
7
- type DrizzleTable = Record<string | symbol, any>;
8
- /**
9
- * Minimal structural type for a Drizzle SQL expression.
10
- *
11
- * Matches any object with a `getSQL()` method, which includes Drizzle's
12
- * `SQL`, `SQLWrapper`, and condition builder results.
13
- */
14
- type DrizzleSQL = {
15
- getSQL(): unknown;
16
- };
17
- /**
18
- * Extracts the table name string from a Drizzle table reference.
19
- *
20
- * @param table - A Drizzle table object containing the `drizzle:Name` symbol.
21
- * @returns The table name, or `"unknown"` if the symbol is not present.
22
- */
23
- declare function getTableName(table: DrizzleTable): string;
24
- /**
25
- * A permission action: one of the four CRUD operations, or `"manage"` for all.
26
- *
27
- * - `"read"` maps to `SELECT` queries.
28
- * - `"create"` maps to `INSERT` statements.
29
- * - `"update"` maps to `UPDATE` statements.
30
- * - `"delete"` maps to `DELETE` statements.
31
- * - `"manage"` is shorthand for granting all four CRUD actions.
32
- */
33
- type PermissionAction = "read" | "create" | "update" | "delete" | "manage";
34
- /**
35
- * A CRUD-only permission action (excludes `"manage"`).
36
- *
37
- * Useful when you need to iterate over concrete operations without the
38
- * `"manage"` shorthand. See also {@link CRUD_ACTIONS}.
39
- */
40
- type CrudAction = Exclude<PermissionAction, "manage">;
41
- /**
42
- * Readonly array of the four CRUD action strings, useful for iteration.
43
- *
44
- * @example
45
- * ```typescript
46
- * import { CRUD_ACTIONS } from "@cfast/permissions";
47
- *
48
- * for (const action of CRUD_ACTIONS) {
49
- * console.log(action); // "read", "create", "update", "delete"
50
- * }
51
- * ```
52
- */
53
- declare const CRUD_ACTIONS: readonly CrudAction[];
54
- /**
55
- * A function that produces a Drizzle `WHERE` clause for row-level permission filtering.
56
- *
57
- * @param columns - The table's column references for building filter expressions.
58
- * @param user - The current user object (from `@cfast/auth`).
59
- * @returns A Drizzle SQL expression to restrict matching rows, or `undefined` for no restriction.
60
- */
61
- type WhereClause = (columns: Record<string, unknown>, user: any) => DrizzleSQL | undefined;
62
- /**
63
- * A single permission grant: an action on a subject, optionally restricted by a `where` clause.
64
- */
65
- type Grant = {
66
- /** The permitted operation. `"manage"` is shorthand for all four CRUD actions. */
67
- action: PermissionAction;
68
- /** The Drizzle table this grant applies to, or `"all"` for every table. */
69
- subject: DrizzleTable | "all";
70
- /** Optional row-level filter that restricts which rows this grant covers. */
71
- where?: WhereClause;
72
- };
73
- /**
74
- * Type-safe grant builder function, parameterized by the user type.
75
- *
76
- * Used when `grants` is provided as a callback in {@link PermissionsConfig}
77
- * so that `where` clauses receive a correctly typed `user` parameter.
78
- *
79
- * @typeParam TUser - The user type passed to `where` clause callbacks.
80
- */
81
- type GrantFn<TUser> = (action: PermissionAction, subject: DrizzleTable | "all", options?: {
82
- where?: (columns: Record<string, unknown>, user: TUser) => DrizzleSQL | undefined;
83
- }) => Grant;
84
- /**
85
- * Structural description of a permission requirement.
86
- *
87
- * Describes *what kind* of operation on *which table* without specifying concrete row values.
88
- * This is what makes client-side permission introspection possible: you can check whether a
89
- * role has the right grants without knowing the specific row being accessed.
90
- *
91
- * @example
92
- * ```typescript
93
- * const descriptor: PermissionDescriptor = {
94
- * action: "update",
95
- * table: posts,
96
- * };
97
- * ```
98
- */
99
- type PermissionDescriptor = {
100
- /** The operation being checked. */
101
- action: PermissionAction;
102
- /** The Drizzle table the operation targets. */
103
- table: DrizzleTable;
104
- };
105
- /**
106
- * Result of a permission check via {@link checkPermissions}.
107
- */
108
- type PermissionCheckResult = {
109
- /** `true` only if every descriptor in the check was satisfied. */
110
- permitted: boolean;
111
- /** The descriptors that were not satisfied. */
112
- denied: PermissionDescriptor[];
113
- /** Human-readable reasons for each denial. */
114
- reasons: string[];
115
- };
116
- /**
117
- * Configuration object for {@link definePermissions}.
118
- *
119
- * @typeParam TRoles - Tuple of role name string literals (use `as const`).
120
- * @typeParam TUser - The user type for typed `where` clauses (defaults to `unknown`).
121
- */
122
- type PermissionsConfig<TRoles extends readonly string[], TUser = unknown> = {
123
- /** All roles in the application, declared with `as const` for type inference. */
124
- roles: TRoles;
125
- /** A map from role to grant arrays, or a callback that receives a typed `grant` function. */
126
- grants: Record<TRoles[number], Grant[]> | ((grant: GrantFn<TUser>) => Record<TRoles[number], Grant[]>);
127
- /** Optional role hierarchy declaring which roles inherit from which. */
128
- hierarchy?: Partial<Record<TRoles[number], TRoles[number][]>>;
129
- };
130
- /**
131
- * The resolved permissions object returned by {@link definePermissions}.
132
- *
133
- * Contains the original roles and grants, plus the hierarchy-expanded `resolvedGrants`.
134
- * Pass this to `createDb()` for server-side enforcement or import it on the client
135
- * for UI-level permission introspection.
136
- *
137
- * @typeParam TRoles - Tuple of role name string literals.
138
- */
139
- type Permissions<TRoles extends readonly string[] = readonly string[]> = {
140
- /** The role names from the configuration. */
141
- roles: TRoles;
142
- /** The raw grants as declared (before hierarchy expansion). */
143
- grants: Record<TRoles[number], Grant[]>;
144
- /** Grants expanded with inherited grants from the role hierarchy. */
145
- resolvedGrants: Record<TRoles[number], Grant[]>;
146
- };
147
-
148
- /** Options for constructing a {@link ForbiddenError}. */
149
- type ForbiddenErrorOptions = {
150
- /** The action that was denied. */
151
- action: PermissionAction;
152
- /** The Drizzle table the action targeted. */
153
- table: DrizzleTable;
154
- /** The role that lacked the permission, if known. */
155
- role?: string;
156
- /** The full list of permission descriptors that were checked. */
157
- descriptors?: PermissionDescriptor[];
158
- };
159
- /**
160
- * Error thrown when a permission check fails during an operation.
161
- *
162
- * Extends `Error` with structured fields for the denied action, target table,
163
- * and role. Includes a `toJSON()` method so it can be serialized across the
164
- * server/client boundary.
165
- */
166
- declare class ForbiddenError extends Error {
167
- /** The action that was denied (e.g., `"delete"`). */
168
- readonly action: PermissionAction;
169
- /** The Drizzle table the action targeted. */
170
- readonly table: DrizzleTable;
171
- /** The role that lacked the permission, or `undefined` if not specified. */
172
- readonly role: string | undefined;
173
- /** The full list of permission descriptors that were checked. */
174
- readonly descriptors: PermissionDescriptor[];
175
- /**
176
- * Creates a new `ForbiddenError`.
177
- *
178
- * @param options - The action, table, and optional role/descriptors for the error.
179
- */
180
- constructor(options: ForbiddenErrorOptions);
181
- /**
182
- * Serializes the error to a JSON-safe object for server-to-client transfer.
183
- *
184
- * @returns A plain object with `name`, `message`, `action`, `table`, and `role` fields.
185
- */
186
- toJSON(): {
187
- name: string;
188
- message: string;
189
- action: PermissionAction;
190
- table: string;
191
- role: string | undefined;
192
- };
193
- }
194
-
195
- export { CRUD_ACTIONS as C, type DrizzleTable as D, ForbiddenError as F, type Grant as G, type PermissionsConfig as P, type WhereClause as W, type Permissions as a, type PermissionAction as b, type PermissionDescriptor as c, type PermissionCheckResult as d, type CrudAction as e, type GrantFn as f, getTableName as g };
@@ -1,59 +0,0 @@
1
- type DrizzleTable = Record<string | symbol, any>;
2
- type DrizzleSQL = {
3
- getSQL(): unknown;
4
- };
5
- declare function getTableName(table: DrizzleTable): string;
6
- type PermissionAction = "read" | "create" | "update" | "delete" | "manage";
7
- type CrudAction = Exclude<PermissionAction, "manage">;
8
- declare const CRUD_ACTIONS: readonly CrudAction[];
9
- type WhereClause = (columns: Record<string, unknown>, user: any) => DrizzleSQL | undefined;
10
- type Grant = {
11
- action: PermissionAction;
12
- subject: DrizzleTable | "all";
13
- where?: WhereClause;
14
- };
15
- type GrantFn<TUser> = (action: PermissionAction, subject: DrizzleTable | "all", options?: {
16
- where?: (columns: Record<string, unknown>, user: TUser) => DrizzleSQL | undefined;
17
- }) => Grant;
18
- type PermissionDescriptor = {
19
- action: PermissionAction;
20
- table: DrizzleTable;
21
- };
22
- type PermissionCheckResult = {
23
- permitted: boolean;
24
- denied: PermissionDescriptor[];
25
- reasons: string[];
26
- };
27
- type PermissionsConfig<TRoles extends readonly string[], TUser = unknown> = {
28
- roles: TRoles;
29
- grants: Record<TRoles[number], Grant[]> | ((grant: GrantFn<TUser>) => Record<TRoles[number], Grant[]>);
30
- hierarchy?: Partial<Record<TRoles[number], TRoles[number][]>>;
31
- };
32
- type Permissions<TRoles extends readonly string[] = readonly string[]> = {
33
- roles: TRoles;
34
- grants: Record<TRoles[number], Grant[]>;
35
- resolvedGrants: Record<TRoles[number], Grant[]>;
36
- };
37
-
38
- type ForbiddenErrorOptions = {
39
- action: PermissionAction;
40
- table: DrizzleTable;
41
- role?: string;
42
- descriptors?: PermissionDescriptor[];
43
- };
44
- declare class ForbiddenError extends Error {
45
- readonly action: PermissionAction;
46
- readonly table: DrizzleTable;
47
- readonly role: string | undefined;
48
- readonly descriptors: PermissionDescriptor[];
49
- constructor(options: ForbiddenErrorOptions);
50
- toJSON(): {
51
- name: string;
52
- message: string;
53
- action: PermissionAction;
54
- table: string;
55
- role: string | undefined;
56
- };
57
- }
58
-
59
- export { CRUD_ACTIONS as C, type DrizzleTable as D, ForbiddenError as F, type Grant as G, type PermissionsConfig as P, type WhereClause as W, type Permissions as a, type PermissionAction as b, type PermissionDescriptor as c, type PermissionCheckResult as d, type CrudAction as e, type GrantFn as f, getTableName as g };
@@ -1,53 +0,0 @@
1
- import { Table, SQL } from 'drizzle-orm';
2
-
3
- type PermissionAction = "read" | "create" | "update" | "delete" | "manage";
4
- type CrudAction = Exclude<PermissionAction, "manage">;
5
- declare const CRUD_ACTIONS: readonly CrudAction[];
6
- type WhereClause<TUser = unknown> = (columns: Record<string, unknown>, user: TUser) => SQL | undefined;
7
- type Grant<TUser = unknown> = {
8
- action: PermissionAction;
9
- subject: Table | "all";
10
- where?: WhereClause<TUser>;
11
- };
12
- type PermissionDescriptor = {
13
- action: PermissionAction;
14
- table: Table;
15
- };
16
- type PermissionCheckResult = {
17
- permitted: boolean;
18
- denied: PermissionDescriptor[];
19
- reasons: string[];
20
- };
21
- type PermissionsConfig<TRoles extends readonly string[], TUser = unknown> = {
22
- roles: TRoles;
23
- grants: Record<TRoles[number], Grant<TUser>[]>;
24
- hierarchy?: Partial<Record<TRoles[number], TRoles[number][]>>;
25
- };
26
- type Permissions<TRoles extends readonly string[] = readonly string[], TUser = unknown> = {
27
- roles: TRoles;
28
- grants: Record<TRoles[number], Grant<TUser>[]>;
29
- resolvedGrants: Record<TRoles[number], Grant<TUser>[]>;
30
- };
31
-
32
- type ForbiddenErrorOptions = {
33
- action: PermissionAction;
34
- table: Table;
35
- role: string;
36
- descriptors?: PermissionDescriptor[];
37
- };
38
- declare class ForbiddenError extends Error {
39
- readonly action: PermissionAction;
40
- readonly table: Table;
41
- readonly role: string;
42
- readonly descriptors: PermissionDescriptor[];
43
- constructor(options: ForbiddenErrorOptions);
44
- toJSON(): {
45
- name: string;
46
- message: string;
47
- action: PermissionAction;
48
- table: string;
49
- role: string;
50
- };
51
- }
52
-
53
- export { CRUD_ACTIONS as C, ForbiddenError as F, type Grant as G, type PermissionsConfig as P, type WhereClause as W, type Permissions as a, type PermissionAction as b, type PermissionDescriptor as c, type PermissionCheckResult as d, type CrudAction as e };