feat(share): add local docker publisher flow

This commit is contained in:
Benjamin Shafii
2026-03-13 13:32:23 -07:00
parent f66d1ded5e
commit 9502137dd4
6 changed files with 143 additions and 5 deletions

View File

@@ -1,11 +1,79 @@
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { head, put } from "@vercel/blob";
import { ulid } from "ulid";
import type { FetchBundleResult, StoreBundleResult } from "./types.ts";
export async function storeBundleJson(rawJson: string): Promise<StoreBundleResult> {
function resolveLocalBlobDir(): string | null {
const explicitDir = String(process.env.LOCAL_BLOB_DIR ?? "").trim();
if (explicitDir) {
return explicitDir;
}
if (String(process.env.BLOB_READ_WRITE_TOKEN ?? "").trim()) {
return null;
}
const isDevLike =
String(process.env.OPENWORK_DEV_MODE ?? "") === "1" ||
String(process.env.NODE_ENV ?? "").trim() !== "production";
if (!isDevLike) {
return null;
}
return path.resolve(process.cwd(), ".openwork-share-blobs");
}
function resolveBundlePathname(id: string): string {
return `bundles/${id}.json`;
}
async function storeBundleJsonLocally(rawJson: string): Promise<StoreBundleResult> {
const id = ulid();
const pathname = `bundles/${id}.json`;
const pathname = resolveBundlePathname(id);
const localBlobDir = resolveLocalBlobDir();
if (!localBlobDir) {
throw new Error("Local blob storage is not configured");
}
const targetPath = path.join(localBlobDir, pathname);
await mkdir(path.dirname(targetPath), { recursive: true });
await writeFile(targetPath, Buffer.from(String(rawJson), "utf8"));
return { id, pathname };
}
async function fetchBundleJsonLocally(id: string): Promise<FetchBundleResult> {
const pathname = resolveBundlePathname(id);
const localBlobDir = resolveLocalBlobDir();
if (!localBlobDir) {
throw new Error("Local blob storage is not configured");
}
const targetPath = path.join(localBlobDir, pathname);
const rawBuffer = await readFile(targetPath);
return {
blob: {
url: `file://${targetPath}`,
contentType: "application/json",
},
rawBuffer,
rawJson: rawBuffer.toString("utf8"),
};
}
export async function storeBundleJson(rawJson: string): Promise<StoreBundleResult> {
if (resolveLocalBlobDir()) {
return storeBundleJsonLocally(rawJson);
}
const id = ulid();
const pathname = resolveBundlePathname(id);
const buffer = Buffer.from(String(rawJson), "utf8");
await put(pathname, buffer, {
@@ -18,7 +86,11 @@ export async function storeBundleJson(rawJson: string): Promise<StoreBundleResul
}
export async function fetchBundleJsonById(id: string): Promise<FetchBundleResult> {
const pathname = `bundles/${id}.json`;
if (resolveLocalBlobDir()) {
return fetchBundleJsonLocally(id);
}
const pathname = resolveBundlePathname(id);
const blob = await head(pathname);
const response = await fetch(blob.url, { method: "GET" });