@cenk1cenk2/oclif-common 3.7.1 → 3.8.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.
@@ -77,8 +77,9 @@ var Logger = class {
77
77
  };
78
78
  if (Logger.instance) {
79
79
  this.logger = Logger.instance;
80
- } else {
80
+ } else if (context === ConfigService.name) {
81
81
  this.logger = this.initiateLogger();
82
+ this.trace("Logger singleton initiated from context: %s", context);
82
83
  Logger.instance = this.logger;
83
84
  }
84
85
  }
@@ -153,6 +154,11 @@ var Logger = class {
153
154
  return logger;
154
155
  }
155
156
  parseMessage(level, data, args, format2) {
157
+ if (!this.logger && !Logger.instance) {
158
+ return;
159
+ } else if (Logger.instance) {
160
+ this.logger = Logger.instance;
161
+ }
156
162
  this.logger.log(level, data.toString(), ...args ?? [], { context: this.context, ...format2 ?? {} });
157
163
  }
158
164
  logColoring({ level, message, context, status }) {
@@ -249,6 +255,42 @@ var CLI_FLAGS = {
249
255
  })
250
256
  };
251
257
 
258
+ // src/lib/parser/env-parser.service.ts
259
+ var import_os2 = require("os");
260
+ var _EnvironmentVariableParser = class {
261
+ constructor() {
262
+ this.LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/gm;
263
+ if (_EnvironmentVariableParser.instance) {
264
+ return _EnvironmentVariableParser.instance;
265
+ }
266
+ _EnvironmentVariableParser.instance = this;
267
+ this.logger = new Logger(this.constructor.name);
268
+ this.logger.trace("Created a new instance.");
269
+ }
270
+ parse(data) {
271
+ try {
272
+ return data.toString().split(import_os2.EOL).reduce((o, line) => {
273
+ const match = this.LINE.exec(line);
274
+ const key = match[1];
275
+ const value = match[2] ?? "";
276
+ return {
277
+ ...o,
278
+ [key]: value
279
+ };
280
+ }, {});
281
+ } catch (e) {
282
+ this.logger.trace("Error during parsing environment file: %s", e.message);
283
+ throw e;
284
+ }
285
+ }
286
+ stringify(data) {
287
+ return Object.entries(data).map(([k, v]) => `${k}=${v}`).join(import_os2.EOL) + import_os2.EOL;
288
+ }
289
+ };
290
+ var EnvironmentVariableParser = _EnvironmentVariableParser;
291
+ __name(EnvironmentVariableParser, "EnvironmentVariableParser");
292
+ EnvironmentVariableParser.extensions = ["env"];
293
+
252
294
  // src/lib/parser/json-parser.service.ts
253
295
  var _JsonParser = class {
254
296
  constructor() {
@@ -305,13 +347,354 @@ YamlParser.extensions = ["yaml", "yml"];
305
347
  // src/lib/fs/filesystem.service.ts
306
348
  var import_fs_extra = __toESM(require("fs-extra"));
307
349
  var import_path = require("path");
350
+ var FileSystemService = class {
351
+ constructor() {
352
+ if (FileSystemService.instance) {
353
+ return FileSystemService.instance;
354
+ } else {
355
+ FileSystemService.instance = this;
356
+ this.logger = new Logger(this.constructor.name);
357
+ this.logger.trace("Created a new instance.");
358
+ }
359
+ }
360
+ exists(path) {
361
+ return import_fs_extra.default.existsSync(path);
362
+ }
363
+ stats(path) {
364
+ return import_fs_extra.default.statSync(path, { throwIfNoEntry: true });
365
+ }
366
+ dirname(path) {
367
+ return (0, import_path.dirname)(path);
368
+ }
369
+ extname(path) {
370
+ return (0, import_path.extname)(path);
371
+ }
372
+ async read(file) {
373
+ try {
374
+ const raw = await import_fs_extra.default.readFile(file, "utf-8");
375
+ return raw;
376
+ } catch (e) {
377
+ throw new Error(`Error while reading file from "${file}": ${e.message}`);
378
+ }
379
+ }
380
+ readSync(file) {
381
+ try {
382
+ const raw = import_fs_extra.default.readFileSync(file, "utf-8");
383
+ return raw;
384
+ } catch (e) {
385
+ throw new Error(`Error while reading file from "${file}": ${e.message}`);
386
+ }
387
+ }
388
+ async write(file, data, options = {}) {
389
+ try {
390
+ await import_fs_extra.default.writeFile(file, data, { encoding: "utf-8", ...options });
391
+ } catch (e) {
392
+ throw new Error(`Error while writing file to "${file}": ${e.message}`);
393
+ }
394
+ }
395
+ writeSync(file, data, options = {}) {
396
+ try {
397
+ import_fs_extra.default.writeFileSync(file, data, { encoding: "utf-8", ...options });
398
+ } catch (e) {
399
+ throw new Error(`Error while writing file to "${file}": ${e.message}`);
400
+ }
401
+ }
402
+ async append(file, data, options) {
403
+ try {
404
+ await import_fs_extra.default.appendFile(file, data, options);
405
+ } catch (e) {
406
+ throw new Error(`Error while appending to file "${file}": ${e.message}`);
407
+ }
408
+ }
409
+ appendSync(file, data) {
410
+ try {
411
+ import_fs_extra.default.appendFileSync(file, data);
412
+ } catch (e) {
413
+ throw new Error(`Error while appending to file "${file}": ${e.message}`);
414
+ }
415
+ }
416
+ async remove(file, options) {
417
+ try {
418
+ await import_fs_extra.default.rm(file, options);
419
+ } catch (e) {
420
+ throw new Error(`Error while deleting the file "${file}": ${e.message}`);
421
+ }
422
+ }
423
+ removeSync(file, options) {
424
+ try {
425
+ import_fs_extra.default.rmSync(file, options);
426
+ } catch (e) {
427
+ throw new Error(`Error while deleting the file "${file}": ${e.message}`);
428
+ }
429
+ }
430
+ async emptyDir(directory) {
431
+ try {
432
+ await import_fs_extra.default.emptyDir(directory);
433
+ } catch (e) {
434
+ throw new Error(`Error while emptying the directory "${directory}": ${e.message}`);
435
+ }
436
+ }
437
+ emptyDirSync(directory) {
438
+ try {
439
+ import_fs_extra.default.emptyDirSync(directory);
440
+ } catch (e) {
441
+ throw new Error(`Error while emptying the directory "${directory}": ${e.message}`);
442
+ }
443
+ }
444
+ async removeDir(directory) {
445
+ try {
446
+ await import_fs_extra.default.rmdir(directory);
447
+ } catch (e) {
448
+ throw new Error(`Error while removing the directory "${directory}": ${e.message}`);
449
+ }
450
+ }
451
+ removeDirSync(directory) {
452
+ try {
453
+ import_fs_extra.default.rmdirSync(directory);
454
+ } catch (e) {
455
+ throw new Error(`Error while removing the directory "${directory}": ${e.message}`);
456
+ }
457
+ }
458
+ async mkdir(directory) {
459
+ try {
460
+ await import_fs_extra.default.mkdirp(directory);
461
+ } catch (e) {
462
+ throw new Error(`Error while creating the directory "${directory}": ${e.message}`);
463
+ }
464
+ }
465
+ mkdirSync(directory) {
466
+ try {
467
+ import_fs_extra.default.mkdirSync(directory);
468
+ } catch (e) {
469
+ throw new Error(`Error while creating the directory "${directory}": ${e.message}`);
470
+ }
471
+ }
472
+ };
473
+ __name(FileSystemService, "FileSystemService");
474
+
475
+ // src/lib/parser/parser.service.ts
476
+ var ParserService = class {
477
+ constructor(parsers) {
478
+ this.parsers = [YamlParser, JsonParser, EnvironmentVariableParser];
479
+ if (ParserService.instance) {
480
+ return ParserService.instance;
481
+ } else {
482
+ if (parsers) {
483
+ this.parsers = parsers;
484
+ }
485
+ this.logger = new Logger(this.constructor.name);
486
+ this.fs = new FileSystemService();
487
+ ParserService.instance = this;
488
+ this.logger.trace("Created a new instance.");
489
+ }
490
+ }
491
+ getParser(file) {
492
+ const ext = (file.includes(".") ? this.fs.extname(file) : file).replace(/^\./, "");
493
+ const Parser = this.parsers.find((parser) => parser.extensions.includes(ext));
494
+ if (!Parser) {
495
+ throw new Error(`Parser for the extension is not configured: ${ext}`);
496
+ }
497
+ return new Parser();
498
+ }
499
+ setParsers(...parsers) {
500
+ this.parsers = parsers;
501
+ this.logger.trace(
502
+ "Set parsers: %s",
503
+ this.parsers.map((p) => p.name)
504
+ );
505
+ }
506
+ addParsers(...parsers) {
507
+ this.parsers.push(...parsers);
508
+ this.logger.trace(
509
+ "Added parser, current parsers: %s",
510
+ this.parsers.map((p) => p.name)
511
+ );
512
+ }
513
+ async read(file) {
514
+ return this.parse(file, await this.fs.read(file));
515
+ }
516
+ async write(file, data) {
517
+ return this.fs.write(file, await this.stringify(file, data));
518
+ }
519
+ parse(file, data) {
520
+ const parser = this.getParser(file);
521
+ this.logger.trace("Parsing file: %s -> %s", file, parser.constructor.name);
522
+ return parser.parse(data);
523
+ }
524
+ stringify(file, data) {
525
+ const parser = this.getParser(file);
526
+ this.logger.trace("Stringifying file: %s -> %s", file, parser.constructor.name);
527
+ return parser.stringify(data);
528
+ }
529
+ };
530
+ __name(ParserService, "ParserService");
531
+
532
+ // src/utils/environment.ts
533
+ function isVerbose(logLevel) {
534
+ return logLevel === "VERBOSE" /* VERBOSE */;
535
+ }
536
+ __name(isVerbose, "isVerbose");
537
+ function isDebug(logLevel) {
538
+ return ["DEBUG" /* DEBUG */, "TRACE" /* TRACE */].includes(logLevel);
539
+ }
540
+ __name(isDebug, "isDebug");
541
+ function isSilent(logLevel) {
542
+ return logLevel === "SILENT" /* SILENT */;
543
+ }
544
+ __name(isSilent, "isSilent");
308
545
 
309
546
  // src/utils/merge.ts
310
547
  var import_deepmerge = __toESM(require("deepmerge"));
548
+ function merge(strategy, ...source) {
549
+ return import_deepmerge.default.all(source, {
550
+ arrayMerge: strategy === "EXTEND" /* EXTEND */ ? (dest, src) => [...dest, ...src].filter(uniqueFilter) : (_, src) => src
551
+ });
552
+ }
553
+ __name(merge, "merge");
554
+ function uniqueFilter(value, index, self) {
555
+ return self.indexOf(value) === index;
556
+ }
557
+ __name(uniqueFilter, "uniqueFilter");
311
558
 
312
559
  // src/utils/index.ts
313
560
  var import_core2 = require("@oclif/core");
314
561
 
562
+ // src/lib/config/config.service.ts
563
+ var ConfigService = class {
564
+ constructor(oclif, command, config) {
565
+ this.oclif = oclif;
566
+ this.command = command;
567
+ if (ConfigService.instance) {
568
+ Object.assign(ConfigService.instance, config);
569
+ return ConfigService.instance;
570
+ } else {
571
+ ConfigService.instance = this;
572
+ }
573
+ this.root = this.oclif.root;
574
+ this.defaults = (0, import_path2.join)(this.oclif.root, "config" /* CONFIG_SERVICE_DEFAULTS_DIR */);
575
+ this.logger = new Logger(this.constructor.name, { level: config.logLevel });
576
+ this.parser = new ParserService();
577
+ Object.assign(ConfigService.instance, config);
578
+ this.recalculate();
579
+ this.logger.trace("Created a new instance.");
580
+ }
581
+ async read(path) {
582
+ const config = await this.parser.read(path);
583
+ this.logger.trace("Read config from: %s", path);
584
+ return config;
585
+ }
586
+ async extend(paths, strategy = "OVERWRITE" /* OVERWRITE */) {
587
+ this.logger.trace("Will generate config from: %o with %s", paths, strategy);
588
+ const configs = (await Promise.all(
589
+ paths.map(async (path) => {
590
+ try {
591
+ const config = typeof path === "string" ? await this.parser.read(path) : path;
592
+ this.logger.trace("Extending config from: %s", path);
593
+ return config;
594
+ } catch (e) {
595
+ this.logger.trace("Failed to extend config from: %s", e.message);
596
+ }
597
+ })
598
+ )).filter(Boolean);
599
+ return this.merge(configs, strategy);
600
+ }
601
+ merge(configs, strategy = "OVERWRITE" /* OVERWRITE */) {
602
+ if (configs.length === 0) {
603
+ throw new Error("Nothing to merge, configuration files are empty.");
604
+ }
605
+ return merge(strategy, ...configs);
606
+ }
607
+ async env(definition, config) {
608
+ const env = typeof definition === "string" ? await this.parser.read(definition) : definition;
609
+ this.logger.trace("Environment variable extensions read: %o", definition);
610
+ const iter = /* @__PURE__ */ __name(async (obj, parent) => {
611
+ const data = await Promise.all(
612
+ Object.entries(obj).map(async ([key, value]) => {
613
+ const location = [...parent ?? [], key];
614
+ if (typeof value === "string") {
615
+ return [{ key: location, env: value }];
616
+ } else if (typeof value === "object") {
617
+ let extensions;
618
+ if ("__element" /* ELEMENT */ in value) {
619
+ extensions = await iter(value["__element" /* ELEMENT */], [...location, "__element" /* ELEMENT */]);
620
+ this.logger.trace("Expanding location to elements: %s -> %s", location, extensions.map((extension) => extension.key.join(".")).join(", "));
621
+ }
622
+ if ("__name" /* NAME */ in value && "__format" /* PARSER */ in value) {
623
+ const variable = [
624
+ {
625
+ key: location,
626
+ env: value["__name" /* NAME */],
627
+ parser: value["__format" /* PARSER */],
628
+ extensions
629
+ }
630
+ ];
631
+ return variable;
632
+ } else {
633
+ return iter(value, location);
634
+ }
635
+ }
636
+ })
637
+ );
638
+ return data.flatMap((d) => d).filter(Boolean);
639
+ }, "iter");
640
+ const parsed = await iter(env);
641
+ const cb = /* @__PURE__ */ __name((config2, variable, data) => {
642
+ if (variable.parser) {
643
+ try {
644
+ data = this.parser.parse(variable.parser, data);
645
+ } catch (e) {
646
+ this.logger.trace("Can not parse environment environment variable for config: %s -> %s with %s", variable.key.join("."), variable.env, variable.parser);
647
+ throw e;
648
+ }
649
+ }
650
+ this.logger.trace("Overwriting config with environment variable: %s -> %s", variable.key.join("."), variable.env);
651
+ return import_object_path_immutable.default.set(config2, variable.key, data);
652
+ }, "cb");
653
+ parsed.forEach((variable) => {
654
+ let data;
655
+ data = process.env[variable.env];
656
+ if (data) {
657
+ config = cb(config, variable, data);
658
+ }
659
+ if (variable.extensions && variable.extensions.length > 0) {
660
+ const timeout = 6e4;
661
+ const startedAt = Date.now();
662
+ for (let i = 0; i < Infinity; i++) {
663
+ if (Date.now() - startedAt > timeout) {
664
+ throw new Error(`Timed-out in ${timeout}ms while looking for element environment variables.`);
665
+ }
666
+ const extensions = variable.extensions.map((extension) => {
667
+ const clone = JSON.parse(JSON.stringify(extension));
668
+ clone.env = clone.env.replace("${i}" /* ELEMENT_REPLACER */, i.toString());
669
+ clone.key[clone.key.findIndex((value) => value === "__element" /* ELEMENT */)] = i.toString();
670
+ data = process.env[clone.env];
671
+ if (!data) {
672
+ this.logger.trace("No extension for environment variable: %s -> %s", clone.key.join("."), clone.env);
673
+ return;
674
+ }
675
+ config = cb(config, clone, data);
676
+ return true;
677
+ }).filter(Boolean);
678
+ if (extensions.length === 0) {
679
+ this.logger.trace("No more extensions for environment variables: %s -> %d", variable.key.join("."), i);
680
+ break;
681
+ }
682
+ }
683
+ }
684
+ });
685
+ return config;
686
+ }
687
+ async write(path, data) {
688
+ return this.parser.write(path, data);
689
+ }
690
+ recalculate() {
691
+ this.isVerbose = isVerbose(this.logLevel);
692
+ this.isDebug = isDebug(this.logLevel);
693
+ this.isSilent = isSilent(this.logLevel);
694
+ }
695
+ };
696
+ __name(ConfigService, "ConfigService");
697
+
315
698
  // src/lib/locker/locker.service.ts
316
699
  var import_object_path_immutable2 = __toESM(require("object-path-immutable"));
317
700
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Command as Command$1, Config, CliUx } from '@oclif/core';
1
+ import { Command as Command$1, CliUx } from '@oclif/core';
2
2
  export { CliUx, Flags } from '@oclif/core';
3
3
  import { Logger as Logger$2, ListrTaskWrapper, ListrContext, Manager, PromptOptions } from 'listr2';
4
4
  import { Logger as Logger$1, LeveledLogMethod } from 'winston';
@@ -61,7 +61,7 @@ declare type Winston = Logger$1 & Record<keyof typeof LogLevels, LeveledLogMetho
61
61
  declare class Logger {
62
62
  private context?;
63
63
  private options?;
64
- private static instance;
64
+ static instance: Winston;
65
65
  private logger;
66
66
  constructor(context?: string, options?: LoggerOptions);
67
67
  log(level: LogLevels, data: string | Buffer, ...args: any): void;
@@ -144,7 +144,8 @@ declare enum MergeStrategy {
144
144
 
145
145
  /** Merge objects deep from overwriting the properties from source to target.
146
146
  * Does not mutate the object */
147
- declare function merge<T extends Record<PropertyKey, any> | any[]>(strategy: MergeStrategy, target: T, ...source: Partial<T>[]): T;
147
+ declare function merge<T extends Record<PropertyKey, any> | any[]>(strategy: MergeStrategy, ...source: Partial<T>[]): T;
148
+ declare function uniqueFilter(value: any, index: any, self: string | any[]): boolean;
148
149
 
149
150
  declare type SetCtxDefaultsOptions<T extends ListrContext = ListrContext> = Partial<T>;
150
151
  interface SetCtxAssignOptions<K = Record<PropertyKey, any>> {
@@ -155,7 +156,7 @@ declare function setCtxDefaults<T extends ListrContext = ListrContext>(ctx: T, .
155
156
  declare function setCtxAssign<T extends ListrContext = ListrContext, K = Record<PropertyKey, any>>(ctx: T, ...assigns: SetCtxAssignOptions<K>[]): void;
156
157
 
157
158
  interface CommonLockerData {
158
- path: string | string[];
159
+ path?: string | string[];
159
160
  enabled?: boolean;
160
161
  root?: boolean;
161
162
  }
@@ -165,6 +166,7 @@ interface LockData<T extends LockableData = LockableData> extends Partial<Common
165
166
  merge?: MergeStrategy;
166
167
  }
167
168
  interface UnlockData extends CommonLockerData {
169
+ path: string | string[];
168
170
  }
169
171
 
170
172
  declare class GenericParser {
@@ -175,13 +177,13 @@ declare class GenericParser {
175
177
 
176
178
  declare class LockerService<LockFile extends LockableData = LockableData> {
177
179
  private file;
178
- private parser;
180
+ private parser?;
179
181
  private root?;
180
182
  private toLock;
181
183
  private toUnlock;
182
184
  private logger;
183
185
  private fs;
184
- constructor(file: string, parser: GenericParser, root?: string, context?: string);
186
+ constructor(file: string, parser?: GenericParser, root?: string[], context?: string);
185
187
  hasLock(): boolean;
186
188
  hasUnlock(): boolean;
187
189
  addLock<T extends LockableData = LockableData>(...data: LockData<T>[]): void;
@@ -254,10 +256,22 @@ declare class FileSystemService {
254
256
  removeSync(file: string, options?: fs.RmOptions): void;
255
257
  emptyDir(directory: string): Promise<void>;
256
258
  emptyDirSync(directory: string): void;
259
+ removeDir(directory: string): Promise<void>;
260
+ removeDirSync(directory: string): void;
257
261
  mkdir(directory: string): Promise<void>;
258
262
  mkdirSync(directory: string): void;
259
263
  }
260
264
 
265
+ declare class EnvironmentVariableParser implements GenericParser {
266
+ static extensions: string[];
267
+ private static instance;
268
+ private logger;
269
+ private LINE;
270
+ constructor();
271
+ parse<T = unknown>(data: string | Buffer): T;
272
+ stringify<T = any>(data: T): string;
273
+ }
274
+
261
275
  declare class YamlParser implements GenericParser {
262
276
  static extensions: string[];
263
277
  private static instance;
@@ -310,8 +324,6 @@ declare type DeepPartial<T> = {
310
324
  };
311
325
 
312
326
  declare class Command<Ctx extends ListrContext = ListrContext, Flags extends Record<PropertyKey, any> = InferFlags<typeof Command>, Args extends Record<PropertyKey, any> = InferArgs<typeof Command>, Store extends Record<PropertyKey, any> = Record<PropertyKey, any>> extends Command$1 {
313
- argv: string[];
314
- config: Config;
315
327
  static get globalFlags(): FlagInput;
316
328
  static set globalFlags(flags: FlagInput);
317
329
  logger: Logger;
@@ -323,7 +335,6 @@ declare class Command<Ctx extends ListrContext = ListrContext, Flags extends Rec
323
335
  store: StoreService<Store>;
324
336
  flags: Flags;
325
337
  args: Args;
326
- constructor(argv: string[], config: Config);
327
338
  /**
328
339
  * Construct the class if you dont want to extend init or constructor.
329
340
  */
@@ -348,7 +359,7 @@ declare class Command<Ctx extends ListrContext = ListrContext, Flags extends Rec
348
359
  ctx: C;
349
360
  }>;
350
361
  /** Catch any error occurred during command. */
351
- protected catch(e: Error): Promise<void>;
362
+ protected catch(e: Error, exit?: number): Promise<void>;
352
363
  private greet;
353
364
  }
354
365
 
@@ -398,4 +409,4 @@ declare enum HelpGroups {
398
409
  CLI = "CLI"
399
410
  }
400
411
 
401
- export { CLI_FLAGS, ClassType, Command, CommonLockerData, ConfigCommand, ConfigCommandChoices, ConfigCommandSetup, ConfigIterator, ConfigService, DeepPartial, FileConstants, FileSystemService, GenericParser, GlobalConfig, GlobalConfigInit, HelpGroups, InferArgs, InferFlags, JsonParser, ListrLogger, LockData, LockableData, LockerService, LogFieldStatus, LogLevels, Logger, LoggerFormat, LoggerOptions, MergeStrategy, ParserService, PipeProcessToLoggerOptions, SetCtxAssignOptions, SetCtxDefaultsOptions, UnlockData, ValidatorService, ValidatorServiceOptions, Winston, YamlParser, color, isDebug, isSilent, isVerbose, merge, pipeProcessThroughListr, pipeProcessToLogger, setCtxAssign, setCtxDefaults, setup };
412
+ export { CLI_FLAGS, ClassType, Command, CommonLockerData, ConfigCommand, ConfigCommandChoices, ConfigCommandSetup, ConfigIterator, ConfigService, DeepPartial, EnvironmentVariableParser, FileConstants, FileSystemService, GenericParser, GlobalConfig, GlobalConfigInit, HelpGroups, InferArgs, InferFlags, JsonParser, ListrLogger, LockData, LockableData, LockerService, LogFieldStatus, LogLevels, Logger, LoggerFormat, LoggerOptions, MergeStrategy, ParserService, PipeProcessToLoggerOptions, SetCtxAssignOptions, SetCtxDefaultsOptions, UnlockData, ValidatorService, ValidatorServiceOptions, Winston, YamlParser, color, isDebug, isSilent, isVerbose, merge, pipeProcessThroughListr, pipeProcessToLogger, setCtxAssign, setCtxDefaults, setup, uniqueFilter };