{"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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"}