@avanio/os-api-linux-utils
Advanced tools
+4
-1
| { | ||
| "name": "@avanio/os-api-linux-utils", | ||
| "version": "0.0.2", | ||
| "version": "0.0.3", | ||
| "description": "", | ||
@@ -12,2 +12,5 @@ "main": "./dist/index.js", | ||
| }, | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "mocha": { | ||
@@ -14,0 +17,0 @@ "exit": true, |
| # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster | ||
| ARG VARIANT=16-bullseye | ||
| FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} | ||
| # Install tslint, typescript. eslint is installed by javascript image | ||
| ARG NODE_MODULES="tslint-to-eslint-config typescript" | ||
| COPY library-scripts/meta.env /usr/local/etc/vscode-dev-containers | ||
| RUN su node -c "umask 0002 && npm install -g ${NODE_MODULES}" \ | ||
| && npm cache clean --force > /dev/null 2>&1 | ||
| # [Optional] Uncomment this section to install additional OS packages. | ||
| # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ | ||
| # && apt-get -y install --no-install-recommends <your-package-list-here> | ||
| # [Optional] Uncomment if you want to install an additional version of node using nvm | ||
| # ARG EXTRA_NODE_VERSION=10 | ||
| # RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" |
| // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: | ||
| // https://github.com/microsoft/vscode-dev-containers/tree/v0.241.1/containers/typescript-node | ||
| { | ||
| "name": "os-api-linux-utils", | ||
| "build": { | ||
| "dockerfile": "Dockerfile", | ||
| // Update 'VARIANT' to pick a Node version: 18, 16, 14. | ||
| // Append -bullseye or -buster to pin to an OS version. | ||
| // Use -bullseye variants on local on arm64/Apple Silicon. | ||
| "args": { | ||
| "VARIANT": "16-bullseye" | ||
| } | ||
| }, | ||
| // Configure tool-specific properties. | ||
| "customizations": { | ||
| // Configure properties specific to VS Code. | ||
| "vscode": { | ||
| // Add the IDs of extensions you want installed when the container is created. | ||
| "extensions": [ | ||
| "dbaeumer.vscode-eslint", | ||
| "esbenp.prettier-vscode" | ||
| ] | ||
| } | ||
| }, | ||
| // Use 'forwardPorts' to make a list of ports inside the container available locally. | ||
| // "forwardPorts": [], | ||
| // Use 'postCreateCommand' to run commands after the container is created. | ||
| // "postCreateCommand": "yarn install", | ||
| // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. | ||
| "remoteUser": "node" | ||
| } |
| # [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster | ||
| ARG VARIANT=16-bullseye | ||
| FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT} | ||
| # [Optional] Uncomment this section to install additional OS packages. | ||
| #RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ | ||
| # && apt-get -y install --no-install-recommends libnss-db | ||
| # [Optional] Uncomment if you want to install an additional version of node using nvm | ||
| # ARG EXTRA_NODE_VERSION=10 | ||
| # RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" | ||
| # [Optional] Uncomment if you want to install more global node packages | ||
| # RUN su node -c "npm install -g <your-package-list -here>" |
| { | ||
| "parser": "@typescript-eslint/parser", | ||
| "parserOptions": { | ||
| "ecmaVersion": 2020, | ||
| "sourceType": "module", | ||
| "project": "./tsconfig.test.json" | ||
| }, | ||
| "plugins": [ | ||
| "@typescript-eslint", | ||
| "prettier", | ||
| "sonarjs", | ||
| "deprecation" | ||
| ], | ||
| "extends": [ | ||
| "standard", | ||
| "eslint:recommended", | ||
| "plugin:@typescript-eslint/eslint-recommended", | ||
| "plugin:@typescript-eslint/recommended", | ||
| "plugin:prettier/recommended", | ||
| "plugin:sonarjs/recommended" | ||
| ], | ||
| "rules": { | ||
| "camelcase": 1, | ||
| "@typescript-eslint/no-this-alias": [ | ||
| "warn", | ||
| { | ||
| "allowedNames": [ | ||
| "self" | ||
| ] | ||
| } | ||
| ], | ||
| "sort-imports": ["warn", { "ignoreCase": true }], | ||
| "sort-keys": [ | ||
| "warn", | ||
| "asc", | ||
| { | ||
| "caseSensitive": false, | ||
| "natural": true, | ||
| "minKeys": 4 | ||
| } | ||
| ], | ||
| "no-unused-vars": "off", | ||
| "@typescript-eslint/no-unused-vars": [ | ||
| "warn", // or "error" | ||
| { | ||
| "argsIgnorePattern": "^_", | ||
| "varsIgnorePattern": "^_", | ||
| "caughtErrorsIgnorePattern": "^_" | ||
| } | ||
| ], | ||
| "deprecation/deprecation": "warn", | ||
| "lines-between-class-members": "off", | ||
| "@typescript-eslint/lines-between-class-members": [ | ||
| "warn", | ||
| "always", | ||
| { | ||
| "exceptAfterOverload": true, | ||
| "exceptAfterSingleLine": true | ||
| } | ||
| ] | ||
| } | ||
| } |
| # Node project setup | ||
| * text=auto | ||
| *.ps1 text eol=crlf | ||
| *.js text eol=lf | ||
| *.ts text eol=lf | ||
| *.html text eol=lf | ||
| *.jsx text eol=lf | ||
| *.json text eol=lf | ||
| *.scss text eol=lf | ||
| *.svg text eol=lf | ||
| *.sh text eol=lf | ||
| *.md text eol=lf | ||
| *.yml text eol=lf | ||
| .gitignore text eol=lf | ||
| .firebaserc text eol=lf | ||
| Dockerfile text eol=lf | ||
| # binary | ||
| *.jpg binary | ||
| *.png binary | ||
| *.ico binary |
| { | ||
| "useTabs": true, | ||
| "singleQuote": true, | ||
| "bracketSpacing": false, | ||
| "arrowParens": "always", | ||
| "semi": true, | ||
| "trailingComma": "all", | ||
| "printWidth": 160 | ||
| } |
-83
| import * as fsPromise from 'fs/promises'; | ||
| import {ILinuxSudoOptions, sudoDeleteFile, sudoDeleteFilePromise, sudoReadFile, sudoReadFilePromise, sudoWriteFile, sudoWriteFilePromise} from './sudo'; | ||
| import {readFileSync, unlinkSync, writeFileSync} from 'fs'; | ||
| export * from './sudo'; | ||
| /** | ||
| * Write a file to disk, optionally using sudo | ||
| * @param {string} fileName - The file to write | ||
| * @param {Buffer} content - The content to write | ||
| * @param {ILinuxSudoOptions} options - Options for sudo | ||
| */ | ||
| export function writeFile(fileName: string, content: Buffer, options: ILinuxSudoOptions = {sudo: false}): void { | ||
| if (options.sudo) { | ||
| return sudoWriteFile(fileName, content, options); | ||
| } | ||
| return writeFileSync(fileName, content); | ||
| } | ||
| /** | ||
| * Read a file from disk, optionally using sudo | ||
| * @param {string} fileName - The file to read | ||
| * @param {ILinuxSudoOptions} options - Options for sudo | ||
| * @returns {Buffer} - The file contents | ||
| */ | ||
| export function readFile(fileName: string, options: ILinuxSudoOptions = {sudo: false}): Buffer { | ||
| if (options.sudo) { | ||
| return sudoReadFile(fileName, options); | ||
| } | ||
| return readFileSync(fileName); | ||
| } | ||
| /** | ||
| * Delete a file from disk, optionally using sudo | ||
| * @param {string} fileName - The file to delete | ||
| * @param {ILinuxSudoOptions} options - Options for sudo | ||
| */ | ||
| export function deleteFile(fileName: string, options: ILinuxSudoOptions = {sudo: false}): void { | ||
| if (options.sudo) { | ||
| return sudoDeleteFile(fileName, options); | ||
| } | ||
| return unlinkSync(fileName); | ||
| } | ||
| /** | ||
| * Async write a file to disk, optionally using sudo | ||
| * @param {string} fileName - The file to write | ||
| * @param {Buffer} content - The content to write | ||
| * @param {ILinuxSudoOptions} options - Options for sudo | ||
| * @returns {Promise<void>} - Promise of write | ||
| */ | ||
| export async function writeFilePromise(fileName: string, content: Buffer, options: ILinuxSudoOptions = {sudo: false}): Promise<void> { | ||
| if (options.sudo) { | ||
| return sudoWriteFilePromise(fileName, content, options); | ||
| } | ||
| return fsPromise.writeFile(fileName, content); | ||
| } | ||
| /** | ||
| * Async read a file from disk, optionally using sudo | ||
| * @param {string} fileName - The file to read | ||
| * @param {ILinuxSudoOptions} options - Options for sudo | ||
| * @returns {Promise<Buffer>} - Promise of the file content | ||
| */ | ||
| export function readFilePromise(fileName: string, options: ILinuxSudoOptions = {sudo: false}): Promise<Buffer> { | ||
| if (options.sudo) { | ||
| return sudoReadFilePromise(fileName, options); | ||
| } | ||
| return fsPromise.readFile(fileName); | ||
| } | ||
| /** | ||
| * Async delete a file from disk, optionally using sudo | ||
| * @param {string} fileName - The file to delete | ||
| * @param {ILinuxSudoOptions} options - Options for sudo | ||
| * @returns {Promise<void>} - Promise of delete | ||
| */ | ||
| export async function deleteFilePromise(fileName: string, options: ILinuxSudoOptions = {sudo: false}): Promise<void> { | ||
| if (options.sudo) { | ||
| return sudoDeleteFilePromise(fileName, options); | ||
| } | ||
| return fsPromise.unlink(fileName); | ||
| } |
-95
| import {execFile, execFileSync} from 'child_process'; | ||
| import {ILoggerLike} from '@avanio/logger-like'; | ||
| let sudoFileLogger: ILoggerLike | undefined; | ||
| export function setSudoFileLogger(logger: ILoggerLike) { | ||
| sudoFileLogger = logger; | ||
| } | ||
| function execFilePromise(cmd: string, args: string[], input?: Buffer): Promise<Buffer> { | ||
| return new Promise((resolve, reject) => { | ||
| const child = execFile(cmd, args, (error, stdout) => { | ||
| if (error) { | ||
| reject(error); | ||
| } else { | ||
| resolve(Buffer.from(stdout)); | ||
| } | ||
| }); | ||
| if (input) { | ||
| child.stdin?.write(input); | ||
| } | ||
| child.stdin?.end(); | ||
| }); | ||
| } | ||
| export interface ILinuxSudoOptions { | ||
| sudo?: boolean; | ||
| sudoUser?: string; | ||
| sudoPath?: string; | ||
| } | ||
| function sudoArgs(args: string[], options: ILinuxSudoOptions) { | ||
| if (process.platform === 'win32') { | ||
| throw new Error('sudo not supported on Windows'); | ||
| } | ||
| const sudoPath = options.sudoPath || '/usr/bin/sudo'; | ||
| if (options.sudoUser) { | ||
| return [sudoPath, '-n', '-U', options.sudoUser, ...args]; | ||
| } | ||
| return [sudoPath, '-n', ...args]; | ||
| } | ||
| /** | ||
| * Write file with sudo and tee | ||
| */ | ||
| export function sudoWriteFile(fileName: string, content: Buffer, options: ILinuxSudoOptions) { | ||
| const [cmd, ...args] = sudoArgs(['tee', fileName], options); | ||
| sudoFileLogger?.debug('sudoWriteFile:', cmd, args); | ||
| execFileSync(cmd, args, {input: content}); | ||
| } | ||
| /** | ||
| * Read file with sudo and cat | ||
| */ | ||
| export function sudoReadFile(fileName: string, options: ILinuxSudoOptions): Buffer { | ||
| const [cmd, ...args] = sudoArgs(['cat', fileName], options); | ||
| sudoFileLogger?.debug('sudoReadFile:', cmd, args); | ||
| return execFileSync(cmd, args); | ||
| } | ||
| /** | ||
| * Delete file with sudo and rm | ||
| */ | ||
| export function sudoDeleteFile(fileName: string, options: ILinuxSudoOptions): void { | ||
| const [cmd, ...args] = sudoArgs(['rm', '-f', fileName], options); | ||
| sudoFileLogger?.debug('sudoDeleteFile:', cmd, args); | ||
| execFileSync(cmd, args); | ||
| } | ||
| /** | ||
| * Async write file with sudo and tee | ||
| */ | ||
| export async function sudoWriteFilePromise(fileName: string, content: Buffer, options: ILinuxSudoOptions): Promise<void> { | ||
| const [cmd, ...args] = sudoArgs(['tee', fileName], options); | ||
| sudoFileLogger?.debug('sudoWriteFilePromise:', cmd, args); | ||
| await execFilePromise(cmd, args, content); | ||
| } | ||
| /** | ||
| * Async read file with sudo and cat | ||
| */ | ||
| export function sudoReadFilePromise(fileName: string, options: ILinuxSudoOptions): Promise<Buffer> { | ||
| const [cmd, ...args] = sudoArgs(['cat', fileName], options); | ||
| sudoFileLogger?.debug('sudoReadFilePromise:', cmd, args); | ||
| return execFilePromise(cmd, args); | ||
| } | ||
| /** | ||
| * Async delete file with sudo and rm | ||
| */ | ||
| export async function sudoDeleteFilePromise(fileName: string, options: ILinuxSudoOptions): Promise<void> { | ||
| const [cmd, ...args] = sudoArgs(['rm', '-f', fileName], options); | ||
| sudoFileLogger?.debug('sudoDeleteFilePromise:', cmd, args); | ||
| await execFilePromise(cmd, args); | ||
| } |
| /* eslint-disable sonarjs/no-duplicate-string */ | ||
| /* eslint-disable import/first */ | ||
| process.env.NODE_ENV = 'test'; | ||
| import 'mocha'; | ||
| import * as chai from 'chai'; | ||
| import * as fs from 'fs'; | ||
| import {deleteFile, deleteFilePromise, readFile, readFilePromise, writeFile, writeFilePromise} from '../src'; | ||
| const expect = chai.expect; | ||
| describe('linux utils', () => { | ||
| describe('sync', () => { | ||
| it('should write text file', async () => { | ||
| writeFile('./test.txt', Buffer.from('demo'), {sudo: true}); | ||
| expect(fs.existsSync('./test.txt')).to.be.eq(true); | ||
| }); | ||
| it('should read text file', async () => { | ||
| expect(readFile('./test.txt', {sudo: true}).toString()).to.be.eq('demo'); | ||
| }); | ||
| it('should delete text file', async () => { | ||
| deleteFile('./test.txt', {sudo: true}); | ||
| expect(fs.existsSync('./test.txt')).to.be.eq(false); | ||
| }); | ||
| }); | ||
| describe('async', () => { | ||
| it('should write text file', async () => { | ||
| await writeFilePromise('./test.txt', Buffer.from('demo'), {sudo: true}); | ||
| expect(fs.existsSync('./test.txt')).to.be.eq(true); | ||
| }); | ||
| it('should read text file', async () => { | ||
| expect((await readFilePromise('./test.txt', {sudo: true})).toString()).to.be.eq('demo'); | ||
| }); | ||
| it('should delete text file', async () => { | ||
| await deleteFilePromise('./test.txt', {sudo: true}); | ||
| expect(fs.existsSync('./test.txt')).to.be.eq(false); | ||
| }); | ||
| }); | ||
| }); |
| { | ||
| "compilerOptions": { | ||
| "module": "commonjs", | ||
| "target": "es2019", | ||
| "lib": [ | ||
| "es2020", | ||
| "DOM", | ||
| ], | ||
| "rootDir": "./src", | ||
| "outDir": "./", | ||
| "moduleResolution": "node", | ||
| "sourceRoot": "./src", | ||
| "types": [ | ||
| "node" | ||
| ], | ||
| "declaration": true, | ||
| "removeComments": false, | ||
| "inlineSources": true, | ||
| "inlineSourceMap": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "noImplicitReturns": true, | ||
| "noImplicitThis": true, | ||
| "noImplicitAny": true, | ||
| "importHelpers": true, | ||
| "strictNullChecks": true, | ||
| "noUnusedLocals": true, | ||
| }, | ||
| "include": [ | ||
| "./src/**/*" | ||
| ], | ||
| "exclude": [ | ||
| "/*.js", | ||
| "/*.d.ts", | ||
| "node_modules/*" | ||
| ] | ||
| } |
| { | ||
| "extends": "./tsconfig.json", | ||
| "compilerOptions": { | ||
| "module": "commonjs" | ||
| }, | ||
| "importHelpers": false, | ||
| "include": [ | ||
| "./src/**/*", | ||
| "./test/**/*" | ||
| ], | ||
| } |
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 2 instances in 1 package
1
-80%2112
-86.09%2
-84.62%0
-100%2
100%