New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

convex-helpers

Package Overview
Dependencies
Maintainers
5
Versions
144
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

convex-helpers - npm Package Compare versions

Comparing version 0.1.57-alpha.3 to 0.1.57

4

package.json
{
"name": "convex-helpers",
"version": "0.1.57-alpha.3",
"version": "0.1.57",
"description": "A collection of useful code to complement the official convex package.",

@@ -125,3 +125,3 @@ "type": "module",

"peerDependencies": {
"convex": "^1.13.0 || >=1.16.0-alpha.1",
"convex": "^1.13.0",
"hono": "^4.0.5",

@@ -128,0 +128,0 @@ "react": "^17.0.2 || ^18.0.0",

import { convexTest } from "convex-test";
import { expect, test } from "vitest";
import { crud } from ".";
import { crud } from "../server.js";
import {

@@ -16,2 +16,3 @@ anyApi,

import { modules } from "./setup.test";
import { customCtx, customMutation, customQuery } from "./customFunctions.js";

@@ -78,1 +79,53 @@ const ExampleFields = {

});
/**
* Custom function tests
*/
const customQ = customQuery(
internalQuery,
customCtx((ctx) => ({ foo: "bar" })),
);
const customM = customMutation(
internalMutation,
customCtx((ctx) => ({})),
);
const customCrud = crud(
{
name: CrudTable,
_id: v.id(CrudTable),
withoutSystemFields: ExampleFields,
},
customQ,
customM,
);
const customTestApi: ApiFromModules<{
fns: {
create: typeof customCrud.create;
read: typeof customCrud.read;
update: typeof customCrud.update;
paginate: typeof customCrud.paginate;
destroy: typeof customCrud.destroy;
};
}>["fns"] = anyApi["crud.test"] as any;
test("custom crud for table", async () => {
const t = convexTest(schema, modules);
const doc = await t.mutation(customTestApi.create, { foo: "", bar: null });
expect(doc).toMatchObject({ foo: "", bar: null });
const read = await t.query(customTestApi.read, { id: doc._id });
expect(read).toMatchObject(doc);
await t.mutation(customTestApi.update, {
id: doc._id,
patch: { foo: "new", bar: { n: 42 }, baz: true },
});
expect(await t.query(customTestApi.read, { id: doc._id })).toMatchObject({
foo: "new",
bar: { n: 42 },
baz: true,
});
await t.mutation(customTestApi.destroy, { id: doc._id });
expect(await t.query(customTestApi.read, { id: doc._id })).toBe(null);
});

@@ -13,3 +13,3 @@ /**

*/
import { GenericValidator, ObjectType, PropertyValidators } from "convex/values";
import { GenericValidator, ObjectType, PropertyValidators, Validator } from "convex/values";
import { ActionBuilder, ArgsArrayForOptionalValidator, ArgsArrayToObject, DefaultArgsForOptionalValidator, DefaultFunctionArgs, FunctionVisibility, GenericActionCtx, GenericDataModel, GenericMutationCtx, GenericQueryCtx, MutationBuilder, QueryBuilder, RegisteredAction, RegisteredMutation, RegisteredQuery, ReturnValueForOptionalValidator } from "convex/server";

@@ -232,3 +232,3 @@ /**

export type CustomBuilder<FuncType extends "query" | "mutation" | "action", ModArgsValidator extends PropertyValidators, ModCtx extends Record<string, any>, ModMadeArgs extends Record<string, any>, InputCtx, Visibility extends FunctionVisibility> = {
<ArgsValidator extends PropertyValidators | void, ReturnsValidator extends PropertyValidators | GenericValidator | void, ReturnValue extends ReturnValueForOptionalValidator<ReturnsValidator> = any, OneOrZeroArgs extends ArgsArrayForOptionalValidator<ArgsValidator> = DefaultArgsForOptionalValidator<ArgsValidator>>(func: {
<ArgsValidator extends PropertyValidators | void | Validator<any, any, any>, ReturnsValidator extends PropertyValidators | GenericValidator | void, ReturnValue extends ReturnValueForOptionalValidator<ReturnsValidator> = any, OneOrZeroArgs extends ArgsArrayForOptionalValidator<ArgsValidator> = DefaultArgsForOptionalValidator<ArgsValidator>>(func: {
args?: ArgsValidator;

@@ -239,3 +239,3 @@ returns?: ReturnsValidator;

(ctx: Overwrite<InputCtx, ModCtx>, ...args: ArgsForHandlerType<OneOrZeroArgs, ModMadeArgs>): ReturnValue;
}): Registration<FuncType, Visibility, ArgsArrayToObject<OneOrZeroArgs extends [infer A] ? [Expand<A & ObjectType<ModArgsValidator>>] : [ObjectType<ModArgsValidator>]>, ReturnValue>;
}): Registration<FuncType, Visibility, ArgsArrayToObject<ModArgsValidator extends Record<string, never> ? OneOrZeroArgs : OneOrZeroArgs extends [infer A] ? [Expand<A & ObjectType<ModArgsValidator>>] : [ObjectType<ModArgsValidator>]>, ReturnValue>;
};

@@ -242,0 +242,0 @@ export type CustomCtx<Builder> = Builder extends CustomBuilder<any, any, infer ModCtx, any, infer InputCtx, any> ? Overwrite<InputCtx, ModCtx> : never;

@@ -0,1 +1,14 @@

/**
* This file contains helpers for defining custom functions that modify the
* context and arguments of a Convex function. Allows you to:
*
* - Run authentication logic before the request starts.
* - Look up commonly used data and add it to the ctx argument.
* - Replace a ctx or argument field with a different value, such as a version
* of `db` that runs custom functions on data access.
* - Consume arguments from the client that are not passed to the query, such
* as taking in an authentication parameter like an API key or session ID.
* These arguments must be sent up by the client along with each request.
*/
import { asObjectValidator, v, } from "convex/values";
import { pick } from "../index.js";

@@ -198,6 +211,3 @@ /**

return builder({
args: {
...fn.args,
...inputArgs,
},
args: addArgs(fn.args, inputArgs),
returns: fn.returns,

@@ -224,1 +234,17 @@ handler: async (ctx, allArgs) => {

}
// Adds args to a property validator or validator
// Needs to call recursively in the case of unions.
function addArgs(validatorOrPropertyValidator, args) {
if (Object.keys(args).length === 0) {
return asObjectValidator(validatorOrPropertyValidator);
}
const validator = asObjectValidator(validatorOrPropertyValidator);
switch (validator.kind) {
case "object":
return v.object({ ...validator.fields, ...args });
case "union":
return v.union(...validator.members.map((m) => addArgs(m, args)));
default:
throw new Error("Cannot add arguments to a validator that is not an object or union.");
}
}

@@ -1,3 +0,4 @@

import { Equals, assert } from "..";
import { Equals, assert } from "../index.js";
import {
customAction,
CustomCtx,

@@ -7,7 +8,9 @@ customCtx,

customQuery,
} from "./customFunctions";
import { wrapDatabaseWriter } from "./rowLevelSecurity";
import { SessionId, vSessionId } from "./sessions";
} from "./customFunctions.js";
import { wrapDatabaseWriter } from "./rowLevelSecurity.js";
import { SessionId, vSessionId } from "./sessions.js";
import { convexTest } from "convex-test";
import {
ActionBuilder,
actionGeneric,
anyApi,

@@ -27,3 +30,3 @@ DataModelFromSchemaDefinition,

import { afterEach, beforeEach, describe, expect, test } from "vitest";
import { modules } from "./setup.test";
import { modules } from "./setup.test.js";

@@ -39,2 +42,3 @@ const schema = defineSchema({

const mutation = mutationGeneric as MutationBuilder<DataModel, "public">;
const action = actionGeneric as ActionBuilder<DataModel, "public">;

@@ -121,2 +125,20 @@ const authenticatedQueryBuilder = customQuery(

/**
* Testing that it conforms to query, mutation, action types when no args
* are added
*/
customQuery(
query,
customCtx((ctx) => ({ foo: "bar" })),
) satisfies typeof query;
customMutation(
mutation,
customCtx((ctx) => ({})),
) satisfies typeof mutation;
customAction(
action,
customCtx((ctx) => ({})),
) satisfies typeof action;
/**
* Testing custom function modifications.

@@ -123,0 +145,0 @@ */

@@ -17,2 +17,5 @@ /**

PropertyValidators,
Validator,
asObjectValidator,
v,
} from "convex/values";

@@ -332,6 +335,3 @@ import {

return builder({
args: {
...fn.args,
...inputArgs,
},
args: addArgs(fn.args, inputArgs),
returns: fn.returns,

@@ -364,2 +364,24 @@ handler: async (ctx: any, allArgs: any) => {

// Adds args to a property validator or validator
// Needs to call recursively in the case of unions.
function addArgs(
validatorOrPropertyValidator: PropertyValidators | Validator<any, any, any>,
args: PropertyValidators,
): Validator<any, any, any> {
if (Object.keys(args).length === 0) {
return asObjectValidator(validatorOrPropertyValidator);
}
const validator = asObjectValidator(validatorOrPropertyValidator);
switch (validator.kind) {
case "object":
return v.object({ ...validator.fields, ...args });
case "union":
return v.union(...validator.members.map((m) => addArgs(m, args)));
default:
throw new Error(
"Cannot add arguments to a validator that is not an object or union.",
);
}
}
/**

@@ -417,3 +439,3 @@ * A Convex function (query, mutation, or action) to be registered for the API.

<
ArgsValidator extends PropertyValidators | void,
ArgsValidator extends PropertyValidators | void | Validator<any, any, any>,
ReturnsValidator extends PropertyValidators | GenericValidator | void,

@@ -443,5 +465,7 @@ ReturnValue extends ReturnValueForOptionalValidator<ReturnsValidator> = any,

ArgsArrayToObject<
OneOrZeroArgs extends [infer A]
? [Expand<A & ObjectType<ModArgsValidator>>]
: [ObjectType<ModArgsValidator>]
ModArgsValidator extends Record<string, never>
? OneOrZeroArgs
: OneOrZeroArgs extends [infer A]
? [Expand<A & ObjectType<ModArgsValidator>>]
: [ObjectType<ModArgsValidator>]
>,

@@ -448,0 +472,0 @@ ReturnValue

import { defineTable, defineSchema, GenericDocument } from "convex/server";
import { convexTest } from "convex-test";
import { expect, test, vi } from "vitest";
import { expect, test } from "vitest";
import { IndexKey, getPage } from "./pagination.js";

@@ -150,3 +150,3 @@ import { modules } from "./setup.test.js";

// document already.
await ctx.db.delete(page0[0]._id as GenericId<"foo">);
await ctx.db.delete(page0[0]!._id as GenericId<"foo">);
const { page: page0Refreshed } = await getPage(ctx, {

@@ -204,3 +204,3 @@ table: "foo",

}
const { page: pageAt, indexKeys: indexKeysAt } = await getPage(ctx, {
const { page: pageAt } = await getPage(ctx, {
table: "foo",

@@ -207,0 +207,0 @@ index: "abc",

@@ -10,6 +10,10 @@ import { convexTest } from "convex-test";

defineTable,
GenericDatabaseReader,
GenericDatabaseWriter,
MutationBuilder,
mutationGeneric,
queryGeneric,
} from "convex/server";
import { modules } from "./setup.test.js";
import { customCtx, customMutation } from "./customFunctions.js";
import { crud } from "../server.js";

@@ -27,22 +31,21 @@ const schema = defineSchema({

type DataModel = DataModelFromSchemaDefinition<typeof schema>;
type DatabaseReader = GenericDatabaseReader<DataModel>;
type DatabaseWriter = GenericDatabaseWriter<DataModel>;
describe("row level security", () => {
const withRLS = async (ctx: { db: DatabaseWriter; auth: Auth }) => {
const tokenIdentifier = (await ctx.auth.getUserIdentity())?.tokenIdentifier;
if (!tokenIdentifier) throw new Error("Unauthenticated");
return {
...ctx,
db: wrapDatabaseWriter({ tokenIdentifier }, ctx.db, {
notes: {
read: async ({ tokenIdentifier }, doc) => {
const author = await ctx.db.get(doc.userId);
return tokenIdentifier === author?.tokenIdentifier;
},
const withRLS = async (ctx: { db: DatabaseWriter; auth: Auth }) => {
const tokenIdentifier = (await ctx.auth.getUserIdentity())?.tokenIdentifier;
if (!tokenIdentifier) throw new Error("Unauthenticated");
return {
...ctx,
db: wrapDatabaseWriter({ tokenIdentifier }, ctx.db, {
notes: {
read: async ({ tokenIdentifier }, doc) => {
const author = await ctx.db.get(doc.userId);
return tokenIdentifier === author?.tokenIdentifier;
},
}),
};
},
}),
};
};
describe("row level security", () => {
test("can only read own notes", async () => {

@@ -81,3 +84,3 @@ const t = convexTest(schema, modules);

const aId = await ctx.db.insert("users", { tokenIdentifier: "Person A" });
const bId = await ctx.db.insert("users", { tokenIdentifier: "Person B" });
await ctx.db.insert("users", { tokenIdentifier: "Person B" });
return ctx.db.insert("notes", {

@@ -102,1 +105,23 @@ note: "Hello from Person A",

});
const mutation = mutationGeneric as MutationBuilder<DataModel, "public">;
const mutationWithRLS = customMutation(
mutation,
customCtx((ctx) => withRLS(ctx)),
);
customMutation(
mutationWithRLS,
customCtx((ctx) => ({ foo: "bar" })),
) satisfies typeof mutation;
crud(
{
_id: v.id("foo"),
name: "foo",
withoutSystemFields: { bar: v.number() },
},
queryGeneric,
mutationWithRLS,
);

@@ -1,4 +0,4 @@

import { assert, omit, pick, pruneNull } from "..";
import { Table } from ".";
import { partial } from "../validators";
import { assert, omit, pick, pruneNull } from "../index.js";
import { Table } from "../server.js";
import { partial } from "../validators.js";
import { convexTest } from "convex-test";

@@ -17,3 +17,3 @@ import {

import { expect, test } from "vitest";
import { modules } from "./setup.test";
import { modules } from "./setup.test.js";

@@ -20,0 +20,0 @@ // Define a table with system fields _id and _creationTime. This also returns

@@ -10,8 +10,8 @@ import {

} from "convex/server";
import { Equals, assert, omit } from "..";
import { Equals, assert, omit } from "../index.js";
import { convexTest } from "convex-test";
import { describe, expect, test } from "vitest";
import { modules } from "./setup.test";
import { zCustomQuery, zid, zodToConvexFields } from "./zod";
import { customCtx } from "./customFunctions";
import { modules } from "./setup.test.js";
import { zCustomQuery, zid, zodToConvexFields } from "./zod.js";
import { customCtx } from "./customFunctions.js";
import { v } from "convex/values";

@@ -18,0 +18,0 @@ import { z } from "zod";

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc