diff --git a/src/index.ts b/src/index.ts index a05c89f..2b7af42 100644 --- a/src/index.ts +++ b/src/index.ts @@ -229,10 +229,10 @@ export default class Enmap { * * const someSubValue = enmap.get("anObjectKey", "someprop.someOtherSubProp"); */ - get(key: string): V | null; - get

>(key: string, path: P): PathValue | null; - get

>(key: string, path: P | undefined): V | PathValue | null; - get

>(key: string, path?: P): V | PathValue | null { + get(key: string): V | undefined; + get

>(key: string, path: P): PathValue | undefined; + get

>(key: string, path: P | undefined): V | PathValue | undefined; + get

>(key: string, path?: P): V | PathValue | undefined { this.#keycheck(key); if (!isNil(this.#autoEnsure) && !this.has(key)) { @@ -242,8 +242,8 @@ export default class Enmap { const data = this.#db .prepare(`SELECT value FROM ${this.#name} WHERE key = ?`) .get(key) as { value: string } | undefined; - const parsed = data ? this.#parse(data.value, key) : null; - if (isNil(parsed)) return null; + const parsed = data ? this.#parse(data.value, key) : undefined; + if (isNil(parsed)) return undefined; if (path) { this.#check(key, ['Object']); @@ -254,19 +254,35 @@ export default class Enmap { /** * Returns whether or not the key exists in the Enmap. - * @param key Required. The key of the element to add to The Enmap or array. + * @param {string} key Required. The key of the element to add to The Enmap or array. + * @param {Path} path Optional. The name of the property to check inside the object or array. + * Should be a path with dot notation, such as "prop1.subprop2.subprop3" * @example * if(enmap.has("myKey")) { * // key is there * } + * + * if(!enmap.has("myOtherKey", "oneProp.otherProp.SubProp")) return false; * @returns {boolean} */ - has(key: string): boolean { + has(key: string, path?: Path): boolean { this.#keycheck(key); + + // Check if the key exists const data = this.#db .prepare(`SELECT count(*) FROM ${this.#name} WHERE key = ?`) .get(key) as { 'count(*)': number }; - return data['count(*)'] > 0; + + if (data['count(*)'] === 0) return false; + + // If path is provided, check if the path exists within the value + if (path) { + this.#check(key, ['Object']); + const value = this.get(key); + return _get(value, path) !== undefined; + } + + return true; } /** @@ -508,7 +524,7 @@ export default class Enmap { operation: MathOps, operand: number, path?: Path, - ): number | null { + ): number | undefined { this.#keycheck(key); this.#check(key, ['Number'], path); const data = this.get(key, path); @@ -580,17 +596,17 @@ export default class Enmap { * console.log(settings) // enmap's value for "1234567890" if it exists, otherwise the defaultSettings value. * @return {*} The value from the database for the key, or the default value provided for a new key. */ - ensure(key: string, defaultValue: any): V | null; + ensure(key: string, defaultValue: any): V | undefined; ensure

>( key: string, defaultValue: any, path: P, - ): PathValue | null; + ): PathValue | undefined; ensure

>( key: string, defaultValue: any, path?: P, - ): V | PathValue | null { + ): V | PathValue | undefined { this.#keycheck(key); if (!isNil(this.#autoEnsure)) { @@ -911,7 +927,7 @@ export default class Enmap { find( pathOrFn: ((val: V, key: string) => boolean) | string, value?: any, - ): V | null { + ): V | undefined { const stmt = this.#db.prepare(`SELECT key, value FROM ${this.#name}`); for (const row of stmt.iterate() as IterableIterator<{ key: string; @@ -925,7 +941,7 @@ export default class Enmap { return parsed; } } - return null; + return undefined; } /** @@ -943,7 +959,7 @@ export default class Enmap { findIndex( pathOrFn: ((val: V, key: string) => boolean) | string, value?: any, - ): string | null { + ): string | undefined { const stmt = this.#db.prepare(`SELECT key, value FROM ${this.#name}`); for (const row of stmt.iterate() as IterableIterator<{ key: string; @@ -957,7 +973,7 @@ export default class Enmap { return row.key; } } - return null; + return undefined; } /** @@ -1207,7 +1223,7 @@ export default class Enmap { } } - #math(base: number, op: MathOps, opand: number): number | null { + #math(base: number, op: MathOps, opand: number): number | undefined { if (base == undefined || op == undefined || opand == undefined) throw new Err( 'Math Operation requires base and operation', @@ -1242,6 +1258,6 @@ export default class Enmap { case 'random': return Math.floor(Math.random() * Math.floor(opand)); } - return null; + return undefined; } } diff --git a/test/index.spec.js b/test/index.spec.js index 7cf031d..94971e8 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -107,10 +107,10 @@ describe('Enmap', () => { expect(enmap.get('setNumber')).toBe(1); }); - test('should set a value w/ null', () => { - enmap.set('setNull', null); + test('should set a value w/ undefined', () => { + enmap.set('setNull', undefined); - expect(enmap.get('setNull')).toBe(null); + expect(enmap.get('setNull')).toBe(undefined); }); test('should set a value w/ boolean', () => { @@ -380,7 +380,7 @@ describe('Enmap', () => { enmap.set('huh', 1); enmap.math('huh', 'huh', 1); - expect(enmap.get('huh')).toBe(null); + expect(enmap.get('huh')).toBe(undefined); }); test('should math value w/ path', () => { @@ -484,9 +484,25 @@ describe('Enmap', () => { expect(enmap.has('has')).toBe(true); }); + test('should return true if key and path exists', () =>{ + enmap.set('hasPath', 'value', 'nested'); + + expect(enmap.has('hasPath', 'nested')).toBe(true); + }); + test("should return false if key doesn't exist", () => { expect(enmap.has('unknown')).toBe(false); }); + + test("Should return false if the subkey doesn't exists", () => { + enmap.set('hasPath2', undefined, 'nested'); + expect(enmap.has('hasPath2', 'nested')).toBe(false); + }); + + test("should return false if key exists but path doesn't", () => { + enmap.set('hasPath3', 'value', 'nested'); + expect(enmap.has('hasPath3', 'other')).toBe(false); + }); }); describe('includes', () => { @@ -512,7 +528,7 @@ describe('Enmap', () => { enmap.set('delete', 'value'); enmap.delete('delete'); - expect(enmap.get('delete')).toBe(null); + expect(enmap.get('delete')).toBe(undefined); }); test('should delete a path', () => { @@ -530,7 +546,7 @@ describe('Enmap', () => { enmap.set('clear', 'value'); enmap.clear(); - expect(enmap.get('clear')).toBe(null); + expect(enmap.get('clear')).toBe(undefined); }); }); @@ -827,11 +843,11 @@ describe('Enmap', () => { expect(enmap.find('sub', 'value')).toEqual({ sub: 'value' }); }); - test('should return null if not found', () => { + test('should return undefined if not found', () => { enmap.set('find', 'value'); enmap.set('find2', 'value2'); - expect(enmap.find((val) => val === 'value3')).toBe(null); + expect(enmap.find((val) => val === 'value3')).toBe(undefined); }); }); @@ -852,11 +868,11 @@ describe('Enmap', () => { expect(enmap.findIndex('sub', 'value')).toBe('find'); }); - test('should return null if not found', () => { + test('should return undefined if not found', () => { enmap.set('find', 'value'); enmap.set('find2', 'value2'); - expect(enmap.findIndex((val) => val === 'value3')).toBe(null); + expect(enmap.findIndex((val) => val === 'value3')).toBe(undefined); }); });