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;