fix(appdata): Fix iteration over overwriteObject in AppData and update configuration for dependency and path handling

This commit is contained in:
2025-08-15 12:12:26 +00:00
parent 5e0edecf18
commit 62e61168a0
25 changed files with 5821 additions and 2835 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/npmextra',
version: '5.1.2',
version: '5.1.3',
description: 'A utility to enhance npm with additional configuration, tool management capabilities, and a key-value store for project setups.'
}

View File

@@ -26,7 +26,7 @@ export class AppData<T = any> {
* @returns
*/
public static async createAndInit<T = any>(
optionsArg: IAppDataOptions<T> = {}
optionsArg: IAppDataOptions<T> = {},
): Promise<AppData<T>> {
const appData = new AppData<T>(optionsArg);
await appData.readyDeferred.promise;
@@ -76,14 +76,14 @@ export class AppData<T = any> {
if (this.options.envMapping) {
const qenvInstance = new plugins.qenv.Qenv(
process.cwd(),
plugins.path.join(process.cwd(), '.nogit')
plugins.path.join(process.cwd(), '.nogit'),
);
// Recursive function to handle nested objects, now includes key parameter
const processEnvMapping = async (
key: keyof T,
mappingValue: any,
parentKey: keyof T | '' = ''
parentKey: keyof T | '' = '',
): Promise<any> => {
if (typeof mappingValue === 'string') {
let envValue: string | boolean | T[keyof T];
@@ -97,36 +97,40 @@ export class AppData<T = any> {
convert = 'boolean';
break;
case mappingValue.startsWith('hard_json:'):
envValue = JSON.parse(mappingValue.replace('hard_json:', '')) as T[keyof T];
envValue = JSON.parse(
mappingValue.replace('hard_json:', ''),
) as T[keyof T];
convert = 'json';
break;
case mappingValue.startsWith('hard_base64:'):
envValue = Buffer.from(
mappingValue.replace('hard_base64:', ''),
'base64'
'base64',
).toString() as T[keyof T];
convert = 'base64';
break;
case mappingValue.startsWith('boolean:'):
envValue = (await qenvInstance.getEnvVarOnDemand(
mappingValue.replace('boolean:', '')
mappingValue.replace('boolean:', ''),
)) as T[keyof T];
convert = 'boolean';
break;
case mappingValue.startsWith('json:'):
envValue = (await qenvInstance.getEnvVarOnDemand(
mappingValue.replace('json:', '')
mappingValue.replace('json:', ''),
)) as T[keyof T];
convert = 'json';
break;
case mappingValue.startsWith('base64:'):
envValue = (await qenvInstance.getEnvVarOnDemand(
mappingValue.replace('base64:', '')
mappingValue.replace('base64:', ''),
)) as T[keyof T];
convert = 'base64';
break;
default:
envValue = (await qenvInstance.getEnvVarOnDemand(mappingValue)) as T[keyof T];
envValue = (await qenvInstance.getEnvVarOnDemand(
mappingValue,
)) as T[keyof T];
break;
}
@@ -160,7 +164,11 @@ export class AppData<T = any> {
for (const innerKey in mappingValue) {
const nestedValue = mappingValue[innerKey];
// For nested objects, call recursively but do not immediately write to kvStore
const nestedResult = await processEnvMapping(innerKey as keyof T, nestedValue, key);
const nestedResult = await processEnvMapping(
innerKey as keyof T,
nestedValue,
key,
);
resultObject[innerKey as keyof T] = nestedResult;
}
if (parentKey === '') {
@@ -179,8 +187,13 @@ export class AppData<T = any> {
if (this.options.overwriteObject) {
for (const key of Object.keys(this.options.overwriteObject)) {
console.log(`-> heads up: overwriting key ${key} from options.overwriteObject`);
await this.kvStore.writeKey(key as keyof T, this.options.overwriteObject[key]);
console.log(
`-> heads up: overwriting key ${key} from options.overwriteObject`,
);
await this.kvStore.writeKey(
key as keyof T,
this.options.overwriteObject[key],
);
}
}
}
@@ -202,8 +215,8 @@ export class AppData<T = any> {
if (missingMandatoryKeys.length > 0) {
console.log(
`The following mandatory keys are missing in the appdata:\n -> ${missingMandatoryKeys.join(
',\n -> '
)}`
',\n -> ',
)}`,
);
} else {
console.log('All mandatory keys are present in the appdata');
@@ -211,7 +224,9 @@ export class AppData<T = any> {
return missingMandatoryKeys;
}
public async waitForAndGetKey<K extends keyof T>(keyArg: K): Promise<T[K] | undefined> {
public async waitForAndGetKey<K extends keyof T>(
keyArg: K,
): Promise<T[K] | undefined> {
await this.readyDeferred.promise;
await this.kvStore.waitForKeysPresent([keyArg]);
return this.kvStore.readKey(keyArg);

View File

@@ -39,7 +39,7 @@ export class KeyValueStore<T = any> {
this.deletedObject = {};
await plugins.smartfile.memory.toFs(
plugins.smartjson.stringifyPretty(this.dataObject),
this.filePath
this.filePath,
);
}
const newStateString = plugins.smartjson.stringify(this.dataObject);
@@ -62,10 +62,16 @@ export class KeyValueStore<T = any> {
}
if (this.customPath) {
// Use custom path if provided
const absolutePath = plugins.smartpath.transform.makeAbsolute(this.customPath, paths.cwd);
const absolutePath = plugins.smartpath.transform.makeAbsolute(
this.customPath,
paths.cwd,
);
this.filePath = absolutePath;
if (plugins.smartfile.fs.isDirectorySync(this.filePath)) {
this.filePath = plugins.path.join(this.filePath, this.identity + '.json');
this.filePath = plugins.path.join(
this.filePath,
this.identity + '.json',
);
}
plugins.smartfile.fs.ensureFileSync(this.filePath, '{}');
return;
@@ -129,7 +135,10 @@ export class KeyValueStore<T = any> {
/**
* writes a specific key to the keyValueStore
*/
public async writeKey<K extends keyof T>(keyArg: K, valueArg: T[K]): Promise<void> {
public async writeKey<K extends keyof T>(
keyArg: K,
valueArg: T[K],
): Promise<void> {
await this.writeAll({
[keyArg]: valueArg,
} as unknown as Partial<T>);
@@ -174,22 +183,28 @@ export class KeyValueStore<T = any> {
}
private setMandatoryKeys(keys: Array<keyof T>) {
keys.forEach(key => this.mandatoryKeys.add(key));
keys.forEach((key) => this.mandatoryKeys.add(key));
}
public async getMissingMandatoryKeys(): Promise<Array<keyof T>> {
await this.readAll();
return Array.from(this.mandatoryKeys).filter(key => !(key in this.dataObject));
return Array.from(this.mandatoryKeys).filter(
(key) => !(key in this.dataObject),
);
}
public async waitForKeysPresent<K extends keyof T>(keysArg: K[]): Promise<void> {
const missingKeys = keysArg.filter(keyArg => !this.dataObject[keyArg]);
public async waitForKeysPresent<K extends keyof T>(
keysArg: K[],
): Promise<void> {
const missingKeys = keysArg.filter((keyArg) => !this.dataObject[keyArg]);
if (missingKeys.length === 0) {
return;
}
return new Promise<void>((resolve, reject) => {
const subscription = this.changeSubject.subscribe(() => {
const missingKeys = keysArg.filter(keyArg => !this.dataObject[keyArg]);
const missingKeys = keysArg.filter(
(keyArg) => !this.dataObject[keyArg],
);
if (missingKeys.length === 0) {
subscription.unsubscribe();
resolve();
@@ -198,8 +213,10 @@ export class KeyValueStore<T = any> {
});
}
public async waitForAndGetKey<K extends keyof T>(keyArg: K): Promise<T[K] | undefined> {
public async waitForAndGetKey<K extends keyof T>(
keyArg: K,
): Promise<T[K] | undefined> {
await this.waitForKeysPresent([keyArg]);
return this.readKey(keyArg);
}
}
}

View File

@@ -27,7 +27,10 @@ export class Npmextra {
/**
* merges the supplied options with the ones from npmextra.json
*/
dataFor<IToolConfig>(toolnameArg: string, defaultOptionsArg: any): IToolConfig {
dataFor<IToolConfig>(
toolnameArg: string,
defaultOptionsArg: any,
): IToolConfig {
let npmextraToolOptions;
if (this.npmextraJsonData[toolnameArg]) {
npmextraToolOptions = this.npmextraJsonData[toolnameArg];
@@ -45,7 +48,9 @@ export class Npmextra {
* checks if the JSON exists
*/
private checkNpmextraJsonExists() {
this.npmextraJsonExists = plugins.smartfile.fs.fileExistsSync(this.lookupPath);
this.npmextraJsonExists = plugins.smartfile.fs.fileExistsSync(
this.lookupPath,
);
}
/**
@@ -64,7 +69,9 @@ export class Npmextra {
*/
private checkNpmextraJsonData() {
if (this.npmextraJsonExists) {
this.npmextraJsonData = plugins.smartfile.fs.toObjectSync(this.lookupPath);
this.npmextraJsonData = plugins.smartfile.fs.toObjectSync(
this.lookupPath,
);
} else {
this.npmextraJsonData = {};
}

View File

@@ -4,7 +4,7 @@ import * as plugins from './npmextra.plugins.js';
export let cwd = process.cwd();
export let packageDir = plugins.path.join(
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
'../'
'../',
);
// ----------------------

View File

@@ -1,8 +1,6 @@
import * as tsclass from '@tsclass/tsclass';
export {
tsclass
}
export { tsclass };
import * as qenv from '@push.rocks/qenv';
import * as smartlog from '@push.rocks/smartlog';
@@ -14,4 +12,14 @@ import * as smartpromise from '@push.rocks/smartpromise';
import * as smartrx from '@push.rocks/smartrx';
import * as taskbuffer from '@push.rocks/taskbuffer';
export { qenv, smartlog, path, smartfile, smartjson, smartpath, smartpromise, smartrx, taskbuffer };
export {
qenv,
smartlog,
path,
smartfile,
smartjson,
smartpath,
smartpromise,
smartrx,
taskbuffer,
};