Comparing version 0.4.4 to 0.5.0
@@ -0,1 +1,2 @@ | ||
export * from './fs.js'; | ||
export * from './list.js'; | ||
@@ -2,0 +3,0 @@ export * from './misc.js'; |
@@ -0,1 +1,2 @@ | ||
export * from './fs.js'; | ||
export * from './list.js'; | ||
@@ -2,0 +3,0 @@ export * from './misc.js'; |
@@ -1,3 +0,1 @@ | ||
/// <reference types="node" resolution-mode="require"/> | ||
import type * as FS from 'fs'; | ||
import { UnionToTuple } from './types.js'; | ||
@@ -17,72 +15,2 @@ export declare function filterObject<O extends object, R extends object>(object: O, predicate: (key: keyof O, value: O[keyof O]) => boolean): R; | ||
export declare function isJSON(str: string): boolean; | ||
export declare abstract class FileMap<V> implements Map<string, V> { | ||
protected readonly path: string; | ||
protected fs: typeof FS; | ||
get [Symbol.toStringTag](): string; | ||
constructor(path: string, fs: typeof FS); | ||
protected abstract readonly _map: Map<string, V>; | ||
abstract clear(): void; | ||
abstract delete(key: string): boolean; | ||
abstract get(key: string): V; | ||
abstract has(key: string): boolean; | ||
abstract set(key: string, value: V): this; | ||
get size(): number; | ||
get [Symbol.iterator](): () => IterableIterator<[string, V]>; | ||
get keys(): typeof this._map.keys; | ||
get values(): typeof this._map.values; | ||
get entries(): typeof this._map.entries; | ||
get forEach(): typeof this._map.forEach; | ||
} | ||
export type JSONObject<Key extends string | number | symbol = string> = { | ||
[K in Key]: JSONValue; | ||
}; | ||
export type JSONValue<Key extends string | number | symbol = string> = string | number | boolean | JSONObject<Key> | Array<JSONValue>; | ||
export interface JSONFileMapOptions { | ||
/** | ||
* Should an invalid JSON file be overwritten | ||
*/ | ||
overwrite_invalid_json: boolean; | ||
/** | ||
* FS module | ||
*/ | ||
fs: typeof FS; | ||
} | ||
/** | ||
* A Map overlaying a JSON file | ||
*/ | ||
export declare class JSONFileMap<T extends JSONValue = JSONValue> extends FileMap<T> { | ||
readonly options: JSONFileMapOptions; | ||
get [Symbol.toStringTag](): 'JSONFileMap'; | ||
constructor(path: string, options: JSONFileMapOptions); | ||
get _map(): Map<string, T>; | ||
_write(map: Map<string, T>): void; | ||
clear(): void; | ||
delete(key: string): boolean; | ||
get<U extends T>(key: string): U; | ||
has(key: string): boolean; | ||
set(key: string, value: T): this; | ||
} | ||
export interface FolderMapOptions { | ||
/** | ||
* Suffix to append to keys to resolve file names | ||
*/ | ||
suffix: string; | ||
fs: typeof FS; | ||
} | ||
/** | ||
* A Map overlaying a folder | ||
*/ | ||
export declare class FolderMap extends FileMap<string> { | ||
readonly options: Partial<FolderMapOptions>; | ||
get [Symbol.toStringTag](): 'FolderMap'; | ||
constructor(path: string, options: Partial<FolderMapOptions>); | ||
protected get _names(): string[]; | ||
protected _join(path: string): string; | ||
protected get _map(): Map<string, string>; | ||
clear(): void; | ||
delete(key: string): boolean; | ||
get(key: string): string; | ||
has(key: string): boolean; | ||
set(key: string, value: string): this; | ||
} | ||
export declare function resolveConstructors(object: object): string[]; |
@@ -35,148 +35,2 @@ export function filterObject(object, predicate) { | ||
} | ||
export class FileMap { | ||
path; | ||
fs; | ||
get [Symbol.toStringTag]() { | ||
return 'FileMap'; | ||
} | ||
constructor(path, fs) { | ||
this.path = path; | ||
this.fs = fs; | ||
if (!path) { | ||
throw new ReferenceError('No path specified'); | ||
} | ||
if (!fs) { | ||
throw new ReferenceError('No filesystem API'); | ||
} | ||
} | ||
get size() { | ||
return this._map.size; | ||
} | ||
get [Symbol.iterator]() { | ||
return this._map[Symbol.iterator].bind(this._map); | ||
} | ||
get keys() { | ||
return this._map.keys.bind(this._map); | ||
} | ||
get values() { | ||
return this._map.values.bind(this._map); | ||
} | ||
get entries() { | ||
return this._map.entries.bind(this._map); | ||
} | ||
get forEach() { | ||
return this._map.forEach.bind(this._map); | ||
} | ||
} | ||
/** | ||
* A Map overlaying a JSON file | ||
*/ | ||
export class JSONFileMap extends FileMap { | ||
options; | ||
get [Symbol.toStringTag]() { | ||
return 'JSONFileMap'; | ||
} | ||
constructor(path, options) { | ||
super(path, options.fs); | ||
this.options = options; | ||
if (!this.fs.existsSync(path)) { | ||
this.fs.writeFileSync(path, '{}'); | ||
} | ||
} | ||
get _map() { | ||
const content = this.fs.readFileSync(this.path, 'utf8'); | ||
if (!isJSON(content)) { | ||
if (!this.options.overwrite_invalid_json) { | ||
throw new SyntaxError('Invalid JSON file: ' + this.path); | ||
} | ||
console.warn('Invalid JSON file (overwriting): ' + this.path); | ||
this.clear(); | ||
return new Map(); | ||
} | ||
return new Map(Object.entries(JSON.parse(content))); | ||
} | ||
_write(map) { | ||
if (!this.fs.existsSync(this.path)) { | ||
this.fs.writeFileSync(this.path, '{}'); | ||
} | ||
const content = JSON.stringify(Object.fromEntries(map)); | ||
this.fs.writeFileSync(this.path, content); | ||
} | ||
clear() { | ||
this.fs.writeFileSync(this.path, '{}'); | ||
} | ||
delete(key) { | ||
const map = this._map; | ||
const rt = map.delete(key); | ||
this._write(map); | ||
return rt; | ||
} | ||
get(key) { | ||
return this._map.get(key); | ||
} | ||
has(key) { | ||
return this._map.has(key); | ||
} | ||
set(key, value) { | ||
const map = this._map; | ||
map.set(key, value); | ||
this._write(map); | ||
return this; | ||
} | ||
} | ||
/** | ||
* A Map overlaying a folder | ||
*/ | ||
export class FolderMap extends FileMap { | ||
options; | ||
get [Symbol.toStringTag]() { | ||
return 'FolderMap'; | ||
} | ||
constructor(path, options) { | ||
super(path, options.fs); | ||
this.options = options; | ||
} | ||
get _names() { | ||
return this.fs | ||
.readdirSync(this.path) | ||
.filter(p => p.endsWith(this.options.suffix || '')) | ||
.map(p => p.slice(0, -this.options.suffix.length)); | ||
} | ||
_join(path) { | ||
return `${this.path}/${path}${this.options.suffix}`; | ||
} | ||
get _map() { | ||
const entries = []; | ||
for (const name of this._names) { | ||
const content = this.fs.readFileSync(this._join(name), 'utf8'); | ||
entries.push([name, content]); | ||
} | ||
return new Map(entries); | ||
} | ||
clear() { | ||
for (const name of this._names) { | ||
this.fs.unlinkSync(this._join(name)); | ||
} | ||
} | ||
delete(key) { | ||
if (!this.has(key)) { | ||
return false; | ||
} | ||
this.fs.unlinkSync(this._join(key)); | ||
return true; | ||
} | ||
get(key) { | ||
if (!this.has(key)) { | ||
throw new ReferenceError('Key not found'); | ||
} | ||
return this.fs.readFileSync(this._join(key), 'utf8'); | ||
} | ||
has(key) { | ||
return this._names.includes(key); | ||
} | ||
set(key, value) { | ||
this.fs.writeFileSync(this._join(key), value); | ||
return this; | ||
} | ||
} | ||
export function resolveConstructors(object) { | ||
@@ -183,0 +37,0 @@ const constructors = []; |
{ | ||
"name": "utilium", | ||
"version": "0.4.4", | ||
"version": "0.5.0", | ||
"description": "Typescript utilies", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -0,1 +1,2 @@ | ||
export * from './fs.js'; | ||
export * from './list.js'; | ||
@@ -2,0 +3,0 @@ export * from './misc.js'; |
@@ -1,2 +0,1 @@ | ||
import type * as FS from 'fs'; | ||
import { UnionToTuple } from './types.js'; | ||
@@ -50,215 +49,2 @@ | ||
export abstract class FileMap<V> implements Map<string, V> { | ||
public get [Symbol.toStringTag](): string { | ||
return 'FileMap'; | ||
} | ||
public constructor( | ||
protected readonly path: string, | ||
protected fs: typeof FS | ||
) { | ||
if (!path) { | ||
throw new ReferenceError('No path specified'); | ||
} | ||
if (!fs) { | ||
throw new ReferenceError('No filesystem API'); | ||
} | ||
} | ||
protected abstract readonly _map: Map<string, V>; | ||
public abstract clear(): void; | ||
public abstract delete(key: string): boolean; | ||
public abstract get(key: string): V; | ||
public abstract has(key: string): boolean; | ||
public abstract set(key: string, value: V): this; | ||
public get size() { | ||
return this._map.size; | ||
} | ||
public get [Symbol.iterator]() { | ||
return this._map[Symbol.iterator].bind(this._map); | ||
} | ||
public get keys(): typeof this._map.keys { | ||
return this._map.keys.bind(this._map); | ||
} | ||
public get values(): typeof this._map.values { | ||
return this._map.values.bind(this._map); | ||
} | ||
public get entries(): typeof this._map.entries { | ||
return this._map.entries.bind(this._map); | ||
} | ||
public get forEach(): typeof this._map.forEach { | ||
return this._map.forEach.bind(this._map); | ||
} | ||
} | ||
export type JSONObject<Key extends string | number | symbol = string> = { [K in Key]: JSONValue }; | ||
export type JSONValue<Key extends string | number | symbol = string> = string | number | boolean | JSONObject<Key> | Array<JSONValue>; | ||
export interface JSONFileMapOptions { | ||
/** | ||
* Should an invalid JSON file be overwritten | ||
*/ | ||
overwrite_invalid_json: boolean; | ||
/** | ||
* FS module | ||
*/ | ||
fs: typeof FS; | ||
} | ||
/** | ||
* A Map overlaying a JSON file | ||
*/ | ||
export class JSONFileMap<T extends JSONValue = JSONValue> extends FileMap<T> { | ||
public get [Symbol.toStringTag](): 'JSONFileMap' { | ||
return 'JSONFileMap'; | ||
} | ||
public constructor( | ||
path: string, | ||
public readonly options: JSONFileMapOptions | ||
) { | ||
super(path, options.fs); | ||
if (!this.fs.existsSync(path)) { | ||
this.fs.writeFileSync(path, '{}'); | ||
} | ||
} | ||
public get _map(): Map<string, T> { | ||
const content = this.fs.readFileSync(this.path, 'utf8'); | ||
if (!isJSON(content)) { | ||
if (!this.options.overwrite_invalid_json) { | ||
throw new SyntaxError('Invalid JSON file: ' + this.path); | ||
} | ||
console.warn('Invalid JSON file (overwriting): ' + this.path); | ||
this.clear(); | ||
return new Map(); | ||
} | ||
return new Map(Object.entries(JSON.parse(content))); | ||
} | ||
public _write(map: Map<string, T>) { | ||
if (!this.fs.existsSync(this.path)) { | ||
this.fs.writeFileSync(this.path, '{}'); | ||
} | ||
const content = JSON.stringify(Object.fromEntries(map)); | ||
this.fs.writeFileSync(this.path, content); | ||
} | ||
public clear() { | ||
this.fs.writeFileSync(this.path, '{}'); | ||
} | ||
public delete(key: string): boolean { | ||
const map = this._map; | ||
const rt = map.delete(key); | ||
this._write(map); | ||
return rt; | ||
} | ||
public get<U extends T>(key: string): U { | ||
return this._map.get(key) as U; | ||
} | ||
public has(key: string): boolean { | ||
return this._map.has(key); | ||
} | ||
public set(key: string, value: T): this { | ||
const map = this._map; | ||
map.set(key, value); | ||
this._write(map); | ||
return this; | ||
} | ||
} | ||
export interface FolderMapOptions { | ||
/** | ||
* Suffix to append to keys to resolve file names | ||
*/ | ||
suffix: string; | ||
fs: typeof FS; | ||
} | ||
/** | ||
* A Map overlaying a folder | ||
*/ | ||
export class FolderMap extends FileMap<string> { | ||
public get [Symbol.toStringTag](): 'FolderMap' { | ||
return 'FolderMap'; | ||
} | ||
public constructor( | ||
path: string, | ||
public readonly options: Partial<FolderMapOptions> | ||
) { | ||
super(path, options.fs!); | ||
} | ||
protected get _names(): string[] { | ||
return this.fs | ||
.readdirSync(this.path) | ||
.filter(p => p.endsWith(this.options.suffix || '')) | ||
.map(p => p.slice(0, -this.options.suffix!.length)); | ||
} | ||
protected _join(path: string): string { | ||
return `${this.path}/${path}${this.options.suffix}`; | ||
} | ||
protected get _map(): Map<string, string> { | ||
const entries: [string, string][] = []; | ||
for (const name of this._names) { | ||
const content = this.fs.readFileSync(this._join(name), 'utf8'); | ||
entries.push([name, content]); | ||
} | ||
return new Map(entries); | ||
} | ||
public clear(): void { | ||
for (const name of this._names) { | ||
this.fs.unlinkSync(this._join(name)); | ||
} | ||
} | ||
public delete(key: string): boolean { | ||
if (!this.has(key)) { | ||
return false; | ||
} | ||
this.fs.unlinkSync(this._join(key)); | ||
return true; | ||
} | ||
public get(key: string): string { | ||
if (!this.has(key)) { | ||
throw new ReferenceError('Key not found'); | ||
} | ||
return this.fs.readFileSync(this._join(key), 'utf8'); | ||
} | ||
public has(key: string): boolean { | ||
return this._names.includes(key); | ||
} | ||
public set(key: string, value: string): this { | ||
this.fs.writeFileSync(this._join(key), value); | ||
return this; | ||
} | ||
} | ||
export function resolveConstructors(object: object): string[] { | ||
@@ -265,0 +51,0 @@ const constructors = []; |
68422
38
2005