convex-helpers
Advanced tools
Comparing version
{ | ||
"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
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
752169
3.57%99
4.21%17748
2.16%861
6.17%