diff --git a/.prettierignore b/.prettierignore index 85f4d4535762..b50914ea60a3 100644 --- a/.prettierignore +++ b/.prettierignore @@ -24,3 +24,4 @@ test/**/out/** bench/nested-deps/pages/**/* bench/nested-deps/components/**/* pnpm-lock.yaml +**/convex/_generated/** diff --git a/examples/convex/.prettierignore b/examples/convex/.prettierignore new file mode 100644 index 000000000000..6c7e363c565d --- /dev/null +++ b/examples/convex/.prettierignore @@ -0,0 +1,2 @@ +.next +convex/_generated diff --git a/examples/convex/.prettierrc.json b/examples/convex/.prettierrc.json new file mode 100644 index 000000000000..fd496a820ea9 --- /dev/null +++ b/examples/convex/.prettierrc.json @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "semi": false +} diff --git a/examples/convex/convex.json b/examples/convex/convex.json new file mode 100644 index 000000000000..4f972abd4642 --- /dev/null +++ b/examples/convex/convex.json @@ -0,0 +1,6 @@ +{ + "authInfo": [], + "functions": "convex/", + "instanceName": "handsome-turtle-915", + "origin": "https://handsome-turtle-915.convex.cloud" +} diff --git a/examples/convex/convex/_generated/dataModel.ts b/examples/convex/convex/_generated/dataModel.ts new file mode 100644 index 000000000000..87c7cb3c1fbe --- /dev/null +++ b/examples/convex/convex/_generated/dataModel.ts @@ -0,0 +1,60 @@ +/* eslint-disable */ +/** + * Generated data model types. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * Generated by convex@0.1.8. + * To regenerate, run `npx convex codegen`. + * @module + */ + +import { AnyDataModel } from "convex/server"; +import { GenericId } from "convex/values"; + +/** + * No `schema.ts` file found! + * + * This generated code has permissive types like `Document = any` because + * Convex doesn't know your schema. If you'd like more type safety, see + * https://docs.convex.dev/using/schemas for instructions on how to add a + * schema file. + * + * After you write a schema, rerun codegen with `npx convex codegen`. + */ + +/** + * The names of all of your Convex tables. + */ +export type TableNames = string; + +/** + * The type of a document stored in Convex. + */ +export type Document = any; + +/** + * 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 [Data Modeling](https://docs.convex.dev/using/data-modeling). + * + * Documents can be loaded using `db.get(id)` in query and mutation functions. + * + * **Important**: Use `myId.equals(otherId)` to check for equality. + * Using `===` will not work because two different instances of `Id` can refer + * to the same document. + */ +export type Id = GenericId; +export const Id = GenericId; + +/** + * 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 = AnyDataModel; diff --git a/examples/convex/convex/_generated/react.ts b/examples/convex/convex/_generated/react.ts new file mode 100644 index 000000000000..0ed0e5634a0c --- /dev/null +++ b/examples/convex/convex/_generated/react.ts @@ -0,0 +1,82 @@ +/* eslint-disable */ +/** + * Generated React hooks. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * Generated by convex@0.1.8. + * To regenerate, run `npx convex codegen`. + * @module + */ + +import type getCounter from "../getCounter"; +import type incrementCounter from "../incrementCounter"; +import type { OptimisticLocalStore as GenericOptimisticLocalStore } from "convex/browser"; +import type { ClientMutation, ClientQuery } from "convex/server"; + +/** + * A type describing your app's public Convex API. + * + * This `ConvexAPI` type includes information about the arguments and return + * types of your app's query and mutation functions. + * + * This type should be used with type-parameterized classes like + * `ConvexReactClient` to create app-specific types. + */ +export type ConvexAPI = { + queries: { + getCounter: ClientQuery; + }; + mutations: { + incrementCounter: ClientMutation; + }; +}; + +import { makeUseQuery, makeUseMutation, makeUseConvex } from "convex/react"; + +/** + * Load a reactive query within a React component. + * + * This React hook contains internal state that will cause a rerender whenever + * the query result changes. + * + * This relies on the {@link ConvexProvider} being above in the React component tree. + * + * @param name - The name of the query function. + * @param args - The arguments to the query function. + * @returns `undefined` if loading and the query's return value otherwise. + */ +export const useQuery = makeUseQuery(); + +/** + * Construct a new {@link ReactMutation}. + * + * Mutation objects can be called like functions to request execution of the + * corresponding Convex function, or further configured with + * [optimistic updates](https://docs.convex.dev/using/optimistic-updates). + * + * The value returned by this hook is stable across renders, so it can be used + * by React dependency arrays and memoization logic relying on object identity + * without causing rerenders. + * + * This relies on the {@link ConvexProvider} being above in the React component tree. + * + * @param name - The name of the mutation. + * @returns The {@link ReactMutation} object with that name. + */ +export const useMutation = makeUseMutation(); + +/** + * Get the {@link ConvexReactClient} within a React component. + * + * This relies on the {@link ConvexProvider} being above in the React component tree. + * + * @returns The active {@link ConvexReactClient} object, or `undefined`. + */ +export const useConvex = makeUseConvex(); + +/** + * A view of the query results currently in the Convex client for use within + * optimistic updates. + */ +export type OptimisticLocalStore = GenericOptimisticLocalStore; diff --git a/examples/convex/convex/_generated/server.ts b/examples/convex/convex/_generated/server.ts new file mode 100644 index 000000000000..0e8d913bbd0a --- /dev/null +++ b/examples/convex/convex/_generated/server.ts @@ -0,0 +1,79 @@ +/* eslint-disable */ +/** + * Generated utilities for implementing server-side Convex query and mutation functions. + * + * THIS CODE IS AUTOMATICALLY GENERATED. + * + * Generated by convex@0.1.8. + * To regenerate, run `npx convex codegen`. + * @module + */ + +import { + makeQuery, + makeMutation, + QueryCtx as GenericQueryCtx, + MutationCtx as GenericMutationCtx, + DatabaseReader as GenericDatabaseReader, + DatabaseWriter as GenericDatabaseWriter, +} from "convex/server"; +import { 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 const query = makeQuery(); + +/** + * 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 = makeMutation(); + +/** + * 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; + +/** + * 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; + +/** + * 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.table}, which starts + * building a query. + */ +export type DatabaseReader = GenericDatabaseReader; + +/** + * 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; diff --git a/examples/convex/convex/incrementCounter.ts b/examples/convex/convex/incrementCounter.ts index 0a6a3ea7c1e0..8e43836c7048 100644 --- a/examples/convex/convex/incrementCounter.ts +++ b/examples/convex/convex/incrementCounter.ts @@ -7,16 +7,16 @@ export default mutation( .filter((q) => q.eq(q.field('name'), counterName)) .first() if (counterDoc === null) { - counterDoc = { + db.insert('counter_table', { name: counterName, counter: increment, - } - db.insert('counter_table', counterDoc) + }) + // console.log messages appear in your browser's console and the Convex dashboard. + console.log('Created counter.') } else { counterDoc.counter += increment db.replace(counterDoc._id, counterDoc) + console.log(`Value of counter is now ${counterDoc.counter}.`) } - // Like console.log but relays log messages from the server to client. - console.log(`Value of counter is now ${counterDoc.counter}`) } ) diff --git a/examples/convex/convex/tsconfig.json b/examples/convex/convex/tsconfig.json new file mode 100644 index 000000000000..8d4ba9df0fd1 --- /dev/null +++ b/examples/convex/convex/tsconfig.json @@ -0,0 +1,28 @@ +{ + /* 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"], + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true, + "module": "ESNext", + "moduleResolution": "Node", + "isolatedModules": true, + "noEmit": true, + /* Prevents node_modules from adding additional global types e.g. node types */ + "types": [] + }, + "include": [ + "./**/*", + "../node_modules/convex/dist/esm/environment/index.d.ts" + ], + "exclude": ["./_generated"] +} diff --git a/examples/convex/package.json b/examples/convex/package.json index daee8a99275a..24cb00227708 100644 --- a/examples/convex/package.json +++ b/examples/convex/package.json @@ -6,10 +6,11 @@ "start": "next start" }, "dependencies": { + "convex": "latest", "next": "latest", + "prettier": "^2.7.1", "react": "^18.2.0", - "react-dom": "^18.2.0", - "convex": "^0.1.6" + "react-dom": "^18.2.0" }, "devDependencies": { "@types/node": "~16.11.12", diff --git a/examples/convex/styles/Home.module.css b/examples/convex/styles/Home.module.css index 94baf8c449a5..5d149f86a6a8 100644 --- a/examples/convex/styles/Home.module.css +++ b/examples/convex/styles/Home.module.css @@ -1,11 +1,13 @@ .container { padding: 0 2rem; + display: flex; + flex-direction: column; + min-height: 100vh; } .main { - min-height: 100vh; padding: 4rem 0; - flex: 1; + flex: 10; display: flex; flex-direction: column; justify-content: center;