@tinycloud/vfs 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/worker.ts","../src/errors.ts","../src/pathing.ts","../src/metadata.ts"],"sourcesContent":["import { parentPort } from \"node:worker_threads\";\nimport type { MessagePort } from \"node:worker_threads\";\nimport { TinyCloudNode } from \"@tinycloud/node-sdk\";\nimport { createEACCES, createEEXIST, createEIO, createEISDIR, createENOTDIR, createENOTEMPTY, createENOENT, createEINVAL, createEBUSY } from \"./errors\";\nimport { dirnameOf, INTERNAL_META_PREFIX, joinStoragePath, normalizeStoragePrefix, toLogicalPath } from \"./pathing\";\nimport { dataKey, decodeEnvelope, decodeMetadata, encodeFileValue, metadataKey, metadataPrefix, normalizeMode, nowMetadata, stripStoragePrefix } from \"./metadata\";\nimport type {\n TinyCloudVfsDirent,\n TinyCloudVfsMetadata,\n TinyCloudVfsSource,\n TinyCloudVfsWorkerInit,\n WorkerRequest,\n WorkerResponse,\n} from \"./types\";\n\ntype KvLike = {\n config?: { prefix?: string };\n get: (key: string, options?: Record<string, unknown>) => Promise<any>;\n put: (key: string, value: unknown, options?: Record<string, unknown>) => Promise<any>;\n list: (options?: Record<string, unknown>) => Promise<any>;\n delete: (key: string, options?: Record<string, unknown>) => Promise<any>;\n};\n\ninterface WorkerState {\n kv: KvLike | null;\n kvPrefix: string;\n storageRoot: string;\n}\n\nconst state: WorkerState = {\n kv: null,\n kvPrefix: \"\",\n storageRoot: \"\",\n};\n\nfunction toWorkerError(error: unknown): WorkerResponse {\n if (error && typeof error === \"object\" && \"code\" in error && \"message\" in error) {\n const typed = error as NodeJS.ErrnoException;\n return {\n ok: false,\n error: {\n code: typed.code ?? \"EIO\",\n message: typed.message,\n syscall: typed.syscall,\n path: typed.path,\n },\n };\n }\n\n return {\n ok: false,\n error: {\n code: \"EIO\",\n message: error instanceof Error ? error.message : String(error),\n syscall: \"vfs\",\n },\n };\n}\n\nfunction ensureKv(): KvLike {\n if (!state.kv) {\n throw createEIO(\"init\", \"/\", \"worker is not initialized\");\n }\n return state.kv;\n}\n\nfunction ensureMountedLogicalPath(inputPath: string): string {\n try {\n return toLogicalPath(inputPath);\n } catch {\n throw createENOENT(\"resolve\", inputPath);\n }\n}\n\nfunction effectiveStorageRoot(): string {\n return joinStoragePath(state.kvPrefix, state.storageRoot);\n}\n\nfunction effectiveStoragePath(logicalPath = \"\"): string {\n return joinStoragePath(effectiveStorageRoot(), logicalPath);\n}\n\nfunction scopedDataKey(logicalPath: string): string {\n return dataKey(effectiveStorageRoot(), logicalPath);\n}\n\nfunction scopedMetaKey(logicalPath: string): string {\n return metadataKey(effectiveStorageRoot(), logicalPath);\n}\n\nfunction scopedMetaPrefix(logicalPath = \"\"): string {\n return metadataPrefix(effectiveStorageRoot(), logicalPath);\n}\n\nfunction effectiveListPrefix(logicalPath = \"\", options?: { trailingSlash?: boolean }): string {\n const prefix = effectiveStoragePath(logicalPath);\n if (!options?.trailingSlash || !prefix) {\n return prefix;\n }\n return prefix.endsWith(\"/\") ? prefix : `${prefix}/`;\n}\n\nasync function kvGet(key: string): Promise<unknown> {\n const kv = ensureKv();\n const result = await kv.get(key);\n if (!result.ok) {\n if (result.error?.code === \"KV_NOT_FOUND\") {\n throw createENOENT(\"get\", key);\n }\n if (result.error?.code === \"AUTH_UNAUTHORIZED\") {\n throw createEACCES(\"get\", key, result.error.message);\n }\n throw createEIO(\"get\", key, result.error?.message ?? \"kv get failed\");\n }\n\n return result.data.data;\n}\n\nasync function kvPut(key: string, value: unknown): Promise<void> {\n const kv = ensureKv();\n const result = await kv.put(key, value);\n if (!result.ok) {\n if (result.error?.code === \"AUTH_UNAUTHORIZED\") {\n throw createEACCES(\"put\", key, result.error.message);\n }\n throw createEIO(\"put\", key, result.error?.message ?? \"kv put failed\");\n }\n}\n\nasync function kvDelete(key: string): Promise<void> {\n const kv = ensureKv();\n const result = await kv.delete(key);\n if (!result.ok) {\n if (result.error?.code === \"KV_NOT_FOUND\") {\n throw createENOENT(\"unlink\", key);\n }\n if (result.error?.code === \"AUTH_UNAUTHORIZED\") {\n throw createEACCES(\"unlink\", key, result.error.message);\n }\n throw createEIO(\"unlink\", key, result.error?.message ?? \"kv delete failed\");\n }\n}\n\nasync function kvList(prefix: string): Promise<string[]> {\n const kv = ensureKv();\n const listOptions = prefix\n ? { prefix, removePrefix: false }\n : { removePrefix: false };\n const result = await kv.list(listOptions);\n if (!result.ok) {\n if (result.error?.code === \"AUTH_UNAUTHORIZED\") {\n throw createEACCES(\"scandir\", prefix, result.error.message);\n }\n throw createEIO(\"scandir\", prefix, result.error?.message ?? \"kv list failed\");\n }\n return result.data.keys ?? [];\n}\n\nasync function tryMetadata(logicalPath: string): Promise<TinyCloudVfsMetadata | null> {\n try {\n return decodeMetadata(await kvGet(scopedMetaKey(logicalPath)));\n } catch (error) {\n const typed = error as NodeJS.ErrnoException;\n if (typed.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function tryRawFile(logicalPath: string): Promise<{ content: Buffer; metadata: TinyCloudVfsMetadata } | null> {\n try {\n const content = decodeEnvelope(await kvGet(scopedDataKey(logicalPath)));\n const metadata = nowMetadata(\n \"file\",\n content.length,\n normalizeMode(\"file\"),\n );\n return { content, metadata };\n } catch (error) {\n const typed = error as NodeJS.ErrnoException;\n if (typed.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nasync function listDescendantKeys(logicalPath: string): Promise<{ dataKeys: string[]; metaKeys: string[] }> {\n const dataPrefixValue = effectiveListPrefix(logicalPath, { trailingSlash: true });\n const metaPrefixValue = effectiveListPrefix(\n joinStoragePath(\".tcvfs-meta\", logicalPath),\n { trailingSlash: true },\n );\n\n const [dataKeys, metaKeys] = await Promise.all([\n kvList(dataPrefixValue),\n kvList(metaPrefixValue),\n ]);\n\n return { dataKeys, metaKeys };\n}\n\nasync function tryInferredDirectory(logicalPath: string): Promise<TinyCloudVfsMetadata | null> {\n const { dataKeys, metaKeys } = await listDescendantKeys(logicalPath);\n if (dataKeys.length === 0 && metaKeys.length === 0) {\n return null;\n }\n\n return nowMetadata(\n \"directory\",\n 4096,\n normalizeMode(\"directory\"),\n );\n}\n\nasync function ensureDirectory(logicalPath: string): Promise<TinyCloudVfsMetadata> {\n if (!logicalPath) {\n return nowMetadata(\"directory\", 4096, normalizeMode(\"directory\"));\n }\n\n const metadata = await tryMetadata(logicalPath);\n if (metadata) {\n if (metadata.kind !== \"directory\") {\n throw createENOTDIR(\"stat\", `/${logicalPath}`);\n }\n return metadata;\n }\n\n const inferred = await tryInferredDirectory(logicalPath);\n if (!inferred) {\n throw createENOENT(\"stat\", `/${logicalPath}`);\n }\n return inferred;\n}\n\nasync function readFileEntry(logicalPath: string): Promise<{ content: Buffer; metadata: TinyCloudVfsMetadata }> {\n const metadata = await tryMetadata(logicalPath);\n if (metadata) {\n if (metadata.kind !== \"file\") {\n throw createEISDIR(\"open\", `/${logicalPath}`);\n }\n\n const content = decodeEnvelope(await kvGet(scopedDataKey(logicalPath)));\n return { content, metadata };\n }\n\n const rawFile = await tryRawFile(logicalPath);\n if (rawFile) {\n return rawFile;\n }\n\n if (await tryInferredDirectory(logicalPath)) {\n throw createEISDIR(\"open\", `/${logicalPath}`);\n }\n\n throw createENOENT(\"open\", `/${logicalPath}`);\n}\n\nasync function statPath(logicalPath: string): Promise<TinyCloudVfsMetadata> {\n if (!logicalPath) {\n return nowMetadata(\"directory\", 4096, normalizeMode(\"directory\"));\n }\n\n const metadata = await tryMetadata(logicalPath);\n if (metadata) {\n return metadata;\n }\n\n const rawFile = await tryRawFile(logicalPath);\n if (rawFile) {\n return rawFile.metadata;\n }\n\n const inferredDirectory = await tryInferredDirectory(logicalPath);\n if (inferredDirectory) {\n return inferredDirectory;\n }\n\n throw createENOENT(\"stat\", `/${logicalPath}`);\n}\n\nasync function ensureParentDirectory(logicalPath: string): Promise<void> {\n const parent = dirnameOf(logicalPath);\n if (!parent) {\n return;\n }\n await ensureDirectory(parent);\n}\n\nasync function collectDirChildren(logicalPath: string): Promise<TinyCloudVfsDirent[]> {\n await ensureDirectory(logicalPath);\n\n const { dataKeys, metaKeys } = await listDescendantKeys(logicalPath);\n\n const names = new Set<string>();\n const relativePrefix = effectiveStoragePath(logicalPath);\n const relativeMetaPrefix = scopedMetaPrefix(logicalPath);\n\n for (const fullKey of dataKeys) {\n const relative = stripStoragePrefix(fullKey, relativePrefix);\n const first = relative.split(\"/\").filter(Boolean)[0];\n if (first) {\n names.add(first);\n }\n }\n\n for (const fullKey of metaKeys) {\n const relative = stripStoragePrefix(fullKey, relativeMetaPrefix);\n const first = relative.split(\"/\").filter(Boolean)[0];\n if (first) {\n names.add(first);\n }\n }\n\n const entries = await Promise.all(\n [...names]\n .filter((name) => name !== INTERNAL_META_PREFIX)\n .sort()\n .map(async (name): Promise<TinyCloudVfsDirent> => {\n const childPath = joinStoragePath(logicalPath, name);\n const metadata = await statPath(childPath);\n return {\n name,\n kind: metadata.kind,\n parentPath: logicalPath ? `/${logicalPath}` : \"/\",\n };\n }),\n );\n\n return entries;\n}\n\nasync function writeFileEntry(logicalPath: string, content: Uint8Array, mode?: number): Promise<TinyCloudVfsMetadata> {\n await ensureParentDirectory(logicalPath);\n const existing = await tryMetadata(logicalPath);\n if (existing) {\n if (existing.kind !== \"file\") {\n throw createEISDIR(\"writeFile\", `/${logicalPath}`);\n }\n } else if (await tryInferredDirectory(logicalPath)) {\n throw createEISDIR(\"writeFile\", `/${logicalPath}`);\n }\n\n const buffer = Buffer.from(content);\n const metadata = nowMetadata(\n \"file\",\n buffer.length,\n normalizeMode(\"file\", mode ?? existing?.mode),\n existing ?? undefined,\n );\n\n await kvPut(scopedDataKey(logicalPath), encodeFileValue(buffer));\n await kvPut(scopedMetaKey(logicalPath), metadata);\n return metadata;\n}\n\nasync function mkdirEntry(logicalPath: string, recursive = false, mode?: number): Promise<void> {\n if (!logicalPath) {\n return;\n }\n\n const existing = await tryMetadata(logicalPath);\n if (existing) {\n if (existing.kind === \"directory\") {\n return;\n }\n throw createEEXIST(\"mkdir\", `/${logicalPath}`);\n }\n\n if (await tryRawFile(logicalPath)) {\n throw createEEXIST(\"mkdir\", `/${logicalPath}`);\n }\n\n if (await tryInferredDirectory(logicalPath)) {\n return;\n }\n\n const segments = logicalPath.split(\"/\").filter(Boolean);\n const targets = recursive\n ? segments.map((_, index) => segments.slice(0, index + 1).join(\"/\"))\n : [logicalPath];\n\n for (const target of targets) {\n const current = await tryMetadata(target);\n if (current) {\n if (current.kind !== \"directory\") {\n throw createENOTDIR(\"mkdir\", `/${target}`);\n }\n continue;\n }\n\n await ensureParentDirectory(target);\n const metadata = nowMetadata(\"directory\", 4096, normalizeMode(\"directory\", mode));\n await kvPut(scopedMetaKey(target), metadata);\n }\n}\n\nasync function rmdirEntry(logicalPath: string): Promise<void> {\n if (!logicalPath) {\n throw createEBUSY(\"rmdir\", \"/\");\n }\n\n const metadata = await ensureDirectory(logicalPath);\n const children = await collectDirChildren(logicalPath);\n if (children.length > 0) {\n throw createENOTEMPTY(\"rmdir\", `/${logicalPath}`);\n }\n\n await kvDelete(scopedMetaKey(logicalPath));\n}\n\nasync function unlinkEntry(logicalPath: string): Promise<void> {\n const metadata = await statPath(logicalPath);\n if (metadata.kind !== \"file\") {\n throw createEISDIR(\"unlink\", `/${logicalPath}`);\n }\n\n await kvDelete(scopedDataKey(logicalPath));\n try {\n await kvDelete(scopedMetaKey(logicalPath));\n } catch (error) {\n const typed = error as NodeJS.ErrnoException;\n if (typed.code !== \"ENOENT\") {\n throw error;\n }\n }\n}\n\nasync function renameEntry(oldLogicalPath: string, newLogicalPath: string): Promise<void> {\n const source = await statPath(oldLogicalPath);\n if (source.kind !== \"file\") {\n throw createEINVAL(\"rename\", `/${oldLogicalPath}`, \"directory rename is not supported in v1\");\n }\n\n const content = decodeEnvelope(await kvGet(scopedDataKey(oldLogicalPath)));\n await writeFileEntry(newLogicalPath, content, source.mode);\n await unlinkEntry(oldLogicalPath);\n}\n\nasync function initialize(init: TinyCloudVfsWorkerInit): Promise<void> {\n const node = new TinyCloudNode({ host: init.source.host });\n await node.restoreSession(init.source.session);\n\n const kv = node.kv as unknown as KvLike;\n const servicePrefix = init.source.kind === \"resolved-delegation\"\n ? normalizeStoragePrefix(init.source.kvPrefix)\n : normalizeStoragePrefix(kv.config?.prefix);\n const mountPrefix = normalizeStoragePrefix(init.mountPrefix);\n\n state.kv = kv;\n state.kvPrefix = servicePrefix;\n state.storageRoot = mountPrefix;\n}\n\nasync function handleRequest(request: WorkerRequest): Promise<WorkerResponse> {\n switch (request.type) {\n case \"init\":\n await initialize(request.init);\n return { ok: true, result: null };\n case \"stat\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n const metadata = await statPath(logicalPath);\n return { ok: true, result: { metadata } };\n }\n case \"readFile\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n const { content, metadata } = await readFileEntry(logicalPath);\n return { ok: true, result: { content, metadata } };\n }\n case \"writeFile\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n await writeFileEntry(logicalPath, request.content, request.mode);\n return { ok: true, result: null };\n }\n case \"readdir\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n const entries = await collectDirChildren(logicalPath);\n return { ok: true, result: { entries } };\n }\n case \"mkdir\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n await mkdirEntry(logicalPath, request.recursive, request.mode);\n return { ok: true, result: null };\n }\n case \"rmdir\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n await rmdirEntry(logicalPath);\n return { ok: true, result: null };\n }\n case \"unlink\": {\n const logicalPath = ensureMountedLogicalPath(request.path);\n await unlinkEntry(logicalPath);\n return { ok: true, result: null };\n }\n case \"rename\": {\n const oldLogicalPath = ensureMountedLogicalPath(request.oldPath);\n const newLogicalPath = ensureMountedLogicalPath(request.newPath);\n await renameEntry(oldLogicalPath, newLogicalPath);\n return { ok: true, result: null };\n }\n default:\n throw createEINVAL(\"vfs\", \"/\");\n }\n}\n\nparentPort?.on(\"message\", async (message: { request: WorkerRequest; replyPort: MessagePort; waitBuffer: SharedArrayBuffer }) => {\n const view = new Int32Array(message.waitBuffer);\n\n try {\n const response = await handleRequest(message.request);\n message.replyPort.postMessage(response);\n } catch (error) {\n message.replyPort.postMessage(toWorkerError(error));\n } finally {\n Atomics.store(view, 0, 1);\n Atomics.notify(view, 0, 1);\n message.replyPort.close();\n }\n});\n","const ERRNO: Record<string, number> = {\n EPERM: -1,\n ENOENT: -2,\n EIO: -5,\n EBADF: -9,\n EACCES: -13,\n EBUSY: -16,\n EEXIST: -17,\n ENOTDIR: -20,\n EISDIR: -21,\n EINVAL: -22,\n ENOTEMPTY: -39,\n EROFS: -30,\n};\n\nexport function createNodeError(\n code: string,\n message: string,\n syscall: string,\n path?: string,\n): NodeJS.ErrnoException {\n const error = new Error(message) as NodeJS.ErrnoException;\n error.code = code;\n error.errno = ERRNO[code] ?? -1;\n error.syscall = syscall;\n if (path) {\n error.path = path;\n }\n return error;\n}\n\nexport function createENOENT(syscall: string, path: string): NodeJS.ErrnoException {\n return createNodeError(\"ENOENT\", `no such file or directory, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEISDIR(syscall: string, path: string): NodeJS.ErrnoException {\n return createNodeError(\"EISDIR\", `illegal operation on a directory, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createENOTDIR(syscall: string, path: string): NodeJS.ErrnoException {\n return createNodeError(\"ENOTDIR\", `not a directory, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createENOTEMPTY(syscall: string, path: string): NodeJS.ErrnoException {\n return createNodeError(\"ENOTEMPTY\", `directory not empty, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEEXIST(syscall: string, path: string): NodeJS.ErrnoException {\n return createNodeError(\"EEXIST\", `file already exists, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEACCES(syscall: string, path: string, message = \"permission denied\"): NodeJS.ErrnoException {\n return createNodeError(\"EACCES\", `${message}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEROFS(syscall: string, path: string): NodeJS.ErrnoException {\n return createNodeError(\"EROFS\", `read-only file system, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEIO(syscall: string, path: string, message: string): NodeJS.ErrnoException {\n return createNodeError(\"EIO\", `${message}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEBUSY(syscall: string, path: string, message = \"resource busy or locked\"): NodeJS.ErrnoException {\n return createNodeError(\"EBUSY\", `${message}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function createEINVAL(syscall: string, path: string, message = \"invalid argument\"): NodeJS.ErrnoException {\n return createNodeError(\"EINVAL\", `${message}, ${syscall} '${path}'`, syscall, path);\n}\n\nexport function fromWorkerError(error: { code: string; message: string; syscall?: string; path?: string }): NodeJS.ErrnoException {\n return createNodeError(\n error.code,\n error.message,\n error.syscall ?? \"vfs\",\n error.path,\n );\n}\n","import { posix as pathPosix } from \"node:path\";\n\nexport const INTERNAL_META_PREFIX = \".tcvfs-meta\";\n\nexport function normalizeVfsPath(inputPath: string): string {\n const normalized = pathPosix.normalize(inputPath.replace(/\\\\/g, \"/\"));\n const absolute = normalized.startsWith(\"/\") ? normalized : `/${normalized}`;\n return absolute;\n}\n\nexport function toLogicalPath(inputPath: string): string {\n const normalized = normalizeVfsPath(inputPath);\n\n if (normalized.includes(\"\\0\")) {\n throw new Error(\"invalid path\");\n }\n\n if (normalized === \"/\") {\n return \"\";\n }\n\n const logical = normalized.slice(1);\n if (\n logical === INTERNAL_META_PREFIX ||\n logical.startsWith(`${INTERNAL_META_PREFIX}/`) ||\n logical.split(\"/\").includes(\"..\")\n ) {\n throw new Error(\"path escapes virtual root\");\n }\n\n return logical;\n}\n\nexport function normalizeStoragePrefix(prefix?: string): string {\n if (!prefix) {\n return \"\";\n }\n\n return prefix\n .replace(/\\\\/g, \"/\")\n .replace(/^\\/+/, \"\")\n .replace(/\\/+$/, \"\");\n}\n\nexport function joinStoragePath(...parts: Array<string | undefined>): string {\n const cleaned = parts\n .filter((part): part is string => Boolean(part))\n .map((part) => normalizeStoragePrefix(part));\n\n return cleaned.filter(Boolean).join(\"/\");\n}\n\nexport function dirnameOf(logicalPath: string): string {\n if (!logicalPath) {\n return \"\";\n }\n\n const dir = pathPosix.dirname(`/${logicalPath}`);\n return dir === \"/\" ? \"\" : dir.slice(1);\n}\n\nexport function basenameOf(logicalPath: string): string {\n return pathPosix.basename(logicalPath ? `/${logicalPath}` : \"/\");\n}\n","import { INTERNAL_META_PREFIX, joinStoragePath, normalizeStoragePrefix } from \"./pathing\";\nimport type { TinyCloudVfsFileEnvelope, TinyCloudVfsMetadata } from \"./types\";\n\nexport function dataKey(storageRoot: string, logicalPath: string): string {\n return joinStoragePath(storageRoot, logicalPath);\n}\n\nexport function metadataKey(storageRoot: string, logicalPath: string): string {\n return joinStoragePath(storageRoot, INTERNAL_META_PREFIX, logicalPath);\n}\n\nexport function metadataPrefix(storageRoot: string, logicalPath = \"\"): string {\n return joinStoragePath(storageRoot, INTERNAL_META_PREFIX, logicalPath);\n}\n\nexport function encodeEnvelope(content: Buffer): TinyCloudVfsFileEnvelope {\n return {\n version: 1,\n encoding: \"base64\",\n data: content.toString(\"base64\"),\n };\n}\n\nfunction isEnvelopeShape(value: unknown): value is TinyCloudVfsFileEnvelope {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n (value as TinyCloudVfsFileEnvelope).version === 1 &&\n (value as TinyCloudVfsFileEnvelope).encoding === \"base64\" &&\n typeof (value as TinyCloudVfsFileEnvelope).data === \"string\"\n );\n}\n\nexport function encodeFileValue(content: Buffer): string | TinyCloudVfsFileEnvelope {\n const utf8 = content.toString(\"utf8\");\n if (Buffer.from(utf8, \"utf8\").equals(content)) {\n return utf8;\n }\n\n return encodeEnvelope(content);\n}\n\nexport function decodeEnvelope(value: unknown): Buffer {\n if (isEnvelopeShape(value)) {\n return Buffer.from((value as TinyCloudVfsFileEnvelope).data, \"base64\");\n }\n\n if (typeof value === \"string\") {\n try {\n const parsed = JSON.parse(value) as unknown;\n if (isEnvelopeShape(parsed)) {\n return Buffer.from(parsed.data, \"base64\");\n }\n } catch {\n // Plain text payloads are expected and should fall through.\n }\n\n return Buffer.from(value, \"utf8\");\n }\n\n throw new Error(\"unsupported file payload\");\n}\n\nfunction isMetadataShape(value: unknown): value is TinyCloudVfsMetadata {\n return Boolean(\n value &&\n typeof value === \"object\" &&\n (((value as TinyCloudVfsMetadata).kind === \"file\") || ((value as TinyCloudVfsMetadata).kind === \"directory\")) &&\n typeof (value as TinyCloudVfsMetadata).size === \"number\" &&\n typeof (value as TinyCloudVfsMetadata).mode === \"number\" &&\n typeof (value as TinyCloudVfsMetadata).ctimeMs === \"number\" &&\n typeof (value as TinyCloudVfsMetadata).mtimeMs === \"number\" &&\n typeof (value as TinyCloudVfsMetadata).birthtimeMs === \"number\"\n );\n}\n\nexport function decodeMetadata(value: unknown): TinyCloudVfsMetadata {\n if (isMetadataShape(value)) {\n return value;\n }\n\n if (typeof value === \"string\") {\n const parsed = JSON.parse(value) as unknown;\n if (isMetadataShape(parsed)) {\n return parsed;\n }\n }\n\n throw new Error(\"unsupported metadata payload\");\n}\n\nexport function nowMetadata(kind: \"file\" | \"directory\", size: number, mode: number, existing?: TinyCloudVfsMetadata): TinyCloudVfsMetadata {\n const now = Date.now();\n return {\n kind,\n size,\n mode,\n ctimeMs: now,\n mtimeMs: now,\n birthtimeMs: existing?.birthtimeMs ?? now,\n };\n}\n\nexport function normalizeMode(kind: \"file\" | \"directory\", mode?: number): number {\n if (typeof mode === \"number\" && Number.isFinite(mode)) {\n return mode;\n }\n\n return kind === \"directory\" ? 0o755 : 0o644;\n}\n\nexport function stripStoragePrefix(fullKey: string, prefix: string): string {\n const normalizedPrefix = normalizeStoragePrefix(prefix);\n if (!normalizedPrefix) {\n return fullKey.replace(/^\\/+/, \"\");\n }\n\n const withSlash = `${normalizedPrefix}/`;\n if (fullKey === normalizedPrefix) {\n return \"\";\n }\n\n if (fullKey.startsWith(withSlash)) {\n return fullKey.slice(withSlash.length);\n }\n\n return fullKey;\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@tinycloud/vfs",
3
+ "version": "0.1.0-beta.0",
4
+ "description": "TinyCloud Virtual File System for Node.js",
5
+ "author": "TinyCloud, Inc.",
6
+ "license": "EGPL",
7
+ "type": "module",
8
+ "main": "dist/index.cjs",
9
+ "module": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22"
23
+ },
24
+ "scripts": {
25
+ "build": "tsup",
26
+ "clean": "rm -rf dist"
27
+ },
28
+ "dependencies": {
29
+ "@platformatic/vfs": "^0.3.0",
30
+ "@tinycloud/node-sdk": "2.1.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^20",
34
+ "tsup": "^8.0.0",
35
+ "typescript": "^5.0.0"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/tinycloudlabs/web-sdk"
40
+ }
41
+ }