init commit
This commit is contained in:
1
packages/backend/.cache/.prettiercache
Normal file
1
packages/backend/.cache/.prettiercache
Normal file
@@ -0,0 +1 @@
|
||||
[["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"],{"key":"16","value":"17"},{"key":"18","value":"19"},{"key":"20","value":"21"},{"key":"22","value":"23"},{"key":"24","value":"25"},{"key":"26","value":"27"},{"key":"28","value":"29"},{"key":"30","value":"31"},{"key":"32","value":"33"},{"key":"34","value":"35"},{"key":"36","value":"37"},{"key":"38","value":"39"},{"key":"40","value":"41"},{"key":"42","value":"43"},{"key":"44","value":"45"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/.gitignore",{"size":16,"mtime":1753933693000,"hash":"46"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/server.d.ts",{"size":5540,"mtime":1761665487097,"hash":"47","data":"48"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/auth.config.js",{"size":128,"mtime":1753933693000,"hash":"49","data":"50"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/package.json",{"size":1135,"mtime":1761665487290,"hash":"51","data":"52"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/openai.ts",{"size":2036,"mtime":1761665487195,"hash":"53","data":"54"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/README.md",{"size":2525,"mtime":1761665487249,"hash":"55","data":"56"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/api.js",{"size":414,"mtime":1753933693000,"hash":"57","data":"58"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/tsconfig.json",{"size":732,"mtime":1753933693000,"hash":"59","data":"60"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/server.js",{"size":3453,"mtime":1761665487114,"hash":"61","data":"62"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/notes.ts",{"size":1632,"mtime":1761665487164,"hash":"63","data":"64"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/env.ts",{"size":219,"mtime":1761665487285,"hash":"65","data":"66"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/dataModel.d.ts",{"size":1726,"mtime":1761665487061,"hash":"67","data":"68"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/schema.ts",{"size":267,"mtime":1753933693000,"hash":"69","data":"70"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/utils.ts",{"size":635,"mtime":1753933693000,"hash":"71","data":"72"},"/home/gib/Documents/Code/monorepo/convex-monorepo/packages/backend/convex/_generated/api.d.ts",{"size":845,"mtime":1761665486984,"hash":"73","data":"74"},"175b1a771387d8b7e26145c3d04e0475","da19b68e90524b894bbf1985bcec4d72",{"hashOfOptions":"75"},"a87d36cd21882ed8968ea6138f23acd9",{"hashOfOptions":"76"},"80903421dc266560a15314b96f727e40",{"hashOfOptions":"77"},"2cf34d0dd087d9749396d5f686419f4f",{"hashOfOptions":"78"},"7beaec3443b6db9c1a6b8c1668c98992",{"hashOfOptions":"79"},"c5dea56b7ddd47516cbd4038de020e53",{"hashOfOptions":"80"},"cfa98923457caed911ec68b626ef4234",{"hashOfOptions":"81"},"4a51b371d17b0a9dcc8d3a3d16790eec",{"hashOfOptions":"82"},"99403ed881c0f3caf6c13ad183e06049",{"hashOfOptions":"83"},"d78af64438f2e86a438ce045e0910a1d",{"hashOfOptions":"84"},"1a6eccbe2f9771c5b418adc40d8532c4",{"hashOfOptions":"85"},"9b1b5b82ff06ae9856df10ae91c15946",{"hashOfOptions":"86"},"0a1b4f144561ba1da064a40a2e089f10",{"hashOfOptions":"87"},"26351eae8dc2fa74ce0e3e6f6f0d4a49",{"hashOfOptions":"88"},"2545271053","1384390439","3159514942","514606721","3861339677","511151554","2611213275","1927515469","2174687556","3247610094","3411100989","2670794290","530123092","4075214594"]
|
||||
2
packages/backend/.gitignore
vendored
Normal file
2
packages/backend/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.env.local
|
||||
.env
|
||||
92
packages/backend/convex/README.md
Normal file
92
packages/backend/convex/README.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Welcome to your Convex functions directory!
|
||||
|
||||
Write your Convex functions here. See
|
||||
https://docs.convex.dev/using/writing-convex-functions for more.
|
||||
|
||||
A query function that takes two arguments looks like:
|
||||
|
||||
```ts
|
||||
// functions.js
|
||||
import { v } from "convex/values";
|
||||
|
||||
import { query } from "./_generated/server";
|
||||
|
||||
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.functions.myQueryFunction, {
|
||||
first: 10,
|
||||
second: "hello",
|
||||
});
|
||||
```
|
||||
|
||||
A mutation function looks like:
|
||||
|
||||
```ts
|
||||
// functions.js
|
||||
import { v } from "convex/values";
|
||||
|
||||
import { mutation } from "./_generated/server";
|
||||
|
||||
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(id);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Using this mutation function in a React component looks like:
|
||||
|
||||
```ts
|
||||
const mutation = useMutation(api.functions.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`.
|
||||
41
packages/backend/convex/_generated/api.d.ts
vendored
Normal file
41
packages/backend/convex/_generated/api.d.ts
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated `api` utility.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type {
|
||||
ApiFromModules,
|
||||
FilterApi,
|
||||
FunctionReference,
|
||||
} from "convex/server";
|
||||
|
||||
import type * as notes from "../notes.js";
|
||||
import type * as openai from "../openai.js";
|
||||
import type * as utils from "../utils.js";
|
||||
|
||||
/**
|
||||
* A utility for referencing Convex functions in your app's API.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* const myFunctionReference = api.myModule.myFunction;
|
||||
* ```
|
||||
*/
|
||||
declare const fullApi: ApiFromModules<{
|
||||
notes: typeof notes;
|
||||
openai: typeof openai;
|
||||
utils: typeof utils;
|
||||
}>;
|
||||
export declare const api: FilterApi<
|
||||
typeof fullApi,
|
||||
FunctionReference<any, "public">
|
||||
>;
|
||||
export declare const internal: FilterApi<
|
||||
typeof fullApi,
|
||||
FunctionReference<any, "internal">
|
||||
>;
|
||||
22
packages/backend/convex/_generated/api.js
Normal file
22
packages/backend/convex/_generated/api.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated `api` utility.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import { anyApi } from "convex/server";
|
||||
|
||||
/**
|
||||
* A utility for referencing Convex functions in your app's API.
|
||||
*
|
||||
* Usage:
|
||||
* ```js
|
||||
* const myFunctionReference = api.myModule.myFunction;
|
||||
* ```
|
||||
*/
|
||||
export const api = anyApi;
|
||||
export const internal = anyApi;
|
||||
61
packages/backend/convex/_generated/dataModel.d.ts
vendored
Normal file
61
packages/backend/convex/_generated/dataModel.d.ts
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated data model types.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import type {
|
||||
DataModelFromSchemaDefinition,
|
||||
DocumentByName,
|
||||
SystemTableNames,
|
||||
TableNamesInDataModel,
|
||||
} from "convex/server";
|
||||
import type { GenericId } from "convex/values";
|
||||
|
||||
import schema from "../schema.js";
|
||||
|
||||
/**
|
||||
* The names of all of your Convex tables.
|
||||
*/
|
||||
export type TableNames = TableNamesInDataModel<DataModel>;
|
||||
|
||||
/**
|
||||
* The type of a document stored in Convex.
|
||||
*
|
||||
* @typeParam TableName - A string literal type of the table name (like "users").
|
||||
*/
|
||||
export type Doc<TableName extends TableNames> = DocumentByName<
|
||||
DataModel,
|
||||
TableName
|
||||
>;
|
||||
|
||||
/**
|
||||
* An identifier for a document in Convex.
|
||||
*
|
||||
* Convex documents are uniquely identified by their `Id`, which is accessible
|
||||
* on the `_id` field. To learn more, see [Document IDs](https://docs.convex.dev/using/document-ids).
|
||||
*
|
||||
* Documents can be loaded using `db.get(id)` in query and mutation functions.
|
||||
*
|
||||
* IDs are just strings at runtime, but this type can be used to distinguish them from other
|
||||
* strings when type checking.
|
||||
*
|
||||
* @typeParam TableName - A string literal type of the table name (like "users").
|
||||
*/
|
||||
export type Id<TableName extends TableNames | SystemTableNames> =
|
||||
GenericId<TableName>;
|
||||
|
||||
/**
|
||||
* A type describing your Convex data model.
|
||||
*
|
||||
* This type includes information about what tables you have, the type of
|
||||
* documents stored in those tables, and the indexes defined on them.
|
||||
*
|
||||
* This type is used to parameterize methods like `queryGeneric` and
|
||||
* `mutationGeneric` to make them type-safe.
|
||||
*/
|
||||
export type DataModel = DataModelFromSchemaDefinition<typeof schema>;
|
||||
143
packages/backend/convex/_generated/server.d.ts
vendored
Normal file
143
packages/backend/convex/_generated/server.d.ts
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated utilities for implementing server-side Convex query and mutation functions.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import {
|
||||
ActionBuilder,
|
||||
GenericActionCtx,
|
||||
GenericDatabaseReader,
|
||||
GenericDatabaseWriter,
|
||||
GenericMutationCtx,
|
||||
GenericQueryCtx,
|
||||
HttpActionBuilder,
|
||||
MutationBuilder,
|
||||
QueryBuilder,
|
||||
} from "convex/server";
|
||||
|
||||
import type { DataModel } from "./dataModel.js";
|
||||
|
||||
/**
|
||||
* Define a query in this Convex app's public API.
|
||||
*
|
||||
* This function will be allowed to read your Convex database and will be accessible from the client.
|
||||
*
|
||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export declare const query: QueryBuilder<DataModel, "public">;
|
||||
|
||||
/**
|
||||
* Define a query that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* This function will be allowed to read from your Convex database. It will not be accessible from the client.
|
||||
*
|
||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export declare const internalQuery: QueryBuilder<DataModel, "internal">;
|
||||
|
||||
/**
|
||||
* Define a mutation in this Convex app's public API.
|
||||
*
|
||||
* This function will be allowed to modify your Convex database and will be accessible from the client.
|
||||
*
|
||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export declare const mutation: MutationBuilder<DataModel, "public">;
|
||||
|
||||
/**
|
||||
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* This function will be allowed to modify your Convex database. It will not be accessible from the client.
|
||||
*
|
||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export declare const internalMutation: MutationBuilder<DataModel, "internal">;
|
||||
|
||||
/**
|
||||
* Define an action in this Convex app's public API.
|
||||
*
|
||||
* An action is a function which can execute any JavaScript code, including non-deterministic
|
||||
* code and code with side-effects, like calling third-party services.
|
||||
* They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
|
||||
* They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
|
||||
*
|
||||
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped action. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export declare const action: ActionBuilder<DataModel, "public">;
|
||||
|
||||
/**
|
||||
* Define an action that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped function. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export declare const internalAction: ActionBuilder<DataModel, "internal">;
|
||||
|
||||
/**
|
||||
* Define an HTTP action.
|
||||
*
|
||||
* This function will be used to respond to HTTP requests received by a Convex
|
||||
* deployment if the requests matches the path and method where this action
|
||||
* is routed. Be sure to route your action in `convex/http.js`.
|
||||
*
|
||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped function. Import this function from `convex/http.js` and route it to hook it up.
|
||||
*/
|
||||
export declare const httpAction: HttpActionBuilder;
|
||||
|
||||
/**
|
||||
* A set of services for use within Convex query functions.
|
||||
*
|
||||
* The query context is passed as the first argument to any Convex query
|
||||
* function run on the server.
|
||||
*
|
||||
* This differs from the {@link MutationCtx} because all of the services are
|
||||
* read-only.
|
||||
*/
|
||||
export type QueryCtx = GenericQueryCtx<DataModel>;
|
||||
|
||||
/**
|
||||
* A set of services for use within Convex mutation functions.
|
||||
*
|
||||
* The mutation context is passed as the first argument to any Convex mutation
|
||||
* function run on the server.
|
||||
*/
|
||||
export type MutationCtx = GenericMutationCtx<DataModel>;
|
||||
|
||||
/**
|
||||
* A set of services for use within Convex action functions.
|
||||
*
|
||||
* The action context is passed as the first argument to any Convex action
|
||||
* function run on the server.
|
||||
*/
|
||||
export type ActionCtx = GenericActionCtx<DataModel>;
|
||||
|
||||
/**
|
||||
* An interface to read from the database within Convex query functions.
|
||||
*
|
||||
* The two entry points are {@link DatabaseReader.get}, which fetches a single
|
||||
* document by its {@link Id}, or {@link DatabaseReader.query}, which starts
|
||||
* building a query.
|
||||
*/
|
||||
export type DatabaseReader = GenericDatabaseReader<DataModel>;
|
||||
|
||||
/**
|
||||
* An interface to read from and write to the database within Convex mutation
|
||||
* functions.
|
||||
*
|
||||
* Convex guarantees that all writes within a single mutation are
|
||||
* executed atomically, so you never have to worry about partial writes leaving
|
||||
* your data in an inconsistent state. See [the Convex Guide](https://docs.convex.dev/understanding/convex-fundamentals/functions#atomicity-and-optimistic-concurrency-control)
|
||||
* for the guarantees Convex provides your functions.
|
||||
*/
|
||||
export type DatabaseWriter = GenericDatabaseWriter<DataModel>;
|
||||
89
packages/backend/convex/_generated/server.js
Normal file
89
packages/backend/convex/_generated/server.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Generated utilities for implementing server-side Convex query and mutation functions.
|
||||
*
|
||||
* THIS CODE IS AUTOMATICALLY GENERATED.
|
||||
*
|
||||
* To regenerate, run `npx convex dev`.
|
||||
* @module
|
||||
*/
|
||||
|
||||
import {
|
||||
actionGeneric,
|
||||
httpActionGeneric,
|
||||
internalActionGeneric,
|
||||
internalMutationGeneric,
|
||||
internalQueryGeneric,
|
||||
mutationGeneric,
|
||||
queryGeneric,
|
||||
} from "convex/server";
|
||||
|
||||
/**
|
||||
* Define a query in this Convex app's public API.
|
||||
*
|
||||
* This function will be allowed to read your Convex database and will be accessible from the client.
|
||||
*
|
||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const query = queryGeneric;
|
||||
|
||||
/**
|
||||
* Define a query that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* This function will be allowed to read from your Convex database. It will not be accessible from the client.
|
||||
*
|
||||
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
||||
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const internalQuery = internalQueryGeneric;
|
||||
|
||||
/**
|
||||
* Define a mutation in this Convex app's public API.
|
||||
*
|
||||
* This function will be allowed to modify your Convex database and will be accessible from the client.
|
||||
*
|
||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const mutation = mutationGeneric;
|
||||
|
||||
/**
|
||||
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* This function will be allowed to modify your Convex database. It will not be accessible from the client.
|
||||
*
|
||||
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
||||
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const internalMutation = internalMutationGeneric;
|
||||
|
||||
/**
|
||||
* Define an action in this Convex app's public API.
|
||||
*
|
||||
* An action is a function which can execute any JavaScript code, including non-deterministic
|
||||
* code and code with side-effects, like calling third-party services.
|
||||
* They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
|
||||
* They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
|
||||
*
|
||||
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped action. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const action = actionGeneric;
|
||||
|
||||
/**
|
||||
* Define an action that is only accessible from other Convex functions (but not from the client).
|
||||
*
|
||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
||||
* @returns The wrapped function. Include this as an `export` to name it and make it accessible.
|
||||
*/
|
||||
export const internalAction = internalActionGeneric;
|
||||
|
||||
/**
|
||||
* Define a Convex HTTP action.
|
||||
*
|
||||
* @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object
|
||||
* as its second.
|
||||
* @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
|
||||
*/
|
||||
export const httpAction = httpActionGeneric;
|
||||
8
packages/backend/convex/auth.config.js
Normal file
8
packages/backend/convex/auth.config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
providers: [
|
||||
{
|
||||
domain: process.env.CLERK_ISSUER_URL,
|
||||
applicationID: "convex",
|
||||
},
|
||||
],
|
||||
};
|
||||
71
packages/backend/convex/notes.ts
Normal file
71
packages/backend/convex/notes.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { Auth } from "convex/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
import { internal } from "../convex/_generated/api";
|
||||
import { mutation, query } from "./_generated/server";
|
||||
|
||||
export const getUserId = async (ctx: { auth: Auth }) => {
|
||||
return (await ctx.auth.getUserIdentity())?.subject;
|
||||
};
|
||||
|
||||
// Get all notes for a specific user
|
||||
export const getNotes = query({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
const userId = await getUserId(ctx);
|
||||
if (!userId) return null;
|
||||
|
||||
const notes = await ctx.db
|
||||
.query("notes")
|
||||
.filter((q) => q.eq(q.field("userId"), userId))
|
||||
.collect();
|
||||
|
||||
return notes;
|
||||
},
|
||||
});
|
||||
|
||||
// Get note for a specific note
|
||||
export const getNote = query({
|
||||
args: {
|
||||
id: v.optional(v.id("notes")),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const { id } = args;
|
||||
if (!id) return null;
|
||||
const note = await ctx.db.get(id);
|
||||
return note;
|
||||
},
|
||||
});
|
||||
|
||||
// Create a new note for a user
|
||||
export const createNote = mutation({
|
||||
args: {
|
||||
title: v.string(),
|
||||
content: v.string(),
|
||||
isSummary: v.boolean(),
|
||||
},
|
||||
handler: async (ctx, { title, content, isSummary }) => {
|
||||
const userId = await getUserId(ctx);
|
||||
if (!userId) throw new Error("User not found");
|
||||
const noteId = await ctx.db.insert("notes", { userId, title, content });
|
||||
|
||||
if (isSummary) {
|
||||
await ctx.scheduler.runAfter(0, internal.openai.summary, {
|
||||
id: noteId,
|
||||
title,
|
||||
content,
|
||||
});
|
||||
}
|
||||
|
||||
return noteId;
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteNote = mutation({
|
||||
args: {
|
||||
noteId: v.id("notes"),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.db.delete(args.noteId);
|
||||
},
|
||||
});
|
||||
76
packages/backend/convex/openai.ts
Normal file
76
packages/backend/convex/openai.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { v } from "convex/values";
|
||||
import OpenAI from "openai";
|
||||
|
||||
import { internal } from "./_generated/api";
|
||||
import { internalAction, internalMutation, query } from "./_generated/server";
|
||||
import { missingEnvVariableUrl } from "./utils";
|
||||
|
||||
export const openaiKeySet = query({
|
||||
args: {},
|
||||
handler: async () => {
|
||||
return !!process.env.OPENAI_API_KEY;
|
||||
},
|
||||
});
|
||||
|
||||
export const summary = internalAction({
|
||||
args: {
|
||||
id: v.id("notes"),
|
||||
title: v.string(),
|
||||
content: v.string(),
|
||||
},
|
||||
handler: async (ctx, { id, title, content }) => {
|
||||
const prompt = `Take in the following note and return a summary: Title: ${title}, Note content: ${content}`;
|
||||
|
||||
const apiKey = process.env.OPENAI_API_KEY;
|
||||
if (!apiKey) {
|
||||
const error = missingEnvVariableUrl(
|
||||
"OPENAI_API_KEY",
|
||||
"https://platform.openai.com/account/api-keys",
|
||||
);
|
||||
console.error(error);
|
||||
await ctx.runMutation(internal.openai.saveSummary, {
|
||||
id: id,
|
||||
summary: error,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const openai = new OpenAI({ apiKey });
|
||||
const output = await openai.chat.completions.create({
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content:
|
||||
"You are a helpful assistant designed to output JSON in this format: {summary: string}",
|
||||
},
|
||||
{ role: "user", content: prompt },
|
||||
],
|
||||
model: "gpt-4-1106-preview",
|
||||
response_format: { type: "json_object" },
|
||||
});
|
||||
|
||||
// Pull the message content out of the response
|
||||
const messageContent = output.choices[0]?.message.content;
|
||||
|
||||
console.log({ messageContent });
|
||||
|
||||
const parsedOutput = JSON.parse(messageContent!);
|
||||
console.log({ parsedOutput });
|
||||
|
||||
await ctx.runMutation(internal.openai.saveSummary, {
|
||||
id: id,
|
||||
summary: parsedOutput.summary,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const saveSummary = internalMutation({
|
||||
args: {
|
||||
id: v.id("notes"),
|
||||
summary: v.string(),
|
||||
},
|
||||
handler: async (ctx, { id, summary }) => {
|
||||
await ctx.db.patch(id, {
|
||||
summary: summary,
|
||||
});
|
||||
},
|
||||
});
|
||||
11
packages/backend/convex/schema.ts
Normal file
11
packages/backend/convex/schema.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { defineSchema, defineTable } from "convex/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
export default defineSchema({
|
||||
notes: defineTable({
|
||||
userId: v.string(),
|
||||
title: v.string(),
|
||||
content: v.string(),
|
||||
summary: v.optional(v.string()),
|
||||
}),
|
||||
});
|
||||
24
packages/backend/convex/tsconfig.json
Normal file
24
packages/backend/convex/tsconfig.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
/* 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 required to use Convex.
|
||||
*/
|
||||
"compilerOptions": {
|
||||
/* These settings are not required by Convex and can be modified. */
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
|
||||
/* These compiler options are required by Convex */
|
||||
"target": "ESNext",
|
||||
"lib": ["ES2021", "dom"],
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"isolatedModules": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["./**/*"],
|
||||
"exclude": ["./_generated"]
|
||||
}
|
||||
16
packages/backend/convex/utils.ts
Normal file
16
packages/backend/convex/utils.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export function missingEnvVariableUrl(envVarName: string, whereToGet: string) {
|
||||
const deployment = deploymentName();
|
||||
if (!deployment) return `Missing ${envVarName} in environment variables.`;
|
||||
return (
|
||||
`\n Missing ${envVarName} in environment variables.\n\n` +
|
||||
` Get it from ${whereToGet} .\n Paste it on the Convex dashboard:\n` +
|
||||
` https://dashboard.convex.dev/d/${deployment}/settings?var=${envVarName}`
|
||||
);
|
||||
}
|
||||
|
||||
export function deploymentName() {
|
||||
const url = process.env.CONVEX_CLOUD_URL;
|
||||
if (!url) return undefined;
|
||||
const regex = new RegExp("https://(.+).convex.cloud");
|
||||
return regex.exec(url)?.[1];
|
||||
}
|
||||
10
packages/backend/env.ts
Normal file
10
packages/backend/env.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { createEnv } from "@t3-oss/env-core";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export const authEnv = () => {
|
||||
return createEnv({
|
||||
server: {},
|
||||
runtimeEnv: process.env,
|
||||
skipValidation: !!process.env.CI,
|
||||
});
|
||||
};
|
||||
40
packages/backend/package.json
Normal file
40
packages/backend/package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@acme/backend",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"description": "Convex Backend for Monorepo",
|
||||
"author": "Gib",
|
||||
"license": "MIT",
|
||||
"exports": {},
|
||||
"scripts": {
|
||||
"dev": "convex dev",
|
||||
"dev:tunnel": "convex dev",
|
||||
"setup": "convex dev --until-success",
|
||||
"clean": "git clean -xdf .cache .turbo dist node_modules",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint --flag unstable_native_nodejs_ts_config",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oslojs/crypto": "^1.0.1",
|
||||
"@react-email/components": "0.5.4",
|
||||
"@react-email/render": "^1.4.0",
|
||||
"@t3-oss/env-core": "^0.13.8",
|
||||
"convex": "^1.28.0",
|
||||
"react": "19.1.1",
|
||||
"react-dom": "19.1.1",
|
||||
"usesend-js": "^1.5.6",
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@acme/eslint-config": "workspace:*",
|
||||
"@acme/prettier-config": "workspace:*",
|
||||
"@acme/tsconfig": "workspace:*",
|
||||
"eslint": "catalog:",
|
||||
"prettier": "catalog:",
|
||||
"react-email": "4.2.11",
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"prettier": "@acme/prettier-config"
|
||||
}
|
||||
Reference in New Issue
Block a user