Fix some mutations

This commit is contained in:
Hakan Shehu
2025-10-25 01:17:30 +02:00
parent 59ea93e136
commit ea34da3326
5 changed files with 55 additions and 31 deletions

View File

@@ -1,5 +1,3 @@
import { merge } from 'lodash-es';
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
import { MutationHandler } from '@colanode/client/lib/types';
import {
@@ -15,8 +13,8 @@ export class NodeUpdateMutationHandler
input: NodeUpdateMutationInput
): Promise<NodeUpdateMutationOutput> {
const workspace = this.getWorkspace(input.userId);
await workspace.nodes.updateNode(input.nodeId, (attributes) => {
return merge(attributes, input.attributes);
await workspace.nodes.updateNode(input.nodeId, () => {
return input.attributes;
});
return {

View File

@@ -4,7 +4,7 @@ export type NodeUpdateMutationInput = {
type: 'node.update';
userId: string;
nodeId: string;
attributes: Partial<NodeAttributes>;
attributes: NodeAttributes;
};
export type NodeUpdateMutationOutput = {

View File

@@ -52,11 +52,16 @@ export class YDoc {
schema: z.ZodSchema,
object: z.infer<typeof schema>
): Uint8Array | null {
if (!schema.safeParse(object).success) {
throw new Error('Invalid object', schema.safeParse(object).error);
const normalizedObject = this.normalizeForUpdate(object);
const parseResult = schema.safeParse(normalizedObject);
if (!parseResult.success) {
throw new Error(`Invalid object: ${parseResult.error.message}`, {
cause: parseResult.error,
});
}
const objectSchema = this.extractType(schema, object);
const objectSchema = this.extractType(schema, normalizedObject);
if (!(objectSchema instanceof z.ZodObject)) {
throw new Error('Schema must be a ZodObject');
}
@@ -70,7 +75,7 @@ export class YDoc {
const objectMap = this.doc.getMap('object');
this.doc.transact(() => {
this.applyObjectChanges(objectSchema, object, objectMap);
this.applyObjectChanges(objectSchema, normalizedObject, objectMap);
const parseResult = schema.safeParse(objectMap.toJSON());
if (!parseResult.success) {
@@ -469,4 +474,26 @@ export class YDoc {
return schema;
}
private normalizeForUpdate(object: any): any {
if (object === null || object === undefined) {
return object;
}
if (Array.isArray(object)) {
return object.map((item) => this.normalizeForUpdate(item));
}
if (typeof object === 'object') {
const normalized: any = {};
for (const [key, value] of Object.entries(object)) {
if (value !== undefined) {
normalized[key] = this.normalizeForUpdate(value);
}
}
return normalized;
}
return object;
}
}

View File

@@ -83,22 +83,24 @@ export const SelectFieldOptions = ({
);
}
if (!fieldDraft.options) {
fieldDraft.options = {};
}
const maxIndex = Object.values(fieldDraft.options)
const existingOptions = fieldDraft.options ?? {};
const maxIndex = Object.values(existingOptions)
.map((selectOption) => selectOption.index)
.sort((a, b) => -compareString(a, b))[0];
const index = generateFractionalIndex(maxIndex, null);
fieldDraft.options[selectOptionId] = {
const updatedOptions = {
...existingOptions,
[selectOptionId]: {
name: name,
id: selectOptionId,
color: color,
index: index,
},
};
fieldDraft.options = updatedOptions;
});
return selectOptionId;
@@ -113,6 +115,7 @@ export const SelectFieldOptions = ({
onSelect(selectOptionId);
},
onError: (error) => {
console.log('error', error);
toast.error(error.message as string);
},
});

View File

@@ -1,4 +1,5 @@
import { createCollection } from '@tanstack/react-db';
import { cloneDeep } from 'lodash-es';
import { LocalNode } from '@colanode/client/types';
@@ -49,38 +50,33 @@ export const createNodesCollection = (userId: string) => {
},
},
onInsert: async ({ transaction }) => {
transaction.mutations.forEach(async (mutation) => {
for (const mutation of transaction.mutations) {
await window.colanode.executeMutation({
type: 'node.create',
userId,
node: mutation.modified,
});
});
}
},
onUpdate: async ({ transaction }) => {
transaction.mutations.forEach(async (mutation) => {
console.log('onUpdate', mutation);
const attributes = mutation.changes.attributes;
if (!attributes) {
return;
}
for (const mutation of transaction.mutations) {
const attributes = cloneDeep(mutation.modified.attributes);
await window.colanode.executeMutation({
type: 'node.update',
userId,
nodeId: mutation.key,
attributes,
});
});
}
},
onDelete: async ({ transaction }) => {
transaction.mutations.forEach(async (mutation) => {
for (const mutation of transaction.mutations) {
await window.colanode.executeMutation({
type: 'node.delete',
userId,
nodeId: mutation.key,
});
});
}
},
});
};