kfg 1.0.0 → 1.1.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/index.cjs CHANGED
@@ -171,18 +171,9 @@ function buildTypeBoxSchema(definition) {
171
171
  return import_typebox.Type.Object(properties, { additionalProperties: true });
172
172
  }
173
173
  function buildDefaultObject(definition) {
174
- const obj = {};
175
- for (const key in definition) {
176
- const value = definition[key];
177
- if (value[Symbol.for("TypeBox.Kind")]) {
178
- if (value.default !== void 0) {
179
- obj[key] = value.default;
180
- }
181
- } else if (typeof value === "object" && value !== null) {
182
- obj[key] = buildDefaultObject(value);
183
- }
184
- }
185
- return obj;
174
+ const schema = buildTypeBoxSchema(definition);
175
+ addSmartDefaults(schema);
176
+ return import_value.Value.Default(schema, {});
186
177
  }
187
178
  function makeSchemaOptional(definition) {
188
179
  const newDefinition = {};
@@ -210,20 +201,30 @@ var Kfg = class {
210
201
  driver;
211
202
  schema;
212
203
  loaded = false;
204
+ _lastOptions;
213
205
  /**
214
206
  * Creates a new instance of Kfg.
215
207
  * @param driver The driver to use for loading and saving the configuration.
216
208
  * @param schema The schema to use for validating the configuration.
217
209
  */
218
210
  constructor(driver, schema) {
219
- this.driver = driver;
211
+ this.driver = driver.clone();
220
212
  this.schema = schema;
221
213
  }
214
+ /**
215
+ * Reloads the configuration.
216
+ * @param options - The loading options.
217
+ */
218
+ reload(options) {
219
+ this.loaded = false;
220
+ return this.load(options || this._lastOptions);
221
+ }
222
222
  /**
223
223
  * Loads the configuration.
224
224
  * @param options - The loading options.
225
225
  */
226
226
  load(options) {
227
+ this._lastOptions = options;
227
228
  let schemaToLoad = this.schema;
228
229
  if (options?.only_importants) {
229
230
  schemaToLoad = makeSchemaOptional(this.schema);
@@ -293,6 +294,16 @@ var Kfg = class {
293
294
  }
294
295
  return this.driver.insert(path3, partial);
295
296
  }
297
+ /**
298
+ * Injects a partial value directly into the root configuration object.
299
+ * @param data The partial data to inject.
300
+ */
301
+ inject(data) {
302
+ if (!this.loaded) {
303
+ throw new Error("[Kfg] Config not loaded. Call load() first.");
304
+ }
305
+ return this.driver.inject(data);
306
+ }
296
307
  /**
297
308
  * Deletes a value from the configuration.
298
309
  * @param path The path to the value.
@@ -314,6 +325,14 @@ var Kfg = class {
314
325
  }
315
326
  return getProperty(this.schema, path3);
316
327
  }
328
+ /**
329
+ * Returns the schema definition for a given path.
330
+ * @param path The path to the schema.
331
+ * @returns The schema at the given path.
332
+ */
333
+ schematic(path3) {
334
+ return this.conf(path3);
335
+ }
317
336
  /**
318
337
  * Returns cached data
319
338
  * @returns
@@ -534,6 +553,44 @@ var KfgFS = class {
534
553
  }
535
554
  return this.pathFn(id);
536
555
  }
556
+ /**
557
+ * Checks if a configuration file exists for a given ID.
558
+ * @param id The ID of the configuration file.
559
+ * @returns True if the file exists, false otherwise.
560
+ */
561
+ exist(id) {
562
+ const filePath = this.getPath(id);
563
+ return fs.existsSync(filePath);
564
+ }
565
+ /**
566
+ * Creates a new configuration file for a given ID.
567
+ * @param id The ID of the configuration file.
568
+ * @param data Optional initial data for the configuration.
569
+ * @returns The created KfgFileFS instance.
570
+ */
571
+ create(id, data) {
572
+ if (this.exist(id)) {
573
+ throw new Error(`[KfgFS] Config with id '${id}' already exists.`);
574
+ }
575
+ const instanceOrPromise = this.file(id);
576
+ const initialize = (instance) => {
577
+ if (data) {
578
+ instance.inject(data);
579
+ }
580
+ const saveResult = instance.save();
581
+ if (this.driver.async) {
582
+ return saveResult.then(() => instance);
583
+ }
584
+ return instance;
585
+ };
586
+ if (this.driver.async) {
587
+ return instanceOrPromise.then(
588
+ initialize
589
+ );
590
+ } else {
591
+ return initialize(instanceOrPromise);
592
+ }
593
+ }
537
594
  /**
538
595
  * Gets a file-based configuration for a given ID.
539
596
  * @param id The ID of the configuration file.
@@ -616,6 +673,23 @@ var KfgDriver = class {
616
673
  // Utilities passed to drivers
617
674
  buildDefaultObject = buildDefaultObject;
618
675
  deepMerge = deepMerge;
676
+ /**
677
+ * Clones the driver.
678
+ * @returns A new instance of the driver with the same options.
679
+ */
680
+ clone() {
681
+ const Constructor = this.constructor;
682
+ return new Constructor(this.options);
683
+ }
684
+ /**
685
+ * Injects data directly into the driver's data store.
686
+ * This data is merged with the existing data.
687
+ * @param data The data to inject.
688
+ */
689
+ inject(data) {
690
+ this.data = this.deepMerge(this.data, data);
691
+ return this.async ? Promise.resolve() : void 0;
692
+ }
619
693
  /**
620
694
  * Loads the configuration.
621
695
  * @param schema The schema to use for validating the configuration.
@@ -709,17 +783,17 @@ var KfgDriver = class {
709
783
  */
710
784
  validate(config = this.data) {
711
785
  if (!this.compiledSchema) return;
712
- this.data = import_value2.Value.Default(this.compiledSchema, {});
713
- import_value2.Value.Convert(this.compiledSchema, config);
714
- if (!import_value2.Value.Check(this.compiledSchema, config)) {
715
- const errors = [...import_value2.Value.Errors(this.compiledSchema, config)];
786
+ const configWithDefaults = import_value2.Value.Default(this.compiledSchema, config);
787
+ import_value2.Value.Convert(this.compiledSchema, configWithDefaults);
788
+ if (!import_value2.Value.Check(this.compiledSchema, configWithDefaults)) {
789
+ const errors = [...import_value2.Value.Errors(this.compiledSchema, configWithDefaults)];
716
790
  throw new Error(
717
791
  `[Kfg] Validation failed:
718
792
  ${errors.map((e) => `- ${e.path}: ${e.message}`).join("\n")}`
719
793
  // Corrected: escaped backtick in template literal
720
794
  );
721
795
  }
722
- this.data = config;
796
+ this.data = configWithDefaults;
723
797
  }
724
798
  };
725
799
 
package/dist/index.d.ts CHANGED
@@ -13,12 +13,20 @@ export declare class Kfg<D extends KfgDriver<any, any, any>, S extends SchemaDef
13
13
  driver: D;
14
14
  schema: S;
15
15
  private loaded;
16
+ private _lastOptions;
16
17
  /**
17
18
  * Creates a new instance of Kfg.
18
19
  * @param driver The driver to use for loading and saving the configuration.
19
20
  * @param schema The schema to use for validating the configuration.
20
21
  */
21
22
  constructor(driver: D, schema: S);
23
+ /**
24
+ * Reloads the configuration.
25
+ * @param options - The loading options.
26
+ */
27
+ reload(options?: Partial<D["config"]> & {
28
+ only_importants?: boolean;
29
+ }): inPromise<D["async"], void>;
22
30
  /**
23
31
  * Loads the configuration.
24
32
  * @param options - The loading options.
@@ -64,6 +72,11 @@ export declare class Kfg<D extends KfgDriver<any, any, any>, S extends SchemaDef
64
72
  * @param partial The partial value to insert.
65
73
  */
66
74
  insert<P extends RootPaths<StaticSchema<S>>>(path: P, partial: Partial<DeepGet<StaticSchema<S>, P>>): inPromise<D["async"], void>;
75
+ /**
76
+ * Injects a partial value directly into the root configuration object.
77
+ * @param data The partial data to inject.
78
+ */
79
+ inject(data: Partial<StaticSchema<S>>): inPromise<D["async"], void>;
67
80
  /**
68
81
  * Deletes a value from the configuration.
69
82
  * @param path The path to the value.
@@ -75,6 +88,12 @@ export declare class Kfg<D extends KfgDriver<any, any, any>, S extends SchemaDef
75
88
  * @returns The schema at the given path.
76
89
  */
77
90
  conf<P extends Paths<StaticSchema<S>>>(path: P): DeepGet<S, P>;
91
+ /**
92
+ * Returns the schema definition for a given path.
93
+ * @param path The path to the schema.
94
+ * @returns The schema at the given path.
95
+ */
96
+ schematic<P extends Paths<StaticSchema<S>>>(path: P): DeepGet<S, P>;
78
97
  /**
79
98
  * Returns cached data
80
99
  * @returns
@@ -106,6 +125,17 @@ export declare class KfgDriver<C extends DriverConfig, S extends DriverStore, As
106
125
  * @param options The driver options.
107
126
  */
108
127
  constructor(options: KfgDriverOptions<C, S, Async>);
128
+ /**
129
+ * Clones the driver.
130
+ * @returns A new instance of the driver with the same options.
131
+ */
132
+ clone(): KfgDriver<C, S, Async>;
133
+ /**
134
+ * Injects data directly into the driver's data store.
135
+ * This data is merged with the existing data.
136
+ * @param data The data to inject.
137
+ */
138
+ inject(data: Partial<StaticSchema<any>>): inPromise<Async, void>;
109
139
  /**
110
140
  * Loads the configuration.
111
141
  * @param schema The schema to use for validating the configuration.
@@ -192,6 +222,19 @@ export declare class KfgFS<D extends KfgDriver<any, any, any>, S extends SchemaD
192
222
  * @returns The file path.
193
223
  */
194
224
  private getPath;
225
+ /**
226
+ * Checks if a configuration file exists for a given ID.
227
+ * @param id The ID of the configuration file.
228
+ * @returns True if the file exists, false otherwise.
229
+ */
230
+ exist(id: string): boolean;
231
+ /**
232
+ * Creates a new configuration file for a given ID.
233
+ * @param id The ID of the configuration file.
234
+ * @param data Optional initial data for the configuration.
235
+ * @returns The created KfgFileFS instance.
236
+ */
237
+ create(id: string, data?: Partial<StaticSchema<S>>): inPromise<D["async"], KfgFileFS<D, S>>;
195
238
  /**
196
239
  * Gets a file-based configuration for a given ID.
197
240
  * @param id The ID of the configuration file.
package/dist/index.js CHANGED
@@ -122,18 +122,9 @@ function buildTypeBoxSchema(definition) {
122
122
  return Type.Object(properties, { additionalProperties: true });
123
123
  }
124
124
  function buildDefaultObject(definition) {
125
- const obj = {};
126
- for (const key in definition) {
127
- const value = definition[key];
128
- if (value[Symbol.for("TypeBox.Kind")]) {
129
- if (value.default !== void 0) {
130
- obj[key] = value.default;
131
- }
132
- } else if (typeof value === "object" && value !== null) {
133
- obj[key] = buildDefaultObject(value);
134
- }
135
- }
136
- return obj;
125
+ const schema = buildTypeBoxSchema(definition);
126
+ addSmartDefaults(schema);
127
+ return Value.Default(schema, {});
137
128
  }
138
129
  function makeSchemaOptional(definition) {
139
130
  const newDefinition = {};
@@ -161,20 +152,30 @@ var Kfg = class {
161
152
  driver;
162
153
  schema;
163
154
  loaded = false;
155
+ _lastOptions;
164
156
  /**
165
157
  * Creates a new instance of Kfg.
166
158
  * @param driver The driver to use for loading and saving the configuration.
167
159
  * @param schema The schema to use for validating the configuration.
168
160
  */
169
161
  constructor(driver, schema) {
170
- this.driver = driver;
162
+ this.driver = driver.clone();
171
163
  this.schema = schema;
172
164
  }
165
+ /**
166
+ * Reloads the configuration.
167
+ * @param options - The loading options.
168
+ */
169
+ reload(options) {
170
+ this.loaded = false;
171
+ return this.load(options || this._lastOptions);
172
+ }
173
173
  /**
174
174
  * Loads the configuration.
175
175
  * @param options - The loading options.
176
176
  */
177
177
  load(options) {
178
+ this._lastOptions = options;
178
179
  let schemaToLoad = this.schema;
179
180
  if (options?.only_importants) {
180
181
  schemaToLoad = makeSchemaOptional(this.schema);
@@ -244,6 +245,16 @@ var Kfg = class {
244
245
  }
245
246
  return this.driver.insert(path3, partial);
246
247
  }
248
+ /**
249
+ * Injects a partial value directly into the root configuration object.
250
+ * @param data The partial data to inject.
251
+ */
252
+ inject(data) {
253
+ if (!this.loaded) {
254
+ throw new Error("[Kfg] Config not loaded. Call load() first.");
255
+ }
256
+ return this.driver.inject(data);
257
+ }
247
258
  /**
248
259
  * Deletes a value from the configuration.
249
260
  * @param path The path to the value.
@@ -265,6 +276,14 @@ var Kfg = class {
265
276
  }
266
277
  return getProperty(this.schema, path3);
267
278
  }
279
+ /**
280
+ * Returns the schema definition for a given path.
281
+ * @param path The path to the schema.
282
+ * @returns The schema at the given path.
283
+ */
284
+ schematic(path3) {
285
+ return this.conf(path3);
286
+ }
268
287
  /**
269
288
  * Returns cached data
270
289
  * @returns
@@ -485,6 +504,44 @@ var KfgFS = class {
485
504
  }
486
505
  return this.pathFn(id);
487
506
  }
507
+ /**
508
+ * Checks if a configuration file exists for a given ID.
509
+ * @param id The ID of the configuration file.
510
+ * @returns True if the file exists, false otherwise.
511
+ */
512
+ exist(id) {
513
+ const filePath = this.getPath(id);
514
+ return fs.existsSync(filePath);
515
+ }
516
+ /**
517
+ * Creates a new configuration file for a given ID.
518
+ * @param id The ID of the configuration file.
519
+ * @param data Optional initial data for the configuration.
520
+ * @returns The created KfgFileFS instance.
521
+ */
522
+ create(id, data) {
523
+ if (this.exist(id)) {
524
+ throw new Error(`[KfgFS] Config with id '${id}' already exists.`);
525
+ }
526
+ const instanceOrPromise = this.file(id);
527
+ const initialize = (instance) => {
528
+ if (data) {
529
+ instance.inject(data);
530
+ }
531
+ const saveResult = instance.save();
532
+ if (this.driver.async) {
533
+ return saveResult.then(() => instance);
534
+ }
535
+ return instance;
536
+ };
537
+ if (this.driver.async) {
538
+ return instanceOrPromise.then(
539
+ initialize
540
+ );
541
+ } else {
542
+ return initialize(instanceOrPromise);
543
+ }
544
+ }
488
545
  /**
489
546
  * Gets a file-based configuration for a given ID.
490
547
  * @param id The ID of the configuration file.
@@ -567,6 +624,23 @@ var KfgDriver = class {
567
624
  // Utilities passed to drivers
568
625
  buildDefaultObject = buildDefaultObject;
569
626
  deepMerge = deepMerge;
627
+ /**
628
+ * Clones the driver.
629
+ * @returns A new instance of the driver with the same options.
630
+ */
631
+ clone() {
632
+ const Constructor = this.constructor;
633
+ return new Constructor(this.options);
634
+ }
635
+ /**
636
+ * Injects data directly into the driver's data store.
637
+ * This data is merged with the existing data.
638
+ * @param data The data to inject.
639
+ */
640
+ inject(data) {
641
+ this.data = this.deepMerge(this.data, data);
642
+ return this.async ? Promise.resolve() : void 0;
643
+ }
570
644
  /**
571
645
  * Loads the configuration.
572
646
  * @param schema The schema to use for validating the configuration.
@@ -660,17 +734,17 @@ var KfgDriver = class {
660
734
  */
661
735
  validate(config = this.data) {
662
736
  if (!this.compiledSchema) return;
663
- this.data = Value2.Default(this.compiledSchema, {});
664
- Value2.Convert(this.compiledSchema, config);
665
- if (!Value2.Check(this.compiledSchema, config)) {
666
- const errors = [...Value2.Errors(this.compiledSchema, config)];
737
+ const configWithDefaults = Value2.Default(this.compiledSchema, config);
738
+ Value2.Convert(this.compiledSchema, configWithDefaults);
739
+ if (!Value2.Check(this.compiledSchema, configWithDefaults)) {
740
+ const errors = [...Value2.Errors(this.compiledSchema, configWithDefaults)];
667
741
  throw new Error(
668
742
  `[Kfg] Validation failed:
669
743
  ${errors.map((e) => `- ${e.path}: ${e.message}`).join("\n")}`
670
744
  // Corrected: escaped backtick in template literal
671
745
  );
672
746
  }
673
- this.data = config;
747
+ this.data = configWithDefaults;
674
748
  }
675
749
  };
676
750
 
package/package.json CHANGED
@@ -2,13 +2,13 @@
2
2
  "name": "kfg",
3
3
  "type": "module",
4
4
  "description": "Simple system of standardization of configurations for node js and bun.",
5
- "version": "1.0.0",
5
+ "version": "1.1.0",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/drylian/kfg.git"
11
+ "url": "git+https://github.com/drysius/kfg.git"
12
12
  },
13
13
  "typesVersions": {
14
14
  "*": {
@@ -46,12 +46,12 @@
46
46
  "output",
47
47
  "performance"
48
48
  ],
49
- "author": "Drylian",
49
+ "author": "Drysius",
50
50
  "license": "MIT",
51
51
  "bugs": {
52
- "url": "https://github.com/drylian/kfg/issues"
52
+ "url": "https://github.com/drysius/kfg/issues"
53
53
  },
54
- "homepage": "https://github.com/drylian/kfg#readme",
54
+ "homepage": "https://kfg.js.org",
55
55
  "files": [
56
56
  "dist"
57
57
  ],
@@ -74,4 +74,4 @@
74
74
  "dependencies": {
75
75
  "@sinclair/typebox": "^0.34.41"
76
76
  }
77
- }
77
+ }