@neodx/vfs
Version:
Simple virtual file system - working dir context, lazy changes, different modes, integrations and moreover
1 lines • 8.23 kB
Source Map (JSON)
{"version":3,"file":"json.mjs","sources":["../../../src/core/file-api.ts","../../../src/plugins/json.ts"],"sourcesContent":["import { mapKeysToObject } from '@neodx/std';\nimport type { BaseVfs } from './types.ts';\n\nexport type FileApi = ReturnType<typeof createFileApi>;\n\nexport const createFileApi = (vfs: BaseVfs, path: string) => ({\n path: vfs.resolve(path),\n ...(mapKeysToObject(inheritedApis, key => (vfs[key] as any).bind(vfs, path)) as {\n [K in (typeof inheritedApis)[number]]: (\n ...args: DropFirst<Parameters<BaseVfs[K]>>\n ) => ReturnType<BaseVfs[K]>;\n })\n});\n\nconst inheritedApis = [\n 'tryRead',\n 'exists',\n 'delete',\n 'rename',\n 'write',\n 'read'\n] satisfies (keyof BaseVfs)[];\n\ntype DropFirst<T extends any[]> = T extends [any, ...infer U] ? U : [];\n","import {\n parseJson,\n type ParseJsonParams,\n serializeJson,\n type SerializeJsonParams\n} from '@neodx/fs';\nimport { createFileApi, type FileApi } from '../core/file-api.ts';\nimport type { BaseVfs } from '../core/types';\nimport { createVfsPlugin } from '../create-vfs-plugin';\n\nexport interface JsonPluginApi {\n jsonFile<FileContents extends JSONValue | unknown = unknown>(\n path: string\n ): JsonFileApi<FileContents>;\n readJson<T extends JSONValue | unknown = unknown>(\n path: string,\n options?: ParseJsonParams\n ): Promise<T>;\n writeJson<T extends JSONValue | unknown = unknown>(\n path: string,\n json: T,\n options?: SerializeJsonParams\n ): Promise<void>;\n updateJson<T extends JSONValue | unknown = unknown>(\n path: string,\n updater: JsonUpdate<T>,\n options?: ParseJsonParams & SerializeJsonParams\n ): Promise<void>;\n}\n\nexport interface JsonFileApi<FileContents extends JSONValue | unknown = unknown>\n extends Omit<FileApi, 'read' | 'write' | 'tryRead'> {\n tryRead<T extends FileContents = FileContents>(options?: ParseJsonParams): Promise<T | null>;\n read<T extends FileContents = FileContents>(options?: ParseJsonParams): Promise<T>;\n write<T extends FileContents = FileContents>(\n json: T,\n options?: SerializeJsonParams\n ): Promise<void>;\n update<T extends FileContents = FileContents>(\n updater: JsonUpdate<T>,\n options?: ParseJsonParams & SerializeJsonParams\n ): Promise<void>;\n /**\n * @todo Implement \"resources\" and streaming APIs\n * @deprecated Unstable API\n */\n experimental_toResource(\n defaultValue: FileContents,\n options?: ParseJsonParams & SerializeJsonParams\n ): Promise<{ data: FileContents } & AsyncDisposable>;\n}\n\nexport type JsonUpdate<T> = (json: T) => T | void | Promise<T | void>;\n\nexport function json() {\n return createVfsPlugin<JsonPluginApi>('json', vfs => {\n vfs.jsonFile = path => createJsonFileApi(vfs, path);\n vfs.readJson = (path, options) => readVfsJson(vfs, path, options);\n vfs.writeJson = (path, json, options) => writeVfsJson(vfs, path, json, options);\n vfs.updateJson = (path, updater, options) => updateVfsJson(vfs, path, updater, options);\n return vfs;\n });\n}\n\nexport function createJsonFileApi<FileContents extends JSONValue | unknown = unknown>(\n vfs: BaseVfs,\n path: string\n): JsonFileApi<FileContents> {\n return {\n ...createFileApi(vfs, path),\n read: options => readVfsJson(vfs, path, options),\n tryRead: options => readVfsJson(vfs, path, options).catch(() => null) as any,\n write: (json, options) => writeVfsJson(vfs, path, json, options),\n update: (updater, options) => updateVfsJson(vfs, path, updater, options),\n experimental_toResource: async (\n defaultValue: FileContents,\n options?: ParseJsonParams & SerializeJsonParams\n ) => {\n const data = (await readVfsJson<FileContents>(vfs, path, options)) ?? defaultValue;\n\n return {\n data,\n [Symbol.asyncDispose]: async () => await writeVfsJson(vfs, path, data, options)\n };\n }\n };\n}\n\nexport async function readVfsJson<T extends JSONValue | unknown = unknown>(\n vfs: BaseVfs,\n path: string,\n options?: ParseJsonParams\n) {\n try {\n return parseJson<T>(await vfs.read(path, 'utf-8'), options);\n } catch (error) {\n throw new Error(`Cannot parse ${path}:\\n${(error as Error).message}`);\n }\n}\n\nexport async function writeVfsJson<T extends JSONValue | unknown = unknown>(\n vfs: BaseVfs,\n path: string,\n json: T,\n options?: SerializeJsonParams\n) {\n return await vfs.write(path, serializeJson(json, options));\n}\n\nexport async function updateVfsJson<T extends JSONValue | unknown = unknown>(\n vfs: BaseVfs,\n path: string,\n updater: JsonUpdate<T>,\n options?: ParseJsonParams & SerializeJsonParams\n) {\n // TODO Implement support for empty, damaged, or nonexistent files\n const current = await readVfsJson(vfs, path, options);\n\n return await writeVfsJson(vfs, path, (await updater(current as any)) ?? current, options);\n}\n\n// TODO Probably, move away to a more generic space\nexport type JSONPrimitive = string | number | boolean | null;\nexport type JSONValue = JSONPrimitive | JSONObject | JSONArray;\nexport type JSONArray = JSONValue[];\nexport interface JSONObject {\n [member: string]: JSONValue;\n}\n"],"names":["createFileApi","vfs","path","resolve","mapKeysToObject","inheritedApis","key","bind","json","createVfsPlugin","jsonFile","createJsonFileApi","readJson","options","readVfsJson","writeJson","writeVfsJson","updateJson","updater","updateVfsJson","read","tryRead","catch","write","update","experimental_toResource","defaultValue","data","Symbol","asyncDispose","parseJson","error","Error","message","serializeJson","current"],"mappings":"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"}