{"id":22339787,"url":"https://github.com/scriptollc/pkgswap","last_synced_at":"2025-07-27T15:40:27.253Z","repository":{"id":57325395,"uuid":"110293035","full_name":"scriptoLLC/pkgswap","owner":"scriptoLLC","description":null,"archived":false,"fork":false,"pushed_at":"2019-02-12T23:32:22.000Z","size":35,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-02T16:47:56.042Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scriptoLLC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-10T21:11:52.000Z","updated_at":"2017-11-10T22:07:29.000Z","dependencies_parsed_at":"2022-09-09T05:50:53.739Z","dependency_job_id":null,"html_url":"https://github.com/scriptoLLC/pkgswap","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/scriptoLLC/pkgswap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptoLLC%2Fpkgswap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptoLLC%2Fpkgswap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptoLLC%2Fpkgswap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptoLLC%2Fpkgswap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scriptoLLC","download_url":"https://codeload.github.com/scriptoLLC/pkgswap/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scriptoLLC%2Fpkgswap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267378819,"owners_count":24077815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-04T07:09:24.586Z","updated_at":"2025-07-27T15:40:27.223Z","avatar_url":"https://github.com/scriptoLLC.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PKGSWAP\n\nA tool to manage multiple package.json files to allow for different sets of modules\nfor ease of development.\n\n## TL;DR\nnpm 5 radicially changes how npm operations on your node_modules directory on disk,\nattempting, after each operation, to generate an \"ideal tree\". This tool makes\nit easier to explain what your \"ideal tree\" is for a particular instance.\n\n## Usage\n\n```js\n\u003e var PkgSwap = require('pkgswap')\n\u003e var ps = new PkgSwap()\n\u003e ps.init()\n\u003e ps.create('my workspace', (err) =\u003e console.log(err || 'done'))\n\u003e ps.enable('my workspace', (err) =\u003e console.log(err || 'done'))\n\u003e ps.disable((err) =\u003e console.log(err || 'done'))\n```\n\n(CLI coming soon)\n\n## NTL;WR\n\nWith npm5 everytime you run an operation which updates the `node_modules` directory\non disk, it will attempt to make the `node_modules` directory on disk match\nwhat you have in your package.json (or package-lock.json file). This means\nif you have removed or added a dependency with an earlier operation but _not saved\nthe change to your package(-lock).json file_, those packages will be re-installed/deleted\nso that your on-disk directory matches the canonicial or \"idealized\" version of the\ndependency graph in the metadata.\n\nNormally, this is what you want -- there are a lot of issues around broken\nnode_modules directories that his behavior is intended to rectify, however,\nsometimes, you _really_ want a broken node_modules directory, especially if you\nare working on a project involving a lot of interdependant modules.\n\nThanks to the way that [require](https://github.com/maxogden/art-of-node#how-require-works)\nworks in node, the following is workflow is possible.\n\nIf you were contributing to [choojs](https://choo.io), and wanted to work on some\nchanges to [nanomorph](https://github.com/choojs/nanomorph) but needed to test\nthose changes in the context of [choo](https://github.com/choojs/choo).\n\nYou could deal with using `npm link` (which has a few known-issues), or you could\nsetup your development enviroment like this:\n\n```\n~/src/choojs/node_modules/choo\n~/src/choojs/node_modules/nanomorph\n```\n\nNow, if you wanted to change nanomorph, running `npm rm nanomorph` from `~/src/choojs/node_modules/choo` would\nremove nanomorph locally, forcing node (and [browserify](http://browserify.org)) to\nload the copy from `~/src/choojs/node_modules/nanomorph`.\n\nWith npm 5, however, this becomes nearly impossible, since any subsequent changes\nto the package.json in the `choo` directory, will cause nanomorph to be re-installed.\n\nThe purpose of this tool is to allow the creation of specifically configured\npackage.json files so that npm 5 will not re-install modules you don't want it to.\n\nFor more about developing inside of a `node_modules` directory, please see: the [_Development workflow_](https://github.com/datproject/dat/blob/master/CONTRIBUTING.md#development-workflow) section for [DAT](https://datproject.org) developers.\n\nFor more details on how/why npm 5 does this: [npm uninstall causes npm install to occur](https://github.com/npm/npm/issues/18290)\n\n## API\n\n### new PkgSwap(wd?:string):PkgSwap\nInstantiate a new instance of PkgSwap. Will attempt to find the closest `package.json`\nfile from the working directory provided. (Will traverse directories up towards the root\nof the filesystem)\n\n* `wd?:string` - (optional) provide a working directory. Default: `process.cwd()`\n\n#### PkgSwap#init(opts?:object, cb:function):undefined\nInitialize this module to use package swap.\n\n* `opts?:object` - (optional) options for the initialization\n    * `force:boolean` - don't abort if package.json is already a symlink. Default: false\n* `cb:function` - will be called when intialization is complete\n\n#### PkgSwap#create(name:string, opts?:object, cb:function):undefined\nCreate a new module workspace. If modules are provided to the blacklist, the `#blacklist`\nmethod will be called after the workspace is created; please see the documentation\nfor that method for information on how this works and what to expect.\n\n* `name:string` - the name of the workspace\n* `opts?:object` - options\n    * `blacklist?:array(string)`: a list of modules to remove from this namespace. Default: []\n    * `force?:boolean`: overwrite existing file if any. Default: false\n    * `enable?:boolean`: enable new workspace. Default: false\n* `cb:function` - will be called when workspace has been created (will wait for activation if `enable: true`)\n\n#### PkgSwap#makConfigName(name:string):string\nResolve a workspace name to a workspace filename.\n\nSince the workspaces are stored as files on disk, they need to be properly santizied\nso we don't write invalid filenames to the device\n\n* `name:string` - the name to resolve\n\n#### PkgSwap#enable(dest:string, cb:function):undefined\nEnable an existing workspace.\n\n* `dest:string` - the filename of the workspace to enable\n* `cp:function` - will be called when the workspace is enabled\n\n#### PkgSwap#disable(cb:function):undefined\nRestore the module to use the `master` package.json file\n\nWill cause the symlink to point back to the original `package.json` file provided\nwhen the last workspace was enabled.\n\n* `cb:function` - will be called when the workspace is disabled\n\n#### PkgSwap#blacklist(pkgs:string || array(string), dest:string, cb:function):undefined\nRemove modules from a workspace's dependencies lists and add them to a blacklist\nfor that workspace. You may not blacklist in the master package.json.\n\nThe dependencies list will be filtered each time that this workspace is enabled\nensuring that the modules listed in the blacklist do not appear on any of the\ndependencies lists for the module.\n\nThis will not prevent npm from installing ANY of the blacklisted packages, it\nwill just ensure that they are not present at the time that thie worksapce is\nenabled.\n\nIt will also not remove these packages from disk. Running `npm install` (or using\nthe CLI tool) will do this for you.\n\n* `pkgs:string || array(string)` - a package or list of packages to blacklist\n* `dest:string` - the filename of the workspace to update the blacklist for\n* `cb:function` - will be called when the packages have been blacklisted\n\n#### PkgSwap#unblacklist(pkgs:string || array(string), dest:string, cb:function):undefined\nRemove modules from a workspace's blacklist.  Same caveats as for blacklist apply,\nbut it just works in reverse!\n\n* `pkgs:string || array(string)` - a package or list of packages to unblacklist\n* `dest:string` - the filename of the workspace to update the blacklist for\n* `cb:function` - will be called then the blacklist has been updated\n\n#### PkgSwap#reconcileMaster (dest:string, cb:function):undefined\nUpdate the master package.json with the changes from a workspace, ignoring the\nblacklisted modules.\n\nThis will update the master package.json file with any changes that have occured\nto the workspace's package.json file, adding packages that have been added in the\nworkspace, removing packages that have been removed, and changing the semver\ntarget for those which have had their semver targets changed.  (e.g. if you upgraded\na dep in the workspace, the master will receive the update as well). The modules in\nthe workspaces's blacklist will be kept in the master package.json file.\n\n* `dest:string` - the source file for the blacklist\n* `cb:function` - will be called when the master package.json has been reconciled\n\n#### Blacklisted packages\n\nThe blacklist is stored in the workspace files as the following structure:\n\n```json\n{\n  \"pkgswap\": {\n    \"blacklist\": [{\n      name: 'pkgName',\n      sources: ['devDependencies', 'peerDependencies']\n    }]\n  }\n}\n```\n\n## Licence\nCopyright © 2017 Scripto, LLC. All rights reserved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscriptollc%2Fpkgswap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscriptollc%2Fpkgswap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscriptollc%2Fpkgswap/lists"}