feature: emit events
This commit is contained in:
parent
0d0f399cc2
commit
3214d17b80
7 changed files with 460 additions and 18 deletions
116
fsdb.ts
116
fsdb.ts
|
@ -34,6 +34,7 @@ export interface FSDB_INDEXER<T> {
|
|||
export class FSDB_COLLECTION<T extends Record<string, any>> {
|
||||
private config: FSDB_COLLECTION_CONFIG;
|
||||
public INDEX: Record<string, FSDB_INDEXER<any>>;
|
||||
private event_listeners: Record<string, []>;
|
||||
|
||||
constructor(input_config: FSDB_COLLECTION_CONFIG_INPUT) {
|
||||
this.config = {
|
||||
|
@ -45,6 +46,8 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
...(input_config ?? {})
|
||||
};
|
||||
|
||||
this.event_listeners = {};
|
||||
|
||||
this.INDEX = this.config.indexers ?? {};
|
||||
for (const indexer of Object.values(this.INDEX)) {
|
||||
indexer.set_fsdb_root(this.config.root);
|
||||
|
@ -84,7 +87,7 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
}
|
||||
|
||||
const collection_info_file_path: string = path.resolve(path.join(this.config.root, '.fsdb.collection.json'));
|
||||
const collection_info_json: string = JSON.stringify(this.config, null, 4);
|
||||
const collection_info_json: string = JSON.stringify(this.config, null, '\t');
|
||||
Deno.mkdirSync(path.dirname(collection_info_file_path), {
|
||||
recursive: true
|
||||
});
|
||||
|
@ -114,26 +117,43 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
|
||||
private async write_item(item: T, override_path?: string): Promise<void> {
|
||||
const item_path: string = override_path ?? await this.ensure_item_path(item, this.config.id_field);
|
||||
Deno.writeTextFileSync(item_path, JSON.stringify(item, null, 1));
|
||||
Deno.writeTextFileSync(item_path, JSON.stringify(item, null, '\t'));
|
||||
|
||||
this.emit('write', {
|
||||
item,
|
||||
item_path
|
||||
});
|
||||
|
||||
if (this.config.indexers) {
|
||||
for (const indexer of Object.values(this.config.indexers)) {
|
||||
await (indexer as FSDB_INDEXER<T>).index(item, item_path);
|
||||
this.emit('index', {
|
||||
item,
|
||||
item_path,
|
||||
indexer
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get an item from the collection given its id. */
|
||||
async get(id: string): Promise<T | null> {
|
||||
const id_path: string = this.get_organized_id_path(id);
|
||||
const item_exists: boolean = await fs.exists(id_path);
|
||||
const item_path: string = this.get_organized_id_path(id);
|
||||
const item_exists: boolean = await fs.exists(item_path);
|
||||
|
||||
if (!item_exists) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content: string = await Deno.readTextFile(id_path);
|
||||
return JSON.parse(content);
|
||||
const content: string = await Deno.readTextFile(item_path);
|
||||
const item: T = JSON.parse(content);
|
||||
|
||||
this.emit('get', {
|
||||
item,
|
||||
item_path
|
||||
});
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/** Create an item in the collection. */
|
||||
|
@ -149,15 +169,21 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
|
||||
await this.write_item(item);
|
||||
|
||||
this.emit('create', {
|
||||
item,
|
||||
item_path
|
||||
});
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/** Update the given item in the collection, requiring the id to be stable. */
|
||||
async update(item: T): Promise<T> {
|
||||
const item_path: string = this.get_organized_item_path(item);
|
||||
const item_exists: boolean = await fs.exists(item_path);
|
||||
const id: string = item[this.config.id_field];
|
||||
const previous: T | null = await this.get(id);
|
||||
|
||||
if (!item_exists) {
|
||||
if (!previous) {
|
||||
throw new Error('item does not exist', {
|
||||
cause: 'item_does_not_exist'
|
||||
});
|
||||
|
@ -165,6 +191,12 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
|
||||
await this.write_item(item, item_path);
|
||||
|
||||
this.emit('update', {
|
||||
item,
|
||||
previous,
|
||||
item_path
|
||||
});
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -202,6 +234,11 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
await Deno.remove(dir);
|
||||
dir = path.dirname(dir);
|
||||
} while (dir.length);
|
||||
|
||||
this.emit('delete', {
|
||||
item
|
||||
});
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -302,6 +339,11 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
if (Deno.env.get('FSDB_PERF')) performance.mark('fsdb_all_end');
|
||||
if (Deno.env.get('FSDB_PERF')) console.dir(performance.measure('fsdb all items time', 'fsdb_all_begin', 'fsdb_all_end'));
|
||||
|
||||
this.emit('all', {
|
||||
options,
|
||||
results
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -350,6 +392,64 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
if (Deno.env.get('FSDB_PERF')) performance.mark('fsdb_find_end');
|
||||
if (Deno.env.get('FSDB_PERF')) console.dir(performance.measure('fsdb find time', 'fsdb_find_begin', 'fsdb_find_end'));
|
||||
|
||||
this.emit('find', {
|
||||
criteria,
|
||||
options,
|
||||
results
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public on(event: string, handler: (event_data: any) => void) {
|
||||
const listeners: ((event: any) => void)[] = this.event_listeners[event] = this.event_listeners[event] ?? [];
|
||||
if (!listeners.includes(handler)) {
|
||||
listeners.push(handler);
|
||||
}
|
||||
|
||||
if (Deno.env.get('FSDB_LOG_EVENTS')) {
|
||||
console.dir({
|
||||
on: {
|
||||
event,
|
||||
handler
|
||||
},
|
||||
listeners
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public off(event: string, handler: (event_data: any) => void) {
|
||||
const listeners: ((event: any) => void)[] = this.event_listeners[event] = this.event_listeners[event] ?? [];
|
||||
if (listeners.includes(handler)) {
|
||||
listeners.splice(listeners.indexOf(handler), 1);
|
||||
}
|
||||
|
||||
if (Deno.env.get('FSDB_LOG_EVENTS')) {
|
||||
console.dir({
|
||||
off: {
|
||||
event: event,
|
||||
handler
|
||||
},
|
||||
listeners
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private emit(event_name: string, event_data: any) {
|
||||
const listeners: ((event: any) => void)[] = this.event_listeners[event_name] = this.event_listeners[event_name] ?? [];
|
||||
|
||||
if (Deno.env.get('FSDB_LOG_EVENTS')) {
|
||||
console.dir({
|
||||
emitting: {
|
||||
event_name,
|
||||
event_data,
|
||||
listeners
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const listener of listeners) {
|
||||
listener(event_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue