@cerbos/orm-prisma 2.0.0 → 3.0.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/README.md CHANGED
@@ -16,7 +16,7 @@ An adapter library that takes a [Cerbos](https://cerbos.dev) Query Plan ([PlanRe
16
16
 
17
17
  - One-to-one: `is`, `isNot`
18
18
  - One-to-many/Many-to-many: `some`, `none`, `every`
19
- - Collection operators: `exists`, `exists_one`, `all`, `filter`
19
+ - Collection operators: `exists`, `exists_one`, `all`, `filter`, `except`
20
20
  - Set operations: `hasIntersection`
21
21
 
22
22
  #### Advanced Features
@@ -33,6 +33,12 @@ An adapter library that takes a [Cerbos](https://cerbos.dev) Query Plan ([PlanRe
33
33
  - `@cerbos/http` or `@cerbos/grpc` client
34
34
  - Prisma > v6.0
35
35
 
36
+ ## System Requirements
37
+
38
+ - Node.js >= 20.0.
39
+ - Prisma CLI & Client >= 6.0
40
+ - A database supported by Prisma (SQLite/PostgreSQL/MySQL/etc.) so the Prisma client can communicate with stored data
41
+
36
42
  ## Installation
37
43
 
38
44
  ```bash
@@ -145,6 +151,37 @@ const records = await prisma.resource.findMany({
145
151
  });
146
152
  ```
147
153
 
154
+ ### Collection Operators
155
+
156
+ The adapter understands the full Cerbos collection operator set, including `except`. For example, the configuration below ensures a resource’s categories do not have any sub-category named `finance`:
157
+
158
+ ```ts
159
+ const result = queryPlanToPrisma({
160
+ queryPlan,
161
+ mapper: {
162
+ "request.resource.attr.categories": {
163
+ relation: {
164
+ name: "categories",
165
+ type: "many",
166
+ fields: {
167
+ subCategories: {
168
+ relation: {
169
+ name: "subCategories",
170
+ type: "many",
171
+ fields: {
172
+ name: { field: "name" },
173
+ },
174
+ },
175
+ },
176
+ },
177
+ },
178
+ },
179
+ },
180
+ });
181
+ ```
182
+
183
+ `queryPlanToPrisma` emits the necessary nested `NOT` structure so Prisma receives a valid filter for the entire relation chain.
184
+
148
185
  ### Field Name Mapping
149
186
 
150
187
  Fields can be mapped using either an object or a function:
@@ -237,6 +274,14 @@ When using relations, fields are automatically inferred from the path unless exp
237
274
  }
238
275
  ```
239
276
 
277
+ ### Handling `in` Operators
278
+
279
+ `queryPlanToPrisma` normalises Cerbos `in` expressions to match Prisma expectations:
280
+
281
+ - Single values become equality comparisons (`{ field: "value" }`).
282
+ - Arrays remain `{ field: { in: [...] } }`.
283
+ - Relation-backed fields retain their relation structure while still applying the appropriate equality or `in` operator at the leaf.
284
+
240
285
  ### Complex Example with Multiple Relations and Direct Fields
241
286
 
242
287
  ```ts
@@ -321,6 +366,18 @@ const result = await primsa.resource.findMany({
321
366
  });
322
367
  ```
323
368
 
369
+ ## Development
370
+
371
+ ### Running Tests
372
+
373
+ ```bash
374
+ npm test
375
+ ```
376
+
377
+ > **Note:** The suite seeds `prisma/dev.db` and invokes `prisma db push --force-reset`. Only run it against disposable development databases.
378
+
379
+ The tests populate Prisma with fixture data and assert query results directly against those fixtures, covering scalar and relation `in` operators, collection behaviour (including `except`), nested relations, and lambda expressions.
380
+
324
381
  ## Types
325
382
 
326
383
  ### Query Plan Response Types
package/lib/index.d.ts CHANGED
@@ -7,14 +7,10 @@ export type MapperConfig = {
7
7
  name: string;
8
8
  type: "one" | "many";
9
9
  field?: string;
10
- fields?: {
11
- [key: string]: MapperConfig;
12
- };
10
+ fields?: Record<string, MapperConfig>;
13
11
  };
14
12
  };
15
- export type Mapper = {
16
- [key: string]: MapperConfig;
17
- } | ((key: string) => MapperConfig);
13
+ export type Mapper = Record<string, MapperConfig> | ((key: string) => MapperConfig);
18
14
  export interface QueryPlanToPrismaArgs {
19
15
  queryPlan: PlanResourcesResponse;
20
16
  mapper?: Mapper;
@@ -23,11 +19,10 @@ export type QueryPlanToPrismaResult = {
23
19
  kind: PlanKind.ALWAYS_ALLOWED | PlanKind.ALWAYS_DENIED;
24
20
  } | {
25
21
  kind: PlanKind.CONDITIONAL;
26
- filters: Record<string, any>;
22
+ filters: PrismaFilter;
27
23
  };
28
24
  /**
29
25
  * Converts a Cerbos query plan to a Prisma filter.
30
- * @param {QueryPlanToPrismaArgs} args - The arguments containing the query plan and mapper.
31
- * @returns {QueryPlanToPrismaResult} The result containing the kind and filters.
32
26
  */
33
27
  export declare function queryPlanToPrisma({ queryPlan, mapper, }: QueryPlanToPrismaArgs): QueryPlanToPrismaResult;
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EAErB,QAAQ,EAET,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,QAAQ,EAAE,CAAC;AAGpB,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAE/C,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;KACvC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAC5B,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,CAAC,CAAC;AAEpC,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,qBAAqB,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,uBAAuB,GAC/B;IACE,IAAI,EAAE,QAAQ,CAAC,cAAc,GAAG,QAAQ,CAAC,aAAa,CAAC;CACxD,GACD;IACE,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC;IAC3B,OAAO,EAAE,YAAY,CAAC;CACvB,CAAC;AA2FN;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,MAAW,GACZ,EAAE,qBAAqB,GAAG,uBAAuB,CAiBjD"}