UNPKG

mktemp

Version:

create temporary files and directories

1 lines 11.4 kB
{"version":3,"file":"creation.cjs","names":["generateUniqueName","getOutcomeCount","fs"],"sources":["../src/creation.ts"],"sourcesContent":["import fs from 'node:fs';\n\nimport { generateUniqueName, getOutcomeCount } from './unique_name';\n\n/* -----------------------------------------------------------------------------\n * private\n * -------------------------------------------------------------------------- */\n\ntype Callback = (\n err: NodeJS.ErrnoException | null,\n path: string | null\n) => void;\n\ntype TryCreateParams = {\n callback: Callback;\n isDir: boolean;\n mode: fs.Mode;\n retryCount: number;\n template: string;\n};\n\n/** permission of 0600 -r-------- */\nconst _r________ = 384; /* =0o600 */\n/** permission of 0700 -rw------- */\nconst _rw_______ = 448; /* =0o700 */\n\n/**\n * getOutcomeCount(\"X\") * 1 → 1 - (35/36)^(36*1) = 0.63728996689\n * ≈ 63%\n * 63% chance of success, 37% chance of failure\n *\n * getOutcomeCount(\"X\") * 3 → 1 - (35/36)^(36*3) = 0.9522823874\n * ≈ 95%\n * 95% chance of success, 5% chance of failure\n */\nconst RETRY_MULTIPLIER = 3;\n\n/**\n * check mode is fs.Mode\n *\n * @param mode - target value\n * @returns true if mode is fs.Mode\n */\nfunction isMode(mode: unknown): mode is fs.Mode {\n return typeof mode === 'number' || typeof mode === 'string';\n}\n\n/**\n * check error is NodeJS.ErrnoException\n *\n * @param error - target value\n * @returns true if error is NodeJS.ErrnoException\n */\nfunction isErrnoException(error: unknown): error is NodeJS.ErrnoException {\n if (typeof error === 'object' && error !== null) {\n return 'code' in (error as NodeJS.ErrnoException);\n }\n\n return false;\n}\n\n/**\n * try create unique name file or directory\n */\nfunction tryCreate({\n callback,\n isDir,\n mode,\n retryCount,\n template\n}: TryCreateParams) {\n const path = generateUniqueName(template);\n\n const fn = (err: NodeJS.ErrnoException | null, fd?: number): void => {\n if (err) {\n if (err.code === 'EEXIST') {\n // NOTE: EEXIST error\n if (retryCount > 0) {\n setImmediate(tryCreate, {\n callback,\n isDir,\n mode,\n retryCount: retryCount - 1,\n template\n });\n } else {\n callback(new RangeError('over max retry count'), null);\n }\n } else {\n // NOTE: other errors\n callback(err, null);\n }\n\n return;\n }\n\n if (fd) {\n fs.close(fd, (err) => {\n callback(err, path);\n });\n } else {\n callback(null, path);\n }\n };\n\n if (isDir) {\n fs.mkdir(path, mode, fn);\n } else {\n fs.open(path, 'ax+', mode, fn);\n }\n}\n\n/* -----------------------------------------------------------------------------\n * public / createFile\n * -------------------------------------------------------------------------- */\n\n/**\n * create unique name file\n *\n * @param template - template string for filename\n * @returns result with Promise\n */\nexport function createFile(template: string): Promise<string | null>;\n/**\n * create unique name file\n *\n * @param template - template string for filename\n * @param mode - permission\n * @returns result with Promise\n */\nexport function createFile(\n template: string,\n mode: fs.Mode\n): Promise<string | null>;\n/**\n * create unique name file\n *\n * @param template - template string for filename\n * @param callback - callback function\n */\nexport function createFile(template: string, callback: Callback): void;\n/**\n * create unique name file\n *\n * @param template - template string for filename\n * @param mode - permission\n * @param callback - callback function\n */\nexport function createFile(\n template: string,\n mode: fs.Mode,\n callback: Callback\n): void;\n\nexport function createFile(\n template: string,\n mode: fs.Mode | Callback = _r________,\n callback?: Callback\n): void | Promise<string | null> {\n if (typeof mode === 'function') {\n callback = mode;\n mode = _r________;\n }\n\n // NOTE: if don't pass mode argument, mode is initialize to _r________\n\n if (typeof callback !== 'function') {\n return new Promise((resolve, reject) => {\n // NOTE: maybe unreachable to else statement, this code is for the tsc\n if (isMode(mode)) {\n createFile(template, mode, (err, path) => {\n if (err) {\n reject(err);\n } else {\n resolve(path);\n }\n });\n } else {\n reject(new TypeError(`mode must be a fs.Mode: ${mode}`));\n }\n });\n }\n\n tryCreate({\n callback,\n isDir: false,\n mode,\n retryCount: getOutcomeCount(template) * RETRY_MULTIPLIER,\n template\n });\n}\n\n/**\n * create unique name file, sync version\n *\n * @param template - template string for filename\n * @returns unique filename\n */\nexport function createFileSync(template: string): string;\n/**\n * create unique name file, sync version\n *\n * @param template - template string for filename\n * @param mode - permission\n * @returns unique filename\n */\nexport function createFileSync(template: string, mode: fs.Mode): string;\n\nexport function createFileSync(\n template: string,\n mode: fs.Mode = _r________\n): string {\n let path: string;\n let isExist: boolean;\n\n let retryCount = getOutcomeCount(template);\n\n do {\n isExist = false;\n path = generateUniqueName(template);\n\n let fd: number | null = null;\n\n try {\n fd = fs.openSync(path, 'ax+', mode);\n } catch (err) {\n if (isErrnoException(err) && err.code === 'EEXIST') {\n if (retryCount > 0) {\n isExist = true;\n } else {\n throw new RangeError('over max retry count');\n }\n } else {\n throw err;\n }\n } finally {\n if (fd !== null) {\n fs.closeSync(fd);\n }\n }\n\n retryCount -= 1;\n } while (isExist);\n\n return path;\n}\n\n/* -----------------------------------------------------------------------------\n * public / createDir\n * -------------------------------------------------------------------------- */\n\n/**\n * create unique name directory\n *\n * @param template - template string for dirname\n * @returns result with Promise\n */\nexport function createDir(template: string): Promise<string | null>;\n/**\n * create unique name directory\n *\n * @param template - template string for dirname\n * @param mode - permission\n * @returns result with Promise\n */\nexport function createDir(\n template: string,\n mode: fs.Mode\n): Promise<string | null>;\n/**\n * create unique name directory\n *\n * @param template - template string for dirname\n * @param callback - callback function\n */\nexport function createDir(template: string, callback: Callback): void;\n/**\n * create unique name directory\n *\n * @param template - template string for dirname\n * @param mode - permission\n * @param callback - callback function\n */\nexport function createDir(\n template: string,\n mode: fs.Mode,\n callback: Callback\n): void;\n\nexport function createDir(\n template: string,\n mode: fs.Mode | Callback = _rw_______,\n callback?: Callback\n): void | Promise<string | null> {\n if (typeof mode === 'function') {\n callback = mode;\n mode = _rw_______;\n }\n\n // NOTE: if don't pass mode argument, mode is initialize to _rw_______\n\n if (typeof callback !== 'function') {\n return new Promise((resolve, reject) => {\n // NOTE: maybe unreachable to else statement, this code is for the tsc\n if (isMode(mode)) {\n createDir(template, mode, (err, path) => {\n if (err) {\n reject(err);\n } else {\n resolve(path);\n }\n });\n } else {\n reject(new TypeError(`mode must be a fs.Mode: ${mode}`));\n }\n });\n }\n\n tryCreate({\n callback,\n isDir: true,\n mode,\n retryCount: getOutcomeCount(template) * RETRY_MULTIPLIER,\n template\n });\n}\n\n/**\n * create unique name directory, sync version\n *\n * @param template - template string for dirname\n * @returns unique filename\n */\nexport function createDirSync(template: string): string;\n/**\n * create unique name directory, sync version\n *\n * @param template - template string for dirname\n * @returns unique filename\n */\nexport function createDirSync(template: string, mode: fs.Mode): string;\n\nexport function createDirSync(\n template: string,\n mode: fs.Mode = _rw_______\n): string {\n let path: string;\n let isExist: boolean;\n\n let retryCount = getOutcomeCount(template);\n\n do {\n isExist = false;\n path = generateUniqueName(template);\n\n try {\n fs.mkdirSync(path, mode);\n } catch (err) {\n if (isErrnoException(err) && err.code === 'EEXIST') {\n if (retryCount > 0) {\n isExist = true;\n } else {\n throw new RangeError('over max retry count');\n }\n } else {\n throw err;\n }\n }\n\n retryCount -= 1;\n } while (isExist);\n\n return path;\n}\n"],"mappings":"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"}