UNPKG

@alwatr/node-fs

Version:

Enhanced file system operations in Node.js with asynchronous queue to prevent parallel writes.

8 lines (7 loc) 14.4 kB
{ "version": 3, "sources": ["../src/main.ts", "../src/read-file.ts", "../src/common.ts", "../src/write-file.ts", "../src/json.ts", "../src/read-json.ts", "../src/write-json.ts", "../src/make-file.ts"], "sourcesContent": ["export * from './read-file.js';\nexport * from './write-file.js';\nexport * from './read-json.js';\nexport * from './write-json.js';\nexport * from './make-file.js';\n\nexport {resolve} from 'node:path';\nexport {existsSync} from 'node:fs';\nexport {unlink} from 'node:fs/promises';\n", "import {readFileSync as readFileSync_} from 'node:fs';\nimport {readFile as readFile_} from 'node:fs/promises';\n\nimport {flatString} from '@alwatr/flat-string';\n\nimport {asyncQueue, logger} from './common.js';\n\n/**\n * Enhanced read File (Synchronous).\n *\n * @param path - file path\n * @returns file content\n * @example\n * ```typescript\n * const fileContent = readFileSync('./file.txt', sync);\n * ```\n */\nexport function readFileSync(path: string): string {\n logger.logMethodArgs?.('readFileSync', '...' + path.slice(-32));\n // if (!existsSync(path)) throw new Error('file_not_found');\n try {\n return flatString(readFileSync_(path, {encoding: 'utf-8', flag: 'r'}));\n }\n catch (err) {\n logger.error('readFileSync', 'read_file_failed', {path}, err);\n throw new Error('read_file_failed', {cause: (err as Error).cause});\n }\n}\n\n/**\n * Enhanced read File (Asynchronous).\n *\n * - If writing queue is running for target path, it will wait for it to finish.\n *\n * @param path - file path\n * @returns file content\n * @example\n * ```typescript\n * const fileContent = await readFile('./file.txt', sync);\n * ```\n */\nexport function readFile(path: string): Promise<string> {\n logger.logMethodArgs?.('readFile', '...' + path.slice(-32));\n // if (!existsSync(path)) throw new Error('file_not_found');\n return asyncQueue.push(path, async () => {\n try {\n return flatString(await readFile_(path, {encoding: 'utf-8', flag: 'r'}));\n }\n catch (err) {\n logger.error('readFile', 'read_file_failed', {path}, err);\n throw new Error('read_file_failed', {cause: (err as Error).cause});\n }\n });\n}\n", "import {AsyncQueue} from '@alwatr/async-queue';\nimport {createLogger} from '@alwatr/logger';\nimport {packageTracer} from '@alwatr/package-tracer';\n\n__dev_mode__: packageTracer.add(__package_name__, __package_version__);\n\nexport const logger = /* #__PURE__ */ createLogger('@alwatr/node-fs');\n\nexport const asyncQueue = /* #__PURE__ */ new AsyncQueue();\n", "import {writeFileSync as writeFileSync_, existsSync, mkdirSync, renameSync} from 'node:fs';\nimport {mkdir, rename, writeFile as writeFile_} from 'node:fs/promises';\nimport {dirname} from 'node:path';\n\nimport {asyncQueue, logger} from './common.js';\n\n/**\n * Enhanced write file (Synchronous).\n *\n * - If directory not exists, create it recursively.\n * - Write file to `path.tmp` before write success.\n * - If file exists, renamed (keep) to `path.bak`.\n * - If write failed, original file will not be changed.\n *\n * @param path - file path\n * @param content - file content\n * @example\n * ```typescript\n * writeFileSync('./file.txt', 'Hello World!');\n * ```\n */\nexport function writeFileSync(path: string, content: Buffer | string): void {\n logger.logMethodArgs?.('writeFileSync', '...' + path.slice(-32));\n try {\n const pathExists = existsSync(path);\n if (!pathExists) {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, {recursive: true});\n }\n }\n writeFileSync_(path + '.tmp', content, {encoding: 'utf-8', flag: 'w'});\n if (pathExists) {\n renameSync(path, path + '.bak');\n }\n renameSync(path + '.tmp', path);\n logger.logOther?.('writeFileSync success', '...' + path.slice(-32));\n }\n catch (err) {\n logger.error('writeFileSync', 'write_file_failed', {path}, err);\n throw new Error('write_file_failed', {cause: (err as Error).cause});\n }\n}\n\n/**\n * Enhanced write file (Asynchronous).\n *\n * - If directory not exists, create it recursively.\n * - Write file to `path.tmp` before write success.\n * - If file exists, renamed (keep) to `path.bak`.\n * - If write failed, original file will not be changed.\n *\n * @param path - file path\n * @param content - file content\n * @example\n * ```typescript\n * await writeFile('./file.txt', 'Hello World!');\n * ```\n */\nexport function writeFile(path: string, content: Buffer | string): Promise<void> {\n logger.logMethodArgs?.('writeFile', '...' + path.slice(-32));\n return asyncQueue.push(path, async () => {\n try {\n logger.logOther?.('writeFile start', '...' + path.slice(-32));\n const pathExists = existsSync(path);\n if (!pathExists) {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n await mkdir(dir, {recursive: true});\n }\n }\n await writeFile_(path + '.tmp', content, {encoding: 'utf-8', flag: 'w'});\n if (pathExists) {\n await rename(path, path + '.bak');\n }\n await rename(path + '.tmp', path);\n logger.logOther?.('writeFile success', '...' + path.slice(-32));\n }\n catch (err) {\n logger.error('writeFile', 'write_file_failed', {path}, err);\n throw new Error('write_file_failed', {cause: (err as Error).cause});\n }\n });\n}\n", "import {logger} from './common.js';\n\n/**\n * Parse json string.\n *\n * @param content - json string\n * @returns json object\n * @example\n * ```typescript\n * const json = parseJson('{\"a\":1,\"b\":2}');\n * console.log(json.a); // 1\n * ```\n */\nexport function parseJson<T extends JsonValue>(content: string): T {\n try {\n return JSON.parse(content);\n }\n catch (err) {\n logger.error('parseJson', 'invalid_json', err);\n throw new Error('invalid_json', {cause: (err as Error).cause});\n }\n}\n\n/**\n * Stringify json object.\n *\n * @param data - json object\n * @returns json string\n * @example\n * ```typescript\n * const json = jsonStringify({a:1, b:2});\n * console.log(json); // '{\"a\":1,\"b\":2}'\n * ```\n */\nexport function jsonStringify<T extends JsonValue>(data: T): string {\n try {\n return JSON.stringify(data);\n }\n catch (err) {\n logger.error('jsonStringify', 'stringify_failed', err);\n throw new Error('stringify_failed', {cause: (err as Error).cause});\n }\n}\n", "import {logger} from './common.js';\nimport {parseJson} from './json.js';\nimport {readFile, readFileSync} from './read-file.js';\n\n/**\n * Enhanced read json file (async).\n *\n * @param path - file path\n * @returns json object\n * @example\n * ```typescript\n * const fileContent = await readJson('./file.json');\n * ```\n */\nexport function readJson<T extends JsonValue>(path: string): Promise<T>;\n/**\n * Enhanced read json file (sync).\n *\n * @param path - file path\n * @param sync - sync mode\n * @returns json object\n * @example\n * ```typescript\n * const fileContent = readJson('./file.json', true);\n * ```\n */\nexport function readJson<T extends JsonValue>(path: string, sync: true): T;\n/**\n * Enhanced read json file.\n *\n * @param path - file path\n * @param sync - sync mode\n * @returns json object\n * @example\n * ```typescript\n * const fileContent = await readJson('./file.json', sync);\n * ```\n */\nexport function readJson<T extends JsonValue>(path: string, sync: boolean): MaybePromise<T>;\n/**\n * Enhanced read json file.\n *\n * @param path - file path\n * @param sync - sync mode\n * @returns json object\n * @example\n * ```typescript\n * const fileContent = await readJson('./file.json');\n * ```\n */\nexport function readJson<T extends JsonValue>(path: string, sync = false): MaybePromise<T> {\n logger.logMethodArgs?.('readJson', {path: path.slice(-32), sync});\n if (sync === true) {\n return parseJson<T>(readFileSync(path));\n }\n else {\n return readFile(path).then((content) => parseJson<T>(content));\n }\n}\n", "import {flatString} from '@alwatr/flat-string';\n\nimport {logger} from './common.js';\nimport {jsonStringify} from './json.js';\nimport {writeFile, writeFileSync} from './write-file.js';\n\n/**\n * Enhanced write json file (Asynchronous).\n *\n * @param path - file path\n * @param data - json object\n * @example\n * ```typescript\n * await writeJsonFile('./file.json', { a:1, b:2, c:3 });\n * ```\n */\nexport function writeJson<T extends JsonValue>(path: string, data: T, sync?: false): Promise<void>;\n/**\n * Enhanced write json file (Synchronous).\n *\n * @param path - file path\n * @param data - json object\n * @param sync - sync mode\n * @example\n * ```typescript\n * writeJsonFile('./file.json', { a:1, b:2, c:3 }, true);\n * ```\n */\nexport function writeJson<T extends JsonValue>(path: string, data: T, sync: true): void;\n/**\n * Enhanced write json file.\n *\n * @param path - file path\n * @param data - json object\n * @param sync - sync mode\n * @example\n * ```typescript\n * await writeJsonFile('./file.json', { a:1, b:2, c:3 }, sync);\n * ```\n */\nexport function writeJson<T extends JsonValue>(path: string, data: T, sync: boolean): MaybePromise<void>;\n/**\n * Enhanced write json file.\n *\n * @param path - file path\n * @param data - json object\n * @param sync - sync mode\n * @example\n * ```typescript\n * await writeJsonFile('./file.json', { a:1, b:2, c:3 });\n * ```\n */\nexport function writeJson<T extends JsonValue>(path: string, data: T, sync = false): MaybePromise<void> {\n logger.logMethodArgs?.('writeJson', '...' + path.slice(-32));\n const content = flatString(jsonStringify(data));\n return sync === true ? writeFileSync(path, content) : writeFile(path, content);\n}\n", "import { existsSync } from 'node:fs';\nimport {mkdir, open} from 'node:fs/promises';\nimport { dirname } from 'node:path';\n\nimport {logger} from './common.js';\n\n/**\n * Make empty file.\n *\n * @param path - file path\n *\n * @example\n * ```ts\n * await makeFile('./dir/file.txt');\n * ```\n */\nexport async function makeEmptyFile(path: string): Promise<void> {\n logger.logMethodArgs?.('makeEmptyFile', '...' + path.slice(-32));\n try {\n const pathExists = existsSync(path);\n if (!pathExists) {\n const dir = dirname(path);\n if (!existsSync(dir)) {\n await mkdir(dir, {recursive: true});\n }\n }\n await (await open(path, 'w')).close();\n }\n catch (err) {\n logger.error('makeEmptyFile', 'make_file_failed', {path}, err);\n throw new Error('make_file_failed', {cause: (err as Error).cause});\n }\n}\n"], "mappings": "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", "names": ["readFileSync_", "readFile_", "import_node_fs", "import_promises", "writeFileSync_", "writeFile_", "import_flat_string", "import_node_fs", "import_promises", "import_node_path", "import_node_path", "import_node_fs", "import_promises"] }