mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Datasets: URL→inline conversion drops url/fetchedAt
This commit is contained in:
@@ -112,6 +112,21 @@ describe('URL dataset edits & refresh', () => {
|
|||||||
expect(ds.name).toBe('Remote'); // preserved
|
expect(ds.name).toBe('Remote'); // preserved
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('a URL→inline conversion removes the url/fetchedAt keys (not left undefined)', () => {
|
||||||
|
const id = seedUrl();
|
||||||
|
store().startEdit();
|
||||||
|
store().updateForm({ source: 'inline', input: '[{"x":1},{"x":2}]' });
|
||||||
|
const later = new Date('2026-07-01T00:00:00Z');
|
||||||
|
expect(store().save(later)).toBe(true);
|
||||||
|
const ds = store().datasets.find((d) => d.id === id)!;
|
||||||
|
expect(ds.source).toBe('inline');
|
||||||
|
expect(ds.rowCount).toBe(2);
|
||||||
|
// The remote origin is shed entirely — the keys are gone, not present-but-undefined,
|
||||||
|
// so an inline record carries no stale url/fetchedAt.
|
||||||
|
expect('url' in ds).toBe(false);
|
||||||
|
expect('fetchedAt' in ds).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
test('refreshDataset is a no-op for an inline dataset', () => {
|
test('refreshDataset is a no-op for an inline dataset', () => {
|
||||||
store().add(
|
store().add(
|
||||||
createDataset({ name: 'Inline', data: [{ a: 1 }], format: 'json', source: 'inline', now: T }),
|
createDataset({ name: 'Inline', data: [{ a: 1 }], format: 'json', source: 'inline', now: T }),
|
||||||
|
|||||||
@@ -291,11 +291,9 @@ export const useDatasetStore = create<DatasetState>((set, get) => ({
|
|||||||
data: resolved.data,
|
data: resolved.data,
|
||||||
format: resolved.format,
|
format: resolved.format,
|
||||||
source: resolved.source,
|
source: resolved.source,
|
||||||
// TODO: `update` shallow-merges, so these set the keys to `undefined`
|
// A URL→inline conversion must shed the remote origin; `update` deletes
|
||||||
// rather than removing them — a URL→inline record keeps `url`/`fetchedAt`
|
// keys set to `undefined`, so these are removed rather than left
|
||||||
// present-but-undefined. Invisible today (rendering/profiling key off
|
// present-but-undefined.
|
||||||
// `source`/`data == null`, and JSON export drops undefined), but it breaks
|
|
||||||
// the "inline records carry no url/fetchedAt keys" invariant on this path.
|
|
||||||
url: undefined,
|
url: undefined,
|
||||||
fetchedAt: undefined,
|
fetchedAt: undefined,
|
||||||
comment: form.comment,
|
comment: form.comment,
|
||||||
@@ -415,7 +413,18 @@ export const useDatasetStore = create<DatasetState>((set, get) => ({
|
|||||||
update: (id, patch, now) => {
|
update: (id, patch, now) => {
|
||||||
const modified = patch.modified ?? (now ?? new Date()).toISOString();
|
const modified = patch.modified ?? (now ?? new Date()).toISOString();
|
||||||
set((s) => ({
|
set((s) => ({
|
||||||
datasets: s.datasets.map((d) => (d.id === id ? { ...d, ...patch, modified } : d)),
|
datasets: s.datasets.map((d) => {
|
||||||
|
if (d.id !== id) return d;
|
||||||
|
const merged = { ...d, ...patch, modified };
|
||||||
|
// A patch key set to `undefined` removes it, rather than leaving a
|
||||||
|
// present-but-undefined key — so a URL→inline conversion drops `url`/
|
||||||
|
// `fetchedAt` cleanly, keeping the "inline records carry no remote-origin
|
||||||
|
// keys" invariant (docs/architecture/07 §6).
|
||||||
|
for (const key of Object.keys(patch) as (keyof Dataset)[]) {
|
||||||
|
if (patch[key] === undefined) delete merged[key];
|
||||||
|
}
|
||||||
|
return merged;
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user