@furystack/filesystem-store
Version:
Simple File System store implementation for FuryStack
86 lines • 3.37 kB
JavaScript
import { createInjector } from '@furystack/inject';
import { mkdtemp, readFile, rm } from 'fs/promises';
import { tmpdir } from 'os';
import { join } from 'path';
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { defineFileSystemStore } from './define-filesystem-store.js';
import { FileSystemStore } from './filesystem-store.js';
class Item {
}
describe('defineFileSystemStore (metadata)', () => {
it('propagates name, lifetime, model and primaryKey onto the returned token', () => {
const token = defineFileSystemStore({
name: 'test/FsUserStore',
model: Item,
primaryKey: 'id',
fileName: 'fs-store-meta-test.json',
});
expect(token.name).toBe('test/FsUserStore');
expect(token.lifetime).toBe('singleton');
expect(token.model).toBe(Item);
expect(token.primaryKey).toBe('id');
});
it('mints a distinct token identity per call even when options match -- declare once at module scope', () => {
const options = {
name: 'test/FsDupe',
model: Item,
primaryKey: 'id',
fileName: 'fs-store-dupe-test.json',
};
const a = defineFileSystemStore(options);
const b = defineFileSystemStore(options);
expect(a.id).not.toBe(b.id);
});
});
describe('defineFileSystemStore (factory + disposal)', () => {
let workDir;
let fileName;
beforeEach(async () => {
workDir = await mkdtemp(join(tmpdir(), 'fs-store-spec-'));
fileName = join(workDir, 'items.json');
});
afterEach(async () => {
await rm(workDir, { recursive: true, force: true });
});
it('instantiates a FileSystemStore that forwards model, primaryKey and fileName', async () => {
const Token = defineFileSystemStore({
name: 'test/FsFactory',
model: Item,
primaryKey: 'id',
fileName,
tickMs: 60_000,
});
const injector = createInjector();
try {
const store = injector.get(Token);
expect(store).toBeInstanceOf(FileSystemStore);
expect(store.model).toBe(Item);
expect(store.primaryKey).toBe('id');
await store.add({ id: '1', value: 'alpha' });
await store.saveChanges();
const persisted = JSON.parse((await readFile(fileName)).toString());
expect(persisted).toEqual([{ id: '1', value: 'alpha' }]);
}
finally {
await injector[Symbol.asyncDispose]();
}
});
it('flushes pending changes when the owning injector is disposed', async () => {
const Token = defineFileSystemStore({
name: 'test/FsDispose',
model: Item,
primaryKey: 'id',
fileName,
tickMs: 60_000,
});
const injector = createInjector();
const store = injector.get(Token);
await store.add({ id: '1', value: 'bravo' });
expect(store.hasChanges).toBe(true);
await injector[Symbol.asyncDispose]();
expect(store.hasChanges).toBe(false);
const persisted = JSON.parse((await readFile(fileName)).toString());
expect(persisted).toEqual([{ id: '1', value: 'bravo' }]);
});
});
//# sourceMappingURL=define-filesystem-store.spec.js.map