@simplysm/core-node 13.0.75 → 13.0.77

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/src/utils/path.ts CHANGED
@@ -7,7 +7,7 @@ const NORM = Symbol("NormPath");
7
7
 
8
8
  /**
9
9
  * Brand type representing a normalized path.
10
- * Can only be created through pathNorm().
10
+ * Can only be created through norm().
11
11
  */
12
12
  export type NormPath = string & {
13
13
  [NORM]: never;
@@ -21,10 +21,10 @@ export type NormPath = string & {
21
21
  * Converts to POSIX-style path (backslash → forward slash).
22
22
  *
23
23
  * @example
24
- * pathPosix("C:\\Users\\test"); // "C:/Users/test"
25
- * pathPosix("src", "index.ts"); // "src/index.ts"
24
+ * posix("C:\\Users\\test"); // "C:/Users/test"
25
+ * posix("src", "index.ts"); // "src/index.ts"
26
26
  */
27
- export function pathPosix(...args: string[]): string {
27
+ export function posix(...args: string[]): string {
28
28
  const resolvedPath = path.join(...args);
29
29
  return resolvedPath.replace(/\\/g, "/");
30
30
  }
@@ -33,12 +33,12 @@ export function pathPosix(...args: string[]): string {
33
33
  * Changes the directory of a file path.
34
34
  *
35
35
  * @example
36
- * pathChangeFileDirectory("/a/b/c.txt", "/a", "/x");
36
+ * changeFileDirectory("/a/b/c.txt", "/a", "/x");
37
37
  * // → "/x/b/c.txt"
38
38
  *
39
39
  * @throws Error if the file is not inside fromDirectory
40
40
  */
41
- export function pathChangeFileDirectory(
41
+ export function changeFileDirectory(
42
42
  filePath: string,
43
43
  fromDirectory: string,
44
44
  toDirectory: string,
@@ -47,7 +47,7 @@ export function pathChangeFileDirectory(
47
47
  return toDirectory;
48
48
  }
49
49
 
50
- if (!pathIsChildPath(filePath, fromDirectory)) {
50
+ if (!isChildPath(filePath, fromDirectory)) {
51
51
  throw new ArgumentError(`'${filePath}' is not inside ${fromDirectory}.`, {
52
52
  filePath,
53
53
  fromDirectory,
@@ -61,10 +61,10 @@ export function pathChangeFileDirectory(
61
61
  * Returns the filename (basename) without extension.
62
62
  *
63
63
  * @example
64
- * pathBasenameWithoutExt("file.txt"); // "file"
65
- * pathBasenameWithoutExt("/path/to/file.spec.ts"); // "file.spec"
64
+ * basenameWithoutExt("file.txt"); // "file"
65
+ * basenameWithoutExt("/path/to/file.spec.ts"); // "file.spec"
66
66
  */
67
- export function pathBasenameWithoutExt(filePath: string): string {
67
+ export function basenameWithoutExt(filePath: string): string {
68
68
  return path.basename(filePath, path.extname(filePath));
69
69
  }
70
70
 
@@ -72,17 +72,17 @@ export function pathBasenameWithoutExt(filePath: string): string {
72
72
  * Checks if childPath is a child path of parentPath.
73
73
  * Returns false if the paths are the same.
74
74
  *
75
- * Paths are internally normalized using `pathNorm()` and compared using
75
+ * Paths are internally normalized using `norm()` and compared using
76
76
  * platform-specific path separators (Windows: `\`, Unix: `/`).
77
77
  *
78
78
  * @example
79
- * pathIsChildPath("/a/b/c", "/a/b"); // true
80
- * pathIsChildPath("/a/b", "/a/b/c"); // false
81
- * pathIsChildPath("/a/b", "/a/b"); // false (same path)
79
+ * isChildPath("/a/b/c", "/a/b"); // true
80
+ * isChildPath("/a/b", "/a/b/c"); // false
81
+ * isChildPath("/a/b", "/a/b"); // false (same path)
82
82
  */
83
- export function pathIsChildPath(childPath: string, parentPath: string): boolean {
84
- const normalizedChild = pathNorm(childPath);
85
- const normalizedParent = pathNorm(parentPath);
83
+ export function isChildPath(childPath: string, parentPath: string): boolean {
84
+ const normalizedChild = norm(childPath);
85
+ const normalizedParent = norm(parentPath);
86
86
 
87
87
  // Same path returns false
88
88
  if (normalizedChild === normalizedParent) {
@@ -102,10 +102,10 @@ export function pathIsChildPath(childPath: string, parentPath: string): boolean
102
102
  * Converts to absolute path and normalizes using platform-specific separators.
103
103
  *
104
104
  * @example
105
- * pathNorm("/some/path"); // NormPath
106
- * pathNorm("relative", "path"); // NormPath (converted to absolute path)
105
+ * norm("/some/path"); // NormPath
106
+ * norm("relative", "path"); // NormPath (converted to absolute path)
107
107
  */
108
- export function pathNorm(...paths: string[]): NormPath {
108
+ export function norm(...paths: string[]): NormPath {
109
109
  return path.resolve(...paths) as NormPath;
110
110
  }
111
111
 
@@ -122,14 +122,14 @@ export function pathNorm(...paths: string[]): NormPath {
122
122
  *
123
123
  * @example
124
124
  * const files = ["/proj/src/a.ts", "/proj/src/b.ts", "/proj/tests/c.ts"];
125
- * pathFilterByTargets(files, ["src"], "/proj");
125
+ * filterByTargets(files, ["src"], "/proj");
126
126
  * // → ["/proj/src/a.ts", "/proj/src/b.ts"]
127
127
  */
128
- export function pathFilterByTargets(files: string[], targets: string[], cwd: string): string[] {
128
+ export function filterByTargets(files: string[], targets: string[], cwd: string): string[] {
129
129
  if (targets.length === 0) return files;
130
- const normalizedTargets = targets.map((t) => pathPosix(t));
130
+ const normalizedTargets = targets.map((t) => posix(t));
131
131
  return files.filter((file) => {
132
- const relativePath = pathPosix(path.relative(cwd, file));
132
+ const relativePath = posix(path.relative(cwd, file));
133
133
  return normalizedTargets.some(
134
134
  (target) => relativePath === target || relativePath.startsWith(target + "/"),
135
135
  );
@@ -1,5 +1,5 @@
1
1
  import { parentPort } from "worker_threads";
2
- import { SdError, transferableDecode, transferableEncode } from "@simplysm/core-common";
2
+ import { SdError, transfer } from "@simplysm/core-common";
3
3
  import type { WorkerRequest, WorkerResponse } from "./types";
4
4
 
5
5
  //#region createWorker
@@ -27,7 +27,7 @@ export function createWorker<
27
27
  >(
28
28
  methods: TMethods,
29
29
  ): {
30
- send<K extends keyof TEvents & string>(event: K, data?: TEvents[K]): void;
30
+ send<TEventName extends keyof TEvents & string>(event: TEventName, data?: TEvents[TEventName]): void;
31
31
  __methods: TMethods;
32
32
  __events: TEvents;
33
33
  } {
@@ -46,7 +46,7 @@ export function createWorker<
46
46
  ): boolean => {
47
47
  const body = typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
48
48
  const response: WorkerResponse = { type: "log", body };
49
- const serialized = transferableEncode(response);
49
+ const serialized = transfer.encode(response);
50
50
  port.postMessage(serialized.result, serialized.transferList);
51
51
 
52
52
  const cb = typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
@@ -58,7 +58,7 @@ export function createWorker<
58
58
  };
59
59
 
60
60
  port.on("message", async (serializedRequest: unknown) => {
61
- const decoded = transferableDecode(serializedRequest);
61
+ const decoded = transfer.decode(serializedRequest);
62
62
 
63
63
  // Validate request structure
64
64
  if (
@@ -79,7 +79,7 @@ export function createWorker<
79
79
  request: { id: "unknown", method: "unknown", params: [] },
80
80
  body: new SdError(`Invalid worker request format: ${decodedStr}`),
81
81
  };
82
- const serialized = transferableEncode(errorResponse);
82
+ const serialized = transfer.encode(errorResponse);
83
83
  port.postMessage(serialized.result, serialized.transferList);
84
84
  return;
85
85
  }
@@ -94,7 +94,7 @@ export function createWorker<
94
94
  body: new SdError(`Unknown method: ${request.method}`),
95
95
  };
96
96
 
97
- const serialized = transferableEncode(response);
97
+ const serialized = transfer.encode(response);
98
98
  port.postMessage(serialized.result, serialized.transferList);
99
99
  return;
100
100
  }
@@ -108,7 +108,7 @@ export function createWorker<
108
108
  body: result,
109
109
  };
110
110
 
111
- const serialized = transferableEncode(response);
111
+ const serialized = transfer.encode(response);
112
112
  port.postMessage(serialized.result, serialized.transferList);
113
113
  } catch (err) {
114
114
  const response: WorkerResponse = {
@@ -117,7 +117,7 @@ export function createWorker<
117
117
  body: err instanceof Error ? err : new Error(String(err)),
118
118
  };
119
119
 
120
- const serialized = transferableEncode(response);
120
+ const serialized = transfer.encode(response);
121
121
  port.postMessage(serialized.result, serialized.transferList);
122
122
  }
123
123
  });
@@ -132,7 +132,7 @@ export function createWorker<
132
132
  body: data,
133
133
  };
134
134
 
135
- const serialized = transferableEncode(response);
135
+ const serialized = transfer.encode(response);
136
136
  port.postMessage(serialized.result, serialized.transferList);
137
137
  },
138
138
  };
@@ -35,17 +35,17 @@ export type WorkerProxy<TModule extends WorkerModule> = PromisifyMethods<
35
35
  /**
36
36
  * Registers a worker event listener.
37
37
  */
38
- on<K extends keyof TModule["default"]["__events"] & string>(
39
- event: K,
40
- listener: (data: TModule["default"]["__events"][K]) => void,
38
+ on<TEventName extends keyof TModule["default"]["__events"] & string>(
39
+ event: TEventName,
40
+ listener: (data: TModule["default"]["__events"][TEventName]) => void,
41
41
  ): void;
42
42
 
43
43
  /**
44
44
  * Unregisters a worker event listener.
45
45
  */
46
- off<K extends keyof TModule["default"]["__events"] & string>(
47
- event: K,
48
- listener: (data: TModule["default"]["__events"][K]) => void,
46
+ off<TEventName extends keyof TModule["default"]["__events"] & string>(
47
+ event: TEventName,
48
+ listener: (data: TModule["default"]["__events"][TEventName]) => void,
49
49
  ): void;
50
50
 
51
51
  /**
@@ -1,4 +1,4 @@
1
- import { EventEmitter, transferableDecode, transferableEncode, Uuid } from "@simplysm/core-common";
1
+ import { EventEmitter, transfer, Uuid } from "@simplysm/core-common";
2
2
  import consola from "consola";
3
3
  import path from "path";
4
4
  import { fileURLToPath } from "url";
@@ -85,7 +85,7 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
85
85
  });
86
86
 
87
87
  this._worker.on("message", (serializedResponse: unknown) => {
88
- const decoded = transferableDecode(serializedResponse);
88
+ const decoded = transfer.decode(serializedResponse);
89
89
 
90
90
  // Validate response structure
91
91
  if (decoded == null || typeof decoded !== "object" || !("type" in decoded)) {
@@ -131,14 +131,14 @@ class WorkerInternal extends EventEmitter<Record<string, unknown>> {
131
131
  call(method: string, params: unknown[]): Promise<unknown> {
132
132
  return new Promise((resolve, reject) => {
133
133
  const request: WorkerRequest = {
134
- id: Uuid.new().toString(),
134
+ id: Uuid.generate().toString(),
135
135
  method,
136
136
  params,
137
137
  };
138
138
 
139
139
  this._pendingRequests.set(request.id, { method, resolve, reject });
140
140
 
141
- const serialized = transferableEncode(request);
141
+ const serialized = transfer.encode(request);
142
142
  this._worker.postMessage(serialized.result, serialized.transferList);
143
143
  });
144
144
  }
@@ -28,22 +28,6 @@ describe("SdFsWatcher", () => {
28
28
  expect(watcher).toBeDefined();
29
29
  });
30
30
 
31
- it("starts watching files with options", async () => {
32
- watcher = await FsWatcher.watch([path.join(testDir, "**/*")], {
33
- ignoreInitial: false,
34
- });
35
- expect(watcher).toBeDefined();
36
- });
37
-
38
- it("logs errors when error events occur", async () => {
39
- // chokidar starts watching non-existent paths without issue
40
- // Error events only occur on actual filesystem errors
41
- const nonExistentPath = path.join(testDir, "non-existent-dir-" + Date.now());
42
- watcher = await FsWatcher.watch([nonExistentPath]);
43
-
44
- // Error handler is registered so it doesn't crash even if an error occurs
45
- expect(watcher).toBeDefined();
46
- });
47
31
  });
48
32
 
49
33
  //#endregion
@@ -75,43 +59,6 @@ describe("SdFsWatcher", () => {
75
59
 
76
60
  expect(result).toBe(watcher);
77
61
  });
78
-
79
- it("can specify delay option with various values", async () => {
80
- watcher = await FsWatcher.watch([path.join(testDir, "**/*")]);
81
-
82
- const fn = vi.fn();
83
- // delay option should be specifiable with various values
84
- expect(() => watcher!.onChange({ delay: 0 }, fn)).not.toThrow();
85
- expect(() => watcher!.onChange({ delay: 500 }, fn)).not.toThrow();
86
- expect(() => watcher!.onChange({ delay: 1000 }, fn)).not.toThrow();
87
- });
88
- });
89
-
90
- //#endregion
91
-
92
- //#region Types
93
-
94
- describe("Types", () => {
95
- it("verifies FsWatcherEvent type definition", () => {
96
- // Verify that event types are correctly defined
97
- const validEvents = ["add", "addDir", "change", "unlink", "unlinkDir"];
98
- expect(validEvents).toContain("add");
99
- expect(validEvents).toContain("addDir");
100
- expect(validEvents).toContain("change");
101
- expect(validEvents).toContain("unlink");
102
- expect(validEvents).toContain("unlinkDir");
103
- });
104
-
105
- it("verifies FsWatcherChangeInfo structure", () => {
106
- // Type check to verify interface structure
107
- const mockChangeInfo = {
108
- event: "add" as const,
109
- path: "/test/path",
110
- };
111
-
112
- expect(mockChangeInfo.event).toBe("add");
113
- expect(mockChangeInfo.path).toBe("/test/path");
114
- });
115
62
  });
116
63
 
117
64
  //#endregion