@jsenv/filesystem 4.15.2 → 4.15.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,21 +1,76 @@
1
- # Jsenv filesystem [![npm package](https://img.shields.io/npm/v/@jsenv/filesystem.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/filesystem)
1
+ # Jsenv Filesystem [![npm package](https://img.shields.io/npm/v/@jsenv/filesystem.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/filesystem)
2
2
 
3
- Collection of functions to interact with filesystem in Node.js
3
+ A modern, Promise-based collection of utilities to interact with the filesystem in Node.js.
4
4
 
5
- ## List files using pattern matching
5
+ 🔍 Pattern-based file operations
6
+ 👀 Efficient file/directory watching
7
+ 🔄 Lifecycle hooks for file changes
8
+ 🛠️ URL-based path handling
9
+
10
+ ## Installation
11
+
12
+ ```console
13
+ npm install @jsenv/filesystem
14
+ ```
15
+
16
+ ## Table of Contents
17
+
18
+ - [Jsenv Filesystem ](#jsenv-filesystem-)
19
+ - [Installation](#installation)
20
+ - [Table of Contents](#table-of-contents)
21
+ - [Quick Start](#quick-start)
22
+ - [Features](#features)
23
+ - [List Files Using Pattern Matching](#list-files-using-pattern-matching)
24
+ - [Watch a Specific File Changes](#watch-a-specific-file-changes)
25
+ - [Watch Many Files Changes](#watch-many-files-changes)
26
+ - [Other Common Operations](#other-common-operations)
27
+ - [API](#api)
28
+
29
+ ## Quick Start
6
30
 
7
31
  ```js
8
- import { listFilesMatching } from "@jsenv/filesystem";
32
+ import { listFilesMatching, writeFile, moveFile } from "@jsenv/filesystem";
9
33
 
34
+ // Find JavaScript files (excluding tests)
10
35
  const jsFiles = await listFilesMatching({
11
- directoryUrl: new URL("./", import.meta.url),
36
+ directoryUrl: new URL("./src/", import.meta.url),
12
37
  patterns: {
13
38
  "./**/*.js": true,
14
39
  "./**/*.test.js": false,
15
40
  },
16
41
  });
42
+
43
+ // Create a new file
44
+ await writeFile(new URL("./output.txt", import.meta.url), "Hello world");
45
+
46
+ // Move a file
47
+ await moveFile({
48
+ source: new URL("./output.txt", import.meta.url),
49
+ destination: new URL("./moved.txt", import.meta.url),
50
+ });
17
51
  ```
18
52
 
53
+ ## Features
54
+
55
+ ### List Files Using Pattern Matching
56
+
57
+ Find files with powerful pattern matching that supports inclusion and exclusion patterns:
58
+
59
+ ```js
60
+ import { listFilesMatching } from "@jsenv/filesystem";
61
+
62
+ const jsFiles = await listFilesMatching({
63
+ directoryUrl: new URL("./", import.meta.url),
64
+ patterns: {
65
+ "./**/*.js": true, // Include all JS files
66
+ "./**/*.test.js": false, // Exclude test files
67
+ "./node_modules/": false, // Exclude node_modules directory
68
+ },
69
+ });
70
+ ```
71
+
72
+ Example output:
73
+
19
74
  ```console
20
75
  [
21
76
  'file:///Users/dmail/docs/demo/a.js',
@@ -23,7 +78,9 @@ const jsFiles = await listFilesMatching({
23
78
  ]
24
79
  ```
25
80
 
26
- ## Watch a specific file changes
81
+ ### Watch a Specific File Changes
82
+
83
+ Monitor a single file for changes with lifecycle hooks:
27
84
 
28
85
  ```js
29
86
  import { readFileSync } from "node:fs";
@@ -31,48 +88,100 @@ import { registerFileLifecycle } from "@jsenv/filesystem";
31
88
 
32
89
  const packageJSONFileUrl = new URL("./package.json", import.meta.url);
33
90
  let packageJSON = null;
91
+
92
+ // Start watching the file
34
93
  const unregister = registerFileLifecycle(packageJSONFileUrl, {
35
94
  added: () => {
36
95
  packageJSON = JSON.parse(String(readFileSync(packageJSONFileUrl)));
96
+ console.log("Package.json was added");
37
97
  },
38
98
  updated: () => {
39
99
  packageJSON = JSON.parse(String(readFileSync(packageJSONFileUrl)));
100
+ console.log("Package.json was updated");
40
101
  },
41
102
  removed: () => {
42
103
  packageJSON = null;
104
+ console.log("Package.json was removed");
43
105
  },
44
- notifyExistent: true,
106
+ notifyExistent: true, // Trigger 'added' callback if file exists when watching starts
45
107
  });
46
- unregister(); // stop watching the file changes
108
+
109
+ // Later, when done watching:
110
+ unregister(); // Stop watching the file changes
47
111
  ```
48
112
 
49
- ## Watch many files changes
113
+ ### Watch Many Files Changes
114
+
115
+ Monitor an entire directory with pattern filtering:
50
116
 
51
117
  ```js
52
118
  import { registerDirectoryLifecycle } from "@jsenv/filesystem";
53
119
 
54
120
  const directoryContentDescription = {};
121
+
122
+ // Start watching the directory
55
123
  const unregister = registerDirectoryLifecycle("file:///directory/", {
56
124
  watchPatterns: {
57
- "./**/*": true,
58
- "./node_modules/": false,
125
+ "./**/*": true, // Watch all files
126
+ "./node_modules/": false, // Except files in node_modules
59
127
  },
60
128
  added: ({ relativeUrl, type }) => {
61
129
  directoryContentDescription[relativeUrl] = type;
130
+ console.log(`Added: ${relativeUrl} (${type})`);
131
+ },
132
+ updated: ({ relativeUrl, type }) => {
133
+ console.log(`Updated: ${relativeUrl} (${type})`);
62
134
  },
63
135
  removed: ({ relativeUrl }) => {
64
136
  delete directoryContentDescription[relativeUrl];
137
+ console.log(`Removed: ${relativeUrl}`);
65
138
  },
66
139
  });
67
- unregister(); // stop watching the directory changes
140
+
141
+ // Later, when done watching:
142
+ unregister(); // Stop watching the directory changes
68
143
  ```
69
144
 
70
- # API
145
+ ### Other Common Operations
71
146
 
72
- [docs/API.md](./docs/API.md)
147
+ ```js
148
+ import {
149
+ ensureEmptyDirectory,
150
+ writeFile,
151
+ readFile,
152
+ copyFile,
153
+ moveFile,
154
+ removeFile,
155
+ } from "@jsenv/filesystem";
73
156
 
74
- # Installation
157
+ // Create or empty a directory
158
+ await ensureEmptyDirectory(new URL("./dist/", import.meta.url));
75
159
 
76
- ```console
77
- npm install @jsenv/filesystem
160
+ // Write a file (creates directories if needed)
161
+ await writeFile(
162
+ new URL("./logs/debug.log", import.meta.url),
163
+ "Debug information",
164
+ );
165
+
166
+ // Read a file (returns a string by default)
167
+ const content = await readFile(new URL("./config.json", import.meta.url));
168
+
169
+ // Copy a file
170
+ await copyFile({
171
+ source: new URL("./template.html", import.meta.url),
172
+ destination: new URL("./output/index.html", import.meta.url),
173
+ });
174
+
175
+ // Move a file
176
+ await moveFile({
177
+ source: new URL("./temp.txt", import.meta.url),
178
+ destination: new URL("./final/document.txt", import.meta.url),
179
+ });
180
+
181
+ // Remove a file
182
+ await removeFile(new URL("./obsolete.txt", import.meta.url));
78
183
  ```
184
+
185
+ ## API
186
+
187
+ For a complete list of all available functions and their parameters, see the [API documentation](./docs/API.md).
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@jsenv/filesystem",
3
- "version": "4.15.2",
3
+ "version": "4.15.4",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/jsenv/core",
8
- "directory": "packages/independent/backend/filesystem"
8
+ "directory": "packages/tooling/filesystem"
9
9
  },
10
10
  "publishConfig": {
11
11
  "access": "public"
@@ -30,9 +30,14 @@
30
30
  ],
31
31
  "sideEffects": false,
32
32
  "dependencies": {
33
- "@jsenv/urls": "2.7.4",
33
+ "@jsenv/urls": "2.9.0",
34
34
  "@jsenv/url-meta": "8.5.7",
35
35
  "@jsenv/abort": "4.3.1",
36
36
  "@jsenv/utils": "2.3.1"
37
+ },
38
+ "devDependencies": {
39
+ "@jsenv/snapshot": "../snapshot",
40
+ "@jsenv/assert": "../assert",
41
+ "@jsenv/filesystem": "./"
37
42
  }
38
43
  }
package/src/cli.mjs CHANGED
@@ -19,7 +19,7 @@ if (values.help || positionals.length === 0) {
19
19
 
20
20
  Usage: npx @jsenv/filesystem clear [pattern]
21
21
 
22
- https://github.com/jsenv/core/tree/main/packages/independent/filesystem
22
+ https://github.com/jsenv/core/tree/main/packages/tooling/filesystem
23
23
 
24
24
  pattern: files matching this pattern will be removed; can use "*" and "**"
25
25
  `);
@@ -2,7 +2,7 @@ import { Abort } from "@jsenv/abort";
2
2
  import {
3
3
  ensurePathnameTrailingSlash,
4
4
  resolveUrl,
5
- urlIsInsideOf,
5
+ urlIsOrIsInsideOf,
6
6
  urlToFileSystemPath,
7
7
  urlToRelativeUrl,
8
8
  } from "@jsenv/urls";
@@ -114,7 +114,7 @@ export const copyEntry = async ({
114
114
  let symbolicLinkCopyTarget;
115
115
  if (symbolicLinkTargetUrl === fromUrl) {
116
116
  symbolicLinkCopyTarget = linkIsRelative ? symbolicLinkTarget : toUrl;
117
- } else if (urlIsInsideOf(symbolicLinkTargetUrl, fromUrl)) {
117
+ } else if (urlIsOrIsInsideOf(symbolicLinkTargetUrl, fromUrl)) {
118
118
  // symbolic link targets something inside the directory we want to copy
119
119
  // reflects it inside the copied directory structure
120
120
  const linkCopyTargetRelative = urlToRelativeUrl(
@@ -2,7 +2,7 @@ import { Abort } from "@jsenv/abort";
2
2
  import {
3
3
  ensurePathnameTrailingSlash,
4
4
  resolveUrl,
5
- urlIsInsideOf,
5
+ urlIsOrIsInsideOf,
6
6
  urlToFileSystemPath,
7
7
  urlToRelativeUrl,
8
8
  } from "@jsenv/urls";
@@ -114,7 +114,7 @@ export const copyEntrySync = ({
114
114
  let symbolicLinkCopyTarget;
115
115
  if (symbolicLinkTargetUrl === fromUrl) {
116
116
  symbolicLinkCopyTarget = linkIsRelative ? symbolicLinkTarget : toUrl;
117
- } else if (urlIsInsideOf(symbolicLinkTargetUrl, fromUrl)) {
117
+ } else if (urlIsOrIsInsideOf(symbolicLinkTargetUrl, fromUrl)) {
118
118
  // symbolic link targets something inside the directory we want to copy
119
119
  // reflects it inside the copied directory structure
120
120
  const linkCopyTargetRelative = urlToRelativeUrl(