├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .npmrc ├── LICENSE ├── README.md ├── better-path-resolve ├── LICENSE ├── README.md ├── index.js ├── package.json └── test.js ├── can-link ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── can-write-to-dir ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── cmd-extension ├── LICENSE ├── README.md ├── index.d.ts ├── index.js └── package.json ├── comver-to-semver ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── dir-is-case-sensitive ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── src │ └── index.ts ├── test │ └── index.ts └── tsconfig.json ├── graceful-git ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example.js ├── index.js ├── package.json └── test.js ├── is-inner-link ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package.json └── test.js ├── is-subdir ├── LICENSE ├── README.md ├── example.js ├── index.d.ts ├── index.js ├── package.json └── test.js ├── make-empty-dir ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── p-map-values ├── .gitignore ├── LICENSE ├── README.md ├── __tests__ │ └── index.ts ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── package.json ├── path-absolute ├── LICENSE ├── README.md ├── index.d.ts ├── index.js └── package.json ├── path-temp ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── preferred-pm ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test │ ├── index.js │ ├── npm-workspace │ ├── package-lock.json │ ├── package.json │ └── packages │ │ └── pkg │ │ └── package.json │ ├── pnpm-workspace │ ├── packages │ │ └── pkg │ │ │ └── package.json │ └── pnpm-workspace.yaml │ ├── prefers-bun │ └── bun.lockb │ ├── prefers-nothing │ └── .gitkeep │ ├── prefers-npm-5 │ └── package-lock.json │ ├── prefers-npm │ ├── .gitignore │ └── node_modules │ │ └── .gitkeep │ ├── prefers-pnpm-1-or-2 │ └── shrinkwrap.yaml │ ├── prefers-pnpm │ └── pnpm-lock.yaml │ ├── prefers-yarn │ └── yarn.lock │ └── yarn-workspace │ ├── package.json │ └── packages │ └── pkg │ └── package.json ├── promise-share ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── read-ini-file ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example │ ├── currencies.ini │ └── index.js ├── index.d.ts ├── index.js ├── package.json └── test │ ├── fixture.ini │ └── index.js ├── read-json5-file ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example │ ├── countries.json5 │ └── index.js ├── index.d.ts ├── index.js ├── package.json └── test │ ├── fixture.json5 │ └── index.js ├── read-yaml-file ├── CHANGELOG.md ├── LICENSE ├── README.md ├── foo.yml ├── index.d.ts ├── index.js ├── package.json └── test.js ├── realpath-missing ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── rename-overwrite ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── render-help ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── __tests__ │ └── index.ts ├── example.js ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── renovate.json ├── resolve-link-target ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js ├── rimraf ├── CHANGELOG.md ├── LICENSE ├── README.md ├── __tests__ │ └── index.js ├── index.d.ts ├── index.js └── package.json ├── root-link-target ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example.js ├── index.d.ts ├── index.js ├── package.json └── test.js ├── run-groups ├── CHANGELOG.md ├── LICENSE ├── README.md ├── lib │ ├── index.d.ts │ ├── index.js │ └── index.js.map ├── package.json ├── src │ └── index.ts ├── test │ └── index.ts └── tsconfig.json ├── safe-execa ├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── safe-promise-defer ├── .gitignore ├── LICENSE ├── README.md ├── __tests__ │ └── index.ts ├── package.json ├── src │ └── index.ts └── tsconfig.json ├── which-pm-runs ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package.json └── test │ ├── fixtures │ ├── bun │ │ ├── index.js │ │ └── package.json │ ├── cnpm │ │ ├── index.js │ │ └── package.json │ ├── npm │ │ ├── index.js │ │ ├── package-lock.json │ │ └── package.json │ ├── pnpm │ │ ├── index.js │ │ ├── package.json │ │ ├── pnpm-lock.yaml │ │ └── pnpm-workspace.yaml │ └── yarn │ │ ├── .yarn │ │ └── install-state.gz │ │ ├── .yarnrc.yml │ │ ├── index.js │ │ ├── package.json │ │ └── yarn.lock │ └── index.js ├── which-pm ├── LICENSE ├── README.md ├── example.js ├── index.d.ts ├── index.js ├── package.json └── test │ ├── fixtures │ ├── .gitignore │ ├── bun │ │ ├── bun.lockb │ │ └── package.json │ ├── npm │ │ └── node_modules │ │ │ └── .gitkeep │ ├── pnpm │ │ └── node_modules │ │ │ └── .modules.yaml │ ├── scoped-pnpm │ │ └── node_modules │ │ │ └── .modules.yaml │ └── yarn │ │ └── node_modules │ │ └── .yarn-integrity │ └── index.js ├── write-ini-file ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json ├── renovate.json └── test.js ├── write-json5-file ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test.js └── write-yaml-file ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.d.ts ├── index.js └── package.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.0.3/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "restricted", 7 | "baseBranch": "main" 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | insert_final_newline = true 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | end_of_line = lf 8 | 9 | [*.{ts,js,json}] 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | strategy: 8 | fail-fast: false 9 | matrix: 10 | node: 11 | - '14' 12 | - '16' 13 | - '18' 14 | - '20' 15 | - '22' 16 | platform: 17 | - ubuntu-latest 18 | - windows-latest 19 | - macos-latest 20 | 21 | name: '${{matrix.platform}} / Node.js ${{ matrix.node }}' 22 | runs-on: ${{matrix.platform}} 23 | 24 | steps: 25 | - name: Checkout Commit 26 | uses: actions/checkout@v4 27 | - name: Setup Node 28 | uses: actions/setup-node@v4 29 | with: 30 | node-version: ${{ matrix.node }} 31 | - name: Install pnpm 32 | uses: pnpm/action-setup@v4.1.0 33 | with: 34 | standalone: true 35 | - name: pnpm install 36 | run: pnpm install 37 | - name: Compile 38 | run: pnpm -r run prepublishOnly 39 | - name: run tests 40 | run: pnpm -r --no-bail test 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Dependency directory 7 | node_modules 8 | bun.lockb 9 | 10 | # Coverage directory used by tools like istanbul 11 | coverage 12 | 13 | .tmp 14 | _docpress 15 | .DS_Store 16 | 17 | # Visual Studio Code configs 18 | .vscode/ 19 | 20 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | hoist = true 2 | link-workspace-packages = false 3 | save-exact = false 4 | strict-peer-dependencies = false 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zoltan Kochan's npm packages 2 | 3 | [![](https://img.shields.io/badge/developed%20by-pnpm-f98080)](https://pnpm.io) 4 | 5 | ## Development Setup 6 | 7 | 1. clone the repo 8 | 1. run `pnpm install` 9 | -------------------------------------------------------------------------------- /better-path-resolve/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /better-path-resolve/README.md: -------------------------------------------------------------------------------- 1 | # better-path-resolve 2 | 3 | > A better path.resolve() that normalizes paths on Windows 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/better-path-resolve.svg)](https://www.npmjs.com/package/better-path-resolve) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add better-path-resolve 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | 'use strict' 19 | const betterPathResolve = require('better-path-resolve') 20 | 21 | console.log(betterPathResolve('c:/src')) 22 | //> C:\src 23 | ``` 24 | 25 | ## License 26 | 27 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 28 | -------------------------------------------------------------------------------- /better-path-resolve/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const isWindows = require('is-windows') 4 | 5 | module.exports = isWindows() ? winResolve : path.resolve 6 | 7 | function winResolve (p) { 8 | if (arguments.length === 0) return path.resolve() 9 | if (typeof p !== 'string') { 10 | return path.resolve(p) 11 | } 12 | // c: => C: 13 | if (p[1] === ':') { 14 | const cc = p[0].charCodeAt() 15 | if (cc < 65 || cc > 90) { 16 | p = `${p[0].toUpperCase()}${p.substr(1)}` 17 | } 18 | } 19 | // On Windows path.resolve('C:') returns C:\Users\ 20 | // We resolve C: to C: 21 | if (p.endsWith(':')) { 22 | return p 23 | } 24 | return path.resolve(p) 25 | } 26 | -------------------------------------------------------------------------------- /better-path-resolve/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "better-path-resolve", 3 | "version": "1.0.0", 4 | "description": "A better path.resolve() that normalizes paths on Windows", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js" 8 | ], 9 | "scripts": { 10 | "test": "node test", 11 | "md": "mos" 12 | }, 13 | "engines": { 14 | "node": ">=4" 15 | }, 16 | "repository": "https://github.com/zkochan/packages/tree/main/better-path-resolve", 17 | "keywords": [], 18 | "author": { 19 | "name": "Zoltan Kochan", 20 | "url": "https://www.kochan.io" 21 | }, 22 | "mos": { 23 | "plugins": [ 24 | "readme" 25 | ], 26 | "installation": { 27 | "useShortAlias": true 28 | } 29 | }, 30 | "license": "MIT", 31 | "homepage": "https://github.com/zkochan/packages/tree/main/better-path-resolve#readme", 32 | "dependencies": { 33 | "is-windows": "^1.0.2" 34 | }, 35 | "devDependencies": { 36 | "mos": "2.0.0-alpha.3", 37 | "mos-plugin-readme": "^1.0.4", 38 | "tape": "^5.9.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /better-path-resolve/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const betterPathResolve = require('.') 4 | 5 | test('betterPathResolve()', (t) => { 6 | t.equal(typeof betterPathResolve(), 'string') 7 | t.end() 8 | }) 9 | -------------------------------------------------------------------------------- /can-link/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # can-link 2 | 3 | ## 2.0.0 4 | ### Major Changes 5 | 6 | - bba9985: Support of Node.js versions older than 10 is dropped. 7 | 8 | ### Minor Changes 9 | 10 | - bba9985: graceful-fs and mz removed from dependencies. 11 | -------------------------------------------------------------------------------- /can-link/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /can-link/README.md: -------------------------------------------------------------------------------- 1 | # can-link 2 | 3 | > Returns true if a link can be created 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/can-link.svg)](https://www.npmjs.com/package/can-link) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add can-link 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const canLink = require('can-link') 19 | 20 | canLink.sync('C:\\foo.txt', 'D:\\foo.txt') 21 | //> false 22 | 23 | canLink.sync('C:\\foo.txt', 'C:\\dir\\foo.txt') 24 | //> true 25 | ``` 26 | 27 | ## API 28 | 29 | ### `canLink.sync(existingPath, newPath): Boolean` 30 | 31 | Returns `true` if `fs.linkSync(existingPath, newPath)` is able to create a link. 32 | 33 | ### `canLink(existingPath, newPath): Promise` 34 | 35 | Returns `true` if `fs.link(existingPath, newPath)` is able to create a link. 36 | 37 | ## License 38 | 39 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 40 | -------------------------------------------------------------------------------- /can-link/index.d.ts: -------------------------------------------------------------------------------- 1 | export = canLink 2 | 3 | declare function canLink (existingPath: string, newPath: string): Promise 4 | 5 | declare namespace canLink { 6 | function sync (existingPath: string, newPath: string): boolean 7 | } 8 | -------------------------------------------------------------------------------- /can-link/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const defaultFS = require('fs') 3 | 4 | module.exports = async (existingPath, newPath, customFS) => { 5 | const fs = customFS || defaultFS 6 | try { 7 | await fs.promises.link(existingPath, newPath) 8 | fs.promises.unlink(newPath).catch(() => {}) 9 | return true 10 | } catch (err) { 11 | if ( 12 | err.code === 'EXDEV' || 13 | err.code === 'EACCES' || 14 | err.code === 'EPERM' 15 | ) { 16 | return false 17 | } 18 | throw err 19 | } 20 | } 21 | 22 | module.exports.sync = (existingPath, newPath, customFS) => { 23 | const fs = customFS || defaultFS 24 | try { 25 | fs.linkSync(existingPath, newPath) 26 | fs.unlinkSync(newPath) 27 | return true 28 | } catch (err) { 29 | if (err.code === 'EXDEV' || err.code === 'EACCES' || err.code === 'EPERM') { 30 | return false 31 | } 32 | throw err 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /can-link/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "can-link", 3 | "version": "2.0.0", 4 | "description": "Returns true if a link can be created", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && node test", 13 | "md": "mos" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/can-link", 16 | "keywords": [ 17 | "link", 18 | "hardlink" 19 | ], 20 | "engines": { 21 | "node": ">=10" 22 | }, 23 | "author": "Zoltan Kochan (https://www.kochan.io/)", 24 | "license": "MIT", 25 | "homepage": "https://github.com/zkochan/packages/tree/main/can-link#readme", 26 | "dependenciesMeta": { 27 | "can-link": { 28 | "injected": true 29 | } 30 | }, 31 | "devDependencies": { 32 | "can-link": "file:", 33 | "mos": "2.0.0-alpha.3", 34 | "mos-plugin-readme": "^1.0.4", 35 | "standard": "^16.0.4", 36 | "tape": "^5.9.0" 37 | }, 38 | "mos": { 39 | "plugins": [ 40 | "readme" 41 | ], 42 | "installation": { 43 | "useShortAlias": true 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /can-link/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const canLink = require('can-link') 4 | 5 | const exdevErr = new Error('EXDEV: cross-device link not permitted') 6 | exdevErr.code = 'EXDEV' 7 | 8 | const eaccesErr = new Error('EACCES: permission denied, link') 9 | eaccesErr.code = 'EACCES' 10 | 11 | const epermErr = new Error('EPERM: permission denied, link') 12 | epermErr.code = 'EPERM' 13 | 14 | test('canLink.sync()', t => { 15 | t.ok(canLink.sync('package.json', 'node_modules/package.json')) 16 | t.notOk(canLink.sync('foo', 'bar', { 17 | linkSync: () => { throw exdevErr }, 18 | unlinkSync: () => {} 19 | }), 'cannot link on EXDEV error') 20 | t.notOk(canLink.sync('foo', 'bar', { 21 | linkSync: () => { throw eaccesErr }, 22 | unlinkSync: () => {} 23 | }), 'cannot link on EACCES error') 24 | t.notOk(canLink.sync('foo', 'bar', { 25 | linkSync: () => { throw epermErr }, 26 | unlinkSync: () => {} 27 | }), 'cannot link on EPERM error') 28 | t.throws(() => { 29 | const fsMock = { 30 | linkSync: () => { throw new Error('Error') } 31 | } 32 | canLink.sync('foo', 'bar', fsMock) 33 | }, /Error/, 'errors are passed through if they are not EXDEV') 34 | t.end() 35 | }) 36 | 37 | test('canLink() returns true', t => { 38 | canLink('package.json', 'node_modules/package.json') 39 | .then(can => { 40 | t.ok(can) 41 | t.end() 42 | }) 43 | .catch(t.end) 44 | }) 45 | 46 | test('canLink() returns false', t => { 47 | canLink('package.json', 'node_modules/package.json', { 48 | promises: { 49 | link: (existingPath, newPath, cb) => Promise.reject(exdevErr), 50 | unlink: (p, cb) => Promise.resolve() 51 | } 52 | }) 53 | .then(can => { 54 | t.notOk(can) 55 | t.end() 56 | }) 57 | .catch(t.end) 58 | }) 59 | 60 | test('canLink() returns false on EACCES error', t => { 61 | canLink('package.json', 'node_modules/package.json', { 62 | promises: { 63 | link: (existingPath, newPath, cb) => Promise.reject(eaccesErr), 64 | unlink: (p, cb) => Promise.resolve() 65 | } 66 | }) 67 | .then(can => { 68 | t.notOk(can) 69 | t.end() 70 | }) 71 | .catch(t.end) 72 | }) 73 | 74 | test('canLink() returns false on EPERM error', async t => { 75 | const can = await canLink('package.json', 'node_modules/package.json', { 76 | promises: { 77 | link: (existingPath, newPath, cb) => Promise.reject(epermErr), 78 | unlink: (p, cb) => cb() 79 | } 80 | }) 81 | t.notOk(can) 82 | t.end() 83 | }) 84 | 85 | test('canLink() non-exdev error passed through', t => { 86 | canLink('package.json', 'node_modules/package.json', { 87 | promises: { 88 | link: (existingPath, newPath, cb) => Promise.reject(new Error('Error')) 89 | } 90 | }) 91 | .then(can => { 92 | t.fail('should have failed') 93 | }) 94 | .catch(err => { 95 | t.ok(err) 96 | t.end() 97 | }) 98 | }) 99 | -------------------------------------------------------------------------------- /can-write-to-dir/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # can-write-to-dir 2 | 3 | ## 1.1.1 4 | 5 | ### Patch Changes 6 | 7 | - 33a7d64: canWriteToDir.sync() should not fail on EROFS error. 8 | 9 | ## 1.1.0 10 | 11 | ### Minor Changes 12 | 13 | - bba9985: graceful-fs and mz removed from dependencies. 14 | 15 | ## 1.0.0 16 | 17 | ### Major Changes 18 | 19 | - 48d36f2: Project created. 20 | -------------------------------------------------------------------------------- /can-write-to-dir/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /can-write-to-dir/README.md: -------------------------------------------------------------------------------- 1 | # can-write-to-dir 2 | 3 | > Returns true if the current process has permission to write to the specified directory 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/can-write-to-dir.svg)](https://www.npmjs.com/package/can-write-to-dir) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add can-write-to-dir 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const canWriteToDir = require('can-write-to-dir') 19 | 20 | canWriteToDir.sync('C:\\') 21 | //> false 22 | ``` 23 | 24 | ## API 25 | 26 | ### `canWriteToDir.sync(dir): Boolean` 27 | 28 | Returns `true` if `fs.writeFileSync` is able to create a file. 29 | 30 | ### `canWriteToDir(dir): Promise` 31 | 32 | Returns `true` if `fs.writeFile` is able to create a file. 33 | 34 | ## License 35 | 36 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 37 | -------------------------------------------------------------------------------- /can-write-to-dir/index.d.ts: -------------------------------------------------------------------------------- 1 | export = canWriteToDir 2 | 3 | declare function canWriteToDir (dir: string): Promise 4 | 5 | declare namespace canWriteToDir { 6 | function sync (dir: string): boolean 7 | } 8 | -------------------------------------------------------------------------------- /can-write-to-dir/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const defaultFS = require('fs') 3 | const pathTemp = require('path-temp') 4 | 5 | module.exports = async (dir, customFS) => { 6 | const fs = customFS || defaultFS 7 | const tempFile = pathTemp(dir) 8 | try { 9 | await fs.promises.writeFile(tempFile, '', 'utf8') 10 | fs.promises.unlink(tempFile).catch(() => {}) 11 | return true 12 | } catch (err) { 13 | if (err.code === 'EACCES' || err.code === 'EPERM' || err.code === 'EROFS') { 14 | return false 15 | } 16 | throw err 17 | } 18 | } 19 | 20 | module.exports.sync = (dir, customFS) => { 21 | const fs = customFS || defaultFS 22 | const tempFile = pathTemp(dir) 23 | try { 24 | fs.writeFileSync(tempFile, '', 'utf8') 25 | fs.unlinkSync(tempFile) 26 | return true 27 | } catch (err) { 28 | if (err.code === 'EACCES' || err.code === 'EPERM' || err.code === 'EROFS') { 29 | return false 30 | } 31 | throw err 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /can-write-to-dir/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "can-write-to-dir", 3 | "version": "1.1.1", 4 | "description": "Returns true if the current process has permission to write to the specified directory", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && node test" 13 | }, 14 | "repository": "https://github.com/zkochan/packages/tree/main/can-write-to-dir", 15 | "keywords": [ 16 | "access", 17 | "permission", 18 | "directory", 19 | "folder" 20 | ], 21 | "engines": { 22 | "node": ">=10.13" 23 | }, 24 | "author": "Zoltan Kochan (https://www.kochan.io/)", 25 | "license": "MIT", 26 | "homepage": "https://github.com/zkochan/packages/tree/main/can-write-to-dir#readme", 27 | "dependenciesMeta": { 28 | "can-write-to-dir": { 29 | "injected": true 30 | } 31 | }, 32 | "dependencies": { 33 | "path-temp": "^2.1.0" 34 | }, 35 | "devDependencies": { 36 | "can-write-to-dir": "file:", 37 | "standard": "^16.0.4", 38 | "tape": "^5.9.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /can-write-to-dir/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const canWriteToDir = require('can-write-to-dir') 4 | 5 | const eaccesErr = new Error('EACCES: permission denied, link') 6 | eaccesErr.code = 'EACCES' 7 | 8 | const epermErr = new Error('EPERM: permission denied, link') 9 | epermErr.code = 'EPERM' 10 | 11 | test('canWriteToDir.sync()', t => { 12 | t.ok(canWriteToDir.sync(process.cwd())) 13 | t.notOk(canWriteToDir.sync('/foo', { 14 | writeFileSync: () => { throw eaccesErr }, 15 | unlinkSync: () => {} 16 | }), 'cannot link on EACCES error') 17 | t.notOk(canWriteToDir.sync('foo', { 18 | writeFileSync: () => { throw epermErr }, 19 | unlinkSync: () => {} 20 | }), 'cannot link on EPERM error') 21 | t.throws(() => { 22 | const fsMock = { 23 | linkSync: () => { throw new Error('Error') } 24 | } 25 | canWriteToDir.sync('foo', 'bar', fsMock) 26 | }, /Error/, 'errors are passed through if they are not EXDEV') 27 | t.end() 28 | }) 29 | 30 | test('canWriteToDir() returns true', async t => { 31 | t.ok(await canWriteToDir(process.cwd())) 32 | t.end() 33 | }) 34 | 35 | test('canWriteToDir() returns false on EACCES error', async t => { 36 | t.notOk(await canWriteToDir('/', { 37 | promises: { 38 | writeFile: (a1, a2, a3, cb) => Promise.reject(eaccesErr), 39 | unlink: (p, cb) => Promise.resolve() 40 | } 41 | })) 42 | t.end() 43 | }) 44 | 45 | test('canWriteToDir() returns false on EACCES error', async t => { 46 | t.notOk(await canWriteToDir('/', { 47 | promises: { 48 | writeFile: (a1, a2, a3, cb) => Promise.reject(epermErr), 49 | unlink: (p, cb) => Promise.resolve() 50 | } 51 | })) 52 | t.end() 53 | }) 54 | 55 | test('canWriteToDir() non-exdev error passed through', async t => { 56 | let err 57 | try { 58 | await canWriteToDir('/', { 59 | writeFile: (a1, a2, a3, cb) => cb(new Error('Error')) 60 | }) 61 | } catch (_err) { 62 | err = _err 63 | } 64 | t.ok(err) 65 | t.end() 66 | }) 67 | -------------------------------------------------------------------------------- /cmd-extension/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmd-extension/README.md: -------------------------------------------------------------------------------- 1 | # cmd-extension 2 | 3 | > Gets the right command file extension on Windows 4 | 5 | [![npm version](https://img.shields.io/npm/v/cmd-extension.svg)](https://www.npmjs.com/package/cmd-extension) 6 | 7 | ## Installation 8 | 9 | ```sh 10 | add cmd-extension 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | 'use strict' 17 | const CMD_EXTENSION = require('cmd-extension') 18 | 19 | console.log(CMD_EXTENSION) 20 | //> .CMD 21 | ``` 22 | 23 | ## License 24 | 25 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 26 | -------------------------------------------------------------------------------- /cmd-extension/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const cmdExtension: string 2 | export = cmdExtension 3 | -------------------------------------------------------------------------------- /cmd-extension/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | 4 | let cmdExtension 5 | 6 | if (process.env.PATHEXT) { 7 | cmdExtension = process.env.PATHEXT 8 | .split(path.delimiter) 9 | .find(ext => ext.toUpperCase() === '.CMD') 10 | } 11 | 12 | module.exports = cmdExtension || '.cmd' 13 | -------------------------------------------------------------------------------- /cmd-extension/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cmd-extension", 3 | "version": "1.0.2", 4 | "description": "Gets the right command file extension on Windows", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "engines": { 11 | "node": ">=10" 12 | }, 13 | "repository": "https://github.com/zkochan/packages/tree/main/cmd-extension", 14 | "author": { 15 | "name": "Zoltan Kochan" 16 | }, 17 | "license": "MIT", 18 | "homepage": "https://github.com/zkochan/packages/tree/main/cmd-extension#readme" 19 | } 20 | -------------------------------------------------------------------------------- /comver-to-semver/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /comver-to-semver/README.md: -------------------------------------------------------------------------------- 1 | # comver-to-semver 2 | 3 | > Converts a comver (compatible version) to a semver (semantic version). 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/comver-to-semver.svg)](https://www.npmjs.com/package/comver-to-semver) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add comver-to-semver 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const comverToSemver = require('comver-to-semver') 19 | 20 | comverToSemver('2.1') 21 | //> '2.1.0' 22 | 23 | comverToSemver('2') 24 | //> '2.0.0' 25 | ``` 26 | 27 | ## License 28 | 29 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 30 | -------------------------------------------------------------------------------- /comver-to-semver/index.d.ts: -------------------------------------------------------------------------------- 1 | export = comverToSemver 2 | 3 | declare function comverToSemver (comver: string): string 4 | -------------------------------------------------------------------------------- /comver-to-semver/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function comverToSemver (comver) { 4 | if (!comver.includes('.')) return `${comver}.0.0` 5 | return `${comver}.0` 6 | } 7 | -------------------------------------------------------------------------------- /comver-to-semver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "comver-to-semver", 3 | "version": "1.0.0", 4 | "description": "Converts a comver (compatible version) to a semver (semantic version).", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "node test" 13 | }, 14 | "repository": "https://github.com/zkochan/packages/tree/main/comver-to-semver", 15 | "keywords": [ 16 | "comver", 17 | "semver" 18 | ], 19 | "engines": { 20 | "node": ">=12.17" 21 | }, 22 | "author": "Zoltan Kochan (https://www.kochan.io/)", 23 | "license": "MIT", 24 | "homepage": "https://github.com/zkochan/packages/tree/main/comver-to-semver#readme", 25 | "devDependencies": { 26 | "tape": "^5.9.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /comver-to-semver/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const comverToSemver = require('.') 4 | 5 | test('canWriteToDir.sync()', t => { 6 | t.equal(comverToSemver('2'), '2.0.0') 7 | t.equal(comverToSemver('2.1'), '2.1.0') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # dir-is-case-sensitive 2 | 3 | ## 2.0.0 4 | ### Major Changes 5 | 6 | - bba9985: Support of Node.js versions older than 10 is dropped. 7 | 8 | ### Minor Changes 9 | 10 | - bba9985: graceful-fs and mz removed from dependencies. 11 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/README.md: -------------------------------------------------------------------------------- 1 | # dir-is-case-sensitive 2 | 3 | > Returns true, if the specified directory is case sensitive 4 | 5 | Some filesystems are case sensitive, some are not. Some allow 6 | specific directories to be case sensitive. This package helps 7 | to detect if a directory is case sensitive or not. 8 | 9 | ## Installation 10 | 11 | ``` 12 | add dir-is-case-sensitive 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```ts 18 | import dirIsCaseSensitive from 'dir-is-case-sensitive' 19 | 20 | await dirIsCaseSensitive('/src') 21 | //> true 22 | ``` 23 | 24 | ## API 25 | 26 | ### `dirIsCaseSensitive(dirPath, [silent=true]): Promise` 27 | 28 | #### Arguments 29 | 30 | * dirPath - *Path* - the dir to check 31 | * silent - *Boolean* - Optional. `true` by default. When `false`, an error is thrown if cannot check case sensibility of the file. 32 | 33 | #### Returns 34 | 35 | * true if dir is case sensible 36 | * false if dir is case sensible 37 | * undefined if could not detect 38 | 39 | ## License 40 | 41 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 42 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dir-is-case-sensitive", 3 | "version": "2.0.0", 4 | "description": "Returns true, if the specified directory is case sensitive", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "engines": { 8 | "node": ">=10" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "scripts": { 14 | "test": "ts-node test", 15 | "tsc": "tsc", 16 | "prepublishOnly": "pnpm run tsc" 17 | }, 18 | "repository": "https://github.com/zkochan/packages/tree/main/dir-is-case-sensitive", 19 | "keywords": [ 20 | "filesystem", 21 | "case" 22 | ], 23 | "author": { 24 | "name": "Zoltan Kochan", 25 | "email": "z@kochan.io" 26 | }, 27 | "license": "MIT", 28 | "homepage": "https://github.com/zkochan/packages/tree/main/dir-is-case-sensitive#readme", 29 | "dependenciesMeta": { 30 | "dir-is-case-sensitive": { 31 | "injected": true 32 | } 33 | }, 34 | "dependencies": { 35 | "path-temp": "2.0.0" 36 | }, 37 | "devDependencies": { 38 | "@types/node": "14.14.6", 39 | "@types/tape": "^4.13.4", 40 | "dir-is-case-sensitive": "file:", 41 | "tape": "^5.9.0", 42 | "ts-node": "^10.9.2", 43 | "typescript": "^4.9.5" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/src/index.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'fs' 2 | import pathTemp = require('path-temp') 3 | 4 | export default async (dir: string, silent: boolean = true): Promise => { 5 | const tempFile = pathTemp(dir).toLowerCase() 6 | try { 7 | await fs.writeFile(tempFile, '', 'utf8') 8 | } catch (err) { 9 | if (silent) { 10 | return 11 | } 12 | throw err 13 | } 14 | try { 15 | await fs.stat(tempFile.toUpperCase()) 16 | // If the file in different casing is FOUND, 17 | // then the directory is case insensitive 18 | return false 19 | } catch (err) { 20 | if (err.code === 'ENOENT') { 21 | // If the file in different casing is NOT FOUND, 22 | // then the directory is case sensitive 23 | return true 24 | } 25 | if (silent) { 26 | return 27 | } 28 | throw err 29 | } finally { 30 | // The temp file is removed 31 | fs.unlink(tempFile).catch((err) => { 32 | // Errors are ignored 33 | }) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/test/index.ts: -------------------------------------------------------------------------------- 1 | import dirIsCaseSensitive from 'dir-is-case-sensitive' 2 | import test = require('tape') 3 | 4 | test('dirIsCaseSensitive()', async (t) => { 5 | const isCaseSensitive = await dirIsCaseSensitive(__dirname) 6 | t.equal(typeof isCaseSensitive, 'boolean') 7 | t.comment(isCaseSensitive ? 'directory is case sensitive' : 'directory is not case sensitive') 8 | t.end() 9 | }) 10 | -------------------------------------------------------------------------------- /dir-is-case-sensitive/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "removeComments": false, 4 | "preserveConstEnums": true, 5 | "sourceMap": true, 6 | "declaration": true, 7 | "noImplicitAny": true, 8 | "noImplicitReturns": true, 9 | "suppressImplicitAnyIndexErrors": true, 10 | "allowSyntheticDefaultImports": true, 11 | "strictNullChecks": true, 12 | "target": "es2017", 13 | "outDir": "lib", 14 | "module": "commonjs", 15 | "moduleResolution": "node" 16 | }, 17 | "include": [ 18 | "src/**/*.ts" 19 | ], 20 | "atom": { 21 | "rewriteTsconfig": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /graceful-git/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # graceful-git 2 | 3 | ## 4.0.0 4 | 5 | ### Major Changes 6 | 7 | - Drop Node.js <18 support. 8 | 9 | ### Patch Changes 10 | 11 | - a242fb3: Update retry to v0.13.0 12 | 13 | ## 3.0.2 14 | 15 | ### Patch Changes 16 | 17 | - Update execa to v5. 18 | -------------------------------------------------------------------------------- /graceful-git/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2024 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /graceful-git/README.md: -------------------------------------------------------------------------------- 1 | # graceful-git 2 | 3 | > Executes Git commands gracefully. Retries on errors 4 | 5 | Git is called by absolute path to avoid binary planting attacks on Windows. 6 | 7 | 8 | [![npm version](https://img.shields.io/npm/v/graceful-git.svg)](https://www.npmjs.com/package/graceful-git) 9 | 10 | 11 | ## Installation 12 | 13 | ```sh 14 | add graceful-git 15 | ``` 16 | 17 | ## Usage 18 | 19 | 20 | ```js 21 | 'use strict' 22 | const gracefulGit = require('graceful-git') 23 | 24 | gracefulGit(['status', 'README.md']) 25 | .then(result => console.log(result.stdout)) 26 | .catch(err => console.error(err)) 27 | //> On branch master 28 | // Your branch is based on 'origin/master', but the upstream is gone. 29 | // (use "git branch --unset-upstream" to fixup) 30 | // nothing to commit, working directory clean 31 | ``` 32 | 33 | 34 | ## API 35 | 36 | ### `git(args, [opts]) => Promise` 37 | 38 | **Arguments:** 39 | 40 | - `args` - _string\[]_ - arguments passed to the Git CLI 41 | - `opts.cwd` - _Path_ - the directory in which the Git command should be executed 42 | - `...opts` - _object_ - optional. Parameters used by [retry](https://www.npmjs.com/package/retry) when git operation fails. 43 | 44 | ### `git.noRetry(args, [opts]) => Promise` 45 | 46 | Same as `git()` but without retries. 47 | 48 | ## License 49 | 50 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 51 | -------------------------------------------------------------------------------- /graceful-git/example.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const gracefulGit = require('graceful-git') 3 | 4 | gracefulGit(['status', 'README.md']) 5 | .then(result => console.log(result.stdout)) 6 | .catch(err => console.error(err)) 7 | -------------------------------------------------------------------------------- /graceful-git/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const execa = require('safe-execa').default 3 | const retry = require('retry') 4 | 5 | const RETRY_OPTIONS = { 6 | retries: 3, 7 | minTimeout: 1 * 1000, 8 | maxTimeout: 10 * 1000, 9 | randomize: true, 10 | } 11 | 12 | module.exports = gracefulGit 13 | module.exports.noRetry = noRetry 14 | 15 | async function gracefulGit (args, opts) { 16 | opts = opts || {} 17 | const operation = retry.operation(Object.assign({}, RETRY_OPTIONS, opts)) 18 | return new Promise((resolve, reject) => { 19 | operation.attempt(currentAttempt => { 20 | noRetry(args, opts).then(resolve) 21 | .catch(err => { 22 | if (operation.retry(err)) { 23 | return 24 | } 25 | reject(operation.mainError()) 26 | }) 27 | }) 28 | }) 29 | } 30 | 31 | async function noRetry (args, opts) { 32 | opts = opts || {} 33 | return execa('git', args, {cwd: opts.cwd || process.cwd()}) 34 | } 35 | -------------------------------------------------------------------------------- /graceful-git/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graceful-git", 3 | "version": "4.0.0", 4 | "description": "Executes git commands gracefully. Retries them on errors", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js" 8 | ], 9 | "engines": { 10 | "node": ">=18.12" 11 | }, 12 | "scripts": { 13 | "test": "tape test.js", 14 | "md": "mos" 15 | }, 16 | "mos": { 17 | "plugins": [ 18 | "readme" 19 | ], 20 | "installation": { 21 | "useShortAlias": true 22 | } 23 | }, 24 | "repository": "https://github.com/zkochan/packages/tree/main/graceful-git", 25 | "keywords": [ 26 | "git", 27 | "retry", 28 | "retries", 29 | "exec" 30 | ], 31 | "author": { 32 | "name": "Zoltan Kochan", 33 | "url": "https://www.kochan.io" 34 | }, 35 | "license": "MIT", 36 | "homepage": "https://github.com/zkochan/packages/tree/main/graceful-git#readme", 37 | "dependenciesMeta": { 38 | "graceful-git": { 39 | "injected": true 40 | } 41 | }, 42 | "dependencies": { 43 | "retry": "^0.13.1", 44 | "safe-execa": "^0.1.4" 45 | }, 46 | "devDependencies": { 47 | "graceful-git": "file:", 48 | "mos": "2.0.0-alpha.3", 49 | "mos-plugin-readme": "^1.0.4", 50 | "tape": "^5.9.0" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /graceful-git/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const git = require('graceful-git') 3 | const test = require('tape') 4 | 5 | test('git command successfully completes', t => { 6 | git(['status']) 7 | .then(() => t.end()) 8 | .catch(t.end) 9 | }) 10 | 11 | test('git command successfully completes with no retries as well', t => { 12 | git.noRetry(['status']) 13 | .then(() => t.end()) 14 | .catch(t.end) 15 | }) 16 | -------------------------------------------------------------------------------- /is-inner-link/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # is-inner-link 2 | 3 | ## 4.0.0 4 | ### Major Changes 5 | 6 | - bba9985: Support of Node.js versions older than 10 is dropped. 7 | 8 | ### Minor Changes 9 | 10 | - bba9985: graceful-fs and mz removed from dependencies. 11 | 12 | ### Patch Changes 13 | 14 | - Updated dependencies [bba9985] 15 | - Updated dependencies [bba9985] 16 | - resolve-link-target@2.0.0 17 | -------------------------------------------------------------------------------- /is-inner-link/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /is-inner-link/README.md: -------------------------------------------------------------------------------- 1 | # is-inner-link 2 | 3 | > Returns true if a link targets a directory inside its parent directory 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/is-inner-link.svg)](https://www.npmjs.com/package/is-inner-link) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add is-inner-link 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | 'use strict' 19 | const isInnerLink = require('is-inner-link') 20 | 21 | isInnerLink('node_modules', 'foo') 22 | .then(link => console.log(link)) 23 | .catch(err => console.error(err)) 24 | //> {isInner: false, target: '/zkochan/foo'} 25 | ``` 26 | 27 | ## License 28 | 29 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 30 | -------------------------------------------------------------------------------- /is-inner-link/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const isSubdir = require('is-subdir') 4 | const resolveLinkTarget = require('resolve-link-target') 5 | 6 | module.exports = async function (parent, relativePathToLink) { 7 | const linkPath = path.resolve(parent, relativePathToLink) 8 | const target = await resolveLinkTarget(linkPath) 9 | return { 10 | isInner: isSubdir(parent, target), 11 | target 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /is-inner-link/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-inner-link", 3 | "version": "4.0.0", 4 | "description": "Returns true if a link targets a directory inside its parent directory", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js" 8 | ], 9 | "scripts": { 10 | "pretest": "rimraf .tmp", 11 | "test": "standard && node test", 12 | "md": "mos" 13 | }, 14 | "repository": "https://github.com/zkochan/packages/tree/main/is-inner-link", 15 | "keywords": [ 16 | "link", 17 | "symlink", 18 | "directory", 19 | "folder" 20 | ], 21 | "author": { 22 | "name": "Zoltan Kochan", 23 | "url": "https://www.kochan.io" 24 | }, 25 | "engines": { 26 | "node": ">=10" 27 | }, 28 | "license": "MIT", 29 | "mos": { 30 | "plugins": [ 31 | "readme" 32 | ], 33 | "installation": { 34 | "useShortAlias": true 35 | } 36 | }, 37 | "homepage": "https://github.com/zkochan/packages/tree/main/is-inner-link#readme", 38 | "dependenciesMeta": { 39 | "is-inner-link": { 40 | "injected": true 41 | } 42 | }, 43 | "dependencies": { 44 | "is-subdir": "^1.2.0", 45 | "resolve-link-target": "workspace:^" 46 | }, 47 | "devDependencies": { 48 | "is-inner-link": "file:", 49 | "make-dir": "^3.1.0", 50 | "mos": "2.0.0-alpha.3", 51 | "mos-plugin-readme": "^1.0.4", 52 | "rimraf": "^3.0.2", 53 | "standard": "^16.0.4", 54 | "symlink-dir": "^5.2.1", 55 | "tape": "^5.9.0" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /is-inner-link/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const isInnerLink = require('is-inner-link') 4 | const makeDir = require('make-dir') 5 | const path = require('path') 6 | const symlinkDir = require('symlink-dir').default 7 | 8 | test('is inner', async t => { 9 | const target = path.resolve('.tmp', '1', 'a', 'b') 10 | makeDir.sync(target) 11 | await symlinkDir(target, path.join(target, '..', '..', 'b')) 12 | const link = await isInnerLink(path.resolve('.tmp', '1'), 'b') 13 | t.ok(link.isInner) 14 | t.equal(typeof link.target, 'string') 15 | t.end() 16 | }) 17 | 18 | test('is not inner', async t => { 19 | const dest = path.resolve('.tmp', '2', 'a') 20 | const target = path.resolve('.tmp', '2', 'b') 21 | makeDir.sync(target) 22 | await symlinkDir(target, path.join(dest, 'b')) 23 | const link = await isInnerLink(dest, 'b') 24 | t.ok(!link.isInner) 25 | t.equal(typeof link.target, 'string') 26 | t.end() 27 | }) 28 | -------------------------------------------------------------------------------- /is-subdir/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /is-subdir/README.md: -------------------------------------------------------------------------------- 1 | # is-subdir 2 | 3 | > Return whether a directory is a subdirectory of another directory 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/is-subdir.svg)](https://www.npmjs.com/package/is-subdir) 7 | 8 | 9 | Cross-platform. Works correctly on Windows, where directory paths can start with disk drive letters in different casings. Like `c:\foo` and `C:\foo\bar`. 10 | 11 | Returns `true` when the directories match. The `isSubdir.strict()` variant only returns true if the second parameter is a strict subdir of the first and not the same. 12 | 13 | ## Installation 14 | 15 | ```sh 16 | add is-subdir 17 | ``` 18 | 19 | ## Usage 20 | 21 | ```js 22 | 'use strict' 23 | const path = require('path') 24 | const isSubdir = require('is-subdir') 25 | 26 | console.log(isSubdir(process.cwd(), path.resolve('node_modules'))) 27 | //> true 28 | console.log(isSubdir.strict('node_modules/tape', '../tape')) 29 | //> false 30 | ``` 31 | 32 | ## API 33 | 34 | ### `isSubdir(parentDir, subdir): boolean` 35 | ### `isSubdir.strict(parentDir, subdir): boolean` 36 | 37 | ## License 38 | 39 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 40 | -------------------------------------------------------------------------------- /is-subdir/example.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const isSubdir = require('.') 4 | 5 | console.log(isSubdir(process.cwd(), path.resolve('node_modules'))) 6 | -------------------------------------------------------------------------------- /is-subdir/index.d.ts: -------------------------------------------------------------------------------- 1 | export = isSubdir 2 | 3 | declare function isSubdir (parentDir: string, subdir: string): boolean 4 | 5 | declare namespace isSubdir { 6 | export function strict (parentDir: string, subdir: string): boolean 7 | } 8 | -------------------------------------------------------------------------------- /is-subdir/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const betterPathResolve = require('better-path-resolve') 3 | const path = require('path') 4 | 5 | function isSubdir (parentDir, subdir) { 6 | const rParent = `${betterPathResolve(parentDir)}${path.sep}` 7 | const rDir = `${betterPathResolve(subdir)}${path.sep}` 8 | return rDir.startsWith(rParent) 9 | } 10 | 11 | isSubdir.strict = function isSubdirStrict (parentDir, subdir) { 12 | const rParent = `${betterPathResolve(parentDir)}${path.sep}` 13 | const rDir = `${betterPathResolve(subdir)}${path.sep}` 14 | return rDir !== rParent && rDir.startsWith(rParent) 15 | } 16 | 17 | module.exports = isSubdir 18 | -------------------------------------------------------------------------------- /is-subdir/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-subdir", 3 | "version": "1.2.0", 4 | "description": "Return whether a directory is a subdirectory of another directory", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "scripts": { 11 | "test": "node test", 12 | "md": "mos" 13 | }, 14 | "engines": { 15 | "node": ">=4" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/is-subdir", 18 | "keywords": [ 19 | "subdirectory", 20 | "subfolder", 21 | "subpath", 22 | "directory", 23 | "folder", 24 | "path" 25 | ], 26 | "author": { 27 | "name": "Zoltan Kochan", 28 | "url": "https://www.kochan.io" 29 | }, 30 | "mos": { 31 | "plugins": [ 32 | "readme" 33 | ], 34 | "installation": { 35 | "useShortAlias": true 36 | } 37 | }, 38 | "license": "MIT", 39 | "homepage": "https://github.com/zkochan/packages/tree/main/is-subdir#readme", 40 | "devDependencies": { 41 | "is-windows": "1.0.2", 42 | "mos": "2.0.0-alpha.3", 43 | "mos-plugin-readme": "^1.0.4", 44 | "tape": "^5.9.0" 45 | }, 46 | "dependencies": { 47 | "better-path-resolve": "1.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /is-subdir/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const path = require('path') 4 | const isSubdir = require('.') 5 | const isWindows = require('is-windows')() 6 | 7 | test('isSubdir()', t => { 8 | t.ok(isSubdir(process.cwd(), path.resolve('node_modules'))) 9 | t.ok(!isSubdir(process.cwd(), path.resolve('..'))) 10 | t.ok(isSubdir(process.cwd(), process.cwd())) 11 | 12 | t.ok(isSubdir('node_modules', path.resolve('node_modules', 'tape'))) 13 | t.notOk(isSubdir(path.resolve('node_modules', 'foo'), path.resolve('node_modules', 'foo-bar'))) 14 | 15 | if (isWindows) { 16 | t.ok(isSubdir('C:', 'C:\\.pnpm-store')) 17 | } 18 | 19 | t.end() 20 | }) 21 | 22 | test('isSubdir.strict()', t => { 23 | t.notOk(isSubdir.strict(process.cwd(), process.cwd())) 24 | t.notOk(isSubdir.strict('node_modules/tape', '../tape')) 25 | t.ok(isSubdir.strict('node_modules', path.resolve('node_modules', 'tape'))) 26 | 27 | t.end() 28 | }) 29 | -------------------------------------------------------------------------------- /make-empty-dir/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # make-empty-dir 2 | 3 | ## 3.0.2 4 | 5 | ### Patch Changes 6 | 7 | - Updated dependencies [b70f4a9] 8 | - @zkochan/rimraf@3.0.2 9 | 10 | ## 3.0.0 11 | 12 | ### Patch Changes 13 | 14 | - Updated dependencies [3fa8bea] 15 | - @zkochan/rimraf@3.0.0 16 | 17 | ## 2.1.0 18 | 19 | ### Minor Changes 20 | 21 | - 59f06c5: Add a sync function. 22 | 23 | ### Patch Changes 24 | 25 | - Updated dependencies [1b6d04d] 26 | - @zkochan/rimraf@2.1.3 27 | 28 | ## 2.0.0 29 | 30 | ### Major Changes 31 | 32 | - Deprecate Node.js 10 33 | 34 | ## 1.1.0 35 | 36 | ### Minor Changes 37 | 38 | - bba9985: graceful-fs and mz removed from dependencies. 39 | 40 | ## 1.0.0 41 | 42 | ### Major Changes 43 | 44 | - 4f1942a: Project created 45 | -------------------------------------------------------------------------------- /make-empty-dir/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2024 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /make-empty-dir/README.md: -------------------------------------------------------------------------------- 1 | # make-empty-dir 2 | 3 | > Ensures that a directory is empty 4 | 5 | [![npm version](https://img.shields.io/npm/v/make-empty-dir.svg)](https://www.npmjs.com/package/make-empty-dir) 6 | 7 | Ensures that a directory is empty. Deletes directory contents if the directory is not empty. If the directory does not exist, it is created. The directory itself is not deleted. 8 | 9 | It works faster than `emptyDir()` of `fs-extra` because the contents of the directory are not read before the creation of the directory. 10 | 11 | ## Installation 12 | 13 | ```sh 14 | add make-empty-dir 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```js 20 | 'use strict' 21 | const makeEmptyDir = require('make-empty-dir') 22 | 23 | await makeEmptyDir('dir-name') 24 | 25 | // or create the parent dir as well 26 | await makeEmptyDir('dir/subdir', { recursive: true }) 27 | ``` 28 | 29 | ## API 30 | 31 | ### `makeEmptyDir(dir: string, [opts]): Promise<'created' | 'emptied'>` 32 | 33 | **Arguments:** 34 | 35 | * `dir` - *Path* - the path of the directory. 36 | * `opts.recursive` - *Boolean* - Optional. If true, parent directories will be created. 37 | 38 | **Returns:** 39 | 40 | A string is returned. 41 | 42 | * `'created'` - if there was no directory 43 | * `'emptied'` - if there was a directory and the its contents were removed. 44 | 45 | ## License 46 | 47 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 48 | -------------------------------------------------------------------------------- /make-empty-dir/index.d.ts: -------------------------------------------------------------------------------- 1 | declare function makeEmptyDir (dir: string, opts?: { recursive?: boolean }): Promise<'created' | 'emptied'> 2 | 3 | declare namespace makeEmptyDir { 4 | function sync(dir: string, opts?: { recursive?: boolean }): 'created' | 'emptied' 5 | } 6 | 7 | export = makeEmptyDir 8 | -------------------------------------------------------------------------------- /make-empty-dir/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const path = require('path') 4 | const rimraf = require('@zkochan/rimraf') 5 | 6 | module.exports = async function makeEmptyDir (dir, opts) { 7 | if (opts && opts.recursive) { 8 | await fs.promises.mkdir(path.dirname(dir), { recursive: true }) 9 | } 10 | try { 11 | await fs.promises.mkdir(dir) 12 | return 'created' 13 | } catch (err) { 14 | if (err.code === 'EEXIST') { 15 | await removeContentsOfDir(dir) 16 | return 'emptied' 17 | } 18 | throw err 19 | } 20 | } 21 | 22 | async function removeContentsOfDir (dir) { 23 | const items = await fs.promises.readdir(dir) 24 | for (const item of items) { 25 | await rimraf(path.join(dir, item)) 26 | } 27 | } 28 | 29 | module.exports.sync = function makeEmptyDirSync (dir, opts) { 30 | if (opts && opts.recursive) { 31 | fs.mkdirSync(path.dirname(dir), { recursive: true }) 32 | } 33 | try { 34 | fs.mkdirSync(dir) 35 | return 'created' 36 | } catch (err) { 37 | if (err.code === 'EEXIST') { 38 | removeContentsOfDirSync(dir) 39 | return 'emptied' 40 | } 41 | throw err 42 | } 43 | } 44 | 45 | function removeContentsOfDirSync (dir) { 46 | const items = fs.readdirSync(dir) 47 | for (const item of items) { 48 | rimraf.sync(path.join(dir, item)) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /make-empty-dir/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "make-empty-dir", 3 | "version": "3.0.2", 4 | "description": "Ensures that a directory is empty", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "scripts": { 11 | "test": "node test" 12 | }, 13 | "engines": { 14 | "node": ">=18.12" 15 | }, 16 | "repository": "https://github.com/zkochan/packages/tree/main/make-empty-dir", 17 | "keywords": [ 18 | "directory", 19 | "folder", 20 | "mkdir", 21 | "make-dir", 22 | "empty" 23 | ], 24 | "author": { 25 | "name": "Zoltan Kochan", 26 | "url": "https://www.kochan.io" 27 | }, 28 | "license": "MIT", 29 | "homepage": "https://github.com/zkochan/packages/tree/main/make-empty-dir#readme", 30 | "devDependencies": { 31 | "tape": "^5.9.0", 32 | "tempy": "^1.0.1" 33 | }, 34 | "dependencies": { 35 | "@zkochan/rimraf": "workspace:^" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /make-empty-dir/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const test = require('tape') 4 | const tempy = require('tempy') 5 | const path = require('path') 6 | const makeEmptyDir = require('.') 7 | 8 | test('creates a new directory if it does not exist', async t => { 9 | const dir = path.join(tempy.directory(), 'empty') 10 | t.equal(await makeEmptyDir(dir), 'created') 11 | t.ok(fs.existsSync(dir)) 12 | t.end() 13 | }) 14 | 15 | test('creates a new directory and its parent directory, when recursive is set to true', async t => { 16 | const dir = path.join(tempy.directory(), 'empty/empty') 17 | t.equal(await makeEmptyDir(dir, { recursive: true }), 'created') 18 | t.ok(fs.existsSync(dir)) 19 | t.end() 20 | }) 21 | 22 | test('fails if the parent directory does not exist and recursive is not set', async t => { 23 | const dir = path.join(tempy.directory(), 'empty/empty') 24 | let err 25 | try { 26 | await makeEmptyDir(dir) 27 | } catch (_err) { 28 | err = _err 29 | } 30 | t.ok(err) 31 | t.end() 32 | }) 33 | 34 | test('removes everything from an existing directory', async t => { 35 | const dir = path.join(tempy.directory(), 'empty') 36 | fs.mkdirSync(path.join(dir)) 37 | const filePath = path.join(dir, 'file') 38 | fs.writeFileSync(filePath, '', 'utf8') 39 | t.equal(await makeEmptyDir(dir), 'emptied') 40 | t.ok(fs.existsSync(dir)) 41 | t.notOk(fs.existsSync(filePath)) 42 | t.end() 43 | }) 44 | 45 | test('sync: creates a new directory if it does not exist', t => { 46 | const dir = path.join(tempy.directory(), 'empty') 47 | t.equal(makeEmptyDir.sync(dir), 'created') 48 | t.ok(fs.existsSync(dir)) 49 | t.end() 50 | }) 51 | 52 | test('sync: creates a new directory and its parent directory, when recursive is set to true', t => { 53 | const dir = path.join(tempy.directory(), 'empty/empty') 54 | t.equal(makeEmptyDir.sync(dir, { recursive: true }), 'created') 55 | t.ok(fs.existsSync(dir)) 56 | t.end() 57 | }) 58 | 59 | test('sync: fails if the parent directory does not exist and recursive is not set', t => { 60 | const dir = path.join(tempy.directory(), 'empty/empty') 61 | let err 62 | try { 63 | makeEmptyDir.sync(dir) 64 | } catch (_err) { 65 | err = _err 66 | } 67 | t.ok(err) 68 | t.end() 69 | }) 70 | 71 | test('sync: removes everything from an existing directory', t => { 72 | const dir = path.join(tempy.directory(), 'empty') 73 | fs.mkdirSync(path.join(dir)) 74 | const filePath = path.join(dir, 'file') 75 | fs.writeFileSync(filePath, '', 'utf8') 76 | t.equal(makeEmptyDir.sync(dir), 'emptied') 77 | t.ok(fs.existsSync(dir)) 78 | t.notOk(fs.existsSync(filePath)) 79 | t.end() 80 | }) 81 | -------------------------------------------------------------------------------- /p-map-values/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /p-map-values/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /p-map-values/README.md: -------------------------------------------------------------------------------- 1 | # p-map-values 2 | 3 | > A function similar to lodash.mapValues or Ramda.mapObjIndexed, but for async functions 4 | 5 | ## Installation 6 | 7 | ``` 8 | pnpm add p-map-values 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```ts 14 | import pMapValues from 'p-map-values' 15 | 16 | const users = { 17 | fred: { id: 1 }, 18 | pebbles: { id: 2 }, 19 | } 20 | 21 | pMapValues(async (user) => await fetchUserFromDB(user.id), users) 22 | // => { fred: { age: 40 }, pebbles: { age: 1 } } 23 | ``` 24 | 25 | ## License 26 | 27 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 28 | -------------------------------------------------------------------------------- /p-map-values/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import pMapValues from '../src' 2 | 3 | test('pMapValues', async () => { 4 | expect(await pMapValues(async (value: number) => value * 2, {a: 1, b: 2})).toEqual({a: 2, b: 4}) 5 | }) 6 | -------------------------------------------------------------------------------- /p-map-values/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "p-map-values", 3 | "version": "0.0.0", 4 | "description": "A function similar to lodash.mapValues or Ramda.mapObjIndexed, but for async functions", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "engines": { 8 | "node": ">=14" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "scripts": { 14 | "test": "jest", 15 | "tsc": "tsc", 16 | "prepublishOnly": "pnpm run tsc" 17 | }, 18 | "repository": "https://github.com/zkochan/packages/tree/main/p-map-values", 19 | "keywords": [], 20 | "author": { 21 | "name": "Zoltan Kochan", 22 | "email": "z@kochan.io" 23 | }, 24 | "license": "MIT", 25 | "homepage": "https://github.com/zkochan/packages/tree/main/p-map-values#readme", 26 | "devDependencies": { 27 | "@types/jest": "^27.5.2", 28 | "jest": "^27.5.1", 29 | "ts-jest": "^27.1.5", 30 | "typescript": "^4.9.5" 31 | }, 32 | "jest": { 33 | "preset": "ts-jest", 34 | "testEnvironment": "node" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /p-map-values/src/index.ts: -------------------------------------------------------------------------------- 1 | export default async function pMapValue ( 2 | mapper: (value: V, key: K, obj: Record) => Promise, 3 | obj: Record 4 | ): Promise> { 5 | const result: Record = {} as Record 6 | await Promise.all( 7 | Object.entries(obj).map(async ([key, value]: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any 8 | result[key] = await mapper(value, key, obj) 9 | }) 10 | ) 11 | return result 12 | } 13 | 14 | -------------------------------------------------------------------------------- /p-map-values/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "noImplicitAny": true, 9 | "noImplicitReturns": true, 10 | "outDir": "lib", 11 | "preserveConstEnums": true, 12 | "removeComments": false, 13 | "sourceMap": true, 14 | "strictNullChecks": true, 15 | "suppressImplicitAnyIndexErrors": true, 16 | "target": "es2017" 17 | }, 18 | "include": [ 19 | "src/**/*.ts" 20 | ], 21 | "atom": { 22 | "rewriteTsconfig": true 23 | }, 24 | "types": [ 25 | "jest" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageManager": "pnpm@10.10.0", 3 | "devDependencies": { 4 | "@changesets/cli": "^2.29.2", 5 | "typescript": "^4.9.5" 6 | }, 7 | "private": true 8 | } 9 | -------------------------------------------------------------------------------- /path-absolute/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /path-absolute/README.md: -------------------------------------------------------------------------------- 1 | # path-absolute 2 | 3 | > Resolves a path to an absolute path. Supports tilde 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/path-absolute.svg)](https://www.npmjs.com/package/path-absolute) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add path-absolute 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const pathAbsolute = require('path-absolute') 19 | 20 | pathAbsolute('~/foo') 21 | //> '/home/zkochan/foo' 22 | 23 | pathAbsolute('/foo/bar') 24 | //> '/foo/bar' 25 | 26 | pathAbsolute('./foo/bar', '/home') 27 | //> '/home/foo/bar' 28 | ``` 29 | 30 | ## API 31 | 32 | ### `pathAbsolute(path, [cwd]): string` 33 | 34 | Resolves a path to an absolute path 35 | 36 | ## License 37 | 38 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 39 | -------------------------------------------------------------------------------- /path-absolute/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'path-absolute' { 2 | export = pathAbsolute; 3 | 4 | function pathAbsolute (filepath: string, cwd?: string): string; 5 | } 6 | -------------------------------------------------------------------------------- /path-absolute/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const os = require('os') 3 | const path = require('path') 4 | 5 | module.exports = function (filepath, cwd) { 6 | const home = getHomedir() 7 | 8 | if (isHomepath(filepath)) { 9 | return path.join(home, filepath.substr(2)) 10 | } 11 | if (path.isAbsolute(filepath)) { 12 | return filepath 13 | } 14 | if (cwd) { 15 | return path.join(cwd, filepath) 16 | } 17 | return path.resolve(filepath) 18 | } 19 | 20 | function getHomedir () { 21 | const home = os.homedir() 22 | if (!home) throw new Error('Could not find the homedir') 23 | return home 24 | } 25 | 26 | function isHomepath (filepath) { 27 | return filepath.indexOf('~/') === 0 || filepath.indexOf('~\\') === 0 28 | } 29 | -------------------------------------------------------------------------------- /path-absolute/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "path-absolute", 3 | "version": "1.0.1", 4 | "description": "Resolves a path to an absolute path. Supports tilde", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard" 13 | }, 14 | "repository": "https://github.com/zkochan/packages/tree/main/path-absolute", 15 | "keywords": [ 16 | "path", 17 | "absolute", 18 | "tilde" 19 | ], 20 | "author": { 21 | "name": "Zoltan Kochan", 22 | "email": "z@kochan.io", 23 | "url": "https://kochan.io/" 24 | }, 25 | "engines": { 26 | "node": ">=4" 27 | }, 28 | "license": "MIT", 29 | "homepage": "https://github.com/zkochan/packages/tree/main/path-absolute#readme", 30 | "devDependencies": { 31 | "standard": "^16.0.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /path-temp/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2023 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /path-temp/README.md: -------------------------------------------------------------------------------- 1 | # path-temp 2 | 3 | > Returns a unique temp file name inside the specified folder 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/path-temp.svg)](https://www.npmjs.com/package/path-temp) 7 | 8 | 9 | Useful when there's a need to do atomic operations. The temp name contains the 10 | process ID. 11 | 12 | ## Installation 13 | 14 | ```sh 15 | add path-temp 16 | ``` 17 | 18 | ## Usage 19 | 20 | ```js 21 | const pathTemp = require('path-temp') 22 | 23 | console.log(pathTemp(process.cwd())) 24 | //> "/home/zkochan/src/path-temp/_tmp_17230_cf3396bb9fddb8ebb30807366facf123" 25 | ``` 26 | 27 | ## License 28 | 29 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 30 | -------------------------------------------------------------------------------- /path-temp/index.d.ts: -------------------------------------------------------------------------------- 1 | declare function pathTemp(folder: string): string 2 | 3 | declare namespace pathTemp { 4 | function fastPathTemp(file: string): string 5 | } 6 | 7 | export = pathTemp 8 | 9 | -------------------------------------------------------------------------------- /path-temp/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const uniqueString = require('unique-string') 4 | 5 | module.exports = function pathTemp (folder) { 6 | return path.join(folder, `_tmp_${process.pid}_${uniqueString()}`) 7 | } 8 | 9 | module.exports.fastPathTemp = function pathTempFast (file) { 10 | return path.join(path.dirname(file), `${path.basename(file)}_tmp_${process.pid}`) 11 | } 12 | -------------------------------------------------------------------------------- /path-temp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "path-temp", 3 | "version": "2.1.0", 4 | "description": "Returns a unique temp file name inside the specified folder", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && node test", 13 | "md": "mos" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/path-temp", 16 | "keywords": [ 17 | "path", 18 | "temp", 19 | "unique" 20 | ], 21 | "engines": { 22 | "node": ">=8.15" 23 | }, 24 | "author": "Zoltan Kochan (https://www.kochan.io/)", 25 | "license": "MIT", 26 | "homepage": "https://github.com/zkochan/packages/tree/main/path-temp#readme", 27 | "dependenciesMeta": { 28 | "path-temp": { 29 | "injected": true 30 | } 31 | }, 32 | "dependencies": { 33 | "unique-string": "^2.0.0" 34 | }, 35 | "devDependencies": { 36 | "mos": "2.0.0-alpha.3", 37 | "mos-plugin-readme": "^1.0.4", 38 | "path-temp": "file:", 39 | "standard": "^16.0.4", 40 | "tape": "^5.9.0" 41 | }, 42 | "mos": { 43 | "plugins": [ 44 | "readme" 45 | ], 46 | "installation": { 47 | "useShortAlias": true 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /path-temp/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const pathTemp = require('path-temp') 4 | const test = require('tape') 5 | 6 | test('pathTemp', t => { 7 | t.equal(typeof pathTemp(process.cwd()), 'string') 8 | t.end() 9 | }) 10 | 11 | test('fastPathTemp', t => { 12 | t.equal(pathTemp.fastPathTemp(path.resolve('foo.txt')), path.resolve(`foo.txt_tmp_${process.pid}`)) 13 | t.end() 14 | }) 15 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - '**' 3 | - '!**/test/**' 4 | - '!resolve-link-target/node_modules_link/**' 5 | configDependencies: 6 | '@pnpm/better-defaults': 0.2.0+sha512-90iZf6xgZTlNuUVn5djvCXM720TgZrYmmb8jmjIv5c5efx3I46rmCcT2j5nlZJ6VrvghNgUaI2y/rnHe2W4L6g== 7 | ignoredBuiltDependencies: 8 | - core-js 9 | onlyBuiltDependencies: 10 | - '@pnpm/exe' 11 | - bun 12 | - yarn 13 | overrides: 14 | '@types/node': 14.14.6 15 | pnpmfile: node_modules/.pnpm-config/@pnpm/better-defaults/pnpmfile.cjs 16 | -------------------------------------------------------------------------------- /preferred-pm/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # preferred-pm 2 | 3 | ## 3.1.4 4 | 5 | - Update which-pm 6 | 7 | ## 3.0.3 8 | 9 | ### Patch Changes 10 | 11 | - 094cecc: Fix types. 12 | 13 | ## 3.0.2 14 | 15 | ### Patch Changes 16 | 17 | - 17d5363: Update find-up to v5. 18 | 19 | ## 3.0.1 20 | 21 | ### Patch Changes 22 | 23 | - f9c6c94: Pin find-yarn-workspace-root2 to version 1.2.16. Newer versions of the package have @types/node in peer dependencies. 24 | 25 | ## 3.0.0 26 | 27 | ### Major Changes 28 | 29 | - 49172aa: Dropped support of Node.js<10. 30 | 31 | ### Minor Changes 32 | 33 | - d50a9b7: Detects a pnpm workspace. 34 | - cec674b: Add types. 35 | - 727f01a: Yarn is the preferred package manager inside a Yarn workspace. 36 | -------------------------------------------------------------------------------- /preferred-pm/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-2025 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /preferred-pm/README.md: -------------------------------------------------------------------------------- 1 | # preferred-pm 2 | 3 | > Returns the preferred package manager of a project 4 | 5 | [![npm version](https://img.shields.io/npm/v/preferred-pm.svg)](https://www.npmjs.com/package/preferred-pm) 6 | 7 | * Inside a Yarn workspace, Yarn is preferred. 8 | * Inside a pnpm workspace, pnpm is preferred. 9 | * If a `package-lock.json` is present, npm is preferred. 10 | * If a `yarn.lock` is present, Yarn is preferred. 11 | * If a `pnpm-lock.yaml` is present, pnpm is preferred. 12 | * If a `bun.lockb` is present, Bun is preferred. 13 | * If a `node_modules` is present, tries to detect which package manager installed it. 14 | 15 | ## Installation 16 | 17 | ``` 18 | add preferred-pm 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```js 24 | 'use strict' 25 | const preferredPM = require('preferred-pm') 26 | 27 | preferredPM(process.cwd()) 28 | .then(pm => console.log(pm)) 29 | //> {name: "npm", version: ">=5"} 30 | ``` 31 | 32 | ## Related 33 | 34 | * [which-pm](https://github.com/zkochan/packages/tree/main/which-pm) - Detects what package manager was used for installation 35 | * [which-pm-runs](https://github.com/zkochan/packages/tree/main/which-pm-runs) - Detects what package manager executes the process 36 | 37 | ## License 38 | 39 | [MIT](LICENSE) © [Zoltan Kochan](https://kochan.io) 40 | -------------------------------------------------------------------------------- /preferred-pm/index.d.ts: -------------------------------------------------------------------------------- 1 | export = preferredPM 2 | 3 | declare function preferredPM (pkgPath: string): Promise<{ name: 'npm' | 'pnpm' | 'yarn' | 'bun', version: string } | null> 4 | -------------------------------------------------------------------------------- /preferred-pm/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const findYarnWorkspaceRoot = require('find-yarn-workspace-root2') 3 | const fs = require('fs') 4 | const path = require('path') 5 | const whichPM = require('which-pm') 6 | 7 | module.exports = async function preferredPM (pkgPath) { 8 | if (typeof pkgPath !== 'string') { 9 | throw new TypeError(`pkgPath should be a string, got ${typeof pkgPath}`) 10 | } 11 | if (fs.existsSync(path.join(pkgPath, 'package-lock.json'))) { 12 | return { 13 | name: 'npm', 14 | version: '>=5' 15 | } 16 | } 17 | if (fs.existsSync(path.join(pkgPath, 'yarn.lock'))) { 18 | return { 19 | name: 'yarn', 20 | version: '*' 21 | } 22 | } 23 | if (fs.existsSync(path.join(pkgPath, 'pnpm-lock.yaml'))) { 24 | return { 25 | name: 'pnpm', 26 | version: '>=3' 27 | } 28 | } 29 | if (fs.existsSync(path.join(pkgPath, 'shrinkwrap.yaml'))) { 30 | return { 31 | name: 'pnpm', 32 | version: '1 || 2' 33 | } 34 | } 35 | if (fs.existsSync(path.join(pkgPath, 'bun.lockb')) || fs.existsSync(path.join(pkgPath, 'bun.lock'))) { 36 | return { 37 | name: 'bun', 38 | version: '*' 39 | } 40 | } 41 | const { findUp } = await import('find-up-simple') 42 | if (await findUp('pnpm-lock.yaml', { cwd: pkgPath })) { 43 | return { 44 | name: 'pnpm', 45 | version: '>=3' 46 | } 47 | } 48 | try { 49 | const workspaceRoot = findYarnWorkspaceRoot(pkgPath) 50 | if (typeof workspaceRoot === 'string') { 51 | if (fs.existsSync(path.join(workspaceRoot, 'package-lock.json'))) { 52 | return { 53 | name: 'npm', 54 | version: '>=7' 55 | } 56 | } 57 | return { 58 | name: 'yarn', 59 | version: '*' 60 | } 61 | } 62 | } catch (err) {} 63 | const pm = await whichPM(pkgPath) 64 | return pm && { name: pm.name, version: pm.version || '*' } 65 | } 66 | -------------------------------------------------------------------------------- /preferred-pm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "preferred-pm", 3 | "version": "4.1.1", 4 | "description": "Detects what package manager was used for installation", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "scripts": { 11 | "test": "standard && node test" 12 | }, 13 | "engines": { 14 | "node": ">=18.12" 15 | }, 16 | "repository": "https://github.com/zkochan/packages/tree/main/preferred-pm", 17 | "bugs": { 18 | "url": "https://github.com/zkochan/packages/labels/package%3A%20preferred-pm" 19 | }, 20 | "keywords": [ 21 | "npm", 22 | "pnpm", 23 | "yarn" 24 | ], 25 | "author": { 26 | "name": "Zoltan Kochan", 27 | "email": "z@kochan.io", 28 | "url": "https://www.kochan.io/" 29 | }, 30 | "license": "MIT", 31 | "dependenciesMeta": { 32 | "preferred-pm": { 33 | "injected": true 34 | } 35 | }, 36 | "dependencies": { 37 | "find-up-simple": "^1.0.1", 38 | "find-yarn-workspace-root2": "1.2.16", 39 | "which-pm": "workspace:^" 40 | }, 41 | "devDependencies": { 42 | "ncp": "^2.0.0", 43 | "preferred-pm": "file:", 44 | "standard": "^16.0.4", 45 | "tape": "^5.9.0", 46 | "tempy": "^1.0.1" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /preferred-pm/test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const ncpcb = require('ncp') 3 | const test = require('tape') 4 | const path = require('path') 5 | const preferredPM = require('preferred-pm') 6 | const tempy = require('tempy') 7 | const { promisify } = require('util') 8 | 9 | const ncp = promisify(ncpcb) 10 | 11 | test('preferredPM()', async t => { 12 | t.plan(2) 13 | try { 14 | await preferredPM() 15 | } catch (err) { 16 | t.equal(err.message, 'pkgPath should be a string, got undefined') 17 | } 18 | try { 19 | await preferredPM(1) 20 | } catch (err) { 21 | t.equal(err.message, 'pkgPath should be a string, got number') 22 | } 23 | t.end() 24 | }) 25 | 26 | test('prefer pnpm 1 or 2', async t => { 27 | const pm = await preferredPM(path.join(__dirname, 'prefers-pnpm-1-or-2')) 28 | t.deepEqual(pm, { name: 'pnpm', version: '1 || 2' }) 29 | t.end() 30 | }) 31 | 32 | test('prefer pnpm', async t => { 33 | const pm = await preferredPM(path.join(__dirname, 'prefers-pnpm')) 34 | t.deepEqual(pm, { name: 'pnpm', version: '>=3' }) 35 | t.end() 36 | }) 37 | 38 | test('prefer pnpm inside a pnpm workspace', async t => { 39 | const pm = await preferredPM(path.join(__dirname, 'pnpm-workspace/packages/pkg')) 40 | t.deepEqual(pm, { name: 'pnpm', version: '>=3' }) 41 | t.end() 42 | }) 43 | 44 | test('prefer Yarn', async t => { 45 | const pm = await preferredPM(path.join(__dirname, 'prefers-yarn')) 46 | t.deepEqual(pm, { name: 'yarn', version: '*' }) 47 | t.end() 48 | }) 49 | 50 | test('prefer Yarn inside a Yarn workspace', async t => { 51 | const dir = tempy.directory() 52 | await ncp(path.join(__dirname, 'yarn-workspace'), dir) 53 | const pm = await preferredPM(path.join(dir, 'packages/pkg')) 54 | t.deepEqual(pm, { name: 'yarn', version: '*' }) 55 | t.end() 56 | }) 57 | 58 | test('prefer npm inside an npm workspace', async t => { 59 | const dir = tempy.directory() 60 | await ncp(path.join(__dirname, 'npm-workspace'), dir) 61 | const pm = await preferredPM(path.join(dir, 'packages/pkg')) 62 | t.deepEqual(pm, { name: 'npm', version: '>=7' }) 63 | t.end() 64 | }) 65 | 66 | test('prefer Bun', async t => { 67 | const pm = await preferredPM(path.join(__dirname, 'prefers-bun')) 68 | t.deepEqual(pm, { name: 'bun', version: '*' }) 69 | t.end() 70 | }) 71 | 72 | test('prefer npm 5', async t => { 73 | const pm = await preferredPM(path.join(__dirname, 'prefers-npm-5')) 74 | t.deepEqual(pm, { name: 'npm', version: '>=5' }) 75 | t.end() 76 | }) 77 | 78 | test('prefer npm', async t => { 79 | const dir = tempy.directory() 80 | await ncp(path.join(__dirname, 'prefers-npm'), dir) 81 | const pm = await preferredPM(dir) 82 | t.deepEqual(pm, { name: 'npm', version: '*' }) 83 | t.end() 84 | }) 85 | 86 | test('prefer nothing', async t => { 87 | const dir = tempy.directory() 88 | await ncp(path.join(__dirname, 'prefers-nothing'), dir) 89 | const pm = await preferredPM(dir) 90 | t.equal(pm, null) 91 | t.end() 92 | }) 93 | -------------------------------------------------------------------------------- /preferred-pm/test/npm-workspace/package-lock.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/npm-workspace/package-lock.json -------------------------------------------------------------------------------- /preferred-pm/test/npm-workspace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/*" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /preferred-pm/test/npm-workspace/packages/pkg/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /preferred-pm/test/pnpm-workspace/packages/pkg/package.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/pnpm-workspace/packages/pkg/package.json -------------------------------------------------------------------------------- /preferred-pm/test/pnpm-workspace/pnpm-workspace.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/pnpm-workspace/pnpm-workspace.yaml -------------------------------------------------------------------------------- /preferred-pm/test/prefers-bun/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-bun/bun.lockb -------------------------------------------------------------------------------- /preferred-pm/test/prefers-nothing/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-nothing/.gitkeep -------------------------------------------------------------------------------- /preferred-pm/test/prefers-npm-5/package-lock.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-npm-5/package-lock.json -------------------------------------------------------------------------------- /preferred-pm/test/prefers-npm/.gitignore: -------------------------------------------------------------------------------- 1 | !node_modules 2 | -------------------------------------------------------------------------------- /preferred-pm/test/prefers-npm/node_modules/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-npm/node_modules/.gitkeep -------------------------------------------------------------------------------- /preferred-pm/test/prefers-pnpm-1-or-2/shrinkwrap.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-pnpm-1-or-2/shrinkwrap.yaml -------------------------------------------------------------------------------- /preferred-pm/test/prefers-pnpm/pnpm-lock.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-pnpm/pnpm-lock.yaml -------------------------------------------------------------------------------- /preferred-pm/test/prefers-yarn/yarn.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/preferred-pm/test/prefers-yarn/yarn.lock -------------------------------------------------------------------------------- /preferred-pm/test/yarn-workspace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/*" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /preferred-pm/test/yarn-workspace/packages/pkg/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /promise-share/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /promise-share/README.md: -------------------------------------------------------------------------------- 1 | # promise-share 2 | 3 | > Creates a getter function for a promise result 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/promise-share.svg)](https://www.npmjs.com/package/promise-share) 7 | 8 | 9 | Helps to avoid *UnhandledPromiseRejectionWarning*. 10 | If you need to export a result as a promise, use this function to wrap the promise. 11 | When you'll need the result of the promise, run the function. 12 | 13 | ## Installation 14 | 15 | ```sh 16 | add promise-share 17 | ``` 18 | 19 | ## Usage 20 | 21 | ```js 22 | 'use strict' 23 | const promiseShare = require('promise-share') 24 | 25 | const file = promiseShare(readFileAsync()) 26 | 27 | console.log(await file()) 28 | //> file content 29 | ``` 30 | 31 | ## License 32 | 33 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 34 | -------------------------------------------------------------------------------- /promise-share/index.d.ts: -------------------------------------------------------------------------------- 1 | declare function pShare (p: Promise): () => Promise 2 | 3 | export = pShare 4 | -------------------------------------------------------------------------------- /promise-share/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const pReflect = require('p-reflect') 3 | 4 | module.exports = function pShare (p) { 5 | const reflected = pReflect(p) 6 | return async () => { 7 | const reflection = await reflected 8 | if (reflection.isRejected) throw reflection.reason 9 | return reflection.value 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /promise-share/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "promise-share", 3 | "version": "1.0.0", 4 | "description": "Creates a getter function for a promise result", 5 | "files": [ 6 | "index.js", 7 | "index.d.ts" 8 | ], 9 | "scripts": { 10 | "test": "node test" 11 | }, 12 | "engines": { 13 | "node": ">=8" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/promise-share", 16 | "keywords": [ 17 | "promise" 18 | ], 19 | "author": { 20 | "name": "Zoltan Kochan", 21 | "url": "https://www.kochan.io" 22 | }, 23 | "license": "MIT", 24 | "homepage": "https://github.com/zkochan/packages/tree/main/promise-share#readme", 25 | "devDependencies": { 26 | "tape": "^5.9.0" 27 | }, 28 | "dependencies": { 29 | "p-reflect": "^2.1.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /promise-share/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const test = require('tape') 3 | 4 | const pShare = require('.') 5 | 6 | test('pShare() success', async (t) => { 7 | const getValue = pShare(Promise.resolve(1)) 8 | 9 | t.equal(await getValue(), 1) 10 | t.equal(await getValue(), 1) 11 | 12 | t.end() 13 | }) 14 | 15 | test('pShare() fail', async (t) => { 16 | t.plan(2) 17 | const getValue = pShare(Promise.reject(new Error('foo'))) 18 | 19 | try { 20 | t.equal(await getValue(), 1) 21 | } catch (err) { 22 | t.equal(err.message, 'foo') 23 | } 24 | try { 25 | t.equal(await getValue(), 1) 26 | } catch (err) { 27 | t.equal(err.message, 'foo') 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /read-ini-file/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # read-ini-file 2 | 3 | ## 4.0.0 4 | 5 | ### Breaking Changes 6 | 7 | - Node.js 14 is required 8 | 9 | ## 3.1.0 10 | 11 | ### Minor Changes 12 | 13 | - bba9985: graceful-fs and mz removed from dependencies. 14 | - Breaking Change: `readIniFile.sync` changes to `readIniFileSync` 15 | - Breaking Change: `import readIniFile` changes to `import { readIniFile, readIniFileSync }` (where you choose what you use) 16 | 17 | ## 3.0.1 18 | 19 | ### Patch Changes 20 | 21 | - 68010ea: Use util.promisify instead of the pify library. 22 | - 01c2324: Update ini to version 2. 23 | -------------------------------------------------------------------------------- /read-ini-file/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /read-ini-file/README.md: -------------------------------------------------------------------------------- 1 | # read-ini-file 2 | 3 | > Read and parse an ini file 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/read-ini-file.svg)](https://www.npmjs.com/package/read-ini-file) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | pnpm add read-ini-file 13 | ``` 14 | 15 | ## Usage 16 | 17 | 18 | ```js 19 | 'use strict' 20 | const { readIniFile } = require('read-ini-file') 21 | const path = require('path') 22 | 23 | const fixture = path.join(__dirname, 'currencies.ini') 24 | const currencies = loadIniFile.sync(fixture) 25 | console.log(currencies) 26 | //> { USA: 'USD', Ukraine: 'UAH', Hungary: 'HUF' } 27 | ``` 28 | 29 | 30 | ## API 31 | 32 | ### `readIniFile(filepath)` 33 | 34 | Returns a promise for the parsed ini. 35 | 36 | ### `readIniFileSync(filepath)` 37 | 38 | Returns the parsed ini. 39 | 40 | ## Related 41 | 42 | - [write-ini-file](https://github.com/zkochan/write-ini-file) - Stringify and write ini to a file atomically 43 | - [ini](https://github.com/npm/ini) - An ini parser/serializer in JavaScript 44 | 45 | ## License 46 | 47 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 48 | -------------------------------------------------------------------------------- /read-ini-file/example/currencies.ini: -------------------------------------------------------------------------------- 1 | USA = USD 2 | Ukraine = UAH 3 | Hungary = HUF 4 | -------------------------------------------------------------------------------- /read-ini-file/example/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const loadIniFile = require('..') 3 | const path = require('path') 4 | 5 | const fixture = path.join(__dirname, 'currencies.ini') 6 | const currencies = loadIniFile.sync(fixture) 7 | console.log(currencies) 8 | -------------------------------------------------------------------------------- /read-ini-file/index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace readIniFile { 2 | function readIniFile (filePath: string): Promise 3 | function readIniFileSync (filePath: string): Object 4 | } 5 | 6 | export = readIniFile 7 | 8 | -------------------------------------------------------------------------------- /read-ini-file/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const stripBom = require('strip-bom') 4 | const ini = require('ini') 5 | 6 | const parse = (data) => ini.parse(stripBom(data)) 7 | 8 | module.exports.readIniFile = async function (fp) { 9 | const data = await fs.promises.readFile(fp, 'utf8') 10 | return parse(data) 11 | } 12 | 13 | module.exports.readIniFileSync = fp => parse(fs.readFileSync(fp, 'utf8')) 14 | -------------------------------------------------------------------------------- /read-ini-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "read-ini-file", 3 | "version": "4.0.0", 4 | "description": "Read and parse an ini file", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "scripts": { 11 | "test-readme": "mos t", 12 | "test": "standard && tape test", 13 | "md": "mos" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/read-ini-file", 16 | "mos": { 17 | "plugins": [ 18 | "readme" 19 | ], 20 | "installation": { 21 | "useShortAlias": true 22 | } 23 | }, 24 | "keywords": [ 25 | "read", 26 | "ini", 27 | "parse", 28 | "file", 29 | "fs", 30 | "graceful", 31 | "load" 32 | ], 33 | "author": { 34 | "name": "Zoltan Kochan", 35 | "email": "zoltankochan@gmail.com", 36 | "url": "https://www.kochan.io" 37 | }, 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/zkochan/packages/issues" 41 | }, 42 | "homepage": "https://github.com/zkochan/packages/tree/main/read-ini-file#readme#readme", 43 | "dependenciesMeta": { 44 | "read-ini-file": { 45 | "injected": true 46 | } 47 | }, 48 | "dependencies": { 49 | "ini": "^3.0.1", 50 | "strip-bom": "^4.0.0" 51 | }, 52 | "devDependencies": { 53 | "mos": "2.0.0-alpha.3", 54 | "mos-plugin-readme": "^1.0.4", 55 | "read-ini-file": "file:", 56 | "standard": "^16.0.4", 57 | "tape": "^5.9.0" 58 | }, 59 | "engines": { 60 | "node": ">=14.6" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /read-ini-file/test/fixture.ini: -------------------------------------------------------------------------------- 1 | name = read-ini-file 2 | -------------------------------------------------------------------------------- /read-ini-file/test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const test = require('tape') 4 | const { readIniFile, readIniFileSync } = require('read-ini-file') 5 | 6 | const fixture = path.join(__dirname, 'fixture.ini') 7 | 8 | test('async', t => { 9 | readIniFile(fixture) 10 | .then(data => { 11 | t.equal(data.name, 'read-ini-file') 12 | t.end() 13 | }) 14 | .catch(t.end) 15 | }) 16 | 17 | test('sync', t => { 18 | t.equal(readIniFileSync(fixture).name, 'read-ini-file') 19 | t.end() 20 | }) 21 | -------------------------------------------------------------------------------- /read-json5-file/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # read-json5-file 2 | 3 | ## 1.0.0 4 | ### Major Changes 5 | 6 | - bba9985: Support of Node.js versions older than 10 is dropped. 7 | 8 | ### Minor Changes 9 | 10 | - bba9985: graceful-fs and mz removed from dependencies. 11 | -------------------------------------------------------------------------------- /read-json5-file/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /read-json5-file/README.md: -------------------------------------------------------------------------------- 1 | # read-json5-file 2 | 3 | > Read and parse a JSON5 file 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/read-json5-file.svg)](https://www.npmjs.com/package/read-json5-file) 7 | 8 | 9 | [Strips UTF-8 BOM](https://github.com/sindresorhus/strip-bom) and uses [`graceful-fs`](https://github.com/isaacs/node-graceful-fs). 10 | 11 | ## Installation 12 | 13 | ```sh 14 | add read-json5-file 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```js 20 | 'use strict' 21 | const loadJson5File = require('read-json5-file') 22 | const path = require('path') 23 | 24 | const fixture = path.join(__dirname, 'countries.json5') 25 | const countries = loadJson5File.sync(fixture) 26 | console.log(countries) 27 | //> [ 'Ukraine', 'Hungary', 'Slovakia' ] 28 | ``` 29 | 30 | ## API 31 | 32 | ### `loadJson5File(filepath)` 33 | 34 | Returns a promise for the parsed JSON5. 35 | 36 | ### `loadJson5File.sync(filepath)` 37 | 38 | Returns the parsed JSON5. 39 | 40 | ## Related 41 | 42 | - [write-json5-file](../write-json5-file) - Stringify and write JSON5 to a file atomically 43 | - [load-json-file](https://github.com/sindresorhus/load-json-file) - Read and parse a JSON file 44 | - [json5](https://github.com/json5/json5) - JSON for the ES5 era 45 | 46 | ## License 47 | 48 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 49 | -------------------------------------------------------------------------------- /read-json5-file/example/countries.json5: -------------------------------------------------------------------------------- 1 | [ 2 | 'Ukraine', 3 | 'Hungary', 4 | 'Slovakia', 5 | ] 6 | -------------------------------------------------------------------------------- /read-json5-file/example/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const loadJson5File = require('..') 3 | const path = require('path') 4 | 5 | const fixture = path.join(__dirname, 'countries.json5') 6 | const countries = loadJson5File.sync(fixture) 7 | console.log(countries) 8 | -------------------------------------------------------------------------------- /read-json5-file/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const readJson5File: { 2 | (filePath: string): Promise 3 | sync: (filePath: string) => T 4 | } 5 | 6 | export = readJson5File 7 | -------------------------------------------------------------------------------- /read-json5-file/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const fs = require('fs') 4 | const stripBom = require('strip-bom') 5 | const JSON5 = require('json5') 6 | 7 | const parse = (data, fp) => JSON5.parse(stripBom(data), path.relative('.', fp)) 8 | 9 | module.exports = async fp => { 10 | const data = await fs.promises.readFile(fp, 'utf8') 11 | return parse(data, fp) 12 | } 13 | 14 | module.exports.sync = fp => parse(fs.readFileSync(fp, 'utf8'), fp) 15 | -------------------------------------------------------------------------------- /read-json5-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "read-json5-file", 3 | "version": "1.0.0", 4 | "description": "Read and parse a JSON5 file", 5 | "main": "index.js", 6 | "engines": { 7 | "node": ">=10" 8 | }, 9 | "files": [ 10 | "index.js", 11 | "index.d.ts" 12 | ], 13 | "scripts": { 14 | "test": "standard && tape test", 15 | "md": "mos" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/read-json5-file", 18 | "mos": { 19 | "plugins": [ 20 | "readme" 21 | ], 22 | "installation": { 23 | "useShortAlias": true 24 | } 25 | }, 26 | "keywords": [ 27 | "read", 28 | "JSON5", 29 | "parse", 30 | "file", 31 | "fs", 32 | "graceful", 33 | "load" 34 | ], 35 | "author": { 36 | "name": "Zoltan Kochan", 37 | "email": "z@kochan.io", 38 | "url": "https://www.kochan.io" 39 | }, 40 | "license": "MIT", 41 | "homepage": "https://github.com/zkochan/packages/tree/main/read-json5-file#readme", 42 | "dependencies": { 43 | "json5": "^2.2.3", 44 | "strip-bom": "^4.0.0" 45 | }, 46 | "devDependencies": { 47 | "mos": "2.0.0-alpha.3", 48 | "mos-plugin-readme": "^1.0.4", 49 | "standard": "^16.0.4", 50 | "tape": "^5.9.0" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /read-json5-file/test/fixture.json5: -------------------------------------------------------------------------------- 1 | { 2 | name: 'load-json5-file', 3 | } 4 | -------------------------------------------------------------------------------- /read-json5-file/test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const test = require('tape') 4 | const readJson5File = require('..') 5 | 6 | const fixture = path.join(__dirname, 'fixture.json5') 7 | 8 | test('async', async t => { 9 | const data = await readJson5File(fixture) 10 | t.equal(data.name, 'load-json5-file') 11 | t.end() 12 | }) 13 | 14 | test('sync', t => { 15 | t.equal(readJson5File.sync(fixture).name, 'load-json5-file') 16 | t.end() 17 | }) 18 | -------------------------------------------------------------------------------- /read-yaml-file/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # read-yaml-file 2 | 3 | ## 2.1.0 4 | 5 | ### Minor Changes 6 | 7 | - bba9985: graceful-fs and mz removed from dependencies. 8 | 9 | ## 2.0.1 10 | 11 | ### Patch Changes 12 | 13 | - 68010ea: Use util.promisify instead of the pify library. 14 | - 5f01634: Update js-yaml to version 4. 15 | -------------------------------------------------------------------------------- /read-yaml-file/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /read-yaml-file/README.md: -------------------------------------------------------------------------------- 1 | # read-yaml-file 2 | 3 | > Read and parse a YAML file 4 | 5 | [![npm version](https://img.shields.io/npm/v/read-yaml-file.svg)](https://www.npmjs.com/package/read-yaml-file) 6 | 7 | ## Installation 8 | 9 | ```sh 10 | add read-yaml-file 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const readYamlFile = require('read-yaml-file') 17 | 18 | readYamlFile('foo.yml').then(data => { 19 | console.log(data) 20 | //=> {foo: true} 21 | }) 22 | ``` 23 | 24 | ## API 25 | 26 | ### readYamlFile(filepath) 27 | 28 | Returns a promise for the parsed YAML. 29 | 30 | ### readYamlFile.sync(filepath) 31 | 32 | Returns the parsed YAML. 33 | 34 | ## Related 35 | 36 | - [write-yaml-file](https://github.com/zkochan/packages/tree/main/write-yaml-file) - Stringify and write YAML to a file atomically 37 | 38 | ## License 39 | 40 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 41 | 42 | *** 43 | 44 | This package was forked from [load-yaml-file](https://github.com/LinusU/load-yaml-file) 45 | -------------------------------------------------------------------------------- /read-yaml-file/foo.yml: -------------------------------------------------------------------------------- 1 | foo: true 2 | -------------------------------------------------------------------------------- /read-yaml-file/index.d.ts: -------------------------------------------------------------------------------- 1 | export function sync(filePath: string): T 2 | 3 | export default function readYamlFile(filePath: string): Promise 4 | -------------------------------------------------------------------------------- /read-yaml-file/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | const stripBom = require('strip-bom') 5 | const yaml = require('js-yaml') 6 | 7 | const parse = data => yaml.load(stripBom(data)) 8 | 9 | const readYamlFile = fp => fs.promises.readFile(fp, 'utf8').then(data => parse(data)) 10 | 11 | module.exports = readYamlFile 12 | module.exports.default = readYamlFile 13 | module.exports.sync = fp => parse(fs.readFileSync(fp, 'utf8')) 14 | -------------------------------------------------------------------------------- /read-yaml-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "read-yaml-file", 3 | "version": "2.1.0", 4 | "license": "MIT", 5 | "main": "index.js", 6 | "description": "Read and parse a YAML file", 7 | "keywords": [ 8 | "yaml", 9 | "read" 10 | ], 11 | "author": { 12 | "name": "Zoltan Kochan", 13 | "email": "z@kochan.io" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/read-yaml-file", 16 | "engines": { 17 | "node": ">=10.13" 18 | }, 19 | "files": [ 20 | "index.js", 21 | "index.d.ts" 22 | ], 23 | "scripts": { 24 | "test": "standard && node test" 25 | }, 26 | "dependenciesMeta": { 27 | "read-yaml-file": { 28 | "injected": true 29 | } 30 | }, 31 | "dependencies": { 32 | "js-yaml": "^4.1.0", 33 | "strip-bom": "^4.0.0" 34 | }, 35 | "devDependencies": { 36 | "read-yaml-file": "file:", 37 | "standard": "^16.0.4", 38 | "tape": "^5.9.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /read-yaml-file/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const readYamlFile = require('read-yaml-file') 4 | 5 | test('readYamlFile()', (t) => { 6 | return readYamlFile('foo.yml').then(data => { 7 | t.deepEqual(data, { foo: true }) 8 | t.end() 9 | }) 10 | }) 11 | 12 | test('readYamlFile.sync()', (t) => { 13 | const data = readYamlFile.sync('foo.yml') 14 | t.deepEqual(data, { foo: true }) 15 | t.end() 16 | }) 17 | -------------------------------------------------------------------------------- /realpath-missing/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # realpath-missing 2 | 3 | ## 1.1.0 4 | ### Minor Changes 5 | 6 | - bba9985: graceful-fs and mz removed from dependencies. 7 | -------------------------------------------------------------------------------- /realpath-missing/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /realpath-missing/README.md: -------------------------------------------------------------------------------- 1 | # realpath-missing 2 | 3 | > `realpath-missing` resolves the absolute path of a file or directory by following every symbolic link in every component of the given name recursively, even if some of the components do not exist. 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/realpath-missing.svg)](https://www.npmjs.com/package/realpath-missing) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add realpath-missing 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | 'use strict' 19 | const realpathMissing = require('realpath-missing') 20 | 21 | console.log(await realpathMissing('package.json')) 22 | //> /home/src/package.json 23 | ``` 24 | 25 | ## API 26 | 27 | ### `realpathMissing(path): Promise` 28 | 29 | ## License 30 | 31 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 32 | -------------------------------------------------------------------------------- /realpath-missing/index.d.ts: -------------------------------------------------------------------------------- 1 | export = realpathMissing 2 | 3 | declare function realpathMissing (path: string): Promise 4 | -------------------------------------------------------------------------------- /realpath-missing/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | module.exports = async function realpathMissing (path) { 4 | try { 5 | return await fs.promises.realpath(path) 6 | } catch (err) { 7 | if (err.code === 'ENOENT') { 8 | return path 9 | } 10 | throw err 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /realpath-missing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "realpath-missing", 3 | "version": "1.1.0", 4 | "description": "Canonicalize by following every symlink in every component of the given name recursively, without requirements on components existence", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "scripts": { 11 | "test": "node test" 12 | }, 13 | "engines": { 14 | "node": ">=10" 15 | }, 16 | "repository": "https://github.com/zkochan/packages/tree/main/realpath-missing", 17 | "keywords": [], 18 | "author": { 19 | "name": "Zoltan Kochan", 20 | "url": "https://www.kochan.io" 21 | }, 22 | "license": "MIT", 23 | "homepage": "https://github.com/zkochan/packages/tree/main/realpath-missing#readme", 24 | "devDependencies": { 25 | "tape": "^5.9.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /realpath-missing/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const realpathMissing = require('.') 4 | 5 | test('realpathMissing()', async t => { 6 | t.equal(typeof await realpathMissing('package.json'), 'string') 7 | t.equal(typeof await realpathMissing('missing-file'), 'string') 8 | 9 | t.end() 10 | }) 11 | -------------------------------------------------------------------------------- /rename-overwrite/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # rename-overwrite 2 | 3 | ## 6.0.2 4 | 5 | ### Patch Changes 6 | 7 | - 574a558: Only import the exported files from fs-extra. 8 | 9 | ## 6.0.1 10 | 11 | ### Patch Changes 12 | 13 | - 2af185a: Update fs-extra to v11. 14 | 15 | ## 5.0.3 16 | 17 | ### Patch Changes 18 | 19 | - Updated dependencies [b70f4a9] 20 | - @zkochan/rimraf@3.0.2 21 | 22 | ## 5.0.1 23 | 24 | ### Patch Changes 25 | 26 | - Updated dependencies [3fa8bea] 27 | - @zkochan/rimraf@3.0.0 28 | 29 | ## 5.0.0 30 | 31 | - Sync rename overwrite locks up the process to wait and retry rename again. 32 | 33 | ## 4.0.4 34 | 35 | ### Patch Changes 36 | 37 | - Retry on EPERM errors. 38 | 39 | ## 4.0.3 40 | 41 | ### Patch Changes 42 | 43 | - 0300ee6: Support moving files and directories across devices. 44 | 45 | ## 4.0.2 46 | 47 | ### Patch Changes 48 | 49 | - 2fd2422: Limit the number of retries. 50 | - Updated dependencies [1d97370] 51 | - @zkochan/rimraf@2.1.2 52 | 53 | ## 4.0.1 54 | 55 | ### Patch Changes 56 | 57 | - d36ad80: If the target file is a symlink, override it. 58 | 59 | ## 4.0.0 60 | 61 | ### Breaking Changes 62 | 63 | - Drop Node.js 10 support 64 | 65 | ## 3.1.0 66 | 67 | ### Minor Changes 68 | 69 | - bba9985: graceful-fs and mz removed from dependencies. 70 | 71 | ## 3.0.0 72 | 73 | ### Major Changes 74 | 75 | - 7624a45: Drop Node.js 8 support. 76 | 77 | ### Minor Changes 78 | 79 | - b0e76c1: Add TypeScript types. 80 | 81 | ### Patch Changes 82 | 83 | - 2dde4bf: If the target parent directory does not exist, create it. 84 | -------------------------------------------------------------------------------- /rename-overwrite/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2024 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rename-overwrite/README.md: -------------------------------------------------------------------------------- 1 | # rename-overwrite 2 | 3 | > Like `fs.rename` but overwrites existing file or directory 4 | 5 | ## Install 6 | 7 | Install it via npm. 8 | 9 | ``` 10 | add rename-overwrite 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const renameOverwrite = require('rename-overwrite') 17 | 18 | renameOverwrite('old-dir-name', 'new-dir-name') 19 | .then(() => console.log('done')) 20 | .catch(err => console.log(err)) 21 | ``` 22 | 23 | ## API 24 | 25 | ### `renameOverwrite(oldPath, newPath) => Promise` 26 | 27 | Renames a file or directory asynchronously. Overwrites existing file or directory. 28 | 29 | ### `renameOverwrite.sync(oldPath, newPath)` 30 | 31 | Renames a file or directory synchronously. Overwrites existing file or directory. 32 | 33 | ## License 34 | 35 | [MIT](LICENSE) 36 | -------------------------------------------------------------------------------- /rename-overwrite/index.d.ts: -------------------------------------------------------------------------------- 1 | export = renameOverwrite 2 | 3 | declare function renameOverwrite (oldPath: string, newPath: string): Promise 4 | 5 | declare namespace renameOverwrite { 6 | function sync (oldPath: string, newPath: string): void 7 | } 8 | -------------------------------------------------------------------------------- /rename-overwrite/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const { copySync, copy } = require('fs-extra') 4 | const path = require('path') 5 | const rimraf = require('@zkochan/rimraf') 6 | 7 | module.exports = async function renameOverwrite (oldPath, newPath, retry = 0) { 8 | try { 9 | await fs.promises.rename(oldPath, newPath) 10 | } catch (err) { 11 | retry++ 12 | if (retry > 3) throw err 13 | switch (err.code) { 14 | case 'ENOTEMPTY': 15 | case 'EEXIST': 16 | case 'ENOTDIR': 17 | await rimraf(newPath) 18 | await renameOverwrite(oldPath, newPath, retry) 19 | break 20 | // Windows Antivirus issues 21 | case 'EPERM': 22 | case 'EACCESS': 23 | case 'EBUSY': { 24 | await rimraf(newPath) 25 | const start = Date.now() 26 | let backoff = 0 27 | let lastError = err 28 | while (Date.now() - start < 60000 && (lastError.code === 'EPERM' || lastError.code === 'EACCESS' || lastError.code === 'EBUSY')) { 29 | await new Promise(resolve => setTimeout(resolve, backoff)) 30 | try { 31 | await fs.promises.rename(oldPath, newPath) 32 | return 33 | } catch (err) { 34 | lastError = err 35 | } 36 | if (backoff < 100) { 37 | backoff += 10 38 | } 39 | } 40 | throw lastError 41 | } 42 | case 'ENOENT': 43 | try { 44 | await fs.promises.stat(oldPath) 45 | } catch (statErr) { 46 | // If the source file does not exist, we cannot possible rename it 47 | if (statErr.code === 'ENOENT') { 48 | throw statErr 49 | } 50 | } 51 | await fs.promises.mkdir(path.dirname(newPath), { recursive: true }) 52 | await renameOverwrite(oldPath, newPath, retry) 53 | break 54 | // Crossing filesystem boundaries so rename is not available 55 | case 'EXDEV': 56 | try { 57 | await rimraf(newPath) 58 | } catch (rimrafErr) { 59 | if (rimrafErr.code !== 'ENOENT') { 60 | throw rimrafErr 61 | } 62 | } 63 | await copy(oldPath, newPath) 64 | await rimraf(oldPath) 65 | break 66 | default: 67 | throw err 68 | } 69 | } 70 | } 71 | 72 | module.exports.sync = function renameOverwriteSync (oldPath, newPath, retry = 0) { 73 | try { 74 | fs.renameSync(oldPath, newPath) 75 | } catch (err) { 76 | retry++ 77 | if (retry > 3) throw err 78 | switch (err.code) { 79 | // Windows Antivirus issues 80 | case 'EPERM': 81 | case 'EACCESS': 82 | case 'EBUSY': { 83 | rimraf.sync(newPath) 84 | const start = Date.now() 85 | let backoff = 0 86 | let lastError = err 87 | while (Date.now() - start < 60000 && (lastError.code === 'EPERM' || lastError.code === 'EACCESS' || lastError.code === 'EBUSY')) { 88 | const waitUntil = Date.now() + backoff 89 | while (waitUntil > Date.now()) {} 90 | try { 91 | fs.renameSync(oldPath, newPath) 92 | return 93 | } catch (err) { 94 | lastError = err 95 | } 96 | if (backoff < 100) { 97 | backoff += 10 98 | } 99 | } 100 | throw lastError 101 | } 102 | case 'ENOTEMPTY': 103 | case 'EEXIST': 104 | case 'ENOTDIR': 105 | rimraf.sync(newPath) 106 | fs.renameSync(oldPath, newPath) 107 | return 108 | case 'ENOENT': 109 | fs.mkdirSync(path.dirname(newPath), { recursive: true }) 110 | renameOverwriteSync(oldPath, newPath, retry) 111 | return 112 | // Crossing filesystem boundaries so rename is not available 113 | case 'EXDEV': 114 | try { 115 | rimraf.sync(newPath) 116 | } catch (rimrafErr) { 117 | if (rimrafErr.code !== 'ENOENT') { 118 | throw rimrafErr 119 | } 120 | } 121 | copySync(oldPath, newPath) 122 | rimraf.sync(oldPath) 123 | break 124 | default: 125 | throw err 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /rename-overwrite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rename-overwrite", 3 | "version": "6.0.3", 4 | "description": "Like `fs.rename` but overwrites existing file or directory", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js", 8 | "index.d.ts" 9 | ], 10 | "engines": { 11 | "node": ">=18" 12 | }, 13 | "scripts": { 14 | "test": "jest" 15 | }, 16 | "repository": "https://github.com/zkochan/packages/tree/main/rename-overwrite", 17 | "keywords": [ 18 | "rename", 19 | "move", 20 | "fs" 21 | ], 22 | "author": { 23 | "name": "Zoltan Kochan", 24 | "email": "z@kochan.io", 25 | "url": "https://www.kochan.io" 26 | }, 27 | "license": "MIT", 28 | "homepage": "https://github.com/zkochan/packages/tree/main/rename-overwrite#readme", 29 | "dependenciesMeta": { 30 | "rename-overwrite": { 31 | "injected": true 32 | } 33 | }, 34 | "devDependencies": { 35 | "jest": "^27.5.1", 36 | "load-json-file": "6.2.0", 37 | "rename-overwrite": "link:", 38 | "standard": "^16.0.4", 39 | "symlink-dir": "^5.2.1", 40 | "tempy": "^1.0.1", 41 | "write-json-file": "^4.3.0" 42 | }, 43 | "dependencies": { 44 | "@zkochan/rimraf": "workspace:^", 45 | "fs-extra": "11.3.0" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /render-help/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /render-help/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # render-help 2 | 3 | ## 1.0.3 4 | 5 | ### Patch Changes 6 | 7 | - Fix description width when no short aliases are provided. 8 | 9 | ## 1.0.2 10 | 11 | ### Patch Changes 12 | 13 | - bd957ab: Passess columns in correct format to the table lib. 14 | 15 | ## 1.0.1 16 | 17 | ### Patch Changes 18 | 19 | - 16f8bec: Update table to v6. 20 | -------------------------------------------------------------------------------- /render-help/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2023 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /render-help/README.md: -------------------------------------------------------------------------------- 1 | # render-help 2 | 3 | > Creates a nice output for a CLI --help 4 | 5 | [![npm version](https://img.shields.io/npm/v/render-help.svg)](https://www.npmjs.com/package/render-help) 6 | 7 | ## Installation 8 | 9 | ``` 10 | add render-help 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```JavaScript 16 | const renderHelp = require('./lib') 17 | 18 | const output = renderHelp({ 19 | usages: ['pnpm install [options]'], 20 | aliases: ['i'], 21 | description: 'Install all dependencies', 22 | descriptionLists: [ 23 | { 24 | title: 'Options', 25 | list: [ 26 | { 27 | name: '--force', 28 | shortAlias: '-f', 29 | description: 'Do some dangerous things' 30 | }, 31 | { 32 | name: '--lockfile-only', 33 | description: "Don't create node_modules. Just generate pnpm-lock.yaml" 34 | } 35 | ] 36 | } 37 | ], 38 | url: 'https://pnpm.js.org/en/cli/install' 39 | }) 40 | console.log(output) 41 | // Usage: pnpm install [options] 42 | // 43 | // Alias: i 44 | // 45 | // Install all dependencies 46 | // 47 | // Options: 48 | // -f, --force Do some dangerous things 49 | // --lockfile-only Don't create node_modules. Just generate pnpm-lock.yaml 50 | // 51 | // Visit https://pnpm.js.org/en/cli/install for documentation about this command. 52 | ``` 53 | 54 | ## License 55 | 56 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 57 | -------------------------------------------------------------------------------- /render-help/example.js: -------------------------------------------------------------------------------- 1 | const renderHelp = require('./lib') 2 | 3 | const output = renderHelp({ 4 | usages: ['pnpm install [options]'], 5 | aliases: ['i'], 6 | description: 'Install all dependencies', 7 | descriptionLists: [ 8 | { 9 | title: 'Options', 10 | list: [ 11 | { 12 | name: '--force', 13 | shortAlias: '-f', 14 | description: 'Do some dangerous things' 15 | }, 16 | { 17 | name: '--lockfile-only', 18 | description: "Don't create node_modules. Just generate pnpm-lock.yaml" 19 | } 20 | ] 21 | } 22 | ], 23 | url: 'https://pnpm.js.org/en/cli/install' 24 | }) 25 | console.log(output) 26 | -------------------------------------------------------------------------------- /render-help/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "render-help", 3 | "version": "1.0.3", 4 | "description": "Creates a nice output for a CLI --help", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "engines": { 11 | "node": ">=10" 12 | }, 13 | "scripts": { 14 | "test": "jest", 15 | "prepublishOnly": "tsc" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/render-help", 18 | "keywords": [ 19 | "cli", 20 | "help", 21 | "bin" 22 | ], 23 | "author": { 24 | "name": "Zoltan Kochan", 25 | "email": "z@kochan.io", 26 | "url": "https://www.kochan.io" 27 | }, 28 | "license": "MIT", 29 | "homepage": "https://github.com/zkochan/packages/tree/main/render-help#readme", 30 | "dependencies": { 31 | "table": "^6.9.0" 32 | }, 33 | "devDependencies": { 34 | "@types/common-tags": "^1.8.4", 35 | "@types/jest": "^27.5.2", 36 | "@types/node": "14.14.6", 37 | "@types/table": "^6.3.2", 38 | "common-tags": "^1.8.2", 39 | "jest": "^27.5.1", 40 | "ts-jest": "^27.1.5", 41 | "typescript": "^4.9.5" 42 | }, 43 | "jest": { 44 | "preset": "ts-jest", 45 | "testEnvironment": "node" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /render-help/src/index.ts: -------------------------------------------------------------------------------- 1 | import { table, getBorderCharacters } from 'table' 2 | 3 | type DescriptionItem = { shortAlias?: string, name: string, description?: string } 4 | 5 | export = function renderHelp ( 6 | config: { 7 | aliases?: string[], 8 | descriptionLists?: Array<{ title: string, list: DescriptionItem[] }>, 9 | description?: string, 10 | usages: string[], 11 | url?: string, 12 | width?: number, 13 | } 14 | ) { 15 | const width = config.width ?? process.stdout.columns ?? 80 16 | let outputSections = [] 17 | 18 | if (config.usages.length > 0) { 19 | const [firstUsage, ...restUsages] = config.usages 20 | let usageOutput = `Usage: ${firstUsage}` 21 | for (let usage of restUsages) { 22 | usageOutput += `\n ${usage}` 23 | } 24 | outputSections.push(usageOutput) 25 | } 26 | if (config.aliases && config.aliases.length) { 27 | outputSections.push(`${config.aliases.length === 1 ? 'Alias' : 'Aliases'}: ${config.aliases.join(', ')}`) 28 | } 29 | if (config.description) outputSections.push(`${config.description}`) 30 | if (config.descriptionLists) { 31 | for (let { title, list } of config.descriptionLists) { 32 | outputSections.push(`${title}:\n` + renderDescriptionList(list, width)) 33 | } 34 | } 35 | if (config.url) { 36 | outputSections.push(`Visit ${config.url} for documentation about this command.`) 37 | } 38 | return outputSections.join('\n\n') 39 | } 40 | 41 | const TABLE_OPTIONS = { 42 | border: getBorderCharacters("void"), 43 | singleLine: true, 44 | } 45 | 46 | const FIRST_COLUMN = { paddingLeft: 2, paddingRight: 0 } 47 | const SHORT_OPTION_COLUMN = { alignment: 'right' as const } 48 | const LONG_OPTION_COLUMN = { paddingLeft: 1, paddingRight: 2 } 49 | const DESCRIPTION_COLUMN = { 50 | paddingLeft: 0, 51 | paddingRight: 0, 52 | wrapWord: true, 53 | } 54 | 55 | function renderDescriptionList (descriptionItems: DescriptionItem[], width: number) { 56 | const data = descriptionItems 57 | .sort((item1, item2) => item1.name.localeCompare(item2.name)) 58 | .map(({ shortAlias, name, description }) => [shortAlias && `${shortAlias},` || ' ', name, description || '']) 59 | const firstColumnMaxWidth = Math.max(getColumnMaxWidth(data, 0), 3) 60 | const nameColumnMaxWidth = Math.max(getColumnMaxWidth(data, 1), 19) 61 | const descriptionColumnWidth = Math.max( 62 | width - 63 | (FIRST_COLUMN.paddingLeft + 64 | firstColumnMaxWidth + 65 | FIRST_COLUMN.paddingRight + 66 | LONG_OPTION_COLUMN.paddingLeft + 67 | nameColumnMaxWidth + 68 | LONG_OPTION_COLUMN.paddingRight + 69 | DESCRIPTION_COLUMN.paddingLeft + 70 | DESCRIPTION_COLUMN.paddingRight), 71 | 2 72 | ) 73 | return multiTrim(table(data, { 74 | ...TABLE_OPTIONS, 75 | columns: { 76 | 0: { 77 | width: firstColumnMaxWidth, 78 | ...SHORT_OPTION_COLUMN, 79 | ...FIRST_COLUMN, 80 | }, 81 | 1: { 82 | width: nameColumnMaxWidth, 83 | ...LONG_OPTION_COLUMN, 84 | }, 85 | 2: { 86 | width: descriptionColumnWidth, 87 | ...DESCRIPTION_COLUMN, 88 | }, 89 | }, 90 | })) 91 | } 92 | 93 | function multiTrim (str: string) { 94 | return str.split('\n').map( 95 | (line) => line.trimRight() 96 | ).filter(Boolean).join('\n') 97 | } 98 | 99 | function getColumnMaxWidth (data: string[][], columnNumber: number) { 100 | return data.reduce((maxWidth, row) => Math.max(maxWidth, row[columnNumber].length), 0) 101 | } 102 | -------------------------------------------------------------------------------- /render-help/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "noImplicitAny": true, 9 | "noImplicitReturns": true, 10 | "outDir": "lib", 11 | "preserveConstEnums": true, 12 | "removeComments": false, 13 | "sourceMap": true, 14 | "strictNullChecks": true, 15 | "suppressImplicitAnyIndexErrors": true, 16 | "target": "es2017" 17 | }, 18 | "include": [ 19 | "src/**/*.ts" 20 | ], 21 | "atom": { 22 | "rewriteTsconfig": true 23 | }, 24 | "types": [ 25 | "jest" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ], 5 | "ignorePaths": [ 6 | "**/test/**" 7 | ], 8 | "pinVersions": false, 9 | "schedule": [ 10 | "on Friday", 11 | "every weekend" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /resolve-link-target/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules_link 2 | -------------------------------------------------------------------------------- /resolve-link-target/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # resolve-link-target 2 | 3 | ## 2.0.0 4 | ### Major Changes 5 | 6 | - bba9985: Support of Node.js versions older than 10 is dropped. 7 | 8 | ### Minor Changes 9 | 10 | - bba9985: graceful-fs and mz removed from dependencies. 11 | -------------------------------------------------------------------------------- /resolve-link-target/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /resolve-link-target/README.md: -------------------------------------------------------------------------------- 1 | # resolve-link-target 2 | 3 | > Resolve a symlink's (or junction's) target 4 | 5 | [![npm version](https://img.shields.io/npm/v/resolve-link-target.svg)](https://www.npmjs.com/package/resolve-link-target) 6 | 7 | ## Installation 8 | 9 | ``` 10 | add resolve-link-target 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const resolveLinkTarget = require('resolve-link-target') 17 | 18 | resolveLinkTarget('path-to-symlink').then(targetPath => console.log(targetPath)) 19 | //> "/home/target" 20 | 21 | resolveLinkTarget.sync('path-to-symlink') 22 | //> "/home/target" 23 | ``` 24 | 25 | ## API 26 | 27 | ### `resolveLinkTarget(linkPath)` 28 | 29 | Returns a `Promise`. 30 | 31 | ### `resolveLinkTarget.sync(linkPath)` 32 | 33 | #### linkPath 34 | 35 | Type: `string` 36 | 37 | Path to the symlink or junction that should be resolved. 38 | 39 | ## License 40 | 41 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 42 | -------------------------------------------------------------------------------- /resolve-link-target/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'resolve-link-target' { 2 | export = resolveLinkTarget; 3 | 4 | function resolveLinkTarget (linkPath: string): Promise; 5 | 6 | namespace resolveLinkTarget { 7 | export function sync (linkPath: string): string 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /resolve-link-target/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const path = require('path') 4 | 5 | module.exports = getLinkTarget 6 | module.exports.sync = getLinkTargetSync 7 | 8 | async function getLinkTarget (linkPath) { 9 | linkPath = path.resolve(linkPath) 10 | const target = await fs.promises.readlink(linkPath) 11 | return _resolveLink(linkPath, target) 12 | } 13 | 14 | function getLinkTargetSync (linkPath) { 15 | linkPath = path.resolve(linkPath) 16 | const target = fs.readlinkSync(linkPath) 17 | return _resolveLink(linkPath, target) 18 | } 19 | 20 | function _resolveLink (dest, target) { 21 | if (path.isAbsolute(target)) { 22 | return path.resolve(target) 23 | } 24 | 25 | return path.join(path.dirname(dest), target) 26 | } 27 | -------------------------------------------------------------------------------- /resolve-link-target/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "resolve-link-target", 3 | "version": "2.0.0", 4 | "description": "Resolve a symlink's (or junction's) target", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && tape test.js" 13 | }, 14 | "engines": { 15 | "node": ">=10" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/resolve-link-target", 18 | "keywords": [ 19 | "symlink", 20 | "junction", 21 | "link", 22 | "target", 23 | "absolute", 24 | "resolve", 25 | "readlink", 26 | "fs", 27 | "filesystem" 28 | ], 29 | "author": "Zoltan Kochan", 30 | "license": "MIT", 31 | "homepage": "https://github.com/zkochan/packages/tree/main/resolve-link-target#readme", 32 | "devDependencies": { 33 | "standard": "^16.0.4", 34 | "symlink-dir": "^5.2.1", 35 | "tape": "^5.9.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resolve-link-target/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const getLinkTarget = require('.') 4 | const symlinkDir = require('symlink-dir').default 5 | const path = require('path') 6 | 7 | test('getLinkTarget()', t => { 8 | symlinkDir('node_modules', 'node_modules_link') 9 | .then(() => getLinkTarget('node_modules_link')) 10 | .then(target => { 11 | t.equal(target, path.resolve('node_modules')) 12 | t.end() 13 | }) 14 | .catch(t.end) 15 | }) 16 | 17 | test('getLinkTarget.sync()', t => { 18 | symlinkDir('node_modules', 'node_modules_link') 19 | .then(() => { 20 | t.equal(getLinkTarget.sync('node_modules_link'), path.resolve('node_modules')) 21 | t.end() 22 | }) 23 | .catch(t.end) 24 | }) 25 | -------------------------------------------------------------------------------- /rimraf/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @zkochan/rimraf 2 | 3 | ## 3.0.2 4 | 5 | ### Patch Changes 6 | 7 | - b70f4a9: Should be able to remove files too. 8 | 9 | ## 3.0.0 10 | 11 | ### Major Changes 12 | 13 | - 3fa8bea: Updates to rimraf 5.x 14 | 15 | ## 2.1.3 16 | 17 | ### Patch Changes 18 | 19 | - 1b6d04d: Add `sync` to `index.d.ts`. 20 | 21 | ## 2.1.2 22 | 23 | ### Patch Changes 24 | 25 | - 1d97370: rimraf should remove a broken symlink. 26 | 27 | ## 2.1.1 28 | 29 | ### Patch Changes 30 | 31 | - 9d537ee: Use `rm()` and `rmSync()` instead of `rmdir()` and `rmdirSync()`, when available. 32 | 33 | ## 2.1.0 34 | 35 | ### Minor Changes 36 | 37 | - sync function added. 38 | 39 | ## 1.0.1 40 | 41 | ### Patch Changes 42 | 43 | - 671127c: Move type dependencies to dev dependencies. 44 | -------------------------------------------------------------------------------- /rimraf/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019-2024 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /rimraf/README.md: -------------------------------------------------------------------------------- 1 | # @zkochan/rimraf 2 | 3 | > rm -rf for Node. Similar to rimraf but returns a promise 4 | 5 | [![npm version](https://img.shields.io/npm/v/@zkochan/rimraf.svg)](https://www.npmjs.com/package/@zkochan/rimraf) 6 | 7 | ## Installation 8 | 9 | ``` 10 | add @zkochan/rimraf 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const rimraf = require('@zkochan/rimraf') 17 | 18 | await rimraf('node_modules') 19 | ``` 20 | 21 | ## License 22 | 23 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 24 | -------------------------------------------------------------------------------- /rimraf/__tests__/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const tempy = require('tempy') 4 | const rimraf = require('..') 5 | 6 | test('rimraf', async () => { 7 | const dir = tempy.directory() 8 | fs.writeFileSync(path.join(dir, 'file.txt'), 'foo', 'utf8') 9 | expect(fs.existsSync(dir)).toBe(true) 10 | await rimraf(dir) 11 | expect(fs.existsSync(dir)).toBe(false) 12 | }) 13 | 14 | test('rimraf sync', () => { 15 | const dir = tempy.directory() 16 | fs.writeFileSync(path.join(dir, 'file.txt'), 'foo', 'utf8') 17 | expect(fs.existsSync(dir)).toBe(true) 18 | rimraf.sync(dir) 19 | expect(fs.existsSync(dir)).toBe(false) 20 | }) 21 | -------------------------------------------------------------------------------- /rimraf/index.d.ts: -------------------------------------------------------------------------------- 1 | declare function rimraf (p: string): Promise 2 | 3 | declare namespace rimraf { 4 | function sync(p: string): void 5 | } 6 | 7 | export = rimraf 8 | -------------------------------------------------------------------------------- /rimraf/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | module.exports = async (p) => { 4 | try { 5 | await fs.promises.rm(p, { recursive: true, force: true, maxRetries: 3 }) 6 | } catch (err) { 7 | if (err.code === 'ENOENT') return 8 | throw err 9 | } 10 | } 11 | 12 | module.exports.sync = (p) => { 13 | try { 14 | fs.rmSync(p, { recursive: true, force: true, maxRetries: 3 }) 15 | } catch (err) { 16 | if (err.code === 'ENOENT') return 17 | throw err 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rimraf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@zkochan/rimraf", 3 | "version": "3.0.2", 4 | "description": "rm -rf for Node. Similar to rimraf but returns a promise", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && jest" 13 | }, 14 | "engines": { 15 | "node": ">=18.12" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/rimraf", 18 | "author": { 19 | "name": "Zoltan Kochan", 20 | "email": "z@kochan.io", 21 | "url": "https://www.kochan.io" 22 | }, 23 | "license": "MIT", 24 | "homepage": "https://github.com/zkochan/packages/tree/main/rimraf#readme", 25 | "devDependencies": { 26 | "jest": "^27.5.1", 27 | "standard": "^16.0.4", 28 | "tempy": "^1.0.1" 29 | }, 30 | "jest": { 31 | "testEnvironment": "node" 32 | }, 33 | "standard": { 34 | "globals": [ 35 | "test", 36 | "expect" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /root-link-target/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # root-link-target 2 | 3 | ## 3.1.0 4 | 5 | ### Minor Changes 6 | 7 | - bba9985: graceful-fs and mz removed from dependencies. 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [bba9985] 12 | - Updated dependencies [bba9985] 13 | - can-link@2.0.0 14 | 15 | ## 3.0.0 16 | 17 | ### Major Changes 18 | 19 | - ce3290e: Drop Node.js 8 support and use async/await syntax. 20 | -------------------------------------------------------------------------------- /root-link-target/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /root-link-target/README.md: -------------------------------------------------------------------------------- 1 | # root-link-target 2 | 3 | > Gets the shortest directory to which a file can be linked 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/root-link-target.svg)](https://www.npmjs.com/package/root-link-target) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add root-link-target 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const rootLinkTarget = require('root-link-target') 19 | 20 | rootLinkTarget.sync('C:\\sub\\dir\\foo.txt') 21 | //> C:\\ 22 | ``` 23 | 24 | ## API 25 | 26 | ### `rootLinkTarget.sync(filename): string` 27 | 28 | Returns the shortest directory to which `filename` can be linked 29 | 30 | ### `rootLinkTarget(filename): Promise` 31 | 32 | ## License 33 | 34 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io/) 35 | -------------------------------------------------------------------------------- /root-link-target/example.js: -------------------------------------------------------------------------------- 1 | const rootLinkTarget = require('.') 2 | 3 | console.log(rootLinkTarget.sync('package.json')) 4 | -------------------------------------------------------------------------------- /root-link-target/index.d.ts: -------------------------------------------------------------------------------- 1 | export = rootLinkTarget 2 | 3 | declare function rootLinkTarget (filePath: string): Promise 4 | 5 | declare namespace rootLinkTarget { 6 | function sync (filePath: string): string 7 | } 8 | -------------------------------------------------------------------------------- /root-link-target/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const canLink = require('can-link') 3 | const path = require('path') 4 | const pathTemp = require('path-temp') 5 | const nextPath = require('next-path') 6 | 7 | module.exports = async (filePath) => { 8 | filePath = path.resolve(filePath) 9 | const end = path.dirname(filePath) 10 | let dir = path.parse(end).root 11 | 12 | while (true) { 13 | const result = await canLink(filePath, pathTemp(dir)) 14 | if (result) { 15 | return dir 16 | } else if (dir === end) { 17 | throw new Error(`${filePath} cannot be linked to anywhere`) 18 | } else { 19 | dir = nextPath(dir, end) 20 | } 21 | } 22 | } 23 | 24 | module.exports.sync = (filePath) => { 25 | filePath = path.resolve(filePath) 26 | const end = path.dirname(filePath) 27 | let dir = path.parse(end).root 28 | 29 | while (true) { 30 | const result = canLink.sync(filePath, pathTemp(dir)) 31 | if (result) { 32 | return dir 33 | } else if (dir === end) { 34 | throw new Error(`${filePath} cannot be linked to anywhere`) 35 | } else { 36 | dir = nextPath(dir, end) 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /root-link-target/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root-link-target", 3 | "version": "3.1.0", 4 | "description": "Gets the shortest directory to which a file can be linked", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && node test", 13 | "md": "mos" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/root-link-target", 16 | "keywords": [ 17 | "link", 18 | "hardlink", 19 | "fs" 20 | ], 21 | "engines": { 22 | "node": ">=10" 23 | }, 24 | "author": "Zoltan Kochan (https://www.kochan.io/)", 25 | "license": "MIT", 26 | "homepage": "https://github.com/zkochan/packages/tree/main/root-link-target#readme", 27 | "dependenciesMeta": { 28 | "root-link-target": { 29 | "injected": true 30 | } 31 | }, 32 | "dependencies": { 33 | "can-link": "workspace:^", 34 | "next-path": "^1.0.0", 35 | "path-temp": "2.0.0" 36 | }, 37 | "devDependencies": { 38 | "mos": "2.0.0-alpha.3", 39 | "mos-plugin-readme": "^1.0.4", 40 | "root-link-target": "file:", 41 | "standard": "^16.0.4", 42 | "tape": "^5.9.0" 43 | }, 44 | "mos": { 45 | "plugins": [ 46 | "readme" 47 | ], 48 | "installation": { 49 | "useShortAlias": true 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /root-link-target/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const rootLinkTarget = require('root-link-target') 3 | const test = require('tape') 4 | 5 | test('rootLinkTarget.sync()', t => { 6 | t.equal(typeof rootLinkTarget.sync('package.json'), 'string') 7 | t.end() 8 | }) 9 | 10 | test('rootLinkTarget.sync()', async t => { 11 | const root = await rootLinkTarget('package.json') 12 | t.equal(typeof root, 'string') 13 | t.end() 14 | }) 15 | -------------------------------------------------------------------------------- /run-groups/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # run-groups 2 | 3 | ## 3.0.1 4 | 5 | ### Patch Changes 6 | 7 | - e4d22f4: Fix pLimit importing. 8 | 9 | ## 3.0.0 10 | 11 | ### Major Changes 12 | 13 | - a593cd5: Update p-limit to v3 and drop Node.js 8 support. 14 | -------------------------------------------------------------------------------- /run-groups/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /run-groups/README.md: -------------------------------------------------------------------------------- 1 | # run-groups 2 | 3 | > Runs a sequence of concurrent task groups 4 | 5 | ## Installation 6 | 7 | ``` 8 | add run-groups 9 | ``` 10 | 11 | ## Usage 12 | 13 | ```ts 14 | import runGroups from 'run-groups' 15 | 16 | await runGroups(10, [ 17 | [ 18 | async () => {}, 19 | async () => {}, 20 | ], 21 | [ 22 | async () => {}, 23 | async () => {}, 24 | async () => {}, 25 | ], 26 | [ 27 | async () => {}, 28 | ], 29 | ]) 30 | ``` 31 | 32 | ## License 33 | 34 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 35 | -------------------------------------------------------------------------------- /run-groups/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: (concurrency: number, groups: (() => Promise)[][]) => Promise; 2 | export default _default; 3 | -------------------------------------------------------------------------------- /run-groups/lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const pLimit = require("p-limit"); 4 | exports.default = async (concurrency, groups) => { 5 | const limitRun = pLimit(concurrency); 6 | for (const tasks of groups) { 7 | await Promise.all(tasks.map((task) => limitRun(task))); 8 | } 9 | }; 10 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /run-groups/lib/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,kCAAkC;AAElC,kBAAe,KAAK,EAAE,WAAmB,EAAE,MAAiC,EAAE,EAAE;IAC9E,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAA;IACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;QAC1B,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;KACvD;AACH,CAAC,CAAA"} -------------------------------------------------------------------------------- /run-groups/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "run-groups", 3 | "version": "3.0.1", 4 | "description": "Runs a sequence of concurrent task groups", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "engines": { 8 | "node": ">=10" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "scripts": { 14 | "test": "ts-node test", 15 | "tsc": "tsc", 16 | "prepublishOnly": "pnpm run tsc" 17 | }, 18 | "repository": "https://github.com/zkochan/packages/tree/main/run-groups", 19 | "keywords": [], 20 | "author": { 21 | "name": "Zoltan Kochan", 22 | "email": "z@kochan.io" 23 | }, 24 | "license": "MIT", 25 | "homepage": "https://github.com/zkochan/packages/tree/main/run-groups#readme", 26 | "dependenciesMeta": { 27 | "run-groups": { 28 | "injected": true 29 | } 30 | }, 31 | "dependencies": { 32 | "p-limit": "^3.1.0" 33 | }, 34 | "devDependencies": { 35 | "@types/node": "14.14.6", 36 | "@types/tape": "^4.13.4", 37 | "delay": "5.0.0", 38 | "run-groups": "file:", 39 | "tape": "^5.9.0", 40 | "ts-node": "^10.9.2", 41 | "typescript": "^4.9.5" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /run-groups/src/index.ts: -------------------------------------------------------------------------------- 1 | import pLimit = require('p-limit') 2 | 3 | export default async (concurrency: number, groups: (() => Promise)[][]) => { 4 | const limitRun = pLimit(concurrency) 5 | for (const tasks of groups) { 6 | await Promise.all(tasks.map((task) => limitRun(task))) 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /run-groups/test/index.ts: -------------------------------------------------------------------------------- 1 | import delay from 'delay' 2 | import runGroups from 'run-groups' 3 | import test = require('tape') 4 | 5 | test('runGroups()', async (t) => { 6 | t.plan(4) 7 | let group2Executed = false 8 | await runGroups(2, [ 9 | [ 10 | async () => { 11 | await delay(100) 12 | t.notOk(group2Executed) 13 | }, 14 | async () => { 15 | await delay(50) 16 | t.notOk(group2Executed) 17 | }, 18 | ], 19 | [ 20 | async () => { 21 | group2Executed = true 22 | await delay(100) 23 | t.pass() 24 | }, 25 | async () => { 26 | group2Executed = true 27 | await delay(50) 28 | t.pass() 29 | }, 30 | ] 31 | ]) 32 | t.end() 33 | }) 34 | -------------------------------------------------------------------------------- /run-groups/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "removeComments": false, 4 | "preserveConstEnums": true, 5 | "sourceMap": true, 6 | "declaration": true, 7 | "noImplicitAny": true, 8 | "noImplicitReturns": true, 9 | "suppressImplicitAnyIndexErrors": true, 10 | "allowSyntheticDefaultImports": true, 11 | "strictNullChecks": true, 12 | "target": "es2017", 13 | "outDir": "lib", 14 | "module": "commonjs", 15 | "moduleResolution": "node" 16 | }, 17 | "include": [ 18 | "src/**/*.ts" 19 | ], 20 | "atom": { 21 | "rewriteTsconfig": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /safe-execa/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /safe-execa/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022-2023 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /safe-execa/README.md: -------------------------------------------------------------------------------- 1 | # safe-execa 2 | 3 | > Like execa but prevents binary planting attacks on Windows 4 | 5 | ## Installation 6 | 7 | ``` 8 | add safe-execa 9 | ``` 10 | 11 | ## License 12 | 13 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 14 | -------------------------------------------------------------------------------- /safe-execa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "safe-execa", 3 | "version": "0.1.4", 4 | "description": "Like execa but prevents binary planting attacks on Windows", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "engines": { 8 | "node": ">=12" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "scripts": { 14 | "tsc": "tsc", 15 | "prepublishOnly": "pnpm run tsc" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/safe-execa", 18 | "keywords": [], 19 | "author": { 20 | "name": "Zoltan Kochan", 21 | "email": "z@kochan.io" 22 | }, 23 | "license": "MIT", 24 | "homepage": "https://github.com/zkochan/packages/tree/main/safe-execa#readme", 25 | "dependencies": { 26 | "@zkochan/which": "^2.0.3", 27 | "execa": "^5.1.1", 28 | "path-name": "^1.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /safe-execa/src/index.ts: -------------------------------------------------------------------------------- 1 | import which from '@zkochan/which' 2 | import execa from 'execa' 3 | import PATH from 'path-name' 4 | 5 | export type { execa } 6 | 7 | const pathCache = new Map() 8 | 9 | export function sync ( 10 | file: string, 11 | args?: readonly string[], 12 | options?: execa.SyncOptions 13 | ): execa.ExecaSyncReturnValue { 14 | try { 15 | which.sync(file, { path: options?.cwd ?? process.cwd() }) 16 | } catch (err: any) { 17 | // If the command is not found in the current directory, there is no need to resolve the command to full location 18 | // as there is no danger of binary planting attack on Windows 19 | if (err.code === 'ENOENT') { 20 | return execa.sync(file, args, options) 21 | } 22 | } 23 | const fileAbsolutePath = getCommandAbsolutePathSync(file, options) 24 | return execa.sync(fileAbsolutePath, args, options) 25 | } 26 | 27 | function getCommandAbsolutePathSync (file: string, options?: { 28 | readonly env?: NodeJS.ProcessEnv; 29 | }) { 30 | if (file.includes('\\') || file.includes('/')) return file 31 | const path = options?.env?.[PATH] ?? process.env[PATH] 32 | const key = JSON.stringify([path, file]) 33 | let fileAbsolutePath = pathCache.get(key) 34 | if (fileAbsolutePath == null) { 35 | fileAbsolutePath = which.sync(file, { path }) 36 | pathCache.set(key, fileAbsolutePath) 37 | } 38 | if (fileAbsolutePath == null) { 39 | throw new Error(`Couldn't find ${file}`) 40 | } 41 | return fileAbsolutePath 42 | } 43 | 44 | export default function ( 45 | file: string, 46 | args?: readonly string[], 47 | options?: execa.Options 48 | ): execa.ExecaChildProcess { 49 | try { 50 | which.sync(file, { path: options?.cwd ?? process.cwd() }) 51 | } catch (err: any) { 52 | // If the command is not found in the current directory, there is no need to resolve the command to full location 53 | // as there is no danger of binary planting attack on Windows 54 | if (err.code === 'ENOENT') { 55 | return execa(file, args, options) 56 | } 57 | } 58 | const fileAbsolutePath = getCommandAbsolutePathSync(file, options) 59 | return execa(fileAbsolutePath, args, options) 60 | } 61 | -------------------------------------------------------------------------------- /safe-execa/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "noImplicitAny": false, 9 | "noImplicitReturns": true, 10 | "outDir": "lib", 11 | "preserveConstEnums": true, 12 | "removeComments": false, 13 | "sourceMap": true, 14 | "strict": true, 15 | "suppressImplicitAnyIndexErrors": true, 16 | "target": "es2019" 17 | }, 18 | "include": [ 19 | "src/**/*.ts" 20 | ], 21 | "atom": { 22 | "rewriteTsconfig": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /safe-promise-defer/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /safe-promise-defer/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /safe-promise-defer/README.md: -------------------------------------------------------------------------------- 1 | # safe-promise-defer 2 | 3 | > Create a deferred promise that is wrappened in a function 4 | 5 | ## Installation 6 | 7 | ``` 8 | pnpm add safe-promise-defer 9 | ``` 10 | 11 | ## License 12 | 13 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 14 | -------------------------------------------------------------------------------- /safe-promise-defer/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import safePromiseDefer from '../src' 2 | 3 | test('safePromiseDefer resolves', async () => { 4 | const p = safePromiseDefer() 5 | p.resolve(1) 6 | expect(await p()).toBe(1) 7 | }) 8 | 9 | test('safePromiseDefer rejects', async () => { 10 | const p = safePromiseDefer() 11 | p.reject(new Error('hello')) 12 | await expect(p()).rejects.toThrow('hello') 13 | }) 14 | -------------------------------------------------------------------------------- /safe-promise-defer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "safe-promise-defer", 3 | "version": "1.0.1", 4 | "description": "Create a deferred promise that is wrappened in a function", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "engines": { 8 | "node": ">=12" 9 | }, 10 | "files": [ 11 | "lib" 12 | ], 13 | "scripts": { 14 | "test": "jest", 15 | "tsc": "tsc", 16 | "prepublishOnly": "pnpm run tsc" 17 | }, 18 | "repository": "https://github.com/zkochan/packages/tree/main/safe-promise-defer", 19 | "keywords": [], 20 | "author": { 21 | "name": "Zoltan Kochan", 22 | "email": "z@kochan.io" 23 | }, 24 | "license": "MIT", 25 | "homepage": "https://github.com/zkochan/packages/tree/main/safe-promise-defer#readme", 26 | "dependencies": { 27 | "promise-share": "^1.0.0" 28 | }, 29 | "devDependencies": { 30 | "@types/jest": "^27.5.2", 31 | "jest": "^27.5.1", 32 | "ts-jest": "^27.1.5", 33 | "typescript": "^4.9.5" 34 | }, 35 | "jest": { 36 | "preset": "ts-jest", 37 | "testEnvironment": "node" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /safe-promise-defer/src/index.ts: -------------------------------------------------------------------------------- 1 | import pShare from 'promise-share' 2 | 3 | export interface SafePromiseDefer { 4 | (): Promise 5 | resolve: (v: T) => void 6 | reject: (err: Error) => void 7 | } 8 | 9 | export default function safeDeferredPromise (): SafePromiseDefer { 10 | let _resolve!: (v: T) => void 11 | let _reject!: (err: Error) => void 12 | 13 | const promiseFn = pShare(new Promise((resolve, reject) => { 14 | _resolve = resolve 15 | _reject = reject 16 | })) 17 | 18 | return Object.assign(promiseFn, { resolve: _resolve, reject: _reject }) 19 | } 20 | 21 | -------------------------------------------------------------------------------- /safe-promise-defer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "noImplicitAny": true, 9 | "noImplicitReturns": true, 10 | "outDir": "lib", 11 | "preserveConstEnums": true, 12 | "removeComments": false, 13 | "sourceMap": true, 14 | "strictNullChecks": true, 15 | "suppressImplicitAnyIndexErrors": true, 16 | "target": "es2017" 17 | }, 18 | "include": [ 19 | "src/**/*.ts" 20 | ], 21 | "atom": { 22 | "rewriteTsconfig": true 23 | }, 24 | "types": [ 25 | "jest" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /which-pm-runs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # which-pm-runs 2 | 3 | ## 1.1.0 4 | ### Minor Changes 5 | 6 | - e7af82f: Support for cnpm added. 7 | -------------------------------------------------------------------------------- /which-pm-runs/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /which-pm-runs/README.md: -------------------------------------------------------------------------------- 1 | # which-pm-runs 2 | 3 | > Detects what package manager executes the process 4 | 5 | [![npm version](https://img.shields.io/npm/v/which-pm-runs.svg)](https://www.npmjs.com/package/which-pm-runs) 6 | 7 | Supports npm, pnpm, Yarn, cnpm, and bun. And also any other package manager that sets the `npm_config_user_agent` env variable. 8 | 9 | ## Installation 10 | 11 | ``` 12 | pnpm add which-pm-runs 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | 'use strict' 19 | const whichPMRuns = require('which-pm-runs') 20 | 21 | whichPMRuns() 22 | //> {name: "pnpm", version: "0.64.2"} 23 | ``` 24 | 25 | ## Related 26 | 27 | * [which-pm](https://github.com/zkochan/packages/tree/main/which-pm) - Detects what package manager was used for installation 28 | 29 | ## License 30 | 31 | [MIT](LICENSE) © [Zoltan Kochan](http://kochan.io) 32 | -------------------------------------------------------------------------------- /which-pm-runs/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function () { 4 | if (!process.env.npm_config_user_agent) { 5 | return undefined 6 | } 7 | return pmFromUserAgent(process.env.npm_config_user_agent) 8 | } 9 | 10 | function pmFromUserAgent (userAgent) { 11 | const pmSpec = userAgent.split(' ')[0] 12 | const separatorPos = pmSpec.lastIndexOf('/') 13 | const name = pmSpec.substring(0, separatorPos) 14 | return { 15 | name: name === 'npminstall' ? 'cnpm' : name, 16 | version: pmSpec.substring(separatorPos + 1) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /which-pm-runs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "which-pm-runs", 3 | "version": "1.1.0", 4 | "description": "Detects what package manager executes the process", 5 | "main": "index.js", 6 | "files": [ 7 | "index.js" 8 | ], 9 | "engines": { 10 | "node": ">=4" 11 | }, 12 | "scripts": { 13 | "test": "tape test" 14 | }, 15 | "repository": "https://github.com/zkochan/packages/tree/main/which-pm-runs", 16 | "bugs": { 17 | "url": "https://github.com/zkochan/packages/labels/package%3A%20which-pm-runs" 18 | }, 19 | "keywords": [ 20 | "npm", 21 | "pnpm", 22 | "yarn", 23 | "cnpm" 24 | ], 25 | "author": "Zoltan Kochan", 26 | "license": "MIT", 27 | "homepage": "https://github.com/zkochan/packages/tree/main/which-pm-runs#readme", 28 | "dependenciesMeta": { 29 | "which-pm-runs": { 30 | "injected": true 31 | } 32 | }, 33 | "devDependencies": { 34 | "@pnpm/exe": "^8.15.9", 35 | "bun": "^0.8.1", 36 | "cnpm": "^7.1.1", 37 | "execa": "^5.1.1", 38 | "npm": "^8.19.4", 39 | "tape": "^5.9.0", 40 | "which-pm-runs": "file:", 41 | "yarn": "^1.22.22" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/bun/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const whichPmRuns = require('which-pm-runs') 3 | 4 | const pm = whichPmRuns(); 5 | if (pm.name !== 'bun' || !pm.version) process.exit(1) 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/bun/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "preinstall": "node index.js" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/cnpm/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const whichPmRuns = require('which-pm-runs') 3 | 4 | const pm = whichPmRuns() 5 | if (pm.name !== 'cnpm' || !pm.version) process.exit(1) 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/cnpm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "preinstall": "node index.js" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/npm/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const whichPmRuns = require('which-pm-runs') 3 | 4 | const pm = whichPmRuns() 5 | if (pm.name !== 'npm' || !pm.version) process.exit(1) 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/npm/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "hasInstallScript": true 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/npm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "preinstall": "node index.js" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/pnpm/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const whichPmRuns = require('which-pm-runs') 3 | 4 | const pm = whichPmRuns() 5 | if (pm.name !== 'pnpm' || !pm.version) process.exit(1) 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/pnpm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "preinstall": "node index.js" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/pnpm/pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: {} 10 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/pnpm/pnpm-workspace.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/which-pm-runs/test/fixtures/pnpm/pnpm-workspace.yaml -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/yarn/.yarn/install-state.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/which-pm-runs/test/fixtures/yarn/.yarn/install-state.gz -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/yarn/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/yarn/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const whichPmRuns = require('which-pm-runs') 3 | 4 | const pm = whichPmRuns() 5 | if (pm.name !== 'yarn' || !pm.version) process.exit(1) 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/yarn/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "preinstall": "node index.js" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /which-pm-runs/test/fixtures/yarn/yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 6 6 | 7 | "root-workspace-0b6124@workspace:.": 8 | version: 0.0.0-use.local 9 | resolution: "root-workspace-0b6124@workspace:." 10 | languageName: unknown 11 | linkType: soft 12 | -------------------------------------------------------------------------------- /which-pm-runs/test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const execa = require('execa') 4 | const path = require('path') 5 | const os = require('os') 6 | 7 | delete process.env.npm_config_user_agent 8 | 9 | const fixturesDir = path.join(__dirname, 'fixtures') 10 | 11 | test('detects yarn', t => { 12 | execa('yarn', [], { cwd: path.join(fixturesDir, 'yarn') }) 13 | .then(() => t.end()) 14 | .catch(t.end) 15 | }) 16 | 17 | test('detects bun', t => { 18 | if(os.platform() === 'win32') return t.end(); 19 | execa('bun', ['install'], { cwd: path.join(fixturesDir, 'bun') }) 20 | .then(() => t.end()) 21 | .catch(t.end) 22 | }) 23 | 24 | test('detects npm', t => { 25 | execa('npm', ['install'], { cwd: path.join(fixturesDir, 'npm') }) 26 | .then(() => t.end()) 27 | .catch(t.end) 28 | }) 29 | 30 | test('detects pnpm', t => { 31 | execa('pnpm', ['install'], { cwd: path.join(fixturesDir, 'pnpm') }) 32 | .then(() => t.end()) 33 | .catch(t.end) 34 | }) 35 | 36 | test('detects cnpm', t => { 37 | execa('cnpm', ['install'], { cwd: path.join(fixturesDir, 'cnpm') }) 38 | .then(() => t.end()) 39 | .catch(t.end) 40 | }) 41 | -------------------------------------------------------------------------------- /which-pm/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017-2025 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /which-pm/README.md: -------------------------------------------------------------------------------- 1 | # which-pm 2 | 3 | > Detects what package manager was used for installation 4 | 5 | [![npm version](https://img.shields.io/npm/v/which-pm.svg)](https://www.npmjs.com/package/which-pm) 6 | 7 | Can detect [npm](https://github.com/npm/cli), [pnpm](https://github.com/pnpm/pnpm) and [yarn](https://github.com/yarnpkg/yarn). 8 | 9 | ## Installation 10 | 11 | ```bash 12 | add which-pm 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | 'use strict' 19 | const whichpm = require('which-pm') 20 | 21 | whichpm(process.cwd()) 22 | .then(pm => console.log(pm)) 23 | .catch(err => console.error(err)) 24 | //> {name: "pnpm", version: "0.64.2"} 25 | ``` 26 | 27 | ## Related 28 | 29 | * [preferred-pm](https://github.com/zkochan/packages/tree/main/preferred-pm) - Returns the preferred package manager of a project 30 | * [which-pm-runs](https://github.com/zkochan/packages/tree/main/which-pm-runs) - Detects what package manager executes the process 31 | 32 | ## License 33 | 34 | [MIT](LICENSE) © [Zoltan Kochan](https://kochan.io) 35 | -------------------------------------------------------------------------------- /which-pm/example.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const whichpm = require('.') 3 | 4 | whichpm(process.cwd()).then(pm => console.log(pm)).catch(err => console.error(err)) 5 | -------------------------------------------------------------------------------- /which-pm/index.d.ts: -------------------------------------------------------------------------------- 1 | declare function whichpm (pkgPath: string): Promise 2 | 3 | declare namespace whichpm { 4 | type Result = NPM | YARN | PNPM | BUN | Other 5 | 6 | interface NPM { 7 | readonly name: 'npm' 8 | } 9 | 10 | interface YARN { 11 | readonly name: 'yarn' 12 | } 13 | 14 | interface PNPM { 15 | readonly name: 'pnpm' 16 | readonly version: string 17 | } 18 | 19 | interface BUN { 20 | readonly name: 'bun' 21 | } 22 | 23 | interface Other { 24 | readonly name: string 25 | readonly version?: string 26 | } 27 | } 28 | 29 | export = whichpm 30 | -------------------------------------------------------------------------------- /which-pm/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const fs = require('fs') 4 | const loadYamlFile = require('load-yaml-file') 5 | 6 | module.exports = async function (pkgPath) { 7 | const modulesPath = path.join(pkgPath, 'node_modules') 8 | const exists = fs.existsSync(path.join(modulesPath, '.yarn-integrity')) 9 | if (exists) return { name: 'yarn' } 10 | 11 | try { 12 | const modules = await loadYamlFile(path.join(modulesPath, '.modules.yaml')) 13 | return toNameAndVersion(modules.packageManager) 14 | } catch (err) { 15 | if (err.code !== 'ENOENT') throw err 16 | } 17 | 18 | if (fs.existsSync(path.join(pkgPath, 'bun.lockb'))) return { name: 'bun' } 19 | 20 | const modulesExists = fs.existsSync(modulesPath) 21 | return modulesExists ? { name: 'npm' } : null 22 | } 23 | 24 | function toNameAndVersion (pkgSpec) { 25 | if (pkgSpec[0] === '@') { 26 | const woPrefix = pkgSpec.substr(1) 27 | const parts = woPrefix.split('@') 28 | return { 29 | name: `@${parts[0]}`, 30 | version: parts[1] 31 | } 32 | } 33 | const parts = pkgSpec.split('@') 34 | return { 35 | name: parts[0], 36 | version: parts[1] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /which-pm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "which-pm", 3 | "version": "3.0.1", 4 | "description": "Detects what package manager was used for installation", 5 | "main": "index.js", 6 | "types": "index.d.ts", 7 | "files": [ 8 | "index.js", 9 | "index.d.ts" 10 | ], 11 | "scripts": { 12 | "test": "standard && node test" 13 | }, 14 | "engines": { 15 | "node": ">=18.12" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/which-pm", 18 | "bugs": { 19 | "url": "https://github.com/zkochan/packages/labels/package%3A%20which-pm" 20 | }, 21 | "keywords": [ 22 | "npm", 23 | "pnpm", 24 | "bun", 25 | "yarn" 26 | ], 27 | "author": "Zoltan Kochan", 28 | "license": "MIT", 29 | "dependenciesMeta": { 30 | "which-pm": { 31 | "injected": true 32 | } 33 | }, 34 | "dependencies": { 35 | "load-yaml-file": "^0.2.0" 36 | }, 37 | "devDependencies": { 38 | "standard": "^16.0.4", 39 | "tape": "^5.9.0", 40 | "which-pm": "file:" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /which-pm/test/fixtures/.gitignore: -------------------------------------------------------------------------------- 1 | !node_modules 2 | -------------------------------------------------------------------------------- /which-pm/test/fixtures/bun/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/which-pm/test/fixtures/bun/bun.lockb -------------------------------------------------------------------------------- /which-pm/test/fixtures/bun/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bun", 3 | "module": "index.ts", 4 | "type": "module", 5 | "devDependencies": { 6 | "@types/bun": "latest" 7 | }, 8 | "peerDependencies": { 9 | "typescript": "^5.0.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /which-pm/test/fixtures/npm/node_modules/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/which-pm/test/fixtures/npm/node_modules/.gitkeep -------------------------------------------------------------------------------- /which-pm/test/fixtures/pnpm/node_modules/.modules.yaml: -------------------------------------------------------------------------------- 1 | packageManager: pnpm@0.70.0 2 | -------------------------------------------------------------------------------- /which-pm/test/fixtures/scoped-pnpm/node_modules/.modules.yaml: -------------------------------------------------------------------------------- 1 | packageManager: '@zkochan/pnpm@0.70.0' 2 | -------------------------------------------------------------------------------- /which-pm/test/fixtures/yarn/node_modules/.yarn-integrity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zkochan/packages/9d27d805525ace20dbece11c82ae4ccc40540184/which-pm/test/fixtures/yarn/node_modules/.yarn-integrity -------------------------------------------------------------------------------- /which-pm/test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const test = require('tape') 3 | const path = require('path') 4 | const whichpm = require('which-pm') 5 | 6 | const fixturesDir = path.join(__dirname, 'fixtures') 7 | 8 | test('identifies pnpm installation', async t => { 9 | const pm = await whichpm(path.join(fixturesDir, 'pnpm')) 10 | t.deepEqual(pm, { name: 'pnpm', version: '0.70.0' }) 11 | t.end() 12 | }) 13 | 14 | test('identifies pnpm installation', async t => { 15 | const pm = await whichpm(path.join(fixturesDir, 'scoped-pnpm')) 16 | t.deepEqual(pm, { name: '@zkochan/pnpm', version: '0.70.0' }) 17 | t.end() 18 | }) 19 | 20 | test('identifies yarn installation', async t => { 21 | const pm = await whichpm(path.join(fixturesDir, 'yarn')) 22 | t.deepEqual(pm, { name: 'yarn' }) 23 | t.end() 24 | }) 25 | 26 | test('identifies bun installation', async t => { 27 | const pm = await whichpm(path.join(fixturesDir, 'bun')) 28 | t.deepEqual(pm, { name: 'bun' }) 29 | t.end() 30 | }) 31 | 32 | test('identifies npm installation', async t => { 33 | const pm = await whichpm(path.join(fixturesDir, 'npm')) 34 | t.deepEqual(pm, { name: 'npm' }) 35 | t.end() 36 | }) 37 | 38 | test('identifies null installation', async t => { 39 | const pm = await whichpm(path.join(fixturesDir, 'null')) 40 | t.equal(pm, null) 41 | t.end() 42 | }) 43 | -------------------------------------------------------------------------------- /write-ini-file/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # write-ini-file 2 | 3 | ## 3.1.0 4 | 5 | ### Minor Changes 6 | 7 | - bba9985: graceful-fs and mz removed from dependencies. 8 | 9 | ## 3.0.2 10 | 11 | ### Patch Changes 12 | 13 | - 01c2324: Update ini to version 2. 14 | 15 | ## 3.0.1 16 | 17 | ### Patch Changes 18 | 19 | - 0a21c77: Update write-file-atomic to v3. 20 | -------------------------------------------------------------------------------- /write-ini-file/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /write-ini-file/README.md: -------------------------------------------------------------------------------- 1 | # write-ini-file 2 | 3 | > Stringify and write ini to a file atomically 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/write-ini-file.svg)](https://www.npmjs.com/package/write-ini-file) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add write-ini-file 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const { writeIniFile } = require('write-ini-file') 19 | 20 | writeIniFile('foo.ini', {foo: true}).then(() => { 21 | console.log('done') 22 | }) 23 | ``` 24 | 25 | ## API 26 | 27 | ### `writeIniFile(filepath, data, [options])` 28 | 29 | Returns a promise. 30 | 31 | ### `writeIniFileSync(filepath, data, [options])` 32 | 33 | #### options 34 | 35 | ##### section 36 | 37 | Read more at the [ini repo](https://github.com/npm/ini#encodeobject-options). 38 | 39 | ##### mode 40 | 41 | Type: `number` 42 | Default `438` _(0666 in octal)_ 43 | 44 | [Mode](https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation) used when writing the file. 45 | 46 | ## Related 47 | 48 | - [read-ini-file](https://github.com/zkochan/packages/tree/main/read-ini-file) - Read and parse an ini file 49 | - [ini](https://github.com/npm/ini) - An ini parser/serializer in JavaScript 50 | 51 | ## License 52 | 53 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 54 | -------------------------------------------------------------------------------- /write-ini-file/index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace writeIniFile { 2 | interface WriteIniFileOpts { 3 | section?: string 4 | mode?: number 5 | } 6 | function writeIniFile (filePath: string, data: Object, opts?: WriteIniFileOpts): Promise 7 | function writeIniFileSync (filePath: string, data: Object, opts?: WriteIniFileOpts): void 8 | } 9 | 10 | export = writeIniFile 11 | 12 | 13 | -------------------------------------------------------------------------------- /write-ini-file/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const writeFileAtomic = require('write-file-atomic') 4 | const fs = require('fs') 5 | const ini = require('ini') 6 | 7 | const main = (fn, fp, data, opts) => { 8 | if (!fp) { 9 | throw new TypeError('Expected a filepath') 10 | } 11 | 12 | if (data === undefined) { 13 | throw new TypeError('Expected data to stringify') 14 | } 15 | 16 | opts = opts || {} 17 | 18 | const encodedData = ini.encode(data, opts) 19 | 20 | return fn(fp, encodedData, { mode: opts.mode }) 21 | } 22 | 23 | module.exports.writeIniFile = async (fp, data, opts) => { 24 | await fs.promises.mkdir(path.dirname(fp), { recursive: true }) 25 | return main(writeFileAtomic, fp, data, opts) 26 | } 27 | 28 | module.exports.writeIniFileSync = (fp, data, opts) => { 29 | fs.mkdirSync(path.dirname(fp), { recursive: true }) 30 | main(writeFileAtomic.sync, fp, data, opts) 31 | } 32 | -------------------------------------------------------------------------------- /write-ini-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "write-ini-file", 3 | "version": "4.0.1", 4 | "description": "Stringify and write ini to a file atomically", 5 | "main": "index.js", 6 | "engines": { 7 | "node": ">=14.6" 8 | }, 9 | "files": [ 10 | "index.js", 11 | "index.d.ts" 12 | ], 13 | "scripts": { 14 | "test": "standard && tape test.js", 15 | "test:readme": "mos t", 16 | "md": "mos" 17 | }, 18 | "repository": "https://github.com/zkochan/packages/tree/main/write-ini-file", 19 | "mos": { 20 | "plugins": [ 21 | "readme" 22 | ], 23 | "installation": { 24 | "useShortAlias": true 25 | } 26 | }, 27 | "keywords": [ 28 | "write", 29 | "ini", 30 | "stringify", 31 | "file", 32 | "fs", 33 | "graceful", 34 | "atomic", 35 | "atomically" 36 | ], 37 | "author": { 38 | "name": "Zoltan Kochan", 39 | "email": "z@kochan.io", 40 | "url": "https://www.kochan.io" 41 | }, 42 | "license": "MIT", 43 | "bugs": { 44 | "url": "https://github.com/zkochan/write-ini-file/issues" 45 | }, 46 | "homepage": "https://github.com/zkochan/packages/tree/main/write-ini-file#readme#readme", 47 | "dependenciesMeta": { 48 | "write-ini-file": { 49 | "injected": true 50 | } 51 | }, 52 | "dependencies": { 53 | "ini": "^3.0.1", 54 | "make-dir": "^3.1.0", 55 | "write-file-atomic": "^5.0.1" 56 | }, 57 | "devDependencies": { 58 | "mos": "2.0.0-alpha.3", 59 | "mos-plugin-readme": "^1.0.4", 60 | "standard": "^16.0.4", 61 | "tape": "^5.9.0", 62 | "tempfile": "^3.0.0", 63 | "write-ini-file": "file:" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /write-ini-file/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | ":preserveSemverRanges" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /write-ini-file/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const fs = require('fs') 3 | const path = require('path') 4 | const tempfile = require('tempfile') 5 | const test = require('tape') 6 | const { EOL } = require('os') 7 | const { writeIniFile, writeIniFileSync } = require('write-ini-file') 8 | 9 | test('async', t => { 10 | const tmp = path.join(tempfile(), 'foo') 11 | writeIniFile(tmp, { foo: true }, { indent: 2 }) 12 | .then(() => { 13 | t.equal(fs.readFileSync(tmp, 'utf8'), `foo=true${EOL}`) 14 | t.end() 15 | }) 16 | .catch(t.end) 17 | }) 18 | 19 | test('sync', t => { 20 | const tmp = path.join(tempfile(), 'foo') 21 | writeIniFileSync(tmp, { foo: true }, { indent: 2 }) 22 | t.equal(fs.readFileSync(tmp, 'utf8'), `foo=true${EOL}`) 23 | t.end() 24 | }) 25 | -------------------------------------------------------------------------------- /write-json5-file/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # write-json5-file 2 | 3 | ## 3.1.0 4 | 5 | ### Minor Changes 6 | 7 | - bba9985: graceful-fs and mz removed from dependencies. 8 | 9 | ## 3.0.1 10 | 11 | ### Patch Changes 12 | 13 | - 0a21c77: Update write-file-atomic to v3. 14 | 15 | ## 3.0.0 16 | 17 | ### Major Changes 18 | 19 | - 674dc01: Use native fs.mkdir instead of make-dir. 20 | 21 | BREAKING CHANGE: 22 | 23 | Node.js 8 support is dropped. 24 | -------------------------------------------------------------------------------- /write-json5-file/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2022 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /write-json5-file/README.md: -------------------------------------------------------------------------------- 1 | # write-json5-file 2 | 3 | > Stringify and write JSON to a file atomically 4 | 5 | 6 | [![npm version](https://img.shields.io/npm/v/write-json5-file.svg)](https://www.npmjs.com/package/write-json5-file) 7 | 8 | 9 | ## Installation 10 | 11 | ```sh 12 | add write-json5-file 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```js 18 | const writeJson5File = require('write-json5-file') 19 | 20 | writeJson5File('foo.json5', {foo: true}).then(() => { 21 | console.log('done') 22 | }) 23 | ``` 24 | 25 | ## API 26 | 27 | ### `writeJson5File(filepath, data, [options])` 28 | 29 | Returns a promise. 30 | 31 | ### `writeJson5File.sync(filepath, data, [options])` 32 | 33 | #### options 34 | 35 | ##### indent 36 | 37 | Type: `string`, `number` 38 | Default: `\t` 39 | 40 | Indentation as a string or number of spaces. 41 | Pass in `null` for no formatting. 42 | 43 | ##### sortKeys 44 | 45 | Type: `boolean`, `function` 46 | Default: `false` 47 | 48 | Sort the keys recursively. 49 | Optionally pass in a [`compare`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) function. 50 | 51 | ##### replacer 52 | 53 | Type: `function` 54 | 55 | Passed into [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter). 56 | 57 | ##### mode 58 | 59 | Type: `number` 60 | Default `438` _(0666 in octal)_ 61 | 62 | [Mode](https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation) used when writing the file. 63 | 64 | ## Related 65 | 66 | - [read-json5-file](../read-json5-file) - Read and parse a JSON5 file 67 | - [write-json-file](https://github.com/sindresorhus/write-json-file) - Stringify and write JSON to a file atomically 68 | - [json5](https://github.com/json5/json5) - JSON for the ES5 era 69 | 70 | ## License 71 | 72 | [MIT](./LICENSE) © [Zoltan Kochan](https://www.kochan.io) 73 | -------------------------------------------------------------------------------- /write-json5-file/index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace writeJson5File { 2 | type Replacer = (this: unknown, key: string, value: any) => unknown; 3 | type SortKeys = (a: string, b: string) => number; 4 | type JSONStringifyable = string | number | boolean | null | object; 5 | 6 | interface Options { 7 | /** 8 | Indentation as a string or number of spaces. Pass in null for no formatting. 9 | 10 | @default '\t' 11 | */ 12 | readonly indent?: string | number | null; 13 | 14 | /** 15 | Sort the keys recursively. Optionally pass in a compare function. 16 | 17 | @default false 18 | */ 19 | readonly sortKeys?: boolean | SortKeys; 20 | 21 | /** 22 | Passed into `JSON.stringify`. 23 | */ 24 | readonly replacer?: Replacer | Array; 25 | 26 | /** 27 | Mode used when writing the file. 28 | 29 | @default 0o666 30 | */ 31 | readonly mode?: number; 32 | } 33 | } 34 | 35 | declare const writeJson5File: { 36 | /** 37 | Stringify and write JSON to a file atomically. 38 | 39 | Creates directories for you as needed. 40 | 41 | @example 42 | ``` 43 | import writeJson5File = require('write-json5-file'); 44 | 45 | (async () => { 46 | await writeJson5File('foo.json', {foo: true}); 47 | })(); 48 | ``` 49 | */ 50 | ( 51 | filepath: string, 52 | data: writeJson5File.JSONStringifyable, 53 | options?: writeJson5File.Options 54 | ): Promise; 55 | 56 | /** 57 | Stringify and write JSON to a file atomically. 58 | 59 | Creates directories for you as needed. 60 | 61 | @example 62 | ``` 63 | import writeJson5File = require('write-json5-file'); 64 | 65 | writeJson5File.sync('foo.json', {foo: true}); 66 | ``` 67 | */ 68 | sync( 69 | filepath: string, 70 | data: writeJson5File.JSONStringifyable, 71 | options?: writeJson5File.Options 72 | ): void; 73 | }; 74 | 75 | export = writeJson5File; 76 | -------------------------------------------------------------------------------- /write-json5-file/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const fs = require('fs') 4 | const writeFileAtomic = require('write-file-atomic') 5 | const sortKeys = require('sort-keys') 6 | const JSON5 = require('json5') 7 | 8 | const main = (fn, fp, data, opts) => { 9 | if (!fp) { 10 | throw new TypeError('Expected a filepath') 11 | } 12 | 13 | if (data === undefined) { 14 | throw new TypeError('Expected data to stringify') 15 | } 16 | 17 | opts = Object.assign({ 18 | indent: '\t', 19 | sortKeys: false 20 | }, opts) 21 | 22 | if (opts.sortKeys) { 23 | data = sortKeys(data, { 24 | deep: true, 25 | compare: typeof opts.sortKeys === 'function' && opts.sortKeys 26 | }) 27 | } 28 | 29 | const json = JSON5.stringify(data, opts.replacer, opts.indent) 30 | 31 | return fn(fp, `${json}\n`, { mode: opts.mode }) 32 | } 33 | 34 | module.exports = async (fp, data, opts) => { 35 | await fs.promises.mkdir(path.dirname(fp), { recursive: true }) 36 | return main(writeFileAtomic, fp, data, opts) 37 | } 38 | 39 | module.exports.sync = (fp, data, opts) => { 40 | fs.mkdirSync(path.dirname(fp), { recursive: true }) 41 | main(writeFileAtomic.sync, fp, data, opts) 42 | } 43 | -------------------------------------------------------------------------------- /write-json5-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "write-json5-file", 3 | "version": "3.1.0", 4 | "description": "Stringify and write JSON to a file atomically", 5 | "main": "index.js", 6 | "engines": { 7 | "node": ">=10.12" 8 | }, 9 | "files": [ 10 | "index.js", 11 | "index.d.ts" 12 | ], 13 | "scripts": { 14 | "test": "standard && tape test.js", 15 | "md": "mos" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/write-json5-file", 18 | "mos": { 19 | "plugins": [ 20 | "readme" 21 | ], 22 | "installation": { 23 | "useShortAlias": true 24 | } 25 | }, 26 | "keywords": [ 27 | "write", 28 | "json5", 29 | "stringify", 30 | "file", 31 | "fs", 32 | "graceful", 33 | "atomic", 34 | "atomically" 35 | ], 36 | "author": { 37 | "name": "Zoltan Kochan", 38 | "email": "z@kochan.io", 39 | "url": "https://www.kochan.io" 40 | }, 41 | "license": "MIT", 42 | "homepage": "https://github.com/zkochan/packages/tree/main/write-json5-file#readme", 43 | "dependencies": { 44 | "json5": "^2.2.3", 45 | "sort-keys": "^4.2.0", 46 | "write-file-atomic": "^3.0.3" 47 | }, 48 | "devDependencies": { 49 | "mos": "2.0.0-alpha.3", 50 | "mos-plugin-readme": "^1.0.4", 51 | "standard": "^16.0.4", 52 | "tape": "^5.9.0", 53 | "tempfile": "^3.0.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /write-json5-file/test.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const test = require('tape') 4 | const tempfile = require('tempfile') 5 | const writeJson5File = require('.') 6 | 7 | test('async', async t => { 8 | const tmp = path.join(tempfile(), 'foo') 9 | await writeJson5File(tmp, { foo: true }, { indent: 2 }) 10 | t.equal(fs.readFileSync(tmp, 'utf8'), '{\n foo: true,\n}\n') 11 | t.end() 12 | }) 13 | 14 | test('sync', t => { 15 | const tmp = path.join(tempfile(), 'foo') 16 | writeJson5File.sync(tmp, { foo: true }, { indent: 2 }) 17 | t.equal(fs.readFileSync(tmp, 'utf8'), '{\n foo: true,\n}\n') 18 | t.end() 19 | }) 20 | -------------------------------------------------------------------------------- /write-yaml-file/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # write-yaml-file 2 | 3 | ## 4.2.0 4 | 5 | ### Minor Changes 6 | 7 | - bba9985: graceful-fs and mz removed from dependencies. 8 | 9 | ## 4.1.3 10 | 11 | ### Patch Changes 12 | 13 | - 75dbec3: Fix stringifying the Yaml object. 14 | 15 | ## 4.1.2 16 | 17 | ### Patch Changes 18 | 19 | - 5f01634: Update js-yaml to version 4. 20 | 21 | ## 4.1.1 22 | 23 | ### Patch Changes 24 | 25 | - 0a21c77: Update write-file-atomic to v3. 26 | 27 | ## 4.1.0 28 | 29 | ### Minor Changes 30 | 31 | - a4b4f41: Native Node.js methods used instead of make-dir and pify 32 | -------------------------------------------------------------------------------- /write-yaml-file/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2023 Zoltan Kochan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /write-yaml-file/README.md: -------------------------------------------------------------------------------- 1 | # write-yaml-file 2 | 3 | > Stringify and write YAML to a file atomically 4 | 5 | Creates directories for you as needed. 6 | 7 | ## Installation 8 | 9 | ``` 10 | add write-yaml-file 11 | ``` 12 | 13 | ## Usage 14 | 15 | ```js 16 | const writeYamlFile = require('write-yaml-file') 17 | 18 | writeYamlFile('foo.yaml', {foo: true}).then(() => { 19 | console.log('done') 20 | }) 21 | ``` 22 | 23 | ## API 24 | 25 | ### `writeYamlFile(filepath, data, [options])` 26 | 27 | Returns a promise. 28 | 29 | ### `writeYamlFile.sync(filepath, data, [options])` 30 | 31 | #### `options` 32 | 33 | Same options that can be passed in to [js-yaml](https://www.npmjs.com/package/js-yaml#safedump-object---options-) 34 | 35 | ##### mode 36 | 37 | Type: `number` 38 | Default `438` *(0666 in octal)* 39 | 40 | [Mode](https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation) used when writing the file. 41 | 42 | #### makeDir 43 | 44 | Type: `boolean` 45 | Default: `true` 46 | 47 | Creates the directory to which the YAML file is written. 48 | 49 | ## Related 50 | 51 | - [load-yaml-file](https://github.com/LinusU/load-yaml-file) - Read and parse a YAML file 52 | 53 | ## License 54 | 55 | [MIT](LICENSE) © [Zoltan Kochan](https://www.kochan.io) 56 | -------------------------------------------------------------------------------- /write-yaml-file/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "write-yaml-file" { 2 | 3 | interface WriteYamlFile { 4 | (filepath: string, data: any, opts?: any): Promise; 5 | sync(filepath: string, data: any, opts?: any): void; 6 | } 7 | 8 | const writeYamlFile: WriteYamlFile; 9 | 10 | export = writeYamlFile; 11 | } 12 | -------------------------------------------------------------------------------- /write-yaml-file/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const path = require('path') 3 | const fs = require('fs') 4 | const writeFileAtomic = require('write-file-atomic') 5 | const YAML = require('js-yaml') 6 | 7 | const main = (fn, fp, data, opts) => { 8 | if (!fp) { 9 | throw new TypeError('Expected a filepath') 10 | } 11 | 12 | if (data === undefined) { 13 | throw new TypeError('Expected data to stringify') 14 | } 15 | 16 | opts = opts || {} 17 | 18 | const yaml = YAML.dump(data, opts) 19 | 20 | return fn(fp, yaml, { mode: opts.mode }) 21 | } 22 | 23 | module.exports = async (fp, data, opts) => { 24 | if (opts?.makeDir ?? true) { 25 | await fs.promises.mkdir(path.dirname(fp), { recursive: true }) 26 | } 27 | return main(writeFileAtomic, fp, data, opts) 28 | } 29 | 30 | module.exports.sync = (fp, data, opts) => { 31 | if (opts?.makeDir ?? true) { 32 | fs.mkdirSync(path.dirname(fp), { recursive: true }) 33 | } 34 | main(writeFileAtomic.sync, fp, data, opts) 35 | } 36 | -------------------------------------------------------------------------------- /write-yaml-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "write-yaml-file", 3 | "version": "5.0.0", 4 | "description": "Stringify and write YAML to a file atomically", 5 | "main": "index.js", 6 | "typings": "index.d.ts", 7 | "engines": { 8 | "node": ">=16.14" 9 | }, 10 | "files": [ 11 | "index.js", 12 | "index.d.ts" 13 | ], 14 | "scripts": { 15 | "test": "standard" 16 | }, 17 | "repository": "https://github.com/zkochan/packages/tree/main/write-yaml-file", 18 | "keywords": [ 19 | "write", 20 | "yaml", 21 | "stringify", 22 | "file", 23 | "fs", 24 | "graceful", 25 | "stable", 26 | "atomic", 27 | "atomically" 28 | ], 29 | "author": { 30 | "name": "Zoltan Kochan", 31 | "email": "z@kochan.io" 32 | }, 33 | "license": "MIT", 34 | "homepage": "https://github.com/zkochan/packages/tree/main/write-yaml-file#readme", 35 | "dependencies": { 36 | "js-yaml": "^4.1.0", 37 | "write-file-atomic": "^5.0.1" 38 | }, 39 | "devDependencies": { 40 | "standard": "^16.0.4" 41 | } 42 | } 43 | --------------------------------------------------------------------------------