refactor: make all() take filter
and sort
options
refactor: return unload item entries from all()/find()
This commit is contained in:
parent
3214d17b80
commit
05178c924f
8 changed files with 308 additions and 206 deletions
133
fsdb.ts
133
fsdb.ts
|
@ -2,6 +2,9 @@ import * as fs from '@std/fs';
|
|||
import * as path from '@std/path';
|
||||
import by_lurid from './organizers/by_lurid.ts';
|
||||
import { Optional } from './utils/optional.ts';
|
||||
import { walk, WALK_ENTRY } from './utils/walk.ts';
|
||||
|
||||
export type { WALK_ENTRY };
|
||||
|
||||
export type FSDB_COLLECTION_CONFIG = {
|
||||
name: string;
|
||||
|
@ -12,22 +15,18 @@ export type FSDB_COLLECTION_CONFIG = {
|
|||
};
|
||||
export type FSDB_COLLECTION_CONFIG_INPUT = Optional<FSDB_COLLECTION_CONFIG, 'id_field' | 'organize' | 'root'>;
|
||||
|
||||
export type FSDB_SEARCH_OPTIONS = {
|
||||
limit: number;
|
||||
export type FSDB_SEARCH_OPTIONS<T> = {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
before?: string;
|
||||
after?: string;
|
||||
modified_before?: string;
|
||||
modified_after?: string;
|
||||
id_before?: string;
|
||||
id_after?: string;
|
||||
filter?: (entry: WALK_ENTRY<T>) => boolean;
|
||||
sort?: (a: WALK_ENTRY<T>, b: WALK_ENTRY<T>) => number;
|
||||
};
|
||||
|
||||
export interface FSDB_INDEXER<T> {
|
||||
set_fsdb_root(root: string): void;
|
||||
index(item: T, authoritative_path: string): Promise<string[]>;
|
||||
remove(item: T, authoritative_path: string): Promise<string[]>;
|
||||
lookup(value: string, options?: FSDB_SEARCH_OPTIONS): Promise<string[]>;
|
||||
lookup(value: string, options?: FSDB_SEARCH_OPTIONS<T>): Promise<string[]>;
|
||||
}
|
||||
|
||||
/** Represents a collection of like items within the database on disk. */
|
||||
|
@ -243,21 +242,16 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
}
|
||||
|
||||
/** Iterate through the items. */
|
||||
async all(input_options?: FSDB_SEARCH_OPTIONS): Promise<T[]> {
|
||||
async all({
|
||||
limit = 100,
|
||||
offset = 0,
|
||||
filter = undefined,
|
||||
sort = undefined
|
||||
}: FSDB_SEARCH_OPTIONS<T> = {}): Promise<WALK_ENTRY<T>[]> {
|
||||
if (Deno.env.get('FSDB_PERF')) performance.mark('fsdb_all_begin');
|
||||
|
||||
const options: FSDB_SEARCH_OPTIONS = {
|
||||
...{
|
||||
limit: 100,
|
||||
offset: 0
|
||||
},
|
||||
...(input_options ?? {})
|
||||
};
|
||||
const results: WALK_ENTRY<T>[] = [];
|
||||
|
||||
const results: T[] = [];
|
||||
|
||||
const limit = options?.limit ?? 100;
|
||||
const offset = options?.offset ?? 0;
|
||||
let counter = 0;
|
||||
|
||||
// TODO: better way to get a pattern to match files in this collection?
|
||||
|
@ -270,65 +264,33 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
}
|
||||
|
||||
for await (
|
||||
const entry of fs.walk(this.config.root, {
|
||||
includeDirs: false,
|
||||
includeSymlinks: false,
|
||||
skip: [/\.fsdb\.collection\.json$/],
|
||||
exts: ['json']
|
||||
const entry of walk(this.config.root, {
|
||||
filter: (entry: WALK_ENTRY<T>): boolean => {
|
||||
const extension = path.extname(entry.path);
|
||||
if (extension.toLowerCase() !== '.json') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.info.isDirectory || entry.info.isSymlink) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const filename = path.basename(entry.path);
|
||||
if (filename === '.fsdb.collection.json') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return filter ? filter(entry) : true;
|
||||
},
|
||||
sort
|
||||
})
|
||||
) {
|
||||
let item_stat = null;
|
||||
if (options.before) {
|
||||
item_stat = item_stat ?? await Deno.lstat(entry.path);
|
||||
const birthtime = (item_stat.birthtime ?? new Date(0)).toISOString();
|
||||
if (birthtime > options.before) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.after) {
|
||||
item_stat = item_stat ?? await Deno.lstat(entry.path);
|
||||
if ((item_stat.birthtime ?? new Date(0)).toISOString() < options.after) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.modified_before) {
|
||||
item_stat = item_stat ?? await Deno.lstat(entry.path);
|
||||
if ((item_stat.mtime ?? new Date(0)).toISOString() > options.modified_before) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.modified_after) {
|
||||
item_stat = item_stat ?? await Deno.lstat(entry.path);
|
||||
if ((item_stat.mtime ?? new Date(0)).toISOString() < options.modified_after) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let item_id = null;
|
||||
if (options.id_before) {
|
||||
item_id = item_id ?? entry.name.replace(/\.json$/, '');
|
||||
if (item_id >= options.id_before) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.id_after) {
|
||||
item_id = item_id ?? entry.name.replace(/\.json$/, '');
|
||||
if (item_id <= options.id_after) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (counter < offset) {
|
||||
++counter;
|
||||
continue;
|
||||
}
|
||||
|
||||
const content = await Deno.readTextFile(entry.path);
|
||||
results.push(JSON.parse(content));
|
||||
results.push(entry);
|
||||
++counter;
|
||||
|
||||
if (counter >= (offset + limit)) {
|
||||
|
@ -340,7 +302,12 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
if (Deno.env.get('FSDB_PERF')) console.dir(performance.measure('fsdb all items time', 'fsdb_all_begin', 'fsdb_all_end'));
|
||||
|
||||
this.emit('all', {
|
||||
options,
|
||||
options: {
|
||||
limit,
|
||||
offset,
|
||||
filter,
|
||||
sort
|
||||
},
|
||||
results
|
||||
});
|
||||
|
||||
|
@ -348,10 +315,10 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
}
|
||||
|
||||
/** Use indexes to search for matching items. */
|
||||
async find(criteria: Record<string, any>, input_options?: FSDB_SEARCH_OPTIONS): Promise<T[]> {
|
||||
async find(criteria: Record<string, any>, input_options?: FSDB_SEARCH_OPTIONS<T>): Promise<WALK_ENTRY<T>[]> {
|
||||
if (Deno.env.get('FSDB_PERF')) performance.mark('fsdb_find_begin');
|
||||
|
||||
const options: FSDB_SEARCH_OPTIONS = {
|
||||
const options: FSDB_SEARCH_OPTIONS<T> = {
|
||||
...{
|
||||
limit: 100,
|
||||
offset: 0
|
||||
|
@ -359,7 +326,7 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
...(input_options ?? {})
|
||||
};
|
||||
|
||||
const results: T[] = [];
|
||||
const results: WALK_ENTRY<T>[] = [];
|
||||
const item_paths: string[] = [];
|
||||
|
||||
for (const search_key of Object.keys(criteria)) {
|
||||
|
@ -380,8 +347,16 @@ export class FSDB_COLLECTION<T extends Record<string, any>> {
|
|||
continue;
|
||||
}
|
||||
|
||||
const content = await Deno.readTextFile(item_path);
|
||||
results.push(JSON.parse(content));
|
||||
const info: Deno.FileInfo = await Deno.lstat(item_path);
|
||||
results.push({
|
||||
path: item_path,
|
||||
info,
|
||||
depth: -1,
|
||||
load: function () {
|
||||
return JSON.parse(Deno.readTextFileSync(this.path)) as T;
|
||||
}
|
||||
});
|
||||
|
||||
++counter;
|
||||
|
||||
if (counter >= (offset + limit)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue