convex-helpers
Advanced tools
Comparing version 0.1.57 to 0.1.58
{ | ||
"name": "convex-helpers", | ||
"version": "0.1.57", | ||
"version": "0.1.58", | ||
"description": "A collection of useful code to complement the official convex package.", | ||
@@ -46,2 +46,6 @@ "type": "module", | ||
}, | ||
"./server/crud": { | ||
"types": "./server/crud.d.ts", | ||
"default": "./server/crud.js" | ||
}, | ||
"./server/customFunctions": { | ||
@@ -48,0 +52,0 @@ "types": "./server/customFunctions.d.ts", |
@@ -424,6 +424,57 @@ # convex-helpers | ||
Use the [RowLevelSecurity](./server/rowLevelSecurity.ts) helper to define | ||
`withQueryRLS` and `withMutationRLS` wrappers to add row-level checks for a | ||
server-side function. Any access to `db` inside functions wrapped with these | ||
database wrappers to add row-level checks for a server-side function. | ||
Any access to `db` inside functions wrapped with these | ||
will check your access rules on read/insert/modify per-document. | ||
```ts | ||
import { | ||
customCtx, | ||
customMutation, | ||
customQuery, | ||
} from "convex-helpers/server/customFunctions"; | ||
import { | ||
Rules, | ||
wrapDatabaseReader, | ||
wrapDatabaseWriter, | ||
} from "convex-helpers/server/rowLevelSecurity"; | ||
import { DataModel } from "./_generated/dataModel"; | ||
import { mutation, query, QueryCtx } from "./_generated/server"; | ||
async function rlsRules(ctx: QueryCtx) { | ||
const identity = await ctx.auth.getUserIdentity(); | ||
return { | ||
users: { | ||
read: async (_, user) => { | ||
// Unauthenticated users can only read users over 18 | ||
if (!identity && user.age < 18) return false; | ||
return true; | ||
}, | ||
insert: async (_, user) => { | ||
return true; | ||
}, | ||
modify: async (_, user) => { | ||
if (!identity) | ||
throw new Error("Must be authenticated to modify a user"); | ||
// Users can only modify their own user | ||
return user.tokenIdentifier === identity.tokenIdentifier; | ||
}, | ||
}, | ||
} satisfies Rules<QueryCtx, DataModel>; | ||
} | ||
const queryWithRLS = customQuery( | ||
query, | ||
customCtx(async (ctx) => ({ | ||
db: wrapDatabaseReader(ctx, ctx.db, await rlsRules(ctx)), | ||
})), | ||
); | ||
const mutationWithRLS = customMutation( | ||
mutation, | ||
customCtx(async (ctx) => ({ | ||
db: wrapDatabaseWriter(ctx, ctx.db, await rlsRules(ctx)), | ||
})), | ||
); | ||
``` | ||
## Zod Validation | ||
@@ -511,3 +562,4 @@ | ||
**Note: I recommend only doing this for prototyping or [internal functions](https://docs.convex.dev/functions/internal-functions)** | ||
See the associated [Stack post](https://stack.convex.dev/crud-and-rest). | ||
**Note: I recommend only doing this for prototyping or [internal functions](https://docs.convex.dev/functions/internal-functions) unless you add Row Level Security** | ||
@@ -517,19 +569,17 @@ Example: | ||
```ts | ||
// in convex/users.ts | ||
import { crud } from "convex-helpers/server"; | ||
import { internalMutation, internalQuery } from "../convex/_generated/server"; | ||
import { crud } from "convex-helpers/server/crud"; | ||
import schema from "./schema.js"; | ||
const Users = Table("users", {...}); | ||
export const { create, read, update, destroy } = crud(schema, "users"); | ||
export const { read, update } = crud(Users, internalQuery, internalMutation); | ||
// in convex/schema.ts | ||
import { Users } from "./users"; | ||
export default defineSchema({users: Users.table}); | ||
// in some file, in an action: | ||
const user = await ctx.runQuery(internal.users.read, { id: userId }); | ||
await ctx.runMutation(internal.users.update, { status: "inactive" }); | ||
await ctx.runMutation(internal.users.update, { | ||
id: userId, | ||
patch: { | ||
status: "inactive", | ||
}, | ||
}); | ||
``` | ||
@@ -536,0 +586,0 @@ |
@@ -108,2 +108,3 @@ import { QueryBuilder, MutationBuilder, GenericDataModel, WithoutSystemFields, DocumentByName, RegisteredMutation, RegisteredQuery, FunctionVisibility, paginationOptsValidator, PaginationResult } from "convex/server"; | ||
* | ||
* @deprecated Use `import { crud } from "convex-helpers/server/crud";` instead. | ||
* @param table The table to create CRUD operations for. | ||
@@ -110,0 +111,0 @@ * Of type returned from Table() in "convex-helpers/server". |
@@ -87,2 +87,3 @@ import { defineTable, paginationOptsValidator, } from "convex/server"; | ||
* | ||
* @deprecated Use `import { crud } from "convex-helpers/server/crud";` instead. | ||
* @param table The table to create CRUD operations for. | ||
@@ -89,0 +90,0 @@ * Of type returned from Table() in "convex-helpers/server". |
@@ -113,2 +113,3 @@ import { | ||
* | ||
* @deprecated Use `import { crud } from "convex-helpers/server/crud";` instead. | ||
* @param table The table to create CRUD operations for. | ||
@@ -115,0 +116,0 @@ * Of type returned from Table() in "convex-helpers/server". |
import { convexTest } from "convex-test"; | ||
import { expect, test } from "vitest"; | ||
import { crud } from "../server.js"; | ||
import { crud } from "./crud.js"; | ||
import { | ||
@@ -39,11 +39,4 @@ anyApi, | ||
export const { create, read, paginate, update, destroy } = crud( | ||
// We could use the Table helper instead, but showing it explicitly here. | ||
// E.g. Table("crud_example", ExampleFields) | ||
{ | ||
name: CrudTable, | ||
_id: v.id(CrudTable), | ||
withoutSystemFields: ExampleFields, | ||
}, | ||
internalQuery, | ||
internalMutation, | ||
schema, | ||
CrudTable, | ||
); | ||
@@ -93,11 +86,3 @@ | ||
const customCrud = crud( | ||
{ | ||
name: CrudTable, | ||
_id: v.id(CrudTable), | ||
withoutSystemFields: ExampleFields, | ||
}, | ||
customQ, | ||
customM, | ||
); | ||
const customCrud = crud(schema, CrudTable, customQ, customM); | ||
@@ -104,0 +89,0 @@ const customTestApi: ApiFromModules<{ |
@@ -17,3 +17,3 @@ import { convexTest } from "convex-test"; | ||
import { customCtx, customMutation } from "./customFunctions.js"; | ||
import { crud } from "../server.js"; | ||
import { crud } from "./crud.js"; | ||
@@ -116,10 +116,2 @@ const schema = defineSchema({ | ||
crud( | ||
{ | ||
_id: v.id("foo"), | ||
name: "foo", | ||
withoutSystemFields: { bar: v.number() }, | ||
}, | ||
queryGeneric, | ||
mutationWithRLS, | ||
); | ||
crud(schema, "users", queryGeneric, mutationWithRLS); |
Sorry, the diff of this file is not supported yet
752169
99
17748
861