@zthun/crumbtrail-cli 2.4.11 → 3.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zthun/crumbtrail-cli",
3
- "version": "2.4.11",
3
+ "version": "3.0.0",
4
4
  "description": "An application for crumbtrail that helps with debugging io issues",
5
5
  "author": "Anthony Bonta",
6
6
  "license": "MIT",
@@ -10,47 +10,36 @@
10
10
  "directory": "packages/crumbtrail-cli"
11
11
  },
12
12
  "type": "module",
13
- "types": "./dist/index.d.mts",
14
- "main": "./dist/index.cjs",
15
- "module": "./dist/index.js",
16
- "exports": {
17
- "types": "./dist/index.d.mts",
18
- "require": "./dist/index.cjs",
19
- "import": "./dist/index.js"
20
- },
21
- "bin": "dist/cli.js",
13
+ "bin": "dist/main.js",
22
14
  "engines": {
23
15
  "node": ">=24.13.0"
24
16
  },
25
17
  "scripts": {
26
18
  "build": "vite build",
27
- "start": "node ./dist/cli.js",
28
- "debug": "tsx src/cli.mts"
19
+ "start": "node ./dist/main.js",
20
+ "debug": "tsx src/main.mts"
29
21
  },
30
22
  "publishConfig": {
31
23
  "access": "public"
32
24
  },
33
25
  "dependencies": {
34
- "@zthun/crumbtrail-fs": "^2.4.11",
35
- "@zthun/helpful-fn": "^9.11.13",
36
- "@zthun/lumberjacky-log": "^4.0.7",
37
- "commander": "^14.0.3",
38
- "fast-glob": "^3.3.3",
39
- "lodash-es": "^4.18.1",
40
- "minimatch": "^10.2.5"
26
+ "@zthun/crumbtrail-fs": "^3.0.0",
27
+ "@zthun/lumberjacky-log": "^4.0.9",
28
+ "commander": "^15.0.0"
41
29
  },
42
30
  "devDependencies": {
43
- "@zthun/janitor-build-config": "^20.0.6",
44
- "@zthun/janitor-ts-config": "^20.0.4",
45
- "tsx": "^4.22.3",
46
- "typescript": "~6.0.3",
47
- "vite": "^8.0.14",
48
- "vitest": "^4.1.7",
49
- "vitest-mock-extended": "^4.0.0"
31
+ "@zthun/janitor-build-config": "^21.1.3",
32
+ "@zthun/janitor-ts-config": "^21.1.3",
33
+ "@zthun/janitor-vite": "^21.1.4",
34
+ "tsx": "^4.23.12",
35
+ "typescript": "^6.0.3",
36
+ "vite": "^8.2.2",
37
+ "vitest": "^4.1.11",
38
+ "vitest-mock-extended": "^5.1.1"
50
39
  },
51
40
  "files": [
52
41
  "dist"
53
42
  ],
54
43
  "sideEffects": false,
55
- "gitHead": "b70b686b5976f3837f8fe6fbafe49b344251f20d"
44
+ "gitHead": "3aac05ac1a20f55ac9617dd55f69063e2cde261f"
56
45
  }
package/dist/cli.cjs DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env node
2
- const require_watch = require("./watch-DXvYTgIr.cjs");
3
- let _zthun_crumbtrail_fs = require("@zthun/crumbtrail-fs");
4
- let _zthun_lumberjacky_log = require("@zthun/lumberjacky-log");
5
- let commander = require("commander");
6
- //#region src/cli.mts
7
- var logger = new _zthun_lumberjacky_log.ZLoggerConsole(console);
8
- var application = new commander.Command();
9
- application.name("crumbtrail-cli").description("Crumbtrail utilities for debugging");
10
- application.command("watch", { isDefault: true }).description("Watch a directory and log changes").option("-d, --directory <dir>", "The directory to watch", process.cwd()).option("-g, --glob <pattern>", "Glob pattern (repeatable)", (val, prev) => prev.concat(val), []).action(async (options) => {
11
- const result = await new require_watch.ZCrumbtrailWatch(logger).run(options);
12
- process.exitCode = result;
13
- });
14
- application.command("nudge").description("Touch directory timestamps to prompt a refresh").option("-d, --directory <path>", "Directory to refresh", process.cwd()).option("--recursive", "Nudge all subdirectories as well", false).option("--silent", "Do not log any output. Nudge silently", false).option("-e, --every <ms>", "Time between nudges in milliseconds", (v) => Number.parseInt(v, 10), _zthun_crumbtrail_fs.ZWatchDelay).action(async (options) => {
15
- const command = new require_watch.ZCrumbtrailNudge(options.silent ? new _zthun_lumberjacky_log.ZLoggerSilent() : logger);
16
- process.exitCode = await command.run(options);
17
- });
18
- application.parse();
19
- //#endregion
20
-
21
- //# sourceMappingURL=cli.cjs.map
package/dist/cli.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.cjs","names":["ZWatchDelay","ZLoggerConsole","ZLoggerSilent","Command","ZCrumbtrailNudge","ZCrumbtrailWatch","logger","console","application","name","description","command","isDefault","option","process","cwd","val","prev","concat","action","options","result","run","exitCode","v","Number","parseInt","log","silent","parse"],"sources":["../src/cli.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ZWatchDelay } from \"@zthun/crumbtrail-fs\";\nimport { ZLoggerConsole, ZLoggerSilent } from \"@zthun/lumberjacky-log\";\nimport { Command } from \"commander\";\n\nimport type { IZCrumbtrailNudgeOptions } from \"./nudge/nudge.mjs\";\nimport { ZCrumbtrailNudge } from \"./nudge/nudge.mjs\";\nimport type { IZCrumbtrailWatchOptions } from \"./watch/watch.mjs\";\nimport { ZCrumbtrailWatch } from \"./watch/watch.mjs\";\n\nconst logger = new ZLoggerConsole(console);\nconst application = new Command();\n\napplication\n .name(\"crumbtrail-cli\")\n .description(\"Crumbtrail utilities for debugging\");\n\napplication\n .command(\"watch\", { isDefault: true })\n .description(\"Watch a directory and log changes\")\n .option(\"-d, --directory <dir>\", \"The directory to watch\", process.cwd())\n .option(\n \"-g, --glob <pattern>\",\n \"Glob pattern (repeatable)\",\n (val, prev: string[]) => prev.concat(val),\n [],\n )\n .action(async (options: IZCrumbtrailWatchOptions) => {\n const command = new ZCrumbtrailWatch(logger);\n const result = await command.run(options);\n process.exitCode = result;\n });\n\napplication\n .command(\"nudge\")\n .description(\"Touch directory timestamps to prompt a refresh\")\n .option(\"-d, --directory <path>\", \"Directory to refresh\", process.cwd())\n .option(\"--recursive\", \"Nudge all subdirectories as well\", false)\n .option(\"--silent\", \"Do not log any output. Nudge silently\", false)\n .option(\n \"-e, --every <ms>\",\n \"Time between nudges in milliseconds\",\n (v) => Number.parseInt(v, 10),\n ZWatchDelay,\n )\n .action(async (options: IZCrumbtrailNudgeOptions & { silent: boolean }) => {\n const log = options.silent ? new ZLoggerSilent() : logger;\n const command = new ZCrumbtrailNudge(log);\n process.exitCode = await command.run(options);\n });\n\napplication.parse();\n"],"mappings":";;;;;;AAWA,IAAMM,SAAS,IAAIL,uBAAAA,eAAeM,OAAAA;AAClC,IAAMC,cAAc,IAAIL,UAAAA,QAAAA;AAExBK,YACGC,KAAK,gBAAA,EACLC,YAAY,oCAAA;AAEfF,YACGG,QAAQ,SAAS,EAAEC,WAAW,KAAK,CAAA,EACnCF,YAAY,mCAAA,EACZG,OAAO,yBAAyB,0BAA0BC,QAAQC,IAAG,CAAA,EACrEF,OACC,wBACA,8BACCG,KAAKC,SAAmBA,KAAKC,OAAOF,GAAAA,GACrC,CAAA,CAAE,EAEHG,OAAO,OAAOC,YAAAA;CAEb,MAAMC,SAAS,MAAMV,IADDN,cAAAA,iBAAiBC,MAChBK,EAAQW,IAAIF,OAAAA;CACjCN,QAAQS,WAAWF;AACrB,CAAA;AAEFb,YACGG,QAAQ,OAAA,EACRD,YAAY,gDAAA,EACZG,OAAO,0BAA0B,wBAAwBC,QAAQC,IAAG,CAAA,EACpEF,OAAO,eAAe,oCAAoC,KAAA,EAC1DA,OAAO,YAAY,0CAA0C,KAAA,EAC7DA,OACC,oBACA,wCACCW,MAAMC,OAAOC,SAASF,GAAG,EAAA,GAC1BxB,qBAAAA,WAAAA,EAEDmB,OAAO,OAAOC,YAAAA;CAEb,MAAMT,UAAU,IAAIP,cAAAA,iBADRgB,QAAQQ,SAAS,IAAI1B,uBAAAA,cAAAA,IAAkBI,MACdqB;CACrCb,QAAQS,WAAW,MAAMZ,QAAQW,IAAIF,OAAAA;AACvC,CAAA;AAEFZ,YAAYqB,MAAK"}
package/dist/cli.d.mts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
package/dist/cli.js DELETED
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env node
2
- import { n as ZCrumbtrailNudge, t as ZCrumbtrailWatch } from "./watch-peSooqy2.js";
3
- import { ZWatchDelay } from "@zthun/crumbtrail-fs";
4
- import { ZLoggerConsole, ZLoggerSilent } from "@zthun/lumberjacky-log";
5
- import { Command } from "commander";
6
- //#region src/cli.mts
7
- var logger = new ZLoggerConsole(console);
8
- var application = new Command();
9
- application.name("crumbtrail-cli").description("Crumbtrail utilities for debugging");
10
- application.command("watch", { isDefault: true }).description("Watch a directory and log changes").option("-d, --directory <dir>", "The directory to watch", process.cwd()).option("-g, --glob <pattern>", "Glob pattern (repeatable)", (val, prev) => prev.concat(val), []).action(async (options) => {
11
- const result = await new ZCrumbtrailWatch(logger).run(options);
12
- process.exitCode = result;
13
- });
14
- application.command("nudge").description("Touch directory timestamps to prompt a refresh").option("-d, --directory <path>", "Directory to refresh", process.cwd()).option("--recursive", "Nudge all subdirectories as well", false).option("--silent", "Do not log any output. Nudge silently", false).option("-e, --every <ms>", "Time between nudges in milliseconds", (v) => Number.parseInt(v, 10), ZWatchDelay).action(async (options) => {
15
- const command = new ZCrumbtrailNudge(options.silent ? new ZLoggerSilent() : logger);
16
- process.exitCode = await command.run(options);
17
- });
18
- application.parse();
19
- //#endregion
20
-
21
- //# sourceMappingURL=cli.js.map
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.js","names":["ZWatchDelay","ZLoggerConsole","ZLoggerSilent","Command","ZCrumbtrailNudge","ZCrumbtrailWatch","logger","console","application","name","description","command","isDefault","option","process","cwd","val","prev","concat","action","options","result","run","exitCode","v","Number","parseInt","log","silent","parse"],"sources":["../src/cli.mts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { ZWatchDelay } from \"@zthun/crumbtrail-fs\";\nimport { ZLoggerConsole, ZLoggerSilent } from \"@zthun/lumberjacky-log\";\nimport { Command } from \"commander\";\n\nimport type { IZCrumbtrailNudgeOptions } from \"./nudge/nudge.mjs\";\nimport { ZCrumbtrailNudge } from \"./nudge/nudge.mjs\";\nimport type { IZCrumbtrailWatchOptions } from \"./watch/watch.mjs\";\nimport { ZCrumbtrailWatch } from \"./watch/watch.mjs\";\n\nconst logger = new ZLoggerConsole(console);\nconst application = new Command();\n\napplication\n .name(\"crumbtrail-cli\")\n .description(\"Crumbtrail utilities for debugging\");\n\napplication\n .command(\"watch\", { isDefault: true })\n .description(\"Watch a directory and log changes\")\n .option(\"-d, --directory <dir>\", \"The directory to watch\", process.cwd())\n .option(\n \"-g, --glob <pattern>\",\n \"Glob pattern (repeatable)\",\n (val, prev: string[]) => prev.concat(val),\n [],\n )\n .action(async (options: IZCrumbtrailWatchOptions) => {\n const command = new ZCrumbtrailWatch(logger);\n const result = await command.run(options);\n process.exitCode = result;\n });\n\napplication\n .command(\"nudge\")\n .description(\"Touch directory timestamps to prompt a refresh\")\n .option(\"-d, --directory <path>\", \"Directory to refresh\", process.cwd())\n .option(\"--recursive\", \"Nudge all subdirectories as well\", false)\n .option(\"--silent\", \"Do not log any output. Nudge silently\", false)\n .option(\n \"-e, --every <ms>\",\n \"Time between nudges in milliseconds\",\n (v) => Number.parseInt(v, 10),\n ZWatchDelay,\n )\n .action(async (options: IZCrumbtrailNudgeOptions & { silent: boolean }) => {\n const log = options.silent ? new ZLoggerSilent() : logger;\n const command = new ZCrumbtrailNudge(log);\n process.exitCode = await command.run(options);\n });\n\napplication.parse();\n"],"mappings":";;;;;;AAWA,IAAMM,SAAS,IAAIL,eAAeM,OAAAA;AAClC,IAAMC,cAAc,IAAIL,QAAAA;AAExBK,YACGC,KAAK,gBAAA,EACLC,YAAY,oCAAA;AAEfF,YACGG,QAAQ,SAAS,EAAEC,WAAW,KAAK,CAAA,EACnCF,YAAY,mCAAA,EACZG,OAAO,yBAAyB,0BAA0BC,QAAQC,IAAG,CAAA,EACrEF,OACC,wBACA,8BACCG,KAAKC,SAAmBA,KAAKC,OAAOF,GAAAA,GACrC,CAAA,CAAE,EAEHG,OAAO,OAAOC,YAAAA;CAEb,MAAMC,SAAS,MAAMV,IADDN,iBAAiBC,MAChBK,EAAQW,IAAIF,OAAAA;CACjCN,QAAQS,WAAWF;AACrB,CAAA;AAEFb,YACGG,QAAQ,OAAA,EACRD,YAAY,gDAAA,EACZG,OAAO,0BAA0B,wBAAwBC,QAAQC,IAAG,CAAA,EACpEF,OAAO,eAAe,oCAAoC,KAAA,EAC1DA,OAAO,YAAY,0CAA0C,KAAA,EAC7DA,OACC,oBACA,wCACCW,MAAMC,OAAOC,SAASF,GAAG,EAAA,GAC1BxB,WAAAA,EAEDmB,OAAO,OAAOC,YAAAA;CAEb,MAAMT,UAAU,IAAIP,iBADRgB,QAAQQ,SAAS,IAAI1B,cAAAA,IAAkBI,MACdqB;CACrCb,QAAQS,WAAW,MAAMZ,QAAQW,IAAIF,OAAAA;AACvC,CAAA;AAEFZ,YAAYqB,MAAK"}
package/dist/index.cjs DELETED
@@ -1,4 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_watch = require("./watch-DXvYTgIr.cjs");
3
- exports.ZCrumbtrailNudge = require_watch.ZCrumbtrailNudge;
4
- exports.ZCrumbtrailWatch = require_watch.ZCrumbtrailWatch;
package/dist/index.d.mts DELETED
@@ -1,2 +0,0 @@
1
- export * from './nudge/nudge.mjs';
2
- export * from './watch/watch.mjs';
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- import { n as ZCrumbtrailNudge, t as ZCrumbtrailWatch } from "./watch-peSooqy2.js";
2
- export { ZCrumbtrailNudge, ZCrumbtrailWatch };
@@ -1,52 +0,0 @@
1
- import { IZLogger } from '@zthun/lumberjacky-log';
2
- /**
3
- * Options for the nudge command.
4
- */
5
- export interface IZCrumbtrailNudgeOptions {
6
- /**
7
- * The directory to nudge.
8
- *
9
- * The default if not specified is the current working directory.
10
- */
11
- directory?: string;
12
- /**
13
- * Whether to nudge recursively.
14
- *
15
- * Warning: This can have severe CPU
16
- * usage for deep directories.
17
- *
18
- * Default is false.
19
- */
20
- recursive?: boolean;
21
- /**
22
- * The total number of milliseconds to wait
23
- * between nudges.
24
- *
25
- * Default is {@link ZWatchDelay}
26
- */
27
- every?: number;
28
- }
29
- /**
30
- * An operation to continuously nudge a directory.
31
- *
32
- * This is a special operation that lists the contents of a targeted parent directory.
33
- * The main reason for this is to work around an issue when you are running inside of
34
- * a container and your host is not linux.
35
- *
36
- * A lot of times, you will not receive events in this situation for add and update
37
- * until the virtual file bridge is refreshed by listing the outer directory contents.
38
- * This command helps to force the bridge to send file change events. You should
39
- * only need this if you are running on a non linux host inside a docker container.
40
- *
41
- * Run a separate container in the background and just nudge the directory
42
- * for however long you need.
43
- */
44
- export declare class ZCrumbtrailNudge {
45
- private _controller?;
46
- private _resolve?;
47
- private _promise?;
48
- private readonly _logger;
49
- constructor(logger: IZLogger);
50
- kill(): Promise<void>;
51
- run(options?: IZCrumbtrailNudgeOptions): Promise<number>;
52
- }
@@ -1,101 +0,0 @@
1
- import { IZLogEntry, IZLogger } from '@zthun/lumberjacky-log';
2
- /**
3
- * Arguments for the crumbtrail app.
4
- */
5
- export interface IZCrumbtrailWatchOptions {
6
- /**
7
- * The directory to watch.
8
- *
9
- * If this is falsy, then the cwd is used.
10
- */
11
- directory?: string;
12
- /**
13
- * The list of file globs to watch.
14
- *
15
- * If this is falsy or empty, then '**' is used.
16
- */
17
- globs?: string[];
18
- }
19
- /**
20
- * The root application for the crumbtrail cli.
21
- */
22
- export declare class ZCrumbtrailWatch {
23
- private _logger;
24
- private _globs;
25
- private _watch;
26
- private _ready;
27
- private _promise;
28
- private _resolve;
29
- /**
30
- * Gets the entry for a basic information message.
31
- *
32
- * @returns
33
- * The log entry for a basic information message.
34
- */
35
- static msg(msg: string): IZLogEntry;
36
- /**
37
- * Gets the message for when a file is added.
38
- *
39
- * @returns
40
- * The message for when a file is added.
41
- */
42
- static add(path: string): IZLogEntry;
43
- /**
44
- * Gets the message for when a file/folder is removed.
45
- *
46
- * @returns
47
- * The message for when a file/folder is added.
48
- */
49
- static remove(path: string): IZLogEntry;
50
- /**
51
- * Gets the message for when a file is updated.
52
- *
53
- * @returns
54
- * The message for when a file is updated.
55
- */
56
- static update(path: string): IZLogEntry;
57
- /**
58
- * Gets the current directory being watched.
59
- *
60
- * @returns
61
- * The directory that is watching for events.
62
- */
63
- watching(): Promise<string | undefined>;
64
- /**
65
- * Gets the list of globs that filter the directory contents.
66
- *
67
- * @returns
68
- * The list of globs that filter the directory contents.
69
- */
70
- globs(): Promise<string[] | undefined>;
71
- /**
72
- * Returns a promise that can be awaited on to
73
- * make sure the watch is initialized.
74
- */
75
- ready(): Promise<void>;
76
- /**
77
- * Initializes a new instance of this object.
78
- *
79
- * @param logger -
80
- * The logger to use to output events.
81
- */
82
- constructor(logger: IZLogger);
83
- /**
84
- * Kills the application.
85
- */
86
- kill(): Promise<void>;
87
- private _handleFsEvent;
88
- private _handleAdd;
89
- private _handleRemove;
90
- private _handleUpdate;
91
- /**
92
- * Runs the application.
93
- *
94
- * @param args -
95
- * The application arguments.
96
- *
97
- * @returns
98
- * The process exit code.
99
- */
100
- run(args?: IZCrumbtrailWatchOptions): Promise<number>;
101
- }
@@ -1,226 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
15
- }
16
- return to;
17
- };
18
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
- value: mod,
20
- enumerable: true
21
- }) : target, mod));
22
- //#endregion
23
- let node_fs_promises = require("node:fs/promises");
24
- let node_path = require("node:path");
25
- let _zthun_crumbtrail_fs = require("@zthun/crumbtrail-fs");
26
- let _zthun_helpful_fn = require("@zthun/helpful-fn");
27
- let _zthun_lumberjacky_log = require("@zthun/lumberjacky-log");
28
- let fast_glob = require("fast-glob");
29
- fast_glob = __toESM(fast_glob, 1);
30
- let lodash_es = require("lodash-es");
31
- let node_process = require("node:process");
32
- let minimatch = require("minimatch");
33
- //#region src/nudge/nudge.mts
34
- /**
35
- * An operation to continuously nudge a directory.
36
- *
37
- * This is a special operation that lists the contents of a targeted parent directory.
38
- * The main reason for this is to work around an issue when you are running inside of
39
- * a container and your host is not linux.
40
- *
41
- * A lot of times, you will not receive events in this situation for add and update
42
- * until the virtual file bridge is refreshed by listing the outer directory contents.
43
- * This command helps to force the bridge to send file change events. You should
44
- * only need this if you are running on a non linux host inside a docker container.
45
- *
46
- * Run a separate container in the background and just nudge the directory
47
- * for however long you need.
48
- */ var ZCrumbtrailNudge = class {
49
- _controller;
50
- _resolve;
51
- _promise;
52
- _logger;
53
- constructor(logger) {
54
- this._logger = new _zthun_lumberjacky_log.ZLoggerContext("ZCrumbtrailNudge", logger);
55
- }
56
- async kill() {
57
- this._controller?.abort();
58
- delete this._controller;
59
- await this._promise;
60
- delete this._promise;
61
- }
62
- async run(options = {}) {
63
- await this.kill();
64
- const controller = new AbortController();
65
- this._controller = controller;
66
- const { promise, resolve } = Promise.withResolvers();
67
- this._promise = promise;
68
- this._resolve = resolve;
69
- const { directory = process.cwd(), recursive, every = _zthun_crumbtrail_fs.ZWatchDelay } = options;
70
- const ms = (0, _zthun_helpful_fn.firstTruthy)(_zthun_crumbtrail_fs.ZWatchDelay, every);
71
- this._logger.log(new _zthun_lumberjacky_log.ZLogEntryBuilder().info().message(`Starting a nudge loop every ${ms} milliseconds`).build());
72
- if (recursive) this._logger.log(new _zthun_lumberjacky_log.ZLogEntryBuilder().warning().message("Nudging is recursive. Child folders will be nudged too.").build());
73
- do {
74
- this._logger.log(new _zthun_lumberjacky_log.ZLogEntryBuilder().info().message(`Nudging ${directory} to refresh`).build());
75
- await (0, node_fs_promises.readdir)((0, node_path.dirname)(directory)).catch(lodash_es.noop);
76
- if (recursive) await (0, fast_glob.default)(`${directory}/**`, { onlyDirectories: true }).catch(lodash_es.noop);
77
- await (0, _zthun_helpful_fn.sleep)(ms);
78
- } while (!controller.signal.aborted);
79
- resolve(0);
80
- delete this._resolve;
81
- return this._promise;
82
- }
83
- };
84
- //#endregion
85
- //#region src/watch/watch.mts
86
- /**
87
- * The root application for the crumbtrail cli.
88
- */ var ZCrumbtrailWatch = class ZCrumbtrailWatch {
89
- _logger;
90
- _globs;
91
- _watch;
92
- _ready = Promise.resolve();
93
- _promise;
94
- _resolve;
95
- /**
96
- * Gets the entry for a basic information message.
97
- *
98
- * @returns
99
- * The log entry for a basic information message.
100
- */ static msg(msg) {
101
- return new _zthun_lumberjacky_log.ZLogEntryBuilder().info().message(msg).build();
102
- }
103
- /**
104
- * Gets the message for when a file is added.
105
- *
106
- * @returns
107
- * The message for when a file is added.
108
- */ static add(path) {
109
- return new _zthun_lumberjacky_log.ZLogEntryBuilder().info().message(`Node added: ${path}`).build();
110
- }
111
- /**
112
- * Gets the message for when a file/folder is removed.
113
- *
114
- * @returns
115
- * The message for when a file/folder is added.
116
- */ static remove(path) {
117
- return new _zthun_lumberjacky_log.ZLogEntryBuilder().warning().message(`Node removed: ${path}`).build();
118
- }
119
- /**
120
- * Gets the message for when a file is updated.
121
- *
122
- * @returns
123
- * The message for when a file is updated.
124
- */ static update(path) {
125
- return new _zthun_lumberjacky_log.ZLogEntryBuilder().info().message(`Node updated: ${path}`).build();
126
- }
127
- /**
128
- * Gets the current directory being watched.
129
- *
130
- * @returns
131
- * The directory that is watching for events.
132
- */ watching() {
133
- return Promise.resolve(this._watch?.path);
134
- }
135
- /**
136
- * Gets the list of globs that filter the directory contents.
137
- *
138
- * @returns
139
- * The list of globs that filter the directory contents.
140
- */ globs() {
141
- return Promise.resolve(this._globs?.slice());
142
- }
143
- /**
144
- * Returns a promise that can be awaited on to
145
- * make sure the watch is initialized.
146
- */ async ready() {
147
- return this._ready;
148
- }
149
- /**
150
- * Initializes a new instance of this object.
151
- *
152
- * @param logger -
153
- * The logger to use to output events.
154
- */ constructor(logger) {
155
- this._logger = new _zthun_lumberjacky_log.ZLoggerContext("ZCrumbtrailApp", logger);
156
- }
157
- /**
158
- * Kills the application.
159
- */ async kill() {
160
- await this._watch?.stop();
161
- delete this._watch;
162
- delete this._globs;
163
- this._ready = Promise.resolve();
164
- this._resolve?.(0);
165
- await this._promise;
166
- delete this._promise;
167
- }
168
- _handleFsEvent(path, entry) {
169
- const globs = (0, _zthun_helpful_fn.firstDefined)(["**"], this._globs);
170
- const directory = (0, _zthun_helpful_fn.firstDefined)((0, node_process.cwd)(), this._watch?.path);
171
- if (globs?.some((g) => (0, minimatch.minimatch)(path, (0, node_path.resolve)(directory, g)))) this._logger.log(entry);
172
- }
173
- _handleAdd(node) {
174
- this._handleFsEvent(node.path, ZCrumbtrailWatch.add(node.path));
175
- }
176
- _handleRemove(node) {
177
- this._handleFsEvent(node.path, ZCrumbtrailWatch.remove(node.path));
178
- }
179
- _handleUpdate(node) {
180
- this._handleFsEvent(node.path, ZCrumbtrailWatch.update(node.path));
181
- }
182
- /**
183
- * Runs the application.
184
- *
185
- * @param args -
186
- * The application arguments.
187
- *
188
- * @returns
189
- * The process exit code.
190
- */ async run(args = {}) {
191
- if (this._promise) return this._promise;
192
- const { promise, resolve } = Promise.withResolvers();
193
- this._resolve = resolve;
194
- this._promise = promise;
195
- const { directory = (0, node_process.cwd)(), globs = ["**"] } = args;
196
- this._globs = (0, lodash_es.uniq)(globs.slice());
197
- this._globs = this._globs.length ? this._globs : ["**"];
198
- this._watch = new _zthun_crumbtrail_fs.ZFileWatch(directory);
199
- const filter = globs.join(",");
200
- this._logger.log(ZCrumbtrailWatch.msg("Welcome to Crumbtrail CLI"));
201
- this._logger.log(ZCrumbtrailWatch.msg(`You are now watching ${directory}`));
202
- this._logger.log(ZCrumbtrailWatch.msg(`Logging files matching ${filter}.`));
203
- this._logger.log(ZCrumbtrailWatch.msg("Press Ctrl+C to stop watching"));
204
- this._watch.add().subscribe(this._handleAdd.bind(this));
205
- this._watch.remove().subscribe(this._handleRemove.bind(this));
206
- this._watch.update().subscribe(this._handleUpdate.bind(this));
207
- this._ready = this._watch.start();
208
- await this._ready;
209
- return this._promise;
210
- }
211
- };
212
- //#endregion
213
- Object.defineProperty(exports, "ZCrumbtrailNudge", {
214
- enumerable: true,
215
- get: function() {
216
- return ZCrumbtrailNudge;
217
- }
218
- });
219
- Object.defineProperty(exports, "ZCrumbtrailWatch", {
220
- enumerable: true,
221
- get: function() {
222
- return ZCrumbtrailWatch;
223
- }
224
- });
225
-
226
- //# sourceMappingURL=watch-DXvYTgIr.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"watch-DXvYTgIr.cjs","names":["readdir","dirname","ZWatchDelay","firstTruthy","sleep","ZLogEntryBuilder","ZLoggerContext","glob","noop","ZCrumbtrailNudge","_controller","_resolve","_promise","_logger","logger","kill","abort","run","options","controller","AbortController","promise","resolve","Promise","withResolvers","directory","process","cwd","recursive","every","ms","log","info","message","build","warning","catch","onlyDirectories","signal","aborted","resolve","cwd","ZFileWatch","firstDefined","ZLogEntryBuilder","ZLoggerContext","uniq","minimatch","ZCrumbtrailWatch","_logger","_globs","_watch","_ready","Promise","_promise","_resolve","msg","info","message","build","add","path","remove","warning","update","watching","globs","slice","ready","logger","kill","stop","_handleFsEvent","entry","directory","some","g","log","_handleAdd","node","_handleRemove","_handleUpdate","run","args","promise","withResolvers","length","filter","join","subscribe","bind","start"],"sources":["../src/nudge/nudge.mts","../src/watch/watch.mts"],"sourcesContent":["import { readdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\nimport { ZWatchDelay } from \"@zthun/crumbtrail-fs\";\nimport { firstTruthy, sleep } from \"@zthun/helpful-fn\";\nimport type { IZLogger } from \"@zthun/lumberjacky-log\";\nimport { ZLogEntryBuilder, ZLoggerContext } from \"@zthun/lumberjacky-log\";\nimport glob from \"fast-glob\";\nimport { noop } from \"lodash-es\";\n\n/**\n * Options for the nudge command.\n */\nexport interface IZCrumbtrailNudgeOptions {\n /**\n * The directory to nudge.\n *\n * The default if not specified is the current working directory.\n */\n directory?: string;\n\n /**\n * Whether to nudge recursively.\n *\n * Warning: This can have severe CPU\n * usage for deep directories.\n *\n * Default is false.\n */\n recursive?: boolean;\n\n /**\n * The total number of milliseconds to wait\n * between nudges.\n *\n * Default is {@link ZWatchDelay}\n */\n every?: number;\n}\n\n/**\n * An operation to continuously nudge a directory.\n *\n * This is a special operation that lists the contents of a targeted parent directory.\n * The main reason for this is to work around an issue when you are running inside of\n * a container and your host is not linux.\n *\n * A lot of times, you will not receive events in this situation for add and update\n * until the virtual file bridge is refreshed by listing the outer directory contents.\n * This command helps to force the bridge to send file change events. You should\n * only need this if you are running on a non linux host inside a docker container.\n *\n * Run a separate container in the background and just nudge the directory\n * for however long you need.\n */\nexport class ZCrumbtrailNudge {\n private _controller?: AbortController;\n private _resolve?: (val: number) => void;\n private _promise?: Promise<number>;\n private readonly _logger: IZLogger;\n\n public constructor(logger: IZLogger) {\n this._logger = new ZLoggerContext(\"ZCrumbtrailNudge\", logger);\n }\n\n public async kill(): Promise<void> {\n this._controller?.abort();\n delete this._controller;\n\n await this._promise;\n delete this._promise;\n }\n\n public async run(options: IZCrumbtrailNudgeOptions = {}): Promise<number> {\n await this.kill();\n\n const controller = new AbortController();\n this._controller = controller;\n\n const { promise, resolve } = Promise.withResolvers<number>();\n this._promise = promise;\n this._resolve = resolve;\n\n const {\n directory = process.cwd(),\n recursive,\n every = ZWatchDelay,\n } = options;\n\n const ms = firstTruthy(ZWatchDelay, every);\n\n this._logger.log(\n new ZLogEntryBuilder()\n .info()\n .message(`Starting a nudge loop every ${ms} milliseconds`)\n .build(),\n );\n\n if (recursive) {\n this._logger.log(\n new ZLogEntryBuilder()\n .warning()\n .message(\"Nudging is recursive. Child folders will be nudged too.\")\n .build(),\n );\n }\n\n do {\n this._logger.log(\n new ZLogEntryBuilder()\n .info()\n .message(`Nudging ${directory} to refresh`)\n .build(),\n );\n await readdir(dirname(directory)).catch(noop);\n\n if (recursive) {\n await glob(`${directory}/**`, { onlyDirectories: true }).catch(noop);\n }\n\n await sleep(ms);\n } while (!controller.signal.aborted);\n\n resolve(0);\n delete this._resolve;\n\n return this._promise;\n }\n}\n","import { resolve } from \"node:path\";\nimport { cwd } from \"node:process\";\n\nimport type { IZFileSystemNode } from \"@zthun/crumbtrail-fs\";\nimport { ZFileWatch } from \"@zthun/crumbtrail-fs\";\nimport { firstDefined } from \"@zthun/helpful-fn\";\nimport type { IZLogEntry, IZLogger } from \"@zthun/lumberjacky-log\";\nimport { ZLogEntryBuilder, ZLoggerContext } from \"@zthun/lumberjacky-log\";\nimport { uniq } from \"lodash-es\";\nimport { minimatch } from \"minimatch\";\n\n/**\n * Arguments for the crumbtrail app.\n */\nexport interface IZCrumbtrailWatchOptions {\n /**\n * The directory to watch.\n *\n * If this is falsy, then the cwd is used.\n */\n directory?: string;\n\n /**\n * The list of file globs to watch.\n *\n * If this is falsy or empty, then '**' is used.\n */\n globs?: string[];\n}\n\n/**\n * The root application for the crumbtrail cli.\n */\nexport class ZCrumbtrailWatch {\n private _logger: IZLogger;\n private _globs: string[] | undefined;\n private _watch: ZFileWatch | undefined;\n private _ready: Promise<void> = Promise.resolve();\n private _promise: Promise<number> | undefined;\n private _resolve: ((value: number) => void) | undefined;\n\n /**\n * Gets the entry for a basic information message.\n *\n * @returns\n * The log entry for a basic information message.\n */\n public static msg(msg: string): IZLogEntry {\n return new ZLogEntryBuilder().info().message(msg).build();\n }\n\n /**\n * Gets the message for when a file is added.\n *\n * @returns\n * The message for when a file is added.\n */\n public static add(path: string): IZLogEntry {\n return new ZLogEntryBuilder().info().message(`Node added: ${path}`).build();\n }\n\n /**\n * Gets the message for when a file/folder is removed.\n *\n * @returns\n * The message for when a file/folder is added.\n */\n public static remove(path: string): IZLogEntry {\n return new ZLogEntryBuilder()\n .warning()\n .message(`Node removed: ${path}`)\n .build();\n }\n\n /**\n * Gets the message for when a file is updated.\n *\n * @returns\n * The message for when a file is updated.\n */\n public static update(path: string): IZLogEntry {\n return new ZLogEntryBuilder()\n .info()\n .message(`Node updated: ${path}`)\n .build();\n }\n\n /**\n * Gets the current directory being watched.\n *\n * @returns\n * The directory that is watching for events.\n */\n public watching() {\n return Promise.resolve(this._watch?.path);\n }\n\n /**\n * Gets the list of globs that filter the directory contents.\n *\n * @returns\n * The list of globs that filter the directory contents.\n */\n public globs() {\n return Promise.resolve(this._globs?.slice());\n }\n\n /**\n * Returns a promise that can be awaited on to\n * make sure the watch is initialized.\n */\n public async ready() {\n return this._ready;\n }\n\n /**\n * Initializes a new instance of this object.\n *\n * @param logger -\n * The logger to use to output events.\n */\n public constructor(logger: IZLogger) {\n this._logger = new ZLoggerContext(\"ZCrumbtrailApp\", logger);\n }\n\n /**\n * Kills the application.\n */\n public async kill(): Promise<void> {\n await this._watch?.stop();\n\n delete this._watch;\n delete this._globs;\n this._ready = Promise.resolve();\n\n this._resolve?.(0);\n await this._promise;\n delete this._promise;\n }\n\n private _handleFsEvent(path: string, entry: IZLogEntry) {\n const globs = firstDefined([\"**\"], this._globs);\n const directory = firstDefined(cwd(), this._watch?.path);\n\n if (globs?.some((g) => minimatch(path, resolve(directory, g)))) {\n this._logger.log(entry);\n }\n }\n\n private _handleAdd(node: IZFileSystemNode) {\n this._handleFsEvent(node.path, ZCrumbtrailWatch.add(node.path));\n }\n\n private _handleRemove(node: IZFileSystemNode) {\n this._handleFsEvent(node.path, ZCrumbtrailWatch.remove(node.path));\n }\n\n private _handleUpdate(node: IZFileSystemNode) {\n this._handleFsEvent(node.path, ZCrumbtrailWatch.update(node.path));\n }\n\n /**\n * Runs the application.\n *\n * @param args -\n * The application arguments.\n *\n * @returns\n * The process exit code.\n */\n public async run(args: IZCrumbtrailWatchOptions = {}): Promise<number> {\n if (this._promise) {\n return this._promise;\n }\n\n const { promise, resolve } = Promise.withResolvers<number>();\n this._resolve = resolve;\n this._promise = promise;\n\n const { directory = cwd(), globs = [\"**\"] } = args;\n\n this._globs = uniq(globs.slice());\n this._globs = this._globs.length ? this._globs : [\"**\"];\n this._watch = new ZFileWatch(directory);\n\n const filter = globs.join(\",\");\n this._logger.log(ZCrumbtrailWatch.msg(\"Welcome to Crumbtrail CLI\"));\n this._logger.log(ZCrumbtrailWatch.msg(`You are now watching ${directory}`));\n this._logger.log(ZCrumbtrailWatch.msg(`Logging files matching ${filter}.`));\n this._logger.log(ZCrumbtrailWatch.msg(\"Press Ctrl+C to stop watching\"));\n\n this._watch.add().subscribe(this._handleAdd.bind(this));\n this._watch.remove().subscribe(this._handleRemove.bind(this));\n this._watch.update().subscribe(this._handleUpdate.bind(this));\n\n this._ready = this._watch.start();\n await this._ready;\n\n return this._promise;\n }\n}\n"],"mappings":"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"}