@adriangalilea/utils 0.16.1 → 0.16.2
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/bot/access-control.d.ts +7 -7
- package/dist/bot/access-control.d.ts.map +1 -1
- package/dist/bot/access-control.js +144 -121
- package/dist/bot/access-control.js.map +1 -1
- package/dist/bot/coalesce.d.ts +1 -1
- package/dist/bot/coalesce.d.ts.map +1 -1
- package/dist/bot/coalesce.js +8 -4
- package/dist/bot/coalesce.js.map +1 -1
- package/dist/bot/index.d.ts +6 -6
- package/dist/bot/index.d.ts.map +1 -1
- package/dist/bot/index.js +6 -6
- package/dist/bot/index.js.map +1 -1
- package/dist/bot/kit.d.ts +2 -2
- package/dist/bot/kit.d.ts.map +1 -1
- package/dist/bot/kit.js +11 -11
- package/dist/bot/kit.js.map +1 -1
- package/dist/bot/language.d.ts +6 -6
- package/dist/bot/language.d.ts.map +1 -1
- package/dist/bot/language.js +51 -33
- package/dist/bot/language.js.map +1 -1
- package/dist/bot/llm.d.ts +12 -12
- package/dist/bot/llm.d.ts.map +1 -1
- package/dist/bot/llm.js +46 -42
- package/dist/bot/llm.js.map +1 -1
- package/dist/bot/menu.d.ts +5 -5
- package/dist/bot/menu.d.ts.map +1 -1
- package/dist/bot/menu.js +70 -67
- package/dist/bot/menu.js.map +1 -1
- package/dist/browser.d.ts +6 -6
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +6 -6
- package/dist/browser.js.map +1 -1
- package/dist/index.d.ts +14 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/offensive.d.ts.map +1 -1
- package/dist/offensive.js +17 -11
- package/dist/offensive.js.map +1 -1
- package/dist/platform/dir.d.ts.map +1 -1
- package/dist/platform/dir.js +8 -8
- package/dist/platform/dir.js.map +1 -1
- package/dist/platform/file.d.ts.map +1 -1
- package/dist/platform/file.js +20 -17
- package/dist/platform/file.js.map +1 -1
- package/dist/platform/kev.d.ts.map +1 -1
- package/dist/platform/kev.js +113 -106
- package/dist/platform/kev.js.map +1 -1
- package/dist/platform/path.d.ts.map +1 -1
- package/dist/platform/path.js +5 -5
- package/dist/platform/path.js.map +1 -1
- package/dist/platform/project.d.ts.map +1 -1
- package/dist/platform/project.js +19 -19
- package/dist/platform/project.js.map +1 -1
- package/dist/platform/unseen.d.ts.map +1 -1
- package/dist/platform/unseen.js +8 -6
- package/dist/platform/unseen.js.map +1 -1
- package/dist/platform/xdg.d.ts.map +1 -1
- package/dist/platform/xdg.js +7 -7
- package/dist/platform/xdg.js.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +35 -22
- package/dist/runtime.js.map +1 -1
- package/dist/say/index.d.ts.map +1 -1
- package/dist/say/index.js +2 -2
- package/dist/say/index.js.map +1 -1
- package/dist/universal/currency/crypto-symbols-data.d.ts.map +1 -1
- package/dist/universal/currency/crypto-symbols-data.js +1 -1
- package/dist/universal/currency/crypto-symbols-data.js.map +1 -1
- package/dist/universal/currency/crypto-symbols.d.ts.map +1 -1
- package/dist/universal/currency/crypto-symbols.js +1 -1
- package/dist/universal/currency/crypto-symbols.js.map +1 -1
- package/dist/universal/currency/download-crypto-list.d.ts.map +1 -1
- package/dist/universal/currency/download-crypto-list.js +17 -17
- package/dist/universal/currency/download-crypto-list.js.map +1 -1
- package/dist/universal/currency/index.d.ts.map +1 -1
- package/dist/universal/currency/index.js +117 -80
- package/dist/universal/currency/index.js.map +1 -1
- package/dist/universal/format.d.ts.map +1 -1
- package/dist/universal/format.js +10 -10
- package/dist/universal/format.js.map +1 -1
- package/dist/universal/log.d.ts +1 -1
- package/dist/universal/log.d.ts.map +1 -1
- package/dist/universal/log.js +66 -60
- package/dist/universal/log.js.map +1 -1
- package/package.json +146 -141
package/dist/platform/kev.js
CHANGED
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
* KEV.debug = true // Shows lookup chain
|
|
34
34
|
* KEV.export("backup.env") // Includes # from: comments
|
|
35
35
|
*/
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import { file } from
|
|
39
|
-
import { path } from
|
|
40
|
-
import {
|
|
36
|
+
import { panic } from "../offensive.js";
|
|
37
|
+
import { runtime } from "../runtime.js";
|
|
38
|
+
import { file } from "./file.js";
|
|
39
|
+
import { path } from "./path.js";
|
|
40
|
+
import { findMonorepoRoot, findProjectRoot } from "./project.js";
|
|
41
41
|
class SourceOps {
|
|
42
42
|
kev;
|
|
43
43
|
constructor(kev) {
|
|
@@ -59,7 +59,7 @@ class SourceOps {
|
|
|
59
59
|
* Remove specific sources
|
|
60
60
|
*/
|
|
61
61
|
remove(...sources) {
|
|
62
|
-
this.kev.sources = this.kev.sources.filter(s => !sources.includes(s));
|
|
62
|
+
this.kev.sources = this.kev.sources.filter((s) => !sources.includes(s));
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* List current sources
|
|
@@ -76,7 +76,7 @@ class SourceOps {
|
|
|
76
76
|
}
|
|
77
77
|
export class KevOps {
|
|
78
78
|
memory = new Map();
|
|
79
|
-
sources = [
|
|
79
|
+
sources = ["os", ".env"];
|
|
80
80
|
source;
|
|
81
81
|
debug = false;
|
|
82
82
|
constructor() {
|
|
@@ -87,64 +87,64 @@ export class KevOps {
|
|
|
87
87
|
// Check for monorepo root first (turborepo)
|
|
88
88
|
const monorepoRoot = findMonorepoRoot();
|
|
89
89
|
if (monorepoRoot) {
|
|
90
|
-
const monorepoEnv = path.join(monorepoRoot,
|
|
90
|
+
const monorepoEnv = path.join(monorepoRoot, ".env");
|
|
91
91
|
this.sources.push(monorepoEnv);
|
|
92
92
|
if (this.debug) {
|
|
93
|
-
console.log(
|
|
94
|
-
console.log(
|
|
93
|
+
console.log("KEV: Auto-discovered monorepo root:", monorepoRoot);
|
|
94
|
+
console.log("KEV: Added monorepo .env to sources:", monorepoEnv);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
// Then check for project root
|
|
98
98
|
const projectRoot = findProjectRoot();
|
|
99
99
|
if (projectRoot) {
|
|
100
|
-
const projectEnv = path.join(projectRoot,
|
|
100
|
+
const projectEnv = path.join(projectRoot, ".env");
|
|
101
101
|
// Only add if it's different from monorepo env
|
|
102
|
-
if (!monorepoRoot || projectEnv !== path.join(monorepoRoot,
|
|
102
|
+
if (!monorepoRoot || projectEnv !== path.join(monorepoRoot, ".env")) {
|
|
103
103
|
this.sources.push(projectEnv);
|
|
104
104
|
if (this.debug) {
|
|
105
|
-
console.log(
|
|
106
|
-
console.log(
|
|
105
|
+
console.log("KEV: Auto-discovered project root:", projectRoot);
|
|
106
|
+
console.log("KEV: Added project .env to sources:", projectEnv);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
if (this.debug) {
|
|
111
111
|
if (!monorepoRoot && !projectRoot) {
|
|
112
|
-
console.log(
|
|
112
|
+
console.log("KEV: No project or monorepo root found, using standard sources:", this.sources);
|
|
113
113
|
}
|
|
114
114
|
else {
|
|
115
|
-
console.log(
|
|
115
|
+
console.log("KEV: Default sources:", this.sources);
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
parseKey(key) {
|
|
120
|
-
if (key.startsWith(
|
|
121
|
-
panic(
|
|
120
|
+
if (key.startsWith(":")) {
|
|
121
|
+
panic("invalid key format - starts with colon:", key);
|
|
122
122
|
}
|
|
123
|
-
if (key.includes(
|
|
124
|
-
panic(
|
|
123
|
+
if (key.includes("::")) {
|
|
124
|
+
panic("invalid key format - double colon:", key);
|
|
125
125
|
}
|
|
126
|
-
const parts = key.split(
|
|
126
|
+
const parts = key.split(":", 2);
|
|
127
127
|
if (parts.length === 2) {
|
|
128
|
-
if (parts[0] ===
|
|
129
|
-
panic(
|
|
128
|
+
if (parts[0] === "" || parts[1] === "") {
|
|
129
|
+
panic("invalid key format - empty namespace or key:", key);
|
|
130
130
|
}
|
|
131
131
|
return [parts[0], parts[1]];
|
|
132
132
|
}
|
|
133
|
-
return [
|
|
133
|
+
return ["", key];
|
|
134
134
|
}
|
|
135
135
|
/**
|
|
136
136
|
* Get environment variable with optional default.
|
|
137
137
|
*/
|
|
138
138
|
get(key, defaultValue) {
|
|
139
139
|
const [namespace, realKey] = this.parseKey(key);
|
|
140
|
-
const debug = this.debug && key !==
|
|
140
|
+
const debug = this.debug && key !== "LOG_LEVEL";
|
|
141
141
|
if (debug) {
|
|
142
142
|
console.log(`KEV: Looking for ${key}`);
|
|
143
143
|
}
|
|
144
144
|
// Namespaced - direct access
|
|
145
145
|
if (namespace) {
|
|
146
146
|
const val = this.getFromNamespace(namespace, realKey);
|
|
147
|
-
if (val !==
|
|
147
|
+
if (val !== "") {
|
|
148
148
|
if (debug) {
|
|
149
149
|
console.log(` ✓ ${namespace}: found ${val}`);
|
|
150
150
|
}
|
|
@@ -159,7 +159,7 @@ export class KevOps {
|
|
|
159
159
|
}
|
|
160
160
|
return defaultValue;
|
|
161
161
|
}
|
|
162
|
-
return
|
|
162
|
+
return "";
|
|
163
163
|
}
|
|
164
164
|
// Unnamespaced - check memory first
|
|
165
165
|
const entry = this.memory.get(realKey);
|
|
@@ -170,17 +170,17 @@ export class KevOps {
|
|
|
170
170
|
return entry.value;
|
|
171
171
|
}
|
|
172
172
|
if (debug) {
|
|
173
|
-
console.log(
|
|
173
|
+
console.log(" ✗ memory: not found");
|
|
174
174
|
}
|
|
175
175
|
// Search through sources
|
|
176
176
|
for (const source of this.sources) {
|
|
177
177
|
const val = this.getFromNamespace(source, realKey);
|
|
178
|
-
if (val !==
|
|
178
|
+
if (val !== "") {
|
|
179
179
|
if (debug) {
|
|
180
180
|
console.log(` ✓ ${source}: found ${val} (caching)`);
|
|
181
181
|
}
|
|
182
182
|
// Cache in memory for next time with source info
|
|
183
|
-
const absoluteSource = source !==
|
|
183
|
+
const absoluteSource = source !== "os" && source !== "default" && source !== "set"
|
|
184
184
|
? path.absolute(source)
|
|
185
185
|
: source;
|
|
186
186
|
this.memory.set(realKey, { value: val, source: absoluteSource });
|
|
@@ -195,21 +195,21 @@ export class KevOps {
|
|
|
195
195
|
if (debug) {
|
|
196
196
|
console.log(` → using default: ${defaultValue} (caching)`);
|
|
197
197
|
}
|
|
198
|
-
this.memory.set(realKey, { value: defaultValue, source:
|
|
198
|
+
this.memory.set(realKey, { value: defaultValue, source: "default" });
|
|
199
199
|
return defaultValue;
|
|
200
200
|
}
|
|
201
201
|
if (debug) {
|
|
202
|
-
console.log(
|
|
202
|
+
console.log(" → not found, returning empty");
|
|
203
203
|
}
|
|
204
|
-
return
|
|
204
|
+
return "";
|
|
205
205
|
}
|
|
206
206
|
/**
|
|
207
207
|
* Get environment variable or panic if not found
|
|
208
208
|
*/
|
|
209
209
|
mustGet(key) {
|
|
210
210
|
const val = this.get(key);
|
|
211
|
-
if (val ===
|
|
212
|
-
panic(
|
|
211
|
+
if (val === "") {
|
|
212
|
+
panic("required key not found:", key);
|
|
213
213
|
}
|
|
214
214
|
return val;
|
|
215
215
|
}
|
|
@@ -218,14 +218,14 @@ export class KevOps {
|
|
|
218
218
|
*/
|
|
219
219
|
sourceOf(key) {
|
|
220
220
|
const entry = this.memory.get(key);
|
|
221
|
-
return entry ? entry.source :
|
|
221
|
+
return entry ? entry.source : "";
|
|
222
222
|
}
|
|
223
223
|
/**
|
|
224
224
|
* Get both value and its source
|
|
225
225
|
*/
|
|
226
226
|
getWithSource(key, defaultValue) {
|
|
227
227
|
const value = this.get(key, defaultValue);
|
|
228
|
-
if (value !==
|
|
228
|
+
if (value !== "") {
|
|
229
229
|
let source = this.sourceOf(key);
|
|
230
230
|
// If not in cache but has value, it might be a namespaced get
|
|
231
231
|
if (!source) {
|
|
@@ -236,33 +236,33 @@ export class KevOps {
|
|
|
236
236
|
}
|
|
237
237
|
return [value, source];
|
|
238
238
|
}
|
|
239
|
-
return [
|
|
239
|
+
return ["", ""];
|
|
240
240
|
}
|
|
241
241
|
getFromNamespace(namespace, key) {
|
|
242
242
|
switch (namespace) {
|
|
243
|
-
case
|
|
244
|
-
return runtime.env(key) ||
|
|
243
|
+
case "os":
|
|
244
|
+
return runtime.env(key) || "";
|
|
245
245
|
default:
|
|
246
246
|
// File namespace (.env, .env.local, etc)
|
|
247
|
-
if (namespace.startsWith(
|
|
247
|
+
if (namespace.startsWith(".") || namespace.includes("/")) {
|
|
248
248
|
return this.getFromFile(namespace, key);
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
|
-
return
|
|
251
|
+
return "";
|
|
252
252
|
}
|
|
253
253
|
getFromFile(filePath, key) {
|
|
254
254
|
if (!file.exists(filePath)) {
|
|
255
|
-
return
|
|
255
|
+
return "";
|
|
256
256
|
}
|
|
257
257
|
try {
|
|
258
258
|
const content = file.readText(filePath);
|
|
259
|
-
const lines = content.split(
|
|
259
|
+
const lines = content.split("\n");
|
|
260
260
|
for (const line of lines) {
|
|
261
261
|
const trimmed = line.trim();
|
|
262
|
-
if (trimmed ===
|
|
262
|
+
if (trimmed === "" || trimmed.startsWith("#")) {
|
|
263
263
|
continue;
|
|
264
264
|
}
|
|
265
|
-
const parts = trimmed.split(
|
|
265
|
+
const parts = trimmed.split("=", 2);
|
|
266
266
|
if (parts.length === 2) {
|
|
267
267
|
const fileKey = parts[0].trim();
|
|
268
268
|
if (fileKey === key) {
|
|
@@ -280,7 +280,7 @@ export class KevOps {
|
|
|
280
280
|
catch {
|
|
281
281
|
// File read error
|
|
282
282
|
}
|
|
283
|
-
return
|
|
283
|
+
return "";
|
|
284
284
|
}
|
|
285
285
|
/**
|
|
286
286
|
* Set environment variable
|
|
@@ -293,16 +293,16 @@ export class KevOps {
|
|
|
293
293
|
return;
|
|
294
294
|
}
|
|
295
295
|
// Unnamespaced - memory only
|
|
296
|
-
this.memory.set(realKey, { value, source:
|
|
296
|
+
this.memory.set(realKey, { value, source: "set" });
|
|
297
297
|
}
|
|
298
298
|
setToNamespace(namespace, key, value) {
|
|
299
299
|
switch (namespace) {
|
|
300
|
-
case
|
|
300
|
+
case "os":
|
|
301
301
|
runtime.setEnv(key, value);
|
|
302
302
|
break;
|
|
303
303
|
default:
|
|
304
304
|
// File namespace - update or append to file
|
|
305
|
-
if (namespace.startsWith(
|
|
305
|
+
if (namespace.startsWith(".") || namespace.includes("/")) {
|
|
306
306
|
this.setToFile(namespace, key, value);
|
|
307
307
|
}
|
|
308
308
|
}
|
|
@@ -312,21 +312,23 @@ export class KevOps {
|
|
|
312
312
|
let found = false;
|
|
313
313
|
if (file.exists(path)) {
|
|
314
314
|
const content = file.readText(path);
|
|
315
|
-
const existingLines = content.split(
|
|
315
|
+
const existingLines = content.split("\n");
|
|
316
316
|
for (const line of existingLines) {
|
|
317
317
|
const trimmed = line.trim();
|
|
318
318
|
// Keep empty lines and comments
|
|
319
|
-
if (trimmed ===
|
|
319
|
+
if (trimmed === "" || trimmed.startsWith("#")) {
|
|
320
320
|
lines.push(line);
|
|
321
321
|
continue;
|
|
322
322
|
}
|
|
323
323
|
// Check if this is the key we're updating
|
|
324
|
-
const parts = trimmed.split(
|
|
324
|
+
const parts = trimmed.split("=", 2);
|
|
325
325
|
if (parts.length >= 1) {
|
|
326
326
|
const fileKey = parts[0].trim();
|
|
327
327
|
if (fileKey === key) {
|
|
328
328
|
// Update existing key
|
|
329
|
-
const quotedValue = value.includes(
|
|
329
|
+
const quotedValue = value.includes(" ") ||
|
|
330
|
+
value.includes("\t") ||
|
|
331
|
+
value.includes("\n")
|
|
330
332
|
? `"${value}"`
|
|
331
333
|
: value;
|
|
332
334
|
lines.push(`${key}=${quotedValue}`);
|
|
@@ -343,13 +345,13 @@ export class KevOps {
|
|
|
343
345
|
}
|
|
344
346
|
// If key wasn't found, append it
|
|
345
347
|
if (!found) {
|
|
346
|
-
const quotedValue = value.includes(
|
|
348
|
+
const quotedValue = value.includes(" ") || value.includes("\t") || value.includes("\n")
|
|
347
349
|
? `"${value}"`
|
|
348
350
|
: value;
|
|
349
351
|
lines.push(`${key}=${quotedValue}`);
|
|
350
352
|
}
|
|
351
353
|
// Write back
|
|
352
|
-
file.write(path, lines.join(
|
|
354
|
+
file.write(path, lines.join("\n"));
|
|
353
355
|
}
|
|
354
356
|
/**
|
|
355
357
|
* Check if key exists
|
|
@@ -374,12 +376,12 @@ export class KevOps {
|
|
|
374
376
|
}
|
|
375
377
|
hasInNamespace(namespace, key) {
|
|
376
378
|
switch (namespace) {
|
|
377
|
-
case
|
|
379
|
+
case "os":
|
|
378
380
|
return runtime.hasEnv(key);
|
|
379
381
|
default:
|
|
380
382
|
// File namespace
|
|
381
|
-
if (namespace.startsWith(
|
|
382
|
-
return this.getFromFile(namespace, key) !==
|
|
383
|
+
if (namespace.startsWith(".") || namespace.includes("/")) {
|
|
384
|
+
return this.getFromFile(namespace, key) !== "";
|
|
383
385
|
}
|
|
384
386
|
}
|
|
385
387
|
return false;
|
|
@@ -387,7 +389,7 @@ export class KevOps {
|
|
|
387
389
|
/**
|
|
388
390
|
* Get all keys matching pattern
|
|
389
391
|
*/
|
|
390
|
-
keys(pattern =
|
|
392
|
+
keys(pattern = "*") {
|
|
391
393
|
const seen = new Set();
|
|
392
394
|
const result = [];
|
|
393
395
|
const patterns = Array.isArray(pattern) ? pattern : [pattern];
|
|
@@ -433,16 +435,16 @@ export class KevOps {
|
|
|
433
435
|
getNamespaceData(namespace, pattern, keysOnly) {
|
|
434
436
|
const result = {};
|
|
435
437
|
switch (namespace) {
|
|
436
|
-
case
|
|
438
|
+
case "os":
|
|
437
439
|
for (const [key, value] of Object.entries(runtime.allEnv())) {
|
|
438
440
|
if (this.matchPattern(key, pattern)) {
|
|
439
|
-
result[key] = keysOnly ?
|
|
441
|
+
result[key] = keysOnly ? "" : value || "";
|
|
440
442
|
}
|
|
441
443
|
}
|
|
442
444
|
break;
|
|
443
445
|
default:
|
|
444
446
|
// File namespace
|
|
445
|
-
if (namespace.startsWith(
|
|
447
|
+
if (namespace.startsWith(".") || namespace.includes("/")) {
|
|
446
448
|
this.parseEnvFile(namespace, pattern, result, keysOnly);
|
|
447
449
|
}
|
|
448
450
|
}
|
|
@@ -454,18 +456,18 @@ export class KevOps {
|
|
|
454
456
|
}
|
|
455
457
|
try {
|
|
456
458
|
const content = file.readText(path);
|
|
457
|
-
const lines = content.split(
|
|
459
|
+
const lines = content.split("\n");
|
|
458
460
|
for (const line of lines) {
|
|
459
461
|
const trimmed = line.trim();
|
|
460
|
-
if (trimmed ===
|
|
462
|
+
if (trimmed === "" || trimmed.startsWith("#")) {
|
|
461
463
|
continue;
|
|
462
464
|
}
|
|
463
|
-
const parts = trimmed.split(
|
|
465
|
+
const parts = trimmed.split("=", 2);
|
|
464
466
|
if (parts.length >= 1) {
|
|
465
467
|
const key = parts[0].trim();
|
|
466
468
|
if (this.matchPattern(key, pattern)) {
|
|
467
469
|
if (keysOnly) {
|
|
468
|
-
result[key] =
|
|
470
|
+
result[key] = "";
|
|
469
471
|
}
|
|
470
472
|
else if (parts.length === 2) {
|
|
471
473
|
let value = parts[1].trim();
|
|
@@ -485,18 +487,18 @@ export class KevOps {
|
|
|
485
487
|
}
|
|
486
488
|
}
|
|
487
489
|
matchPattern(key, pattern) {
|
|
488
|
-
if (pattern ===
|
|
490
|
+
if (pattern === "*")
|
|
489
491
|
return true;
|
|
490
|
-
if (pattern.endsWith(
|
|
492
|
+
if (pattern.endsWith("*")) {
|
|
491
493
|
const prefix = pattern.slice(0, -1);
|
|
492
494
|
return key.startsWith(prefix);
|
|
493
495
|
}
|
|
494
|
-
if (pattern.startsWith(
|
|
496
|
+
if (pattern.startsWith("*")) {
|
|
495
497
|
const suffix = pattern.slice(1);
|
|
496
498
|
return key.endsWith(suffix);
|
|
497
499
|
}
|
|
498
|
-
if (pattern.includes(
|
|
499
|
-
const parts = pattern.split(
|
|
500
|
+
if (pattern.includes("*")) {
|
|
501
|
+
const parts = pattern.split("*");
|
|
500
502
|
if (parts.length === 2) {
|
|
501
503
|
return key.startsWith(parts[0]) && key.endsWith(parts[1]);
|
|
502
504
|
}
|
|
@@ -508,7 +510,11 @@ export class KevOps {
|
|
|
508
510
|
*/
|
|
509
511
|
all(pattern) {
|
|
510
512
|
const result = {};
|
|
511
|
-
const patterns = pattern
|
|
513
|
+
const patterns = pattern
|
|
514
|
+
? Array.isArray(pattern)
|
|
515
|
+
? pattern
|
|
516
|
+
: [pattern]
|
|
517
|
+
: [];
|
|
512
518
|
if (patterns.length === 0) {
|
|
513
519
|
// Default - return memory only with source info
|
|
514
520
|
if (this.memory.size > 0) {
|
|
@@ -521,7 +527,7 @@ export class KevOps {
|
|
|
521
527
|
return result;
|
|
522
528
|
}
|
|
523
529
|
// Check if any pattern has namespace
|
|
524
|
-
const hasNamespace = patterns.some(p => p.includes(
|
|
530
|
+
const hasNamespace = patterns.some((p) => p.includes(":"));
|
|
525
531
|
if (!hasNamespace) {
|
|
526
532
|
// No namespaces - get from memory and all sources
|
|
527
533
|
const memMatches = {};
|
|
@@ -539,7 +545,7 @@ export class KevOps {
|
|
|
539
545
|
// Check all sources
|
|
540
546
|
for (const source of this.sources) {
|
|
541
547
|
const sourceMatches = {};
|
|
542
|
-
const sourceVars = this.getAllFromNamespace(source,
|
|
548
|
+
const sourceVars = this.getAllFromNamespace(source, "*");
|
|
543
549
|
for (const [key, val] of Object.entries(sourceVars)) {
|
|
544
550
|
for (const pat of patterns) {
|
|
545
551
|
if (this.matchPattern(key, pat)) {
|
|
@@ -555,7 +561,7 @@ export class KevOps {
|
|
|
555
561
|
return result;
|
|
556
562
|
}
|
|
557
563
|
// Special case for *:*
|
|
558
|
-
if (patterns.length === 1 && patterns[0] ===
|
|
564
|
+
if (patterns.length === 1 && patterns[0] === "*:*") {
|
|
559
565
|
// Add memory
|
|
560
566
|
if (this.memory.size > 0) {
|
|
561
567
|
const memCopy = {};
|
|
@@ -566,7 +572,7 @@ export class KevOps {
|
|
|
566
572
|
}
|
|
567
573
|
// Add all sources
|
|
568
574
|
for (const source of this.sources) {
|
|
569
|
-
const sourceVars = this.getAllFromNamespace(source,
|
|
575
|
+
const sourceVars = this.getAllFromNamespace(source, "*");
|
|
570
576
|
if (Object.keys(sourceVars).length > 0) {
|
|
571
577
|
result[source] = sourceVars;
|
|
572
578
|
}
|
|
@@ -598,8 +604,8 @@ export class KevOps {
|
|
|
598
604
|
clear(...patterns) {
|
|
599
605
|
// Only allow memory clearing for safety
|
|
600
606
|
for (const pattern of patterns) {
|
|
601
|
-
if (pattern.includes(
|
|
602
|
-
panic(
|
|
607
|
+
if (pattern.includes(":")) {
|
|
608
|
+
panic("Clear() with namespace is dangerous! Use clearUnsafe() if you really need this.");
|
|
603
609
|
}
|
|
604
610
|
}
|
|
605
611
|
if (patterns.length === 0) {
|
|
@@ -628,17 +634,18 @@ export class KevOps {
|
|
|
628
634
|
continue;
|
|
629
635
|
}
|
|
630
636
|
switch (namespace) {
|
|
631
|
-
case
|
|
632
|
-
if (keyPattern ===
|
|
637
|
+
case "os": {
|
|
638
|
+
if (keyPattern === "*") {
|
|
633
639
|
panic('clearUnsafe("os:*") would destroy system! This is never allowed.');
|
|
634
640
|
}
|
|
635
|
-
const keys = this.keysFromNamespace(
|
|
641
|
+
const keys = this.keysFromNamespace("os", keyPattern);
|
|
636
642
|
for (const key of keys) {
|
|
637
643
|
runtime.deleteEnv(key);
|
|
638
644
|
}
|
|
639
645
|
break;
|
|
646
|
+
}
|
|
640
647
|
default:
|
|
641
|
-
panic(
|
|
648
|
+
panic("Clearing from files not yet implemented");
|
|
642
649
|
}
|
|
643
650
|
}
|
|
644
651
|
}
|
|
@@ -651,11 +658,11 @@ export class KevOps {
|
|
|
651
658
|
if (namespace) {
|
|
652
659
|
// Namespaced unset
|
|
653
660
|
switch (namespace) {
|
|
654
|
-
case
|
|
661
|
+
case "os":
|
|
655
662
|
runtime.deleteEnv(realKey);
|
|
656
663
|
break;
|
|
657
664
|
default:
|
|
658
|
-
panic(
|
|
665
|
+
panic("Unsetting from files not yet implemented");
|
|
659
666
|
}
|
|
660
667
|
}
|
|
661
668
|
else {
|
|
@@ -669,11 +676,11 @@ export class KevOps {
|
|
|
669
676
|
*/
|
|
670
677
|
int(key, defaultValue) {
|
|
671
678
|
const val = this.get(key);
|
|
672
|
-
if (val ===
|
|
679
|
+
if (val === "") {
|
|
673
680
|
return defaultValue;
|
|
674
681
|
}
|
|
675
682
|
const i = parseInt(val, 10);
|
|
676
|
-
if (isNaN(i)) {
|
|
683
|
+
if (Number.isNaN(i)) {
|
|
677
684
|
panic(`invalid int value for ${key}: ${val}`);
|
|
678
685
|
}
|
|
679
686
|
return i;
|
|
@@ -683,19 +690,19 @@ export class KevOps {
|
|
|
683
690
|
*/
|
|
684
691
|
bool(key, defaultValue) {
|
|
685
692
|
const val = this.get(key).toLowerCase();
|
|
686
|
-
if (val ===
|
|
693
|
+
if (val === "") {
|
|
687
694
|
return defaultValue;
|
|
688
695
|
}
|
|
689
696
|
switch (val) {
|
|
690
|
-
case
|
|
691
|
-
case
|
|
692
|
-
case
|
|
693
|
-
case
|
|
697
|
+
case "true":
|
|
698
|
+
case "1":
|
|
699
|
+
case "yes":
|
|
700
|
+
case "on":
|
|
694
701
|
return true;
|
|
695
|
-
case
|
|
696
|
-
case
|
|
697
|
-
case
|
|
698
|
-
case
|
|
702
|
+
case "false":
|
|
703
|
+
case "0":
|
|
704
|
+
case "no":
|
|
705
|
+
case "off":
|
|
699
706
|
return false;
|
|
700
707
|
default:
|
|
701
708
|
panic(`invalid bool value for ${key}: ${val}`);
|
|
@@ -706,11 +713,11 @@ export class KevOps {
|
|
|
706
713
|
*/
|
|
707
714
|
float(key, defaultValue) {
|
|
708
715
|
const val = this.get(key);
|
|
709
|
-
if (val ===
|
|
716
|
+
if (val === "") {
|
|
710
717
|
return defaultValue;
|
|
711
718
|
}
|
|
712
719
|
const f = parseFloat(val);
|
|
713
|
-
if (isNaN(f)) {
|
|
720
|
+
if (Number.isNaN(f)) {
|
|
714
721
|
panic(`invalid float value for ${key}: ${val}`);
|
|
715
722
|
}
|
|
716
723
|
return f;
|
|
@@ -723,13 +730,13 @@ export class KevOps {
|
|
|
723
730
|
for (const [key, entry] of this.memory) {
|
|
724
731
|
let val = entry.value;
|
|
725
732
|
// Escape values with spaces or special chars
|
|
726
|
-
if (val.includes(
|
|
733
|
+
if (val.includes(" ") || val.includes("\t") || val.includes("\n")) {
|
|
727
734
|
val = `"${val}"`;
|
|
728
735
|
}
|
|
729
736
|
// Add comment with source info
|
|
730
737
|
lines.push(`${key}=${val} # from: ${entry.source}`);
|
|
731
738
|
}
|
|
732
|
-
file.write(path, lines.join(
|
|
739
|
+
file.write(path, lines.join("\n"));
|
|
733
740
|
}
|
|
734
741
|
/**
|
|
735
742
|
* Print all environment variables (masks sensitive keys)
|
|
@@ -741,15 +748,15 @@ export class KevOps {
|
|
|
741
748
|
let maskedVal = val;
|
|
742
749
|
// Mask sensitive values
|
|
743
750
|
const lower = key.toLowerCase();
|
|
744
|
-
if (lower.includes(
|
|
745
|
-
lower.includes(
|
|
746
|
-
lower.includes(
|
|
747
|
-
lower.includes(
|
|
751
|
+
if (lower.includes("key") ||
|
|
752
|
+
lower.includes("secret") ||
|
|
753
|
+
lower.includes("password") ||
|
|
754
|
+
lower.includes("token")) {
|
|
748
755
|
if (val.length > 4) {
|
|
749
|
-
maskedVal = val.slice(0, 4)
|
|
756
|
+
maskedVal = `${val.slice(0, 4)}****`;
|
|
750
757
|
}
|
|
751
758
|
else {
|
|
752
|
-
maskedVal =
|
|
759
|
+
maskedVal = "****";
|
|
753
760
|
}
|
|
754
761
|
}
|
|
755
762
|
console.log(`${namespace}:${key}=${maskedVal}`);
|