Skip to content

Commit

Permalink
fix: improve data parsing for unstorage (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
Aareksio authored Jan 11, 2024
1 parent 39c7199 commit be4b092
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 5 deletions.
41 changes: 36 additions & 5 deletions src/storage/unstorage.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import type { Storage, Driver } from "unstorage";
import { createError } from "h3";
import type { IPXStorage, IPXStorageMeta } from "../types";

export type UnstorageIPXStorageOptions = {
prefix?: string;
};

export function unstorageToIPXStorage(
storage: Storage | Driver,
prefix: string,
_options: UnstorageIPXStorageOptions | string = {},
): IPXStorage {
const resolveKey = (id: string) => prefix + ":" + id;
const options =
typeof _options === "string" ? { prefix: _options } : _options;

const resolveKey = (id: string) =>
options.prefix ? `${options.prefix}:${id}` : id;

return {
name: "ipx:" + ((storage as any).name || "unstorage"),
async getMeta(id, opts = {}) {
Expand All @@ -21,9 +31,30 @@ export function unstorageToIPXStorage(
return;
}
const storageKey = resolveKey(id);
const data = await storage.getItemRaw(storageKey, opts);
// TODO: Convert Buffer to ArrayBuffer
return data as ArrayBuffer;

// Known possible data types: ArrayBuffer, Buffer, String, Blob
let data = await storage.getItemRaw(storageKey, opts);

if (!data) {
// File not found, do not attempt to parse
return;
}

if (data instanceof Blob) {
data = await data.arrayBuffer();
}

try {
// IPX requires a Buffer, attempt parse and normalize error
return Buffer.from(data as ArrayBuffer);
} catch (error: any) {
throw createError({
statusCode: 500,
statusText: `IPX_STORAGE_ERROR`,
message: `Failed to parse storage data to Buffer:\n${error.message}`,
cause: error,
});
}
},
};
}
Binary file added test/assets/nested/bliss.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
105 changes: 105 additions & 0 deletions test/unstorage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { readFile } from "node:fs/promises";
import { resolve } from "pathe";
import { describe, it, expect, beforeAll } from "vitest";
import { createStorage } from "unstorage";
import fsLiteDriver from "unstorage/drivers/fs-lite";
import githubDriver from "unstorage/drivers/github";
import httpDriver from "unstorage/drivers/http";
import { IPX, createIPX, unstorageToIPXStorage } from "../src";

const sampleImage = await readFile(
new URL("assets/bliss.jpg", import.meta.url),
);

const tests = [
{
name: "node-fs",
skip: false,
setup() {
// eslint-disable-next-line unicorn/prefer-module
const driver = fsLiteDriver({ base: resolve(__dirname, "assets") });
const storage = createStorage({ driver });
return createIPX({ storage: unstorageToIPXStorage(storage) });
},
},
{
name: "memory",
skip: false,
async setup() {
const storage = createStorage();
await storage.setItemRaw("bliss.jpg", sampleImage);
await storage.setItemRaw("nested/bliss.jpg", sampleImage);
return createIPX({ storage: unstorageToIPXStorage(storage) });
},
},
{
name: "memory (prefixed)",
skip: false,
async setup() {
const storage = createStorage();
await storage.setItemRaw("images/bliss.jpg", sampleImage);
await storage.setItemRaw("images/nested/bliss.jpg", sampleImage);
return createIPX({
storage: unstorageToIPXStorage(storage, { prefix: "images" }),
});
},
},
{
name: "github",
skip: !process.env.TEST_UNSTORAGE_GITHUB,
setup: () => {
const driver = githubDriver({ repo: "unjs/ipx", dir: "test/assets" });
const storage = createStorage({ driver });
return createIPX({ storage: unstorageToIPXStorage(storage) });
},
},
{
name: "http",
skip: !process.env.TEST_UNSTORAGE_HTTP,
setup: () => {
const driver = httpDriver({
base: "https://raw.githubusercontent.com/unjs/ipx/main/test/assets",
});
const storage = createStorage({ driver });
return createIPX({ storage: unstorageToIPXStorage(storage) });
},
},
] as const;

for (const test of tests) {
describe.skipIf(test.skip)(`unstorage:ipx:${test.name}`, () => {
let ipx: IPX;

beforeAll(async () => {
ipx = await test.setup();
});

it("file found", async () => {
const source = await ipx("bliss.jpg");
const { data, format } = await source.process();
expect(data).toBeInstanceOf(Buffer);
expect(format).toBe("jpeg");
});

it("file found nested", async () => {
const source = await ipx("nested/bliss.jpg");
const { data, format } = await source.process();
expect(data).toBeInstanceOf(Buffer);
expect(format).toBe("jpeg");
});

it("file not found", async () => {
const source = await ipx("unknown.jpg");
await expect(() => source.process()).rejects.toThrowError(
"Resource not found: /unknown.jpg",
);
});

it("invalid path", async () => {
const source = await ipx("*.jpg");
await expect(() => source.process()).rejects.toThrowError(
"Resource not found: /*.jpg",
);
});
});
}

0 comments on commit be4b092

Please sign in to comment.