tauri-plugin-configurate-api 0.1.0 → 0.2.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/README.md +410 -351
- package/dist-js/index.cjs +65 -20
- package/dist-js/index.d.ts +103 -32
- package/dist-js/index.js +65 -20
- package/package.json +60 -60
package/dist-js/index.cjs
CHANGED
|
@@ -243,7 +243,7 @@ class LazyConfigEntry {
|
|
|
243
243
|
* });
|
|
244
244
|
*
|
|
245
245
|
* const config = new Configurate(schema, {
|
|
246
|
-
*
|
|
246
|
+
* name: "app-config.json",
|
|
247
247
|
* dir: BaseDirectory.AppConfig,
|
|
248
248
|
* format: "json",
|
|
249
249
|
* });
|
|
@@ -275,6 +275,27 @@ class Configurate {
|
|
|
275
275
|
throw new Error(`encryptionKey is only supported with format "binary", got "${opts.format}". ` +
|
|
276
276
|
`Remove encryptionKey or change format to "binary".`);
|
|
277
277
|
}
|
|
278
|
+
if (!opts.name) {
|
|
279
|
+
throw new Error('Configurate: "name" must not be empty.');
|
|
280
|
+
}
|
|
281
|
+
if (opts.name.includes("/") || opts.name.includes("\\")) {
|
|
282
|
+
throw new Error('Configurate: "name" must be a single filename and cannot contain path separators.');
|
|
283
|
+
}
|
|
284
|
+
if (opts.name === "." || opts.name === "..") {
|
|
285
|
+
throw new Error('Configurate: "name" must not be "." or "..".');
|
|
286
|
+
}
|
|
287
|
+
if (opts.dirName !== undefined) {
|
|
288
|
+
const dirNameSegments = opts.dirName.split(/[/\\]/);
|
|
289
|
+
if (dirNameSegments.some((seg) => seg === "" || seg === "." || seg === "..")) {
|
|
290
|
+
throw new Error('Configurate: "dirName" must not contain empty or special segments.');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
if (opts.path !== undefined) {
|
|
294
|
+
const pathSegments = opts.path.split(/[/\\]/);
|
|
295
|
+
if (pathSegments.some((seg) => seg === "" || seg === "." || seg === "..")) {
|
|
296
|
+
throw new Error('Configurate: "path" must not contain empty or special segments.');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
278
299
|
this._schema = schema;
|
|
279
300
|
this._opts = opts;
|
|
280
301
|
this._keyringPaths = collectKeyringPaths(this._schema);
|
|
@@ -367,13 +388,16 @@ class Configurate {
|
|
|
367
388
|
/** @internal */
|
|
368
389
|
_buildPayload(op, data, keyringOpts, withUnlock) {
|
|
369
390
|
const base = {
|
|
370
|
-
|
|
391
|
+
name: this._opts.name,
|
|
371
392
|
dir: this._opts.dir,
|
|
372
393
|
format: this._opts.format,
|
|
373
394
|
withUnlock,
|
|
374
395
|
};
|
|
375
|
-
if (this._opts.
|
|
376
|
-
base.
|
|
396
|
+
if (this._opts.dirName !== undefined) {
|
|
397
|
+
base.dirName = this._opts.dirName;
|
|
398
|
+
}
|
|
399
|
+
if (this._opts.path !== undefined) {
|
|
400
|
+
base.path = this._opts.path;
|
|
377
401
|
}
|
|
378
402
|
if (this._opts.encryptionKey) {
|
|
379
403
|
base.encryptionKey = this._opts.encryptionKey;
|
|
@@ -403,10 +427,10 @@ class Configurate {
|
|
|
403
427
|
}
|
|
404
428
|
/**
|
|
405
429
|
* A factory that creates `Configurate` instances with pre-set shared options
|
|
406
|
-
* (`dir`, `format`, and optionally `encryptionKey`).
|
|
430
|
+
* (`dir`, `format`, and optionally `dirName`, `path`, `encryptionKey`).
|
|
407
431
|
*
|
|
408
432
|
* Each call to `build()` creates a fresh `Configurate` instance — schema,
|
|
409
|
-
* `
|
|
433
|
+
* `name`, and all other options can differ freely. This is the recommended
|
|
410
434
|
* way to manage multiple config files with different schemas in a single
|
|
411
435
|
* application.
|
|
412
436
|
*
|
|
@@ -423,9 +447,11 @@ class Configurate {
|
|
|
423
447
|
* format: "json",
|
|
424
448
|
* });
|
|
425
449
|
*
|
|
426
|
-
* const appConfig = factory.build(appSchema, "app");
|
|
427
|
-
* const cacheConfig = factory.build(cacheSchema, "cache");
|
|
428
|
-
* const
|
|
450
|
+
* const appConfig = factory.build(appSchema, "app.json"); // → app.json
|
|
451
|
+
* const cacheConfig = factory.build(cacheSchema, "cache.json"); // → cache.json
|
|
452
|
+
* const nestedConfig = factory.build(appSchema, { name: "app.json", path: "config" }); // → config/app.json
|
|
453
|
+
* const movedConfig = factory.build(appSchema, { name: "app.json", dirName: "my-app" }); // → %APPDATA%/my-app/app.json
|
|
454
|
+
* const fullConfig = factory.build(appSchema, { name: "app.json", dirName: "my-app", path: "cfg" }); // → %APPDATA%/my-app/cfg/app.json
|
|
429
455
|
* ```
|
|
430
456
|
*/
|
|
431
457
|
class ConfigurateFactory {
|
|
@@ -433,18 +459,37 @@ class ConfigurateFactory {
|
|
|
433
459
|
constructor(_baseOpts) {
|
|
434
460
|
this._baseOpts = _baseOpts;
|
|
435
461
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
462
|
+
build(schema, nameOrConfig, dirName) {
|
|
463
|
+
let fileName;
|
|
464
|
+
let resolvedDirName;
|
|
465
|
+
let resolvedPath;
|
|
466
|
+
if (typeof nameOrConfig === "string") {
|
|
467
|
+
fileName = nameOrConfig;
|
|
468
|
+
// The explicit `dirName` argument overrides the factory-level dirName;
|
|
469
|
+
// fall back to the factory-level dirName when omitted.
|
|
470
|
+
resolvedDirName = dirName ?? this._baseOpts.dirName;
|
|
471
|
+
resolvedPath = this._baseOpts.path;
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
fileName = nameOrConfig.name;
|
|
475
|
+
// Object form: fields inside take precedence over factory-level values.
|
|
476
|
+
// Pass `null` to explicitly disable the factory-level value;
|
|
477
|
+
// `undefined` (or omitted) falls back to the factory-level value.
|
|
478
|
+
resolvedDirName =
|
|
479
|
+
nameOrConfig.dirName === null
|
|
480
|
+
? undefined
|
|
481
|
+
: (nameOrConfig.dirName ?? this._baseOpts.dirName);
|
|
482
|
+
resolvedPath =
|
|
483
|
+
nameOrConfig.path === null
|
|
484
|
+
? undefined
|
|
485
|
+
: (nameOrConfig.path ?? this._baseOpts.path);
|
|
447
486
|
}
|
|
487
|
+
const opts = {
|
|
488
|
+
...this._baseOpts,
|
|
489
|
+
name: fileName,
|
|
490
|
+
dirName: resolvedDirName,
|
|
491
|
+
path: resolvedPath,
|
|
492
|
+
};
|
|
448
493
|
// Explicitly pass <S> to prevent TypeScript from re-inferring the type
|
|
449
494
|
// parameter from the argument and double-evaluating HasDuplicateKeyringIds
|
|
450
495
|
// on the already-constrained type. The duplicate-id guarantee was already
|
package/dist-js/index.d.ts
CHANGED
|
@@ -166,33 +166,49 @@ export declare class LazyConfigEntry<S extends SchemaObject> {
|
|
|
166
166
|
*/
|
|
167
167
|
unlock(opts: KeyringOptions): Promise<UnlockedConfig<S>>;
|
|
168
168
|
}
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Base options shared across all configs created by a `ConfigurateFactory`.
|
|
171
|
+
* `name` is omitted because each config provides its own filename.
|
|
172
|
+
*
|
|
173
|
+
* `dirName` replaces the app identifier component of the base path.
|
|
174
|
+
* `path` adds a sub-directory within the root (after `dirName` / identifier).
|
|
175
|
+
*/
|
|
176
|
+
export interface ConfigurateBaseOptions {
|
|
173
177
|
/** Base directory in which the configuration file will be stored. */
|
|
174
178
|
dir: BaseDirectory;
|
|
175
179
|
/**
|
|
176
|
-
* Optional
|
|
180
|
+
* Optional replacement for the app identifier directory.
|
|
181
|
+
*
|
|
182
|
+
* When provided, **replaces** the identifier component of the resolved base path.
|
|
183
|
+
* For example, with `BaseDirectory.AppConfig` on Windows:
|
|
184
|
+
*
|
|
185
|
+
* | `dirName` | Resolved root |
|
|
186
|
+
* | ------------ | ------------------------------------ |
|
|
187
|
+
* | _(omitted)_ | `%APPDATA%/com.example.app/` |
|
|
188
|
+
* | `"my-app"` | `%APPDATA%/my-app/` |
|
|
189
|
+
* | `"org/app"` | `%APPDATA%/org/app/` |
|
|
190
|
+
*
|
|
191
|
+
* Each segment is validated on the Rust side; `..` and Windows-forbidden
|
|
192
|
+
* characters are rejected.
|
|
193
|
+
*/
|
|
194
|
+
dirName?: string;
|
|
195
|
+
/**
|
|
196
|
+
* Optional sub-directory within the root (after `dirName` / identifier is applied).
|
|
177
197
|
*
|
|
178
|
-
* Use forward slashes
|
|
198
|
+
* Use forward slashes to create nested directories (e.g. `"config/v2"`).
|
|
179
199
|
* Each segment is validated on the Rust side; `..` and Windows-forbidden
|
|
180
200
|
* characters are rejected.
|
|
181
201
|
*
|
|
182
|
-
*
|
|
202
|
+
* ### Path layout
|
|
183
203
|
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
* format: "json",
|
|
191
|
-
* subDir: "my-app",
|
|
192
|
-
* });
|
|
193
|
-
* ```
|
|
204
|
+
* | `dirName` | `path` | Resolved path (AppConfig, identifier `com.example.app`) |
|
|
205
|
+
* | ----------- | ----------- | --------------------------------------------------------- |
|
|
206
|
+
* | _(omitted)_ | _(omitted)_ | `%APPDATA%/com.example.app/<name>` |
|
|
207
|
+
* | `"my-app"` | _(omitted)_ | `%APPDATA%/my-app/<name>` |
|
|
208
|
+
* | _(omitted)_ | `"cfg/v2"` | `%APPDATA%/com.example.app/cfg/v2/<name>` |
|
|
209
|
+
* | `"my-app"` | `"cfg/v2"` | `%APPDATA%/my-app/cfg/v2/<name>` |
|
|
194
210
|
*/
|
|
195
|
-
|
|
211
|
+
path?: string;
|
|
196
212
|
/** On-disk storage format. */
|
|
197
213
|
format: StorageFormat;
|
|
198
214
|
/**
|
|
@@ -208,6 +224,18 @@ export interface ConfigurateOptions {
|
|
|
208
224
|
*/
|
|
209
225
|
encryptionKey?: string;
|
|
210
226
|
}
|
|
227
|
+
/** Options passed to the `Configurate` constructor. */
|
|
228
|
+
export interface ConfigurateOptions extends ConfigurateBaseOptions {
|
|
229
|
+
/**
|
|
230
|
+
* Full filename for the configuration file, including extension.
|
|
231
|
+
*
|
|
232
|
+
* Examples: `"app.json"`, `"data.yaml"`, `"settings.binc"`, `".env"`.
|
|
233
|
+
*
|
|
234
|
+
* Must be a single path component — path separators (`/`, `\`) are rejected
|
|
235
|
+
* by the Rust side. Use the `path` option to store files in a sub-directory.
|
|
236
|
+
*/
|
|
237
|
+
name: string;
|
|
238
|
+
}
|
|
211
239
|
/**
|
|
212
240
|
* Main entry point for managing application configuration.
|
|
213
241
|
*
|
|
@@ -222,7 +250,7 @@ export interface ConfigurateOptions {
|
|
|
222
250
|
* });
|
|
223
251
|
*
|
|
224
252
|
* const config = new Configurate(schema, {
|
|
225
|
-
*
|
|
253
|
+
* name: "app-config.json",
|
|
226
254
|
* dir: BaseDirectory.AppConfig,
|
|
227
255
|
* format: "json",
|
|
228
256
|
* });
|
|
@@ -292,16 +320,26 @@ export declare class Configurate<S extends SchemaObject> {
|
|
|
292
320
|
_buildPayload(op: "create" | "load" | "save", data: InferUnlocked<S> | undefined, keyringOpts: KeyringOptions | null, withUnlock: boolean): Record<string, unknown>;
|
|
293
321
|
}
|
|
294
322
|
/**
|
|
295
|
-
*
|
|
296
|
-
*
|
|
323
|
+
* Object form accepted by `ConfigurateFactory.build()` as the second argument.
|
|
324
|
+
*
|
|
325
|
+
* - `name` — filename (may include a relative path, e.g. `"config/state.bin"`)
|
|
326
|
+
* - `path` — sub-directory appended after the root / `dirName`; `null` disables the factory-level value
|
|
327
|
+
* - `dirName` — replaces the app identifier segment; `null` disables the factory-level value
|
|
297
328
|
*/
|
|
298
|
-
export
|
|
329
|
+
export interface BuildConfig {
|
|
330
|
+
/** Filename including extension. May contain `/`-separated path segments (e.g. `"config/state.bin"`). */
|
|
331
|
+
name: string;
|
|
332
|
+
/** Optional sub-directory within the root. Pass `null` to disable the factory-level value. */
|
|
333
|
+
path?: string | null;
|
|
334
|
+
/** Optional replacement for the app identifier directory. Pass `null` to disable the factory-level value. */
|
|
335
|
+
dirName?: string | null;
|
|
336
|
+
}
|
|
299
337
|
/**
|
|
300
338
|
* A factory that creates `Configurate` instances with pre-set shared options
|
|
301
|
-
* (`dir`, `format`, and optionally `encryptionKey`).
|
|
339
|
+
* (`dir`, `format`, and optionally `dirName`, `path`, `encryptionKey`).
|
|
302
340
|
*
|
|
303
341
|
* Each call to `build()` creates a fresh `Configurate` instance — schema,
|
|
304
|
-
* `
|
|
342
|
+
* `name`, and all other options can differ freely. This is the recommended
|
|
305
343
|
* way to manage multiple config files with different schemas in a single
|
|
306
344
|
* application.
|
|
307
345
|
*
|
|
@@ -318,22 +356,55 @@ export type ConfigurateBaseOptions = Omit<ConfigurateOptions, "id">;
|
|
|
318
356
|
* format: "json",
|
|
319
357
|
* });
|
|
320
358
|
*
|
|
321
|
-
* const appConfig = factory.build(appSchema, "app");
|
|
322
|
-
* const cacheConfig = factory.build(cacheSchema, "cache");
|
|
323
|
-
* const
|
|
359
|
+
* const appConfig = factory.build(appSchema, "app.json"); // → app.json
|
|
360
|
+
* const cacheConfig = factory.build(cacheSchema, "cache.json"); // → cache.json
|
|
361
|
+
* const nestedConfig = factory.build(appSchema, { name: "app.json", path: "config" }); // → config/app.json
|
|
362
|
+
* const movedConfig = factory.build(appSchema, { name: "app.json", dirName: "my-app" }); // → %APPDATA%/my-app/app.json
|
|
363
|
+
* const fullConfig = factory.build(appSchema, { name: "app.json", dirName: "my-app", path: "cfg" }); // → %APPDATA%/my-app/cfg/app.json
|
|
324
364
|
* ```
|
|
325
365
|
*/
|
|
326
366
|
export declare class ConfigurateFactory {
|
|
327
367
|
private readonly _baseOpts;
|
|
328
368
|
constructor(_baseOpts: ConfigurateBaseOptions);
|
|
329
369
|
/**
|
|
330
|
-
* Creates a `Configurate<S>` for the given schema
|
|
331
|
-
*
|
|
370
|
+
* Creates a `Configurate<S>` for the given schema, applying the shared base
|
|
371
|
+
* options.
|
|
332
372
|
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
373
|
+
* `nameOrConfig` accepts either:
|
|
374
|
+
* - a plain `string` — used as the full filename (e.g. `"app.json"`, `".env"`)
|
|
375
|
+
* - `{ name: string; path?: string | null; dirName?: string | null }` — explicitly
|
|
376
|
+
* provides the filename, optional sub-directory within the root, and optional
|
|
377
|
+
* identifier replacement
|
|
378
|
+
*
|
|
379
|
+
* In the object form, passing `null` for `dirName` or `path` explicitly
|
|
380
|
+
* disables the factory-level value. Omitting the field (or passing
|
|
381
|
+
* `undefined`) falls back to the factory-level value.
|
|
382
|
+
*
|
|
383
|
+
* The optional third `dirName` string overrides the factory-level `dirName`
|
|
384
|
+
* for this instance (only used when `nameOrConfig` is a plain string).
|
|
385
|
+
*
|
|
386
|
+
* ### Path layout (AppConfig, identifier `com.example.app`)
|
|
387
|
+
*
|
|
388
|
+
* | `nameOrConfig` | `dirName` arg | Resolved path |
|
|
389
|
+
* | ------------------------------------------------ | ------------- | ---------------------------------------------- |
|
|
390
|
+
* | `"app.json"` | _(omitted)_ | `%APPDATA%/com.example.app/app.json` |
|
|
391
|
+
* | `"app.json"` | `"my-app"` | `%APPDATA%/my-app/app.json` |
|
|
392
|
+
* | `{ name: "app.json", path: "cfg" }` | _(omitted)_ | `%APPDATA%/com.example.app/cfg/app.json` |
|
|
393
|
+
* | `{ name: "app.json", dirName: "my-app" }` | _(omitted)_ | `%APPDATA%/my-app/app.json` |
|
|
394
|
+
* | `{ name: "app.json", dirName: "my-app", path: "cfg" }` | _(omitted)_ | `%APPDATA%/my-app/cfg/app.json` |
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```ts
|
|
398
|
+
* factory.build(schema, "app.json") // → <root>/app.json
|
|
399
|
+
* factory.build(schema, "app.json", "my-app") // → %APPDATA%/my-app/app.json
|
|
400
|
+
* factory.build(schema, { name: "app.json", path: "config" }) // → <root>/config/app.json
|
|
401
|
+
* factory.build(schema, { name: "app.json", dirName: "my-app" }) // → %APPDATA%/my-app/app.json
|
|
402
|
+
* factory.build(schema, { name: "cfg.json", dirName: "my-app", path: "a/b" }) // → %APPDATA%/my-app/a/b/cfg.json
|
|
403
|
+
* ```
|
|
335
404
|
*/
|
|
336
|
-
build<S extends SchemaObject>(schema: S & (true extends HasDuplicateKeyringIds<S> ? never : unknown),
|
|
405
|
+
build<S extends SchemaObject>(schema: S & (true extends HasDuplicateKeyringIds<S> ? never : unknown), nameOrConfig: string | BuildConfig, dirName?: string): Configurate<S>;
|
|
406
|
+
build<S extends SchemaObject>(schema: S & (true extends HasDuplicateKeyringIds<S> ? never : unknown), config: BuildConfig): Configurate<S>;
|
|
407
|
+
build<S extends SchemaObject>(schema: S & (true extends HasDuplicateKeyringIds<S> ? never : unknown), name: string, dirName?: string): Configurate<S>;
|
|
337
408
|
}
|
|
338
409
|
/**
|
|
339
410
|
* Defines a configuration schema. Provides a convenient declaration site and
|
package/dist-js/index.js
CHANGED
|
@@ -241,7 +241,7 @@ class LazyConfigEntry {
|
|
|
241
241
|
* });
|
|
242
242
|
*
|
|
243
243
|
* const config = new Configurate(schema, {
|
|
244
|
-
*
|
|
244
|
+
* name: "app-config.json",
|
|
245
245
|
* dir: BaseDirectory.AppConfig,
|
|
246
246
|
* format: "json",
|
|
247
247
|
* });
|
|
@@ -273,6 +273,27 @@ class Configurate {
|
|
|
273
273
|
throw new Error(`encryptionKey is only supported with format "binary", got "${opts.format}". ` +
|
|
274
274
|
`Remove encryptionKey or change format to "binary".`);
|
|
275
275
|
}
|
|
276
|
+
if (!opts.name) {
|
|
277
|
+
throw new Error('Configurate: "name" must not be empty.');
|
|
278
|
+
}
|
|
279
|
+
if (opts.name.includes("/") || opts.name.includes("\\")) {
|
|
280
|
+
throw new Error('Configurate: "name" must be a single filename and cannot contain path separators.');
|
|
281
|
+
}
|
|
282
|
+
if (opts.name === "." || opts.name === "..") {
|
|
283
|
+
throw new Error('Configurate: "name" must not be "." or "..".');
|
|
284
|
+
}
|
|
285
|
+
if (opts.dirName !== undefined) {
|
|
286
|
+
const dirNameSegments = opts.dirName.split(/[/\\]/);
|
|
287
|
+
if (dirNameSegments.some((seg) => seg === "" || seg === "." || seg === "..")) {
|
|
288
|
+
throw new Error('Configurate: "dirName" must not contain empty or special segments.');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (opts.path !== undefined) {
|
|
292
|
+
const pathSegments = opts.path.split(/[/\\]/);
|
|
293
|
+
if (pathSegments.some((seg) => seg === "" || seg === "." || seg === "..")) {
|
|
294
|
+
throw new Error('Configurate: "path" must not contain empty or special segments.');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
276
297
|
this._schema = schema;
|
|
277
298
|
this._opts = opts;
|
|
278
299
|
this._keyringPaths = collectKeyringPaths(this._schema);
|
|
@@ -365,13 +386,16 @@ class Configurate {
|
|
|
365
386
|
/** @internal */
|
|
366
387
|
_buildPayload(op, data, keyringOpts, withUnlock) {
|
|
367
388
|
const base = {
|
|
368
|
-
|
|
389
|
+
name: this._opts.name,
|
|
369
390
|
dir: this._opts.dir,
|
|
370
391
|
format: this._opts.format,
|
|
371
392
|
withUnlock,
|
|
372
393
|
};
|
|
373
|
-
if (this._opts.
|
|
374
|
-
base.
|
|
394
|
+
if (this._opts.dirName !== undefined) {
|
|
395
|
+
base.dirName = this._opts.dirName;
|
|
396
|
+
}
|
|
397
|
+
if (this._opts.path !== undefined) {
|
|
398
|
+
base.path = this._opts.path;
|
|
375
399
|
}
|
|
376
400
|
if (this._opts.encryptionKey) {
|
|
377
401
|
base.encryptionKey = this._opts.encryptionKey;
|
|
@@ -401,10 +425,10 @@ class Configurate {
|
|
|
401
425
|
}
|
|
402
426
|
/**
|
|
403
427
|
* A factory that creates `Configurate` instances with pre-set shared options
|
|
404
|
-
* (`dir`, `format`, and optionally `encryptionKey`).
|
|
428
|
+
* (`dir`, `format`, and optionally `dirName`, `path`, `encryptionKey`).
|
|
405
429
|
*
|
|
406
430
|
* Each call to `build()` creates a fresh `Configurate` instance — schema,
|
|
407
|
-
* `
|
|
431
|
+
* `name`, and all other options can differ freely. This is the recommended
|
|
408
432
|
* way to manage multiple config files with different schemas in a single
|
|
409
433
|
* application.
|
|
410
434
|
*
|
|
@@ -421,9 +445,11 @@ class Configurate {
|
|
|
421
445
|
* format: "json",
|
|
422
446
|
* });
|
|
423
447
|
*
|
|
424
|
-
* const appConfig = factory.build(appSchema, "app");
|
|
425
|
-
* const cacheConfig = factory.build(cacheSchema, "cache");
|
|
426
|
-
* const
|
|
448
|
+
* const appConfig = factory.build(appSchema, "app.json"); // → app.json
|
|
449
|
+
* const cacheConfig = factory.build(cacheSchema, "cache.json"); // → cache.json
|
|
450
|
+
* const nestedConfig = factory.build(appSchema, { name: "app.json", path: "config" }); // → config/app.json
|
|
451
|
+
* const movedConfig = factory.build(appSchema, { name: "app.json", dirName: "my-app" }); // → %APPDATA%/my-app/app.json
|
|
452
|
+
* const fullConfig = factory.build(appSchema, { name: "app.json", dirName: "my-app", path: "cfg" }); // → %APPDATA%/my-app/cfg/app.json
|
|
427
453
|
* ```
|
|
428
454
|
*/
|
|
429
455
|
class ConfigurateFactory {
|
|
@@ -431,18 +457,37 @@ class ConfigurateFactory {
|
|
|
431
457
|
constructor(_baseOpts) {
|
|
432
458
|
this._baseOpts = _baseOpts;
|
|
433
459
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
460
|
+
build(schema, nameOrConfig, dirName) {
|
|
461
|
+
let fileName;
|
|
462
|
+
let resolvedDirName;
|
|
463
|
+
let resolvedPath;
|
|
464
|
+
if (typeof nameOrConfig === "string") {
|
|
465
|
+
fileName = nameOrConfig;
|
|
466
|
+
// The explicit `dirName` argument overrides the factory-level dirName;
|
|
467
|
+
// fall back to the factory-level dirName when omitted.
|
|
468
|
+
resolvedDirName = dirName ?? this._baseOpts.dirName;
|
|
469
|
+
resolvedPath = this._baseOpts.path;
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
fileName = nameOrConfig.name;
|
|
473
|
+
// Object form: fields inside take precedence over factory-level values.
|
|
474
|
+
// Pass `null` to explicitly disable the factory-level value;
|
|
475
|
+
// `undefined` (or omitted) falls back to the factory-level value.
|
|
476
|
+
resolvedDirName =
|
|
477
|
+
nameOrConfig.dirName === null
|
|
478
|
+
? undefined
|
|
479
|
+
: (nameOrConfig.dirName ?? this._baseOpts.dirName);
|
|
480
|
+
resolvedPath =
|
|
481
|
+
nameOrConfig.path === null
|
|
482
|
+
? undefined
|
|
483
|
+
: (nameOrConfig.path ?? this._baseOpts.path);
|
|
445
484
|
}
|
|
485
|
+
const opts = {
|
|
486
|
+
...this._baseOpts,
|
|
487
|
+
name: fileName,
|
|
488
|
+
dirName: resolvedDirName,
|
|
489
|
+
path: resolvedPath,
|
|
490
|
+
};
|
|
446
491
|
// Explicitly pass <S> to prevent TypeScript from re-inferring the type
|
|
447
492
|
// parameter from the argument and double-evaluating HasDuplicateKeyringIds
|
|
448
493
|
// on the already-constrained type. The duplicate-id guarantee was already
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "tauri-plugin-configurate-api",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A Tauri v2 plugin for type-safe application configuration management.",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
"files": [
|
|
23
|
-
"dist-js",
|
|
24
|
-
"README.md",
|
|
25
|
-
"LICENSE"
|
|
26
|
-
],
|
|
27
|
-
"type": "module",
|
|
28
|
-
"main": "./dist-js/index.cjs",
|
|
29
|
-
"module": "./dist-js/index.js",
|
|
30
|
-
"types": "./dist-js/index.d.ts",
|
|
31
|
-
"exports": {
|
|
32
|
-
"types": "./dist-js/index.d.ts",
|
|
33
|
-
"import": "./dist-js/index.js",
|
|
34
|
-
"require": "./dist-js/index.cjs"
|
|
35
|
-
},
|
|
36
|
-
"scripts": {
|
|
37
|
-
"build": "rollup -c",
|
|
38
|
-
"build:sync": "rollup -c && cd examples/tauri-app && pnpm install",
|
|
39
|
-
"prepublishOnly": "bun run build",
|
|
40
|
-
"pretest": "pnpm build",
|
|
41
|
-
"fmt": "oxfmt",
|
|
42
|
-
"fmt:check": "oxfmt --check",
|
|
43
|
-
"lint": "oxlint --type-aware",
|
|
44
|
-
"lint:fix": "oxlint --type-aware --fix"
|
|
45
|
-
},
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
},
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "tauri-plugin-configurate-api",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "A Tauri v2 plugin for type-safe application configuration management.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"config",
|
|
7
|
+
"configuration",
|
|
8
|
+
"keyring",
|
|
9
|
+
"tauri",
|
|
10
|
+
"tauri-plugin"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/Crysta1221/tauri-plugin-configurate",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/Crysta1221/tauri-plugin-configurate/issues"
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": "Crysta1221",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "https://github.com/Crysta1221/tauri-plugin-configurate.git"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist-js",
|
|
24
|
+
"README.md",
|
|
25
|
+
"LICENSE"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./dist-js/index.cjs",
|
|
29
|
+
"module": "./dist-js/index.js",
|
|
30
|
+
"types": "./dist-js/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
"types": "./dist-js/index.d.ts",
|
|
33
|
+
"import": "./dist-js/index.js",
|
|
34
|
+
"require": "./dist-js/index.cjs"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "rollup -c",
|
|
38
|
+
"build:sync": "rollup -c && cd examples/tauri-app && pnpm install",
|
|
39
|
+
"prepublishOnly": "bun run build",
|
|
40
|
+
"pretest": "pnpm build",
|
|
41
|
+
"fmt": "oxfmt",
|
|
42
|
+
"fmt:check": "oxfmt --check",
|
|
43
|
+
"lint": "oxlint --type-aware",
|
|
44
|
+
"lint:fix": "oxlint --type-aware --fix"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"oxlint-tsgolint": "^0.15.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@rollup/plugin-typescript": "^12.0.0",
|
|
51
|
+
"oxfmt": "^0.35.0",
|
|
52
|
+
"oxlint": "^1.50.0",
|
|
53
|
+
"rollup": "^4.9.6",
|
|
54
|
+
"tslib": "^2.6.2",
|
|
55
|
+
"typescript": "^5.3.3"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"@tauri-apps/api": "^2.0.0"
|
|
59
|
+
}
|
|
60
|
+
}
|