- TypeScript 87%
- JavaScript 13%
|
|
||
|---|---|---|
| scripts | ||
| src | ||
| template | ||
| tests | ||
| .gitignore | ||
| CHANGELOG.md | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
Introduction
This template scaffolds a npm-package-like workspace. The generated workspace is configured for TypeScript and provides basic structures for documentation and change management.
Additional templates exist to scaffold more specific package types:
| Template | Purpose |
|---|---|
create-ts-lib |
This template scaffolds a TypeScript library package providing basic structures to build, bundle, test, and publish a distributable library. |
create-template |
This template scaffolds a package that is itself a template for other packages. |
Table of Contents
Quick Start
# placeholder:
# <TEMPLATE_PACKAGE_NAME: @temir.ra/create-workspace
# <TEMPLATE_NAME: @temir.ra/workspace
# print the latest version
npm info "@temir.ra/create-workspace" version
# create/update a package from the template in the current directory
npm create --no-install --no-git "@temir.ra/workspace@latest" .
# set metadata in package.json
npm update
Documentation
The following sections explain the configurations and conventions baked into the generated package. Useful when adapting it to fit specific needs.
package.json
See npmjs documentation on package.json for detailed explanations of all fields.
{
"name": "",
"version": "0.0.0",
"description": "",
"private": true,
"keywords": [],
"author": "",
"license": "",
"repository": {
"type": "git",
"url": ""
},
"scripts": {
// deletes node_modules and lockfiles, then re-installs
"reinstall": "rm -rf node_modules && rm -f package-lock.json bun.lock yarn.lock pnpm-lock.yaml && npm install",
// type-checks the project without emitting output
"typecheck": "tsc --noEmit",
// executes the script in watch mode
"dev": "tsx --watch scripts/dev.ts"
},
"devDependencies": {
"@types/node": "latest",
"tsx": "latest",
"typescript": "^6.0.3"
}
}
⚠️ Some scripts may not work on Windows out of the box due to the use of Unix-specific commands (e.g. rm). Some execution environments (e.g. Bun) ship with a builtin bash-compatible CLI that can run these scripts without modification. Alternatively, Windows users can configure npm to use a compatible shell (e.g. Git Bash) by setting the script-shell config:
# placeholder:
# <PATH_TO_SHELL: <PATH_TO_SHELL>
# e.g. C:\Program Files\Git\bin\bash.exe
npm config set script-shell "<PATH_TO_SHELL>"
tsconfig.json
See the TypeScript documentation on tsconfig.json for detailed explanations of all options.
{
"compilerOptions": {
// ECMAScript version of emitted output; ESNext targets the latest JS version supported by the TypeScript compiler
// if the package must support older runtimes or browsers, pin to a specific year (e.g. "ES2022", "ES2024")
"target": "ESNext",
// output module format; ESNext passes ES module syntax through unchanged
// ES module syntax: import/export statements (as opposed to CommonJS require()/module.exports)
"module": "ESNext",
// type definitions for built-in APIs
"lib": [
"ESNext"
],
// module resolution strategy; bundler mode allows omitting file extensions in imports
"moduleResolution": "bundler",
// enables all strict type-checking options
"strict": true,
// enforces import type for type-only imports; emitted module syntax matches source exactly
"verbatimModuleSyntax": true,
// array indexing and index signature access returns T | undefined instead of T
"noUncheckedIndexedAccess": true,
// distinguishes absent optional properties from those explicitly set to undefined
"exactOptionalPropertyTypes": true,
// requires explicit override keyword when overriding base class methods
"noImplicitOverride": true,
// requires explicit types on all exported declarations; enables parallel .d.ts generation by external tools
"isolatedDeclarations": true,
// allows default imports from CommonJS modules
"esModuleInterop": true,
// enables project references and incremental builds via *.tsbuildinfo
"composite": true,
// do not type-check `.d.ts` files in `node_modules/`
"skipLibCheck": true,
// explicitly set global type definitions
// if omitted, all types from `@types/*` dependencies are included automatically
"types": [
"node"
],
// enforce consistent casing across import statements
"forceConsistentCasingInFileNames": true,
// allows importing JSON files as typed modules
"resolveJsonModule": true
},
// files matched by include are type-checked and visible to the IDE (IntelliSense, go-to-definition, etc.)
"include": [
"scripts/**/*.ts"
],
// files matched by exclude are hidden from the IDE and excluded from type-checking
"exclude": [
"node_modules/"
]
}
Workspaces
To extend the package into a workspace root, add the workspaces field to package.json and run npm update:
{
// ... ,
"workspaces": [
"packages/*"
],
// ...
}
All workspace dependencies are installed into a single shared node_modules/ at the workspace root and symlinks are created for each workspace package by its package name.
workspace_root/
├── node_modules/ ← shared dependencies
├── package.json ← root
└── packages/
├── pkg-a/
│ ├── node_modules/ ← pkg-a's dependencies symlinked from the root
│ ├── package.json ← "@scope/pkg-a"
│ └── ...
└── pkg-b/
├── node_modules/ ← pkg-b's dependencies symlinked from the root
├── package.json ← "@scope/pkg-b"
└── ...
workspace_root/packages/pkg-b/package.json:
{
// ... ,
"dependencies": {
"@scope/pkg-a": "latest"
}
// ...
}
Scaffolding Patterns
On a high level, the process of scaffolding packages with this template is as follows:
- Scaffold a workspace package from this template.
- Scaffold workspace packages inside it.
- Add
workspacestoworkspace_root/package.jsonand list the paths to the workspace packages. - Add dependencies between workspace packages as needed.
npm updateto install dependencies and create symlinks.
Package Registry
# placeholder:
# <SCOPE_WITHOUT_AT: <SCOPE_WITHOUT_AT>
# <REGISTRY_ORIGIN_AND_PATH: <REGISTRY_ORIGIN_AND_PATH>
# e.g.
# registry.npmjs.org/
# forgejo.example.com/api/packages/<SCOPE_WITHOUT_AT>/npm/
# <REGISTRY_AUTH_TOKEN_ENV_VAR: <REGISTRY_AUTH_TOKEN_ENV_VAR>
Scope Registry
~/.npmrc or .npmrc:
@<SCOPE_WITHOUT_AT>:registry=https://<REGISTRY_ORIGIN_AND_PATH>
//<REGISTRY_ORIGIN_AND_PATH>:_authToken=${<REGISTRY_AUTH_TOKEN_ENV_VAR>}
~/.bunfig.toml or bunfig.toml:
[install.scopes]
"<SCOPE_WITHOUT_AT>" = { url = "https://<REGISTRY_ORIGIN_AND_PATH>", token = "$<REGISTRY_AUTH_TOKEN_ENV_VAR>" }
Auth
For official npm registry (npmjs.org), run npm login to authenticate.
For custom registries, follow the registry's instructions to obtain an auth token, then set it in the environment variable '<REGISTRY_AUTH_TOKEN_ENV_VAR>'.
export <REGISTRY_AUTH_TOKEN_ENV_VAR>=<AUTH_TOKEN>
$env:<REGISTRY_AUTH_TOKEN_ENV_VAR> = "<AUTH_TOKEN>"
DevOps
npm install
npm update
npm run clean
npm run build
npm run tests
npx tsx dist/cli.bundle.js -- example/
Change Management
- Create a new branch for the change.
- Make the changes and commit.
- Bump the version in
package.json. - Add an entry for the new version in
CHANGELOG.md. - Pull-request the branch.
- Ensure package artifacts are current.
- Publish.
Publish
~/.npmrc or .npmrc:
@temir.ra:registry=https://registry.npmjs.org/
~/.bunfig.toml or bunfig.toml:
[install.scopes]
"temir.ra" = { url = "https://registry.npmjs.org/" }
# registry.npmjs.org/
npm login
npm publish