-
-
Notifications
You must be signed in to change notification settings - Fork 0
refactor: modify fs-bridge to work better #439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
13223d1
chore(fs-bridge): update @luxass/msw-utils to version 0.6.0
luxass c69d2d5
refactor(fs-bridge): simplify BridgeGenericError constructor
luxass dfa455f
chore(fs-bridge): update entry points in tsdown config
luxass 264723a
feat(fs-bridge): add isBuiltinHttpBridge function and update exports
luxass 73157ce
refactor(fs-bridge): enhance debugging in HTTP bridge and add TODO fo…
luxass 93b5941
test(fs-bridge): improve error messages in encoding tests
luxass 11e65a5
refactor(fs-bridge): standardize file paths in tests
luxass eda5a23
feat(fs-bridge): add node and http playground scripts
luxass 22ecdde
feat(fs-bridge): add detailed documentation for listdir method
luxass af87868
test(fs-bridge): enhance schema validation and security tests for lis…
luxass 21748cc
chore: lint
luxass eacb0e9
fix(fs-bridge): update error handling to use BridgeBaseError
luxass 1c3664e
feat(fs-bridge): add symbol support for HTTP bridge definition
luxass 6783289
fix(fs-bridge): add optional chaining to bridge methods
luxass 57a5785
test(ucd-store): convert describe blocks to describe.todo for pending…
luxass df9b301
feat(fs-bridge): format paths with leading and trailing slashes
luxass 5334e8c
chore: tmp disable test
luxass File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,262 @@ | ||
| /* eslint-disable no-console, antfu/no-top-level-await */ | ||
| /** | ||
| * fs-bridge HTTP Playground | ||
| * | ||
| * This playground verifies the HTTP fs-bridge works correctly against | ||
| * the real UCD.js API. It tests read, exists, and listdir operations. | ||
| * | ||
| * Configure with: FS_BRIDGE_HTTP_BASE_URL env var | ||
| * Run with: pnpm playground:http | ||
| */ | ||
|
|
||
| import process from "node:process"; | ||
| import { assertCapability } from "../src"; | ||
| import HTTPFileSystemBridge from "../src/bridges/http"; | ||
|
|
||
| interface TestCase { | ||
| description: string; | ||
| run: () => Promise<void>; | ||
| } | ||
|
|
||
| const BASE_URL = process.env.FS_BRIDGE_HTTP_BASE_URL || "https://api.ucdjs.dev/api/v1/files"; | ||
|
|
||
| console.log("fs-bridge HTTP Playground\n"); | ||
| console.log("=".repeat(60)); | ||
| console.log(`\nBase URL: ${BASE_URL}\n`); | ||
|
|
||
| const bridge = HTTPFileSystemBridge({ baseUrl: BASE_URL }); | ||
|
|
||
| console.log("=".repeat(60)); | ||
|
|
||
| const testCases: TestCase[] = [ | ||
| // Capability tests (HTTP bridge is read-only) | ||
| { | ||
| description: "Bridge does NOT have write capability", | ||
| async run() { | ||
| if (bridge.optionalCapabilities.write) throw new Error("Should not have write"); | ||
| try { | ||
| assertCapability(bridge, "write"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Bridge does NOT have mkdir capability", | ||
| async run() { | ||
| if (bridge.optionalCapabilities.mkdir) throw new Error("Should not have mkdir"); | ||
| try { | ||
| assertCapability(bridge, "mkdir"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Bridge does NOT have rm capability", | ||
| async run() { | ||
| if (bridge.optionalCapabilities.rm) throw new Error("Should not have rm"); | ||
| try { | ||
| assertCapability(bridge, "rm"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
|
|
||
| // Read tests | ||
| { | ||
| description: "Read 16.0.0/ReadMe.txt", | ||
| async run() { | ||
| const content = await bridge.read("16.0.0/ReadMe.txt"); | ||
| if (typeof content !== "string") throw new Error("Content should be string"); | ||
| if (content.length === 0) throw new Error("Content should not be empty"); | ||
| if (!content.includes("Unicode")) throw new Error("Should mention Unicode"); | ||
| }, | ||
| }, | ||
| { | ||
| description: "Read with / prefix", | ||
| async run() { | ||
| const content = await bridge.read("/16.0.0/ReadMe.txt"); | ||
| if (!content.includes("Unicode")) throw new Error("Should work with / prefix"); | ||
| }, | ||
| }, | ||
| { | ||
| description: "Read non-existent file throws", | ||
| async run() { | ||
| try { | ||
| await bridge.read("16.0.0/NonExistent12345.txt"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Read trailing slash throws", | ||
| async run() { | ||
| try { | ||
| await bridge.read("16.0.0/ReadMe.txt/"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
|
|
||
| // Exists tests | ||
| { | ||
| description: "Exists returns true for 16.0.0/ReadMe.txt", | ||
| async run() { | ||
| if (!(await bridge.exists("16.0.0/ReadMe.txt"))) throw new Error("Should exist"); | ||
| }, | ||
| }, | ||
| { | ||
| description: "Exists returns false for non-existent", | ||
| async run() { | ||
| if (await bridge.exists("16.0.0/NonExistent12345.txt")) throw new Error("Should not exist"); | ||
| }, | ||
| }, | ||
| { | ||
| description: "Exists with / prefix", | ||
| async run() { | ||
| if (!(await bridge.exists("/16.0.0/ReadMe.txt"))) throw new Error("Should exist"); | ||
| }, | ||
| }, | ||
|
|
||
| // Listdir tests | ||
| { | ||
| description: "Listdir 16.0.0 returns entries", | ||
| async run() { | ||
| const entries = await bridge.listdir("16.0.0"); | ||
| if (!Array.isArray(entries)) throw new Error("Should return array"); | ||
| if (entries.length === 0) throw new Error("Should have entries"); | ||
| const hasReadme = entries.some((e) => e.name === "ReadMe.txt"); | ||
| if (!hasReadme) throw new Error("Should contain ReadMe.txt"); | ||
| }, | ||
| }, | ||
| { | ||
| description: "Listdir shallow has empty children", | ||
| async run() { | ||
| const entries = await bridge.listdir("16.0.0"); | ||
| const dir = entries.find((e) => e.type === "directory"); | ||
| if (dir && dir.type === "directory" && dir.children.length > 0) { | ||
| throw new Error("Shallow should have empty children"); | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Listdir recursive populates children", | ||
| async run() { | ||
| const entries = await bridge.listdir("16.0.0/ucd", true); | ||
| // Note: this may not find a dir with children if ucd has no subdirs | ||
| if (!Array.isArray(entries)) throw new Error("Should return array"); | ||
| }, | ||
| }, | ||
| { | ||
| description: "Listdir non-existent returns empty array", | ||
| async run() { | ||
| const entries = await bridge.listdir("NonExistentVersion12345"); | ||
| if (!Array.isArray(entries) || entries.length !== 0) { | ||
| throw new Error("Should return empty array"); | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Listdir with / prefix", | ||
| async run() { | ||
| const entries = await bridge.listdir("/16.0.0"); | ||
| if (entries.length === 0) throw new Error("Should have entries"); | ||
| }, | ||
| }, | ||
|
|
||
| // Unsupported operations throw | ||
| { | ||
| description: "Write operation throws", | ||
| async run() { | ||
| try { | ||
| await bridge.write?.("test.txt", "content"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Mkdir operation throws", | ||
| async run() { | ||
| try { | ||
| await bridge.mkdir?.("new-dir"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
| { | ||
| description: "Rm operation throws", | ||
| async run() { | ||
| try { | ||
| await bridge.rm?.("test.txt"); | ||
| throw new Error("Should have thrown"); | ||
| } catch (err) { | ||
| if (err instanceof Error && err.message === "Should have thrown") throw err; | ||
| } | ||
| }, | ||
| }, | ||
|
|
||
| // Bridge metadata | ||
| { | ||
| description: "Bridge has correct metadata", | ||
| async run() { | ||
| if (bridge.meta.name !== "HTTP File System Bridge") throw new Error("Wrong name"); | ||
| if (typeof bridge.meta.description !== "string") throw new Error("Missing description"); | ||
| }, | ||
| }, | ||
|
|
||
| // Complex workflow | ||
| { | ||
| description: "Discover and read UnicodeData.txt", | ||
| async run() { | ||
| const entries = await bridge.listdir("16.0.0/ucd"); | ||
| const unicodeData = entries.find((e) => e.name === "UnicodeData.txt"); | ||
| if (!unicodeData) throw new Error("UnicodeData.txt not found"); | ||
| if (unicodeData.type !== "file") throw new Error("Should be a file"); | ||
|
|
||
| const exists = await bridge.exists("16.0.0/ucd/UnicodeData.txt"); | ||
| if (!exists) throw new Error("Should exist"); | ||
|
|
||
| const content = await bridge.read("16.0.0/ucd/UnicodeData.txt"); | ||
| if (!content.includes(";")) throw new Error("Should contain semicolons"); | ||
| }, | ||
| }, | ||
| ]; | ||
|
|
||
| console.log("\nRunning test cases:\n"); | ||
|
|
||
| let passed = 0; | ||
| let failed = 0; | ||
|
|
||
| for (const testCase of testCases) { | ||
| console.log(` ${testCase.description}... `); | ||
|
|
||
| try { | ||
| await testCase.run(); | ||
| console.log("PASS"); | ||
| passed++; | ||
| } catch (error) { | ||
| console.log("FAIL"); | ||
| console.log(` Error: ${(error as Error).message}`); | ||
| failed++; | ||
| } | ||
| } | ||
|
|
||
| console.log(`\n${"=".repeat(60)}`); | ||
| console.log(`\nResults: ${passed} passed, ${failed} failed\n`); | ||
|
|
||
| if (failed > 0) { | ||
| process.exit(1); | ||
luxass marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.