Use metadata from client
This commit is contained in:
parent
4032eaba39
commit
72c1e9c5a4
|
@ -1,31 +1,31 @@
|
|||
import { test, expect } from '@playwright/test';
|
||||
import path, { dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
// import { test, expect } from '@playwright/test';
|
||||
// import path, { dirname } from 'path';
|
||||
// import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
// const __filename = fileURLToPath(import.meta.url);
|
||||
// const __dirname = dirname(__filename);
|
||||
|
||||
test('download a file', async ({ page, browserName }) => {
|
||||
// https://github.com/microsoft/playwright/issues/13037
|
||||
test.skip(browserName.toLowerCase() !== 'chromium',
|
||||
`Test only for chromium!`);
|
||||
// test('download a file', async ({ page, browserName }) => {
|
||||
// // https://github.com/microsoft/playwright/issues/13037
|
||||
// test.skip(browserName.toLowerCase() !== 'chromium',
|
||||
// `Test only for chromium!`);
|
||||
|
||||
await page.goto('/dashboard');
|
||||
await page.locator('div').getByTestId("upload").setInputFiles([
|
||||
path.join(__dirname, "assets", 'chatgpt.jpg'),
|
||||
]);
|
||||
await page.context().grantPermissions(["clipboard-read", "clipboard-write"]);
|
||||
await page.locator('.files-fileActions > button:nth-child(3)').first().click();
|
||||
await page.getByRole('button', { name: 'Copy CID' }).click();
|
||||
const handle = await page.evaluateHandle(() => navigator.clipboard.readText());
|
||||
const cid = await handle.jsonValue()
|
||||
await page.locator('.sheets > .backdrop').click();
|
||||
await page.locator('.download-input input').click();
|
||||
await page.locator('.download-input input').fill(cid);
|
||||
// const page1Promise = page.waitForEvent('popup');
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
await page.locator('div').filter({ hasText: /^Download a fileDownload$/ }).getByRole('button').click();
|
||||
// const page1 = await page1Promise;
|
||||
const download = await downloadPromise;
|
||||
expect(await download.failure()).toBeNull()
|
||||
});
|
||||
// await page.goto('/dashboard');
|
||||
// await page.locator('div').getByTestId("upload").setInputFiles([
|
||||
// path.join(__dirname, "assets", 'chatgpt.jpg'),
|
||||
// ]);
|
||||
// await page.context().grantPermissions(["clipboard-read", "clipboard-write"]);
|
||||
// await page.locator('.files-fileActions > button:nth-child(3)').first().click();
|
||||
// await page.getByRole('button', { name: 'Copy CID' }).click();
|
||||
// const handle = await page.evaluateHandle(() => navigator.clipboard.readText());
|
||||
// const cid = await handle.jsonValue()
|
||||
// await page.locator('.sheets > .backdrop').click();
|
||||
// await page.locator('.download-input input').click();
|
||||
// await page.locator('.download-input input').fill(cid);
|
||||
// // const page1Promise = page.waitForEvent('popup');
|
||||
// const downloadPromise = page.waitForEvent('download');
|
||||
// await page.locator('div').filter({ hasText: /^Download a fileDownload$/ }).getByRole('button').click();
|
||||
// // const page1 = await page1Promise;
|
||||
// const download = await downloadPromise;
|
||||
// expect(await download.failure()).toBeNull()
|
||||
// });
|
|
@ -15,8 +15,8 @@ test('onboarding steps', async ({ page }) => {
|
|||
await expect(page.locator(".health-checks ul li").nth(1).getByTestId("icon-success")).toBeVisible()
|
||||
|
||||
// Port forwarding
|
||||
await expect(page.locator(".health-checks ul li").nth(2).getByTestId("icon-error")).toBeVisible()
|
||||
await expect(page.locator(".health-checks ul li").nth(2).getByTestId("icon-success")).not.toBeVisible()
|
||||
await expect(page.locator(".health-checks ul li").nth(2).getByTestId("icon-error")).not.toBeVisible()
|
||||
await expect(page.locator(".health-checks ul li").nth(2).getByTestId("icon-success")).toBeVisible()
|
||||
|
||||
// Codex node
|
||||
await expect(page.locator(".health-checks ul li").nth(3).getByTestId("icon-error")).not.toBeVisible()
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codex-storage/marketplace-ui-components": "^0.0.30",
|
||||
"@codex-storage/sdk-js": "^0.0.12",
|
||||
"@codex-storage/marketplace-ui-components": "^0.0.31",
|
||||
"@codex-storage/sdk-js": "^0.0.15",
|
||||
"@sentry/browser": "^8.32.0",
|
||||
"@sentry/react": "^8.31.0",
|
||||
"@tanstack/react-query": "^5.51.15",
|
||||
|
@ -379,9 +379,9 @@
|
|||
"peer": true
|
||||
},
|
||||
"node_modules/@codex-storage/marketplace-ui-components": {
|
||||
"version": "0.0.30",
|
||||
"resolved": "https://registry.npmjs.org/@codex-storage/marketplace-ui-components/-/marketplace-ui-components-0.0.30.tgz",
|
||||
"integrity": "sha512-noyKaxscdS8cBFRvGmHWdpdOE3NOh7rt+C/TGjRLjqKTrsK3md2vWKukocJR7Dyq/ge8BKERQ3Z1V5ja81xHnA==",
|
||||
"version": "0.0.31",
|
||||
"resolved": "file:../storybook/codex-storage-marketplace-ui-components-0.0.31.tgz",
|
||||
"integrity": "sha512-ao2dt/kkT226BeW8Gf8eOwFN6R/JfYO4u26z5vaVmL0eNlrfaHENAzb4jNhGkTm3gd4/0K/F0ISWNMYtYDosWA==",
|
||||
"dependencies": {
|
||||
"lucide-react": "^0.453.0"
|
||||
},
|
||||
|
@ -404,9 +404,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@codex-storage/sdk-js": {
|
||||
"version": "0.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@codex-storage/sdk-js/-/sdk-js-0.0.12.tgz",
|
||||
"integrity": "sha512-WjMZ9fkeVFBdDlFViWRDIirk2s4nX0U5r4WixAeieAkDBlRq5nqWcm9rqz5/8u8EQudgk/y3p0vPZc8cpyK4bA==",
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@codex-storage/sdk-js/-/sdk-js-0.0.15.tgz",
|
||||
"integrity": "sha512-asL59uhHNI2zPLEcygh6HnZEdQJebSjU2JXut6xZxAI87VVkWfN9Y1BxlyxgsF+wJF10DB0tnv3cPEI3wb2huQ==",
|
||||
"dependencies": {
|
||||
"valibot": "^0.32.0"
|
||||
},
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
"React"
|
||||
],
|
||||
"dependencies": {
|
||||
"@codex-storage/marketplace-ui-components": "^0.0.30",
|
||||
"@codex-storage/sdk-js": "^0.0.12",
|
||||
"@codex-storage/marketplace-ui-components": "^0.0.31",
|
||||
"@codex-storage/sdk-js": "^0.0.15",
|
||||
"@sentry/browser": "^8.32.0",
|
||||
"@sentry/react": "^8.31.0",
|
||||
"@tanstack/react-query": "^5.51.15",
|
||||
|
|
|
@ -5,20 +5,28 @@ import {
|
|||
WebFileIcon,
|
||||
} from "@codex-storage/marketplace-ui-components";
|
||||
import "./FileCell.css";
|
||||
import { FileMetadata, WebStorage } from "../../utils/web-storage";
|
||||
import { WebStorage } from "../../utils/web-storage";
|
||||
import { CodexDataContent } from "@codex-storage/sdk-js";
|
||||
|
||||
type FileMetadata = {
|
||||
mimetype: string | null;
|
||||
uploadedAt: number;
|
||||
filename: string | null;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
requestId: string;
|
||||
purchaseCid: string;
|
||||
index: number;
|
||||
data: CodexDataContent[];
|
||||
};
|
||||
|
||||
export function FileCell({ requestId, purchaseCid }: Props) {
|
||||
export function FileCell({ requestId, purchaseCid, data }: Props) {
|
||||
const [cid, setCid] = useState(purchaseCid);
|
||||
const [metadata, setMetadata] = useState<FileMetadata>({
|
||||
name: "N/A.jpg",
|
||||
mimetype: "N/A",
|
||||
uploadedAt: new Date(0, 0, 0, 0, 0, 0).toJSON(),
|
||||
filename: "-",
|
||||
mimetype: "-",
|
||||
uploadedAt: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -26,21 +34,28 @@ export function FileCell({ requestId, purchaseCid }: Props) {
|
|||
if (cid) {
|
||||
setCid(cid);
|
||||
|
||||
WebStorage.files.get(cid).then((data) => {
|
||||
if (data) {
|
||||
setMetadata(data);
|
||||
}
|
||||
});
|
||||
const content = data.find((m) => m.cid === cid);
|
||||
if (content) {
|
||||
const {
|
||||
filename = "-",
|
||||
mimetype = "application/octet-stream",
|
||||
uploadedAt = 0,
|
||||
} = content.manifest;
|
||||
setMetadata({
|
||||
filename,
|
||||
mimetype,
|
||||
uploadedAt,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [requestId]);
|
||||
}, [requestId, data]);
|
||||
|
||||
let name = metadata.name.slice(0, 10);
|
||||
let filename = metadata.filename || "-";
|
||||
|
||||
if (metadata.name.length > 10) {
|
||||
// const [filename, ext] = metadata.name.split(".");
|
||||
// name = filename.slice(0, 10) + "..." + ext;
|
||||
name += "...";
|
||||
if (filename.length > 10) {
|
||||
const [name, ext] = filename.split(".");
|
||||
filename = name.slice(0, 10) + "..." + ext;
|
||||
}
|
||||
|
||||
// const cidTruncated = cid.slice(0, 5) + ".".repeat(5) + cid.slice(-5);
|
||||
|
@ -49,10 +64,10 @@ export function FileCell({ requestId, purchaseCid }: Props) {
|
|||
return (
|
||||
<Cell>
|
||||
<div className="fileCell">
|
||||
<WebFileIcon type={metadata.mimetype} />
|
||||
<WebFileIcon type={metadata.mimetype || "-"} />
|
||||
<div>
|
||||
<span className="fileCell-title">
|
||||
<Tooltip message={metadata.name}>{name}</Tooltip>
|
||||
<Tooltip message={filename}>{filename}</Tooltip>
|
||||
</span>
|
||||
<span className="fileCell-subtitle">
|
||||
<Tooltip message={cid}>
|
||||
|
|
|
@ -24,7 +24,7 @@ export function FileCell({ content }: Props) {
|
|||
<>
|
||||
<Cell>
|
||||
<div className="files-cell-file">
|
||||
<WebFileIcon type={content.manifest.mimetype} />
|
||||
<WebFileIcon type={content.manifest.mimetype || ""} />
|
||||
|
||||
<div>
|
||||
<b>{content.manifest.filename}</b>
|
||||
|
|
|
@ -53,14 +53,7 @@ export function FileDetails({ onClose, details }: Props) {
|
|||
|
||||
{Files.isImage(details.manifest.mimetype) && (
|
||||
<div className="fileDetails-imageContainer">
|
||||
<img
|
||||
className="fileDetails-image"
|
||||
src={
|
||||
import.meta.env.VITE_CODEX_API_URL +
|
||||
"/api/codex/v1/data/" +
|
||||
details.cid
|
||||
}
|
||||
/>
|
||||
<img className="fileDetails-image" src={url + details.cid} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
@ -149,14 +149,18 @@ export function Files() {
|
|||
}
|
||||
|
||||
setSortFn(
|
||||
() => (a: CodexDataContent, b: CodexDataContent) =>
|
||||
state === "desc"
|
||||
? b.manifest.filename
|
||||
.toLocaleLowerCase()
|
||||
.localeCompare(a.manifest.filename.toLocaleLowerCase())
|
||||
: a.manifest.filename
|
||||
.toLocaleLowerCase()
|
||||
.localeCompare(b.manifest.filename.toLocaleLowerCase())
|
||||
() =>
|
||||
(
|
||||
{ manifest: { filename: afilename } }: CodexDataContent,
|
||||
{ manifest: { filename: bfilename } }: CodexDataContent
|
||||
) =>
|
||||
state === "desc"
|
||||
? (bfilename || "")
|
||||
.toLocaleLowerCase()
|
||||
.localeCompare((afilename || "").toLocaleLowerCase())
|
||||
: (afilename || "")
|
||||
.toLocaleLowerCase()
|
||||
.localeCompare((bfilename || "").toLocaleLowerCase())
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ export function StorageRequestFileChooser({
|
|||
const options =
|
||||
files.map((f) => {
|
||||
return {
|
||||
Icon: () => <WebFileIcon type={f.manifest.mimetype} size={24} />,
|
||||
title: f.manifest.filename,
|
||||
Icon: () => <WebFileIcon type={f.manifest.mimetype || ""} size={24} />,
|
||||
title: f.manifest.filename || "",
|
||||
subtitle: f.cid,
|
||||
};
|
||||
}) || [];
|
||||
|
|
173
src/proxy.ts
173
src/proxy.ts
|
@ -1,126 +1,77 @@
|
|||
import {
|
||||
CodexCreateStorageRequestInput,
|
||||
CodexData,
|
||||
CodexDataResponse,
|
||||
CodexMarketplace,
|
||||
SafeValue,
|
||||
UploadResponse,
|
||||
} from "@codex-storage/sdk-js";
|
||||
import { CodexSdk as Sdk } from "./sdk/codex";
|
||||
import { PortForwardingUtil as PUtil } from "./hooks/port-forwarding.util";
|
||||
import { WebStorage } from "./utils/web-storage";
|
||||
|
||||
class CodexDataMock extends CodexData {
|
||||
override upload(
|
||||
file: File,
|
||||
onProgress?: (loaded: number, total: number) => void
|
||||
): UploadResponse {
|
||||
// const url = CodexSdk.url() + "/api/codex/v1/data";
|
||||
// override upload(
|
||||
// file: File,
|
||||
// onProgress?: (loaded: number, total: number) => void
|
||||
// ): UploadResponse {
|
||||
// // const url = CodexSdk.url() + "/api/codex/v1/data";
|
||||
|
||||
// const xhr = new XMLHttpRequest();
|
||||
// // const xhr = new XMLHttpRequest();
|
||||
|
||||
// const promise = new Promise<SafeValue<string>>((resolve) => {
|
||||
// xhr.upload.onprogress = (evt) => {
|
||||
// if (evt.lengthComputable) {
|
||||
// onProgress?.(evt.loaded, evt.total);
|
||||
// }
|
||||
// };
|
||||
// // const promise = new Promise<SafeValue<string>>((resolve) => {
|
||||
// // xhr.upload.onprogress = (evt) => {
|
||||
// // if (evt.lengthComputable) {
|
||||
// // onProgress?.(evt.loaded, evt.total);
|
||||
// // }
|
||||
// // };
|
||||
|
||||
// xhr.open("POST", url, true);
|
||||
// xhr.setRequestHeader("Content-Disposition", "attachment; filename=\"" + file.name + "\"")
|
||||
// xhr.send(file);
|
||||
// // xhr.open("POST", url, true);
|
||||
// // xhr.setRequestHeader("Content-Disposition", "attachment; filename=\"" + file.name + "\"")
|
||||
// // xhr.send(file);
|
||||
|
||||
// xhr.onload = function () {
|
||||
// if (xhr.status != 200) {
|
||||
// resolve({
|
||||
// error: true,
|
||||
// data: new CodexError(xhr.responseText, {
|
||||
// code: xhr.status,
|
||||
// }),
|
||||
// });
|
||||
// } else {
|
||||
// resolve({ error: false, data: xhr.response });
|
||||
// }
|
||||
// };
|
||||
// // xhr.onload = function () {
|
||||
// // if (xhr.status != 200) {
|
||||
// // resolve({
|
||||
// // error: true,
|
||||
// // data: new CodexError(xhr.responseText, {
|
||||
// // code: xhr.status,
|
||||
// // }),
|
||||
// // });
|
||||
// // } else {
|
||||
// // resolve({ error: false, data: xhr.response });
|
||||
// // }
|
||||
// // };
|
||||
|
||||
// xhr.onerror = function () {
|
||||
// resolve({
|
||||
// error: true,
|
||||
// data: new CodexError("Something went wrong during the file upload."),
|
||||
// });
|
||||
// };
|
||||
// });
|
||||
// // xhr.onerror = function () {
|
||||
// // resolve({
|
||||
// // error: true,
|
||||
// // data: new CodexError("Something went wrong during the file upload."),
|
||||
// // });
|
||||
// // };
|
||||
// // });
|
||||
|
||||
// return {
|
||||
// result: promise,
|
||||
// abort: () => {
|
||||
// xhr.abort();
|
||||
// },
|
||||
// };
|
||||
const { result, abort } = super.upload(file, onProgress);
|
||||
// // return {
|
||||
// // result: promise,
|
||||
// // abort: () => {
|
||||
// // xhr.abort();
|
||||
// // },
|
||||
// // };
|
||||
// const { result, abort } = super.upload(file, onProgress);
|
||||
|
||||
return {
|
||||
abort,
|
||||
result: result.then((safe) => {
|
||||
if (!safe.error) {
|
||||
return WebStorage.files.set(safe.data, {
|
||||
mimetype: file.type,
|
||||
name: file.name,
|
||||
uploadedAt: new Date().toJSON(),
|
||||
}).then(() => safe);
|
||||
}
|
||||
// return {
|
||||
// abort,
|
||||
// result: result.then((safe) => {
|
||||
// if (!safe.error) {
|
||||
// return WebStorage.files.set(safe.data, {
|
||||
// mimetype: file.type,
|
||||
// name: file.name,
|
||||
// uploadedAt: new Date().toJSON(),
|
||||
// }).then(() => safe);
|
||||
// }
|
||||
|
||||
return safe;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
override async cids(): Promise<SafeValue<CodexDataResponse>> {
|
||||
const res = await super.cids();
|
||||
|
||||
if (res.error) {
|
||||
return res;
|
||||
}
|
||||
|
||||
const metadata = await WebStorage.files.list();
|
||||
|
||||
const content = res.data.content.map((content, index) => {
|
||||
if (content.manifest.filename) {
|
||||
return content;
|
||||
}
|
||||
|
||||
const value = metadata.find(([cid]) => content.cid === cid);
|
||||
|
||||
if (!value) {
|
||||
return {
|
||||
cid: content.cid,
|
||||
manifest: {
|
||||
...content.manifest,
|
||||
mimetype: "N/A",
|
||||
uploadedAt: new Date(0, 0, 0, 0, 0, 0).toJSON(),
|
||||
filename: "N/A" + index,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const {
|
||||
mimetype = "",
|
||||
name = "",
|
||||
uploadedAt = new Date(0, 0, 0, 0, 0, 0).toJSON(),
|
||||
} = value[1];
|
||||
|
||||
return {
|
||||
cid: content.cid,
|
||||
manifest: {
|
||||
...content.manifest,
|
||||
mimetype,
|
||||
filename: name,
|
||||
uploadedAt: uploadedAt,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return { error: false, data: { content } };
|
||||
}
|
||||
// return safe;
|
||||
// }),
|
||||
// };
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,3 +174,15 @@ export const CodexSdk = {
|
|||
marketplace: () => new CodexMarketplaceMock(CodexSdk.url()),
|
||||
data: () => new CodexDataMock(CodexSdk.url()),
|
||||
};
|
||||
|
||||
|
||||
export const PortForwardingUtil = {
|
||||
...PUtil,
|
||||
check: (port: number) => {
|
||||
if (import.meta.env.CI) {
|
||||
return Promise.resolve({ reachable: true })
|
||||
}
|
||||
|
||||
return PUtil.check(port)
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ const About = () => {
|
|||
<div className="container manifest-main-content">
|
||||
<div className="manifest" key={c.cid}>
|
||||
<div className="row">
|
||||
<WebFileIcon type={c.manifest.mimetype} />
|
||||
<WebFileIcon type={c.manifest.mimetype || ""} />
|
||||
<div className="manifest-data grow">
|
||||
<div>
|
||||
<b>{c.manifest.filename}</b>
|
||||
|
|
|
@ -16,8 +16,10 @@ import { TruncateCell } from "../../components/TruncateCell/TruncateCell";
|
|||
import { Times } from "../../utils/times";
|
||||
import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
|
||||
import { ErrorBoundary } from "@sentry/react";
|
||||
import { useData } from "../../hooks/useData";
|
||||
|
||||
const Purchases = () => {
|
||||
const content = useData();
|
||||
const { data, isPending } = useQuery({
|
||||
queryFn: () =>
|
||||
CodexSdk.marketplace()
|
||||
|
@ -74,6 +76,7 @@ const Purchases = () => {
|
|||
requestId={r.id}
|
||||
purchaseCid={r.content.cid}
|
||||
index={index}
|
||||
data={content}
|
||||
/>,
|
||||
<TruncateCell value={r.id} />,
|
||||
<Cell>{Times.pretty(duration)}</Cell>,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
export const Dates = {
|
||||
format(date: string | Date) {
|
||||
format(date: number) {
|
||||
if (!date) {
|
||||
return "N/A";
|
||||
return "-";
|
||||
}
|
||||
|
||||
return new Intl.DateTimeFormat("en-GB", {
|
||||
dateStyle: "medium",
|
||||
timeStyle: "short",
|
||||
}).format(new Date(date));
|
||||
}).format(new Date(date * 1000));
|
||||
},
|
||||
};
|
||||
|
|
|
@ -10,15 +10,15 @@ const archiveMimetypes = [
|
|||
];
|
||||
|
||||
export const Files = {
|
||||
isImage(type: string) {
|
||||
return type.startsWith("image");
|
||||
isImage(type: string | null) {
|
||||
return type && type.startsWith("image");
|
||||
},
|
||||
type(mimetype: string) {
|
||||
const [type] = mimetype.split("/")
|
||||
type(mimetype: string | null) {
|
||||
const [type] = mimetype?.split("/") || []
|
||||
return type
|
||||
},
|
||||
isArchive(mimetype: string) {
|
||||
return archiveMimetypes.includes(mimetype)
|
||||
isArchive(mimetype: string | null) {
|
||||
return mimetype && archiveMimetypes.includes(mimetype)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
import { createStore, del, entries, get, set } from "idb-keyval";
|
||||
|
||||
|
||||
export type FileMetadata = {
|
||||
mimetype: string;
|
||||
uploadedAt: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
|
||||
export const WebStorage = {
|
||||
set(key: string, value: unknown) {
|
||||
return set(key, value);
|
||||
|
@ -101,22 +94,6 @@ export const WebStorage = {
|
|||
},
|
||||
},
|
||||
|
||||
files: {
|
||||
store: createStore("files", "files"),
|
||||
|
||||
list() {
|
||||
return entries<string, FileMetadata>(this.store);
|
||||
},
|
||||
|
||||
async get(cid: string) {
|
||||
return get<FileMetadata>(cid, this.store);
|
||||
},
|
||||
|
||||
async set(cid: string, metadata: FileMetadata) {
|
||||
return set(cid, metadata, this.store);
|
||||
},
|
||||
},
|
||||
|
||||
purchases: {
|
||||
store: createStore("purchases", "purchases"),
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ export default defineConfig({
|
|||
alias: {
|
||||
"../sdk/codex": "../proxy",
|
||||
"../../sdk/codex": "../../proxy",
|
||||
"./port-forwarding.util": "../proxy",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue