Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@drovp/save-as-path

Package Overview
Dependencies
Maintainers
2
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@drovp/save-as-path

Drovp utility to determine path for file results.

  • 1.1.2
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
1
decreased by-50%
Maintainers
2
Weekly downloads
 
Created
Source

@drovp/save-as-path

Drovp utility to determine destination path for file results. Also comes with option schema to easily plugin into your processor's profile options.

Features

Destination path template option with a lot of available replacement tokens, such as all of the file path parts like <basename>, <filename>, <extension>, ... as well as common platform directory paths like <downloads>, <documents>, <pictures>, ...

Separate options to Delete original file and Overwrite destination (only or even if it's a different file than original), so that the saving destination is generated exactly to user's needs.

Configurable filename incrementation style for when the desired destination already exists, but the user configuration says it can't be overwritten.

Install

npm install @drovp/save-as-path

Usage

In main file, make and add options to your processor:

// index.js
const {makeOptionSchema} = require('@drovp/save-as-path');

module.exports = (plugin) => {
	plugin.registerProcessor('name', {
		// ...
		options: [
			makeOptionSchema(),
			// ... other options
		],
	});
};

This will add saving namespace option item to your profile options.

Then in processor, we pass this to the saveAsPath() util:

// processor.js
const {saveAsPath} = require('@drovp/save-as-path');
const {promises: FSP} = require('fs');

module.exports = async (payload) => {
	const {item, options} = payload;
	const destinationExtension = 'jpg';
	const destinationPath = await saveAsPath(item.path, destinationExtension, options.saving);
	const tmpPath = `${destinationPath}.tmp${Math.random().toString().slice(-6)}`;

	// Do your stuff, and save the file into `tmpPath`
	// ...
	await FSP.writeFile(tmpPath, contents);

	// Comply with `deleteOriginal` request to get rid of the input file
	if (options.saving.deleteOriginal) {
		await FSP.rm(item.path);
	}

	// Rename `tmpPath` to `destinationPath` (see IMPORTANT! below)
	await FSP.rename(tmpPath, destinationPath);
};

IMPORTANT!

Depending on input options, saveAsPath() can generate the same file path as the original file, which might cause issues during processing, saving, or deleting when not accounted for. The best practice is to:

  1. Use saveAsPath() to get the destination path.
    const destinationPath = await saveAsPath(...params);
    
  2. Make a temporary path out of it:
    const tmpPath = `${destinationPath}.tmp${Math.random().toString().slice(-6)}`;
    
  3. Process and save the new file into tmpPath.
  4. If options.deleteOriginal is true, delete the original file.
  5. Finally, rename tmpPath to destinationPath.

TypeScript

In TypeScript, you can import Options type and extend your options with it:

import {PayloadData} from '@drovp/types';
import {Options as SaveAsOptions} from '@drovp/save-as-path';

type Options = SaveAsOptions & {
	myOther: string,
	options: boolean,
};

export type Payload = PayloadData<Options>;

// ... rest of the main file

API

All exported interfaces.

Options

Options data type the makeOptionSchema() will produce on your options object:

interface Options {
	saving: {
		destination: string;
		deleteOriginal: boolean;
		overwriteDestination: boolean;
		incrementer: 'space' | 'dash' | 'underscore' | 'parentheses';
	};
}

makeOptionSchema(options: MakeOptionSchemaOptions): OptionNamespace

A function to construct saving namespace option item schema. Example:

plugin.registerProcessor('foo', {
	options: [makeOptionsSchema(), /* other options */],
	// ...
});
options

Exported as MakeOptionSchemaOptions.

interface MakeOptionSchemaOptions {
	extraTokens?: Record<string, string>;
	tokenStart?: string;
	tokenEnd?: string;
}
extraTokens

An object map with extra token names and their descriptions if you are using any. They'll be listed in the destination template description so that users know these tokens are available.

Example:

makeOptionsSchema({
	// As used in @drovp/image-optimizer
	encoder: `name of the encoder used to compress the file`,
});
tokenStart & tokenEnd

Type: string Default: < & >

Token start and end terminating characters. If you're customizing these when calling saveAsPath(), pass them here as well so that it can be reflected in option descriptions as well.

saveAsPath(originalPath: string, newExtension: string, options: SaveAsPathOptions): Promise<string>

An async function that determines the final file destination. Example:

const destinationPath = await saveAsPath(payload.item.path, 'webp', payload.options.saving);
originalPath

Type: string required

Path to the original file to be processed.

newExtension

Type: string required

The extension the new file should have. Can be same as the original.

options

Type: SaveAsPathOptions required

interface SaveAsPathOptions {
	destination?: string;
	deleteOriginal?: boolean;
	overwriteDestination?: boolean;
	incrementer?: 'space' | 'dash' | 'underscore' | 'parentheses';
	tokenStart?: string;
	tokenEnd?: string;
	tokenChars?: string;
	tokenReplacer?: (name: string) => string | number | null | undefined | Promise<string | number | null | undefined>;
}

Options destination, deleteOriginal, overwriteDestination, and incrementer are provided by the saving option schema. The rest is for you to customize tokens, or add more of them with tokenReplacer.

destination

Type: string Default: '<basename>'

A desired destination template. Relative paths resolve from the original path's dirname.

Currently supports these tokens:

  • <tmp>, <home>, <downloads>, <documents>, <pictures>, <music>, <videos>, <desktop> - platform folders
  • <basename> - result file basename /foo/bar.jpgbar.jpg
  • <filename> - file name without the extension /foo/bar.jpgbar
  • <extname> - result file extension with the dot /foo/bar.jpg.jpg
  • <ext> - result file extension without the dot /foo/bar.jpgjpg
  • <dirname> - directory path /foo/bar/baz.jpg/foo/bar
  • <dirbasename> - name of a parent directory /foo/bar/baz.jpgbar
  • <srcBasename> - original file basename /foo/bar.jpgbar.jpg
  • <srcExtname> - original file extension with the dot /foo/bar.jpg.jpg
  • <srcExt> - original file extension without the dot /foo/bar.jpgjpg

You can add more tokens with tokenReplacer option below.

deleteOriginal

Type: boolean Default: false

Wether to delete the original file. The saveAsPath() DOESN'T delete any files, it will only generate a result file path that will comply with this requirement.

You have to delete the original file manually yourself after you've processed and saved the new file. See the IMPORTANT! note in the Usage section above.

overwriteDestination

Type: boolean Default: false

Specifies wether the new path is allowed to overwrite existing files.

When enabled, it'll ignore if any file exists on the requested destination, UNLESS the deleteOriginal options is disabled, then it'll ensuring the original is not deleted.

When disabled, filename will be incremented until there's no conflict, UNLESS the deleteOriginal options is enabled and the desired result path matches the original, in which case the result path will not be increment, and will allow the original to be overwritten.

incrementer

Type: 'space' | 'dash' | 'underscore' | 'parentheses' Default: space

Filename incrementation style. When there is already a file on requested destination path, and the configuration states it shouldn't be overwritten, saveAsPath() will increment the file name until it satisfies the configuration requirements.

Styles:

  • space: file.jpg -> file 1.jpg
  • dash: file.jpg -> file-1.jpg
  • underscore: file.jpg -> file_1.jpg
  • parentheses: file.jpg -> file (1).jpg
tokenStart & tokenEnd

Type: string Default: < & >

Token start and end terminating characters.

You can also just disable the tokenEnd by passing an empty string, and set the tokenStart to : to have tokens such as :name, but that is prone to conflicts.

tokenChars

Type: string Default: [a-zA-Z0-9]+

A regexp string that should match token name.

tokenReplacer

Type: (name: string) => string | number | null | undefined | Promise<string | number | null | undefined>

Allows providing your own custom destination template tokens. Accepts a token name (without the <> characters), and should return a string or a number.

Returning null | undefined is recognized as non-existent token, and results in an Unknown token operation error.

Can be async.

Example:

const destinationPath = await saveAsPath(item.path, 'jpg', {
	...options.saving,
	tokenReplacer: (name) => {
		if (name === 'myCustomToken') return 'token value';
	},
});

Keywords

FAQs

Package last updated on 07 Sep 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc