Skip to content

Commit

Permalink
fix: deleting a property in keel was not setting it to null
Browse files Browse the repository at this point in the history
  • Loading branch information
jmeistrich committed Aug 29, 2024
1 parent 11fa6ab commit 93e7556
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 11 deletions.
6 changes: 5 additions & 1 deletion src/sync-plugins/crud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,11 @@ export function syncedCrud<TRemote extends object, TLocal = TRemote, TAsOption e
isCreate = false;
}
if (isCreate || retryAsCreate) {
creates.set(id, value);
if (createFn) {
creates.set(id, value);
} else {
console.log('[legend-state] missing create function');
}
} else if (path.length === 0) {
if (valueAtPath) {
updates.set(id, getUpdateValue(valueAtPath, prevAtPath));
Expand Down
20 changes: 11 additions & 9 deletions src/sync-plugins/keel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,18 +202,21 @@ async function handleApiError(error: APIError, retry?: () => any) {
}
}

function convertObjectToCreate<TRemote>(item: TRemote): TRemote {
const cloned = clone(item);
Object.keys(cloned).forEach((key) => {
function convertObjectToCreate<TRemote extends Record<string, any>>(item: TRemote): TRemote {
const cloned: Record<string, any> = {};
Object.keys(item).forEach((key) => {
if (key.endsWith('Id')) {
if (cloned[key]) {
if (item[key]) {
cloned[key.slice(0, -2)] = { id: cloned[key] };
}
delete cloned[key];
} else if (key !== 'createdAt' && key !== 'updatedAt') {
if (item[key] === undefined) {
cloned[key] = null;
} else {
cloned[key] = item[key];
}
}
});
delete cloned.createdAt;
delete cloned.updatedAt;
return cloned as unknown as TRemote;
}

Expand Down Expand Up @@ -483,8 +486,7 @@ export function syncedKeel<
const values = convertObjectToCreate(input as unknown as Partial<KeelObjectBase>) as Partial<TRemote> &
Partial<KeelObjectBase>;
delete values.id;
delete values.createdAt;
delete values.updatedAt;

if (!isEmpty(values)) {
const { data, error } = await updateParam({ where: { id }, values });

Expand Down
35 changes: 35 additions & 0 deletions tests/crud.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,41 @@ describe('update partial', () => {
another: 3,
});
});
test('with updatePartial deleting a key', async () => {
let updated = undefined;
const obs = observable(
syncedCrud({
get: () => ({ ...ItemBasicValue(), other: 2, another: 3 }),
update: async (value) => {
updated = value;
return value;
},
updatePartial: true,
}),
);

obs.get();

await promiseTimeout(1);

expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
other: 2,
another: 3,
});

obs.other.delete();

await promiseTimeout(1);

expect(updated).toEqual({ id: 'id1', other: undefined });
expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
another: 3,
});
});
test('with updatePartial setting multiple', async () => {
const updated: any[] = [];
const obs = observable(
Expand Down
89 changes: 88 additions & 1 deletion tests/keel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type Result<T, U> = NonNullable<Data<T> | Err<U>>;
interface BasicValue {
id: string;
test: string;
createdAt?: string | number | null;
updatedAt?: string | number | null;
parent?: {
child: {
Expand All @@ -32,6 +33,8 @@ interface BasicValue {
const ItemBasicValue: () => BasicValue = () => ({
id: 'id1',
test: 'hi',
createdAt: 1,
updatedAt: 1,
});

async function fakeKeelList<T>(results: T[]): Promise<APIResult<{ results: T[]; pageInfo: any }>> {
Expand Down Expand Up @@ -65,9 +68,11 @@ describe('keel', () => {
id1: {
id: 'id1',
test: 'hi',
createdAt: 1,
updatedAt: 1,
},
});
expect(obs.id1.get()).toEqual({ id: 'id1', test: 'hi' });
expect(obs.id1.get()).toEqual({ id: 'id1', test: 'hi', createdAt: 1, updatedAt: 1 });
expect(obs.id1.test.get()).toEqual('hi');
});
test('get', async () => {
Expand All @@ -84,6 +89,88 @@ describe('keel', () => {
expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
createdAt: 1,
updatedAt: 1,
});
});
test('setting a child value', async () => {
let updated = undefined;
const obs = observable(
syncedKeel({
get: () => fakeKeelGet({ ...ItemBasicValue(), other: 2, another: 3 }),
update: async (update) => {
const { values } = update;
updated = values;
return { data: values! } as any;
},
}),
);

obs.get();

await promiseTimeout(1);

expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
other: 2,
another: 3,
createdAt: 1,
updatedAt: 1,
});

obs.other.set(4);

await promiseTimeout(10);

expect(updated).toEqual({ other: 4 });
expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
another: 3,
other: 4,
createdAt: 1,
updatedAt: 1,
});
});
test('deleting a property sets it to null', async () => {
let updated = undefined;
const obs = observable(
syncedKeel({
get: () => fakeKeelGet({ ...ItemBasicValue(), other: 2, another: 3 }),
update: async (update) => {
const { values } = update;
updated = values;
return { data: values! } as any;
},
}),
);

obs.get();

await promiseTimeout(1);

expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
other: 2,
another: 3,
createdAt: 1,
updatedAt: 1,
});

obs.other.delete();

await promiseTimeout(10);

expect(updated).toEqual({ other: null });
expect(obs.get()).toEqual({
id: 'id1',
test: 'hi',
another: 3,
createdAt: 1,
updatedAt: 1,
other: null,
});
});
});

0 comments on commit 93e7556

Please sign in to comment.