Both package.json andpackage-lock.json should be committed to your source code repository. https://stackoverflow.com/a/55609763/400306 the Examples section, and the link to the detailed procedure cover same steps here for the guy's Typescript project. How to publish a NPM package starting with nothing. This is summary starting with https://devdojo.com/myogeshchavan97/how-to-create-and-publish-npm-package but with my optimizations and much more concise. PREREQs GitHub account npmjs account Multiple account usage: Liberally use 'npm whoami' to verify you are using the account that you intend to use. To switch to another account use "npm logout; npm [--auth-type=legacy] login". Understand sym link usage: N.b. "npm link" is actually a GLOBAL command! "npm link x" is not. So remember: sudo npm link "npm link" creates sym-link from /lib/node_modules/X -> your dev directory, and if project has bin specification then symlinks created from /bin/ to normal location under /lib/node_modules/X/ (i.e. indirectly linked to script in your dev dir). [ here can be determined by "npm prefix -g"] [Don't go by "npm bin˝ which is apparently reporting something else.] N.b. even though it's grafted into /lib/node_modules/, it is apparently specially hidden from lookups because resolve requires and install via "npm i" do not see this; yet just by having ONLY a sym link from any node_modules dir -> dev project dir, requires then work. "npm link NAME" does this. Does not require privilege. Don't forget to ensure that desired destination node_modules dir exists. Git Branching GOTCHAs. If you want to check ANYTHING before committing the merge, then use --no-commit switch to: git merge --no-commit default Check, "git restore --staged file.txt" and "git add file.txt" back when done. If merging causes conflicts with "package-lock.json", check, but it is usually updates that you do want to pull in from default. Can alway regenerate: rm package-lock.json npm i package-lock-only Difficult to delete packages, but in most cases deprecating works great: npm deprecate 'your message. To un-deprecate: npm deprecate '' # empty message Variables npmrc files allow either ${REF} or $REF. TODO: Test (conflicting advice). package.json seems to have no variable expansion capability, though both config and package values get exported to executed scripts: $npm_config_* and $npm_package_* Verify that desired module name by trying https://www.npmjs.com/package/ Create a Git repos: https://github.com/new cd your/dir copy in these files with precisely these names: .gitignore Add this line to the file: /driver.js .gitattributes LICENSE replace {keywords} in doc create an initial README.md file Initialize the git workspace any way that works, obviously tied to the repos created above. commit the files. Edit package.json. Start with copy of "~/code-templates/package-template.json". Most importantly, 'name' must be available as GitHub repos and NPM module. (initial value in the generated file will be the current directory name). (for playing can instead create with "npm init -q") [npm i -D esm # This installs npm module needed to test ES6 includes.] TYPESCRIPT ts-node ONLY!: npm in typescript Create your index.js file, driver.js, and any other source or resource files and develop. 'driver.js' is just for dev test loading and testing of your module. Only "driver.js" and scripts you will publish for bin scripts should be executable. Give them the node interpreter line. There's are default package-exclusion patterns. If .gitnores are present, they will be honored. To override, write .npmignore files. Since filepath require specs need to start with / or ., all requires for internal files will begin with ".". Often "./lib/x". Commit the other files whenever it makes sense to. For module dependencies, do not depend on module installations outside of your work area. Install all and then will go to ./node_modules and update your package.json and package-lock.json files (should not need -S for this!) Great default behavior is like "^2.3.4" where 2.3.4 is current. This requires >= 2.3.4 allow upgrades within the 2.*.* series. As early as possible, work on package.json scripts to test with them. For "package.json" updates, better to use "npm pkg set key1=val1 key2.subattr=val2..." Can insert to lists with: key[2]=val, and append with[key[]=addlVal because that will format the JSON so it won't get changed by some future npm command. If you have any bin scripts, to test them you need to run: sudo npm link (Remember this is a global command, so to undo you need: sudo npm -g unlink). commit EXTERNAL (not-from-work-area) DEV-LINK REQUIRES TESTING If any, test bin scripts from /bin/ ( on Win). "npm link x" does not give access to a local bin script dir. You must do a real "npm i x" to get node_modules/bin/*. Therefore, before publish your module, test bin links with the /bin/ (/ on Win) links created by "npm link". mkdir ~/tmp/mt cd ~/tmp/mt mkdir node_modules EITHER ln -s ~/base/dev/dir node_modules/ # beware the "npm update" will wipe the sym link OR (required if need to test bin command scripts) (you need to have already run 'sudo npm link' from dev project root dir npm link NAME # OR same ln command above from test dir Test from external dev project. If you have been using 'npm run-script', should be able to take your package.json script test commands, change the module specs from filepaths, and issue those commands from CLI. Require usage test command like these. + node -p 'const { validate, is } = require("bycontract-plus"); validate("str", "string");' - node -p 'const { validate, is } = require("bycontract-plus"); validate("str", "int");' ES6 Include usage test command like: npm i esm # very quick +: node -r esm -p 'import { validate, is } from "bycontract-plus"; validate("str", "string");' -: node -r esm -p 'import { validate, is } from "bycontract-plus"; validate("str", "int");' AFTER DONE WITH LINK TESTING, UNDO npm unlink NAME # or remove sym link created above, from test dir EXTERNAL (not-from-work-area) DEV-LINK REQUIRES TESTING Back to package dev dir, check package.json and what gets published (by checking contents) with: npm pack See Tarballing section below. In a new test project dir, 'npm i path/to/*.tgz'. You get a snapshot. Can do this on another host. Esp. useful for multi-platform testing. Do end user testing using "npm -e/p '...'" and/or with scripts. AFTER DONE WITH ALL TESTING, UNDO sudo npm unlink -g [NAME] #if ran "sudo npm link". NAME if not in dev dir. EXTERNALLY (not-from-work-area) TEST ES6 INCLUDING Create test script "something.mjs" that does something like: import dflt, {v1toTest, v2toTest} from " Once everything verified and you're sure all needed updates committed….. [see above re. 'npm logout', 'npm login' if switching from one NPM account to another] # For Typescript projects: add "build": "tsc" to package.json compile the project with: npm run build # For scopes package, for first release you must add switch: --access public : npm [--auth-type=legacy] publish # auth-type defaults to browser See version and publish time at very top under module name; version to right at https://www.npmjs.com/package/ To increment version / republish: Update the version number in package.json, any segment(s). Compare last-published version to current version: npm show $(npm pkg get name | sed 's:"::g;') version npm pkg get version # current version npm version patch # increments version+=1 and commits to local code repos BUT DOES NOT PUSH! Or set major, minor, "1.2.3". The lower segments automatically => 0. GOTCHA! If you accidentally run this earlier, you can recover by running: git reset --hard If project has executable scripts with yargs, or any other code reporting version, update those versions to matcḣ. TODO: Consider a package.json script command to automatically update yargs version values according to package.json. git push # The publish would work with local content, but to have git repos times match, do this! npm [--auth-type=legacy] publish # auth-type defaults to browser. PUBLISHES LOCAL CONTENT! See https://www.npmjs.com/package/ To update the dependency module versions pulled into my project, run npm up [pkg] # Updates all dep modules which have available minor upgrades # Unfortunately 'update' doesn't report what it updates, only a module count, # and іt takes no options other than -g. npm outdated # Run anytime to see all available dependency upgrades To update a dependency major version: npm in pkgname@newMajorVersion [I have a not about updating to absolute latest, but not working for me: npm in pkgname] Show dependencies: npm ls [-a] See this for how to update a single package across major versions: npm in pkg@latest BIN COMMAND SCRIPTS I will call "command scripts" the consumer-intended node that consumers are intended to use for invocation. On UNIX, command bin are always sym-links pointing to the real source scripts inside of installed module dirs (with special situation that npm-link-created /usr/lib/node_modules/X module dir links are not real installed module dirs).. For installed-for-you global bins, you can only check /bin or on Win because these point right to package scripts. The .../npm_modules/.../.bin dirs are for 2nd-level (and higher) bin scripts not installed for your usage). The links for these are all relative symlinks pointing elsewhere under the same npm_modules. GOTCHA! Contrary to docs, and idiosyncractically, you MUST provide interpreter line in bin scripts. For installs for UNIX shells, the real source script is executed (via symlinks). Apparently the npm cmd-wrapper-builder depends on seeing interpreter because fails ever for Windows without it. GOTCHA! As long as the JSON formatting is correct, you will get no warning or any indication of bin config mistakes, like conflicting entries or missing files. The build will continue as if the bad entries were absent. /usr/bin/x or %APPDATA%/node/x via "npm -g i" and 'npm link" [N.b. %APPDATA% resolves to .../AppData/Roaming, not to .../AppData] /node_modules/.bin/ directory is for binary dependencies of current project, not for the binary outputs of the current project. Whether current project has an output bin configured or not, ./node_modules/bin/ has binaries from all locally installed modules, not mine. If my project has output bins configured, only the original source script exists. Bin links are only ever created outside of this modules' directories, when my module is installed -g (to /usr/bin/ on UNIX and %APPDATA%/node/ on Windows) ODD that %APPDATA%/node/ contains both bin scripts and node_libraries/. some other module installs my package locally, it goes to the depending projects ./node_modules/.bin Either simplest case of ONE scripts to be invoked with precise module name, just set bin = "local/script/path.js": npm pkg set bin=local/script/path.js anything else: Simply add package.json bin map entries from final-script-invocation-names -> script-filepaths-local-to-module-dir Path for script in current directory can simply be 'x.js'. Tarballing Only formats *.tar, *tar.gz, *.ar supported. Default *.tgz. npm pack [--pack-destination other/dir] # make name-version.tgz for $PWD package; chmod +x's your scripts! npm pack pkg-spec # fetches the package tarball to $PWD. GOTCHA: Remove *.tgz when done unless excluded via .gitignore or .npmignore! Otherwise all *.tgz's will get published. Good practice is to cp .gitignore to .ingore and add *tgz entry to latter. Benefit of this is, you still get reminder of lingering junk when you run "git status -s". DUAL-MODE es5+es6 publishing: In "package.json" type to module Set main to the es6 entry script. No path, and use suffix ".mjs" (for Module). ["main" is probably never used, since both entry-points are specified in the exports element]. Add an export element like this: "exports": [ { "require": "./bcplus-es5.cjs" }, "./bcplus-es6.mjs" ],