@zap-studio/permit 0.1.0 → 0.1.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.
- package/CHANGELOG.md +6 -0
- package/dist/errors-CgD70cJR.mjs +15 -0
- package/dist/errors-CgD70cJR.mjs.map +1 -0
- package/dist/errors.mjs +2 -14
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +41 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{types-Bd4zClp0.d.mts → types-BgG1Aq6K.d.mts} +1 -1
- package/dist/{types-Bd4zClp0.d.mts.map → types-BgG1Aq6K.d.mts.map} +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +4 -4
- package/dist/errors.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* Represents an error that occurs during policy evaluation or enforcement.
|
|
4
|
+
* Use this error to indicate issues related to policy logic, configuration, or execution.
|
|
5
|
+
*/
|
|
6
|
+
var PolicyError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "PolicyError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { PolicyError as t };
|
|
15
|
+
//# sourceMappingURL=errors-CgD70cJR.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-CgD70cJR.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Represents an error that occurs during policy evaluation or enforcement.\n * Use this error to indicate issues related to policy logic, configuration, or execution.\n */\nexport class PolicyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PolicyError\";\n }\n}\n"],"mappings":";;;;;AAIA,IAAa,cAAb,cAAiC,MAAM;CACrC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO"}
|
package/dist/errors.mjs
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* Represents an error that occurs during policy evaluation or enforcement.
|
|
4
|
-
* Use this error to indicate issues related to policy logic, configuration, or execution.
|
|
5
|
-
*/
|
|
6
|
-
var PolicyError = class extends Error {
|
|
7
|
-
constructor(message) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = "PolicyError";
|
|
10
|
-
}
|
|
11
|
-
};
|
|
1
|
+
import { t as PolicyError } from "./errors-CgD70cJR.mjs";
|
|
12
2
|
|
|
13
|
-
|
|
14
|
-
export { PolicyError };
|
|
15
|
-
//# sourceMappingURL=errors.mjs.map
|
|
3
|
+
export { PolicyError };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as PermitConfig, d as Resources, f as Role, i as Context, l as Policy, n as Actions, p as RoleHierarchy, r as ConditionFn, u as PolicyFn } from "./types-
|
|
1
|
+
import { c as PermitConfig, d as Resources, f as Role, i as Context, l as Policy, n as Actions, p as RoleHierarchy, r as ConditionFn, u as PolicyFn } from "./types-BgG1Aq6K.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/index.d.ts
|
|
4
4
|
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;AAgCA;;;;;;;AAwBA;;;;;;;AAwBgB,iBAhDA,KAgDA,CACG,iBAhDA,OAgDA,EAIM,gBAAA,MAAA,GAAA,MAAA,EAAU,YAAA,OAAA,CAAS,CAAA,CAAA,EAjDvC,QAiDuC,CAjD9B,QAiD8B,EAjDpB,OAiDoB,EAjDX,SAiDW,CAAA;;;;;;;AAuB5C;;;;;;;;;;AAMG,iBA1Da,IA0Db,CAsBH,iBA/EmB,OA+EH,EACG,gBAAA,MAAA,GAAA,MAAA,EAIU,YAAA,OAAA,CAAU,CAAA,CAAA,EAjFlC,QAiFkC,CAjFzB,QAiFyB,EAjFf,OAiFe,EAjFN,SAiFM,CAAA;;;;;;;;AAoBvC;;;;;;;;;AAMG,iBAvFa,IAuFb,CAAA,iBAtFgB,OAsFhB,EAgBH,gBAAgB,MAAA,GAAA,MAAA,EAAqB,YAAA,OAAA,CAAyB,CAAA,SAAA,EAlGjD,WAkGiD,CAlGrC,QAkGqC,EAlG3B,OAkG2B,EAlGlB,SAkGkB,CAAA,CAAA,EAjG3D,QAiG2D,CAjGlD,QAiGkD,EAjGxC,OAiGwC,EAjG/B,SAiG+B,CAAA;;;;;;;AAwB9D;;;;;;;;;AA6CA;;AACqC,iBAjJrB,GAiJqB,CAAO,iBAhJzB,OAgJyB,EAGpC,gBAAA,MAAA,GAAA,MAAA,EAAmB,YAAA,OAAA,CAAU,CAAA,GAAA,UAAA,EA/IpB,WA+IoB,CA/IR,QA+IQ,EA/IE,OA+IF,EA/IW,SA+IX,CAAA,EAAA,CAAA,EA9IlC,WA8IkC,CA9ItB,QA8IsB,EA9IZ,OA8IY,EA9IH,SA8IG,CAAA;;;;AAErC;;;;;;;;;;;;;;AAuFgB,iBAjNA,EAiNA,CACG,iBAjNA,OAiNA,EACE,gBAAA,MAAA,GAAA,MAAA,EAAY,YAAA,OAAA,CACN,CAAA,GAAA,UAAA,EA/MV,WA+MU,CA/ME,QA+MF,EA/MY,OA+MZ,EA/MqB,SA+MrB,CAAA,EAAA,CAAA,EA9MxB,WA8MwB,CA9MZ,QA8MY,EA9MF,OA8ME,EA9MO,SA8MP,CAAA;;;;;;;;;;;;;AAwG3B;;AAEqB,iBArSL,GAqSK,CAAY,iBApSd,OAoSc,EACN,gBAAA,MAAA,GAAA,MAAA,EAAR,YAAA,OAAA,CAA8B,CAAA,SAAA,EAjSpC,WAiSoC,CAjSxB,QAiSwB,EAjSd,OAiSc,EAjSL,SAiSK,CAAA,CAAA,EAhS9C,WAgS8C,CAhSlC,QAgSkC,EAhSxB,OAgSwB,EAhSf,SAgSe,CAAA;;;;;;;;;;;AAqCjD;;AAEqB,iBAvTL,GAuTK,CAAY,iBAvTI,OAuTJ,EACN,UAAA,MAxTmC,QAwTnC,CAAR,CAAA,GAAA,EAvTZ,CAuTY,EAAA,KAAA,EAtTV,QAsTU,CAtTD,CAsTC,CAAA,CAAA,EArThB,WAqTgB,CArTJ,QAqTI,CAAA;;;;;;;;;;;;;;;;;;iBAhSH,oCAAoC,OAAO,aAClD,oBACI,cAAc,SACxB,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0CS,yBACG;QAAkB,OAAO;+DAGpC,OAAO,YAAY,UAAU,SAAS;iBAE9B,yBACG;QAAkB,QAAQ;uEAG7B,OAAO,YAEf,kBACK,cAAc,SACxB,YAAY,UAAU,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+ElB,8BACG,4BACE,YAAY,4BACd,QAAQ,cAAc,QAAQ,qBAEvC,aAAa,UAAU,YAAY,YAC1C,OAAO,UAAU,YAAY;;;;;;;;;;;;;;iBAqGhB,+BACG,4BACE,YAAY,4BACd,QAAQ,cAAc,QAAQ,0BAElC,OAAO,UAAU,YAAY,cACzC,OAAO,UAAU,YAAY;;;;;;;;;;;;;;iBAkChB,kCACG,4BACE,YAAY,4BACd,QAAQ,cAAc,QAAQ,0BAElC,OAAO,UAAU,YAAY,cACzC,OAAO,UAAU,YAAY"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { t as PolicyError } from "./errors-CgD70cJR.mjs";
|
|
2
|
+
|
|
1
3
|
//#region src/index.ts
|
|
2
4
|
/**
|
|
3
5
|
* Returns a policy function that always allows the action.
|
|
@@ -219,11 +221,45 @@ function hasRole(role, hierarchy) {
|
|
|
219
221
|
* ```
|
|
220
222
|
*/
|
|
221
223
|
function createPolicy(config) {
|
|
222
|
-
const { rules } = config;
|
|
224
|
+
const { rules, resources, actions } = config;
|
|
225
|
+
const validators = /* @__PURE__ */ new Map();
|
|
226
|
+
const getValidatedResource = (resourceType, resource) => {
|
|
227
|
+
const validator = validators.get(resourceType);
|
|
228
|
+
if (!validator) return null;
|
|
229
|
+
try {
|
|
230
|
+
const result = validator(resource);
|
|
231
|
+
if (result.issues) return null;
|
|
232
|
+
return result.value;
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.warn(`Resource validation failed for ${String(resourceType)}: ${String(error)}`);
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
for (const key of Object.keys(resources)) {
|
|
239
|
+
const schema = resources[key];
|
|
240
|
+
if (!schema) throw new PolicyError(`Missing schema for resource: ${String(key)}`);
|
|
241
|
+
validators.set(key, (input) => {
|
|
242
|
+
const result = schema["~standard"].validate(input);
|
|
243
|
+
if (result instanceof Promise) throw new PolicyError("Async schemas are not supported in createPolicy");
|
|
244
|
+
return result;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
223
247
|
return { can(context, action, resourceType, resource) {
|
|
224
|
-
const
|
|
248
|
+
const allowedActions = actions[resourceType];
|
|
249
|
+
if (!allowedActions) return false;
|
|
250
|
+
if (!allowedActions.includes(action)) return false;
|
|
251
|
+
const validatedResource = getValidatedResource(resourceType, resource);
|
|
252
|
+
if (!validatedResource) return false;
|
|
253
|
+
const resourceRules = rules[resourceType];
|
|
254
|
+
if (!resourceRules) return false;
|
|
255
|
+
const policyFn = resourceRules[action];
|
|
225
256
|
if (!policyFn) return false;
|
|
226
|
-
|
|
257
|
+
try {
|
|
258
|
+
return policyFn(context, action, validatedResource) === "allow";
|
|
259
|
+
} catch (error) {
|
|
260
|
+
console.warn(`Policy evaluation error for ${String(resourceType)}.${String(action)}: ${String(error)}`);
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
227
263
|
} };
|
|
228
264
|
}
|
|
229
265
|
/**
|
|
@@ -241,6 +277,7 @@ function createPolicy(config) {
|
|
|
241
277
|
*/
|
|
242
278
|
function mergePolicies(...policies) {
|
|
243
279
|
return { can(context, action, resourceType, resource) {
|
|
280
|
+
if (!policies.length) return false;
|
|
244
281
|
for (const policy of policies) if (!policy.can(context, action, resourceType, resource)) return false;
|
|
245
282
|
return true;
|
|
246
283
|
} };
|
|
@@ -260,6 +297,7 @@ function mergePolicies(...policies) {
|
|
|
260
297
|
*/
|
|
261
298
|
function mergePoliciesAny(...policies) {
|
|
262
299
|
return { can(context, action, resourceType, resource) {
|
|
300
|
+
if (!policies.length) return false;
|
|
263
301
|
return policies.some((policy) => policy.can(context, action, resourceType, resource));
|
|
264
302
|
} };
|
|
265
303
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type {\n Actions,\n ConditionFn,\n Context,\n InferAction,\n InferResource,\n PermitConfig,\n Policy,\n PolicyFn,\n Resources,\n Role,\n RoleHierarchy,\n} from \"./types\";\n\n/**\n * Returns a policy function that always allows the action.\n *\n * @example\n * ```ts\n * const policy = createPolicy({\n * resources,\n * actions,\n * rules: {\n * post: {\n * read: allow(), // Always allow reading posts\n * },\n * },\n * });\n * ```\n */\nexport function allow<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(): PolicyFn<TContext, TAction, TResource> {\n return () => \"allow\";\n}\n\n/**\n * Returns a policy function that always denies the action.\n *\n * @example\n * ```ts\n * const policy = createPolicy({\n * resources,\n * actions,\n * rules: {\n * post: {\n * delete: deny(), // Never allow deleting posts\n * },\n * },\n * });\n * ```\n */\nexport function deny<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(): PolicyFn<TContext, TAction, TResource> {\n return () => \"deny\";\n}\n\n/**\n * Returns a policy function that allows or denies based on a condition.\n *\n * @example\n * ```ts\n * const policy = createPolicy({\n * resources,\n * actions,\n * rules: {\n * post: {\n * write: when((ctx, action, resource) => ctx.user.id === resource.authorId),\n * },\n * },\n * });\n * ```\n */\nexport function when<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n condition: ConditionFn<TContext, TAction, TResource>\n): PolicyFn<TContext, TAction, TResource> {\n return (context, action, resource) =>\n condition(context, action, resource) ? \"allow\" : \"deny\";\n}\n\n/**\n * Returns a condition function that returns `true` if all conditions are met.\n *\n * @example\n * ```ts\n * const isOwnerAndPublished = and(\n * (ctx, action, resource) => ctx.user.id === resource.authorId,\n * (ctx, action, resource) => resource.status === \"published\"\n * );\n *\n * rules: {\n * post: {\n * delete: when(isOwnerAndPublished),\n * },\n * }\n * ```\n */\nexport function and<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n ...conditions: ConditionFn<TContext, TAction, TResource>[]\n): ConditionFn<TContext, TAction, TResource> {\n return (context, action, resource) =>\n conditions.every((condition) => condition(context, action, resource));\n}\n\n/**\n * Returns a condition function that returns `true` if any condition is met.\n *\n * @example\n * ```ts\n * const isOwnerOrAdmin = or(\n * (ctx, action, resource) => ctx.user.id === resource.authorId,\n * (ctx, action, resource) => ctx.user.role === \"admin\"\n * );\n *\n * rules: {\n * post: {\n * write: when(isOwnerOrAdmin),\n * },\n * }\n * ```\n */\nexport function or<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n ...conditions: ConditionFn<TContext, TAction, TResource>[]\n): ConditionFn<TContext, TAction, TResource> {\n return (context, action, resource) =>\n conditions.some((condition) => condition(context, action, resource));\n}\n\n/**\n * Returns a condition function that negates another condition.\n *\n * @example\n * ```ts\n * const isNotOwner = not((ctx, action, resource) => ctx.user.id === resource.authorId);\n *\n * rules: {\n * post: {\n * like: when(isNotOwner), // Can only like posts you don't own\n * },\n * }\n * ```\n */\nexport function not<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n condition: ConditionFn<TContext, TAction, TResource>\n): ConditionFn<TContext, TAction, TResource> {\n return (context, action, resource) => !condition(context, action, resource);\n}\n\n/**\n * Returns a condition function that checks if a context property equals a value.\n *\n * @example\n * ```ts\n * rules: {\n * post: {\n * write: when(has(\"role\", \"admin\")), // Only admins can write\n * },\n * }\n * ```\n */\nexport function has<TContext extends Context, K extends keyof TContext>(\n key: K,\n value: TContext[K]\n): ConditionFn<TContext> {\n return (context) => context[key] === value;\n}\n\n/**\n * Collects all roles including inherited ones from a role hierarchy.\n *\n * @example\n * ```ts\n * type Role = \"guest\" | \"user\" | \"admin\";\n *\n * const hierarchy: RoleHierarchy<Role> = {\n * guest: [],\n * user: [\"guest\"],\n * admin: [\"user\"],\n * };\n *\n * collectInheritedRoles([\"admin\"], hierarchy);\n * // Returns: Set { \"admin\", \"user\", \"guest\" }\n * ```\n */\nexport function collectInheritedRoles<TRole extends Role = Role>(\n roles: TRole[],\n hierarchy: RoleHierarchy<TRole>\n): Set<TRole> {\n const inherited = new Set<TRole>();\n\n function add(role: TRole) {\n if (!inherited.has(role)) {\n inherited.add(role);\n const parents = hierarchy[role] ?? [];\n parents.forEach(add); // recursively add parent roles\n }\n }\n\n roles.forEach(add);\n return inherited;\n}\n\n/**\n * Returns a condition function that checks if the user has a specific role.\n * Supports role hierarchy for inherited permissions.\n *\n * @example\n * ```ts\n * // Without hierarchy\n * rules: {\n * post: {\n * delete: when(hasRole(\"admin\")),\n * },\n * }\n *\n * // With hierarchy\n * const hierarchy = {\n * guest: [],\n * user: [\"guest\"],\n * admin: [\"user\"],\n * };\n *\n * rules: {\n * post: {\n * read: when(hasRole(\"guest\", hierarchy)), // Admins and users can also read\n * },\n * }\n * ```\n */\nexport function hasRole<\n TContext extends Context & { role: Role | Role[] },\n TAction extends string = string,\n TResource = unknown,\n>(role: Role): ConditionFn<TContext, TAction, TResource>;\n\nexport function hasRole<\n TContext extends Context & { role: TRole | TRole[] },\n TAction extends string = string,\n TResource = unknown,\n TRole extends Role = Role,\n>(\n role: TRole,\n hierarchy: RoleHierarchy<TRole>\n): ConditionFn<TContext, TAction, TResource>;\n\nexport function hasRole<\n TContext extends Context & { role: Role | Role[] },\n TAction extends string = string,\n TResource = unknown,\n>(\n role: Role,\n hierarchy?: RoleHierarchy<Role>\n): ConditionFn<TContext, TAction, TResource> {\n return (context) => {\n const userRoles = Array.isArray(context.role)\n ? context.role\n : [context.role];\n\n if (!hierarchy) {\n return userRoles.includes(role);\n }\n\n const inherited = collectInheritedRoles(userRoles, hierarchy);\n return inherited.has(role);\n };\n}\n\n/**\n * Creates a type-safe policy from resource schemas, actions, and rules.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { createPolicy, allow, deny, when } from \"@zap-studio/permit\";\n * import type { Resources, Actions } from \"@zap-studio/permit/types\";\n *\n * // Define resource schemas\n * const resources = {\n * post: z.object({\n * id: z.string(),\n * authorId: z.string(),\n * visibility: z.enum([\"public\", \"private\"]),\n * }),\n * comment: z.object({\n * id: z.string(),\n * postId: z.string(),\n * authorId: z.string(),\n * }),\n * } satisfies Resources;\n *\n * // Define actions per resource\n * const actions = {\n * post: [\"read\", \"write\", \"delete\"],\n * comment: [\"read\", \"write\"],\n * } as const satisfies Actions<typeof resources>;\n *\n * // Define context type\n * type AppContext = { user: { id: string; role: string } };\n *\n * // Create the policy\n * const policy = createPolicy<AppContext>({\n * resources,\n * actions,\n * rules: {\n * post: {\n * read: when((ctx, action, resource) => resource.visibility === \"public\"),\n * write: when((ctx, action, resource) => ctx.user.id === resource.authorId),\n * delete: deny(),\n * },\n * comment: {\n * read: allow(),\n * write: when((ctx, action, resource) => ctx.user.id === resource.authorId),\n * },\n * },\n * });\n *\n * // Check permissions\n * const post = { id: \"1\", authorId: \"user-1\", visibility: \"public\" as const };\n * policy.can(ctx, \"read\", \"post\", post); // true\n * policy.can(ctx, \"write\", \"post\", post); // depends on ctx.user.id\n * ```\n */\nexport function createPolicy<\n TContext extends Context,\n TResources extends Resources = Resources,\n TActions extends Actions<TResources> = Actions<TResources>,\n>(\n config: PermitConfig<TContext, TResources, TActions>\n): Policy<TContext, TResources, TActions> {\n const { rules } = config;\n\n return {\n can<K extends keyof TResources & keyof TActions>(\n context: TContext,\n action: InferAction<TActions, K>,\n resourceType: K,\n resource: InferResource<TResources, K>\n ): boolean {\n const resourceRules = rules[resourceType];\n const policyFn = resourceRules[action];\n\n if (!policyFn) {\n return false;\n }\n\n return policyFn(context, action, resource) === \"allow\";\n },\n };\n}\n\n/**\n * Merges multiple policies into one using \"deny-overrides\" strategy.\n * If any policy denies, the merged policy denies. All must allow for the result to allow.\n *\n * @example\n * ```ts\n * const basePolicy = createPolicy({ ... });\n * const adminPolicy = createPolicy({ ... });\n *\n * const merged = mergePolicies(basePolicy, adminPolicy);\n * // Both policies must allow for the action to be permitted\n * ```\n */\nexport function mergePolicies<\n TContext extends Context,\n TResources extends Resources = Resources,\n TActions extends Actions<TResources> = Actions<TResources>,\n>(\n ...policies: Policy<TContext, TResources, TActions>[]\n): Policy<TContext, TResources, TActions> {\n return {\n can<K extends keyof TResources & keyof TActions>(\n context: TContext,\n action: InferAction<TActions, K>,\n resourceType: K,\n resource: InferResource<TResources, K>\n ): boolean {\n for (const policy of policies) {\n if (!policy.can(context, action, resourceType, resource)) {\n return false;\n }\n }\n return true;\n },\n };\n}\n\n/**\n * Merges multiple policies into one using \"allow-overrides\" strategy.\n * If any policy allows, the merged policy allows. All must deny for the result to deny.\n *\n * @example\n * ```ts\n * const guestPolicy = createPolicy({ ... });\n * const memberPolicy = createPolicy({ ... });\n *\n * const merged = mergePoliciesAny(guestPolicy, memberPolicy);\n * // If either policy allows, the action is permitted\n * ```\n */\nexport function mergePoliciesAny<\n TContext extends Context,\n TResources extends Resources = Resources,\n TActions extends Actions<TResources> = Actions<TResources>,\n>(\n ...policies: Policy<TContext, TResources, TActions>[]\n): Policy<TContext, TResources, TActions> {\n return {\n can<K extends keyof TResources & keyof TActions>(\n context: TContext,\n action: InferAction<TActions, K>,\n resourceType: K,\n resource: InferResource<TResources, K>\n ): boolean {\n return policies.some((policy) =>\n policy.can(context, action, resourceType, resource)\n );\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA8BA,SAAgB,QAI4B;AAC1C,cAAa;;;;;;;;;;;;;;;;;;AAmBf,SAAgB,OAI4B;AAC1C,cAAa;;;;;;;;;;;;;;;;;;AAmBf,SAAgB,KAKd,WACwC;AACxC,SAAQ,SAAS,QAAQ,aACvB,UAAU,SAAS,QAAQ,SAAS,GAAG,UAAU;;;;;;;;;;;;;;;;;;;AAoBrD,SAAgB,IAKd,GAAG,YACwC;AAC3C,SAAQ,SAAS,QAAQ,aACvB,WAAW,OAAO,cAAc,UAAU,SAAS,QAAQ,SAAS,CAAC;;;;;;;;;;;;;;;;;;;AAoBzE,SAAgB,GAKd,GAAG,YACwC;AAC3C,SAAQ,SAAS,QAAQ,aACvB,WAAW,MAAM,cAAc,UAAU,SAAS,QAAQ,SAAS,CAAC;;;;;;;;;;;;;;;;AAiBxE,SAAgB,IAKd,WAC2C;AAC3C,SAAQ,SAAS,QAAQ,aAAa,CAAC,UAAU,SAAS,QAAQ,SAAS;;;;;;;;;;;;;;AAe7E,SAAgB,IACd,KACA,OACuB;AACvB,SAAQ,YAAY,QAAQ,SAAS;;;;;;;;;;;;;;;;;;;AAoBvC,SAAgB,sBACd,OACA,WACY;CACZ,MAAM,4BAAY,IAAI,KAAY;CAElC,SAAS,IAAI,MAAa;AACxB,MAAI,CAAC,UAAU,IAAI,KAAK,EAAE;AACxB,aAAU,IAAI,KAAK;AAEnB,IADgB,UAAU,SAAS,EAAE,EAC7B,QAAQ,IAAI;;;AAIxB,OAAM,QAAQ,IAAI;AAClB,QAAO;;AA8CT,SAAgB,QAKd,MACA,WAC2C;AAC3C,SAAQ,YAAY;EAClB,MAAM,YAAY,MAAM,QAAQ,QAAQ,KAAK,GACzC,QAAQ,OACR,CAAC,QAAQ,KAAK;AAElB,MAAI,CAAC,UACH,QAAO,UAAU,SAAS,KAAK;AAIjC,SADkB,sBAAsB,WAAW,UAAU,CAC5C,IAAI,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2D9B,SAAgB,aAKd,QACwC;CACxC,MAAM,EAAE,UAAU;AAElB,QAAO,EACL,IACE,SACA,QACA,cACA,UACS;EAET,MAAM,WADgB,MAAM,cACG;AAE/B,MAAI,CAAC,SACH,QAAO;AAGT,SAAO,SAAS,SAAS,QAAQ,SAAS,KAAK;IAElD;;;;;;;;;;;;;;;AAgBH,SAAgB,cAKd,GAAG,UACqC;AACxC,QAAO,EACL,IACE,SACA,QACA,cACA,UACS;AACT,OAAK,MAAM,UAAU,SACnB,KAAI,CAAC,OAAO,IAAI,SAAS,QAAQ,cAAc,SAAS,CACtD,QAAO;AAGX,SAAO;IAEV;;;;;;;;;;;;;;;AAgBH,SAAgB,iBAKd,GAAG,UACqC;AACxC,QAAO,EACL,IACE,SACA,QACA,cACA,UACS;AACT,SAAO,SAAS,MAAM,WACpB,OAAO,IAAI,SAAS,QAAQ,cAAc,SAAS,CACpD;IAEJ"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { PolicyError } from \"./errors\";\nimport type {\n Actions,\n ConditionFn,\n Context,\n InferAction,\n InferResource,\n PermitConfig,\n Policy,\n PolicyFn,\n Resources,\n Role,\n RoleHierarchy,\n} from \"./types\";\n\n/**\n * Returns a policy function that always allows the action.\n *\n * @example\n * ```ts\n * const policy = createPolicy({\n * resources,\n * actions,\n * rules: {\n * post: {\n * read: allow(), // Always allow reading posts\n * },\n * },\n * });\n * ```\n */\nexport function allow<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(): PolicyFn<TContext, TAction, TResource> {\n return () => \"allow\";\n}\n\n/**\n * Returns a policy function that always denies the action.\n *\n * @example\n * ```ts\n * const policy = createPolicy({\n * resources,\n * actions,\n * rules: {\n * post: {\n * delete: deny(), // Never allow deleting posts\n * },\n * },\n * });\n * ```\n */\nexport function deny<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(): PolicyFn<TContext, TAction, TResource> {\n return () => \"deny\";\n}\n\n/**\n * Returns a policy function that allows or denies based on a condition.\n *\n * @example\n * ```ts\n * const policy = createPolicy({\n * resources,\n * actions,\n * rules: {\n * post: {\n * write: when((ctx, action, resource) => ctx.user.id === resource.authorId),\n * },\n * },\n * });\n * ```\n */\nexport function when<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n condition: ConditionFn<TContext, TAction, TResource>\n): PolicyFn<TContext, TAction, TResource> {\n return (context, action, resource) =>\n condition(context, action, resource) ? \"allow\" : \"deny\";\n}\n\n/**\n * Returns a condition function that returns `true` if all conditions are met.\n *\n * @example\n * ```ts\n * const isOwnerAndPublished = and(\n * (ctx, action, resource) => ctx.user.id === resource.authorId,\n * (ctx, action, resource) => resource.status === \"published\"\n * );\n *\n * rules: {\n * post: {\n * delete: when(isOwnerAndPublished),\n * },\n * }\n * ```\n */\nexport function and<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n ...conditions: ConditionFn<TContext, TAction, TResource>[]\n): ConditionFn<TContext, TAction, TResource> {\n return (context, action, resource) =>\n conditions.every((condition) => condition(context, action, resource));\n}\n\n/**\n * Returns a condition function that returns `true` if any condition is met.\n *\n * @example\n * ```ts\n * const isOwnerOrAdmin = or(\n * (ctx, action, resource) => ctx.user.id === resource.authorId,\n * (ctx, action, resource) => ctx.user.role === \"admin\"\n * );\n *\n * rules: {\n * post: {\n * write: when(isOwnerOrAdmin),\n * },\n * }\n * ```\n */\nexport function or<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n ...conditions: ConditionFn<TContext, TAction, TResource>[]\n): ConditionFn<TContext, TAction, TResource> {\n return (context, action, resource) =>\n conditions.some((condition) => condition(context, action, resource));\n}\n\n/**\n * Returns a condition function that negates another condition.\n *\n * @example\n * ```ts\n * const isNotOwner = not((ctx, action, resource) => ctx.user.id === resource.authorId);\n *\n * rules: {\n * post: {\n * like: when(isNotOwner), // Can only like posts you don't own\n * },\n * }\n * ```\n */\nexport function not<\n TContext extends Context,\n TAction extends string = string,\n TResource = unknown,\n>(\n condition: ConditionFn<TContext, TAction, TResource>\n): ConditionFn<TContext, TAction, TResource> {\n return (context, action, resource) => !condition(context, action, resource);\n}\n\n/**\n * Returns a condition function that checks if a context property equals a value.\n *\n * @example\n * ```ts\n * rules: {\n * post: {\n * write: when(has(\"role\", \"admin\")), // Only admins can write\n * },\n * }\n * ```\n */\nexport function has<TContext extends Context, K extends keyof TContext>(\n key: K,\n value: TContext[K]\n): ConditionFn<TContext> {\n return (context) => context[key] === value;\n}\n\n/**\n * Collects all roles including inherited ones from a role hierarchy.\n *\n * @example\n * ```ts\n * type Role = \"guest\" | \"user\" | \"admin\";\n *\n * const hierarchy: RoleHierarchy<Role> = {\n * guest: [],\n * user: [\"guest\"],\n * admin: [\"user\"],\n * };\n *\n * collectInheritedRoles([\"admin\"], hierarchy);\n * // Returns: Set { \"admin\", \"user\", \"guest\" }\n * ```\n */\nexport function collectInheritedRoles<TRole extends Role = Role>(\n roles: TRole[],\n hierarchy: RoleHierarchy<TRole>\n): Set<TRole> {\n const inherited = new Set<TRole>();\n\n function add(role: TRole) {\n if (!inherited.has(role)) {\n inherited.add(role);\n const parents = hierarchy[role] ?? [];\n parents.forEach(add); // recursively add parent roles\n }\n }\n\n roles.forEach(add);\n return inherited;\n}\n\n/**\n * Returns a condition function that checks if the user has a specific role.\n * Supports role hierarchy for inherited permissions.\n *\n * @example\n * ```ts\n * // Without hierarchy\n * rules: {\n * post: {\n * delete: when(hasRole(\"admin\")),\n * },\n * }\n *\n * // With hierarchy\n * const hierarchy = {\n * guest: [],\n * user: [\"guest\"],\n * admin: [\"user\"],\n * };\n *\n * rules: {\n * post: {\n * read: when(hasRole(\"guest\", hierarchy)), // Admins and users can also read\n * },\n * }\n * ```\n */\nexport function hasRole<\n TContext extends Context & { role: Role | Role[] },\n TAction extends string = string,\n TResource = unknown,\n>(role: Role): ConditionFn<TContext, TAction, TResource>;\n\nexport function hasRole<\n TContext extends Context & { role: TRole | TRole[] },\n TAction extends string = string,\n TResource = unknown,\n TRole extends Role = Role,\n>(\n role: TRole,\n hierarchy: RoleHierarchy<TRole>\n): ConditionFn<TContext, TAction, TResource>;\n\nexport function hasRole<\n TContext extends Context & { role: Role | Role[] },\n TAction extends string = string,\n TResource = unknown,\n>(\n role: Role,\n hierarchy?: RoleHierarchy<Role>\n): ConditionFn<TContext, TAction, TResource> {\n return (context) => {\n const userRoles = Array.isArray(context.role)\n ? context.role\n : [context.role];\n\n if (!hierarchy) {\n return userRoles.includes(role);\n }\n\n const inherited = collectInheritedRoles(userRoles, hierarchy);\n return inherited.has(role);\n };\n}\n\n/**\n * Creates a type-safe policy from resource schemas, actions, and rules.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { createPolicy, allow, deny, when } from \"@zap-studio/permit\";\n * import type { Resources, Actions } from \"@zap-studio/permit/types\";\n *\n * // Define resource schemas\n * const resources = {\n * post: z.object({\n * id: z.string(),\n * authorId: z.string(),\n * visibility: z.enum([\"public\", \"private\"]),\n * }),\n * comment: z.object({\n * id: z.string(),\n * postId: z.string(),\n * authorId: z.string(),\n * }),\n * } satisfies Resources;\n *\n * // Define actions per resource\n * const actions = {\n * post: [\"read\", \"write\", \"delete\"],\n * comment: [\"read\", \"write\"],\n * } as const satisfies Actions<typeof resources>;\n *\n * // Define context type\n * type AppContext = { user: { id: string; role: string } };\n *\n * // Create the policy\n * const policy = createPolicy<AppContext>({\n * resources,\n * actions,\n * rules: {\n * post: {\n * read: when((ctx, action, resource) => resource.visibility === \"public\"),\n * write: when((ctx, action, resource) => ctx.user.id === resource.authorId),\n * delete: deny(),\n * },\n * comment: {\n * read: allow(),\n * write: when((ctx, action, resource) => ctx.user.id === resource.authorId),\n * },\n * },\n * });\n *\n * // Check permissions\n * const post = { id: \"1\", authorId: \"user-1\", visibility: \"public\" as const };\n * policy.can(ctx, \"read\", \"post\", post); // true\n * policy.can(ctx, \"write\", \"post\", post); // depends on ctx.user.id\n * ```\n */\nexport function createPolicy<\n TContext extends Context,\n TResources extends Resources = Resources,\n TActions extends Actions<TResources> = Actions<TResources>,\n>(\n config: PermitConfig<TContext, TResources, TActions>\n): Policy<TContext, TResources, TActions> {\n const { rules, resources, actions } = config;\n const validators = new Map<\n keyof TResources,\n (input: unknown) => StandardSchemaV1.Result<unknown>\n >();\n\n const getValidatedResource = <K extends keyof TResources>(\n resourceType: K,\n resource: InferResource<TResources, K>\n ): InferResource<TResources, K> | null => {\n const validator = validators.get(resourceType);\n if (!validator) {\n return null;\n }\n try {\n const result = validator(resource);\n if (result.issues) {\n return null;\n }\n return result.value as InferResource<TResources, K>;\n } catch (error) {\n console.warn(\n `Resource validation failed for ${String(resourceType)}: ${String(error)}`\n );\n return null;\n }\n };\n\n for (const key of Object.keys(resources) as Array<keyof TResources>) {\n const schema = resources[key];\n if (!schema) {\n throw new PolicyError(`Missing schema for resource: ${String(key)}`);\n }\n validators.set(key, (input: unknown) => {\n const result = schema[\"~standard\"].validate(input);\n if (result instanceof Promise) {\n throw new PolicyError(\n \"Async schemas are not supported in createPolicy\"\n );\n }\n return result;\n });\n }\n\n return {\n can<K extends keyof TResources & keyof TActions>(\n context: TContext,\n action: InferAction<TActions, K>,\n resourceType: K,\n resource: InferResource<TResources, K>\n ): boolean {\n const allowedActions = actions[resourceType];\n if (!allowedActions) {\n return false;\n }\n if (!allowedActions.includes(action)) {\n return false;\n }\n\n const validatedResource = getValidatedResource(resourceType, resource);\n if (!validatedResource) {\n return false;\n }\n\n const resourceRules = rules[resourceType];\n if (!resourceRules) {\n return false;\n }\n\n const policyFn = resourceRules[action];\n\n if (!policyFn) {\n return false;\n }\n\n try {\n return policyFn(context, action, validatedResource) === \"allow\";\n } catch (error) {\n console.warn(\n `Policy evaluation error for ${String(resourceType)}.${String(action)}: ${String(error)}`\n );\n return false;\n }\n },\n };\n}\n\n/**\n * Merges multiple policies into one using \"deny-overrides\" strategy.\n * If any policy denies, the merged policy denies. All must allow for the result to allow.\n *\n * @example\n * ```ts\n * const basePolicy = createPolicy({ ... });\n * const adminPolicy = createPolicy({ ... });\n *\n * const merged = mergePolicies(basePolicy, adminPolicy);\n * // Both policies must allow for the action to be permitted\n * ```\n */\nexport function mergePolicies<\n TContext extends Context,\n TResources extends Resources = Resources,\n TActions extends Actions<TResources> = Actions<TResources>,\n>(\n ...policies: Policy<TContext, TResources, TActions>[]\n): Policy<TContext, TResources, TActions> {\n return {\n can<K extends keyof TResources & keyof TActions>(\n context: TContext,\n action: InferAction<TActions, K>,\n resourceType: K,\n resource: InferResource<TResources, K>\n ): boolean {\n if (!policies.length) {\n return false;\n }\n for (const policy of policies) {\n if (!policy.can(context, action, resourceType, resource)) {\n return false;\n }\n }\n return true;\n },\n };\n}\n\n/**\n * Merges multiple policies into one using \"allow-overrides\" strategy.\n * If any policy allows, the merged policy allows. All must deny for the result to deny.\n *\n * @example\n * ```ts\n * const guestPolicy = createPolicy({ ... });\n * const memberPolicy = createPolicy({ ... });\n *\n * const merged = mergePoliciesAny(guestPolicy, memberPolicy);\n * // If either policy allows, the action is permitted\n * ```\n */\nexport function mergePoliciesAny<\n TContext extends Context,\n TResources extends Resources = Resources,\n TActions extends Actions<TResources> = Actions<TResources>,\n>(\n ...policies: Policy<TContext, TResources, TActions>[]\n): Policy<TContext, TResources, TActions> {\n return {\n can<K extends keyof TResources & keyof TActions>(\n context: TContext,\n action: InferAction<TActions, K>,\n resourceType: K,\n resource: InferResource<TResources, K>\n ): boolean {\n if (!policies.length) {\n return false;\n }\n return policies.some((policy) =>\n policy.can(context, action, resourceType, resource)\n );\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -131,4 +131,4 @@ type Policy<TContext extends Context, TResources extends Resources = Resources,
|
|
|
131
131
|
};
|
|
132
132
|
//#endregion
|
|
133
133
|
export { Decision as a, PermitConfig as c, Resources as d, Role as f, Context as i, Policy as l, Rules as m, Actions as n, InferAction as o, RoleHierarchy as p, ConditionFn as r, InferResource as s, ActionPolicyMap as t, PolicyFn as u };
|
|
134
|
-
//# sourceMappingURL=types-
|
|
134
|
+
//# sourceMappingURL=types-BgG1Aq6K.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-
|
|
1
|
+
{"version":3,"file":"types-BgG1Aq6K.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;AAOA;AAMA;AAKA;AAiBY,KA5BA,QAAA,GA4BA,OAAA,GAAA,MAAA;;;;;AAA2C,KAtB3C,OAsB2C,CAAA,WAAA,OAAA,CAAA,GAtBb,QAsBa;;AAiBvD;;AAEE,KApCU,IAoCV,CAAA,cAAA,MAAA,GAAA,MAAA,CAAA,GApCgD,KAoChD;;;AAiBF;AAOA;;;;;;;AAQA;;;;;AAGa,KAtDD,aAsDC,CAAA,cAtD2B,IAsD3B,GAtDkC,IAsDlC,CAAA,GAtD0C,MAsD1C,CAtDiD,KAsDjD,EAtDwD,KAsDxD,EAAA,CAAA;AAKb;;;;;;;AASA;;;;;;AASA;;AAKQ,KAjEI,SAiEJ,CAAA,qBAAA,MAAA,GAAA,MAAA,CAAA,GAjEsD,MAiEtD,CAhEN,YAgEM,EA/DN,gBA+DM,CAAA;;;;;;AAOR;;;;;;;;;AAKiC,KA1DrB,OA0DqB,CAAA,mBA1DM,SA0DN,CAAA,GAAA,QAAA,MAzDnB,UAyDmB,GAAA,SAAA,MAAA,EAAA,EAAA;;;;AAE7B,KArDQ,aAqDR,CACc,mBArDG,SAqDH,EAAY,qBAAA,MApDD,UAoDC,CAA1B,GAnDA,gBAAA,CAAiB,WAmDjB,CAnD6B,UAmD7B,CAnDwC,YAmDxC,CAAA,CAAA;;;AAkBJ;AACmB,KAjEP,WAiEO,CACE,iBAjEF,MAiEE,CAAA,MAAA,EAAA,SAAA,MAAA,EAAA,CAAA,EAAY,YAAA,MAhEf,QAgEe,CACN,GAhEvB,QAgEuB,CAhEd,GAgEc,CAAA,CAAA,MAAA,CAAA;;;;AAEd,KA7DD,QA6DC,CACF,iBA7DQ,OA6DR,EACI,gBAAA,MAAA,GAAA,MAAA,EAAU,YAAA,OAAA,CAAY,GAAA,CAAA,OAAA,EA3DvB,QA2DuB,EAAA,MAAA,EA3DL,OA2DK,EAAA,QAAA,EA3Dc,SA2Dd,EAAA,GA3D4B,QA2D5B;;;AAkBrC;AACmB,KAzEP,WAyEO,CACE,iBAzEF,OAyEE,EAAY,gBAAA,MAAA,GAAA,MAAA,EACN,YAAA,OAAA,CAAR,GAAA,CAAA,OAAA,EAvEL,QAuEK,EAAA,MAAA,EAvEa,OAuEb,EAAA,QAAA,EAvEgC,SAuEhC,EAAA,GAAA,OAAA;;;;AAKsB,KAvE7B,eAuE6B,CAC5B,iBAvEM,OAuEN,EACW,gBAAA,MAAA,GAAA,MAAA,EAAU,YAAA,OAAA,CAAtB,GAAA,QApEJ,OAoEI,IApEO,QAoEP,CApEgB,QAoEhB,EApE0B,CAoE1B,EApE6B,SAoE7B,CAAA,EAAA;;;;;AAEE,KA/DF,KA+DE,kBA9DK,4BACE,YAAY,4BACd,QAAQ,cAAc,QAAQ,6BAEnC,mBAAmB,WAAW,gBACxC,UACA,YAAY,UAAU,IACtB,cAAc,YAAY;;;;;;;;;;;;;;;KAkBlB,8BACO,4BACE,YAAY,4BACd,QAAQ,cAAc,QAAQ;aAEpC;WACF;SACF,MAAM,UAAU,YAAY;;;;;;;;;;;;;;;;;KAkBzB,wBACO,4BACE,YAAY,4BACd,QAAQ,cAAc,QAAQ;;;;wBAK3B,mBAAmB,mBAC5B,kBACD,YAAY,UAAU,oBAChB,eACJ,cAAc,YAAY"}
|
package/dist/types.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as Decision, c as PermitConfig, d as Resources, f as Role, i as Context, l as Policy, m as Rules, n as Actions, o as InferAction, p as RoleHierarchy, r as ConditionFn, s as InferResource, t as ActionPolicyMap, u as PolicyFn } from "./types-
|
|
1
|
+
import { a as Decision, c as PermitConfig, d as Resources, f as Role, i as Context, l as Policy, m as Rules, n as Actions, o as InferAction, p as RoleHierarchy, r as ConditionFn, s as InferResource, t as ActionPolicyMap, u as PolicyFn } from "./types-BgG1Aq6K.mjs";
|
|
2
2
|
export { ActionPolicyMap, Actions, ConditionFn, Context, Decision, InferAction, InferResource, PermitConfig, Policy, PolicyFn, Resources, Role, RoleHierarchy, Rules };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zap-studio/permit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@standard-schema/spec": "^1.
|
|
37
|
+
"@standard-schema/spec": "^1.1.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^25.0.2",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"tsdown": "^0.18.0",
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"vitest": "^4.0.15",
|
|
45
|
+
"@zap-studio/vitest-config": "0.0.0",
|
|
45
46
|
"@zap-studio/tsdown-config": "0.0.0",
|
|
46
|
-
"@zap-studio/typescript-config": "0.0.0"
|
|
47
|
-
"@zap-studio/vitest-config": "0.0.0"
|
|
47
|
+
"@zap-studio/typescript-config": "0.0.0"
|
|
48
48
|
},
|
|
49
49
|
"exports": {
|
|
50
50
|
".": "./dist/index.mjs",
|
package/dist/errors.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors.mjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["/**\n * Represents an error that occurs during policy evaluation or enforcement.\n * Use this error to indicate issues related to policy logic, configuration, or execution.\n */\nexport class PolicyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"PolicyError\";\n }\n}\n"],"mappings":";;;;;AAIA,IAAa,cAAb,cAAiC,MAAM;CACrC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO"}
|