Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { Drive } from "@suaveplan/drive";
import { createNodeFsStorage } from "@suaveplan/storage-file";
import {
createStorageUriResolver,
type UriPlugin,
} from "@suaveplan/storage-uri";
import {
afterEach,
beforeEach,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import { driveUriPlugin } from "../../src/plugins/drive/drive.js";
interface FileUriOptions {
readonly rootDir: string;
}
function fileUriPlugin(options: FileUriOptions): UriPlugin {
const adapter = createNodeFsStorage({
rootDir: options.rootDir,
mkdirp: true,
});
return {
scheme: "file",
adapter,
parse(uri: string) {
// file:///some/path -> key = "some/path"
const idx = uri.indexOf("://");
const after = uri.slice(idx + 3);
const pathStart = after.indexOf("/");
const path = pathStart >= 0 ? after.slice(pathStart + 1) : after;
return { key: path };
},
build(key: string) {
return `file:///${key.replace(/^\//, "")}`;
},
};
}
describe("compose-with-storage-uri integration", () => {
let rootDir: string;
let driveRoot: string;
let drive: Drive;
beforeEach(async () => {
rootDir = mkdtempSync(join(tmpdir(), "drive-uri-file-"));
driveRoot = mkdtempSync(join(tmpdir(), "drive-uri-drive-"));
const driveStorage = Object.assign(
createNodeFsStorage({ rootDir: driveRoot, mkdirp: true }),
{ id: "default" }
);
drive = new Drive(driveStorage);
await drive.initialize();
});
afterEach(async () => {
await drive.dispose();
rmSync(rootDir, { recursive: true, force: true });
rmSync(driveRoot, { recursive: true, force: true });
});
it("file:// and drive:// resolve through one StorageUriResolver", {
timeout: 30000,
}, async () => {
const resolver = createStorageUriResolver([
fileUriPlugin({ rootDir }),
driveUriPlugin({ drive, driveId: "primary" }),
]);
// Seed both backends with distinct bytes.
await drive.write("a.bin", new Uint8Array([0xaa]));
// Use the file plugin directly to write — the resolver rejects
// writes for drive:// (by design) so we exercise the file side via
// resolver.write to confirm it works.
await resolver.write("file:///b.bin", new Uint8Array([0xbb]));
const fileBytes = await resolver.read("file:///b.bin");
const driveBytes = await resolver.read("drive://primary/a.bin");
expect(Array.from(fileBytes)).toEqual([0xbb]);
expect(Array.from(driveBytes)).toEqual([0xaa]);
// Neither plugin sees the other's state.
expect(resolver.hasScheme("file")).toBe(true);
expect(resolver.hasScheme("drive")).toBe(true);
expect(resolver.schemeCount).toBe(2);
});
});

View File

@@ -0,0 +1,76 @@
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { Drive } from "@suaveplan/drive";
import { createNodeFsStorage } from "@suaveplan/storage-file";
import { createStorageUriResolver } from "@suaveplan/storage-uri";
import {
afterEach,
beforeEach,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import { driveUriPlugin } from "../../src/plugins/drive/drive.js";
describe("drive-roundtrip integration", () => {
let rootDir: string;
let drive: Drive;
beforeEach(async () => {
rootDir = mkdtempSync(join(tmpdir(), "drive-uri-roundtrip-"));
const fileStorage = createNodeFsStorage({ rootDir, mkdirp: true });
const storage = Object.assign(fileStorage, { id: "default" });
drive = new Drive(storage);
await drive.initialize();
});
afterEach(async () => {
await drive.dispose();
rmSync(rootDir, { recursive: true, force: true });
});
it("writes a file via Drive.write then reads it via resolver.read('drive://')", {
timeout: 30000,
}, async () => {
const plugin = driveUriPlugin({ drive, driveId: "test-drive" });
const resolver = createStorageUriResolver([plugin]);
const payload = new Uint8Array([0x4d, 0x4f, 0x56, 0x21]);
await drive.write("folder/clip.mov", payload);
const bytes = await resolver.read("drive://test-drive/folder/clip.mov");
expect(Array.from(bytes)).toEqual(Array.from(payload));
});
it("resolver.open streams the file via Drive.createReadStream", {
timeout: 30000,
}, async () => {
const plugin = driveUriPlugin({ drive, driveId: "test-drive" });
const resolver = createStorageUriResolver([plugin]);
const payload = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
await drive.write("clip.dat", payload);
const stream = await resolver.open("drive://test-drive/clip.dat");
const reader = stream.getReader();
const chunks: number[] = [];
for (;;) {
const { value, done } = await reader.read();
if (done) break;
if (value !== undefined) chunks.push(...value);
}
reader.releaseLock();
expect(chunks).toEqual(Array.from(payload));
});
it("resolver.remove deletes the file", { timeout: 30000 }, async () => {
const plugin = driveUriPlugin({ drive, driveId: "test-drive" });
const resolver = createStorageUriResolver([plugin]);
await drive.write("doomed.bin", new Uint8Array([42]));
const removed = await resolver.remove("drive://test-drive/doomed.bin");
expect(removed).toBe(true);
// A subsequent read should yield STORAGE_URI.NOT_FOUND (the
// adapter translates Drive's not-found into undefined, and the
// resolver maps undefined to NOT_FOUND).
await expect(
resolver.read("drive://test-drive/doomed.bin")
).rejects.toBeDefined();
});
});

View File

@@ -0,0 +1,96 @@
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { Drive } from "@suaveplan/drive";
import { createNodeFsStorage } from "@suaveplan/storage-file";
import { createStorageUriResolver } from "@suaveplan/storage-uri";
import {
afterEach,
beforeEach,
describe,
expect,
it,
} from "@suaveplan/testing/runner";
import {
DRIVE_URI_CODES,
DriveUriError,
} from "../../src/error-codes/error-codes.js";
import { driveTemplateUriPlugin } from "../../src/plugins/drive-template/drive-template.js";
describe("template-roundtrip integration", () => {
let rootDir: string;
let drive: Drive;
beforeEach(async () => {
rootDir = mkdtempSync(join(tmpdir(), "drive-uri-template-"));
const fileStorage = createNodeFsStorage({ rootDir, mkdirp: true });
const storage = Object.assign(fileStorage, { id: "default" });
drive = new Drive(storage);
await drive.initialize();
});
afterEach(async () => {
await drive.dispose();
rmSync(rootDir, { recursive: true, force: true });
});
it("real Drive.hydrateFrom rejects unsigned template as TEMPLATE_INVALID", {
timeout: 30000,
}, async () => {
const provider = {
async fetchTemplate(): Promise<unknown> {
// Returning an obviously-malformed template forces
// Drive.hydrateFrom's validation pipeline to reject.
return {};
},
};
const plugin = driveTemplateUriPlugin({
drive,
templateProvider: provider as unknown as Parameters<
typeof driveTemplateUriPlugin
>[0]["templateProvider"],
});
const resolver = createStorageUriResolver([plugin]);
try {
await resolver.read("drive+template://templA/x");
throw new Error("expected throw");
} catch (err) {
// SuaveplanError subclasses pass through the resolver
// unchanged, so the caller sees the DriveUriError directly.
expect(err).toBeInstanceOf(DriveUriError);
const e = err as DriveUriError;
expect(e.code).toBe(DRIVE_URI_CODES.TEMPLATE_INVALID);
// The inner cause is the real DTP_*/DRIVE error surfaced by
// Drive's hydrateFrom — confirming the wrapping path is wired
// through real package code, not a stub.
expect(e.cause).toBeDefined();
}
});
it("provider rejection becomes TEMPLATE_NOT_AVAILABLE via real Drive", {
timeout: 30000,
}, async () => {
const original = new Error("network down");
const provider = {
async fetchTemplate(): Promise<never> {
throw original;
},
};
const plugin = driveTemplateUriPlugin({
drive,
templateProvider: provider as unknown as Parameters<
typeof driveTemplateUriPlugin
>[0]["templateProvider"],
});
const resolver = createStorageUriResolver([plugin]);
try {
await resolver.read("drive+template://templA/x");
throw new Error("expected throw");
} catch (err) {
expect(err).toBeInstanceOf(DriveUriError);
const e = err as DriveUriError;
expect(e.code).toBe(DRIVE_URI_CODES.TEMPLATE_NOT_AVAILABLE);
expect(e.cause).toBe(original);
}
});
});