diff --git a/app/page.tsx b/app/page.tsx index bbd23bd2..0dfb04f9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -9,6 +9,7 @@ import { redirect } from "next/navigation"; import postgres from "postgres"; import { Doc } from "./[doc_id]/Doc"; import { UpdateURL } from "components/UpdateURL"; +import { v7 } from "uuid"; const client = postgres(process.env.DB_URL as string); const db = drizzle(client); @@ -26,7 +27,7 @@ export default async function RootPage() { let [entity] = await tx .insert(entities) // And add it to that permission set - .values({ set: entity_set.id }) + .values({ set: entity_set.id, id: v7() }) .returning(); //Create a new permission token let [permissionToken] = await tx diff --git a/components/BlockOptions.tsx b/components/BlockOptions.tsx index 5f4530a6..6ee7d036 100644 --- a/components/BlockOptions.tsx +++ b/components/BlockOptions.tsx @@ -14,6 +14,7 @@ import { useState } from "react"; import { Separator } from "./Layout"; import { addLinkBlock } from "src/utils/addLinkBlock"; import { useEntitySetContext } from "./EntitySetProvider"; +import { v7 } from "uuid"; type Props = { parent: string; @@ -53,7 +54,7 @@ export function BlockOptions(props: Props) { await rep.mutate.retractFact({ factID: props.factID }); let entity = props.entityID; if (!entity) { - entity = crypto.randomUUID(); + entity = v7(); await rep?.mutate.addBlock({ parent: props.parent, permission_set: entity_set.set, @@ -85,7 +86,7 @@ export function BlockOptions(props: Props) { onMouseDown={(e) => e.preventDefault()} onClick={async () => { if (!props.entityID) { - let entity = crypto.randomUUID(); + let entity = v7(); await rep?.mutate.addBlock({ permission_set: entity_set.set, @@ -125,7 +126,7 @@ const BlockLinkButton = (props: Props) => { let submit = async () => { let entity = props.entityID; if (!entity) { - entity = crypto.randomUUID(); + entity = v7(); await rep?.mutate.addBlock({ permission_set: entity_set.set, diff --git a/components/Blocks.tsx b/components/Blocks.tsx index b223a086..6ca3e7b6 100644 --- a/components/Blocks.tsx +++ b/components/Blocks.tsx @@ -15,6 +15,7 @@ import { useBlocks } from "src/hooks/queries/useBlocks"; import { setEditorState, useEditorStates } from "src/state/useEditorState"; import { useEntitySetContext } from "./EntitySetProvider"; import { scanIndex } from "src/replicache/utils"; +import { v7 } from "uuid"; export type Block = { parent: string; @@ -38,7 +39,7 @@ export function Blocks(props: { entityID: string }) { !lastBlock || (lastBlock.type !== "text" && lastBlock.type !== "heading") ) { - let newEntityID = crypto.randomUUID(); + let newEntityID = v7(); await rep.rep?.mutate.addBlock({ parent: props.entityID, permission_set: entity_set.set, @@ -75,7 +76,7 @@ export function Blocks(props: { entityID: string }) {
{ - let newEntityID = crypto.randomUUID(); + let newEntityID = v7(); if (lastBlock && lastBlock.type === "text") { focusBlock({ ...lastBlock, type: "text" }, { type: "end" }); @@ -117,7 +118,7 @@ function NewBlockButton(props: { lastBlock: Block | null; entityID: string }) {
{ - let newEntityID = crypto.randomUUID(); + let newEntityID = v7(); await rep?.mutate.addBlock({ parent: props.entityID, type: "text", @@ -204,7 +205,7 @@ function Block(props: BlockProps) { if (block) focusBlock(block, { type: "end" }); } if (e.key === "Enter") { - let newEntityID = crypto.randomUUID(); + let newEntityID = v7(); r.mutate.addBlock({ permission_set: entity_set.set, newEntityID, @@ -239,6 +240,7 @@ function Block(props: BlockProps) {
{ + useSelectingMouse.setState({ start: props.entityID }); if (e.shiftKey) { e.preventDefault(); useUIState.getState().addBlockToSelection(props); diff --git a/components/TextBlock/keymap.ts b/components/TextBlock/keymap.ts index a670695d..23dd96b7 100644 --- a/components/TextBlock/keymap.ts +++ b/components/TextBlock/keymap.ts @@ -11,6 +11,7 @@ import { schema } from "./schema"; import { useUIState } from "src/useUIState"; import { setEditorState, useEditorStates } from "src/state/useEditorState"; import { focusCard } from "components/Cards"; +import { v7 } from "uuid"; export const TextBlockKeymap = ( propsRef: MutableRefObject, @@ -250,7 +251,7 @@ const enter = let newContent = tr.doc.slice(state.selection.anchor); tr.delete(state.selection.anchor, state.doc.content.size); dispatch?.(tr); - let newEntityID = crypto.randomUUID(); + let newEntityID = v7(); let position = generateKeyBetween( propsRef.current.position, propsRef.current.nextPosition, diff --git a/components/TextBlock/useHandlePaste.ts b/components/TextBlock/useHandlePaste.ts index d62db482..2f6d1bba 100644 --- a/components/TextBlock/useHandlePaste.ts +++ b/components/TextBlock/useHandlePaste.ts @@ -8,6 +8,7 @@ import { generateKeyBetween } from "fractional-indexing"; import { addImage } from "src/utils/addImage"; import { BlockProps, focusBlock } from "components/Blocks"; import { useEntitySetContext } from "components/EntitySetProvider"; +import { v7 } from "uuid"; export const useHandlePaste = ( entityID: string, @@ -67,7 +68,7 @@ export const useHandlePaste = ( if (index === 0 && type === propsRef.current.type) entityID = propsRef.current.entityID; else { - entityID = crypto.randomUUID(); + entityID = v7(); currentPosition = generateKeyBetween( currentPosition, propsRef.current.nextPosition, @@ -121,7 +122,7 @@ export const useHandlePaste = ( .filter((f) => !!f); let currentPosition = propsRef.current.position; for (let p of paragraphs) { - let newEntityID = crypto.randomUUID(); + let newEntityID = v7(); currentPosition = generateKeyBetween( currentPosition, propsRef.current.nextPosition, @@ -161,7 +162,7 @@ export const useHandlePaste = ( }); if (factID) rep.mutate.retractFact({ factID: factID }); } else { - entity = crypto.randomUUID(); + entity = v7(); rep.mutate.addBlock({ permission_set: entity_set.set, type: "image", diff --git a/drizzle/schema.ts b/drizzle/schema.ts index 13b7c8ba..138d6a8c 100644 --- a/drizzle/schema.ts +++ b/drizzle/schema.ts @@ -21,7 +21,7 @@ export const replicache_clients = pgTable("replicache_clients", { }); export const entities = pgTable("entities", { - id: uuid("id").defaultRandom().primaryKey().notNull(), + id: uuid("id").primaryKey().notNull(), created_at: timestamp("created_at", { withTimezone: true, mode: 'string' }).defaultNow().notNull(), set: uuid("set").notNull().references(() => entity_sets.id, { onDelete: "cascade", onUpdate: "cascade" } ), }); @@ -37,7 +37,7 @@ export const permission_tokens = pgTable("permission_tokens", { }); export const facts = pgTable("facts", { - id: uuid("id").defaultRandom().primaryKey().notNull(), + id: uuid("id").primaryKey().notNull(), entity: uuid("entity").notNull().references(() => entities.id, { onDelete: "cascade", onUpdate: "restrict" } ), attribute: text("attribute").notNull(), data: jsonb("data").notNull(), diff --git a/src/replicache/clientMutationContext.ts b/src/replicache/clientMutationContext.ts index afc275a1..3ac8d703 100644 --- a/src/replicache/clientMutationContext.ts +++ b/src/replicache/clientMutationContext.ts @@ -6,6 +6,7 @@ import { Attributes, FilterAttributes } from "./attributes"; import { Fact } from "."; import { MutationContext } from "./mutations"; import { supabaseBrowserClient } from "supabase/browserClient"; +import { v7 } from "uuid"; export function clientMutationContext(tx: WriteTransaction) { let ctx: MutationContext = { @@ -32,7 +33,7 @@ export function clientMutationContext(tx: WriteTransaction) { async assertFact(f) { let attribute = Attributes[f.attribute as keyof typeof Attributes]; if (!attribute) return; - let id = f.id || crypto.randomUUID(); + let id = f.id || v7(); let data = { ...f.data }; if (attribute.cardinality === "one") { let existingFact = await tx diff --git a/src/replicache/serverMutationContext.ts b/src/replicache/serverMutationContext.ts index 9a0d267f..c7810d06 100644 --- a/src/replicache/serverMutationContext.ts +++ b/src/replicache/serverMutationContext.ts @@ -9,6 +9,7 @@ import { Fact, PermissionToken } from "."; import { DeepReadonly } from "replicache"; import { createClient } from "@supabase/supabase-js"; import { Database } from "supabase/database.types"; +import { v7 } from "uuid"; export function serverMutationContext( tx: PgTransaction, token_rights: PermissionToken["permission_token_rights"], @@ -77,7 +78,7 @@ export function serverMutationContext( async assertFact(f) { let attribute = Attributes[f.attribute as keyof typeof Attributes]; if (!attribute) return; - let id = f.id || crypto.randomUUID(); + let id = f.id || v7(); let data = { ...f.data }; let [permission_set] = await tx .select({ entity_set: entities.set }) diff --git a/src/utils/addImage.ts b/src/utils/addImage.ts index 3858ef8f..aefd2360 100644 --- a/src/utils/addImage.ts +++ b/src/utils/addImage.ts @@ -3,6 +3,7 @@ import { ReplicacheMutators } from "../replicache"; import { supabaseBrowserClient } from "supabase/browserClient"; import { FilterAttributes } from "src/replicache/attributes"; import { rgbaToDataURL, rgbaToThumbHash, thumbHashToDataURL } from "thumbhash"; +import { v7 } from "uuid"; export async function addImage( file: File, @@ -14,7 +15,7 @@ export async function addImage( ) { let client = supabaseBrowserClient(); let cache = await caches.open("minilink-user-assets"); - let fileID = crypto.randomUUID(); + let fileID = v7(); let url = client.storage.from("minilink-user-assets").getPublicUrl(fileID) .data.publicUrl; let dimensions = await getImageDimensions(file); diff --git a/supabase/database.types.ts b/supabase/database.types.ts index 3b4bd810..6378e30f 100644 --- a/supabase/database.types.ts +++ b/supabase/database.types.ts @@ -42,7 +42,7 @@ export type Database = { } Insert: { created_at?: string - id?: string + id: string set: string } Update: { @@ -90,7 +90,7 @@ export type Database = { created_at?: string data: Json entity: string - id?: string + id: string updated_at?: string | null version?: number } diff --git a/supabase/migrations/20240707221949_make_ids_mandatory_for_entities_and_facts.sql b/supabase/migrations/20240707221949_make_ids_mandatory_for_entities_and_facts.sql new file mode 100644 index 00000000..8fada70b --- /dev/null +++ b/supabase/migrations/20240707221949_make_ids_mandatory_for_entities_and_facts.sql @@ -0,0 +1,3 @@ +alter table "public"."entities" alter column "id" drop default; + +alter table "public"."facts" alter column "id" drop default;