Remove index column from node tables

This commit is contained in:
Hakan Shehu
2024-11-22 20:05:25 +01:00
parent d50e3018a1
commit 95e91319f2
25 changed files with 31 additions and 57 deletions

View File

@@ -96,7 +96,6 @@
"clsx": "^2.1.1",
"cmdk": "^1.0.4",
"electron-squirrel-startup": "^1.0.1",
"fractional-indexing-jittered": "^0.9.1",
"is-hotkey": "^0.2.0",
"lowlight": "^3.1.0",
"lucide-react": "^0.460.0",

View File

@@ -19,9 +19,6 @@ const createNodesTable: Migration = {
.onDelete('cascade')
.notNull()
)
.addColumn('index', 'text', (col) =>
col.generatedAlwaysAs(sql`json_extract(attributes, '$.index')`).stored()
)
.addColumn('attributes', 'text', (col) => col.notNull())
.addColumn('state', 'blob', (col) => col.notNull())
.addColumn('created_at', 'text', (col) => col.notNull())

View File

@@ -4,7 +4,6 @@ interface NodeTable {
id: ColumnType<string, string, never>;
parent_id: ColumnType<string, never, never>;
type: ColumnType<string, never, never>;
index: ColumnType<string | null, never, never>;
attributes: ColumnType<string, string, string>;
state: ColumnType<Uint8Array, Uint8Array, Uint8Array>;
created_at: ColumnType<string, string, never>;

View File

@@ -1,6 +1,5 @@
import { databaseService } from '@/main/data/database-service';
import { generateId, IdType } from '@colanode/core';
import { generateNodeIndex } from '@/shared/lib/nodes';
import { MutationHandler } from '@/main/types';
import {
ChannelCreateMutationInput,
@@ -29,23 +28,12 @@ export class ChannelCreateMutationHandler
throw new Error('Space not found');
}
const maxIndexResult = await workspaceDatabase
.selectFrom('nodes')
.select(['index'])
.where('parent_id', '=', input.spaceId)
.orderBy('index', 'desc')
.limit(1)
.executeTakeFirst();
const maxIndex = maxIndexResult?.index ?? null;
const id = generateId(IdType.Channel);
const attributes: ChannelAttributes = {
type: 'channel',
name: input.name,
avatar: input.avatar,
parentId: input.spaceId,
index: generateNodeIndex(maxIndex, null),
collaborators: null,
};

View File

@@ -1,11 +1,14 @@
import { generateId, IdType } from '@colanode/core';
import { generateNodeIndex } from '@/shared/lib/nodes';
import {
generateId,
IdType,
DatabaseAttributes,
generateNodeIndex,
} from '@colanode/core';
import { MutationHandler } from '@/main/types';
import {
DatabaseCreateMutationInput,
DatabaseCreateMutationOutput,
} from '@/shared/mutations/database-create';
import { DatabaseAttributes } from '@colanode/core';
import { nodeService } from '@/main/services/node-service';
export class DatabaseCreateMutationHandler

View File

@@ -1,5 +1,4 @@
import { generateId, IdType } from '@colanode/core';
import { generateNodeIndex } from '@/shared/lib/nodes';
import { generateId, IdType, generateNodeIndex } from '@colanode/core';
import { compareString } from '@/shared/lib/utils';
import { MutationHandler } from '@/main/types';
import {

View File

@@ -1,5 +1,4 @@
import { generateId, IdType } from '@colanode/core';
import { generateNodeIndex } from '@/shared/lib/nodes';
import { generateId, IdType, generateNodeIndex } from '@colanode/core';
import { MutationHandler } from '@/main/types';
import {
SelectOptionCreateMutationInput,

View File

@@ -1,5 +1,4 @@
import { generateId, IdType, NodeRoles } from '@colanode/core';
import { generateNodeIndex } from '@/shared/lib/nodes';
import { MutationHandler } from '@/main/types';
import {
SpaceCreateMutationInput,
@@ -59,7 +58,6 @@ export class SpaceCreateMutationHandler
type: 'channel',
name: 'Discussions',
parentId: spaceId,
index: generateNodeIndex(null, null),
};
await nodeService.createNode(input.userId, [

View File

@@ -1,11 +1,10 @@
import { generateId, IdType } from '@colanode/core';
import { generateId, IdType, generateNodeIndex } from '@colanode/core';
import { MutationHandler } from '@/main/types';
import {
ViewCreateMutationInput,
ViewCreateMutationOutput,
} from '@/shared/mutations/view-create';
import { compareString } from '@/shared/lib/utils';
import { generateNodeIndex } from '@/shared/lib/nodes';
import { nodeService } from '@/main/services/node-service';
export class ViewCreateMutationHandler

View File

@@ -87,7 +87,6 @@ export const mapNode = (row: SelectNode): Node => {
return {
id: row.id,
type: row.type as any,
index: row.index,
parentId: row.parent_id,
attributes: JSON.parse(row.attributes),
createdAt: row.created_at,

View File

@@ -40,6 +40,7 @@ import {
ChevronRight,
} from 'lucide-react';
import { useQuery } from '@/renderer/hooks/use-query';
import { compareString } from '@/shared/lib/utils';
interface SettingsState {
open: boolean;
@@ -60,7 +61,7 @@ export const SpaceSidebarItem = ({ node }: SpaceSidebarItemProps) => {
types: ['page', 'channel', 'database', 'folder'],
});
const children = data ?? [];
const children = (data ?? []).toSorted((a, b) => compareString(a.id, b.id));
const [openCreatePage, setOpenCreatePage] = React.useState(false);
const [openCreateChannel, setOpenCreateChannel] = React.useState(false);

View File

@@ -9,9 +9,9 @@ import {
MultiSelectFieldAttributes,
SelectFieldAttributes,
ViewType,
generateNodeIndex,
} from '@colanode/core';
import { compareString, isStringArray } from '@/shared/lib/utils';
import { generateNodeIndex } from '@/shared/lib/nodes';
export const getDefaultFieldWidth = (type: FieldType): number => {
if (!type) return 0;

View File

@@ -1,5 +1,9 @@
import { EditorNodeTypes, generateId, getIdTypeFromNode } from '@colanode/core';
import { generateNodeIndex } from '@/shared/lib/nodes';
import {
EditorNodeTypes,
generateId,
getIdTypeFromNode,
generateNodeIndex,
} from '@colanode/core';
import { compareString } from '@/shared/lib/utils';
import { JSONContent } from '@tiptap/core';
import { Block, BlockLeaf } from '@colanode/core';

View File

@@ -1,17 +1,6 @@
import { generateKeyBetween } from 'fractional-indexing-jittered';
import { extractNodeCollaborators, Node, NodeTypes } from '@colanode/core';
import { NodeCollaborator } from '@/shared/types/nodes';
export const generateNodeIndex = (
previous?: string | null,
next?: string | null
) => {
const lower = previous === undefined ? null : previous;
const upper = next === undefined ? null : next;
return generateKeyBetween(lower, upper);
};
export const getDefaultNodeIcon = (type: string) => {
switch (type) {
case NodeTypes.Channel:

View File

@@ -111,9 +111,6 @@ const createNodesTable: Migration = {
.onDelete('cascade')
.notNull()
)
.addColumn('index', 'varchar(30)', (col) =>
col.generatedAlwaysAs(sql`(attributes->>'index')::VARCHAR(30)`).stored()
)
.addColumn('attributes', 'jsonb', (col) => col.notNull())
.addColumn('state', 'bytea', (col) => col.notNull())
.addColumn('created_at', 'timestamptz', (col) => col.notNull())

View File

@@ -86,7 +86,6 @@ interface NodeTable {
workspace_id: ColumnType<string, string, never>;
parent_id: ColumnType<string, never, never>;
type: ColumnType<string, never, never>;
index: ColumnType<string | null, never, never>;
attributes: JSONColumnType<NodeAttributes, string | null, string | null>;
state: ColumnType<Uint8Array, Uint8Array, Uint8Array>;
created_at: ColumnType<Date, Date, never>;

View File

@@ -16,7 +16,6 @@ export const mapNodeOutput = (node: SelectNode): NodeOutput => {
parentId: node.parent_id,
workspaceId: node.workspace_id,
type: node.type,
index: node.index,
attributes: node.attributes,
state: fromUint8Array(node.state),
createdAt: node.created_at.toISOString(),
@@ -34,7 +33,6 @@ export const mapNode = (node: SelectNode): Node => {
id: node.id,
parentId: node.parent_id,
type: node.type as NodeType,
index: node.index,
attributes: node.attributes,
createdAt: node.created_at.toISOString(),
createdBy: node.created_by,

View File

@@ -209,7 +209,6 @@ const buildChannelNodeCreate = (
type: 'channel',
name: 'Discussions',
parentId: spaceId,
index: '0',
};
const ydoc = new YDoc(id);

View File

@@ -619,7 +619,6 @@ workspacesRouter.post(
serverCreatedAt: new Date().toISOString(),
versionId: userVersionId,
workspaceId: workspace.id,
index: null,
};
usersToCreate.push({
@@ -776,7 +775,6 @@ workspacesRouter.put(
id: user.id,
type: user.type,
workspaceId: user.workspace_id,
index: null,
parentId: workspace.id,
attributes: userDoc.getAttributes(),
state: userDoc.getEncodedState(),

2
package-lock.json generated
View File

@@ -77,7 +77,6 @@
"clsx": "^2.1.1",
"cmdk": "^1.0.4",
"electron-squirrel-startup": "^1.0.1",
"fractional-indexing-jittered": "^0.9.1",
"is-hotkey": "^0.2.0",
"lowlight": "^3.1.0",
"lucide-react": "^0.460.0",
@@ -18397,6 +18396,7 @@
"name": "@colanode/core",
"version": "1.0.0",
"dependencies": {
"fractional-indexing-jittered": "^0.9.1",
"ulid": "^2.3.0",
"zod": "^3.23.8"
},

View File

@@ -25,6 +25,7 @@
"vitest": "^2.1.5"
},
"dependencies": {
"fractional-indexing-jittered": "^0.9.1",
"ulid": "^2.3.0",
"zod": "^3.23.8"
}

View File

@@ -1,4 +1,5 @@
import { Node, NodeAttributes, NodeRole } from '../index';
import { generateKeyBetween } from 'fractional-indexing-jittered';
export const extractNodeCollaborators = (
attributes: NodeAttributes
@@ -55,3 +56,13 @@ export const hasViewerAccess = (role: NodeRole | null): boolean => {
role === 'viewer'
);
};
export const generateNodeIndex = (
previous?: string | null,
next?: string | null
) => {
const lower = previous === undefined ? null : previous;
const upper = next === undefined ? null : next;
return generateKeyBetween(lower, upper);
};

View File

@@ -7,7 +7,6 @@ export const channelAttributesSchema = z.object({
name: z.string(),
avatar: z.string().nullable().optional(),
parentId: z.string(),
index: z.string(),
collaborators: z.record(z.string()).nullable().optional(),
});

View File

@@ -14,7 +14,6 @@ import { WorkspaceAttributes, workspaceModel } from './workspace';
type NodeBase = {
id: string;
parentId: string;
index: string | null;
createdAt: string;
createdBy: string;
updatedAt: string | null;

View File

@@ -5,7 +5,6 @@ export type NodeOutput = {
workspaceId: string;
parentId: string;
type: string;
index: string | null;
attributes: NodeAttributes;
state: string;
createdAt: string;