toride 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.
@@ -0,0 +1,309 @@
1
+ import { P as Policy, T as TorideSchema, D as DefaultSchema, a as TorideOptions, A as ActorRef, R as ResourceRef, C as CheckOptions, E as ExplainResult, b as PermissionSnapshot, B as BatchCheckItem, c as TestCase, d as Resolvers } from './client-RqwW0K_-.js';
2
+ export { e as ActorDeclaration, f as AttributeType, g as ClientResourceRef, h as ConditionExpression, i as ConditionOperator, j as ConditionValue, k as CycleError, l as DecisionEvent, m as DepthLimitError, n as DerivedRoleEntry, o as DerivedRoleTrace, p as EvaluatorFn, F as FieldAccessDef, G as GlobalRole, M as MatchedRule, Q as QueryEvent, q as ResolvedRolesDetail, r as ResourceBlock, s as ResourceResolver, t as Rule, S as SimpleConditions, u as TorideClient, V as ValidationError } from './client-RqwW0K_-.js';
3
+
4
+ /**
5
+ * Parse and validate a YAML string into a typed Policy object.
6
+ * Uses the `yaml` package with pretty errors.
7
+ */
8
+ declare function loadYaml(input: string): Promise<Policy>;
9
+ /**
10
+ * Parse and validate a JSON string into a typed Policy object.
11
+ */
12
+ declare function loadJson(input: string): Promise<Policy>;
13
+
14
+ /**
15
+ * Merge two policies into one.
16
+ *
17
+ * - Actors: additive union of actor types and their attributes
18
+ * - Global roles: additive union (overlay wins on conflict)
19
+ * - Resources: additive union of resource types; overlapping resources merge
20
+ * roles, permissions, relations, derived_roles, rules, and field_access
21
+ * - Grants: throws on conflicting grants (same role, different permission sets)
22
+ * - Rules: silently appended
23
+ * - Tests: dropped (not merged)
24
+ */
25
+ declare function mergePolicies(base: Policy, overlay: Policy): Policy;
26
+
27
+ /** A single validation diagnostic (error or warning). */
28
+ interface ValidationDiagnostic {
29
+ readonly message: string;
30
+ readonly path: string;
31
+ }
32
+ /** Result from non-throwing validation. */
33
+ interface ValidationResult {
34
+ readonly errors: ValidationDiagnostic[];
35
+ }
36
+ /** Result from strict validation (errors + warnings). */
37
+ interface StrictValidationResult {
38
+ readonly errors: ValidationDiagnostic[];
39
+ readonly warnings: ValidationDiagnostic[];
40
+ }
41
+ /**
42
+ * Validate cross-references in a structurally valid policy.
43
+ * Collects ALL errors and throws ValidationError with all messages.
44
+ * Backward compatible: always throws on first error set.
45
+ */
46
+ declare function validatePolicy(policy: Policy): void;
47
+ /**
48
+ * Non-throwing validation: returns all errors as an array.
49
+ * Used by CLI and programmatic consumers that want to collect errors.
50
+ */
51
+ declare function validatePolicyResult(policy: Policy): ValidationResult;
52
+ /**
53
+ * Strict validation: returns errors + static analysis warnings.
54
+ * Errors are the same as validatePolicy().
55
+ * Warnings include unused roles, unreachable rules, redundant derivations.
56
+ */
57
+ declare function validatePolicyStrict(policy: Policy): StrictValidationResult;
58
+
59
+ interface FieldEqConstraint {
60
+ readonly type: "field_eq";
61
+ readonly field: string;
62
+ readonly value: unknown;
63
+ }
64
+ interface FieldNeqConstraint {
65
+ readonly type: "field_neq";
66
+ readonly field: string;
67
+ readonly value: unknown;
68
+ }
69
+ interface FieldGtConstraint {
70
+ readonly type: "field_gt";
71
+ readonly field: string;
72
+ readonly value: unknown;
73
+ }
74
+ interface FieldGteConstraint {
75
+ readonly type: "field_gte";
76
+ readonly field: string;
77
+ readonly value: unknown;
78
+ }
79
+ interface FieldLtConstraint {
80
+ readonly type: "field_lt";
81
+ readonly field: string;
82
+ readonly value: unknown;
83
+ }
84
+ interface FieldLteConstraint {
85
+ readonly type: "field_lte";
86
+ readonly field: string;
87
+ readonly value: unknown;
88
+ }
89
+ interface FieldInConstraint {
90
+ readonly type: "field_in";
91
+ readonly field: string;
92
+ readonly values: unknown[];
93
+ }
94
+ interface FieldNinConstraint {
95
+ readonly type: "field_nin";
96
+ readonly field: string;
97
+ readonly values: unknown[];
98
+ }
99
+ interface FieldExistsConstraint {
100
+ readonly type: "field_exists";
101
+ readonly field: string;
102
+ readonly exists: boolean;
103
+ }
104
+ interface FieldIncludesConstraint {
105
+ readonly type: "field_includes";
106
+ readonly field: string;
107
+ readonly value: unknown;
108
+ }
109
+ interface FieldContainsConstraint {
110
+ readonly type: "field_contains";
111
+ readonly field: string;
112
+ readonly value: string;
113
+ }
114
+ interface RelationConstraint {
115
+ readonly type: "relation";
116
+ readonly field: string;
117
+ readonly resourceType: string;
118
+ readonly constraint: Constraint;
119
+ }
120
+ interface HasRoleConstraint {
121
+ readonly type: "has_role";
122
+ readonly actorId: string;
123
+ readonly actorType: string;
124
+ readonly role: string;
125
+ }
126
+ interface UnknownConstraint {
127
+ readonly type: "unknown";
128
+ readonly name: string;
129
+ }
130
+ interface AndConstraint {
131
+ readonly type: "and";
132
+ readonly children: Constraint[];
133
+ }
134
+ interface OrConstraint {
135
+ readonly type: "or";
136
+ readonly children: Constraint[];
137
+ }
138
+ interface NotConstraint {
139
+ readonly type: "not";
140
+ readonly child: Constraint;
141
+ }
142
+ interface AlwaysConstraint {
143
+ readonly type: "always";
144
+ }
145
+ interface NeverConstraint {
146
+ readonly type: "never";
147
+ }
148
+ /** Full constraint discriminated union (AST node). */
149
+ type Constraint = FieldEqConstraint | FieldNeqConstraint | FieldGtConstraint | FieldGteConstraint | FieldLtConstraint | FieldLteConstraint | FieldInConstraint | FieldNinConstraint | FieldExistsConstraint | FieldIncludesConstraint | FieldContainsConstraint | RelationConstraint | HasRoleConstraint | UnknownConstraint | AndConstraint | OrConstraint | NotConstraint | AlwaysConstraint | NeverConstraint;
150
+ /** Leaf constraint subset for ConstraintAdapter.translate(). */
151
+ type LeafConstraint = FieldEqConstraint | FieldNeqConstraint | FieldGtConstraint | FieldGteConstraint | FieldLtConstraint | FieldLteConstraint | FieldInConstraint | FieldNinConstraint | FieldExistsConstraint | FieldIncludesConstraint | FieldContainsConstraint;
152
+ /** Result of partial evaluation. */
153
+ type ConstraintResult = {
154
+ readonly unrestricted: true;
155
+ } | {
156
+ readonly forbidden: true;
157
+ } | {
158
+ readonly constraints: Constraint;
159
+ };
160
+ /** User-provided adapter for translating constraint ASTs to queries. */
161
+ interface ConstraintAdapter<TQuery> {
162
+ translate(constraint: LeafConstraint): TQuery;
163
+ relation(field: string, resourceType: string, childQuery: TQuery): TQuery;
164
+ hasRole(actorId: string, actorType: string, role: string): TQuery;
165
+ unknown(name: string): TQuery;
166
+ and(queries: TQuery[]): TQuery;
167
+ or(queries: TQuery[]): TQuery;
168
+ not(query: TQuery): TQuery;
169
+ }
170
+
171
+ /**
172
+ * Main authorization engine.
173
+ * Creates a per-check cache, resolves direct roles, checks grants,
174
+ * and returns boolean with default-deny semantics.
175
+ */
176
+ declare class Toride<S extends TorideSchema = DefaultSchema> {
177
+ private policy;
178
+ private readonly resolvers;
179
+ private readonly options;
180
+ constructor(options: TorideOptions<S>);
181
+ /**
182
+ * Check if an actor can perform an action on a resource.
183
+ * Default-deny: returns false if resource type is unknown or no grants match.
184
+ */
185
+ can<R extends S["resources"]>(actor: ActorRef<S>, action: S["permissionMap"][R], resource: ResourceRef<S, R>, options?: CheckOptions): Promise<boolean>;
186
+ /**
187
+ * T097: Atomic policy swap. In-flight checks capture the resource block
188
+ * at the start of evaluateInternal, so they complete with the old policy.
189
+ * JS single-threaded nature ensures the assignment is atomic.
190
+ */
191
+ setPolicy(policy: Policy): void;
192
+ /**
193
+ * T068: Return full ExplainResult with role derivation traces,
194
+ * granted permissions, matched rules, and human-readable final decision.
195
+ */
196
+ explain<R extends S["resources"]>(actor: ActorRef<S>, action: S["permissionMap"][R], resource: ResourceRef<S, R>, options?: CheckOptions): Promise<ExplainResult<S, R>>;
197
+ /**
198
+ * T069: Check all declared permissions for a resource and return permitted ones.
199
+ * Uses a shared cache across all per-action evaluations.
200
+ */
201
+ permittedActions<R extends S["resources"]>(actor: ActorRef<S>, resource: ResourceRef<S, R>, options?: CheckOptions): Promise<S["permissionMap"][R][]>;
202
+ /**
203
+ * T083: Generate a PermissionSnapshot for a list of resources.
204
+ * Calls permittedActions() for each resource and returns a map
205
+ * keyed by "Type:id" with arrays of permitted action strings.
206
+ * Suitable for serializing to the client via TorideClient.
207
+ */
208
+ snapshot(actor: ActorRef<S>, resources: ResourceRef<S>[], options?: CheckOptions): Promise<PermissionSnapshot>;
209
+ /**
210
+ * T095: Check if an actor can perform a field-level operation on a specific field.
211
+ * Restricted fields require the actor to have a role listed in field_access.
212
+ * Unlisted fields are unrestricted: any actor with the resource-level permission can access them.
213
+ */
214
+ canField<R extends S["resources"]>(actor: ActorRef<S>, operation: "read" | "update", resource: ResourceRef<S, R>, field: string, options?: CheckOptions): Promise<boolean>;
215
+ /**
216
+ * T095: Return the list of declared field_access field names the actor can access
217
+ * for the given operation. Only returns explicitly declared fields.
218
+ */
219
+ permittedFields<R extends S["resources"]>(actor: ActorRef<S>, operation: "read" | "update", resource: ResourceRef<S, R>, options?: CheckOptions): Promise<string[]>;
220
+ /**
221
+ * T070: Return flat deduplicated list of all resolved roles (direct + derived).
222
+ */
223
+ resolvedRoles<R extends S["resources"]>(actor: ActorRef<S>, resource: ResourceRef<S, R>, options?: CheckOptions): Promise<string[]>;
224
+ /**
225
+ * T071: Evaluate multiple checks for the same actor with a shared resolver cache.
226
+ * Returns boolean[] in the same order as the input checks.
227
+ */
228
+ canBatch(actor: ActorRef<S>, checks: BatchCheckItem<S>[], options?: CheckOptions): Promise<boolean[]>;
229
+ /**
230
+ * T064: Build constraint AST for partial evaluation / data filtering.
231
+ * Returns ConstraintResult with unrestricted/forbidden sentinels or constraint AST.
232
+ */
233
+ buildConstraints<R extends S["resources"]>(actor: ActorRef<S>, action: S["permissionMap"][R], resourceType: R, options?: CheckOptions): Promise<ConstraintResult>;
234
+ /**
235
+ * T064: Translate constraint AST using an adapter.
236
+ * Dispatches each constraint node to the adapter's methods.
237
+ */
238
+ translateConstraints<TQuery>(constraints: Constraint, adapter: ConstraintAdapter<TQuery>): TQuery;
239
+ /**
240
+ * T072: Fire onDecision audit callback via microtask (non-blocking).
241
+ * Errors are silently swallowed to prevent audit failures from affecting authorization.
242
+ */
243
+ private fireDecisionEvent;
244
+ /**
245
+ * T072: Fire onQuery audit callback via microtask (non-blocking).
246
+ * Errors are silently swallowed.
247
+ */
248
+ private fireQueryEvent;
249
+ /**
250
+ * Evaluate with full ExplainResult (shared code path for can(), explain(), and helpers).
251
+ * Accepts an optional pre-existing AttributeCache for shared-cache scenarios (canBatch, permittedActions).
252
+ */
253
+ private evaluateInternal;
254
+ }
255
+ /**
256
+ * Typed factory function for creating a Toride instance.
257
+ */
258
+ declare function createToride<S extends TorideSchema = DefaultSchema>(options: TorideOptions<S>): Toride<S>;
259
+
260
+ /**
261
+ * Constructs a Resolvers map from test case mock data.
262
+ * Uses "Type:id" format as keys in the TestCase.resolvers map.
263
+ * Each entry maps to an attribute object that the mock resolver returns.
264
+ *
265
+ * Example TestCase.resolvers:
266
+ * { "Document:doc1": { status: "draft", owner_id: "u1" },
267
+ * "Organization:org1": { plan: "enterprise" } }
268
+ *
269
+ * This produces a Resolvers map where each resource type has a resolver
270
+ * that looks up the attributes by "Type:id" key.
271
+ */
272
+ declare function createMockResolver(testCase: TestCase): Resolvers;
273
+
274
+ /** Result of parsing a separate .test.yaml file. */
275
+ interface TestFileResult {
276
+ policyPath: string;
277
+ tests: TestCase[];
278
+ }
279
+ /**
280
+ * Extract inline tests from a loaded Policy object.
281
+ * Returns the policy (unchanged) and the test cases (or empty array if none).
282
+ */
283
+ declare function parseInlineTests(policy: Policy): {
284
+ policy: Policy;
285
+ tests: TestCase[];
286
+ };
287
+ /**
288
+ * Parse a separate .test.yaml file content string.
289
+ * Returns the path to the policy file and the test cases.
290
+ */
291
+ declare function parseTestFile(yamlContent: string): TestFileResult;
292
+
293
+ /** Result of a single test case execution. */
294
+ interface TestResult {
295
+ name: string;
296
+ passed: boolean;
297
+ expected: "allow" | "deny";
298
+ actual: "allow" | "deny";
299
+ }
300
+ /**
301
+ * Run a set of test cases against a policy.
302
+ * Creates a fresh engine per test case for isolation.
303
+ * Global roles are derived from actor attributes -- never mocked.
304
+ */
305
+ declare function runTestCases(policy: Policy, tests: TestCase[]): Promise<TestResult[]>;
306
+
307
+ declare const VERSION = "0.0.1";
308
+
309
+ export { ActorRef, BatchCheckItem, CheckOptions, type Constraint, type ConstraintAdapter, type ConstraintResult, DefaultSchema, ExplainResult, type LeafConstraint, PermissionSnapshot, Policy, Resolvers, ResourceRef, type StrictValidationResult, TestCase, type TestFileResult, type TestResult, Toride, TorideOptions, TorideSchema, VERSION, type ValidationDiagnostic, type ValidationResult, createMockResolver, createToride, loadJson, loadYaml, mergePolicies, parseInlineTests, parseTestFile, runTestCases, validatePolicy, validatePolicyResult, validatePolicyStrict };
package/dist/index.js ADDED
@@ -0,0 +1,246 @@
1
+ import {
2
+ CycleError,
3
+ DepthLimitError,
4
+ PolicySchema,
5
+ Toride,
6
+ ValidationError,
7
+ createMockResolver,
8
+ createToride,
9
+ parseInlineTests,
10
+ parseTestFile,
11
+ runTestCases,
12
+ validatePolicy,
13
+ validatePolicyResult,
14
+ validatePolicyStrict
15
+ } from "./chunk-24PMDTLE.js";
16
+ import {
17
+ TorideClient
18
+ } from "./chunk-475CNU63.js";
19
+
20
+ // src/policy/parser.ts
21
+ import * as YAML from "yaml";
22
+ import * as v from "valibot";
23
+ function detectOldRelationSyntax(raw) {
24
+ if (typeof raw !== "object" || raw === null) return;
25
+ const obj = raw;
26
+ const resources = obj.resources;
27
+ if (typeof resources !== "object" || resources === null) return;
28
+ for (const [resName, resDef] of Object.entries(
29
+ resources
30
+ )) {
31
+ if (typeof resDef !== "object" || resDef === null) continue;
32
+ const relations = resDef.relations;
33
+ if (typeof relations !== "object" || relations === null) continue;
34
+ for (const [relName, relDef] of Object.entries(
35
+ relations
36
+ )) {
37
+ if (typeof relDef === "object" && relDef !== null) {
38
+ const relObj = relDef;
39
+ if ("resource" in relObj) {
40
+ const targetType = String(relObj.resource ?? relName);
41
+ throw new ValidationError(
42
+ `Relation "${relName}" on resource "${resName}" uses the old object syntax ({ resource: ..., cardinality: ... }). Relations must now be a plain type name. Change to: ${relName}: ${targetType}`,
43
+ `resources.${resName}.relations.${relName}`
44
+ );
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ function parsePolicy(raw) {
51
+ detectOldRelationSyntax(raw);
52
+ const result = v.safeParse(PolicySchema, raw);
53
+ if (!result.success) {
54
+ const issue = result.issues[0];
55
+ const path = issue?.path?.map((p) => String(p.key)).join(".") ?? "";
56
+ throw new ValidationError(
57
+ `Policy validation failed: ${issue?.message ?? "unknown error"}${path ? ` at ${path}` : ""}`,
58
+ path
59
+ );
60
+ }
61
+ const policy = result.output;
62
+ validatePolicy(policy);
63
+ return policy;
64
+ }
65
+ async function loadYaml(input) {
66
+ let raw;
67
+ try {
68
+ raw = YAML.parse(input, { prettyErrors: true });
69
+ } catch (err) {
70
+ throw new ValidationError(
71
+ `YAML parse error: ${err instanceof Error ? err.message : String(err)}`,
72
+ ""
73
+ );
74
+ }
75
+ return parsePolicy(raw);
76
+ }
77
+ async function loadJson(input) {
78
+ let raw;
79
+ try {
80
+ raw = JSON.parse(input);
81
+ } catch (err) {
82
+ throw new ValidationError(
83
+ `JSON parse error: ${err instanceof Error ? err.message : String(err)}`,
84
+ ""
85
+ );
86
+ }
87
+ return parsePolicy(raw);
88
+ }
89
+
90
+ // src/policy/merger.ts
91
+ var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
92
+ function assertNoDangerousKeys(obj, context) {
93
+ for (const key of Object.keys(obj)) {
94
+ if (DANGEROUS_KEYS.has(key)) {
95
+ throw new Error(`Dangerous key "${key}" detected in ${context}`);
96
+ }
97
+ }
98
+ }
99
+ function mergePolicies(base, overlay) {
100
+ const actors = mergeActors(base.actors, overlay.actors);
101
+ const global_roles = mergeGlobalRoles(base.global_roles, overlay.global_roles);
102
+ const resources = mergeResources(base.resources, overlay.resources);
103
+ const result = {
104
+ version: "1",
105
+ actors,
106
+ resources
107
+ };
108
+ if (global_roles && Object.keys(global_roles).length > 0) {
109
+ result.global_roles = global_roles;
110
+ }
111
+ return result;
112
+ }
113
+ function mergeActors(base, overlay) {
114
+ assertNoDangerousKeys(base, "base actors");
115
+ assertNoDangerousKeys(overlay, "overlay actors");
116
+ const result = { ...base };
117
+ for (const [name, actor] of Object.entries(overlay)) {
118
+ if (result[name]) {
119
+ result[name] = {
120
+ attributes: { ...result[name].attributes, ...actor.attributes }
121
+ };
122
+ } else {
123
+ result[name] = actor;
124
+ }
125
+ }
126
+ return result;
127
+ }
128
+ function mergeGlobalRoles(base, overlay) {
129
+ if (!base && !overlay) return void 0;
130
+ if (base) assertNoDangerousKeys(base, "base global_roles");
131
+ if (overlay) assertNoDangerousKeys(overlay, "overlay global_roles");
132
+ return { ...base ?? {}, ...overlay ?? {} };
133
+ }
134
+ function mergeResources(base, overlay) {
135
+ assertNoDangerousKeys(base, "base resources");
136
+ assertNoDangerousKeys(overlay, "overlay resources");
137
+ const result = {};
138
+ for (const [name, block] of Object.entries(base)) {
139
+ result[name] = block;
140
+ }
141
+ for (const [name, overlayBlock] of Object.entries(overlay)) {
142
+ if (result[name]) {
143
+ result[name] = mergeResourceBlock(name, result[name], overlayBlock);
144
+ } else {
145
+ result[name] = overlayBlock;
146
+ }
147
+ }
148
+ return result;
149
+ }
150
+ function mergeResourceBlock(resourceName, base, overlay) {
151
+ const roles = unionArrays(base.roles, overlay.roles);
152
+ const permissions = unionArrays(base.permissions, overlay.permissions);
153
+ const grants = mergeGrants(resourceName, base.grants, overlay.grants);
154
+ const relations = mergeRelations(base.relations, overlay.relations);
155
+ const derived_roles = appendArrays(base.derived_roles, overlay.derived_roles);
156
+ const rules = appendArrays(base.rules, overlay.rules);
157
+ const field_access = mergeFieldAccess(base.field_access, overlay.field_access);
158
+ const result = {
159
+ roles,
160
+ permissions,
161
+ ...grants && Object.keys(grants).length > 0 ? { grants } : {},
162
+ ...relations && Object.keys(relations).length > 0 ? { relations } : {},
163
+ ...derived_roles && derived_roles.length > 0 ? { derived_roles } : {},
164
+ ...rules && rules.length > 0 ? { rules } : {},
165
+ ...field_access && Object.keys(field_access).length > 0 ? { field_access } : {}
166
+ };
167
+ return result;
168
+ }
169
+ function unionArrays(a, b) {
170
+ return [.../* @__PURE__ */ new Set([...a, ...b])];
171
+ }
172
+ function appendArrays(a, b) {
173
+ if (!a && !b) return void 0;
174
+ return [...a ?? [], ...b ?? []];
175
+ }
176
+ function mergeGrants(resourceName, base, overlay) {
177
+ if (!base && !overlay) return void 0;
178
+ if (!base) return overlay;
179
+ if (!overlay) return base;
180
+ assertNoDangerousKeys(base, "base grants");
181
+ assertNoDangerousKeys(overlay, "overlay grants");
182
+ const result = { ...base };
183
+ for (const [role, perms] of Object.entries(overlay)) {
184
+ if (result[role]) {
185
+ const existingSet = new Set(result[role]);
186
+ const newSet = new Set(perms);
187
+ if (existingSet.size !== newSet.size || ![...existingSet].every((p) => newSet.has(p))) {
188
+ throw new Error(
189
+ `Grant conflict on resource "${resourceName}": role "${role}" has different permission sets. Base: [${result[role].join(", ")}], Overlay: [${perms.join(", ")}]`
190
+ );
191
+ }
192
+ } else {
193
+ result[role] = perms;
194
+ }
195
+ }
196
+ return result;
197
+ }
198
+ function mergeRelations(base, overlay) {
199
+ if (!base && !overlay) return void 0;
200
+ if (base) assertNoDangerousKeys(base, "base relations");
201
+ if (overlay) assertNoDangerousKeys(overlay, "overlay relations");
202
+ return { ...base ?? {}, ...overlay ?? {} };
203
+ }
204
+ function mergeFieldAccess(base, overlay) {
205
+ if (!base && !overlay) return void 0;
206
+ if (!base) return overlay;
207
+ if (!overlay) return base;
208
+ assertNoDangerousKeys(base, "base field_access");
209
+ assertNoDangerousKeys(overlay, "overlay field_access");
210
+ const result = { ...base };
211
+ for (const [field, def] of Object.entries(overlay)) {
212
+ if (result[field]) {
213
+ const mergedRead = unionArrays(result[field].read ?? [], def.read ?? []);
214
+ const mergedUpdate = unionArrays(result[field].update ?? [], def.update ?? []);
215
+ const merged = {};
216
+ if (mergedRead.length > 0) merged.read = mergedRead;
217
+ if (mergedUpdate.length > 0) merged.update = mergedUpdate;
218
+ result[field] = merged;
219
+ } else {
220
+ result[field] = def;
221
+ }
222
+ }
223
+ return result;
224
+ }
225
+
226
+ // src/index.ts
227
+ var VERSION = "0.0.1";
228
+ export {
229
+ CycleError,
230
+ DepthLimitError,
231
+ Toride,
232
+ TorideClient,
233
+ VERSION,
234
+ ValidationError,
235
+ createMockResolver,
236
+ createToride,
237
+ loadJson,
238
+ loadYaml,
239
+ mergePolicies,
240
+ parseInlineTests,
241
+ parseTestFile,
242
+ runTestCases,
243
+ validatePolicy,
244
+ validatePolicyResult,
245
+ validatePolicyStrict
246
+ };
package/package.json CHANGED
@@ -1,12 +1,55 @@
1
1
  {
2
2
  "name": "toride",
3
- "version": "0.0.1",
3
+ "version": "0.2.0",
4
4
  "description": "Relation-aware authorization engine for TypeScript",
5
- "main": "index.js",
6
- "keywords": ["authorization", "rbac", "rebac", "abac", "permissions"],
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ },
11
+ "./client": {
12
+ "types": "./dist/client.d.ts",
13
+ "import": "./dist/client.js"
14
+ }
15
+ },
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "bin": {
19
+ "toride": "./dist/cli.js"
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "nx": {
25
+ "tags": [
26
+ "type:core"
27
+ ]
28
+ },
29
+ "dependencies": {
30
+ "valibot": "^1.2.0",
31
+ "yaml": "^2.3.0"
32
+ },
33
+ "keywords": [
34
+ "authorization",
35
+ "rbac",
36
+ "rebac",
37
+ "abac",
38
+ "permissions"
39
+ ],
7
40
  "license": "MIT",
8
41
  "repository": {
9
42
  "type": "git",
10
43
  "url": "https://github.com/toride-auth/toride"
44
+ },
45
+ "devDependencies": {
46
+ "tsd": "^0.33.0"
47
+ },
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "test": "vitest run",
51
+ "typetest": "tsd --files 'src/__typetests__/*.test-d.ts'",
52
+ "lint": "tsc --noEmit",
53
+ "bench": "vitest bench"
11
54
  }
12
- }
55
+ }
package/index.js DELETED
@@ -1 +0,0 @@
1
- // Coming soon