@push.rocks/smartconfig 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.appdata.d.ts +72 -0
- package/dist_ts/classes.appdata.js +454 -0
- package/dist_ts/classes.keyvaluestore.d.ts +63 -0
- package/dist_ts/classes.keyvaluestore.js +169 -0
- package/dist_ts/classes.smartconfig.d.ts +29 -0
- package/dist_ts/classes.smartconfig.js +67 -0
- package/dist_ts/index.d.ts +3 -0
- package/dist_ts/index.js +4 -0
- package/dist_ts/paths.d.ts +8 -0
- package/dist_ts/paths.js +15 -0
- package/dist_ts/plugins.d.ts +12 -0
- package/dist_ts/plugins.js +13 -0
- package/package.json +73 -0
- package/readme.hints.md +0 -0
- package/readme.md +517 -0
- package/readme.plan.md +225 -0
- package/smartconfig.json +42 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.appdata.ts +548 -0
- package/ts/classes.keyvaluestore.ts +222 -0
- package/ts/classes.smartconfig.ts +79 -0
- package/ts/index.ts +3 -0
- package/ts/paths.ts +22 -0
- package/ts/plugins.ts +25 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@push.rocks/smartconfig',
|
|
6
|
+
version: '6.0.0',
|
|
7
|
+
description: 'A comprehensive configuration management library providing key-value storage, environment variable mapping, and tool configuration.'
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx5QkFBeUI7SUFDL0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFJQUFxSTtDQUNuSixDQUFBIn0=
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { KeyValueStore } from './classes.keyvaluestore.js';
|
|
3
|
+
export interface IAppDataOptions<T = any> {
|
|
4
|
+
dirPath?: string;
|
|
5
|
+
requiredKeys?: Array<keyof T>;
|
|
6
|
+
/**
|
|
7
|
+
* Whether keys should be persisted on disk or not
|
|
8
|
+
*/
|
|
9
|
+
ephemeral?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Use 'ephemeral' instead
|
|
12
|
+
*/
|
|
13
|
+
ephermal?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* kvStoreKey: 'MY_ENV_VAR'
|
|
16
|
+
*/
|
|
17
|
+
envMapping?: plugins.tsclass.typeFest.PartialDeep<T>;
|
|
18
|
+
overwriteObject?: plugins.tsclass.typeFest.PartialDeep<T>;
|
|
19
|
+
}
|
|
20
|
+
export declare class AppData<T = any> {
|
|
21
|
+
/**
|
|
22
|
+
* creates appdata. If no pathArg is given, data will be stored here:
|
|
23
|
+
* ${PWD}/.nogit/appdata
|
|
24
|
+
* @param pathArg
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
static createAndInit<T = any>(optionsArg?: IAppDataOptions<T>): Promise<AppData<T>>;
|
|
28
|
+
/**
|
|
29
|
+
* Static helper to get an environment variable as a boolean
|
|
30
|
+
* @param envVarName The name of the environment variable
|
|
31
|
+
* @returns boolean value (true if env var is "true", false otherwise)
|
|
32
|
+
*/
|
|
33
|
+
static valueAsBoolean(envVarName: string): Promise<boolean>;
|
|
34
|
+
/**
|
|
35
|
+
* Static helper to get an environment variable as parsed JSON
|
|
36
|
+
* @param envVarName The name of the environment variable
|
|
37
|
+
* @returns Parsed JSON object/array
|
|
38
|
+
*/
|
|
39
|
+
static valueAsJson<R = any>(envVarName: string): Promise<R | undefined>;
|
|
40
|
+
/**
|
|
41
|
+
* Static helper to get an environment variable as base64 decoded string
|
|
42
|
+
* @param envVarName The name of the environment variable
|
|
43
|
+
* @returns Decoded string
|
|
44
|
+
*/
|
|
45
|
+
static valueAsBase64(envVarName: string): Promise<string | undefined>;
|
|
46
|
+
/**
|
|
47
|
+
* Static helper to get an environment variable as a string
|
|
48
|
+
* @param envVarName The name of the environment variable
|
|
49
|
+
* @returns String value
|
|
50
|
+
*/
|
|
51
|
+
static valueAsString(envVarName: string): Promise<string | undefined>;
|
|
52
|
+
/**
|
|
53
|
+
* Static helper to get an environment variable as a number
|
|
54
|
+
* @param envVarName The name of the environment variable
|
|
55
|
+
* @returns Number value
|
|
56
|
+
*/
|
|
57
|
+
static valueAsNumber(envVarName: string): Promise<number | undefined>;
|
|
58
|
+
readyDeferred: plugins.smartpromise.Deferred<void>;
|
|
59
|
+
options: IAppDataOptions<T>;
|
|
60
|
+
private kvStore;
|
|
61
|
+
constructor(optionsArg?: IAppDataOptions<T>);
|
|
62
|
+
/**
|
|
63
|
+
* inits app data
|
|
64
|
+
*/
|
|
65
|
+
private init;
|
|
66
|
+
/**
|
|
67
|
+
* returns a kvstore that resides in appdata
|
|
68
|
+
*/
|
|
69
|
+
getKvStore(): Promise<KeyValueStore<T>>;
|
|
70
|
+
logMissingKeys(): Promise<Array<keyof T>>;
|
|
71
|
+
waitForAndGetKey<K extends keyof T>(keyArg: K): Promise<T[K] | undefined>;
|
|
72
|
+
}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { KeyValueStore } from './classes.keyvaluestore.js';
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// Singleton Qenv Provider
|
|
5
|
+
// ============================================================================
|
|
6
|
+
let sharedQenv;
|
|
7
|
+
function getQenv() {
|
|
8
|
+
if (!sharedQenv) {
|
|
9
|
+
sharedQenv = new plugins.qenv.Qenv(process.cwd(), plugins.path.join(process.cwd(), '.nogit'));
|
|
10
|
+
}
|
|
11
|
+
return sharedQenv;
|
|
12
|
+
}
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Security - Redaction for sensitive data
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Redacts sensitive values in logs to prevent exposure of secrets
|
|
18
|
+
*/
|
|
19
|
+
function redactSensitiveValue(key, value) {
|
|
20
|
+
// List of patterns that indicate sensitive data
|
|
21
|
+
const sensitivePatterns = [
|
|
22
|
+
/secret/i, /token/i, /key/i, /password/i, /pass/i,
|
|
23
|
+
/api/i, /credential/i, /auth/i, /private/i, /jwt/i,
|
|
24
|
+
/cert/i, /signature/i, /bearer/i
|
|
25
|
+
];
|
|
26
|
+
// Check if key contains sensitive pattern
|
|
27
|
+
const isSensitive = sensitivePatterns.some(pattern => pattern.test(key));
|
|
28
|
+
if (isSensitive) {
|
|
29
|
+
if (typeof value === 'string') {
|
|
30
|
+
// Show first 3 chars and length for debugging
|
|
31
|
+
return value.length > 3
|
|
32
|
+
? `${value.substring(0, 3)}...[${value.length} chars]`
|
|
33
|
+
: '[redacted]';
|
|
34
|
+
}
|
|
35
|
+
return '[redacted]';
|
|
36
|
+
}
|
|
37
|
+
// Check if value looks like a JWT token or base64 secret
|
|
38
|
+
if (typeof value === 'string') {
|
|
39
|
+
// JWT tokens start with eyJ
|
|
40
|
+
if (value.startsWith('eyJ')) {
|
|
41
|
+
return `eyJ...[${value.length} chars]`;
|
|
42
|
+
}
|
|
43
|
+
// Very long strings might be encoded secrets
|
|
44
|
+
if (value.length > 100) {
|
|
45
|
+
return `${value.substring(0, 50)}...[${value.length} chars total]`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return JSON.stringify(value);
|
|
49
|
+
}
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Type Converters - Centralized conversion logic
|
|
52
|
+
// ============================================================================
|
|
53
|
+
function toBoolean(value) {
|
|
54
|
+
// If already boolean, return as-is
|
|
55
|
+
if (typeof value === 'boolean') {
|
|
56
|
+
console.log(` 🔹 toBoolean: value is already boolean: ${value}`);
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
// Handle null/undefined
|
|
60
|
+
if (value == null) {
|
|
61
|
+
console.log(` 🔹 toBoolean: value is null/undefined, returning false`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
// Handle string representations
|
|
65
|
+
const s = String(value).toLowerCase().trim();
|
|
66
|
+
// True values: "true", "1", "yes", "y", "on"
|
|
67
|
+
if (['true', '1', 'yes', 'y', 'on'].includes(s)) {
|
|
68
|
+
console.log(` 🔹 toBoolean: converting "${value}" to true`);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
// False values: "false", "0", "no", "n", "off"
|
|
72
|
+
if (['false', '0', 'no', 'n', 'off'].includes(s)) {
|
|
73
|
+
console.log(` 🔹 toBoolean: converting "${value}" to false`);
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
// Default: non-empty string = true, empty = false
|
|
77
|
+
const result = s.length > 0;
|
|
78
|
+
console.log(` 🔹 toBoolean: defaulting "${value}" to ${result}`);
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
function toJson(value) {
|
|
82
|
+
if (value == null)
|
|
83
|
+
return undefined;
|
|
84
|
+
if (typeof value === 'string') {
|
|
85
|
+
try {
|
|
86
|
+
return JSON.parse(value);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
function fromBase64(value) {
|
|
95
|
+
if (value == null)
|
|
96
|
+
return undefined;
|
|
97
|
+
try {
|
|
98
|
+
return Buffer.from(String(value), 'base64').toString('utf8');
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return String(value);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function toNumber(value) {
|
|
105
|
+
if (value == null)
|
|
106
|
+
return undefined;
|
|
107
|
+
const num = Number(value);
|
|
108
|
+
return Number.isNaN(num) ? undefined : num;
|
|
109
|
+
}
|
|
110
|
+
function toString(value) {
|
|
111
|
+
if (value == null)
|
|
112
|
+
return undefined;
|
|
113
|
+
return String(value);
|
|
114
|
+
}
|
|
115
|
+
// Transform registry for extensibility
|
|
116
|
+
const transformRegistry = {
|
|
117
|
+
boolean: toBoolean,
|
|
118
|
+
json: toJson,
|
|
119
|
+
base64: fromBase64,
|
|
120
|
+
number: toNumber,
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Parse a mapping string into a declarative spec
|
|
124
|
+
*/
|
|
125
|
+
function parseMappingSpec(input) {
|
|
126
|
+
const transforms = [];
|
|
127
|
+
let remaining = input;
|
|
128
|
+
// Check for hardcoded prefixes with type conversion
|
|
129
|
+
if (remaining.startsWith('hard_boolean:')) {
|
|
130
|
+
return {
|
|
131
|
+
source: { type: 'hard', value: remaining.slice(13) },
|
|
132
|
+
transforms: ['boolean']
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (remaining.startsWith('hard_json:')) {
|
|
136
|
+
return {
|
|
137
|
+
source: { type: 'hard', value: remaining.slice(10) },
|
|
138
|
+
transforms: ['json']
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (remaining.startsWith('hard_base64:')) {
|
|
142
|
+
return {
|
|
143
|
+
source: { type: 'hard', value: remaining.slice(12) },
|
|
144
|
+
transforms: ['base64']
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
// Check for generic hard: prefix
|
|
148
|
+
if (remaining.startsWith('hard:')) {
|
|
149
|
+
remaining = remaining.slice(5);
|
|
150
|
+
// Check for legacy suffixes on hardcoded values
|
|
151
|
+
if (remaining.endsWith('_JSON')) {
|
|
152
|
+
transforms.push('json');
|
|
153
|
+
remaining = remaining.slice(0, -5);
|
|
154
|
+
}
|
|
155
|
+
else if (remaining.endsWith('_BASE64')) {
|
|
156
|
+
transforms.push('base64');
|
|
157
|
+
remaining = remaining.slice(0, -7);
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
source: { type: 'hard', value: remaining },
|
|
161
|
+
transforms
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
// Check for env var prefixes
|
|
165
|
+
if (remaining.startsWith('boolean:')) {
|
|
166
|
+
transforms.push('boolean');
|
|
167
|
+
remaining = remaining.slice(8);
|
|
168
|
+
}
|
|
169
|
+
else if (remaining.startsWith('json:')) {
|
|
170
|
+
transforms.push('json');
|
|
171
|
+
remaining = remaining.slice(5);
|
|
172
|
+
}
|
|
173
|
+
else if (remaining.startsWith('base64:')) {
|
|
174
|
+
transforms.push('base64');
|
|
175
|
+
remaining = remaining.slice(7);
|
|
176
|
+
}
|
|
177
|
+
// Check for legacy suffixes on env vars
|
|
178
|
+
if (remaining.endsWith('_JSON')) {
|
|
179
|
+
transforms.push('json');
|
|
180
|
+
remaining = remaining.slice(0, -5);
|
|
181
|
+
}
|
|
182
|
+
else if (remaining.endsWith('_BASE64')) {
|
|
183
|
+
transforms.push('base64');
|
|
184
|
+
remaining = remaining.slice(0, -7);
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
source: { type: 'env', key: remaining },
|
|
188
|
+
transforms
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Resolve the source value (env var or hardcoded)
|
|
193
|
+
*/
|
|
194
|
+
async function resolveSource(source) {
|
|
195
|
+
if (source.type === 'hard') {
|
|
196
|
+
return source.value;
|
|
197
|
+
}
|
|
198
|
+
// source.type === 'env'
|
|
199
|
+
// Workaround for Qenv bug where empty strings are treated as undefined
|
|
200
|
+
// Check process.env directly first to preserve empty strings
|
|
201
|
+
if (Object.prototype.hasOwnProperty.call(process.env, source.key)) {
|
|
202
|
+
return process.env[source.key];
|
|
203
|
+
}
|
|
204
|
+
// Fall back to Qenv for other sources (env.json, docker secrets, etc.)
|
|
205
|
+
return await getQenv().getEnvVarOnDemand(source.key);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Apply transformations in sequence
|
|
209
|
+
*/
|
|
210
|
+
function applyTransforms(value, transforms) {
|
|
211
|
+
return transforms.reduce((acc, transform) => {
|
|
212
|
+
const fn = transformRegistry[transform];
|
|
213
|
+
return fn ? fn(acc) : acc;
|
|
214
|
+
}, value);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Process a mapping value through the complete pipeline
|
|
218
|
+
*/
|
|
219
|
+
async function processMappingValue(mappingString) {
|
|
220
|
+
const spec = parseMappingSpec(mappingString);
|
|
221
|
+
const keyName = spec.source.type === 'env' ? spec.source.key : 'hardcoded';
|
|
222
|
+
console.log(` 🔍 Processing mapping: "${mappingString}"`);
|
|
223
|
+
console.log(` Source: ${spec.source.type === 'env' ? `env:${spec.source.key}` : `hard:${spec.source.value}`}`);
|
|
224
|
+
console.log(` Transforms: ${spec.transforms.length > 0 ? spec.transforms.join(', ') : 'none'}`);
|
|
225
|
+
const rawValue = await resolveSource(spec.source);
|
|
226
|
+
console.log(` Raw value: ${redactSensitiveValue(keyName, rawValue)} (type: ${typeof rawValue})`);
|
|
227
|
+
if (rawValue === undefined || rawValue === null) {
|
|
228
|
+
console.log(` ⚠️ Raw value is undefined/null, returning undefined`);
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
const result = applyTransforms(rawValue, spec.transforms);
|
|
232
|
+
console.log(` Final value: ${redactSensitiveValue(keyName, result)} (type: ${typeof result})`);
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Recursively evaluate mapping values (strings or nested objects)
|
|
237
|
+
*/
|
|
238
|
+
async function evaluateMappingValue(mappingValue) {
|
|
239
|
+
// Handle null explicitly - it should return null, not be treated as object
|
|
240
|
+
if (mappingValue === null) {
|
|
241
|
+
console.log(` 📌 Value is null, returning null`);
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
// Handle strings (mapping specs)
|
|
245
|
+
if (typeof mappingValue === 'string') {
|
|
246
|
+
return processMappingValue(mappingValue);
|
|
247
|
+
}
|
|
248
|
+
// Handle objects (but not arrays or null)
|
|
249
|
+
if (mappingValue && typeof mappingValue === 'object' && !Array.isArray(mappingValue)) {
|
|
250
|
+
console.log(` 📂 Processing nested object with ${Object.keys(mappingValue).length} keys`);
|
|
251
|
+
const result = {};
|
|
252
|
+
for (const [key, value] of Object.entries(mappingValue)) {
|
|
253
|
+
console.log(` → Processing nested key "${key}"`);
|
|
254
|
+
const evaluated = await evaluateMappingValue(value);
|
|
255
|
+
// Important: Don't filter out false or other falsy values!
|
|
256
|
+
// Only skip if explicitly undefined
|
|
257
|
+
if (evaluated !== undefined) {
|
|
258
|
+
result[key] = evaluated;
|
|
259
|
+
console.log(` ✓ Nested key "${key}" = ${redactSensitiveValue(key, evaluated)} (type: ${typeof evaluated})`);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
console.log(` ⚠️ Nested key "${key}" evaluated to undefined, skipping`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
// For any other type (numbers, booleans, etc.), return as-is
|
|
268
|
+
// Note: We don't have key context here, so we'll just indicate the type
|
|
269
|
+
console.log(` 📎 Returning value as-is: [value] (type: ${typeof mappingValue})`);
|
|
270
|
+
return mappingValue;
|
|
271
|
+
}
|
|
272
|
+
export class AppData {
|
|
273
|
+
/**
|
|
274
|
+
* creates appdata. If no pathArg is given, data will be stored here:
|
|
275
|
+
* ${PWD}/.nogit/appdata
|
|
276
|
+
* @param pathArg
|
|
277
|
+
* @returns
|
|
278
|
+
*/
|
|
279
|
+
static async createAndInit(optionsArg = {}) {
|
|
280
|
+
const appData = new AppData(optionsArg);
|
|
281
|
+
await appData.readyDeferred.promise;
|
|
282
|
+
return appData;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Static helper to get an environment variable as a boolean
|
|
286
|
+
* @param envVarName The name of the environment variable
|
|
287
|
+
* @returns boolean value (true if env var is "true", false otherwise)
|
|
288
|
+
*/
|
|
289
|
+
static async valueAsBoolean(envVarName) {
|
|
290
|
+
const value = await getQenv().getEnvVarOnDemand(envVarName);
|
|
291
|
+
return toBoolean(value);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Static helper to get an environment variable as parsed JSON
|
|
295
|
+
* @param envVarName The name of the environment variable
|
|
296
|
+
* @returns Parsed JSON object/array
|
|
297
|
+
*/
|
|
298
|
+
static async valueAsJson(envVarName) {
|
|
299
|
+
const value = await getQenv().getEnvVarOnDemand(envVarName);
|
|
300
|
+
return toJson(value);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Static helper to get an environment variable as base64 decoded string
|
|
304
|
+
* @param envVarName The name of the environment variable
|
|
305
|
+
* @returns Decoded string
|
|
306
|
+
*/
|
|
307
|
+
static async valueAsBase64(envVarName) {
|
|
308
|
+
const value = await getQenv().getEnvVarOnDemand(envVarName);
|
|
309
|
+
return fromBase64(value);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Static helper to get an environment variable as a string
|
|
313
|
+
* @param envVarName The name of the environment variable
|
|
314
|
+
* @returns String value
|
|
315
|
+
*/
|
|
316
|
+
static async valueAsString(envVarName) {
|
|
317
|
+
const value = await getQenv().getEnvVarOnDemand(envVarName);
|
|
318
|
+
return toString(value);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Static helper to get an environment variable as a number
|
|
322
|
+
* @param envVarName The name of the environment variable
|
|
323
|
+
* @returns Number value
|
|
324
|
+
*/
|
|
325
|
+
static async valueAsNumber(envVarName) {
|
|
326
|
+
const value = await getQenv().getEnvVarOnDemand(envVarName);
|
|
327
|
+
return toNumber(value);
|
|
328
|
+
}
|
|
329
|
+
constructor(optionsArg = {}) {
|
|
330
|
+
// instance
|
|
331
|
+
this.readyDeferred = plugins.smartpromise.defer();
|
|
332
|
+
this.options = optionsArg;
|
|
333
|
+
this.init();
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* inits app data
|
|
337
|
+
*/
|
|
338
|
+
async init() {
|
|
339
|
+
console.log('🚀 Initializing AppData...');
|
|
340
|
+
// Handle backward compatibility for typo
|
|
341
|
+
const isEphemeral = this.options.ephemeral ?? this.options.ephermal ?? false;
|
|
342
|
+
if (this.options.ephermal && !this.options.ephemeral) {
|
|
343
|
+
console.warn('⚠️ Option "ephermal" is deprecated, use "ephemeral" instead.');
|
|
344
|
+
}
|
|
345
|
+
if (this.options.dirPath) {
|
|
346
|
+
console.log(` 📁 Using custom directory: ${this.options.dirPath}`);
|
|
347
|
+
}
|
|
348
|
+
else if (isEphemeral) {
|
|
349
|
+
console.log(` 💨 Using ephemeral storage (in-memory only)`);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
const appDataDir = '/app/data';
|
|
353
|
+
const dataDir = '/data';
|
|
354
|
+
const nogitAppData = '.nogit/appdata';
|
|
355
|
+
const appDataExists = plugins.smartfile.fs.isDirectory(appDataDir);
|
|
356
|
+
const dataExists = plugins.smartfile.fs.isDirectory(dataDir);
|
|
357
|
+
if (appDataExists) {
|
|
358
|
+
this.options.dirPath = appDataDir;
|
|
359
|
+
console.log(` 📁 Auto-selected container directory: ${appDataDir}`);
|
|
360
|
+
}
|
|
361
|
+
else if (dataExists) {
|
|
362
|
+
this.options.dirPath = dataDir;
|
|
363
|
+
console.log(` 📁 Auto-selected data directory: ${dataDir}`);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
await plugins.smartfile.fs.ensureDir(nogitAppData);
|
|
367
|
+
this.options.dirPath = nogitAppData;
|
|
368
|
+
console.log(` 📁 Auto-selected local directory: ${nogitAppData}`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
this.kvStore = new KeyValueStore({
|
|
372
|
+
typeArg: isEphemeral ? 'ephemeral' : 'custom',
|
|
373
|
+
identityArg: 'appkv',
|
|
374
|
+
customPath: this.options.dirPath,
|
|
375
|
+
mandatoryKeys: this.options.requiredKeys,
|
|
376
|
+
});
|
|
377
|
+
if (this.options.envMapping) {
|
|
378
|
+
console.log(`📦 Processing envMapping for AppData...`);
|
|
379
|
+
const totalKeys = Object.keys(this.options.envMapping).length;
|
|
380
|
+
let processedCount = 0;
|
|
381
|
+
// Process each top-level key in envMapping
|
|
382
|
+
for (const key in this.options.envMapping) {
|
|
383
|
+
try {
|
|
384
|
+
const mappingSpec = this.options.envMapping[key];
|
|
385
|
+
const specType = mappingSpec === null ? 'null' :
|
|
386
|
+
typeof mappingSpec === 'string' ? mappingSpec :
|
|
387
|
+
typeof mappingSpec === 'object' ? 'nested object' :
|
|
388
|
+
typeof mappingSpec;
|
|
389
|
+
console.log(` → Processing key "${key}" with spec: ${specType}`);
|
|
390
|
+
const evaluated = await evaluateMappingValue(mappingSpec);
|
|
391
|
+
// Important: Don't skip false, 0, empty string, or null values!
|
|
392
|
+
// Only skip if explicitly undefined
|
|
393
|
+
if (evaluated !== undefined) {
|
|
394
|
+
await this.kvStore.writeKey(key, evaluated);
|
|
395
|
+
processedCount++;
|
|
396
|
+
const valueType = evaluated === null ? 'null' :
|
|
397
|
+
Array.isArray(evaluated) ? 'array' :
|
|
398
|
+
typeof evaluated;
|
|
399
|
+
const valuePreview = evaluated === null ? 'null' :
|
|
400
|
+
typeof evaluated === 'object' ?
|
|
401
|
+
(Array.isArray(evaluated) ? `[${evaluated.length} items]` : `{${Object.keys(evaluated).length} keys}`) :
|
|
402
|
+
redactSensitiveValue(key, evaluated);
|
|
403
|
+
console.log(` ✅ Successfully processed key "${key}" = ${valuePreview} (type: ${valueType})`);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
console.log(` ⚠️ Key "${key}" evaluated to undefined, skipping`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
console.error(` ❌ Failed to evaluate envMapping for key "${key}":`, err);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
console.log(`📊 EnvMapping complete: ${processedCount}/${totalKeys} keys successfully processed`);
|
|
414
|
+
}
|
|
415
|
+
// Apply overwrite object after env mapping
|
|
416
|
+
if (this.options.overwriteObject) {
|
|
417
|
+
const overwriteKeys = Object.keys(this.options.overwriteObject);
|
|
418
|
+
console.log(`🔄 Applying overwriteObject with ${overwriteKeys.length} key(s)...`);
|
|
419
|
+
for (const key of overwriteKeys) {
|
|
420
|
+
const value = this.options.overwriteObject[key];
|
|
421
|
+
const valueType = Array.isArray(value) ? 'array' : typeof value;
|
|
422
|
+
console.log(` 🔧 Overwriting key "${key}" with ${valueType} value`);
|
|
423
|
+
await this.kvStore.writeKey(key, value);
|
|
424
|
+
}
|
|
425
|
+
console.log(`✅ OverwriteObject complete: ${overwriteKeys.length} key(s) overwritten`);
|
|
426
|
+
}
|
|
427
|
+
this.readyDeferred.resolve();
|
|
428
|
+
console.log('✨ AppData initialization complete!');
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* returns a kvstore that resides in appdata
|
|
432
|
+
*/
|
|
433
|
+
async getKvStore() {
|
|
434
|
+
await this.readyDeferred.promise;
|
|
435
|
+
return this.kvStore;
|
|
436
|
+
}
|
|
437
|
+
async logMissingKeys() {
|
|
438
|
+
const kvStore = await this.getKvStore();
|
|
439
|
+
const missingMandatoryKeys = await kvStore.getMissingMandatoryKeys();
|
|
440
|
+
if (missingMandatoryKeys.length > 0) {
|
|
441
|
+
console.log(`The following mandatory keys are missing in the appdata:\n -> ${missingMandatoryKeys.join(',\n -> ')}`);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
console.log('All mandatory keys are present in the appdata');
|
|
445
|
+
}
|
|
446
|
+
return missingMandatoryKeys;
|
|
447
|
+
}
|
|
448
|
+
async waitForAndGetKey(keyArg) {
|
|
449
|
+
await this.readyDeferred.promise;
|
|
450
|
+
await this.kvStore.waitForKeysPresent([keyArg]);
|
|
451
|
+
return this.kvStore.readKey(keyArg);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hcHBkYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5hcHBkYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUUzRCwrRUFBK0U7QUFDL0UsMEJBQTBCO0FBQzFCLCtFQUErRTtBQUMvRSxJQUFJLFVBQXlDLENBQUM7QUFFOUMsU0FBUyxPQUFPO0lBQ2QsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLFVBQVUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUNoQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQ2IsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUMzQyxDQUFDO0lBQ0osQ0FBQztJQUNELE9BQU8sVUFBVSxDQUFDO0FBQ3BCLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsMENBQTBDO0FBQzFDLCtFQUErRTtBQUMvRTs7R0FFRztBQUNILFNBQVMsb0JBQW9CLENBQUMsR0FBVyxFQUFFLEtBQWM7SUFDdkQsZ0RBQWdEO0lBQ2hELE1BQU0saUJBQWlCLEdBQUc7UUFDeEIsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU87UUFDakQsTUFBTSxFQUFFLGFBQWEsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU07UUFDbEQsT0FBTyxFQUFFLFlBQVksRUFBRSxTQUFTO0tBQ2pDLENBQUM7SUFFRiwwQ0FBMEM7SUFDMUMsTUFBTSxXQUFXLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRXpFLElBQUksV0FBVyxFQUFF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
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
export type TKeyValueStore = 'custom' | 'userHomeDir' | 'ephemeral';
|
|
3
|
+
export interface IKvStoreConstructorOptions<T> {
|
|
4
|
+
typeArg: TKeyValueStore;
|
|
5
|
+
identityArg: string;
|
|
6
|
+
customPath?: string;
|
|
7
|
+
mandatoryKeys?: Array<keyof T>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* kvStore is a simple key value store to store data about projects between runs
|
|
11
|
+
*/
|
|
12
|
+
export declare class KeyValueStore<T = any> {
|
|
13
|
+
private dataObject;
|
|
14
|
+
private deletedObject;
|
|
15
|
+
private mandatoryKeys;
|
|
16
|
+
changeSubject: plugins.smartrx.rxjs.Subject<Partial<T>>;
|
|
17
|
+
private storedStateString;
|
|
18
|
+
syncTask: plugins.taskbuffer.Task<undefined>;
|
|
19
|
+
/**
|
|
20
|
+
* computes the identity and filePath
|
|
21
|
+
*/
|
|
22
|
+
private initFilePath;
|
|
23
|
+
type: TKeyValueStore;
|
|
24
|
+
identity: string;
|
|
25
|
+
filePath?: string;
|
|
26
|
+
private customPath?;
|
|
27
|
+
/**
|
|
28
|
+
* the constructor of keyvalue store
|
|
29
|
+
* @param typeArg
|
|
30
|
+
* @param identityArg
|
|
31
|
+
* @param customPath Optional custom path for the keyValue store
|
|
32
|
+
*/
|
|
33
|
+
constructor(optionsArg: IKvStoreConstructorOptions<T>);
|
|
34
|
+
/**
|
|
35
|
+
* reads all keyValue pairs at once and returns them
|
|
36
|
+
*/
|
|
37
|
+
readAll(): Promise<Partial<T>>;
|
|
38
|
+
/**
|
|
39
|
+
* reads a keyValueFile from disk
|
|
40
|
+
*/
|
|
41
|
+
readKey<K extends keyof T>(keyArg: K): Promise<T[K]>;
|
|
42
|
+
/**
|
|
43
|
+
* writes a specific key to the keyValueStore
|
|
44
|
+
*/
|
|
45
|
+
writeKey<K extends keyof T>(keyArg: K, valueArg: T[K]): Promise<void>;
|
|
46
|
+
deleteKey<K extends keyof T>(keyArg: K): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* writes all keyValue pairs in the object argument
|
|
49
|
+
*/
|
|
50
|
+
writeAll(keyValueObject: Partial<T>): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* wipes a key value store from disk
|
|
53
|
+
*/
|
|
54
|
+
wipe(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* resets the KeyValueStore to the initial state by syncing first, deleting all keys, and then triggering a sync again
|
|
57
|
+
*/
|
|
58
|
+
reset(): Promise<void>;
|
|
59
|
+
private setMandatoryKeys;
|
|
60
|
+
getMissingMandatoryKeys(): Promise<Array<keyof T>>;
|
|
61
|
+
waitForKeysPresent<K extends keyof T>(keysArg: K[]): Promise<void>;
|
|
62
|
+
waitForAndGetKey<K extends keyof T>(keyArg: K): Promise<T[K] | undefined>;
|
|
63
|
+
}
|