@ucdjs/fs-bridge 0.1.1-beta.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-PRESENT Lucas Nørgård
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.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # @ucdjs/fs-bridge
2
+
3
+ [![npm version][npm-version-src]][npm-version-href]
4
+ [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
+ [![codecov][codecov-src]][codecov-href]
6
+
7
+ A collection of filesystem bridge implementations for the UCD project, providing both Node.js and HTTP-based file system access.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @ucdjs/fs-bridge
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ You can create your own filesystem bridge or use the preconfigured ones provided by this package.
18
+
19
+ ### Creating a Custom Bridge
20
+
21
+ You can define a custom filesystem bridge using the `defineFileSystemBridge` function. This allows you to implement your own file system operations.
22
+
23
+ ```typescript
24
+ import { defineFileSystemBridge } from "@ucdjs/fs-bridge";
25
+
26
+ const MyFileSystemBridge = defineFileSystemBridge({
27
+ read: async (path) => {
28
+ // Implement your read logic here
29
+ },
30
+ write: async (path, content) => {
31
+ // Implement your write logic here
32
+ },
33
+ listdir: async (path, recursive = false) => {
34
+ // Implement your directory listing logic here
35
+ },
36
+ mkdir: async (path) => {
37
+ // Implement your directory creation logic here
38
+ },
39
+ exists: async (path) => {
40
+ // Implement your existence check logic here
41
+ },
42
+ stat: async (path) => {
43
+ // Implement your file stats retrieval logic here
44
+ },
45
+ rm: async (path, options) => {
46
+ // Implement your file/directory removal logic here
47
+ }
48
+ });
49
+ ```
50
+
51
+ ### Predefined Bridges
52
+
53
+ #### Node.js File System Bridge
54
+
55
+ ```typescript
56
+ import NodeFileSystemBridge from "@ucdjs/fs-bridge/bridges/node";
57
+
58
+ // Read a file
59
+ const content = await NodeFileSystemBridge.read("/path/to/file.txt");
60
+
61
+ // Write a file
62
+ await NodeFileSystemBridge.write("/path/to/file.txt", "Hello World");
63
+
64
+ // List directory contents
65
+ const files = await NodeFileSystemBridge.listdir("/path/to/dir");
66
+ const allFiles = await NodeFileSystemBridge.listdir("/path/to/dir", true); // recursive
67
+
68
+ // Create directory
69
+ await NodeFileSystemBridge.mkdir("/path/to/new/dir");
70
+
71
+ // Check if file exists
72
+ const exists = await NodeFileSystemBridge.exists("/path/to/file.txt");
73
+
74
+ // Get file stats
75
+ const stats = await NodeFileSystemBridge.stat("/path/to/file.txt");
76
+ console.log(stats.isFile()); // true/false
77
+ console.log(stats.isDirectory()); // true/false
78
+ console.log(stats.size); // file size in bytes
79
+ console.log(stats.mtime); // last modified date
80
+
81
+ // Remove file/directory
82
+ await NodeFileSystemBridge.rm("/path/to/file.txt");
83
+ await NodeFileSystemBridge.rm("/path/to/dir", { recursive: true, force: true });
84
+ ```
85
+
86
+ #### HTTP File System Bridge
87
+
88
+ Read-only filesystem bridge for accessing files over HTTP/HTTPS:
89
+
90
+ ```typescript
91
+ import HTTPFileSystemBridge from "@ucdjs/fs-bridge/bridges/http";
92
+
93
+ const httpFS = HTTPFileSystemBridge({
94
+ baseUrl: "https://example.com/files/"
95
+ });
96
+
97
+ // Read remote file
98
+ const content = await httpFS.read("/data/file.txt");
99
+
100
+ // List remote directory
101
+ const files = await httpFS.listdir("/data/");
102
+
103
+ // Check if remote file exists
104
+ const exists = await httpFS.exists("/data/file.txt");
105
+
106
+ // Get remote file stats
107
+ const stats = await httpFS.stat("/data/file.txt");
108
+ ```
109
+
110
+ ## 📄 License
111
+
112
+ Published under [MIT License](./LICENSE).
113
+
114
+ [npm-version-src]: https://img.shields.io/npm/v/@ucdjs/fs-bridge?style=flat&colorA=18181B&colorB=4169E1
115
+ [npm-version-href]: https://npmjs.com/package/@ucdjs/fs-bridge
116
+ [npm-downloads-src]: https://img.shields.io/npm/dm/@ucdjs/fs-bridge?style=flat&colorA=18181B&colorB=4169E1
117
+ [npm-downloads-href]: https://npmjs.com/package/@ucdjs/fs-bridge
118
+ [codecov-src]: https://img.shields.io/codecov/c/gh/ucdjs/ucd?style=flat&colorA=18181B&colorB=4169E1
119
+ [codecov-href]: https://codecov.io/gh/ucdjs/ucd
@@ -0,0 +1,12 @@
1
+ import { i as FileSystemBridgeFactory } from "../types-BRcSW-lJ.mjs";
2
+ import "../guards-CXuUenP_.mjs";
3
+ import "../index.mjs";
4
+ import { z } from "zod";
5
+
6
+ //#region src/bridges/http.d.ts
7
+ declare const kHttpBridgeSymbol: unique symbol;
8
+ declare const HTTPFileSystemBridge: FileSystemBridgeFactory<z.ZodObject<{
9
+ baseUrl: z.ZodDefault<z.ZodCodec<z.ZodURL, z.ZodCustom<URL, URL>>>;
10
+ }, z.core.$strip>>;
11
+ //#endregion
12
+ export { HTTPFileSystemBridge as default, kHttpBridgeSymbol };
@@ -0,0 +1,161 @@
1
+ import { t as defineFileSystemBridge } from "../define-BfE46g0d.mjs";
2
+ import { createDebugger } from "@ucdjs-internal/shared";
3
+ import { z } from "zod";
4
+ import { joinURL } from "@luxass/utils/path";
5
+ import { UCDJS_STORE_BASE_URL } from "@ucdjs/env";
6
+ import { FileEntrySchema } from "@ucdjs/schemas";
7
+
8
+ //#region src/bridges/http.ts
9
+ const debug = createDebugger("ucdjs:fs-bridge:http");
10
+ const kHttpBridgeSymbol = Symbol.for("@ucdjs/fs-bridge:http");
11
+ const API_BASE_URL_SCHEMA = z.codec(z.url({
12
+ protocol: /^https?$/,
13
+ hostname: z.regexes.hostname,
14
+ normalize: true
15
+ }), z.instanceof(URL), {
16
+ decode: (urlString) => new URL(urlString),
17
+ encode: (url) => url.href
18
+ }).default(new URL("/", UCDJS_STORE_BASE_URL));
19
+ const HTTPFileSystemBridge = defineFileSystemBridge({
20
+ meta: {
21
+ name: "HTTP File System Bridge",
22
+ description: "A file system bridge that interacts with a remote HTTP API to perform file system operations."
23
+ },
24
+ optionsSchema: z.object({ baseUrl: API_BASE_URL_SCHEMA }),
25
+ symbol: kHttpBridgeSymbol,
26
+ setup({ options, resolveSafePath }) {
27
+ const baseUrl = options.baseUrl;
28
+ return {
29
+ async read(path) {
30
+ debug?.("Reading file", { path });
31
+ const trimmedPath = path.trim();
32
+ if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") {
33
+ debug?.("Rejected file path ending with '/'", { path });
34
+ throw new Error("Cannot read file: path ends with '/'");
35
+ }
36
+ const url = joinURL(baseUrl.origin, resolveSafePath(baseUrl.pathname, path));
37
+ debug?.("Fetching remote file", { url });
38
+ const response = await fetch(url);
39
+ if (!response.ok) {
40
+ debug?.("Failed to read remote file", {
41
+ url,
42
+ status: response.status,
43
+ statusText: response.statusText
44
+ });
45
+ throw new Error(`Failed to read remote file: ${response.statusText}`);
46
+ }
47
+ debug?.("Successfully read remote file", { url });
48
+ return response.text();
49
+ },
50
+ async listdir(path, recursive = false) {
51
+ debug?.("Listing directory", {
52
+ path,
53
+ recursive
54
+ });
55
+ const url = joinURL(baseUrl.origin, resolveSafePath(baseUrl.pathname, `/${path}`));
56
+ debug?.("Fetching directory listing", { url });
57
+ const response = await fetch(url, {
58
+ method: "GET",
59
+ headers: { Accept: "application/json" }
60
+ });
61
+ if (!response.ok) {
62
+ if (response.status === 404) {
63
+ debug?.("Directory not found, returning empty array", { url });
64
+ return [];
65
+ }
66
+ if (response.status === 403) {
67
+ debug?.("Directory access forbidden, returning empty array", { url });
68
+ return [];
69
+ }
70
+ if (response.status === 500) {
71
+ debug?.("Server error while listing directory", {
72
+ url,
73
+ status: response.status
74
+ });
75
+ throw new Error(`Server error while listing directory: ${response.statusText}`);
76
+ }
77
+ debug?.("Failed to list directory", {
78
+ url,
79
+ status: response.status,
80
+ statusText: response.statusText
81
+ });
82
+ throw new Error(`Failed to list directory: ${response.statusText} (${response.status})`);
83
+ }
84
+ const json = await response.json();
85
+ const result = z.array(FileEntrySchema).safeParse(json);
86
+ if (!result.success) {
87
+ debug?.("Invalid response schema from directory listing", {
88
+ url,
89
+ error: result.error.message
90
+ });
91
+ throw new Error(`Invalid response schema: ${result.error.message}`);
92
+ }
93
+ const data = result.data;
94
+ if (!recursive) {
95
+ debug?.("Returning non-recursive directory listing", {
96
+ path,
97
+ entryCount: data.length
98
+ });
99
+ return data.map((entry) => {
100
+ if (entry.type === "directory") return {
101
+ type: "directory",
102
+ name: entry.name,
103
+ path: entry.path,
104
+ children: []
105
+ };
106
+ return {
107
+ type: entry.type,
108
+ name: entry.name,
109
+ path: entry.path
110
+ };
111
+ });
112
+ }
113
+ debug?.("Processing recursive directory listing", {
114
+ path,
115
+ entryCount: data.length
116
+ });
117
+ const entries = [];
118
+ for (const entry of data) if (entry.type === "directory") {
119
+ const children = await this.listdir(entry.path, true);
120
+ entries.push({
121
+ type: "directory",
122
+ name: entry.name,
123
+ path: entry.path,
124
+ children
125
+ });
126
+ } else entries.push({
127
+ type: "file",
128
+ name: entry.name,
129
+ path: entry.path
130
+ });
131
+ debug?.("Completed recursive directory listing", {
132
+ path,
133
+ totalEntries: entries.length
134
+ });
135
+ return entries;
136
+ },
137
+ async exists(path) {
138
+ debug?.("Checking file existence", { path });
139
+ const url = joinURL(baseUrl.origin, resolveSafePath(baseUrl.pathname, path));
140
+ debug?.("Sending HEAD request", { url });
141
+ return fetch(url, { method: "HEAD" }).then((response) => {
142
+ debug?.("File existence check result", {
143
+ url,
144
+ exists: response.ok
145
+ });
146
+ return response.ok;
147
+ }).catch((err) => {
148
+ if (err instanceof Error && err.message.startsWith("[MSW]")) throw err;
149
+ debug?.("Error checking file existence", {
150
+ url,
151
+ error: err instanceof Error ? err.message : String(err)
152
+ });
153
+ return false;
154
+ });
155
+ }
156
+ };
157
+ }
158
+ });
159
+
160
+ //#endregion
161
+ export { HTTPFileSystemBridge as default, kHttpBridgeSymbol };
@@ -0,0 +1,11 @@
1
+ import { i as FileSystemBridgeFactory } from "../types-BRcSW-lJ.mjs";
2
+ import "../guards-CXuUenP_.mjs";
3
+ import "../index.mjs";
4
+ import { z } from "zod";
5
+
6
+ //#region src/bridges/node.d.ts
7
+ declare const NodeFileSystemBridge: FileSystemBridgeFactory<z.ZodObject<{
8
+ basePath: z.ZodString;
9
+ }, z.core.$strip>>;
10
+ //#endregion
11
+ export { NodeFileSystemBridge as default };
@@ -0,0 +1,115 @@
1
+ import { t as defineFileSystemBridge } from "../define-BfE46g0d.mjs";
2
+ import { createDebugger } from "@ucdjs-internal/shared";
3
+ import { assertNotUNCPath } from "@ucdjs/path-utils";
4
+ import { z } from "zod";
5
+ import { appendTrailingSlash, prependLeadingSlash } from "@luxass/utils/path";
6
+ import fsp from "node:fs/promises";
7
+ import nodePath from "node:path";
8
+
9
+ //#region src/bridges/node.ts
10
+ const debug = createDebugger("ucdjs:fs-bridge:node");
11
+ /**
12
+ * Normalizes path separators to forward slashes for cross-platform consistency.
13
+ * On Windows, converts backslashes to forward slashes.
14
+ */
15
+ function normalizePathSeparators(path) {
16
+ return path.replace(/\\/g, "/");
17
+ }
18
+ async function safeExists(path) {
19
+ try {
20
+ await fsp.stat(path);
21
+ return true;
22
+ } catch {
23
+ debug?.("File existence check failed", { path });
24
+ return false;
25
+ }
26
+ }
27
+ const NodeFileSystemBridge = defineFileSystemBridge({
28
+ meta: {
29
+ name: "Node.js File System Bridge",
30
+ description: "A file system bridge that uses Node.js fs module to interact with the local file system."
31
+ },
32
+ optionsSchema: z.object({ basePath: z.string() }),
33
+ setup({ options, resolveSafePath }) {
34
+ assertNotUNCPath(options.basePath);
35
+ const basePath = nodePath.resolve(options.basePath);
36
+ return {
37
+ async read(path) {
38
+ const trimmedPath = path.trim();
39
+ if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") throw new Error("Cannot read file: path ends with '/'");
40
+ const resolvedPath = resolveSafePath(basePath, path);
41
+ return fsp.readFile(resolvedPath, "utf-8");
42
+ },
43
+ async exists(path) {
44
+ return safeExists(resolveSafePath(basePath, path));
45
+ },
46
+ async listdir(path, recursive = false) {
47
+ const targetPath = resolveSafePath(basePath, path);
48
+ function formatEntryPath(relativeToRoot, isDirectory) {
49
+ const withLeadingSlash = prependLeadingSlash(relativeToRoot);
50
+ return isDirectory ? appendTrailingSlash(withLeadingSlash) : withLeadingSlash;
51
+ }
52
+ function createFSEntry(entry, relativeToRoot) {
53
+ const formattedPath = formatEntryPath(relativeToRoot, entry.isDirectory());
54
+ return entry.isDirectory() ? {
55
+ type: "directory",
56
+ name: entry.name,
57
+ path: formattedPath,
58
+ children: []
59
+ } : {
60
+ type: "file",
61
+ name: entry.name,
62
+ path: formattedPath
63
+ };
64
+ }
65
+ if (!recursive) return (await fsp.readdir(targetPath, { withFileTypes: true })).map((entry) => {
66
+ const absEntryPath = nodePath.join(targetPath, entry.name);
67
+ return createFSEntry(entry, normalizePathSeparators(nodePath.relative(basePath, absEntryPath)));
68
+ });
69
+ const allEntries = await fsp.readdir(targetPath, {
70
+ withFileTypes: true,
71
+ recursive: true
72
+ });
73
+ const entryMap = /* @__PURE__ */ new Map();
74
+ const rootEntries = [];
75
+ for (const entry of allEntries) {
76
+ const entryDirPath = entry.parentPath || entry.path;
77
+ const relativeToTargetDir = nodePath.relative(targetPath, entryDirPath);
78
+ const absEntryPath = nodePath.join(entryDirPath, entry.name);
79
+ const normalized = normalizePathSeparators(nodePath.relative(basePath, absEntryPath));
80
+ const fsEntry = createFSEntry(entry, normalized);
81
+ entryMap.set(normalized, fsEntry);
82
+ if (!relativeToTargetDir) rootEntries.push(fsEntry);
83
+ }
84
+ for (const [entryPath, entry] of entryMap) {
85
+ const parentPath = nodePath.dirname(entryPath);
86
+ if (parentPath && parentPath !== ".") {
87
+ const parent = entryMap.get(parentPath);
88
+ if (parent?.type === "directory") parent.children.push(entry);
89
+ }
90
+ }
91
+ return rootEntries;
92
+ },
93
+ async write(path, data, encoding = "utf-8") {
94
+ const trimmedPath = path.trim();
95
+ if (trimmedPath.endsWith("/") && trimmedPath !== "/" && trimmedPath !== "./" && trimmedPath !== "../") throw new Error("Cannot write file: path ends with '/'");
96
+ const resolvedPath = resolveSafePath(basePath, path);
97
+ const parentDir = nodePath.dirname(resolvedPath);
98
+ if (!await safeExists(parentDir)) await fsp.mkdir(parentDir, { recursive: true });
99
+ return fsp.writeFile(resolvedPath, data, { encoding });
100
+ },
101
+ async mkdir(path) {
102
+ await fsp.mkdir(resolveSafePath(basePath, path), { recursive: true });
103
+ },
104
+ async rm(path, options) {
105
+ return fsp.rm(resolveSafePath(basePath, path), {
106
+ recursive: options?.recursive ?? false,
107
+ force: options?.force ?? false
108
+ });
109
+ }
110
+ };
111
+ }
112
+ });
113
+
114
+ //#endregion
115
+ export { NodeFileSystemBridge as default };
@@ -0,0 +1,205 @@
1
+ import { BridgeBaseError, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation } from "./errors.mjs";
2
+ import { createDebugger } from "@ucdjs-internal/shared";
3
+ import { PathUtilsBaseError, resolveSafePath } from "@ucdjs/path-utils";
4
+ import { HookableCore } from "hookable";
5
+ import { z } from "zod";
6
+
7
+ //#region ../../node_modules/.pnpm/@luxass+msw-utils@0.6.0_msw@2.12.10_@types+node@25.2.2_typescript@5.9.3_/node_modules/@luxass/msw-utils/dist/runtime-guards.mjs
8
+ /**
9
+ * Checks if an error is an MSW internal error.
10
+ *
11
+ * MSW throws internal errors with the name "InternalError" and
12
+ * prefixes error messages with "[MSW]".
13
+ *
14
+ * @param {unknown} error - The error to check
15
+ * @returns {boolean} true if the error is from MSW
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * try {
20
+ * // some code that might throw MSW errors
21
+ * } catch (error) {
22
+ * if (isMSWError(error)) {
23
+ * console.log("This is an MSW error:", error.message);
24
+ * }
25
+ * }
26
+ * ```
27
+ */
28
+ function isMSWError(error) {
29
+ return error instanceof Error && (error.name === "InternalError" || error.message.startsWith("[MSW]"));
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/utils.ts
34
+ const debug$1 = createDebugger("ucdjs:fs-bridge:utils");
35
+ /**
36
+ * @internal
37
+ */
38
+ function inferOptionalCapabilitiesFromOperations(ops) {
39
+ return {
40
+ write: "write" in ops && typeof ops.write === "function",
41
+ mkdir: "mkdir" in ops && typeof ops.mkdir === "function",
42
+ rm: "rm" in ops && typeof ops.rm === "function"
43
+ };
44
+ }
45
+ /**
46
+ * Constructs a hook payload object for a given file system bridge operation.
47
+ *
48
+ * This function normalizes arguments and results from different file system operations
49
+ * into their corresponding hook payload structures. It supports both "before" and "after"
50
+ * phases for operations that distinguish between them.
51
+ *
52
+ * @param {string} property - The name of the file system operation (e.g., "read", "write", "listdir", "exists", "mkdir", "rm")
53
+ * @param {string} phase - The hook execution phase: "before" runs before the operation, "after" runs after
54
+ * @param {unknown[]} args - The arguments passed to the original operation
55
+ * @param {unknown} result - The result from the operation (only used for "after" phase hooks)
56
+ * @returns A {@link HookPayload} object containing normalized data for the hook
57
+ */
58
+ function getPayloadForHook(property, phase, args, result) {
59
+ debug$1?.(`Constructing hook payload for '${property}:${phase}'`);
60
+ switch (property) {
61
+ case "read": if (phase === "before") return { path: args[0] };
62
+ else return {
63
+ path: args[0],
64
+ content: result
65
+ };
66
+ case "write": if (phase === "before") return {
67
+ path: args[0],
68
+ content: args[1],
69
+ encoding: args[2]
70
+ };
71
+ else return { path: args[0] };
72
+ case "listdir": if (phase === "before") return {
73
+ path: args[0],
74
+ recursive: args[1] ?? false
75
+ };
76
+ else return {
77
+ path: args[0],
78
+ recursive: args[1] ?? false,
79
+ entries: result
80
+ };
81
+ case "exists": if (phase === "before") return { path: args[0] };
82
+ else return {
83
+ path: args[0],
84
+ exists: result
85
+ };
86
+ case "mkdir": return { path: args[0] };
87
+ case "rm": return {
88
+ path: args[0],
89
+ ...args[1]
90
+ };
91
+ default: throw new BridgeGenericError(`Failed to construct hook payload for '${property}:${phase}' hook`);
92
+ }
93
+ }
94
+ /**
95
+ * @internal
96
+ */
97
+ function createOperationWrapper(operationName, { hooks, operations }) {
98
+ const operation = operations[operationName];
99
+ if (operation == null || typeof operation !== "function") return async (...args) => {
100
+ debug$1?.("Attempted to call unsupported operation", { operation: operationName });
101
+ const error = new BridgeUnsupportedOperation(operationName);
102
+ await hooks.callHook("error", {
103
+ method: operationName,
104
+ path: args[0],
105
+ error,
106
+ args
107
+ });
108
+ throw error;
109
+ };
110
+ return async (...args) => {
111
+ try {
112
+ const beforePayload = getPayloadForHook(operationName, "before", args);
113
+ await hooks.callHook(`${operationName}:before`, beforePayload);
114
+ const result = await operation.apply(operations, args);
115
+ const afterPayload = getPayloadForHook(operationName, "after", args, result);
116
+ await hooks.callHook(`${operationName}:after`, afterPayload);
117
+ return result;
118
+ } catch (err) {
119
+ return handleError(operationName, args, err, hooks);
120
+ }
121
+ };
122
+ }
123
+ async function handleError(operation, args, err, hooks) {
124
+ const normalizedError = (() => {
125
+ if (err instanceof Error) return err;
126
+ debug$1?.("Non-Error thrown in bridge operation", {
127
+ operation: String(operation),
128
+ error: String(err)
129
+ });
130
+ return new BridgeGenericError(`Non-Error thrown in '${String(operation)}' operation: ${String(err)}`, { cause: err });
131
+ })();
132
+ if (isMSWError(normalizedError)) {
133
+ debug$1?.("MSW error detected in bridge operation", {
134
+ operation: String(operation),
135
+ error: normalizedError.message
136
+ });
137
+ throw normalizedError;
138
+ }
139
+ await hooks.callHook("error", {
140
+ method: operation,
141
+ path: args[0],
142
+ error: normalizedError,
143
+ args
144
+ });
145
+ if (normalizedError instanceof BridgeBaseError || normalizedError instanceof PathUtilsBaseError) {
146
+ debug$1?.("Known error thrown in bridge operation", {
147
+ operation: String(operation),
148
+ error: normalizedError.message
149
+ });
150
+ throw normalizedError;
151
+ }
152
+ debug$1?.("Unexpected error in bridge operation", {
153
+ operation: String(operation),
154
+ error: normalizedError.message
155
+ });
156
+ throw new BridgeGenericError(`Unexpected error in '${String(operation)}' operation: ${normalizedError.message}`, { cause: normalizedError });
157
+ }
158
+
159
+ //#endregion
160
+ //#region src/define.ts
161
+ const debug = createDebugger("ucdjs:fs-bridge:define");
162
+ function defineFileSystemBridge(fsBridge) {
163
+ return (...args) => {
164
+ const parsedOptions = (fsBridge.optionsSchema ?? z.never().optional()).safeParse(args[0]);
165
+ if (!parsedOptions.success) {
166
+ debug?.("Invalid options provided to file system bridge", { error: parsedOptions.error.message });
167
+ throw new Error(`Invalid options provided to file system bridge: ${parsedOptions.error.message}`);
168
+ }
169
+ const options = parsedOptions.data;
170
+ const { state } = fsBridge;
171
+ let bridgeOperations = null;
172
+ try {
173
+ bridgeOperations = fsBridge.setup({
174
+ options,
175
+ state: structuredClone(state) ?? {},
176
+ resolveSafePath
177
+ });
178
+ } catch (err) {
179
+ debug?.("Failed to setup file system bridge", { error: err instanceof Error ? err.message : String(err) });
180
+ throw new BridgeSetupError("Failed to setup file system bridge", err instanceof Error ? err : void 0);
181
+ }
182
+ const hooks = new HookableCore();
183
+ const optionalCapabilities = inferOptionalCapabilitiesFromOperations(bridgeOperations);
184
+ const baseWrapperOptions = {
185
+ hooks,
186
+ operations: bridgeOperations
187
+ };
188
+ const bridge = {
189
+ meta: fsBridge.meta,
190
+ optionalCapabilities,
191
+ hook: hooks.hook.bind(hooks),
192
+ read: createOperationWrapper("read", baseWrapperOptions),
193
+ exists: createOperationWrapper("exists", baseWrapperOptions),
194
+ listdir: createOperationWrapper("listdir", baseWrapperOptions),
195
+ write: createOperationWrapper("write", baseWrapperOptions),
196
+ mkdir: createOperationWrapper("mkdir", baseWrapperOptions),
197
+ rm: createOperationWrapper("rm", baseWrapperOptions)
198
+ };
199
+ if (fsBridge.symbol) bridge[fsBridge.symbol] = true;
200
+ return bridge;
201
+ };
202
+ }
203
+
204
+ //#endregion
205
+ export { defineFileSystemBridge as t };
@@ -0,0 +1,27 @@
1
+ import { u as OptionalCapabilityKey } from "./types-BRcSW-lJ.mjs";
2
+
3
+ //#region src/errors.d.ts
4
+ declare abstract class BridgeBaseError extends Error {
5
+ constructor(message: string, options?: ErrorOptions);
6
+ }
7
+ declare class BridgeGenericError extends BridgeBaseError {
8
+ constructor(message: string, options?: ErrorOptions);
9
+ }
10
+ declare class BridgeSetupError extends BridgeBaseError {
11
+ readonly originalError?: Error;
12
+ constructor(message: string, originalError?: Error);
13
+ }
14
+ declare class BridgeUnsupportedOperation extends BridgeBaseError {
15
+ readonly capability: OptionalCapabilityKey;
16
+ constructor(capability: OptionalCapabilityKey);
17
+ }
18
+ declare class BridgeFileNotFound extends BridgeBaseError {
19
+ readonly path: string;
20
+ constructor(path: string);
21
+ }
22
+ declare class BridgeEntryIsDir extends BridgeBaseError {
23
+ readonly path: string;
24
+ constructor(path: string);
25
+ }
26
+ //#endregion
27
+ export { BridgeBaseError, BridgeEntryIsDir, BridgeFileNotFound, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation };
@@ -0,0 +1,48 @@
1
+ //#region src/errors.ts
2
+ var BridgeBaseError = class extends Error {
3
+ constructor(message, options) {
4
+ super(message, options);
5
+ this.name = "BridgeBaseError";
6
+ }
7
+ };
8
+ var BridgeGenericError = class extends BridgeBaseError {
9
+ constructor(message, options) {
10
+ super(message, options);
11
+ this.name = "BridgeGenericError";
12
+ }
13
+ };
14
+ var BridgeSetupError = class extends BridgeBaseError {
15
+ originalError;
16
+ constructor(message, originalError) {
17
+ super(message, { cause: originalError });
18
+ this.name = "BridgeSetupError";
19
+ this.originalError = originalError;
20
+ }
21
+ };
22
+ var BridgeUnsupportedOperation = class extends BridgeBaseError {
23
+ capability;
24
+ constructor(capability) {
25
+ super(`File system bridge does not support the '${capability}' capability.`);
26
+ this.name = "BridgeUnsupportedOperation";
27
+ this.capability = capability;
28
+ }
29
+ };
30
+ var BridgeFileNotFound = class extends BridgeBaseError {
31
+ path;
32
+ constructor(path) {
33
+ super(`File or directory not found: ${path}`);
34
+ this.name = "BridgeFileNotFound";
35
+ this.path = path;
36
+ }
37
+ };
38
+ var BridgeEntryIsDir = class extends BridgeBaseError {
39
+ path;
40
+ constructor(path) {
41
+ super(`Expected file but found directory: ${path}`);
42
+ this.name = "BridgeEntryIsDir";
43
+ this.path = path;
44
+ }
45
+ };
46
+
47
+ //#endregion
48
+ export { BridgeBaseError, BridgeEntryIsDir, BridgeFileNotFound, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation };
@@ -0,0 +1,45 @@
1
+ import { i as FileSystemBridgeFactory, n as FileSystemBridge, s as FileSystemBridgeObject, u as OptionalCapabilityKey } from "./types-BRcSW-lJ.mjs";
2
+ import { z } from "zod";
3
+
4
+ //#region src/assertions.d.ts
5
+ /**
6
+ * Asserts that a file system bridge supports the specified capability or capabilities.
7
+ *
8
+ * This function performs a runtime check to ensure the bridge has the required capabilities
9
+ * and acts as a type guard to narrow the bridge type to include the specified capabilities.
10
+ *
11
+ * @template {OptionalCapabilityKey} T - The capability key(s) to check for, extending OptionalCapabilityKey
12
+ * @param {FileSystemBridge} bridge - The file system bridge to check capabilities for
13
+ * @param {T | T[]} capabilityOrCapabilities - A single capability or array of capabilities to verify
14
+ * @throws {BridgeUnsupportedOperation} When the bridge doesn't support one or more of the specified capabilities
15
+ */
16
+ declare function assertCapability<T extends OptionalCapabilityKey = never>(bridge: FileSystemBridge, capabilityOrCapabilities: T | T[]): asserts bridge is FileSystemBridge & Required<Pick<FileSystemBridge, T>>;
17
+ //#endregion
18
+ //#region src/define.d.ts
19
+ declare function defineFileSystemBridge<TOptionsSchema extends z.ZodType = z.ZodNever, TState extends Record<string, unknown> = Record<string, unknown>>(fsBridge: FileSystemBridgeObject<TOptionsSchema, TState> & {
20
+ symbol?: symbol;
21
+ }): FileSystemBridgeFactory<TOptionsSchema>;
22
+ //#endregion
23
+ //#region src/guards.d.ts
24
+ /**
25
+ * Checks whether a file system bridge supports the specified capability or capabilities.
26
+ *
27
+ * Performs a runtime check and acts as a type guard to narrow the bridge type
28
+ * when all required capabilities are present.
29
+ *
30
+ * @template {OptionalCapabilityKey} T - The capability key(s) to check for, extending OptionalCapabilityKey
31
+ * @param {FileSystemBridge} bridge - The file system bridge to check capabilities for
32
+ * @param {T | T[]} capabilityOrCapabilities - A single capability or array of capabilities to verify
33
+ */
34
+ declare function hasCapability<T extends OptionalCapabilityKey = never>(bridge: FileSystemBridge, capabilityOrCapabilities: T | T[]): bridge is FileSystemBridge & Required<Pick<FileSystemBridge, T>>;
35
+ /**
36
+ * Checks whether a file system bridge is the built-in HTTP File System Bridge.
37
+ *
38
+ * Uses a symbol to identify the bridge type, making it safe against name changes.
39
+ *
40
+ * @param {FileSystemBridge} fs - The file system bridge to check
41
+ * @returns {boolean} True if the bridge is the built-in HTTP File System Bridge, false otherwise
42
+ */
43
+ declare function isBuiltinHttpBridge(fs: FileSystemBridge): boolean;
44
+ //#endregion
45
+ export { assertCapability as i, isBuiltinHttpBridge as n, defineFileSystemBridge as r, hasCapability as t };
@@ -0,0 +1,4 @@
1
+ import { a as FileSystemBridgeHooks, c as FileSystemBridgeOperations, i as FileSystemBridgeFactory, l as FileSystemBridgeRmOptions, n as FileSystemBridge, o as FileSystemBridgeMetadata, r as FileSystemBridgeArgs, t as FSEntry } from "./types-BRcSW-lJ.mjs";
2
+ import { i as assertCapability, n as isBuiltinHttpBridge, r as defineFileSystemBridge, t as hasCapability } from "./guards-CXuUenP_.mjs";
3
+ import { BridgeBaseError, BridgeEntryIsDir, BridgeFileNotFound, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation } from "./errors.mjs";
4
+ export { BridgeBaseError, BridgeEntryIsDir, BridgeFileNotFound, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation, type FSEntry, type FileSystemBridge, type FileSystemBridgeArgs, type FileSystemBridgeFactory, type FileSystemBridgeHooks, type FileSystemBridgeMetadata, type FileSystemBridgeOperations, type FileSystemBridgeRmOptions, assertCapability, defineFileSystemBridge, hasCapability, isBuiltinHttpBridge };
package/dist/index.mjs ADDED
@@ -0,0 +1,67 @@
1
+ import { BridgeBaseError, BridgeEntryIsDir, BridgeFileNotFound, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation } from "./errors.mjs";
2
+ import { t as defineFileSystemBridge } from "./define-BfE46g0d.mjs";
3
+ import { kHttpBridgeSymbol } from "./bridges/http.mjs";
4
+ import { createDebugger } from "@ucdjs-internal/shared";
5
+
6
+ //#region src/assertions.ts
7
+ const debug$1 = createDebugger("ucdjs:fs-bridge:assertions");
8
+ /**
9
+ * Asserts that a file system bridge supports the specified capability or capabilities.
10
+ *
11
+ * This function performs a runtime check to ensure the bridge has the required capabilities
12
+ * and acts as a type guard to narrow the bridge type to include the specified capabilities.
13
+ *
14
+ * @template {OptionalCapabilityKey} T - The capability key(s) to check for, extending OptionalCapabilityKey
15
+ * @param {FileSystemBridge} bridge - The file system bridge to check capabilities for
16
+ * @param {T | T[]} capabilityOrCapabilities - A single capability or array of capabilities to verify
17
+ * @throws {BridgeUnsupportedOperation} When the bridge doesn't support one or more of the specified capabilities
18
+ */
19
+ function assertCapability(bridge, capabilityOrCapabilities) {
20
+ const capabilitiesToCheck = Array.isArray(capabilityOrCapabilities) ? capabilityOrCapabilities : [capabilityOrCapabilities];
21
+ for (const capability of capabilitiesToCheck) if (!bridge.optionalCapabilities[capability]) {
22
+ debug$1?.("Bridge capability check failed", {
23
+ capability,
24
+ availableCapabilities: Object.keys(bridge.optionalCapabilities).filter((k) => bridge.optionalCapabilities[k])
25
+ });
26
+ throw new BridgeUnsupportedOperation(capability);
27
+ }
28
+ }
29
+
30
+ //#endregion
31
+ //#region src/guards.ts
32
+ const debug = createDebugger("ucdjs:fs-bridge:guards");
33
+ /**
34
+ * Checks whether a file system bridge supports the specified capability or capabilities.
35
+ *
36
+ * Performs a runtime check and acts as a type guard to narrow the bridge type
37
+ * when all required capabilities are present.
38
+ *
39
+ * @template {OptionalCapabilityKey} T - The capability key(s) to check for, extending OptionalCapabilityKey
40
+ * @param {FileSystemBridge} bridge - The file system bridge to check capabilities for
41
+ * @param {T | T[]} capabilityOrCapabilities - A single capability or array of capabilities to verify
42
+ */
43
+ function hasCapability(bridge, capabilityOrCapabilities) {
44
+ const capabilitiesToCheck = Array.isArray(capabilityOrCapabilities) ? capabilityOrCapabilities : [capabilityOrCapabilities];
45
+ for (const capability of capabilitiesToCheck) if (!bridge.optionalCapabilities[capability]) {
46
+ debug?.("Bridge capability check failed", {
47
+ capability,
48
+ availableCapabilities: Object.keys(bridge.optionalCapabilities).filter((k) => bridge.optionalCapabilities[k])
49
+ });
50
+ return false;
51
+ }
52
+ return true;
53
+ }
54
+ /**
55
+ * Checks whether a file system bridge is the built-in HTTP File System Bridge.
56
+ *
57
+ * Uses a symbol to identify the bridge type, making it safe against name changes.
58
+ *
59
+ * @param {FileSystemBridge} fs - The file system bridge to check
60
+ * @returns {boolean} True if the bridge is the built-in HTTP File System Bridge, false otherwise
61
+ */
62
+ function isBuiltinHttpBridge(fs) {
63
+ return kHttpBridgeSymbol in fs && fs[kHttpBridgeSymbol] === true;
64
+ }
65
+
66
+ //#endregion
67
+ export { BridgeBaseError, BridgeEntryIsDir, BridgeFileNotFound, BridgeGenericError, BridgeSetupError, BridgeUnsupportedOperation, assertCapability, defineFileSystemBridge, hasCapability, isBuiltinHttpBridge };
@@ -0,0 +1,266 @@
1
+ import { HookableCore } from "hookable";
2
+ import { z } from "zod";
3
+
4
+ //#region src/types.d.ts
5
+ interface FileSystemBridgeRmOptions {
6
+ /**
7
+ * If true, removes directories and their contents recursively
8
+ */
9
+ recursive?: boolean;
10
+ /**
11
+ * If true, ignores errors if the path doesn't exist
12
+ */
13
+ force?: boolean;
14
+ }
15
+ type FSEntry = {
16
+ type: "file";
17
+ name: string;
18
+ path: string;
19
+ } | {
20
+ type: "directory";
21
+ name: string;
22
+ path: string;
23
+ children: FSEntry[];
24
+ };
25
+ interface RequiredFileSystemBridgeOperations {
26
+ /**
27
+ * Reads the contents of a file.
28
+ * @param {string} path - The path to the file to read
29
+ * @returns {Promise<string>} A promise that resolves to the file contents as a string
30
+ */
31
+ read: (path: string) => Promise<string>;
32
+ /**
33
+ * Lists the contents of a directory.
34
+ * @param {string} path - The path to the directory to list
35
+ * @param {boolean} [recursive=false] - If true, lists files in subdirectories as well
36
+ * @returns {Promise<FSEntry[]>} A promise that resolves to an array of file and directory entries
37
+ */
38
+ listdir: (path: string, recursive?: boolean) => Promise<FSEntry[]>;
39
+ /**
40
+ * Checks if a file or directory exists.
41
+ * @param {string} path - The path to check for existence
42
+ * @returns {Promise<boolean>} A promise that resolves to true if the path exists, false otherwise
43
+ */
44
+ exists: (path: string) => Promise<boolean>;
45
+ }
46
+ interface OptionalFileSystemBridgeOperations {
47
+ /**
48
+ * Writes data to a file.
49
+ * @param {string} path - The path to the file to write
50
+ * @param {string | Uint8Array} data - The data to write to the file
51
+ * @param {BufferEncoding} [encoding] - Optional encoding for the data (defaults to 'utf8')
52
+ * @returns {Promise<void>} A promise that resolves when the write operation is complete
53
+ */
54
+ write?: (path: string, data: string | Uint8Array, encoding?: BufferEncoding) => Promise<void>;
55
+ /**
56
+ * Creates a directory.
57
+ * @param {string} path - The path of the directory to create
58
+ * @returns {Promise<void>} A promise that resolves when the directory is created
59
+ */
60
+ mkdir?: (path: string) => Promise<void>;
61
+ /**
62
+ * Removes a file or directory.
63
+ * @param {string} path - The path to remove
64
+ * @param {FileSystemBridgeRmOptions} [options] - Optional configuration for removal
65
+ * @returns {Promise<void>} A promise that resolves when the removal is complete
66
+ */
67
+ rm?: (path: string, options?: FileSystemBridgeRmOptions) => Promise<void>;
68
+ }
69
+ type FileSystemBridgeOperations = OptionalFileSystemBridgeOperations & RequiredFileSystemBridgeOperations;
70
+ type OptionalCapabilityKey = keyof OptionalFileSystemBridgeOperations;
71
+ type HasOptionalCapabilityMap = Record<OptionalCapabilityKey, boolean>;
72
+ type ResolveSafePathFn = (basePath: string, inputPath: string) => string;
73
+ type FileSystemBridgeSetupFn<TOptionsSchema extends z.ZodType, TState extends Record<string, unknown> = Record<string, unknown>> = (ctx: {
74
+ options: z.infer<TOptionsSchema>;
75
+ state: TState;
76
+ resolveSafePath: ResolveSafePathFn;
77
+ }) => FileSystemBridgeOperations;
78
+ interface FileSystemBridgeMetadata {
79
+ /**
80
+ * A unique name for the file system bridge
81
+ */
82
+ name: string;
83
+ /**
84
+ * A brief description of the file system bridge
85
+ */
86
+ description: string;
87
+ }
88
+ interface FileSystemBridgeObject<TOptionsSchema extends z.ZodType = z.ZodNever, TState extends Record<string, unknown> = Record<string, unknown>> {
89
+ /**
90
+ * Metadata about the file system bridge
91
+ */
92
+ meta: FileSystemBridgeMetadata;
93
+ /**
94
+ * Zod schema for validating bridge options
95
+ */
96
+ optionsSchema?: TOptionsSchema;
97
+ /**
98
+ * Optional state object for the file system bridge.
99
+ * This can be used to store any relevant state information
100
+ * that the bridge implementation may need.
101
+ * @type {Record<string, unknown>}
102
+ * @default {}
103
+ * @example
104
+ * ```ts
105
+ * import { FileSystemBridge } from "@ucdjs/fs-bridge";
106
+ *
107
+ * const fsBridge: FileSystemBridge = {
108
+ * state: {
109
+ * lastReadPath: "",
110
+ * },
111
+ * setup({ options, state }) {
112
+ * return {
113
+ * async read(path) {
114
+ * state.lastReadPath = path;
115
+ * // ... implementation
116
+ * }
117
+ * }
118
+ * }
119
+ * }
120
+ * ```
121
+ */
122
+ state?: TState;
123
+ /**
124
+ * Setup function that receives options, and state
125
+ * and returns the filesystem operations implementation
126
+ */
127
+ setup: FileSystemBridgeSetupFn<TOptionsSchema, TState>;
128
+ }
129
+ interface FileSystemBridge extends FileSystemBridgeOperations {
130
+ /**
131
+ * The capabilities of this file system bridge.
132
+ */
133
+ optionalCapabilities: HasOptionalCapabilityMap;
134
+ /**
135
+ * Metadata about this file system bridge.
136
+ */
137
+ meta: FileSystemBridgeMetadata;
138
+ /**
139
+ * Hook system for listening to file system events.
140
+ */
141
+ hook: HookableCore<FileSystemBridgeHooks>["hook"];
142
+ }
143
+ type FileSystemBridgeArgs<TOptionsSchema extends z.ZodType> = [z.input<TOptionsSchema>] extends [never] ? [] : undefined extends z.input<TOptionsSchema> ? [options?: z.input<TOptionsSchema>] : [options: z.input<TOptionsSchema>];
144
+ type FileSystemBridgeFactory<TOptionsSchema extends z.ZodType> = (...args: FileSystemBridgeArgs<TOptionsSchema>) => FileSystemBridge;
145
+ interface FileSystemBridgeHooks {
146
+ "error": (payload: {
147
+ /**
148
+ * The method that triggered the error.
149
+ */
150
+ method: keyof FileSystemBridgeOperations;
151
+ /**
152
+ * The path involved in the operation.
153
+ */
154
+ path: string;
155
+ /**
156
+ * The error that occurred.
157
+ */
158
+ error: Error;
159
+ /**
160
+ * Optional arguments passed to the method.
161
+ */
162
+ args?: unknown[];
163
+ }) => void;
164
+ "read:before": (payload: {
165
+ /**
166
+ * The path involved in the operation.
167
+ */
168
+ path: string;
169
+ }) => void;
170
+ "read:after": (payload: {
171
+ /**
172
+ * The path involved in the operation.
173
+ */
174
+ path: string;
175
+ /**
176
+ * The content being read or written.
177
+ */
178
+ content: string;
179
+ }) => void;
180
+ "write:before": (payload: {
181
+ /**
182
+ * The path involved in the operation.
183
+ */
184
+ path: string;
185
+ /**
186
+ * The content being read or written.
187
+ */
188
+ content: string;
189
+ /**
190
+ * Optional encoding for string content.
191
+ */
192
+ encoding?: BufferEncoding;
193
+ }) => void;
194
+ "write:after": (payload: {
195
+ /**
196
+ * The path involved in the operation.
197
+ */
198
+ path: string;
199
+ }) => void;
200
+ "listdir:before": (payload: {
201
+ /**
202
+ * The path involved in the operation.
203
+ */
204
+ path: string;
205
+ /**
206
+ * Whether the operation is recursive.
207
+ */
208
+ recursive: boolean;
209
+ }) => void;
210
+ "listdir:after": (payload: {
211
+ /**
212
+ * The path involved in the operation.
213
+ */
214
+ path: string;
215
+ /**
216
+ * Whether the operation is recursive.
217
+ */
218
+ recursive: boolean;
219
+ /**
220
+ * The list of entries returned by the operation.
221
+ */
222
+ entries: FSEntry[];
223
+ }) => void;
224
+ "exists:before": (payload: {
225
+ /**
226
+ * The path involved in the operation.
227
+ */
228
+ path: string;
229
+ }) => void;
230
+ "exists:after": (payload: {
231
+ /**
232
+ * The path involved in the operation.
233
+ */
234
+ path: string;
235
+ /**
236
+ * Whether the path exists.
237
+ */
238
+ exists: boolean;
239
+ }) => void;
240
+ "mkdir:before": (payload: {
241
+ /**
242
+ * The path involved in the operation.
243
+ */
244
+ path: string;
245
+ }) => void;
246
+ "mkdir:after": (payload: {
247
+ /**
248
+ * The path involved in the operation.
249
+ */
250
+ path: string;
251
+ }) => void;
252
+ "rm:before": (payload: {
253
+ /**
254
+ * The path involved in the operation.
255
+ */
256
+ path: string;
257
+ } & FileSystemBridgeRmOptions) => void;
258
+ "rm:after": (payload: {
259
+ /**
260
+ * The path involved in the operation.
261
+ */
262
+ path: string;
263
+ } & FileSystemBridgeRmOptions) => void;
264
+ }
265
+ //#endregion
266
+ export { FileSystemBridgeHooks as a, FileSystemBridgeOperations as c, FileSystemBridgeFactory as i, FileSystemBridgeRmOptions as l, FileSystemBridge as n, FileSystemBridgeMetadata as o, FileSystemBridgeArgs as r, FileSystemBridgeObject as s, FSEntry as t, OptionalCapabilityKey as u };
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "@ucdjs/fs-bridge",
3
+ "version": "0.1.1-beta.1",
4
+ "type": "module",
5
+ "author": {
6
+ "name": "Lucas Nørgård",
7
+ "email": "lucasnrgaard@gmail.com",
8
+ "url": "https://luxass.dev"
9
+ },
10
+ "license": "MIT",
11
+ "homepage": "https://github.com/ucdjs/ucd",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/ucdjs/ucd.git",
15
+ "directory": "packages/fs-bridge"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/ucdjs/ucd/issues"
19
+ },
20
+ "imports": {
21
+ "#internal:bridge/node": "./src/bridges/node.ts",
22
+ "#internal:bridge/http": "./src/bridges/http.ts"
23
+ },
24
+ "exports": {
25
+ ".": "./dist/index.mjs",
26
+ "./bridges/http": "./dist/bridges/http.mjs",
27
+ "./bridges/node": "./dist/bridges/node.mjs",
28
+ "./errors": "./dist/errors.mjs",
29
+ "./package.json": "./package.json"
30
+ },
31
+ "types": "./dist/index.d.mts",
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "engines": {
36
+ "node": ">=22.18"
37
+ },
38
+ "dependencies": {
39
+ "@luxass/utils": "2.7.3",
40
+ "defu": "6.1.4",
41
+ "hookable": "6.0.1",
42
+ "pathe": "2.0.3",
43
+ "zod": "4.3.6",
44
+ "@ucdjs-internal/shared": "0.1.1-beta.1",
45
+ "@ucdjs/env": "0.1.1-beta.1",
46
+ "@ucdjs/path-utils": "0.1.1-beta.1",
47
+ "@ucdjs/schemas": "0.1.1-beta.1"
48
+ },
49
+ "devDependencies": {
50
+ "@luxass/eslint-config": "7.2.0",
51
+ "@luxass/msw-utils": "0.6.0",
52
+ "eslint": "10.0.0",
53
+ "publint": "0.3.17",
54
+ "tsdown": "0.20.3",
55
+ "tsx": "4.21.0",
56
+ "typescript": "5.9.3",
57
+ "vitest-testdirs": "4.4.2",
58
+ "@ucdjs-internal/shared": "0.1.1-beta.1",
59
+ "@ucdjs-tooling/tsconfig": "1.0.0",
60
+ "@ucdjs-tooling/tsdown-config": "1.0.0"
61
+ },
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "scripts": {
66
+ "build": "tsdown --tsconfig=./tsconfig.build.json",
67
+ "dev": "tsdown --watch",
68
+ "clean": "git clean -xdf dist node_modules",
69
+ "lint": "eslint .",
70
+ "typecheck": "tsc --noEmit -p tsconfig.build.json",
71
+ "playground:node": "tsx --tsconfig=./tsconfig.json ./playgrounds/node-playground.ts",
72
+ "playground:http": "tsx --tsconfig=./tsconfig.json ./playgrounds/http-playground.ts"
73
+ }
74
+ }