Comparing version 11.0.2 to 12.0.0
/// <reference types="node" resolution-mode="require"/> | ||
import { EventEmitter } from 'node:events'; | ||
import { type OnDidChangeCallback, type Options, type Unsubscribe, type OnDidAnyChangeCallback } from './types.js'; | ||
@@ -7,3 +6,3 @@ export default class Conf<T extends Record<string, any> = Record<string, unknown>> implements Iterable<[keyof T, T[keyof T]]> { | ||
readonly path: string; | ||
readonly events: EventEmitter; | ||
readonly events: EventTarget; | ||
constructor(partialOptions?: Readonly<Partial<Options<T>>>); | ||
@@ -10,0 +9,0 @@ /** |
@@ -1,17 +0,4 @@ | ||
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
if (kind === "m") throw new TypeError("Private method is not writable"); | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); | ||
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; | ||
}; | ||
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { | ||
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); | ||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); | ||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); | ||
}; | ||
var _Conf_validator, _Conf_encryptionKey, _Conf_options, _Conf_defaultValues; | ||
/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-redundant-type-constituents */ | ||
/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-unsafe-return */ | ||
import { isDeepStrictEqual } from 'node:util'; | ||
import process from 'node:process'; | ||
import { Buffer } from 'node:buffer'; | ||
import fs from 'node:fs'; | ||
@@ -21,3 +8,2 @@ import path from 'node:path'; | ||
import assert from 'node:assert'; | ||
import { EventEmitter } from 'node:events'; | ||
import { getProperty, hasProperty, setProperty, deleteProperty } from 'dot-prop'; | ||
@@ -30,2 +16,3 @@ import envPaths from 'env-paths'; | ||
import semver from 'semver'; | ||
import { concatUint8Arrays, stringToUint8Array, uint8ArrayToString, } from 'uint8array-extras'; | ||
// FIXME: https://github.com/ajv-validator/ajv/issues/2047 | ||
@@ -51,31 +38,9 @@ const Ajv = AjvModule.default; | ||
export default class Conf { | ||
path; | ||
events; | ||
#validator; | ||
#encryptionKey; | ||
#options; | ||
#defaultValues = {}; | ||
constructor(partialOptions = {}) { | ||
Object.defineProperty(this, "path", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "events", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
_Conf_validator.set(this, void 0); | ||
_Conf_encryptionKey.set(this, void 0); | ||
_Conf_options.set(this, void 0); | ||
_Conf_defaultValues.set(this, {}); | ||
Object.defineProperty(this, "_deserialize", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: value => JSON.parse(value) | ||
}); | ||
Object.defineProperty(this, "_serialize", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: value => JSON.stringify(value, undefined, '\t') | ||
}); | ||
const options = { | ||
@@ -96,3 +61,3 @@ configName: 'config', | ||
} | ||
__classPrivateFieldSet(this, _Conf_options, options, "f"); | ||
this.#options = options; | ||
if (options.schema) { | ||
@@ -111,6 +76,6 @@ if (typeof options.schema !== 'object') { | ||
}; | ||
__classPrivateFieldSet(this, _Conf_validator, ajv.compile(schema), "f"); | ||
this.#validator = ajv.compile(schema); | ||
for (const [key, value] of Object.entries(options.schema)) { // TODO: Remove the `as any`. | ||
if (value?.default) { | ||
__classPrivateFieldGet(this, _Conf_defaultValues, "f")[key] = value.default; // eslint-disable-line @typescript-eslint/no-unsafe-assignment | ||
this.#defaultValues[key] = value.default; // eslint-disable-line @typescript-eslint/no-unsafe-assignment | ||
} | ||
@@ -120,6 +85,6 @@ } | ||
if (options.defaults) { | ||
__classPrivateFieldSet(this, _Conf_defaultValues, { | ||
...__classPrivateFieldGet(this, _Conf_defaultValues, "f"), | ||
this.#defaultValues = { | ||
...this.#defaultValues, | ||
...options.defaults, | ||
}, "f"); | ||
}; | ||
} | ||
@@ -132,4 +97,4 @@ if (options.serialize) { | ||
} | ||
this.events = new EventEmitter(); | ||
__classPrivateFieldSet(this, _Conf_encryptionKey, options.encryptionKey, "f"); | ||
this.events = new EventTarget(); | ||
this.#encryptionKey = options.encryptionKey; | ||
const fileExtension = options.fileExtension ? `.${options.fileExtension}` : ''; | ||
@@ -157,3 +122,3 @@ this.path = path.resolve(options.cwd, `${options.configName ?? 'config'}${fileExtension}`); | ||
get(key, defaultValue) { | ||
if (__classPrivateFieldGet(this, _Conf_options, "f").accessPropertiesByDotNotation) { | ||
if (this.#options.accessPropertiesByDotNotation) { | ||
return this._get(key, defaultValue); | ||
@@ -177,3 +142,3 @@ } | ||
checkValueType(key, value); | ||
if (__classPrivateFieldGet(this, _Conf_options, "f").accessPropertiesByDotNotation) { | ||
if (this.#options.accessPropertiesByDotNotation) { | ||
setProperty(store, key, value); | ||
@@ -202,3 +167,3 @@ } | ||
has(key) { | ||
if (__classPrivateFieldGet(this, _Conf_options, "f").accessPropertiesByDotNotation) { | ||
if (this.#options.accessPropertiesByDotNotation) { | ||
return hasProperty(this.store, key); | ||
@@ -217,4 +182,4 @@ } | ||
for (const key of keys) { | ||
if (isExist(__classPrivateFieldGet(this, _Conf_defaultValues, "f")[key])) { | ||
this.set(key, __classPrivateFieldGet(this, _Conf_defaultValues, "f")[key]); | ||
if (isExist(this.#defaultValues[key])) { | ||
this.set(key, this.#defaultValues[key]); | ||
} | ||
@@ -225,3 +190,3 @@ } | ||
const { store } = this; | ||
if (__classPrivateFieldGet(this, _Conf_options, "f").accessPropertiesByDotNotation) { | ||
if (this.#options.accessPropertiesByDotNotation) { | ||
deleteProperty(store, key); | ||
@@ -242,3 +207,3 @@ } | ||
this.store = createPlainObject(); | ||
for (const key of Object.keys(__classPrivateFieldGet(this, _Conf_defaultValues, "f"))) { | ||
for (const key of Object.keys(this.#defaultValues)) { | ||
this.reset(key); | ||
@@ -280,3 +245,3 @@ } | ||
try { | ||
const data = fs.readFileSync(this.path, __classPrivateFieldGet(this, _Conf_encryptionKey, "f") ? null : 'utf8'); | ||
const data = fs.readFileSync(this.path, this.#encryptionKey ? null : 'utf8'); | ||
const dataString = this._encryptData(data); | ||
@@ -292,3 +257,3 @@ const deserializedData = this._deserialize(dataString); | ||
} | ||
if (__classPrivateFieldGet(this, _Conf_options, "f").clearInvalidConfig && error.name === 'SyntaxError') { | ||
if (this.#options.clearInvalidConfig && error.name === 'SyntaxError') { | ||
return createPlainObject(); | ||
@@ -303,5 +268,5 @@ } | ||
this._write(value); | ||
this.events.emit('change'); | ||
this.events.dispatchEvent(new Event('change')); | ||
} | ||
*[(_Conf_validator = new WeakMap(), _Conf_encryptionKey = new WeakMap(), _Conf_options = new WeakMap(), _Conf_defaultValues = new WeakMap(), Symbol.iterator)]() { | ||
*[Symbol.iterator]() { | ||
for (const [key, value] of Object.entries(this.store)) { | ||
@@ -312,4 +277,4 @@ yield [key, value]; | ||
_encryptData(data) { | ||
if (!__classPrivateFieldGet(this, _Conf_encryptionKey, "f")) { | ||
return data.toString(); | ||
if (!this.#encryptionKey) { | ||
return typeof data === 'string' ? data : uint8ArrayToString(data); | ||
} | ||
@@ -319,5 +284,7 @@ // Check if an initialization vector has been used to encrypt the data. | ||
const initializationVector = data.slice(0, 16); | ||
const password = crypto.pbkdf2Sync(__classPrivateFieldGet(this, _Conf_encryptionKey, "f"), initializationVector.toString(), 10000, 32, 'sha512'); | ||
const password = crypto.pbkdf2Sync(this.#encryptionKey, initializationVector.toString(), 10000, 32, 'sha512'); | ||
const decipher = crypto.createDecipheriv(encryptionAlgorithm, password, initializationVector); | ||
return Buffer.concat([decipher.update(Buffer.from(data.slice(17))), decipher.final()]).toString('utf8'); | ||
const slice = data.slice(17); | ||
const dataUpdate = typeof slice === 'string' ? stringToUint8Array(slice) : slice; | ||
return uint8ArrayToString(concatUint8Arrays([decipher.update(dataUpdate), decipher.final()])); | ||
} | ||
@@ -338,14 +305,18 @@ catch { } | ||
}; | ||
this.events.on('change', onChange); | ||
return () => this.events.removeListener('change', onChange); | ||
this.events.addEventListener('change', onChange); | ||
return () => { | ||
this.events.removeEventListener('change', onChange); | ||
}; | ||
} | ||
_deserialize = value => JSON.parse(value); | ||
_serialize = value => JSON.stringify(value, undefined, '\t'); | ||
_validate(data) { | ||
if (!__classPrivateFieldGet(this, _Conf_validator, "f")) { | ||
if (!this.#validator) { | ||
return; | ||
} | ||
const valid = __classPrivateFieldGet(this, _Conf_validator, "f").call(this, data); | ||
if (valid || !__classPrivateFieldGet(this, _Conf_validator, "f").errors) { | ||
const valid = this.#validator(data); | ||
if (valid || !this.#validator.errors) { | ||
return; | ||
} | ||
const errors = __classPrivateFieldGet(this, _Conf_validator, "f").errors | ||
const errors = this.#validator.errors | ||
.map(({ instancePath, message = '' }) => `\`${instancePath.slice(1)}\` ${message}`); | ||
@@ -360,7 +331,7 @@ throw new Error('Config schema violation: ' + errors.join('; ')); | ||
let data = this._serialize(value); | ||
if (__classPrivateFieldGet(this, _Conf_encryptionKey, "f")) { | ||
if (this.#encryptionKey) { | ||
const initializationVector = crypto.randomBytes(16); | ||
const password = crypto.pbkdf2Sync(__classPrivateFieldGet(this, _Conf_encryptionKey, "f"), initializationVector.toString(), 10000, 32, 'sha512'); | ||
const password = crypto.pbkdf2Sync(this.#encryptionKey, initializationVector.toString(), 10000, 32, 'sha512'); | ||
const cipher = crypto.createCipheriv(encryptionAlgorithm, password, initializationVector); | ||
data = Buffer.concat([initializationVector, Buffer.from(':'), cipher.update(Buffer.from(data)), cipher.final()]); | ||
data = concatUint8Arrays([initializationVector, stringToUint8Array(':'), cipher.update(stringToUint8Array(data)), cipher.final()]); | ||
} | ||
@@ -370,7 +341,7 @@ // Temporary workaround for Conf being packaged in a Ubuntu Snap app. | ||
if (process.env.SNAP) { | ||
fs.writeFileSync(this.path, data, { mode: __classPrivateFieldGet(this, _Conf_options, "f").configFileMode }); | ||
fs.writeFileSync(this.path, data, { mode: this.#options.configFileMode }); | ||
} | ||
else { | ||
try { | ||
atomicWriteFileSync(this.path, data, { mode: __classPrivateFieldGet(this, _Conf_options, "f").configFileMode }); | ||
atomicWriteFileSync(this.path, data, { mode: this.#options.configFileMode }); | ||
} | ||
@@ -382,3 +353,3 @@ catch (error) { | ||
if (error?.code === 'EXDEV') { | ||
fs.writeFileSync(this.path, data, { mode: __classPrivateFieldGet(this, _Conf_options, "f").configFileMode }); | ||
fs.writeFileSync(this.path, data, { mode: this.#options.configFileMode }); | ||
return; | ||
@@ -398,3 +369,3 @@ } | ||
// On Linux and Windows, writing to the config file emits a `rename` event, so we skip checking the event type. | ||
this.events.emit('change'); | ||
this.events.dispatchEvent(new Event('change')); | ||
}, { wait: 100 })); | ||
@@ -404,3 +375,3 @@ } | ||
fs.watchFile(this.path, { persistent: false }, debounceFn(() => { | ||
this.events.emit('change'); | ||
this.events.dispatchEvent(new Event('change')); | ||
}, { wait: 5000 })); | ||
@@ -449,3 +420,3 @@ } | ||
} | ||
if (__classPrivateFieldGet(this, _Conf_options, "f").accessPropertiesByDotNotation) { | ||
if (this.#options.accessPropertiesByDotNotation) { | ||
if (key.startsWith(`${INTERNAL_KEY}.`)) { | ||
@@ -452,0 +423,0 @@ return true; |
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
/// <reference types="node" resolution-mode="require"/> | ||
import { type Buffer } from 'node:buffer'; | ||
import { type EventEmitter } from 'node:events'; | ||
import { type JSONSchema as TypedJSONSchema } from 'json-schema-typed'; | ||
@@ -128,3 +124,3 @@ import type Conf from './index.js'; | ||
*/ | ||
encryptionKey?: string | Buffer | NodeJS.TypedArray | DataView; | ||
encryptionKey?: string | Uint8Array | NodeJS.TypedArray | DataView; | ||
/** | ||
@@ -245,2 +241,2 @@ Extension of the config file. | ||
export type OnDidAnyChangeCallback<T> = (newValue?: Readonly<T>, oldValue?: Readonly<T>) => void; | ||
export type Unsubscribe = () => EventEmitter; | ||
export type Unsubscribe = () => void; |
{ | ||
"name": "conf", | ||
"version": "11.0.2", | ||
"version": "12.0.0", | ||
"description": "Simple config handling for your app or module", | ||
@@ -19,4 +19,5 @@ "license": "MIT", | ||
"engines": { | ||
"node": ">=14.16" | ||
"node": ">=18" | ||
}, | ||
"sideEffects": false, | ||
"scripts": { | ||
@@ -52,25 +53,25 @@ "test": "xo && npm run build && ava", | ||
"ajv-formats": "^2.1.1", | ||
"atomically": "^2.0.0", | ||
"atomically": "^2.0.2", | ||
"debounce-fn": "^5.1.2", | ||
"dot-prop": "^7.2.0", | ||
"dot-prop": "^8.0.2", | ||
"env-paths": "^3.0.0", | ||
"json-schema-typed": "^8.0.1", | ||
"semver": "^7.3.8" | ||
"semver": "^7.5.4", | ||
"uint8array-extras": "^0.3.0" | ||
}, | ||
"devDependencies": { | ||
"@sindresorhus/tsconfig": "^3.0.1", | ||
"@types/node": "^18.11.18", | ||
"@types/semver": "^7.3.13", | ||
"ava": "^5.1.0", | ||
"del": "^7.0.0", | ||
"del-cli": "^5.0.0", | ||
"delay": "^5.0.0", | ||
"p-event": "^5.0.1", | ||
"tempy": "^3.0.0", | ||
"@sindresorhus/tsconfig": "^5.0.0", | ||
"@types/node": "^20.8.8", | ||
"@types/semver": "^7.5.4", | ||
"ava": "^5.3.1", | ||
"del": "^7.1.0", | ||
"del-cli": "^5.1.0", | ||
"delay": "^6.0.0", | ||
"p-event": "^6.0.0", | ||
"tempy": "^3.1.0", | ||
"ts-node": "^10.9.1", | ||
"tsd": "^0.28.1", | ||
"typescript": "^5.1.6", | ||
"xo": "^0.54.0" | ||
"tsd": "^0.29.0", | ||
"typescript": "^5.2.2", | ||
"xo": "^0.56.0" | ||
}, | ||
"sideEffects": false, | ||
"ava": { | ||
@@ -77,0 +78,0 @@ "files": [ |
@@ -103,3 +103,3 @@ # conf | ||
### migrations | ||
#### migrations | ||
@@ -142,3 +142,3 @@ Type: `object` | ||
### beforeEachMigration | ||
#### beforeEachMigration | ||
@@ -229,3 +229,3 @@ Type: `Function`\ | ||
Type: `string | Buffer | TypedArray | DataView`\ | ||
Type: `string | Uint8Array | TypedArray | DataView`\ | ||
Default: `undefined` | ||
@@ -232,0 +232,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45683
9
698
+ Addeduint8array-extras@^0.3.0
+ Addeddot-prop@8.0.2(transitive)
+ Addedtype-fest@3.13.1(transitive)
+ Addeduint8array-extras@0.3.0(transitive)
- Removeddot-prop@7.2.0(transitive)
- Removedtype-fest@2.19.0(transitive)
Updatedatomically@^2.0.2
Updateddot-prop@^8.0.2
Updatedsemver@^7.5.4