@fgv/ts-json-base 3.0.0-alpha.1 → 3.0.1-alpha.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-json-base.d.ts +169 -12
- package/lib/packlets/json-file/file.d.ts +5 -48
- package/lib/packlets/json-file/file.d.ts.map +1 -1
- package/lib/packlets/json-file/file.js +15 -95
- package/lib/packlets/json-file/file.js.map +1 -1
- package/lib/packlets/json-file/index.d.ts +2 -0
- package/lib/packlets/json-file/index.d.ts.map +1 -1
- package/lib/packlets/json-file/index.js +2 -0
- package/lib/packlets/json-file/index.js.map +1 -1
- package/lib/packlets/json-file/jsonFsHelper.d.ts +147 -0
- package/lib/packlets/json-file/jsonFsHelper.d.ts.map +1 -0
- package/lib/packlets/json-file/jsonFsHelper.js +186 -0
- package/lib/packlets/json-file/jsonFsHelper.js.map +1 -0
- package/lib/packlets/json-file/jsonLike.d.ts +29 -0
- package/lib/packlets/json-file/jsonLike.d.ts.map +1 -0
- package/lib/packlets/json-file/jsonLike.js +29 -0
- package/lib/packlets/json-file/jsonLike.js.map +1 -0
- package/package.json +4 -4
package/dist/ts-json-base.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Converter } from '@fgv/ts-utils';
|
|
2
2
|
import { Result } from '@fgv/ts-utils';
|
|
3
|
+
import { Validation } from '@fgv/ts-utils';
|
|
3
4
|
import { Validator } from '@fgv/ts-utils';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -44,15 +45,30 @@ declare function convertJsonDirectorySync<T>(srcPath: string, options: IDirector
|
|
|
44
45
|
declare function convertJsonDirectoryToMapSync<T, TC = unknown>(srcPath: string, options: IDirectoryToMapConvertOptions<T, TC>): Result<Map<string, T>>;
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
|
-
*
|
|
48
|
+
* Read a JSON file and apply a supplied converter.
|
|
48
49
|
* @param srcPath - Path of the file to read.
|
|
49
50
|
* @param converter - `Converter` used to convert the file contents
|
|
50
|
-
* @returns `Success` with a result of type `<T>`, or `Failure
|
|
51
|
-
* with a message if an error occurs.
|
|
51
|
+
* @returns `Success` with a result of type `<T>`, or `Failure`* with a message if an error occurs.
|
|
52
52
|
* @public
|
|
53
53
|
*/
|
|
54
54
|
declare function convertJsonFileSync<T>(srcPath: string, converter: Converter<T>): Result<T>;
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
declare const DefaultJsonFsHelper: JsonFsHelper;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Default configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
63
|
+
* @public
|
|
64
|
+
*/
|
|
65
|
+
declare const DefaultJsonFsHelperConfig: IJsonFsHelperConfig;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
declare const DefaultJsonLike: IJsonLike;
|
|
71
|
+
|
|
56
72
|
/**
|
|
57
73
|
* Options for directory conversion.
|
|
58
74
|
* TODO: add filtering, allowed and excluded.
|
|
@@ -63,16 +79,37 @@ declare interface IDirectoryConvertOptions<T, TC = unknown> {
|
|
|
63
79
|
* The converter used to convert incoming JSON objects.
|
|
64
80
|
*/
|
|
65
81
|
converter: Converter<T, TC>;
|
|
82
|
+
validator?: undefined;
|
|
66
83
|
}
|
|
67
84
|
|
|
68
85
|
/**
|
|
69
|
-
* Options controlling conversion of a directory
|
|
86
|
+
* Options controlling conversion of a directory to a `Map`.
|
|
70
87
|
* @public
|
|
71
88
|
*/
|
|
72
89
|
declare interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirectoryConvertOptions<T, TC> {
|
|
73
90
|
transformName?: ItemNameTransformFunction<T>;
|
|
74
91
|
}
|
|
75
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Options controlling validation of a directory to a `Map`.
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
declare interface IDirectoryToMapValidateOptions<T, TC = unknown> extends IDirectoryValidateOptions<T, TC> {
|
|
98
|
+
transformName?: ItemNameTransformFunction<T>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Options for directory validation.
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
declare interface IDirectoryValidateOptions<T, TC = unknown> {
|
|
106
|
+
converter?: undefined;
|
|
107
|
+
/**
|
|
108
|
+
* The validator used to validate incoming JSON objects
|
|
109
|
+
*/
|
|
110
|
+
validator: Validator<T, TC>;
|
|
111
|
+
}
|
|
112
|
+
|
|
76
113
|
/**
|
|
77
114
|
* Conversion context for JSON converters.
|
|
78
115
|
* @public
|
|
@@ -81,6 +118,23 @@ declare interface IJsonConverterContext {
|
|
|
81
118
|
ignoreUndefinedProperties?: boolean;
|
|
82
119
|
}
|
|
83
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
123
|
+
* @public
|
|
124
|
+
*/
|
|
125
|
+
declare interface IJsonFsHelperConfig {
|
|
126
|
+
json: IJsonLike;
|
|
127
|
+
allowUndefinedWrite: boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @public
|
|
132
|
+
*/
|
|
133
|
+
declare interface IJsonLike {
|
|
134
|
+
parse(text: string, reviver?: JsonReviver, options?: unknown): JsonValue | undefined;
|
|
135
|
+
stringify(value: JsonValue, replacer?: JsonReplacer, space?: string | number): string | undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
84
138
|
/**
|
|
85
139
|
* Validation context for in-place JSON validators.
|
|
86
140
|
* @public
|
|
@@ -173,13 +227,101 @@ declare namespace JsonFile {
|
|
|
173
227
|
convertJsonDirectoryToMapSync,
|
|
174
228
|
writeJsonFileSync,
|
|
175
229
|
IDirectoryConvertOptions,
|
|
230
|
+
IDirectoryValidateOptions,
|
|
231
|
+
JsonFsDirectoryOptions,
|
|
176
232
|
IReadDirectoryItem,
|
|
177
233
|
ItemNameTransformFunction,
|
|
178
|
-
IDirectoryToMapConvertOptions
|
|
234
|
+
IDirectoryToMapConvertOptions,
|
|
235
|
+
IDirectoryToMapValidateOptions,
|
|
236
|
+
JsonFsDirectoryToMapOptions,
|
|
237
|
+
IJsonFsHelperConfig,
|
|
238
|
+
JsonFsHelperInitOptions,
|
|
239
|
+
DefaultJsonFsHelperConfig,
|
|
240
|
+
JsonFsHelper,
|
|
241
|
+
DefaultJsonFsHelper,
|
|
242
|
+
JsonReviver,
|
|
243
|
+
JsonReplacerFunction,
|
|
244
|
+
JsonReplacerArray,
|
|
245
|
+
JsonReplacer,
|
|
246
|
+
IJsonLike,
|
|
247
|
+
DefaultJsonLike
|
|
179
248
|
}
|
|
180
249
|
}
|
|
181
250
|
export { JsonFile }
|
|
182
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Options for directory conversion or validation.
|
|
254
|
+
* @public
|
|
255
|
+
*/
|
|
256
|
+
declare type JsonFsDirectoryOptions<T, TC = unknown> = IDirectoryConvertOptions<T, TC> | IDirectoryValidateOptions<T, TC>;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Options controlling processing of a directory to a `Map`.
|
|
260
|
+
* @public
|
|
261
|
+
*/
|
|
262
|
+
declare type JsonFsDirectoryToMapOptions<T, TC = unknown> = IDirectoryToMapConvertOptions<T, TC> | IDirectoryToMapValidateOptions<T, TC>;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Helper class to simplify common filesystem operations involving JSON (or JSON-like)
|
|
266
|
+
* files.
|
|
267
|
+
* @public
|
|
268
|
+
*/
|
|
269
|
+
declare class JsonFsHelper {
|
|
270
|
+
/**
|
|
271
|
+
* Configuration for this {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
272
|
+
*/
|
|
273
|
+
readonly config: IJsonFsHelperConfig;
|
|
274
|
+
/**
|
|
275
|
+
* Construct a new {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
276
|
+
* @param json - Optional {@link JsonFile.IJsonLike | IJsonLike} used to process strings
|
|
277
|
+
* and JSON values.
|
|
278
|
+
*/
|
|
279
|
+
constructor(init?: JsonFsHelperInitOptions);
|
|
280
|
+
/**
|
|
281
|
+
* Read type-safe JSON from a file.
|
|
282
|
+
* @param srcPath - Path of the file to read
|
|
283
|
+
* @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`
|
|
284
|
+
* with a message if an error occurs.
|
|
285
|
+
*/
|
|
286
|
+
readJsonFileSync(srcPath: string): Result<JsonValue>;
|
|
287
|
+
/**
|
|
288
|
+
* Read a JSON file and apply a supplied converter or validator.
|
|
289
|
+
* @param srcPath - Path of the file to read.
|
|
290
|
+
* @param cv - Converter or validator used to process the file.
|
|
291
|
+
* @returns `Success` with a result of type `<T>`, or `Failure`
|
|
292
|
+
* with a message if an error occurs.
|
|
293
|
+
*/
|
|
294
|
+
processJsonFileSync<T>(srcPath: string, cv: Validation.Convalidator<T>): Result<T>;
|
|
295
|
+
/**
|
|
296
|
+
* Reads all JSON files from a directory and apply a supplied converter or validator.
|
|
297
|
+
* @param srcPath - The path of the folder to be read.
|
|
298
|
+
* @param options - {@link JsonFile.JsonFsDirectoryOptions | Options} to control
|
|
299
|
+
* conversion and filtering
|
|
300
|
+
*/
|
|
301
|
+
processJsonDirectorySync<T>(srcPath: string, options: JsonFsDirectoryOptions<T>): Result<IReadDirectoryItem<T>[]>;
|
|
302
|
+
/**
|
|
303
|
+
* Reads and converts or validates all JSON files from a directory, returning a
|
|
304
|
+
* `Map<string, T>` indexed by file base name (i.e. minus the extension)
|
|
305
|
+
* with an optional name transformation applied if present.
|
|
306
|
+
* @param srcPath - The path of the folder to be read.
|
|
307
|
+
* @param options - {@link JsonFile.JsonFsDirectoryToMapOptions | Options} to control conversion,
|
|
308
|
+
* filtering and naming.
|
|
309
|
+
*/
|
|
310
|
+
processJsonDirectoryToMapSync<T, TC = unknown>(srcPath: string, options: JsonFsDirectoryToMapOptions<T, TC>): Result<Map<string, T>>;
|
|
311
|
+
/**
|
|
312
|
+
* Write type-safe JSON to a file.
|
|
313
|
+
* @param srcPath - Path of the file to write.
|
|
314
|
+
* @param value - The {@link JsonValue | JsonValue} to be written.
|
|
315
|
+
*/
|
|
316
|
+
writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean>;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Initialization options for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
321
|
+
* @public
|
|
322
|
+
*/
|
|
323
|
+
declare type JsonFsHelperInitOptions = Partial<IJsonFsHelperConfig>;
|
|
324
|
+
|
|
183
325
|
/**
|
|
184
326
|
* A {@link JsonObject | JsonObject} is a string-keyed object
|
|
185
327
|
* containing only valid {@link JsonValue | JSON values}.
|
|
@@ -228,6 +370,26 @@ declare const jsonPrimitive: Converter<JsonPrimitive, IJsonConverterContext>;
|
|
|
228
370
|
*/
|
|
229
371
|
declare const jsonPrimitive_2: Validator<JsonPrimitive, IJsonValidatorContext>;
|
|
230
372
|
|
|
373
|
+
/**
|
|
374
|
+
* @public
|
|
375
|
+
*/
|
|
376
|
+
declare type JsonReplacer = JsonReplacerFunction | JsonReplacerArray;
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* @public
|
|
380
|
+
*/
|
|
381
|
+
declare type JsonReplacerArray = (string | number)[];
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* @public
|
|
385
|
+
*/
|
|
386
|
+
declare type JsonReplacerFunction = (key: string, value: JsonValue) => JsonValue;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* @public
|
|
390
|
+
*/
|
|
391
|
+
declare type JsonReviver = (key: string, value: JsonValue) => JsonValue;
|
|
392
|
+
|
|
231
393
|
/**
|
|
232
394
|
* A {@link JsonValue | JsonValue} is one of: a {@link JsonPrimitive | JsonPrimitive},
|
|
233
395
|
* a {@link JsonObject | JsonObject} or an {@link JsonArray | JsonArray}.
|
|
@@ -282,10 +444,7 @@ export declare function pickJsonObject(src: JsonObject, path: string): Result<Js
|
|
|
282
444
|
export declare function pickJsonValue(src: JsonObject, path: string): Result<JsonValue>;
|
|
283
445
|
|
|
284
446
|
/**
|
|
285
|
-
*
|
|
286
|
-
* @param srcPath - Path of the file to read
|
|
287
|
-
* @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`
|
|
288
|
-
* with a message if an error occurs.
|
|
447
|
+
* {@inheritdoc JsonFile.JsonFsHelper.readJsonFileSync}
|
|
289
448
|
* @public
|
|
290
449
|
*/
|
|
291
450
|
declare function readJsonFileSync(srcPath: string): Result<JsonValue>;
|
|
@@ -313,9 +472,7 @@ declare namespace Validators {
|
|
|
313
472
|
export { Validators }
|
|
314
473
|
|
|
315
474
|
/**
|
|
316
|
-
*
|
|
317
|
-
* @param srcPath - Path of the file to write.
|
|
318
|
-
* @param value - The {@link JsonValue | JsonValue} to be written.
|
|
475
|
+
* {@inheritDoc JsonFile.JsonFsHelper.writeJsonFileSync}
|
|
319
476
|
* @public
|
|
320
477
|
*/
|
|
321
478
|
declare function writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean>;
|
|
@@ -1,47 +1,19 @@
|
|
|
1
1
|
import { Converter, Result } from '@fgv/ts-utils';
|
|
2
2
|
import { JsonValue } from '../json';
|
|
3
|
+
import { IDirectoryConvertOptions, IDirectoryToMapConvertOptions, IReadDirectoryItem } from './jsonFsHelper';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
* @param srcPath - Path of the file to read
|
|
6
|
-
* @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`
|
|
7
|
-
* with a message if an error occurs.
|
|
5
|
+
* {@inheritdoc JsonFile.JsonFsHelper.readJsonFileSync}
|
|
8
6
|
* @public
|
|
9
7
|
*/
|
|
10
8
|
export declare function readJsonFileSync(srcPath: string): Result<JsonValue>;
|
|
11
9
|
/**
|
|
12
|
-
*
|
|
10
|
+
* Read a JSON file and apply a supplied converter.
|
|
13
11
|
* @param srcPath - Path of the file to read.
|
|
14
12
|
* @param converter - `Converter` used to convert the file contents
|
|
15
|
-
* @returns `Success` with a result of type `<T>`, or `Failure
|
|
16
|
-
* with a message if an error occurs.
|
|
13
|
+
* @returns `Success` with a result of type `<T>`, or `Failure`* with a message if an error occurs.
|
|
17
14
|
* @public
|
|
18
15
|
*/
|
|
19
16
|
export declare function convertJsonFileSync<T>(srcPath: string, converter: Converter<T>): Result<T>;
|
|
20
|
-
/**
|
|
21
|
-
* Options for directory conversion.
|
|
22
|
-
* TODO: add filtering, allowed and excluded.
|
|
23
|
-
* @public
|
|
24
|
-
*/
|
|
25
|
-
export interface IDirectoryConvertOptions<T, TC = unknown> {
|
|
26
|
-
/**
|
|
27
|
-
* The converter used to convert incoming JSON objects.
|
|
28
|
-
*/
|
|
29
|
-
converter: Converter<T, TC>;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Return value for one item in a directory conversion.
|
|
33
|
-
* @public
|
|
34
|
-
*/
|
|
35
|
-
export interface IReadDirectoryItem<T> {
|
|
36
|
-
/**
|
|
37
|
-
* Relative name of the file that was processed
|
|
38
|
-
*/
|
|
39
|
-
filename: string;
|
|
40
|
-
/**
|
|
41
|
-
* The payload of the file.
|
|
42
|
-
*/
|
|
43
|
-
item: T;
|
|
44
|
-
}
|
|
45
17
|
/**
|
|
46
18
|
* Reads all JSON files from a directory and apply a supplied converter.
|
|
47
19
|
* @param srcPath - The path of the folder to be read.
|
|
@@ -50,19 +22,6 @@ export interface IReadDirectoryItem<T> {
|
|
|
50
22
|
* @public
|
|
51
23
|
*/
|
|
52
24
|
export declare function convertJsonDirectorySync<T>(srcPath: string, options: IDirectoryConvertOptions<T>): Result<IReadDirectoryItem<T>[]>;
|
|
53
|
-
/**
|
|
54
|
-
* Function to transform the name of a some entity, given an original name
|
|
55
|
-
* and the contents of the entity.
|
|
56
|
-
* @public
|
|
57
|
-
*/
|
|
58
|
-
export type ItemNameTransformFunction<T> = (name: string, item: T) => Result<string>;
|
|
59
|
-
/**
|
|
60
|
-
* Options controlling conversion of a directory.
|
|
61
|
-
* @public
|
|
62
|
-
*/
|
|
63
|
-
export interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirectoryConvertOptions<T, TC> {
|
|
64
|
-
transformName?: ItemNameTransformFunction<T>;
|
|
65
|
-
}
|
|
66
25
|
/**
|
|
67
26
|
* Reads and converts all JSON files from a directory, returning a
|
|
68
27
|
* `Map<string, T>` indexed by file base name (i.e. minus the extension)
|
|
@@ -74,9 +33,7 @@ export interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirecto
|
|
|
74
33
|
*/
|
|
75
34
|
export declare function convertJsonDirectoryToMapSync<T, TC = unknown>(srcPath: string, options: IDirectoryToMapConvertOptions<T, TC>): Result<Map<string, T>>;
|
|
76
35
|
/**
|
|
77
|
-
*
|
|
78
|
-
* @param srcPath - Path of the file to write.
|
|
79
|
-
* @param value - The {@link JsonValue | JsonValue} to be written.
|
|
36
|
+
* {@inheritDoc JsonFile.JsonFsHelper.writeJsonFileSync}
|
|
80
37
|
* @public
|
|
81
38
|
*/
|
|
82
39
|
export declare function writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/packlets/json-file/file.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../src/packlets/json-file/file.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAEL,wBAAwB,EACxB,6BAA6B,EAC7B,kBAAkB,EAEnB,MAAM,gBAAgB,CAAC;AAGxB;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAEnE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAE1F;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EACxC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,wBAAwB,CAAC,CAAC,CAAC,GACnC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAEjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAC3D,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,6BAA6B,CAAC,CAAC,EAAE,EAAE,CAAC,GAC5C,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAExB;AAOD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,CAEpF"}
|
|
@@ -20,61 +20,27 @@
|
|
|
20
20
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
21
|
* SOFTWARE.
|
|
22
22
|
*/
|
|
23
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
-
if (k2 === undefined) k2 = k;
|
|
25
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
-
}
|
|
29
|
-
Object.defineProperty(o, k2, desc);
|
|
30
|
-
}) : (function(o, m, k, k2) {
|
|
31
|
-
if (k2 === undefined) k2 = k;
|
|
32
|
-
o[k2] = m[k];
|
|
33
|
-
}));
|
|
34
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
-
}) : function(o, v) {
|
|
37
|
-
o["default"] = v;
|
|
38
|
-
});
|
|
39
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
40
|
-
if (mod && mod.__esModule) return mod;
|
|
41
|
-
var result = {};
|
|
42
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
43
|
-
__setModuleDefault(result, mod);
|
|
44
|
-
return result;
|
|
45
|
-
};
|
|
46
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
24
|
exports.writeJsonFileSync = exports.convertJsonDirectoryToMapSync = exports.convertJsonDirectorySync = exports.convertJsonFileSync = exports.readJsonFileSync = void 0;
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const path = __importStar(require("path"));
|
|
25
|
+
const jsonFsHelper_1 = require("./jsonFsHelper");
|
|
26
|
+
const jsonLike_1 = require("./jsonLike");
|
|
51
27
|
/**
|
|
52
|
-
*
|
|
53
|
-
* @param srcPath - Path of the file to read
|
|
54
|
-
* @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`
|
|
55
|
-
* with a message if an error occurs.
|
|
28
|
+
* {@inheritdoc JsonFile.JsonFsHelper.readJsonFileSync}
|
|
56
29
|
* @public
|
|
57
30
|
*/
|
|
58
31
|
function readJsonFileSync(srcPath) {
|
|
59
|
-
return
|
|
60
|
-
const fullPath = path.resolve(srcPath);
|
|
61
|
-
const body = fs.readFileSync(fullPath, 'utf8').toString();
|
|
62
|
-
return JSON.parse(body);
|
|
63
|
-
});
|
|
32
|
+
return jsonFsHelper_1.DefaultJsonFsHelper.readJsonFileSync(srcPath);
|
|
64
33
|
}
|
|
65
34
|
exports.readJsonFileSync = readJsonFileSync;
|
|
66
35
|
/**
|
|
67
|
-
*
|
|
36
|
+
* Read a JSON file and apply a supplied converter.
|
|
68
37
|
* @param srcPath - Path of the file to read.
|
|
69
38
|
* @param converter - `Converter` used to convert the file contents
|
|
70
|
-
* @returns `Success` with a result of type `<T>`, or `Failure
|
|
71
|
-
* with a message if an error occurs.
|
|
39
|
+
* @returns `Success` with a result of type `<T>`, or `Failure`* with a message if an error occurs.
|
|
72
40
|
* @public
|
|
73
41
|
*/
|
|
74
42
|
function convertJsonFileSync(srcPath, converter) {
|
|
75
|
-
return
|
|
76
|
-
return converter.convert(json);
|
|
77
|
-
});
|
|
43
|
+
return jsonFsHelper_1.DefaultJsonFsHelper.processJsonFileSync(srcPath, converter);
|
|
78
44
|
}
|
|
79
45
|
exports.convertJsonFileSync = convertJsonFileSync;
|
|
80
46
|
/**
|
|
@@ -85,42 +51,9 @@ exports.convertJsonFileSync = convertJsonFileSync;
|
|
|
85
51
|
* @public
|
|
86
52
|
*/
|
|
87
53
|
function convertJsonDirectorySync(srcPath, options) {
|
|
88
|
-
return (
|
|
89
|
-
const fullPath = path.resolve(srcPath);
|
|
90
|
-
if (!fs.statSync(fullPath).isDirectory()) {
|
|
91
|
-
throw new Error(`${fullPath}: Not a directory`);
|
|
92
|
-
}
|
|
93
|
-
const files = fs.readdirSync(fullPath, { withFileTypes: true });
|
|
94
|
-
const results = files
|
|
95
|
-
.map((fi) => {
|
|
96
|
-
if (fi.isFile() && path.extname(fi.name) === '.json') {
|
|
97
|
-
const filePath = path.resolve(fullPath, fi.name);
|
|
98
|
-
return convertJsonFileSync(filePath, options.converter)
|
|
99
|
-
.onSuccess((payload) => {
|
|
100
|
-
return (0, ts_utils_1.succeed)({
|
|
101
|
-
filename: fi.name,
|
|
102
|
-
item: payload
|
|
103
|
-
});
|
|
104
|
-
})
|
|
105
|
-
.onFailure((message) => {
|
|
106
|
-
return (0, ts_utils_1.fail)(`${fi.name}: ${message}`);
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
return undefined;
|
|
110
|
-
})
|
|
111
|
-
.filter((r) => r !== undefined);
|
|
112
|
-
return (0, ts_utils_1.mapResults)(results).orThrow();
|
|
113
|
-
});
|
|
54
|
+
return jsonFsHelper_1.DefaultJsonFsHelper.processJsonDirectorySync(srcPath, options);
|
|
114
55
|
}
|
|
115
56
|
exports.convertJsonDirectorySync = convertJsonDirectorySync;
|
|
116
|
-
/**
|
|
117
|
-
* Function to transform the name of some entity, given only a previous name. This
|
|
118
|
-
* default implementation always returns `Success` with the value that was passed in.
|
|
119
|
-
* @param n - The name to be transformed.
|
|
120
|
-
* @returns - `Success` with the string that was passed in.
|
|
121
|
-
* @public
|
|
122
|
-
*/
|
|
123
|
-
const defaultNameTransformer = (n) => (0, ts_utils_1.succeed)(n);
|
|
124
57
|
/**
|
|
125
58
|
* Reads and converts all JSON files from a directory, returning a
|
|
126
59
|
* `Map<string, T>` indexed by file base name (i.e. minus the extension)
|
|
@@ -131,32 +64,19 @@ const defaultNameTransformer = (n) => (0, ts_utils_1.succeed)(n);
|
|
|
131
64
|
* @public
|
|
132
65
|
*/
|
|
133
66
|
function convertJsonDirectoryToMapSync(srcPath, options) {
|
|
134
|
-
return
|
|
135
|
-
var _a;
|
|
136
|
-
const transformName = (_a = options.transformName) !== null && _a !== void 0 ? _a : defaultNameTransformer;
|
|
137
|
-
return (0, ts_utils_1.mapResults)(items.map((item) => {
|
|
138
|
-
const basename = path.basename(item.filename, '.json');
|
|
139
|
-
return transformName(basename, item.item).onSuccess((name) => {
|
|
140
|
-
return (0, ts_utils_1.succeed)([name, item.item]);
|
|
141
|
-
});
|
|
142
|
-
})).onSuccess((items) => {
|
|
143
|
-
return (0, ts_utils_1.succeed)(new Map(items));
|
|
144
|
-
});
|
|
145
|
-
});
|
|
67
|
+
return jsonFsHelper_1.DefaultJsonFsHelper.processJsonDirectoryToMapSync(srcPath, options);
|
|
146
68
|
}
|
|
147
69
|
exports.convertJsonDirectoryToMapSync = convertJsonDirectoryToMapSync;
|
|
70
|
+
const CompatJsonFsHelper = new jsonFsHelper_1.JsonFsHelper({
|
|
71
|
+
json: jsonLike_1.DefaultJsonLike,
|
|
72
|
+
allowUndefinedWrite: true // for compatibility
|
|
73
|
+
});
|
|
148
74
|
/**
|
|
149
|
-
*
|
|
150
|
-
* @param srcPath - Path of the file to write.
|
|
151
|
-
* @param value - The {@link JsonValue | JsonValue} to be written.
|
|
75
|
+
* {@inheritDoc JsonFile.JsonFsHelper.writeJsonFileSync}
|
|
152
76
|
* @public
|
|
153
77
|
*/
|
|
154
78
|
function writeJsonFileSync(srcPath, value) {
|
|
155
|
-
return (
|
|
156
|
-
const fullPath = path.resolve(srcPath);
|
|
157
|
-
fs.writeFileSync(fullPath, JSON.stringify(value, undefined, 2));
|
|
158
|
-
return true;
|
|
159
|
-
});
|
|
79
|
+
return CompatJsonFsHelper.writeJsonFileSync(srcPath, value);
|
|
160
80
|
}
|
|
161
81
|
exports.writeJsonFileSync = writeJsonFileSync;
|
|
162
82
|
//# sourceMappingURL=file.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/packlets/json-file/file.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG
|
|
1
|
+
{"version":3,"file":"file.js","sourceRoot":"","sources":["../../../src/packlets/json-file/file.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAIH,iDAMwB;AACxB,yCAA6C;AAE7C;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,OAAe;IAC9C,OAAO,kCAAmB,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;AACvD,CAAC;AAFD,4CAEC;AAED;;;;;;GAMG;AACH,SAAgB,mBAAmB,CAAI,OAAe,EAAE,SAAuB;IAC7E,OAAO,kCAAmB,CAAC,mBAAmB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AACrE,CAAC;AAFD,kDAEC;AAED;;;;;;GAMG;AACH,SAAgB,wBAAwB,CACtC,OAAe,EACf,OAAoC;IAEpC,OAAO,kCAAmB,CAAC,wBAAwB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACxE,CAAC;AALD,4DAKC;AAED;;;;;;;;GAQG;AACH,SAAgB,6BAA6B,CAC3C,OAAe,EACf,OAA6C;IAE7C,OAAO,kCAAmB,CAAC,6BAA6B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC7E,CAAC;AALD,sEAKC;AAED,MAAM,kBAAkB,GAAiB,IAAI,2BAAY,CAAC;IACxD,IAAI,EAAE,0BAAe;IACrB,mBAAmB,EAAE,IAAI,CAAC,oBAAoB;CAC/C,CAAC,CAAC;AAEH;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,OAAe,EAAE,KAAgB;IACjE,OAAO,kBAAkB,CAAC,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC9D,CAAC;AAFD,8CAEC","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { Converter, Result } from '@fgv/ts-utils';\nimport { JsonValue } from '../json';\nimport {\n DefaultJsonFsHelper,\n IDirectoryConvertOptions,\n IDirectoryToMapConvertOptions,\n IReadDirectoryItem,\n JsonFsHelper\n} from './jsonFsHelper';\nimport { DefaultJsonLike } from './jsonLike';\n\n/**\n * {@inheritdoc JsonFile.JsonFsHelper.readJsonFileSync}\n * @public\n */\nexport function readJsonFileSync(srcPath: string): Result<JsonValue> {\n return DefaultJsonFsHelper.readJsonFileSync(srcPath);\n}\n\n/**\n * Read a JSON file and apply a supplied converter.\n * @param srcPath - Path of the file to read.\n * @param converter - `Converter` used to convert the file contents\n * @returns `Success` with a result of type `<T>`, or `Failure`* with a message if an error occurs.\n * @public\n */\nexport function convertJsonFileSync<T>(srcPath: string, converter: Converter<T>): Result<T> {\n return DefaultJsonFsHelper.processJsonFileSync(srcPath, converter);\n}\n\n/**\n * Reads all JSON files from a directory and apply a supplied converter.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link JsonFile.IDirectoryConvertOptions | Options} to control\n * conversion and filtering\n * @public\n */\nexport function convertJsonDirectorySync<T>(\n srcPath: string,\n options: IDirectoryConvertOptions<T>\n): Result<IReadDirectoryItem<T>[]> {\n return DefaultJsonFsHelper.processJsonDirectorySync(srcPath, options);\n}\n\n/**\n * Reads and converts all JSON files from a directory, returning a\n * `Map<string, T>` indexed by file base name (i.e. minus the extension)\n * with an optional name transformation applied if present.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link JsonFile.IDirectoryToMapConvertOptions | Options} to control conversion,\n * filtering and naming.\n * @public\n */\nexport function convertJsonDirectoryToMapSync<T, TC = unknown>(\n srcPath: string,\n options: IDirectoryToMapConvertOptions<T, TC>\n): Result<Map<string, T>> {\n return DefaultJsonFsHelper.processJsonDirectoryToMapSync(srcPath, options);\n}\n\nconst CompatJsonFsHelper: JsonFsHelper = new JsonFsHelper({\n json: DefaultJsonLike,\n allowUndefinedWrite: true // for compatibility\n});\n\n/**\n * {@inheritDoc JsonFile.JsonFsHelper.writeJsonFileSync}\n * @public\n */\nexport function writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean> {\n return CompatJsonFsHelper.writeJsonFileSync(srcPath, value);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/json-file/index.ts"],"names":[],"mappings":"AAsBA,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/json-file/index.ts"],"names":[],"mappings":"AAsBA,cAAc,QAAQ,CAAC;AACvB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC"}
|
|
@@ -36,4 +36,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
__exportStar(require("./file"), exports);
|
|
39
|
+
__exportStar(require("./jsonFsHelper"), exports);
|
|
40
|
+
__exportStar(require("./jsonLike"), exports);
|
|
39
41
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/json-file/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,yCAAuB","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport * from './file';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/json-file/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH,yCAAuB;AACvB,iDAA+B;AAC/B,6CAA2B","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nexport * from './file';\nexport * from './jsonFsHelper';\nexport * from './jsonLike';\n"]}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Converter, Result, Validation, Validator } from '@fgv/ts-utils';
|
|
2
|
+
import { JsonValue } from '../json';
|
|
3
|
+
import { IJsonLike } from './jsonLike';
|
|
4
|
+
/**
|
|
5
|
+
* Options for directory conversion.
|
|
6
|
+
* TODO: add filtering, allowed and excluded.
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export interface IDirectoryConvertOptions<T, TC = unknown> {
|
|
10
|
+
/**
|
|
11
|
+
* The converter used to convert incoming JSON objects.
|
|
12
|
+
*/
|
|
13
|
+
converter: Converter<T, TC>;
|
|
14
|
+
validator?: undefined;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Options for directory validation.
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export interface IDirectoryValidateOptions<T, TC = unknown> {
|
|
21
|
+
converter?: undefined;
|
|
22
|
+
/**
|
|
23
|
+
* The validator used to validate incoming JSON objects
|
|
24
|
+
*/
|
|
25
|
+
validator: Validator<T, TC>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for directory conversion or validation.
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
export type JsonFsDirectoryOptions<T, TC = unknown> = IDirectoryConvertOptions<T, TC> | IDirectoryValidateOptions<T, TC>;
|
|
32
|
+
/**
|
|
33
|
+
* Return value for one item in a directory conversion.
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export interface IReadDirectoryItem<T> {
|
|
37
|
+
/**
|
|
38
|
+
* Relative name of the file that was processed
|
|
39
|
+
*/
|
|
40
|
+
filename: string;
|
|
41
|
+
/**
|
|
42
|
+
* The payload of the file.
|
|
43
|
+
*/
|
|
44
|
+
item: T;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Function to transform the name of a some entity, given an original name
|
|
48
|
+
* and the contents of the entity.
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export type ItemNameTransformFunction<T> = (name: string, item: T) => Result<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Options controlling conversion of a directory to a `Map`.
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirectoryConvertOptions<T, TC> {
|
|
57
|
+
transformName?: ItemNameTransformFunction<T>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Options controlling validation of a directory to a `Map`.
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export interface IDirectoryToMapValidateOptions<T, TC = unknown> extends IDirectoryValidateOptions<T, TC> {
|
|
64
|
+
transformName?: ItemNameTransformFunction<T>;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Options controlling processing of a directory to a `Map`.
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
export type JsonFsDirectoryToMapOptions<T, TC = unknown> = IDirectoryToMapConvertOptions<T, TC> | IDirectoryToMapValidateOptions<T, TC>;
|
|
71
|
+
/**
|
|
72
|
+
* Configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export interface IJsonFsHelperConfig {
|
|
76
|
+
json: IJsonLike;
|
|
77
|
+
allowUndefinedWrite: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Initialization options for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
export type JsonFsHelperInitOptions = Partial<IJsonFsHelperConfig>;
|
|
84
|
+
/**
|
|
85
|
+
* Default configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
export declare const DefaultJsonFsHelperConfig: IJsonFsHelperConfig;
|
|
89
|
+
/**
|
|
90
|
+
* Helper class to simplify common filesystem operations involving JSON (or JSON-like)
|
|
91
|
+
* files.
|
|
92
|
+
* @public
|
|
93
|
+
*/
|
|
94
|
+
export declare class JsonFsHelper {
|
|
95
|
+
/**
|
|
96
|
+
* Configuration for this {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
97
|
+
*/
|
|
98
|
+
readonly config: IJsonFsHelperConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Construct a new {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
101
|
+
* @param json - Optional {@link JsonFile.IJsonLike | IJsonLike} used to process strings
|
|
102
|
+
* and JSON values.
|
|
103
|
+
*/
|
|
104
|
+
constructor(init?: JsonFsHelperInitOptions);
|
|
105
|
+
/**
|
|
106
|
+
* Read type-safe JSON from a file.
|
|
107
|
+
* @param srcPath - Path of the file to read
|
|
108
|
+
* @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`
|
|
109
|
+
* with a message if an error occurs.
|
|
110
|
+
*/
|
|
111
|
+
readJsonFileSync(srcPath: string): Result<JsonValue>;
|
|
112
|
+
/**
|
|
113
|
+
* Read a JSON file and apply a supplied converter or validator.
|
|
114
|
+
* @param srcPath - Path of the file to read.
|
|
115
|
+
* @param cv - Converter or validator used to process the file.
|
|
116
|
+
* @returns `Success` with a result of type `<T>`, or `Failure`
|
|
117
|
+
* with a message if an error occurs.
|
|
118
|
+
*/
|
|
119
|
+
processJsonFileSync<T>(srcPath: string, cv: Validation.Convalidator<T>): Result<T>;
|
|
120
|
+
/**
|
|
121
|
+
* Reads all JSON files from a directory and apply a supplied converter or validator.
|
|
122
|
+
* @param srcPath - The path of the folder to be read.
|
|
123
|
+
* @param options - {@link JsonFile.JsonFsDirectoryOptions | Options} to control
|
|
124
|
+
* conversion and filtering
|
|
125
|
+
*/
|
|
126
|
+
processJsonDirectorySync<T>(srcPath: string, options: JsonFsDirectoryOptions<T>): Result<IReadDirectoryItem<T>[]>;
|
|
127
|
+
/**
|
|
128
|
+
* Reads and converts or validates all JSON files from a directory, returning a
|
|
129
|
+
* `Map<string, T>` indexed by file base name (i.e. minus the extension)
|
|
130
|
+
* with an optional name transformation applied if present.
|
|
131
|
+
* @param srcPath - The path of the folder to be read.
|
|
132
|
+
* @param options - {@link JsonFile.JsonFsDirectoryToMapOptions | Options} to control conversion,
|
|
133
|
+
* filtering and naming.
|
|
134
|
+
*/
|
|
135
|
+
processJsonDirectoryToMapSync<T, TC = unknown>(srcPath: string, options: JsonFsDirectoryToMapOptions<T, TC>): Result<Map<string, T>>;
|
|
136
|
+
/**
|
|
137
|
+
* Write type-safe JSON to a file.
|
|
138
|
+
* @param srcPath - Path of the file to write.
|
|
139
|
+
* @param value - The {@link JsonValue | JsonValue} to be written.
|
|
140
|
+
*/
|
|
141
|
+
writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean>;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* @public
|
|
145
|
+
*/
|
|
146
|
+
export declare const DefaultJsonFsHelper: JsonFsHelper;
|
|
147
|
+
//# sourceMappingURL=jsonFsHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonFsHelper.d.ts","sourceRoot":"","sources":["../../../src/packlets/json-file/jsonFsHelper.ts"],"names":[],"mappings":"AAsBA,OAAO,EACL,SAAS,EACT,MAAM,EACN,UAAU,EACV,SAAS,EAKV,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAmB,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,wBAAwB,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO;IACvD;;OAEG;IACH,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO;IACxD,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;OAEG;IACH,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,IAC9C,wBAAwB,CAAC,CAAC,EAAE,EAAE,CAAC,GAC/B,yBAAyB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAErC;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC;CACT;AAED;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC;AAErF;;;GAGG;AACH,MAAM,WAAW,6BAA6B,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAE,SAAQ,wBAAwB,CAAC,CAAC,EAAE,EAAE,CAAC;IACrG,aAAa,CAAC,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,MAAM,WAAW,8BAA8B,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,CAAE,SAAQ,yBAAyB,CAAC,CAAC,EAAE,EAAE,CAAC;IACvG,aAAa,CAAC,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,MAAM,MAAM,2BAA2B,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,IACnD,6BAA6B,CAAC,CAAC,EAAE,EAAE,CAAC,GACpC,8BAA8B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAW1C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,SAAS,CAAC;IAChB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAEnE;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,mBAGvC,CAAC;AAEF;;;;GAIG;AACH,qBAAa,YAAY;IACvB;;OAEG;IACH,SAAgB,MAAM,EAAE,mBAAmB,CAAC;IAE5C;;;;OAIG;gBACgB,IAAI,CAAC,EAAE,uBAAuB;IAOjD;;;;;OAKG;IACI,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAQ3D;;;;;;OAMG;IACI,mBAAmB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAMzF;;;;;OAKG;IACI,wBAAwB,CAAC,CAAC,EAC/B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,sBAAsB,CAAC,CAAC,CAAC,GACjC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IA6BlC;;;;;;;OAOG;IACI,6BAA6B,CAAC,CAAC,EAAE,EAAE,GAAG,OAAO,EAClD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,2BAA2B,CAAC,CAAC,EAAE,EAAE,CAAC,GAC1C,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAgBzB;;;;OAIG;IACI,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC;CAW7E;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAAiC,CAAC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2020 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
26
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
27
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(o, k2, desc);
|
|
30
|
+
}) : (function(o, m, k, k2) {
|
|
31
|
+
if (k2 === undefined) k2 = k;
|
|
32
|
+
o[k2] = m[k];
|
|
33
|
+
}));
|
|
34
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
35
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
36
|
+
}) : function(o, v) {
|
|
37
|
+
o["default"] = v;
|
|
38
|
+
});
|
|
39
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
40
|
+
if (mod && mod.__esModule) return mod;
|
|
41
|
+
var result = {};
|
|
42
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
43
|
+
__setModuleDefault(result, mod);
|
|
44
|
+
return result;
|
|
45
|
+
};
|
|
46
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
+
exports.DefaultJsonFsHelper = exports.JsonFsHelper = exports.DefaultJsonFsHelperConfig = void 0;
|
|
48
|
+
const ts_utils_1 = require("@fgv/ts-utils");
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const path = __importStar(require("path"));
|
|
51
|
+
const jsonLike_1 = require("./jsonLike");
|
|
52
|
+
/**
|
|
53
|
+
* Function to transform the name of some entity, given only a previous name. This
|
|
54
|
+
* default implementation always returns `Success` with the value that was passed in.
|
|
55
|
+
* @param n - The name to be transformed.
|
|
56
|
+
* @returns - `Success` with the string that was passed in.
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
const defaultNameTransformer = (n) => (0, ts_utils_1.succeed)(n);
|
|
60
|
+
/**
|
|
61
|
+
* Default configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
exports.DefaultJsonFsHelperConfig = {
|
|
65
|
+
json: jsonLike_1.DefaultJsonLike,
|
|
66
|
+
allowUndefinedWrite: false
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Helper class to simplify common filesystem operations involving JSON (or JSON-like)
|
|
70
|
+
* files.
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
73
|
+
class JsonFsHelper {
|
|
74
|
+
/**
|
|
75
|
+
* Construct a new {@link JsonFile.JsonFsHelper | JsonFsHelper}.
|
|
76
|
+
* @param json - Optional {@link JsonFile.IJsonLike | IJsonLike} used to process strings
|
|
77
|
+
* and JSON values.
|
|
78
|
+
*/
|
|
79
|
+
constructor(init) {
|
|
80
|
+
this.config = Object.assign(Object.assign({}, exports.DefaultJsonFsHelperConfig), (init !== null && init !== void 0 ? init : {}));
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read type-safe JSON from a file.
|
|
84
|
+
* @param srcPath - Path of the file to read
|
|
85
|
+
* @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`
|
|
86
|
+
* with a message if an error occurs.
|
|
87
|
+
*/
|
|
88
|
+
readJsonFileSync(srcPath) {
|
|
89
|
+
return (0, ts_utils_1.captureResult)(() => {
|
|
90
|
+
const fullPath = path.resolve(srcPath);
|
|
91
|
+
const body = fs.readFileSync(fullPath, 'utf8').toString();
|
|
92
|
+
return this.config.json.parse(body);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Read a JSON file and apply a supplied converter or validator.
|
|
97
|
+
* @param srcPath - Path of the file to read.
|
|
98
|
+
* @param cv - Converter or validator used to process the file.
|
|
99
|
+
* @returns `Success` with a result of type `<T>`, or `Failure`
|
|
100
|
+
* with a message if an error occurs.
|
|
101
|
+
*/
|
|
102
|
+
processJsonFileSync(srcPath, cv) {
|
|
103
|
+
return this.readJsonFileSync(srcPath).onSuccess((json) => {
|
|
104
|
+
return cv.convalidate(json);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Reads all JSON files from a directory and apply a supplied converter or validator.
|
|
109
|
+
* @param srcPath - The path of the folder to be read.
|
|
110
|
+
* @param options - {@link JsonFile.JsonFsDirectoryOptions | Options} to control
|
|
111
|
+
* conversion and filtering
|
|
112
|
+
*/
|
|
113
|
+
processJsonDirectorySync(srcPath, options) {
|
|
114
|
+
return (0, ts_utils_1.captureResult)(() => {
|
|
115
|
+
const fullPath = path.resolve(srcPath);
|
|
116
|
+
if (!fs.statSync(fullPath).isDirectory()) {
|
|
117
|
+
throw new Error(`${fullPath}: Not a directory`);
|
|
118
|
+
}
|
|
119
|
+
const files = fs.readdirSync(fullPath, { withFileTypes: true });
|
|
120
|
+
const results = files
|
|
121
|
+
.map((fi) => {
|
|
122
|
+
var _a;
|
|
123
|
+
if (fi.isFile() && path.extname(fi.name) === '.json') {
|
|
124
|
+
const filePath = path.resolve(fullPath, fi.name);
|
|
125
|
+
return this.processJsonFileSync(filePath, (_a = options.converter) !== null && _a !== void 0 ? _a : options.validator)
|
|
126
|
+
.onSuccess((payload) => {
|
|
127
|
+
return (0, ts_utils_1.succeed)({
|
|
128
|
+
filename: fi.name,
|
|
129
|
+
item: payload
|
|
130
|
+
});
|
|
131
|
+
})
|
|
132
|
+
.onFailure((message) => {
|
|
133
|
+
return (0, ts_utils_1.fail)(`${fi.name}: ${message}`);
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
})
|
|
138
|
+
.filter((r) => r !== undefined);
|
|
139
|
+
return (0, ts_utils_1.mapResults)(results).orThrow();
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Reads and converts or validates all JSON files from a directory, returning a
|
|
144
|
+
* `Map<string, T>` indexed by file base name (i.e. minus the extension)
|
|
145
|
+
* with an optional name transformation applied if present.
|
|
146
|
+
* @param srcPath - The path of the folder to be read.
|
|
147
|
+
* @param options - {@link JsonFile.JsonFsDirectoryToMapOptions | Options} to control conversion,
|
|
148
|
+
* filtering and naming.
|
|
149
|
+
*/
|
|
150
|
+
processJsonDirectoryToMapSync(srcPath, options) {
|
|
151
|
+
return this.processJsonDirectorySync(srcPath, options).onSuccess((items) => {
|
|
152
|
+
var _a;
|
|
153
|
+
const transformName = (_a = options.transformName) !== null && _a !== void 0 ? _a : defaultNameTransformer;
|
|
154
|
+
return (0, ts_utils_1.mapResults)(items.map((item) => {
|
|
155
|
+
const basename = path.basename(item.filename, '.json');
|
|
156
|
+
return transformName(basename, item.item).onSuccess((name) => {
|
|
157
|
+
return (0, ts_utils_1.succeed)([name, item.item]);
|
|
158
|
+
});
|
|
159
|
+
})).onSuccess((items) => {
|
|
160
|
+
return (0, ts_utils_1.succeed)(new Map(items));
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Write type-safe JSON to a file.
|
|
166
|
+
* @param srcPath - Path of the file to write.
|
|
167
|
+
* @param value - The {@link JsonValue | JsonValue} to be written.
|
|
168
|
+
*/
|
|
169
|
+
writeJsonFileSync(srcPath, value) {
|
|
170
|
+
return (0, ts_utils_1.captureResult)(() => {
|
|
171
|
+
const fullPath = path.resolve(srcPath);
|
|
172
|
+
const stringified = this.config.json.stringify(value, undefined, 2);
|
|
173
|
+
if (stringified === undefined && this.config.allowUndefinedWrite !== true) {
|
|
174
|
+
throw new Error(`Could not stringify ${value}`);
|
|
175
|
+
}
|
|
176
|
+
fs.writeFileSync(fullPath, stringified);
|
|
177
|
+
return true;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
exports.JsonFsHelper = JsonFsHelper;
|
|
182
|
+
/**
|
|
183
|
+
* @public
|
|
184
|
+
*/
|
|
185
|
+
exports.DefaultJsonFsHelper = new JsonFsHelper();
|
|
186
|
+
//# sourceMappingURL=jsonFsHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonFsHelper.js","sourceRoot":"","sources":["../../../src/packlets/json-file/jsonFsHelper.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2020 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport {\n Converter,\n Result,\n Validation,\n Validator,\n captureResult,\n fail,\n mapResults,\n succeed\n} from '@fgv/ts-utils';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { JsonValue } from '../json';\nimport { DefaultJsonLike, IJsonLike } from './jsonLike';\n\n/**\n * Options for directory conversion.\n * TODO: add filtering, allowed and excluded.\n * @public\n */\nexport interface IDirectoryConvertOptions<T, TC = unknown> {\n /**\n * The converter used to convert incoming JSON objects.\n */\n converter: Converter<T, TC>;\n validator?: undefined;\n}\n\n/**\n * Options for directory validation.\n * @public\n */\nexport interface IDirectoryValidateOptions<T, TC = unknown> {\n converter?: undefined;\n /**\n * The validator used to validate incoming JSON objects\n */\n validator: Validator<T, TC>;\n}\n\n/**\n * Options for directory conversion or validation.\n * @public\n */\nexport type JsonFsDirectoryOptions<T, TC = unknown> =\n | IDirectoryConvertOptions<T, TC>\n | IDirectoryValidateOptions<T, TC>;\n\n/**\n * Return value for one item in a directory conversion.\n * @public\n */\nexport interface IReadDirectoryItem<T> {\n /**\n * Relative name of the file that was processed\n */\n filename: string;\n\n /**\n * The payload of the file.\n */\n item: T;\n}\n\n/**\n * Function to transform the name of a some entity, given an original name\n * and the contents of the entity.\n * @public\n */\nexport type ItemNameTransformFunction<T> = (name: string, item: T) => Result<string>;\n\n/**\n * Options controlling conversion of a directory to a `Map`.\n * @public\n */\nexport interface IDirectoryToMapConvertOptions<T, TC = unknown> extends IDirectoryConvertOptions<T, TC> {\n transformName?: ItemNameTransformFunction<T>;\n}\n\n/**\n * Options controlling validation of a directory to a `Map`.\n * @public\n */\nexport interface IDirectoryToMapValidateOptions<T, TC = unknown> extends IDirectoryValidateOptions<T, TC> {\n transformName?: ItemNameTransformFunction<T>;\n}\n\n/**\n * Options controlling processing of a directory to a `Map`.\n * @public\n */\nexport type JsonFsDirectoryToMapOptions<T, TC = unknown> =\n | IDirectoryToMapConvertOptions<T, TC>\n | IDirectoryToMapValidateOptions<T, TC>;\n\n/**\n * Function to transform the name of some entity, given only a previous name. This\n * default implementation always returns `Success` with the value that was passed in.\n * @param n - The name to be transformed.\n * @returns - `Success` with the string that was passed in.\n * @public\n */\nconst defaultNameTransformer = (n: string): Result<string> => succeed(n);\n\n/**\n * Configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.\n * @public\n */\nexport interface IJsonFsHelperConfig {\n json: IJsonLike;\n allowUndefinedWrite: boolean;\n}\n\n/**\n * Initialization options for {@link JsonFile.JsonFsHelper | JsonFsHelper}.\n * @public\n */\nexport type JsonFsHelperInitOptions = Partial<IJsonFsHelperConfig>;\n\n/**\n * Default configuration for {@link JsonFile.JsonFsHelper | JsonFsHelper}.\n * @public\n */\nexport const DefaultJsonFsHelperConfig: IJsonFsHelperConfig = {\n json: DefaultJsonLike,\n allowUndefinedWrite: false\n};\n\n/**\n * Helper class to simplify common filesystem operations involving JSON (or JSON-like)\n * files.\n * @public\n */\nexport class JsonFsHelper {\n /**\n * Configuration for this {@link JsonFile.JsonFsHelper | JsonFsHelper}.\n */\n public readonly config: IJsonFsHelperConfig;\n\n /**\n * Construct a new {@link JsonFile.JsonFsHelper | JsonFsHelper}.\n * @param json - Optional {@link JsonFile.IJsonLike | IJsonLike} used to process strings\n * and JSON values.\n */\n public constructor(init?: JsonFsHelperInitOptions) {\n this.config = {\n ...DefaultJsonFsHelperConfig,\n ...(init ?? {})\n };\n }\n\n /**\n * Read type-safe JSON from a file.\n * @param srcPath - Path of the file to read\n * @returns `Success` with a {@link JsonValue | JsonValue} or `Failure`\n * with a message if an error occurs.\n */\n public readJsonFileSync(srcPath: string): Result<JsonValue> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n const body = fs.readFileSync(fullPath, 'utf8').toString();\n return this.config.json.parse(body) as JsonValue;\n });\n }\n\n /**\n * Read a JSON file and apply a supplied converter or validator.\n * @param srcPath - Path of the file to read.\n * @param cv - Converter or validator used to process the file.\n * @returns `Success` with a result of type `<T>`, or `Failure`\n * with a message if an error occurs.\n */\n public processJsonFileSync<T>(srcPath: string, cv: Validation.Convalidator<T>): Result<T> {\n return this.readJsonFileSync(srcPath).onSuccess((json) => {\n return cv.convalidate(json);\n });\n }\n\n /**\n * Reads all JSON files from a directory and apply a supplied converter or validator.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link JsonFile.JsonFsDirectoryOptions | Options} to control\n * conversion and filtering\n */\n public processJsonDirectorySync<T>(\n srcPath: string,\n options: JsonFsDirectoryOptions<T>\n ): Result<IReadDirectoryItem<T>[]> {\n return captureResult<IReadDirectoryItem<T>[]>(() => {\n const fullPath = path.resolve(srcPath);\n if (!fs.statSync(fullPath).isDirectory()) {\n throw new Error(`${fullPath}: Not a directory`);\n }\n const files = fs.readdirSync(fullPath, { withFileTypes: true });\n const results = files\n .map((fi) => {\n if (fi.isFile() && path.extname(fi.name) === '.json') {\n const filePath = path.resolve(fullPath, fi.name);\n return this.processJsonFileSync(filePath, options.converter ?? options.validator)\n .onSuccess((payload) => {\n return succeed({\n filename: fi.name,\n item: payload\n });\n })\n .onFailure((message) => {\n return fail(`${fi.name}: ${message}`);\n });\n }\n return undefined;\n })\n .filter((r): r is Result<IReadDirectoryItem<T>> => r !== undefined);\n return mapResults(results).orThrow();\n });\n }\n\n /**\n * Reads and converts or validates all JSON files from a directory, returning a\n * `Map<string, T>` indexed by file base name (i.e. minus the extension)\n * with an optional name transformation applied if present.\n * @param srcPath - The path of the folder to be read.\n * @param options - {@link JsonFile.JsonFsDirectoryToMapOptions | Options} to control conversion,\n * filtering and naming.\n */\n public processJsonDirectoryToMapSync<T, TC = unknown>(\n srcPath: string,\n options: JsonFsDirectoryToMapOptions<T, TC>\n ): Result<Map<string, T>> {\n return this.processJsonDirectorySync(srcPath, options).onSuccess((items) => {\n const transformName = options.transformName ?? defaultNameTransformer;\n return mapResults(\n items.map((item) => {\n const basename = path.basename(item.filename, '.json');\n return transformName(basename, item.item).onSuccess((name) => {\n return succeed<[string, T]>([name, item.item]);\n });\n })\n ).onSuccess((items) => {\n return succeed(new Map<string, T>(items));\n });\n });\n }\n\n /**\n * Write type-safe JSON to a file.\n * @param srcPath - Path of the file to write.\n * @param value - The {@link JsonValue | JsonValue} to be written.\n */\n public writeJsonFileSync(srcPath: string, value: JsonValue): Result<boolean> {\n return captureResult(() => {\n const fullPath = path.resolve(srcPath);\n const stringified = this.config.json.stringify(value, undefined, 2);\n if (stringified === undefined && this.config.allowUndefinedWrite !== true) {\n throw new Error(`Could not stringify ${value}`);\n }\n fs.writeFileSync(fullPath, stringified!);\n return true;\n });\n }\n}\n\n/**\n * @public\n */\nexport const DefaultJsonFsHelper: JsonFsHelper = new JsonFsHelper();\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { JsonValue } from '../json';
|
|
2
|
+
/**
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export type JsonReviver = (key: string, value: JsonValue) => JsonValue;
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export type JsonReplacerFunction = (key: string, value: JsonValue) => JsonValue;
|
|
10
|
+
/**
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export type JsonReplacerArray = (string | number)[];
|
|
14
|
+
/**
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export type JsonReplacer = JsonReplacerFunction | JsonReplacerArray;
|
|
18
|
+
/**
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export interface IJsonLike {
|
|
22
|
+
parse(text: string, reviver?: JsonReviver, options?: unknown): JsonValue | undefined;
|
|
23
|
+
stringify(value: JsonValue, replacer?: JsonReplacer, space?: string | number): string | undefined;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export declare const DefaultJsonLike: IJsonLike;
|
|
29
|
+
//# sourceMappingURL=jsonLike.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonLike.d.ts","sourceRoot":"","sources":["../../../src/packlets/json-file/jsonLike.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,oBAAoB,GAAG,iBAAiB,CAAC;AAEpE;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;IACrF,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnG;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,SAAgB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2024 Erik Fortune
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
* furnished to do so, subject to the following conditions:
|
|
11
|
+
*
|
|
12
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
* copies or substantial portions of the Software.
|
|
14
|
+
*
|
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
* SOFTWARE.
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.DefaultJsonLike = void 0;
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
exports.DefaultJsonLike = JSON;
|
|
29
|
+
//# sourceMappingURL=jsonLike.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonLike.js","sourceRoot":"","sources":["../../../src/packlets/json-file/jsonLike.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAgCH;;GAEG;AACU,QAAA,eAAe,GAAc,IAAI,CAAC","sourcesContent":["/*\n * Copyright (c) 2024 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { JsonValue } from '../json';\n\n/**\n * @public\n */\nexport type JsonReviver = (key: string, value: JsonValue) => JsonValue;\n\n/**\n * @public\n */\nexport type JsonReplacerFunction = (key: string, value: JsonValue) => JsonValue;\n\n/**\n * @public\n */\nexport type JsonReplacerArray = (string | number)[];\n\n/**\n * @public\n */\nexport type JsonReplacer = JsonReplacerFunction | JsonReplacerArray;\n\n/**\n * @public\n */\nexport interface IJsonLike {\n parse(text: string, reviver?: JsonReviver, options?: unknown): JsonValue | undefined;\n stringify(value: JsonValue, replacer?: JsonReplacer, space?: string | number): string | undefined;\n}\n\n/**\n * @public\n */\nexport const DefaultJsonLike: IJsonLike = JSON;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-json-base",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1-alpha.0",
|
|
4
4
|
"description": "Typescript types and basic functions for working with json",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "dist/ts-json-base.d.ts",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"homepage": "https://github.com/ErikFortune/fgv/tree/main/libraries/ts-json-base#readme",
|
|
17
17
|
"sideEffects": false,
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@fgv/ts-utils": "3.0.
|
|
20
|
-
"@fgv/ts-utils-jest": "3.0.
|
|
19
|
+
"@fgv/ts-utils": "3.0.1-alpha.0",
|
|
20
|
+
"@fgv/ts-utils-jest": "3.0.1-alpha.0",
|
|
21
21
|
"@types/jest": "^29.5.11",
|
|
22
22
|
"@types/mustache": "^4.2.5",
|
|
23
23
|
"@types/node": "^20.11.5",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@microsoft/api-documenter": "^7.23.17"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@fgv/ts-utils": "
|
|
46
|
+
"@fgv/ts-utils": "3.0.1-alpha.0",
|
|
47
47
|
"mustache": "^4.2.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|