Socket
Socket
Sign inDemoInstall

unused-filename

Package Overview
Dependencies
2
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.1.0 to 3.0.0

139

index.d.ts

@@ -0,9 +1,127 @@

/* eslint-disable no-redeclare */
declare namespace unusedFilename {
interface Options {
/**
Custom function to increment a filename.
Default: Parentheses incrementer: `file.txt` → `file (1).txt`
*/
readonly incrementer?: Incrementer;
/**
The max number of attempts to find an unused filename.
When the limit is reached, the function will throw `unusedFilename.MaxTryError`.
@default Infinity
*/
readonly maxTries?: number;
}
/**
A function that accepts a file path, and increments its index. It's the incrementer's responsibility to extract an already existing index from the given file path so that it picks up and continues incrementing an already present index instead of appending a second one.
The incrementer has to return a tuple of `[originalFilename, incrementedFilename]`, where `originalFilename` is the filename without the index, and `incrementedFilename` is a filename with input's index bumped by one.
@param filename - The filename of the file path.
@param extension - The extension of the file path.
@returns A tuple of original filename, and new incremented filename, including extension.
@example
```
// Example incrementer that inserts a new index as a prefix.
import unusedFilename = require('unused-filename');
(async () => {
const filename = await unusedFilename('rainbow.txt', {
incrementer(filename, extension) => {
const match = filename.match(/^(?<index>\d+)_(?<originalFilename>.*)$/);
let {originalFilename, index} = match ? match.groups : {originalFilename: filename, index: 0};
let originalFilename = originalFilename.trim();
return [`${originalFilename}${extension}`, `${++index}_${originalFilename}${extension}`;
}
});
console.log(filename);
//=> '1_rainbow.txt'
})();
```
*/
type Incrementer = (filename: string, extension: string) => string;
/**
The error thrown when `maxTries` limit is reached without finding an unused filename.
@param originalPath - Path without the incrementation sequence.
@param lastTriedPath - The last tested incremented path.
@example
```
import unusedFilename = require('unused-filename');
const {MaxTryError} = unusedFilename;
try {
const path = await unusedFilename('rainbow (1).txt', {maxTries: 0});
} catch (error) {
if (error instanceof MaxTryError) {
console.log(error.originalPath); // 'rainbow.txt'
console.log(error.lastTriedPath); // 'rainbow (1).txt'
}
}
```
*/
interface MaxTryError extends Error {
originalPath: string;
lastTriedPath: string;
}
}
declare const unusedFilename: {
/**
Creates an incrementer that appends a number after a separator.
`separatorIncrementer('_')` will increment `file.txt` → `file_1.txt`.
Not all characters can be used as separators:
- On Unix-like systems, `/` is reserved.
- On Windows, `<>:"/|?*` along with trailing periods are reserved.
@example
```
import unusedFilename = require('unused-filename');
console.log(await unusedFilename('rainbow.txt', {incrementer: unusedFilename.separatorIncrementer('_')}));
//=> 'rainbow_1.txt'
```
*/
separatorIncrementer: (separator: string) => unusedFilename.Incrementer;
MaxTryError: unusedFilename.MaxTryError;
// TODO: Remove this for the next major release
default: typeof unusedFilename;
/**
Get an unused filename by appending a number if it exists: `file.txt` → `file (1).txt`.
@param filePath - The path to check for filename collision.
@returns Either the original `filename` or the `filename` appended with a number.
@returns Either the original `filename` or the `filename` appended with a number (or modified by `option.incrementer` if specified).
If an already incremented `filePath` is passed, `unusedFilename` will simply increment and replace the already existing index:
@example
```
import unusedFilename = require('unused-filename');
(async () => {
console.log(await unusedFilename('rainbow (1).txt'));
//=> 'rainbow (2).txt'
})();
```
*/
(filePath: string): Promise<string>;
(filePath: string, options?: unusedFilename.Options): Promise<string>;

@@ -14,10 +132,17 @@ /**

@param filePath - The path to check for filename collision.
@returns Either the original `filename` or the `filename` appended with a number.
@returns Either the original `filename` or the `filename` appended with a number (or modified by `option.incrementer` if specified).
If an already incremented `filePath` is passed, `unusedFilename` will simply increment and replace the already existing index:
@example
```
import unusedFilename = require('unused-filename');
console.log(unusedFilename.sync('rainbow (1).txt'));
//=> 'rainbow (2).txt'
```
*/
sync(filePath: string): string;
// TODO: Remove this for the next major release
default: typeof unusedFilename;
sync(filePath: string, options?: unusedFilename.Options): string;
};
export = unusedFilename;
'use strict';
const path = require('path');
const pathExists = require('path-exists');
const modifyFilename = require('modify-filename');
const escapeStringRegexp = require('escape-string-regexp');
const incrementer = filePath => {
let counter = 0;
return () => modifyFilename(filePath, (filename, extension) => `${filename} (${++counter})${extension}`);
class MaxTryError extends Error {
constructor(originalPath, lastTriedPath) {
super('Max tries reached.');
this.originalPath = originalPath;
this.lastTriedPath = lastTriedPath;
}
}
const parenthesesIncrementer = (inputFilename, extension) => {
const match = inputFilename.match(/^(?<filename>.*)\((?<index>\d+)\)$/);
let {filename, index} = match ? match.groups : {filename: inputFilename, index: 0};
filename = filename.trim();
return [`${filename}${extension}`, `${filename} (${++index})${extension}`];
};
const unusedFilename = filePath => {
const getFilePath = incrementer(filePath);
const find = async newFilePath => await pathExists(newFilePath) ? find(getFilePath()) : newFilePath;
return find(filePath);
const separatorIncrementer = separator => {
const escapedSeparator = escapeStringRegexp(separator);
return (inputFilename, extension) => {
const match = new RegExp(`^(?<filename>.*)${escapedSeparator}(?<index>\\d+)$`).exec(inputFilename);
let {filename, index} = match ? match.groups : {filename: inputFilename, index: 0};
return [`${filename}${extension}`, `${filename.trim()}_${++index}${extension}`];
};
};
const incrementPath = (filePath, incrementer) => {
const ext = path.extname(filePath);
const dirname = path.dirname(filePath);
const [originalFilename, incrementedFilename] = incrementer(path.basename(filePath, ext), ext);
return [path.join(dirname, originalFilename), path.join(dirname, incrementedFilename)];
};
const unusedFilename = async (filePath, {incrementer = parenthesesIncrementer, maxTries = Number.POSITIVE_INFINITY} = {}) => {
let tries = 0;
let [originalPath] = incrementPath(filePath, incrementer);
let unusedPath = filePath;
/* eslint-disable no-await-in-loop, no-constant-condition */
while (true) {
if (!(await pathExists(unusedPath))) {
return unusedPath;
}
if (++tries > maxTries) {
throw new MaxTryError(originalPath, unusedPath);
}
[originalPath, unusedPath] = incrementPath(unusedPath, incrementer);
}
/* eslint-enable no-await-in-loop, no-constant-condition */
};
module.exports = unusedFilename;

@@ -20,6 +62,23 @@ // TODO: Remove this for the next major release

module.exports.sync = filePath => {
const getFilePath = incrementer(filePath);
const find = newFilePath => pathExists.sync(newFilePath) ? find(getFilePath()) : newFilePath;
return find(filePath);
module.exports.sync = (filePath, {incrementer = parenthesesIncrementer, maxTries = Number.POSITIVE_INFINITY} = {}) => {
let tries = 0;
let [originalPath] = incrementPath(filePath, incrementer);
let unusedPath = filePath;
/* eslint-disable no-constant-condition */
while (true) {
if (!pathExists.sync(unusedPath)) {
return unusedPath;
}
if (++tries > maxTries) {
throw new MaxTryError(originalPath, unusedPath);
}
[originalPath, unusedPath] = incrementPath(unusedPath, incrementer);
}
/* eslint-enable no-constant-condition */
};
module.exports.MaxTryError = MaxTryError;
module.exports.separatorIncrementer = separatorIncrementer;

15

package.json
{
"name": "unused-filename",
"version": "2.1.0",
"version": "3.0.0",
"description": "Get an unused filename by appending a number if it exists: `file.txt` → `file (1).txt`",
"license": "MIT",
"repository": "sindresorhus/unused-filename",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=8"
"node": ">=12"
},

@@ -38,10 +39,10 @@ "scripts": {

"dependencies": {
"modify-filename": "^1.1.0",
"escape-string-regexp": "^4.0.0",
"path-exists": "^4.0.0"
},
"devDependencies": {
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
"ava": "^2.4.0",
"tsd": "^0.15.0",
"xo": "^0.39.0"
}
}

@@ -1,2 +0,2 @@

# unused-filename [![Build Status](https://travis-ci.org/sindresorhus/unused-filename.svg?branch=master)](https://travis-ci.org/sindresorhus/unused-filename)
# unused-filename

@@ -7,3 +7,2 @@ > Get an unused filename by appending a number if it exists: `file.txt` → `file (1).txt`

## Install

@@ -15,3 +14,2 @@

## Usage

@@ -35,13 +33,23 @@

## API
### unusedFilename(filePath)
### unusedFilename(filePath, options?)
Returns a `Promise<string>` containing either the original `filename` or the `filename` appended with a number.
Returns a `Promise<string>` containing either the original `filename` or the `filename` increment by `options.incrementer`.
### unusedFilename.sync(filePath)
If an already incremented `filePath` is passed, `unusedFilename` will simply increment and replace the already existing index:
Returns a `string` containing either the original `filename` or the `filename` appended with a number.
```js
const unusedFilename = require('unused-filename');
(async () => {
console.log(await unusedFilename('rainbow (1).txt'));
//=> 'rainbow (2).txt'
})();
```
### unusedFilename.sync(filePath, options?)
Synchronous version of `unusedFilename`.
#### filePath

@@ -53,10 +61,85 @@

#### options
## Related
Type: `object`
- [filenamify](https://github.com/sindresorhus/filenamify) - Convert a string to a valid safe filename
##### incrementer
Type: `(filePath: string) => [string, string]`\
Default: Parentheses incrementer: `file.txt` → `file (1).txt`
## License
A function that accepts a file path, and increments its index. It's the incrementer's responsibility to extract an already existing index from the given file path so that it picks up and continues incrementing an already present index instead of appending a second one.
MIT © [Sindre Sorhus](https://sindresorhus.com)
The incrementer has to return a tuple of `[originalFilename, incrementedFilename]`, where `originalFilename` is the filename without the index, and `incrementedFilename` is a filename with input's index bumped by one.
Example incrementer that inserts a new index as a prefix:
```js
const unusedFilename = require('unused-filename');
const prefixIncrementer = (filename, extension) => {
const match = filename.match(/^(?<index>\d+)_(?<originalFilename>.*)$/);
let {originalFilename, index} = match ? match.groups : {originalFilename: filename, index: 0};
let originalFilename = originalFilename.trim();
return [`${originalFilename}${extension}`, `${++index}_${originalFilename}${extension}`;
};
console.log(await unusedFilename('rainbow.txt', {incrementer: prefixIncrementer}));
//=> '1_rainbow.txt'
```
##### maxTries
Type: `number`\
Default: `Infinity`
The max number of attempts to find an unused filename.
When the limit is reached, the function will throw `unusedFilename.MaxTryError`.
### unusedFilename.separatorIncrementer
Creates an incrementer that appends a number after a separator.
`separatorIncrementer('_')` will increment `file.txt` → `file_1.txt`.
Not all characters can be used as separators:
- On Unix-like systems, `/` is reserved.
- On Windows, `<>:"/|?*` along with trailing periods are reserved.
```js
const unusedFilename = require('unused-filename');
console.log(await unusedFilename('rainbow.txt', {incrementer: unusedFilename.separatorIncrementer('_')}));
//=> 'rainbow_1.txt'
```
### unusedFilename.MaxTryError
The error thrown when `maxTries` limit is reached without finding an unused filename.
It comes with 2 custom properties:
- `originalPath` - Path without incrementation sequence.
- `lastTriedPath` - The last tested incremented path.
Example:
```js
const unusedFilename = require('unused-filename');
const {MaxTryError} = unusedFilename;
try {
const path = await unusedFilename('rainbow (1).txt', {maxTries: 0});
} catch (error) {
if (error instanceof MaxTryError) {
console.log(error.originalPath); // 'rainbow.txt'
console.log(error.lastTriedPath); // 'rainbow (1).txt'
}
}
```
## Related
- [filenamify](https://github.com/sindresorhus/filenamify) - Convert a string to a valid safe filename

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc