initial commit
This commit is contained in:
88
packages/backend/convex/README.md
Normal file
88
packages/backend/convex/README.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Welcome to your Convex functions directory!
|
||||
|
||||
Write your Convex functions here.
|
||||
See https://docs.convex.dev/functions for more.
|
||||
|
||||
A query function that takes two arguments looks like:
|
||||
|
||||
```ts
|
||||
// convex/myFunctions.ts
|
||||
import { query } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
export const myQueryFunction = query({
|
||||
// Validators for arguments.
|
||||
args: {
|
||||
first: v.number(),
|
||||
second: v.string(),
|
||||
},
|
||||
|
||||
// Function implementation.
|
||||
handler: async (ctx, args) => {
|
||||
// Read the database as many times as you need here.
|
||||
// See https://docs.convex.dev/database/reading-data.
|
||||
const documents = await ctx.db.query("tablename").collect();
|
||||
|
||||
// Arguments passed from the client are properties of the args object.
|
||||
console.log(args.first, args.second);
|
||||
|
||||
// Write arbitrary JavaScript here: filter, aggregate, build derived data,
|
||||
// remove non-public properties, or create new objects.
|
||||
return documents;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Using this query function in a React component looks like:
|
||||
|
||||
```ts
|
||||
const data = useQuery(api.myFunctions.myQueryFunction, {
|
||||
first: 10,
|
||||
second: "hello",
|
||||
});
|
||||
```
|
||||
|
||||
A mutation function looks like:
|
||||
|
||||
```ts
|
||||
// convex/myFunctions.ts
|
||||
import { mutation } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
export const myMutationFunction = mutation({
|
||||
// Validators for arguments.
|
||||
args: {
|
||||
first: v.string(),
|
||||
second: v.string(),
|
||||
},
|
||||
|
||||
// Function implementation.
|
||||
handler: async (ctx, args) => {
|
||||
// Insert or modify documents in the database here.
|
||||
// Mutations can also read from the database like queries.
|
||||
// See https://docs.convex.dev/database/writing-data.
|
||||
const message = { body: args.first, author: args.second };
|
||||
const id = await ctx.db.insert("messages", message);
|
||||
|
||||
// Optionally, return a value from your mutation.
|
||||
return await ctx.db.get("messages", id);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Using this mutation function in a React component looks like:
|
||||
|
||||
```ts
|
||||
const mutation = useMutation(api.myFunctions.myMutationFunction);
|
||||
function handleButtonPress() {
|
||||
// fire and forget, the most common way to use mutations
|
||||
mutation({ first: "Hello!", second: "me" });
|
||||
// OR
|
||||
// use the result once the mutation has completed
|
||||
mutation({ first: "Hello!", second: "me" }).then((result) => console.log(result));
|
||||
}
|
||||
```
|
||||
|
||||
Use the Convex CLI to push your functions to a deployment. See everything
|
||||
the Convex CLI can do by running `npx convex -h` in your project root
|
||||
directory. To learn more, launch the docs with `npx convex docs`.
|
||||
4
packages/backend/convex/_generated/api.d.ts
vendored
Normal file
4
packages/backend/convex/_generated/api.d.ts
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable */
|
||||
export declare const api: any;
|
||||
export declare const internal: any;
|
||||
export declare const components: any;
|
||||
6
packages/backend/convex/_generated/api.js
Normal file
6
packages/backend/convex/_generated/api.js
Normal file
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import { anyApi, componentsGeneric } from "convex/server";
|
||||
|
||||
export const api = anyApi;
|
||||
export const internal = anyApi;
|
||||
export const components = componentsGeneric();
|
||||
15
packages/backend/convex/_generated/dataModel.d.ts
vendored
Normal file
15
packages/backend/convex/_generated/dataModel.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-disable */
|
||||
import type {
|
||||
DataModelFromSchemaDefinition,
|
||||
DocumentByName,
|
||||
SystemTableNames,
|
||||
TableNamesInDataModel,
|
||||
} from "convex/server";
|
||||
import type { GenericId } from "convex/values";
|
||||
|
||||
import schema from "../schema.js";
|
||||
|
||||
export type DataModel = DataModelFromSchemaDefinition<typeof schema>;
|
||||
export type TableNames = TableNamesInDataModel<DataModel>;
|
||||
export type Doc<TableName extends TableNames> = DocumentByName<DataModel, TableName>;
|
||||
export type Id<TableName extends TableNames | SystemTableNames> = GenericId<TableName>;
|
||||
28
packages/backend/convex/_generated/server.d.ts
vendored
Normal file
28
packages/backend/convex/_generated/server.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/* eslint-disable */
|
||||
import type {
|
||||
ActionBuilder,
|
||||
GenericActionCtx,
|
||||
GenericDatabaseReader,
|
||||
GenericDatabaseWriter,
|
||||
GenericMutationCtx,
|
||||
GenericQueryCtx,
|
||||
HttpActionBuilder,
|
||||
MutationBuilder,
|
||||
QueryBuilder,
|
||||
} from "convex/server";
|
||||
|
||||
import type { DataModel } from "./dataModel.js";
|
||||
|
||||
export declare const query: QueryBuilder<DataModel, "public">;
|
||||
export declare const internalQuery: QueryBuilder<DataModel, "internal">;
|
||||
export declare const mutation: MutationBuilder<DataModel, "public">;
|
||||
export declare const internalMutation: MutationBuilder<DataModel, "internal">;
|
||||
export declare const action: ActionBuilder<DataModel, "public">;
|
||||
export declare const internalAction: ActionBuilder<DataModel, "internal">;
|
||||
export declare const httpAction: HttpActionBuilder;
|
||||
|
||||
export type QueryCtx = GenericQueryCtx<DataModel>;
|
||||
export type MutationCtx = GenericMutationCtx<DataModel>;
|
||||
export type ActionCtx = GenericActionCtx<DataModel>;
|
||||
export type DatabaseReader = GenericDatabaseReader<DataModel>;
|
||||
export type DatabaseWriter = GenericDatabaseWriter<DataModel>;
|
||||
18
packages/backend/convex/_generated/server.js
Normal file
18
packages/backend/convex/_generated/server.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/* eslint-disable */
|
||||
import {
|
||||
actionGeneric,
|
||||
httpActionGeneric,
|
||||
internalActionGeneric,
|
||||
internalMutationGeneric,
|
||||
internalQueryGeneric,
|
||||
mutationGeneric,
|
||||
queryGeneric,
|
||||
} from "convex/server";
|
||||
|
||||
export const query = queryGeneric;
|
||||
export const internalQuery = internalQueryGeneric;
|
||||
export const mutation = mutationGeneric;
|
||||
export const internalMutation = internalMutationGeneric;
|
||||
export const action = actionGeneric;
|
||||
export const internalAction = internalActionGeneric;
|
||||
export const httpAction = httpActionGeneric;
|
||||
6
packages/backend/convex/auth.config.ts
Normal file
6
packages/backend/convex/auth.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { getAuthConfigProvider } from "@convex-dev/better-auth/auth-config";
|
||||
import type { AuthConfig } from "convex/server";
|
||||
|
||||
export default {
|
||||
providers: [getAuthConfigProvider()],
|
||||
} satisfies AuthConfig;
|
||||
43
packages/backend/convex/auth.ts
Normal file
43
packages/backend/convex/auth.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { expo } from "@better-auth/expo";
|
||||
import { createClient, type GenericCtx } from "@convex-dev/better-auth";
|
||||
import { convex, crossDomain } from "@convex-dev/better-auth/plugins";
|
||||
import { betterAuth } from "better-auth/minimal";
|
||||
|
||||
import { components } from "./_generated/api";
|
||||
import type { DataModel } from "./_generated/dataModel";
|
||||
import { query } from "./_generated/server";
|
||||
import authConfig from "./auth.config";
|
||||
|
||||
const siteUrl = process.env.SITE_URL!;
|
||||
const nativeAppUrl = process.env.NATIVE_APP_URL || "code://";
|
||||
|
||||
export const authComponent = createClient<DataModel>(components.betterAuth);
|
||||
|
||||
function createAuth(ctx: GenericCtx<DataModel>) {
|
||||
return betterAuth({
|
||||
baseURL: process.env.CONVEX_SITE_URL,
|
||||
trustedOrigins: [siteUrl, nativeAppUrl, "exp://"],
|
||||
database: authComponent.adapter(ctx),
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
requireEmailVerification: false,
|
||||
},
|
||||
plugins: [
|
||||
expo(),
|
||||
crossDomain({ siteUrl }),
|
||||
convex({
|
||||
authConfig,
|
||||
jwksRotateOnTokenGenerationError: true,
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export { createAuth };
|
||||
|
||||
export const getCurrentUser = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
return await authComponent.safeGetAuthUser(ctx);
|
||||
},
|
||||
});
|
||||
7
packages/backend/convex/convex.config.ts
Normal file
7
packages/backend/convex/convex.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import betterAuth from "@convex-dev/better-auth/convex.config";
|
||||
import { defineApp } from "convex/server";
|
||||
|
||||
const app = defineApp();
|
||||
app.use(betterAuth);
|
||||
|
||||
export default app;
|
||||
7
packages/backend/convex/healthCheck.ts
Normal file
7
packages/backend/convex/healthCheck.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { query } from "./_generated/server";
|
||||
|
||||
export const get = query({
|
||||
handler: async () => {
|
||||
return "OK";
|
||||
},
|
||||
});
|
||||
9
packages/backend/convex/http.ts
Normal file
9
packages/backend/convex/http.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { httpRouter } from "convex/server";
|
||||
|
||||
import { authComponent, createAuth } from "./auth";
|
||||
|
||||
const http = httpRouter();
|
||||
|
||||
authComponent.registerRoutes(http, createAuth, { cors: true });
|
||||
|
||||
export default http;
|
||||
17
packages/backend/convex/privateData.ts
Normal file
17
packages/backend/convex/privateData.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { query } from "./_generated/server";
|
||||
import { authComponent } from "./auth";
|
||||
|
||||
export const get = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
const authUser = await authComponent.safeGetAuthUser(ctx);
|
||||
if (!authUser) {
|
||||
return {
|
||||
message: "Not authenticated",
|
||||
};
|
||||
}
|
||||
return {
|
||||
message: "This is private",
|
||||
};
|
||||
},
|
||||
});
|
||||
9
packages/backend/convex/schema.ts
Normal file
9
packages/backend/convex/schema.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { defineSchema, defineTable } from "convex/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
export default defineSchema({
|
||||
todos: defineTable({
|
||||
text: v.string(),
|
||||
completed: v.boolean(),
|
||||
}),
|
||||
});
|
||||
43
packages/backend/convex/todos.ts
Normal file
43
packages/backend/convex/todos.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { v } from "convex/values";
|
||||
|
||||
import { query, mutation } from "./_generated/server";
|
||||
|
||||
export const getAll = query({
|
||||
handler: async (ctx) => {
|
||||
return await ctx.db.query("todos").collect();
|
||||
},
|
||||
});
|
||||
|
||||
export const create = mutation({
|
||||
args: {
|
||||
text: v.string(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const newTodoId = await ctx.db.insert("todos", {
|
||||
text: args.text,
|
||||
completed: false,
|
||||
});
|
||||
return await ctx.db.get("todos", newTodoId);
|
||||
},
|
||||
});
|
||||
|
||||
export const toggle = mutation({
|
||||
args: {
|
||||
id: v.id("todos"),
|
||||
completed: v.boolean(),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.db.patch("todos", args.id, { completed: args.completed });
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteTodo = mutation({
|
||||
args: {
|
||||
id: v.id("todos"),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.db.delete("todos", args.id);
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
26
packages/backend/convex/tsconfig.json
Normal file
26
packages/backend/convex/tsconfig.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
/* This TypeScript project config describes the environment that
|
||||
* Convex functions run in and is used to typecheck them.
|
||||
* You can modify it, but some settings are required to use Convex.
|
||||
*/
|
||||
"compilerOptions": {
|
||||
/* These settings are not required by Convex and can be modified. */
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"moduleResolution": "Bundler",
|
||||
"jsx": "react-jsx",
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"types": ["node"],
|
||||
|
||||
/* These compiler options are required by Convex */
|
||||
"target": "ESNext",
|
||||
"lib": ["ES2021", "dom"],
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "ESNext",
|
||||
"isolatedModules": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["./**/*"],
|
||||
"exclude": ["./_generated"]
|
||||
}
|
||||
Reference in New Issue
Block a user