From 0e686a1f85b61fa74a2191cca0f9a6d1b76892d8 Mon Sep 17 00:00:00 2001 From: kenneth Date: Fri, 3 Oct 2025 21:23:51 +0000 Subject: [PATCH] refactor[db]: store time as unix ms Co-authored-by: Ona --- bun.lock | 1 + packages/convex/README.md | 90 +++++++++++++++++++++ packages/convex/_generated/api.d.ts | 2 + packages/convex/files.ts | 2 +- packages/convex/filesystem.ts | 2 +- packages/convex/model/directories.ts | 6 +- packages/convex/model/files.ts | 4 +- packages/convex/model/user.ts | 2 +- packages/convex/schema.ts | 12 +-- packages/convex/tsconfig.json | 25 ++++++ packages/web/src/routes/login_.callback.tsx | 1 - 11 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 packages/convex/README.md create mode 100644 packages/convex/tsconfig.json diff --git a/bun.lock b/bun.lock index 5e10453..62e7c2f 100644 --- a/bun.lock +++ b/bun.lock @@ -13,6 +13,7 @@ "name": "@fileone/convex", "dependencies": { "@fileone/path": "workspace:*", + "convex-helpers": "^0.1.104", }, "peerDependencies": { "convex": "^1.27.0", diff --git a/packages/convex/README.md b/packages/convex/README.md new file mode 100644 index 0000000..7fda0c3 --- /dev/null +++ b/packages/convex/README.md @@ -0,0 +1,90 @@ +# 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(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`. diff --git a/packages/convex/_generated/api.d.ts b/packages/convex/_generated/api.d.ts index 5fd0788..c462248 100644 --- a/packages/convex/_generated/api.d.ts +++ b/packages/convex/_generated/api.d.ts @@ -13,6 +13,7 @@ import type { FilterApi, FunctionReference, } from "convex/server"; +import type * as admin from "../admin.js"; import type * as files from "../files.js"; import type * as filesystem from "../filesystem.js"; import type * as functions from "../functions.js"; @@ -32,6 +33,7 @@ import type * as users from "../users.js"; * ``` */ declare const fullApi: ApiFromModules<{ + admin: typeof admin; files: typeof files; filesystem: typeof filesystem; functions: typeof functions; diff --git a/packages/convex/files.ts b/packages/convex/files.ts index dfc9917..19740ee 100644 --- a/packages/convex/files.ts +++ b/packages/convex/files.ts @@ -81,7 +81,7 @@ export const saveFile = authenticatedMutation({ mimeType: v.optional(v.string()), }, handler: async (ctx, { name, storageId, directoryId, size, mimeType }) => { - const now = new Date().toISOString() + const now = Date.now() await ctx.db.insert("files", { name, diff --git a/packages/convex/filesystem.ts b/packages/convex/filesystem.ts index 5365f7f..889f0f1 100644 --- a/packages/convex/filesystem.ts +++ b/packages/convex/filesystem.ts @@ -70,7 +70,7 @@ export const moveToTrash = authenticatedMutation({ case FileType.File: return ctx.db .patch(handle.id, { - deletedAt: new Date().toISOString(), + deletedAt: Date.now(), }) .then(() => handle) case FileType.Directory: diff --git a/packages/convex/model/directories.ts b/packages/convex/model/directories.ts index 695d0d0..23f54ff 100644 --- a/packages/convex/model/directories.ts +++ b/packages/convex/model/directories.ts @@ -144,7 +144,7 @@ export async function create( ) } - const now = new Date().toISOString() + const now = Date.now() return await ctx.db.insert("directories", { name, parentId, @@ -216,7 +216,7 @@ export async function move( ignoredHandles.add(handle) } else { promises.push( - ctx.db.patch(handle.id, { parentId: targetDirectory.id }), + ctx.db.patch(handle.id, { parentId: targetDirectory.id, updatedAt: Date.now() }), ) } } @@ -239,7 +239,7 @@ export async function moveToTrashRecursive( ctx: AuthenticatedMutationCtx, handle: DirectoryHandle, ): Promise { - const now = new Date().toISOString() + const now = Date.now() const filesToDelete: Id<"files">[] = [] const directoriesToDelete: Id<"directories">[] = [] diff --git a/packages/convex/model/files.ts b/packages/convex/model/files.ts index 85ec5b0..2f58636 100644 --- a/packages/convex/model/files.ts +++ b/packages/convex/model/files.ts @@ -33,7 +33,7 @@ export async function renameFile( ) } - await ctx.db.patch(itemId, { name: newName }) + await ctx.db.patch(itemId, { name: newName, updatedAt: Date.now() }) } export async function move( @@ -90,7 +90,7 @@ export async function move( const results = await Promise.allSettled( okFiles.map((handle) => - ctx.db.patch(handle.id, { directoryId: targetDirectoryHandle.id }), + ctx.db.patch(handle.id, { directoryId: targetDirectoryHandle.id, updatedAt: Date.now() }), ), ) diff --git a/packages/convex/model/user.ts b/packages/convex/model/user.ts index 632e6b1..c62069d 100644 --- a/packages/convex/model/user.ts +++ b/packages/convex/model/user.ts @@ -39,7 +39,7 @@ export async function userOrThrow(ctx: QueryCtx | MutationCtx) { } export async function register(ctx: AuthenticatedMutationCtx) { - const now = new Date().toISOString() + const now = Date.now() await Promise.all([ ctx.db.insert("users", { jwtSubject: ctx.identity.subject, diff --git a/packages/convex/schema.ts b/packages/convex/schema.ts index 783d4b4..6571c21 100644 --- a/packages/convex/schema.ts +++ b/packages/convex/schema.ts @@ -12,9 +12,9 @@ const schema = defineSchema({ name: v.string(), size: v.number(), mimeType: v.optional(v.string()), - createdAt: v.string(), - updatedAt: v.string(), - deletedAt: v.optional(v.string()), + createdAt: v.number(), + updatedAt: v.number(), + deletedAt: v.optional(v.number()), }) .index("byDirectoryId", ["userId", "directoryId", "deletedAt"]) .index("byUserId", ["userId", "deletedAt"]) @@ -29,9 +29,9 @@ const schema = defineSchema({ name: v.string(), userId: v.id("users"), parentId: v.optional(v.id("directories")), - createdAt: v.string(), - updatedAt: v.string(), - deletedAt: v.optional(v.string()), + createdAt: v.number(), + updatedAt: v.number(), + deletedAt: v.optional(v.number()), }) .index("byUserId", ["userId", "deletedAt"]) .index("byParentId", ["userId", "parentId", "deletedAt"]) diff --git a/packages/convex/tsconfig.json b/packages/convex/tsconfig.json new file mode 100644 index 0000000..7374127 --- /dev/null +++ b/packages/convex/tsconfig.json @@ -0,0 +1,25 @@ +{ + /* 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, + + /* These compiler options are required by Convex */ + "target": "ESNext", + "lib": ["ES2021", "dom"], + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "isolatedModules": true, + "noEmit": true + }, + "include": ["./**/*"], + "exclude": ["./_generated"] +} diff --git a/packages/web/src/routes/login_.callback.tsx b/packages/web/src/routes/login_.callback.tsx index d02a9e9..b651900 100644 --- a/packages/web/src/routes/login_.callback.tsx +++ b/packages/web/src/routes/login_.callback.tsx @@ -19,7 +19,6 @@ function RouteComponent() { useEffect(() => { if (!isLoadingConvexAuth && isAuthenticated && !isSyncingUser) { - console.log({ isLoadingConvexAuth, isAuthenticated, isSyncingUser }) syncUser(undefined, { onSuccess: () => { navigate({