@thi.ng/file-io 0.1.0 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2022-05-18T12:59:20Z
3
+ - **Last updated**: 2022-05-19T13:17:54Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
@@ -9,6 +9,12 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
9
9
  **Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
10
10
  and/or version bumps of transitive dependencies.
11
11
 
12
+ ## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/file-io@0.2.0) (2022-05-19)
13
+
14
+ #### 🚀 Features
15
+
16
+ - add dirs() iterator, add writeFile(), dry-run handling ([0279db8](https://github.com/thi-ng/umbrella/commit/0279db8))
17
+
12
18
  ## [0.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/file-io@0.1.0) (2022-05-18)
13
19
 
14
20
  #### 🚀 Features
package/delete.d.ts CHANGED
@@ -1,3 +1,12 @@
1
1
  import type { ILogger } from "@thi.ng/logger";
2
- export declare const deleteFile: (path: string, logger?: ILogger | undefined) => void;
2
+ /**
3
+ * Deletes file at given path. If `dryRun` is true (default: false), the file
4
+ * WON'T be deleted, however if a `logger` is provided then at least a dry-run
5
+ * log message will be emitted.
6
+ *
7
+ * @param path
8
+ * @param logger
9
+ * @param dryRun
10
+ */
11
+ export declare const deleteFile: (path: string, logger?: ILogger | undefined, dryRun?: boolean) => void;
3
12
  //# sourceMappingURL=delete.d.ts.map
package/delete.js CHANGED
@@ -1,5 +1,16 @@
1
1
  import { unlinkSync } from "fs";
2
- export const deleteFile = (path, logger) => {
3
- logger && logger.debug("deleting file:", path);
2
+ /**
3
+ * Deletes file at given path. If `dryRun` is true (default: false), the file
4
+ * WON'T be deleted, however if a `logger` is provided then at least a dry-run
5
+ * log message will be emitted.
6
+ *
7
+ * @param path
8
+ * @param logger
9
+ * @param dryRun
10
+ */
11
+ export const deleteFile = (path, logger, dryRun = false) => {
12
+ logger && logger.info(`${dryRun ? "[dryrun] " : ""}deleting file: ${path}`);
13
+ if (dryRun)
14
+ return;
4
15
  unlinkSync(path);
5
16
  };
package/files.d.ts CHANGED
@@ -3,10 +3,31 @@ import type { ILogger } from "@thi.ng/logger";
3
3
  * Recursively reads given directory (up to given max. depth, default: infinite)
4
4
  * and yields sequence of file names matching given extension (or regexp).
5
5
  *
6
+ * @remarks
7
+ * If NO `match` is given, all files will be matched. Directory names will not
8
+ * be tested and are always traversed (up to given `maxDepth`).
9
+ *
10
+ * The optional `logger` is only used to log errors for files which couldn't be
11
+ * accessed.
12
+ *
13
+ * @param dir
14
+ * @param match
15
+ * @param maxDepth
16
+ * @param logger
17
+ */
18
+ export declare const files: (dir: string, match?: string | RegExp, maxDepth?: number, logger?: ILogger | undefined) => IterableIterator<string>;
19
+ /**
20
+ * Similar to {@link files}, however yields iterator of only matching
21
+ * sub-directories in given `dir`. Normal files are being ignored.
22
+ *
23
+ * @remarks
24
+ * Unlike the regex matching in {@link files}, here the regex will be applied to
25
+ * the _full_ sub-path (starting with `dir`) in order to determine a match.
26
+ *
6
27
  * @param dir
7
28
  * @param match
8
29
  * @param maxDepth
9
30
  * @param logger
10
31
  */
11
- export declare const files: (dir: string, match: string | RegExp, maxDepth?: number, logger?: ILogger | undefined) => IterableIterator<string>;
32
+ export declare const dirs: (dir: string, match?: string | RegExp, maxDepth?: number, logger?: ILogger | undefined) => IterableIterator<string>;
12
33
  //# sourceMappingURL=files.d.ts.map
package/files.js CHANGED
@@ -5,27 +5,32 @@ import { sep } from "path";
5
5
  * Recursively reads given directory (up to given max. depth, default: infinite)
6
6
  * and yields sequence of file names matching given extension (or regexp).
7
7
  *
8
+ * @remarks
9
+ * If NO `match` is given, all files will be matched. Directory names will not
10
+ * be tested and are always traversed (up to given `maxDepth`).
11
+ *
12
+ * The optional `logger` is only used to log errors for files which couldn't be
13
+ * accessed.
14
+ *
8
15
  * @param dir
9
16
  * @param match
10
17
  * @param maxDepth
11
18
  * @param logger
12
19
  */
13
- export const files = (dir, match, maxDepth = Infinity, logger) => __files(dir, match, logger, maxDepth, 0);
14
- function* __files(dir, match, logger, maxDepth = Infinity, depth = 0) {
20
+ export const files = (dir, match = "", maxDepth = Infinity, logger) => __files(dir, match, logger, maxDepth, 0);
21
+ function* __files(dir, match = "", logger, maxDepth = Infinity, depth = 0) {
15
22
  if (depth >= maxDepth)
16
23
  return;
17
- const re = isString(match)
18
- ? new RegExp(`${match.replace(/\./g, "\\.")}$`)
19
- : match;
24
+ const re = __ensureRegEx(match);
20
25
  for (let f of readdirSync(dir)) {
21
26
  const curr = dir + sep + f;
22
27
  try {
23
- if (re.test(f)) {
24
- yield curr;
25
- }
26
- else if (statSync(curr).isDirectory()) {
28
+ if (statSync(curr).isDirectory()) {
27
29
  yield* __files(curr, match, logger, maxDepth, depth + 1);
28
30
  }
31
+ else if (re.test(f)) {
32
+ yield curr;
33
+ }
29
34
  }
30
35
  catch (e) {
31
36
  logger &&
@@ -33,3 +38,38 @@ function* __files(dir, match, logger, maxDepth = Infinity, depth = 0) {
33
38
  }
34
39
  }
35
40
  }
41
+ /**
42
+ * Similar to {@link files}, however yields iterator of only matching
43
+ * sub-directories in given `dir`. Normal files are being ignored.
44
+ *
45
+ * @remarks
46
+ * Unlike the regex matching in {@link files}, here the regex will be applied to
47
+ * the _full_ sub-path (starting with `dir`) in order to determine a match.
48
+ *
49
+ * @param dir
50
+ * @param match
51
+ * @param maxDepth
52
+ * @param logger
53
+ */
54
+ export const dirs = (dir, match = "", maxDepth = Infinity, logger) => __dirs(dir, match, logger, maxDepth, 0);
55
+ function* __dirs(dir, match = "", logger, maxDepth = Infinity, depth = 0) {
56
+ if (depth >= maxDepth)
57
+ return;
58
+ const re = __ensureRegEx(match);
59
+ for (let f of readdirSync(dir)) {
60
+ const curr = dir + sep + f;
61
+ try {
62
+ if (statSync(curr).isDirectory()) {
63
+ if (re.test(curr))
64
+ yield curr;
65
+ yield* __dirs(curr, match, logger, maxDepth, depth + 1);
66
+ }
67
+ }
68
+ catch (e) {
69
+ logger &&
70
+ logger.warn(`ignoring file/dir: ${f} (${e.message})`);
71
+ }
72
+ }
73
+ }
74
+ /** @internal */
75
+ const __ensureRegEx = (match) => isString(match) ? new RegExp(`${match.replace(/\./g, "\\.")}$`) : match;
package/index.d.ts CHANGED
@@ -4,4 +4,5 @@ export * from "./files.js";
4
4
  export * from "./json.js";
5
5
  export * from "./temp.js";
6
6
  export * from "./text.js";
7
+ export * from "./write.js";
7
8
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -4,3 +4,4 @@ export * from "./files.js";
4
4
  export * from "./json.js";
5
5
  export * from "./temp.js";
6
6
  export * from "./text.js";
7
+ export * from "./write.js";
package/json.d.ts CHANGED
@@ -1,5 +1,20 @@
1
1
  import type { Fn3, NumOrString } from "@thi.ng/api";
2
2
  import type { ILogger } from "@thi.ng/logger";
3
3
  export declare const readJSON: (path: string, logger?: ILogger | undefined) => any;
4
- export declare const writeJSON: (path: string, obj: any, replacer?: Fn3<any, string, any, any> | NumOrString[] | null | undefined, space?: NumOrString | undefined, logger?: ILogger | undefined) => void;
4
+ /**
5
+ * Serializes `obj` to JSON and writes result to UTF-8 file `path`. See
6
+ * {@link writeText} for more details.
7
+ *
8
+ * @remarks
9
+ * The `replacer` and `space` args are the same as supported by
10
+ * `JSON.stringify()`.
11
+ *
12
+ * @param path
13
+ * @param obj
14
+ * @param replacer
15
+ * @param space
16
+ * @param logger
17
+ * @param dryRun
18
+ */
19
+ export declare const writeJSON: (path: string, obj: any, replacer?: Fn3<any, string, any, any> | NumOrString[] | null | undefined, space?: NumOrString | undefined, logger?: ILogger | undefined, dryRun?: boolean) => void;
5
20
  //# sourceMappingURL=json.d.ts.map
package/json.js CHANGED
@@ -1,3 +1,18 @@
1
1
  import { readText, writeText } from "./text.js";
2
2
  export const readJSON = (path, logger) => JSON.parse(readText(path, logger));
3
- export const writeJSON = (path, obj, replacer, space, logger) => writeText(path, JSON.stringify(obj, replacer, space), logger);
3
+ /**
4
+ * Serializes `obj` to JSON and writes result to UTF-8 file `path`. See
5
+ * {@link writeText} for more details.
6
+ *
7
+ * @remarks
8
+ * The `replacer` and `space` args are the same as supported by
9
+ * `JSON.stringify()`.
10
+ *
11
+ * @param path
12
+ * @param obj
13
+ * @param replacer
14
+ * @param space
15
+ * @param logger
16
+ * @param dryRun
17
+ */
18
+ export const writeJSON = (path, obj, replacer, space, logger, dryRun = false) => writeText(path, JSON.stringify(obj, replacer, space) + "\n", logger, dryRun);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/file-io",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Assorted file I/O utils (with logging support) for NodeJS",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -87,11 +87,14 @@
87
87
  },
88
88
  "./text": {
89
89
  "default": "./text.js"
90
+ },
91
+ "./write": {
92
+ "default": "./write.js"
90
93
  }
91
94
  },
92
95
  "thi.ng": {
93
96
  "status": "stable",
94
97
  "year": 2022
95
98
  },
96
- "gitHead": "f696c94665a3adef4fa475d99dd2e18ceb15863f\n"
99
+ "gitHead": "ec1685021284dc0e98bbfe67abefc3d1f6c0f7dd\n"
97
100
  }
package/text.d.ts CHANGED
@@ -1,4 +1,14 @@
1
1
  import type { ILogger } from "@thi.ng/logger";
2
2
  export declare const readText: (path: string, logger?: ILogger | undefined) => string;
3
- export declare const writeText: (path: string, body: string | string[], logger?: ILogger | undefined) => void;
3
+ /**
4
+ * Writes `body` as UTF-8 file to given `path`. If `dryRun` is true (default:
5
+ * false), the file WON'T be written, however if a `logger` is provided then at
6
+ * least a dry-run log message will be emitted.
7
+ *
8
+ * @param path
9
+ * @param body
10
+ * @param logger
11
+ * @param dryRun
12
+ */
13
+ export declare const writeText: (path: string, body: string | string[], logger?: ILogger | undefined, dryRun?: boolean) => void;
4
14
  //# sourceMappingURL=text.d.ts.map
package/text.js CHANGED
@@ -1,12 +1,18 @@
1
1
  import { isArray } from "@thi.ng/checks/is-array";
2
- import { readFileSync, writeFileSync } from "fs";
3
- import { ensureDirForFile } from "./ensure-dir.js";
2
+ import { readFileSync } from "fs";
3
+ import { writeFile } from "./write.js";
4
4
  export const readText = (path, logger) => {
5
5
  logger && logger.debug("reading file:", path);
6
6
  return readFileSync(path, "utf-8");
7
7
  };
8
- export const writeText = (path, body, logger) => {
9
- logger && logger.debug("writing file:", path);
10
- ensureDirForFile(path);
11
- writeFileSync(path, isArray(body) ? body.join("\n") : body, "utf-8");
12
- };
8
+ /**
9
+ * Writes `body` as UTF-8 file to given `path`. If `dryRun` is true (default:
10
+ * false), the file WON'T be written, however if a `logger` is provided then at
11
+ * least a dry-run log message will be emitted.
12
+ *
13
+ * @param path
14
+ * @param body
15
+ * @param logger
16
+ * @param dryRun
17
+ */
18
+ export const writeText = (path, body, logger, dryRun = false) => writeFile(path, isArray(body) ? body.join("\n") : body, "utf-8", logger, dryRun);
package/write.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ /// <reference types="node" />
2
+ import type { TypedArray } from "@thi.ng/api";
3
+ import type { ILogger } from "@thi.ng/logger";
4
+ import { WriteFileOptions } from "fs";
5
+ /**
6
+ * Writes `body` as to given `path` (using optional `opts` to define encoding).
7
+ * If `dryRun` is true (default: false), the file WON'T be written, however if a
8
+ * `logger` is provided then at least a dry-run log message will be emitted.
9
+ *
10
+ * @param path
11
+ * @param body
12
+ * @param opts
13
+ * @param logger
14
+ * @param dryRun
15
+ */
16
+ export declare const writeFile: (path: string, body: string | TypedArray, opts?: WriteFileOptions | undefined, logger?: ILogger | undefined, dryRun?: boolean) => void;
17
+ //# sourceMappingURL=write.d.ts.map
package/write.js ADDED
@@ -0,0 +1,21 @@
1
+ import { isString } from "@thi.ng/checks/is-string";
2
+ import { writeFileSync } from "fs";
3
+ import { ensureDirForFile } from "./ensure-dir.js";
4
+ /**
5
+ * Writes `body` as to given `path` (using optional `opts` to define encoding).
6
+ * If `dryRun` is true (default: false), the file WON'T be written, however if a
7
+ * `logger` is provided then at least a dry-run log message will be emitted.
8
+ *
9
+ * @param path
10
+ * @param body
11
+ * @param opts
12
+ * @param logger
13
+ * @param dryRun
14
+ */
15
+ export const writeFile = (path, body, opts, logger, dryRun = false) => {
16
+ logger && logger.info(`${dryRun ? "[dryrun] " : ""}writing file: ${path}`);
17
+ if (dryRun)
18
+ return;
19
+ ensureDirForFile(path);
20
+ writeFileSync(path, body, !opts && isString(body) ? "utf-8" : opts);
21
+ };