Change permissions of Vinyl files in Gulp build pipelines
npx @tessl/cli install tessl/npm-gulp-chmod@4.0.0gulp-chmod is a Gulp plugin that provides a fluent interface for changing file permissions of Vinyl files during the build process. It supports both octal number and object-based permission specifications, with separate modes for files and directories, making it ideal for build systems that need to set appropriate file permissions during file processing.
npm install --save-dev gulp-chmodimport chmod from "gulp-chmod";For CommonJS environments:
const chmod = require("gulp-chmod");import gulp from "gulp";
import chmod from "gulp-chmod";
// Set executable permissions using octal notation
export default () => (
gulp.src("src/scripts/*.sh")
.pipe(chmod(0o755))
.pipe(gulp.dest("dist"))
);
// Set permissions using object notation
export default () => (
gulp.src("src/app.js")
.pipe(chmod({
owner: {
read: true,
write: true,
execute: true
},
group: {
execute: true
},
others: {
execute: true
}
}))
.pipe(gulp.dest("dist"))
);Creates a Gulp transform stream that modifies file permissions.
/**
* Creates a Gulp plugin for changing file permissions
* @param {undefined|number|object} fileMode - Permissions for files (octal or permission object)
* @param {undefined|true|number|object} directoryMode - Permissions for directories (optional)
* @returns {Transform} Gulp transform stream
*/
function chmod(fileMode, directoryMode);Parameters:
fileMode: undefined | number | object
0o755) for numeric permissionsundefined to skip file permission changesdirectoryMode: undefined | true | number | object (optional)
fileMode but applied to directoriestrue to apply the same mode as fileModeundefined to skip directory permission changesReturns: Transform stream compatible with Gulp pipelines
Usage Examples:
import gulp from "gulp";
import chmod from "gulp-chmod";
// Octal permissions for files only
gulp.src("src/*.js")
.pipe(chmod(0o644))
.pipe(gulp.dest("dist"));
// Different permissions for files and directories
gulp.src("src/**/*")
.pipe(chmod(0o644, 0o755))
.pipe(gulp.dest("dist"));
// Use same permissions for files and directories
gulp.src("src/**/*")
.pipe(chmod(0o755, true))
.pipe(gulp.dest("dist"));
// Only set directory permissions, skip files
gulp.src("src/**/*")
.pipe(chmod(undefined, 0o755))
.pipe(gulp.dest("dist"));
// Object-based permissions
gulp.src("src/scripts/*.sh")
.pipe(chmod({
owner: { read: true, write: true, execute: true },
group: { read: true, execute: true },
others: { execute: true }
}))
.pipe(gulp.dest("dist"));
// Simplified object permissions (applies to all: owner, group, others)
gulp.src("src/readonly/*.txt")
.pipe(chmod({ read: true, write: false, execute: false }))
.pipe(gulp.dest("dist"));interface PermissionObject {
owner?: {
read?: boolean;
write?: boolean;
execute?: boolean;
};
group?: {
read?: boolean;
write?: boolean;
execute?: boolean;
};
others?: {
read?: boolean;
write?: boolean;
execute?: boolean;
};
}When all permission levels (owner, group, others) should have the same permissions:
interface SimplifiedPermissionObject {
read?: boolean;
write?: boolean;
execute?: boolean;
}// Make shell scripts executable
gulp.src("src/scripts/*.sh")
.pipe(chmod(0o755)) // rwxr-xr-x
.pipe(gulp.dest("dist"));// Make configuration files read-only
gulp.src("src/config/*.conf")
.pipe(chmod(0o444)) // r--r--r--
.pipe(gulp.dest("dist"));// Standard web file permissions
gulp.src("src/assets/**/*")
.pipe(chmod(0o644, 0o755)) // files: rw-r--r--, directories: rwxr-xr-x
.pipe(gulp.dest("dist"));import gulpFilter from "gulp-filter";
const scriptFilter = gulpFilter("**/*.sh", {restore: true});
export default () => (
gulp.src("src/**/*")
// Filter shell scripts
.pipe(scriptFilter)
// Make them executable
.pipe(chmod(0o755))
// Restore all files
.pipe(scriptFilter.restore)
.pipe(gulp.dest("dist"))
);The plugin throws TypeError for invalid parameter types:
undefined, number, or objectundefined, true, number, or object// These will throw TypeError
chmod("invalid"); // fileMode must be undefined/number/object
chmod(0o755, "invalid"); // directoryMode must be undefined/true/number/objectgulp-chmod integrates seamlessly with Gulp's streaming workflow and supports the supportsDirectories option, allowing it to process both files and directories in the stream.
The plugin automatically handles files with missing or incomplete stat objects:
process.umask()) as the base, then applies the specified permissionsimport gulp from "gulp";
import chmod from "gulp-chmod";
import rename from "gulp-rename";
// Example build pipeline with permission setting
export default () => (
gulp.src("src/**/*")
.pipe(rename({ suffix: ".processed" }))
.pipe(chmod(0o644, 0o755))
.pipe(gulp.dest("dist"))
);