From b20dcbfaa4fa962df2b26be53174a09f7ea143aa Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sat, 23 Nov 2024 15:36:16 +0100 Subject: [PATCH 01/24] feat(learn): add article for publishing a typescript package --- apps/site/navigation.json | 4 ++++ apps/site/pages/en/learn/typescript/publishing.md | 7 +++++++ packages/i18n/locales/en.json | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 apps/site/pages/en/learn/typescript/publishing.md diff --git a/apps/site/navigation.json b/apps/site/navigation.json index 850e6899a0681..b3f5d409046bc 100644 --- a/apps/site/navigation.json +++ b/apps/site/navigation.json @@ -209,6 +209,10 @@ "runNatively": { "link": "/learn/typescript/run-natively", "label": "components.navigation.learn.typescript.links.runNatively" + }, + "publishing": { + "link": "/learn/typescript/publishing", + "label": "components.navigation.learn.typescript.links.publishing" } } }, diff --git a/apps/site/pages/en/learn/typescript/publishing.md b/apps/site/pages/en/learn/typescript/publishing.md new file mode 100644 index 0000000000000..a7dc37969c12e --- /dev/null +++ b/apps/site/pages/en/learn/typescript/publishing.md @@ -0,0 +1,7 @@ +--- +title: Publishing a TypeScript package +layout: learn +authors: JakobJingleheimer +--- + +# Publishing a TypeScript package diff --git a/packages/i18n/locales/en.json b/packages/i18n/locales/en.json index b26a0ab739471..e7155f420337b 100644 --- a/packages/i18n/locales/en.json +++ b/packages/i18n/locales/en.json @@ -48,7 +48,8 @@ "introduction": "Introduction to TypeScript", "transpile": "Running TypeScript code using transpilation", "run": "Running TypeScript with a runner", - "runNatively": "Running TypeScript Natively" + "runNatively": "Running TypeScript Natively", + "publishing": "Publishing a TypeScript package" } }, "asynchronousWork": { From 2d5d3595576e925013130b7176bb46f07b3dcbe9 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 29 Dec 2024 16:23:15 +0100 Subject: [PATCH 02/24] WIP: initial content for article --- .../pages/en/learn/typescript/publishing.md | 176 ++++++++++++++++++ 1 file changed, 176 insertions(+) diff --git a/apps/site/pages/en/learn/typescript/publishing.md b/apps/site/pages/en/learn/typescript/publishing.md index a7dc37969c12e..4d4917457e393 100644 --- a/apps/site/pages/en/learn/typescript/publishing.md +++ b/apps/site/pages/en/learn/typescript/publishing.md @@ -5,3 +5,179 @@ authors: JakobJingleheimer --- # Publishing a TypeScript package + +This article augments TypeScript's [Publishing guide](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) with specifics for native node support. + +Some important things to note: + +- Node runs typescript via a process called "type stripping", wherein node (via SWC under the hood of [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. + + - Node does **not** strip types in `node_modules`. This decision was at the request of TypeScript maintainers because it can cause significant performance issues for the official compiler (`tsc`). + +- TypeScript-specific features like `enum` still require a flag ([`--experimental-transform-types`](https://nodejs.org/api/typescript.html#typescript-features)) + +## What to do with your types + +### Treat them like a test + +The purpose of types are to warn an implementation will not work: + +```ts +const foo = 'a'; +const bar: number = 1 + foo; +// ^^^ Type 'string' is not assignable to type 'number'. +``` + +TypeScript has warned you that the above code will not behave as intended, just like a unit test warns you code does not behave as intended. + +Your IDE (ex VS Code) likely has built-in support for TypeScript, displaying errors as you work. If not, and/or you missed those, CI will have your back. + +```yaml displayName=".github/workflows/ci.yml" +name: Tests + +on: + push: + branches: ['main'] + pull_request: + branches: ['main'] + +jobs: + lint-and-check-types: + # Separate these from tests because + # they are platform and node-version independent. + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'npm' + - name: npm clean install + run: npm ci + - run: node --run lint + - run: node --run types:check + + test: + runs-on: ubuntu-latest + + strategy: + matrix: + node: + - version: 23.x + - version: 22.x + # glob is not backported below 22.x + fail-fast: false # prevent a failure in one version cancelling other runs + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node.version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node.version }} + cache: 'npm' + - name: npm clean install + run: npm ci + - run: node --run test +``` + +```json displayName="package.json" +{ + "version": "0.0.0", + "name": "example-ts-pkg", + "scripts": { + "lint": "…", + "types:check": "tsc --noEmit" + }, + "optionalDependencies": { + // This is used only in CI. + // Marking it 'optional' avoids installing on your local + // (where you probably won't use it). + "typescript": "^5.7.2" + } +} +``` + +```json displayName="tsconfig.json" +{ + "compilerOptions": { + "declarationMap": true, + "declaration": true, + "emitDeclarationOnly": true, + "esModuleInterop": true, // Flux Capacitor: The universe breaks without it, but nobody knows what it does. + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ESNext" + }, + // These may be different for your repo: + "include": "./src", + "exclude": ["**/*/*.test.*"] +} +``` + +### Generating type declarations + +Type declarations (`.d.ts` and friends) provide type information as a sidecar file, allowing the execution code to be vanilla JavaScript whilst still having types. + +Since these are generated based on source code, they can be built as part of your publication process and do not need to be checked into your repository. + +Take the following example (a [GitHub Action](https://github.com/features/actions)), where the type declarations are generated just before publishing to the NPM registry. + +```yaml displayName=".github/workflows/publish.yml" +name: Publish to NPM +on: + push: + tags: + - '**@*' + +jobs: + build: + runs-on: ubuntu-latest + + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + registry-url: 'https://registry.npmjs.org' + - run: npm ci + + # You can probably ignore the boilerplate config above + + - name: Generate types + run: node --run types:generate + + - name: Publish with provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm publish --access public --provenance +``` + +```diff displayName="package.json" +{ + "name": "example-ts-pkg", + "scripts": { + "types:check": "tsc --noEmit", ++ "types:generate": "tsc" + } +} +``` + +```text displayName=".npmignore" +*.test.* +*.fixture.* +fixture.* +fixtures +``` + +#### Breaking this down + +Generating type declarations is deterministic: you'll get the same output from the same input, every time. So there is no need to commit these to git. + +[`npm publish`](https://docs.npmjs.com/cli/v11/commands/npm-publish) grabs everything applicable and available at the moment the command is run; so generating type declarations immediately before means those are available and will get picked up. + +By default, `npm publish` grabs (almost) everything (see [Files included in package](https://docs.npmjs.com/cli/v11/commands/npm-publish#files-included-in-package)). In order to keep your published package minimal (see the "Heaviest Objects in the Universe" meme about `node_modules`), you want to exclude certain files (like tests and test fixtures) from from packaging. From 86394b6641b9e1606662528016ebc8b224ed2487 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:41:40 +0100 Subject: [PATCH 03/24] WIP: polish sample code, & dir overviews --- .../pages/en/learn/typescript/publishing.md | 110 ++++++++++++------ 1 file changed, 76 insertions(+), 34 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing.md b/apps/site/pages/en/learn/typescript/publishing.md index 4d4917457e393..fb77f566e6416 100644 --- a/apps/site/pages/en/learn/typescript/publishing.md +++ b/apps/site/pages/en/learn/typescript/publishing.md @@ -6,21 +6,60 @@ authors: JakobJingleheimer # Publishing a TypeScript package -This article augments TypeScript's [Publishing guide](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) with specifics for native node support. +This article augments TypeScript's own [Publishing guide](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) with specifics for native node support. Some important things to note: -- Node runs typescript via a process called "type stripping", wherein node (via SWC under the hood of [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. +- Everything from [][../modules/publishing-a-package] applies here. - - Node does **not** strip types in `node_modules`. This decision was at the request of TypeScript maintainers because it can cause significant performance issues for the official compiler (`tsc`). +- Node runs TypeScript via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. -- TypeScript-specific features like `enum` still require a flag ([`--experimental-transform-types`](https://nodejs.org/api/typescript.html#typescript-features)) + - Node does **not** strip types in `node_modules` because it can cause significant performance issues for the official TypeScript compiler (`tsc`), so the TypeScript maintainers would like to discourage people publishing raw TypeScript, at least for now. + +- Consuming TypeScript-specific features like `enum` in node still require a flag ([`--experimental-transform-types`](https://nodejs.org/api/typescript.html#typescript-features)). There are often better alternatives for these anyway. + +- Use [dependabot](https://docs.github.com/en/code-security/dependabot) to keep your dependencies current, including those in github actions. It's a very easy set-and-forget configuration. + +- `.nvmrc` comes from [NVM](https://github.com/nvm-sh/nvm), a multi-version manager for node. It allows you to specify the version of node the project should generally use. + +A published package will look something like: + +```text displayName="Published example TypeScript package (directory overview)" +example-ts-pkg/ +├ LICENSE +├ main.d.ts +├ main.js +├ package.json +├ README.md +├ some-util.d.ts +└ some-util.js +``` + +That would be derived from a repository looking something like: + +```text displayName="Source of the example TypeScript package (directory overview)" +example-ts-pkg/ +├ .github/ +┆ ├ workflows/ +┆ ┆ ├ ci.yml +┆ ┆ └ publish.yml +┆ └ dependabot.yml +├ src/ +┆ ├ foo.fixture.js +┆ ├ main.ts +┆ ├ main.test.ts +┆ ├ some-util.ts +┆ └ some-util.test.ts +├ LICENSE +├ package.json +└ README.md +``` ## What to do with your types -### Treat them like a test +### Treat types like a test -The purpose of types are to warn an implementation will not work: +The purpose of types is to warn an implementation will not work: ```ts const foo = 'a'; @@ -28,7 +67,7 @@ const bar: number = 1 + foo; // ^^^ Type 'string' is not assignable to type 'number'. ``` -TypeScript has warned you that the above code will not behave as intended, just like a unit test warns you code does not behave as intended. +TypeScript has warned that the above code will not behave as intended, just like a unit test warns that code does not behave as intended. Your IDE (ex VS Code) likely has built-in support for TypeScript, displaying errors as you work. If not, and/or you missed those, CI will have your back. @@ -36,15 +75,14 @@ Your IDE (ex VS Code) likely has built-in support for TypeScript, displaying err name: Tests on: - push: - branches: ['main'] pull_request: branches: ['main'] jobs: - lint-and-check-types: + check-types: # Separate these from tests because - # they are platform and node-version independent. + # they are platform and node-version independent + # and need be run only once. runs-on: ubuntu-latest @@ -56,7 +94,7 @@ jobs: cache: 'npm' - name: npm clean install run: npm ci - - run: node --run lint + # You may want to run a lint check here too - run: node --run types:check test: @@ -67,12 +105,11 @@ jobs: node: - version: 23.x - version: 22.x - # glob is not backported below 22.x - fail-fast: false # prevent a failure in one version cancelling other runs + fail-fast: false # Prevent a failure in one version cancelling other runs steps: - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node.version }} + - name: Use node ${{ matrix.node.version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node.version }} @@ -84,16 +121,16 @@ jobs: ```json displayName="package.json" { - "version": "0.0.0", "name": "example-ts-pkg", "scripts": { - "lint": "…", + "test": "node --test", "types:check": "tsc --noEmit" }, "optionalDependencies": { // This is used only in CI. - // Marking it 'optional' avoids installing on your local - // (where you probably won't use it). + // Avoid bloating your local node_modules + // (where you probably won't use it) by + // running `npm install --omit="optional"` "typescript": "^5.7.2" } } @@ -102,21 +139,28 @@ jobs: ```json displayName="tsconfig.json" { "compilerOptions": { - "declarationMap": true, + "allowArbitraryExtensions": true, + "allowImportingTsExtensions": true, + "baseUrl": "./", "declaration": true, - "emitDeclarationOnly": true, - "esModuleInterop": true, // Flux Capacitor: The universe breaks without it, but nobody knows what it does. + "declarationMap": true, + "esModuleInterop": true, // Flux Capacitor: The universe breaks without it, but nobody knows exactly what it does. + "lib": ["ESNext"], "module": "NodeNext", "moduleResolution": "NodeNext", + "outDir": "./", + "resolveJsonModule": true, + "resolvePackageJsonExports": true, + "resolvePackageJsonImports": true, "target": "ESNext" }, // These may be different for your repo: - "include": "./src", - "exclude": ["**/*/*.test.*"] + "include": ["./src"], + "exclude": ["**/*/*.test.*", "**/fixtures/**"] } ``` -### Generating type declarations +### Generate type declarations Type declarations (`.d.ts` and friends) provide type information as a sidecar file, allowing the execution code to be vanilla JavaScript whilst still having types. @@ -148,9 +192,6 @@ jobs: # You can probably ignore the boilerplate config above - - name: Generate types - run: node --run types:generate - - name: Publish with provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -161,23 +202,24 @@ jobs: { "name": "example-ts-pkg", "scripts": { - "types:check": "tsc --noEmit", -+ "types:generate": "tsc" ++ "prepack": "tsc", + "types:check": "tsc --noEmit" } } ``` ```text displayName=".npmignore" -*.test.* -*.fixture.* -fixture.* +*.ts +!*.d.ts fixtures ``` +`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](https://nodejs.org/api/cli.html#intentional-limitations). You can't use `node --run` for this step, so that is not a caveat here, but it can be for other steps. + #### Breaking this down Generating type declarations is deterministic: you'll get the same output from the same input, every time. So there is no need to commit these to git. [`npm publish`](https://docs.npmjs.com/cli/v11/commands/npm-publish) grabs everything applicable and available at the moment the command is run; so generating type declarations immediately before means those are available and will get picked up. -By default, `npm publish` grabs (almost) everything (see [Files included in package](https://docs.npmjs.com/cli/v11/commands/npm-publish#files-included-in-package)). In order to keep your published package minimal (see the "Heaviest Objects in the Universe" meme about `node_modules`), you want to exclude certain files (like tests and test fixtures) from from packaging. +By default, `npm publish` grabs (almost) everything (see [Files included in package](https://docs.npmjs.com/cli/v11/commands/npm-publish#files-included-in-package)). In order to keep your published package minimal (see the "Heaviest Objects in the Universe" meme about `node_modules`), you want to exclude certain files (like tests and test fixtures) from from packaging. Add these to the opt-out list specified in [`.npmignore`](https://docs.npmjs.com/cli/v11/using-npm/developers#keeping-files-out-of-your-package); ensure the `!*.d.ts` exception is listed, or the generated type declartions will not be published! Alternatively, you can use [package.json "files"](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#files) to create an opt-in list. From d583e03bdcd415cded86b8dbdec96022214a5d0a Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 29 Dec 2024 22:45:16 +0100 Subject: [PATCH 04/24] rename article to be more specific --- apps/site/navigation.json | 6 +++--- .../{publishing.md => publishing-a-ts-project.md} | 4 ++-- packages/i18n/locales/en.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename apps/site/pages/en/learn/typescript/{publishing.md => publishing-a-ts-project.md} (99%) diff --git a/apps/site/navigation.json b/apps/site/navigation.json index b3f5d409046bc..7d09802a7796a 100644 --- a/apps/site/navigation.json +++ b/apps/site/navigation.json @@ -210,9 +210,9 @@ "link": "/learn/typescript/run-natively", "label": "components.navigation.learn.typescript.links.runNatively" }, - "publishing": { - "link": "/learn/typescript/publishing", - "label": "components.navigation.learn.typescript.links.publishing" + "publishingTSProject": { + "link": "/learn/typescript/publishing-a-ts-project", + "label": "components.navigation.learn.typescript.links.publishing-a-ts-project" } } }, diff --git a/apps/site/pages/en/learn/typescript/publishing.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md similarity index 99% rename from apps/site/pages/en/learn/typescript/publishing.md rename to apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index fb77f566e6416..c6222324f632d 100644 --- a/apps/site/pages/en/learn/typescript/publishing.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -1,10 +1,10 @@ --- -title: Publishing a TypeScript package +title: Publishing a TypeScript project layout: learn authors: JakobJingleheimer --- -# Publishing a TypeScript package +# Publishing a TypeScript project This article augments TypeScript's own [Publishing guide](https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) with specifics for native node support. diff --git a/packages/i18n/locales/en.json b/packages/i18n/locales/en.json index e7155f420337b..04d81decb0aba 100644 --- a/packages/i18n/locales/en.json +++ b/packages/i18n/locales/en.json @@ -49,7 +49,7 @@ "transpile": "Running TypeScript code using transpilation", "run": "Running TypeScript with a runner", "runNatively": "Running TypeScript Natively", - "publishing": "Publishing a TypeScript package" + "publishingTSProject": "Publishing a TypeScript project" } }, "asynchronousWork": { From 48e2ad965830f91f4866e800be77548c5cc11cd6 Mon Sep 17 00:00:00 2001 From: Augustin Mauroy Date: Sun, 29 Dec 2024 23:21:16 +0100 Subject: [PATCH 05/24] fix unsuported lang --- apps/site/shiki.config.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/site/shiki.config.mjs b/apps/site/shiki.config.mjs index d28ee4d3a8ecf..941987ac84bc0 100644 --- a/apps/site/shiki.config.mjs +++ b/apps/site/shiki.config.mjs @@ -8,6 +8,7 @@ import powershellLanguage from 'shiki/langs/powershell.mjs'; import shellScriptLanguage from 'shiki/langs/shellscript.mjs'; import shellSessionLanguage from 'shiki/langs/shellsession.mjs'; import typeScriptLanguage from 'shiki/langs/typescript.mjs'; +import yamlLanguage from 'shiki/langs/yaml.mjs'; import shikiNordTheme from 'shiki/themes/nord.mjs'; /** @@ -29,6 +30,7 @@ export const LANGUAGES = [ ...shellSessionLanguage, ...dockerLanguage, ...diffLanguage, + ...yamlLanguage, ]; // This is the default theme we use for our Shiki Syntax Highlighter From 081b7f266119367407070259a48f8bf010e9be8d Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 29 Dec 2024 23:30:53 +0000 Subject: [PATCH 06/24] fix navigation.json Co-authored-by: Augustin Mauroy Signed-off-by: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> --- apps/site/navigation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/site/navigation.json b/apps/site/navigation.json index 7d09802a7796a..3bc282ebd74b8 100644 --- a/apps/site/navigation.json +++ b/apps/site/navigation.json @@ -212,7 +212,7 @@ }, "publishingTSProject": { "link": "/learn/typescript/publishing-a-ts-project", - "label": "components.navigation.learn.typescript.links.publishing-a-ts-project" + "label": "components.navigation.learn.typescript.links.publishingTSProject" } } }, From 2a2020285758dcd26f3c1b261c5179d88453e5f5 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 30 Dec 2024 13:01:52 +0100 Subject: [PATCH 07/24] fix links --- .../site/pages/en/learn/typescript/publishing-a-ts-project.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index c6222324f632d..d177de1e332d3 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -10,7 +10,7 @@ This article augments TypeScript's own [Publishing guide](https://www.typescript Some important things to note: -- Everything from [][../modules/publishing-a-package] applies here. +- Everything from [Publishing a package](../modules/publishing-a-package) applies here. - Node runs TypeScript via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. @@ -214,7 +214,7 @@ jobs: fixtures ``` -`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](https://nodejs.org/api/cli.html#intentional-limitations). You can't use `node --run` for this step, so that is not a caveat here, but it can be for other steps. +`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that is not a caveat here, but it can be for other steps. #### Breaking this down From 52d3a130326ba218e479322925d5859678edc16c Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 30 Dec 2024 13:02:43 +0100 Subject: [PATCH 08/24] extract note from codeblock into article --- .../pages/en/learn/typescript/publishing-a-ts-project.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index d177de1e332d3..a7c2b8a3e1400 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -127,10 +127,6 @@ jobs: "types:check": "tsc --noEmit" }, "optionalDependencies": { - // This is used only in CI. - // Avoid bloating your local node_modules - // (where you probably won't use it) by - // running `npm install --omit="optional"` "typescript": "^5.7.2" } } @@ -160,6 +156,8 @@ jobs: } ``` +Pro-tip: The TypeScript executable (`tsc`) is likely used only in CI. Avoid bloating your local node_modules (where you probably won't use it) by adding [`--omit="optional"`](https://docs.npmjs.com/cli/v11/commands/npm-install#omit) when you run `npm install` locally: `npm install --omit="optional"` + ### Generate type declarations Type declarations (`.d.ts` and friends) provide type information as a sidecar file, allowing the execution code to be vanilla JavaScript whilst still having types. From 2228ab360ee1b9ab5435c48a50bef3dcd9d0e57d Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 30 Dec 2024 13:02:59 +0100 Subject: [PATCH 09/24] tidy codeblocks --- .../typescript/publishing-a-ts-project.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index a7c2b8a3e1400..5273136cad2a3 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -40,16 +40,16 @@ That would be derived from a repository looking something like: ```text displayName="Source of the example TypeScript package (directory overview)" example-ts-pkg/ ├ .github/ -┆ ├ workflows/ -┆ ┆ ├ ci.yml -┆ ┆ └ publish.yml -┆ └ dependabot.yml + ├ workflows/ + ├ ci.yml + └ publish.yml + └ dependabot.yml ├ src/ -┆ ├ foo.fixture.js -┆ ├ main.ts -┆ ├ main.test.ts -┆ ├ some-util.ts -┆ └ some-util.test.ts + ├ foo.fixture.js + ├ main.ts + ├ main.test.ts + ├ some-util.ts + └ some-util.test.ts ├ LICENSE ├ package.json └ README.md @@ -123,7 +123,7 @@ jobs: { "name": "example-ts-pkg", "scripts": { - "test": "node --test", + "test": "node --test './src/**/*.test.ts'", "types:check": "tsc --noEmit" }, "optionalDependencies": { From 50349180b63eceef8abbd009afe404ae679ccdcf Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 30 Dec 2024 13:03:07 +0100 Subject: [PATCH 10/24] wordsmith --- .../pages/en/learn/typescript/publishing-a-ts-project.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 5273136cad2a3..b3718c3b4db41 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -12,7 +12,7 @@ Some important things to note: - Everything from [Publishing a package](../modules/publishing-a-package) applies here. -- Node runs TypeScript via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. +- Node runs TypeScript code via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. - Node does **not** strip types in `node_modules` because it can cause significant performance issues for the official TypeScript compiler (`tsc`), so the TypeScript maintainers would like to discourage people publishing raw TypeScript, at least for now. @@ -71,6 +71,8 @@ TypeScript has warned that the above code will not behave as intended, just like Your IDE (ex VS Code) likely has built-in support for TypeScript, displaying errors as you work. If not, and/or you missed those, CI will have your back. +The following [GitHub Action](https://github.com/features/actions) sets up a CI task to automatically check (and require) types pass inspection for a PR into the `main` branch. + ```yaml displayName=".github/workflows/ci.yml" name: Tests @@ -164,7 +166,7 @@ Type declarations (`.d.ts` and friends) provide type information as a sidecar fi Since these are generated based on source code, they can be built as part of your publication process and do not need to be checked into your repository. -Take the following example (a [GitHub Action](https://github.com/features/actions)), where the type declarations are generated just before publishing to the NPM registry. +Take the following example, where the type declarations are generated just before publishing to the NPM registry. ```yaml displayName=".github/workflows/publish.yml" name: Publish to NPM From ddb1cf11447cdf99bc8f388bf8e3ac1a7f805b15 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 6 Jan 2025 18:35:09 +0100 Subject: [PATCH 11/24] fixup!: remove controversial "optionalDependencies" --- .../site/pages/en/learn/typescript/publishing-a-ts-project.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index b3718c3b4db41..c8bcc9ee3d0ac 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -128,7 +128,7 @@ jobs: "test": "node --test './src/**/*.test.ts'", "types:check": "tsc --noEmit" }, - "optionalDependencies": { + "devDependencies": { "typescript": "^5.7.2" } } @@ -158,8 +158,6 @@ jobs: } ``` -Pro-tip: The TypeScript executable (`tsc`) is likely used only in CI. Avoid bloating your local node_modules (where you probably won't use it) by adding [`--omit="optional"`](https://docs.npmjs.com/cli/v11/commands/npm-install#omit) when you run `npm install` locally: `npm install --omit="optional"` - ### Generate type declarations Type declarations (`.d.ts` and friends) provide type information as a sidecar file, allowing the execution code to be vanilla JavaScript whilst still having types. From 9258389ebd64d2e62a5e732ea6a2039d17c9000f Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 8 Jan 2025 19:48:30 +0100 Subject: [PATCH 12/24] fixup!: wordsmith & align code samples --- .../learn/typescript/publishing-a-ts-project.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index c8bcc9ee3d0ac..2d46c4cd8eb4e 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -12,11 +12,11 @@ Some important things to note: - Everything from [Publishing a package](../modules/publishing-a-package) applies here. -- Node runs TypeScript code via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default of node version 23.6.0. +- Node runs TypeScript code via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default as of node version 23.6.0. - - Node does **not** strip types in `node_modules` because it can cause significant performance issues for the official TypeScript compiler (`tsc`), so the TypeScript maintainers would like to discourage people publishing raw TypeScript, at least for now. + - Node does **not** strip types in `node_modules` because it can cause significant performance issues for the official TypeScript compiler (`tsc`) and parts of VS Code, so the TypeScript maintainers would like to discourage people publishing raw TypeScript, at least for now. -- Consuming TypeScript-specific features like `enum` in node still require a flag ([`--experimental-transform-types`](https://nodejs.org/api/typescript.html#typescript-features)). There are often better alternatives for these anyway. +- Consuming TypeScript-specific features like `enum` in node still requires a flag ([`--experimental-transform-types`](https://nodejs.org/api/typescript.html#typescript-features)). There are often better alternatives for these anyway. - Use [dependabot](https://docs.github.com/en/code-security/dependabot) to keep your dependencies current, including those in github actions. It's a very easy set-and-forget configuration. @@ -28,10 +28,12 @@ A published package will look something like: example-ts-pkg/ ├ LICENSE ├ main.d.ts +├ main.d.ts.map ├ main.js ├ package.json ├ README.md ├ some-util.d.ts +├ some-util.d.ts.map └ some-util.js ``` @@ -154,7 +156,7 @@ jobs: }, // These may be different for your repo: "include": ["./src"], - "exclude": ["**/*/*.test.*", "**/fixtures/**"] + "exclude": ["**/*/*.test.*", "**/*.fixture.*"] } ``` @@ -179,7 +181,6 @@ jobs: permissions: contents: read - id-token: write steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -209,10 +210,10 @@ jobs: ```text displayName=".npmignore" *.ts !*.d.ts -fixtures +*.fixture.* ``` -`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that is not a caveat here, but it can be for other steps. +`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that caveat does not apply here, but it can for other steps. #### Breaking this down From 4906609ccdd32225b0883e67a7f02cc1c93bbf5c Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 8 Jan 2025 21:20:41 +0100 Subject: [PATCH 13/24] fixup!: tsconfig --- .../pages/en/learn/typescript/publishing-a-ts-project.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 2d46c4cd8eb4e..7b4989b1a0c46 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -140,19 +140,13 @@ jobs: { "compilerOptions": { "allowArbitraryExtensions": true, - "allowImportingTsExtensions": true, - "baseUrl": "./", "declaration": true, "declarationMap": true, - "esModuleInterop": true, // Flux Capacitor: The universe breaks without it, but nobody knows exactly what it does. "lib": ["ESNext"], "module": "NodeNext", - "moduleResolution": "NodeNext", "outDir": "./", "resolveJsonModule": true, - "resolvePackageJsonExports": true, - "resolvePackageJsonImports": true, - "target": "ESNext" + "rewriteRelativeImportExtensions": true }, // These may be different for your repo: "include": ["./src"], From 07095c6927df3e6c06ad557dbf04e5e83f71e086 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 9 Jan 2025 00:22:46 +0100 Subject: [PATCH 14/24] fixup!: switch sequence of repo vs package --- .../typescript/publishing-a-ts-project.md | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 7b4989b1a0c46..8fcb89ee64b4f 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -22,22 +22,7 @@ Some important things to note: - `.nvmrc` comes from [NVM](https://github.com/nvm-sh/nvm), a multi-version manager for node. It allows you to specify the version of node the project should generally use. -A published package will look something like: - -```text displayName="Published example TypeScript package (directory overview)" -example-ts-pkg/ -├ LICENSE -├ main.d.ts -├ main.d.ts.map -├ main.js -├ package.json -├ README.md -├ some-util.d.ts -├ some-util.d.ts.map -└ some-util.js -``` - -That would be derived from a repository looking something like: +A repository would look something like: ```text displayName="Source of the example TypeScript package (directory overview)" example-ts-pkg/ @@ -54,7 +39,23 @@ example-ts-pkg/ └ some-util.test.ts ├ LICENSE ├ package.json -└ README.md +├ README.md +└ tsconfig.json +``` + +And its published package would look something like: + +```text displayName="Published example TypeScript package (directory overview)" +example-ts-pkg/ +├ LICENSE +├ main.d.ts +├ main.d.ts.map +├ main.js +├ package.json +├ README.md +├ some-util.d.ts +├ some-util.d.ts.map +└ some-util.js ``` ## What to do with your types From 33e744a76edf96014a7d7218b3e6b42ea29ee0a6 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 9 Jan 2025 00:23:27 +0100 Subject: [PATCH 15/24] fixup!: note types and unit tests are complementary --- apps/site/pages/en/learn/typescript/publishing-a-ts-project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 8fcb89ee64b4f..ca7e3c1639b26 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -70,7 +70,7 @@ const bar: number = 1 + foo; // ^^^ Type 'string' is not assignable to type 'number'. ``` -TypeScript has warned that the above code will not behave as intended, just like a unit test warns that code does not behave as intended. +TypeScript has warned that the above code will not behave as intended, just like a unit test warns that code does not behave as intended. They are complementary and verify different things—you should have both. Your IDE (ex VS Code) likely has built-in support for TypeScript, displaying errors as you work. If not, and/or you missed those, CI will have your back. From f1703ad5a35b869284fb9d265f734de65704c03f Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 9 Jan 2025 00:23:44 +0100 Subject: [PATCH 16/24] =?UTF-8?q?fixup!:=20`IDE`=20=E2=86=92=20`editor`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/site/pages/en/learn/typescript/publishing-a-ts-project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index ca7e3c1639b26..b5e8dafbbed0c 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -72,7 +72,7 @@ const bar: number = 1 + foo; TypeScript has warned that the above code will not behave as intended, just like a unit test warns that code does not behave as intended. They are complementary and verify different things—you should have both. -Your IDE (ex VS Code) likely has built-in support for TypeScript, displaying errors as you work. If not, and/or you missed those, CI will have your back. +Your editor (ex VS Code) likely has built-in support for TypeScript, displaying errors as you work. If not, and/or you missed those, CI will have your back. The following [GitHub Action](https://github.com/features/actions) sets up a CI task to automatically check (and require) types pass inspection for a PR into the `main` branch. From 3fd80769453c964d82f800f888543218f7dad67a Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:57:28 +0100 Subject: [PATCH 17/24] fixup!: note file extensions in package.json fields (js vs ts) --- .../site/pages/en/learn/typescript/publishing-a-ts-project.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index b5e8dafbbed0c..cf14eeb8c6267 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -12,6 +12,10 @@ Some important things to note: - Everything from [Publishing a package](../modules/publishing-a-package) applies here. + - Fields like `main` operate on _published_ content, so when TypeScript source-code is transpiled to JavaScript, JavaScript is the published content and `main` would point to a JavaScript file with a JavaScript file extension (ex `main.ts` → `"main": "main.js"`). + + - Fields like `scripts.test` operate on source-code, so they would use the file extensions of the source code (ex `"test": "node --test './src/**/*.test.ts'`). + - Node runs TypeScript code via a process called "[type stripping](https://nodejs.org/api/typescript.html#type-stripping)", wherein node (via [Amaro](https://github.com/nodejs/amaro)) removes TypeScript-specific syntax, leaving behind vanilla JavaScript (which node already understands). This behaviour is enabled by default as of node version 23.6.0. - Node does **not** strip types in `node_modules` because it can cause significant performance issues for the official TypeScript compiler (`tsc`) and parts of VS Code, so the TypeScript maintainers would like to discourage people publishing raw TypeScript, at least for now. From 64fd53116577494dfdacf86f67f67f692376754e Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Mon, 13 Jan 2025 22:50:08 +0100 Subject: [PATCH 18/24] fixup!: add alternative samples & configs --- .../typescript/publishing-a-ts-project.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index cf14eeb8c6267..9ac1809a69056 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -47,6 +47,48 @@ example-ts-pkg/ └ tsconfig.json ``` +```text displayName="(alt 1) Source of the example TypeScript package (directory overview)" +example-ts-pkg/ +├ .github/ + ├ workflows/ + ├ ci.yml + └ publish.yml + └ dependabot.yml +├ src/ + ├ __test__ + ├ foo.fixture.js + ├ main.test.ts + ├ main.ts + └ some-util.ts + ├ __test__ + └ some-util.test.ts + └ some-util.ts +├ LICENSE +├ package.json +├ README.md +└ tsconfig.json +``` + +```text displayName="(alt 2) Source of the example TypeScript package (directory overview)" +example-ts-pkg/ +├ .github/ + ├ workflows/ + ├ ci.yml + └ publish.yml + └ dependabot.yml +├ src/ + ├ main.ts + ├ some-util.ts +├ test/ + ├ foo.fixture.js + ├ main.ts + └ some-util.ts +├ LICENSE +├ package.json +├ README.md +└ tsconfig.json +``` + And its published package would look something like: ```text displayName="Published example TypeScript package (directory overview)" @@ -62,6 +104,22 @@ example-ts-pkg/ └ some-util.js ``` +```text displayName="(alt) Published example TypeScript package (directory overview)" +example-ts-pkg/ +├ dist/ + ├ main.d.ts + ├ main.d.ts.map + ├ main.js + ├ some-util.d.ts + ├ some-util.d.ts.map + └ some-util.js +├ LICENSE +├ package.json +└ README.md +``` + +A note about directory organisation: There are a few common practices for placing tests. Principle of least knowledge says to co-locate them (put them adjacent to implementation). Sometimes, that's in the same directory, or within a drawer like a `__test__` (also adjacent to the implementation, "alt 1"). Alternatively, some opt to create a `test/` sibling to `src/` ("alt 2"), either with a mirrored structure or a "junk drawer". + ## What to do with your types ### Treat types like a test @@ -159,6 +217,8 @@ jobs: } ``` +Note that test files may well have a different `tsconfig.json` applied (hence why they are excluded in the above sample). + ### Generate type declarations Type declarations (`.d.ts` and friends) provide type information as a sidecar file, allowing the execution code to be vanilla JavaScript whilst still having types. @@ -212,6 +272,11 @@ jobs: *.fixture.* ``` +```text displayName="(alt: dist/) .npmignore" +src +test +``` + `npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that caveat does not apply here, but it can for other steps. #### Breaking this down From 7305f8e769c680c2be5080f81160c21d1ca0abf2 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:31:09 +0100 Subject: [PATCH 19/24] fixup!: remove version from npm links --- .../pages/en/learn/typescript/publishing-a-ts-project.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 9ac1809a69056..9d42039351a6d 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -277,12 +277,12 @@ src test ``` -`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/v11/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that caveat does not apply here, but it can for other steps. +`npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that caveat does not apply here, but it can for other steps. #### Breaking this down Generating type declarations is deterministic: you'll get the same output from the same input, every time. So there is no need to commit these to git. -[`npm publish`](https://docs.npmjs.com/cli/v11/commands/npm-publish) grabs everything applicable and available at the moment the command is run; so generating type declarations immediately before means those are available and will get picked up. +[`npm publish`](https://docs.npmjs.com/cli/commands/npm-publish) grabs everything applicable and available at the moment the command is run; so generating type declarations immediately before means those are available and will get picked up. -By default, `npm publish` grabs (almost) everything (see [Files included in package](https://docs.npmjs.com/cli/v11/commands/npm-publish#files-included-in-package)). In order to keep your published package minimal (see the "Heaviest Objects in the Universe" meme about `node_modules`), you want to exclude certain files (like tests and test fixtures) from from packaging. Add these to the opt-out list specified in [`.npmignore`](https://docs.npmjs.com/cli/v11/using-npm/developers#keeping-files-out-of-your-package); ensure the `!*.d.ts` exception is listed, or the generated type declartions will not be published! Alternatively, you can use [package.json "files"](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#files) to create an opt-in list. +By default, `npm publish` grabs (almost) everything (see [Files included in package](https://docs.npmjs.com/cli/commands/npm-publish#files-included-in-package)). In order to keep your published package minimal (see the "Heaviest Objects in the Universe" meme about `node_modules`), you want to exclude certain files (like tests and test fixtures) from from packaging. Add these to the opt-out list specified in [`.npmignore`](https://docs.npmjs.com/cli/using-npm/developers#keeping-files-out-of-your-package); ensure the `!*.d.ts` exception is listed, or the generated type declartions will not be published! Alternatively, you can use [package.json "files"](https://docs.npmjs.com/cli/configuring-npm/package-json#files) to create an opt-in list. From 13b8e1cf82cc2e26a9c1bd5d6293a3a637ed0bf5 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:49:00 +0100 Subject: [PATCH 20/24] fixup!: shorter code sample display names --- .../pages/en/learn/typescript/publishing-a-ts-project.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 9d42039351a6d..1b5eeeddd3e5c 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -28,7 +28,7 @@ Some important things to note: A repository would look something like: -```text displayName="Source of the example TypeScript package (directory overview)" +```text displayName="Directory overview the example TypeScript package" example-ts-pkg/ ├ .github/ ├ workflows/ @@ -47,7 +47,7 @@ example-ts-pkg/ └ tsconfig.json ``` -```text displayName="(alt 1) Source of the example TypeScript package (directory overview)" +```text displayName="(alt 1) Directory overview the example TypeScript package (directory overview)" example-ts-pkg/ ├ .github/ ├ workflows/ @@ -69,7 +69,7 @@ example-ts-pkg/ └ tsconfig.json ``` -```text displayName="(alt 2) Source of the example TypeScript package (directory overview)" +```text displayName="(alt 2) Directory overview the example TypeScript package (directory overview)" example-ts-pkg/ ├ .github/ ├ workflows/ From 0f7f993d8848c4c58389c52d2dce71b442b56e1b Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:24:55 +0100 Subject: [PATCH 21/24] fixup!: add note about `NPM_TOKEN` --- apps/site/pages/en/learn/typescript/publishing-a-ts-project.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index 1b5eeeddd3e5c..b546b1c923484 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -279,6 +279,8 @@ test `npm publish` will automatically run [`prepack` beforehand](https://docs.npmjs.com/cli/using-npm/scripts#npm-publish). `npm` will also run `prepack` automatically before `npm pack --dry-run` (so you can easily see what your published package will be without actually publishing it). **Beware**, [`node --run` does _not_ do that](../command-line/run-nodejs-scripts-from-the-command-line.md#using-the---run-flag). You can't use `node --run` for this step, so that caveat does not apply here, but it can for other steps. +The `NPM_TOKEN` within `publish.yml` is an [npm access token](https://docs.npmjs.com/about-access-tokens). It must be added it to your [github **repository** secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository). + #### Breaking this down Generating type declarations is deterministic: you'll get the same output from the same input, every time. So there is no need to commit these to git. From 53793f183ecc410ba2d643b67432861be612aef8 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:42:13 +0100 Subject: [PATCH 22/24] fixup!: switch node version matrix to LTS matrix action --- .../typescript/publishing-a-ts-project.md | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index b546b1c923484..e3998fe56762d 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -139,11 +139,13 @@ Your editor (ex VS Code) likely has built-in support for TypeScript, displaying The following [GitHub Action](https://github.com/features/actions) sets up a CI task to automatically check (and require) types pass inspection for a PR into the `main` branch. ```yaml displayName=".github/workflows/ci.yml" +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + name: Tests on: pull_request: - branches: ['main'] + branches: ['*'] jobs: check-types: @@ -164,22 +166,38 @@ jobs: # You may want to run a lint check here too - run: node --run types:check - test: + get-matrix: + # Automatically pick active LTS versions runs-on: ubuntu-latest + outputs: + latest: ${{ steps.set-matrix.outputs.requireds }} + steps: + - uses: ljharb/actions/node/matrix@main + id: set-matrix + with: + versionsAsRoot: true + type: majors + preset: '>= 22' # glob is not backported below 22.x + + test: + needs: [get-matrix] + runs-on: ${{ matrix.os }} strategy: + fail-fast: false matrix: - node: - - version: 23.x - - version: 22.x - fail-fast: false # Prevent a failure in one version cancelling other runs + node-version: ${{ fromJson(needs.get-matrix.outputs.latest) }} + os: + - macos-latest + - ubuntu-latest + - windows-latest steps: - uses: actions/checkout@v4 - - name: Use node ${{ matrix.node.version }} + - name: Use node ${{ matrix.node-version }} uses: actions/setup-node@v4 with: - node-version: ${{ matrix.node.version }} + node-version: ${{ matrix.node-version }} cache: 'npm' - name: npm clean install run: npm ci @@ -228,6 +246,8 @@ Since these are generated based on source code, they can be built as part of you Take the following example, where the type declarations are generated just before publishing to the NPM registry. ```yaml displayName=".github/workflows/publish.yml" +# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json + name: Publish to NPM on: push: From 4b06b6cefaad443b8bd3b315502a4cb55ed0e6cf Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:53:57 +0100 Subject: [PATCH 23/24] fixup!: shorten displayNames (they were breaking page layout) --- .../en/learn/typescript/publishing-a-ts-project.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index e3998fe56762d..ac52257e7d1fd 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -26,9 +26,9 @@ Some important things to note: - `.nvmrc` comes from [NVM](https://github.com/nvm-sh/nvm), a multi-version manager for node. It allows you to specify the version of node the project should generally use. -A repository would look something like: +A directory overview of a repository would look something like: -```text displayName="Directory overview the example TypeScript package" +```text displayName="Files co-located" example-ts-pkg/ ├ .github/ ├ workflows/ @@ -47,7 +47,7 @@ example-ts-pkg/ └ tsconfig.json ``` -```text displayName="(alt 1) Directory overview the example TypeScript package (directory overview)" +```text displayName="Files co-located but segregated" example-ts-pkg/ ├ .github/ ├ workflows/ @@ -69,7 +69,7 @@ example-ts-pkg/ └ tsconfig.json ``` -```text displayName="(alt 2) Directory overview the example TypeScript package (directory overview)" +```text displayName="'src' and 'test' fully segregated" example-ts-pkg/ ├ .github/ ├ workflows/ @@ -89,9 +89,9 @@ example-ts-pkg/ └ tsconfig.json ``` -And its published package would look something like: +And a directory overview of its published package would look something like: -```text displayName="Published example TypeScript package (directory overview)" +```text displayName="Fully flat" example-ts-pkg/ ├ LICENSE ├ main.d.ts @@ -104,7 +104,7 @@ example-ts-pkg/ └ some-util.js ``` -```text displayName="(alt) Published example TypeScript package (directory overview)" +```text displayName="With 'dist'" example-ts-pkg/ ├ dist/ ├ main.d.ts From d250a86d56128cff65f93320c92235e3bc8d840e Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 15 Jan 2025 22:58:14 +0100 Subject: [PATCH 24/24] fixup!: update references to samples --- apps/site/pages/en/learn/typescript/publishing-a-ts-project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md index ac52257e7d1fd..e504a5a7b6730 100644 --- a/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md +++ b/apps/site/pages/en/learn/typescript/publishing-a-ts-project.md @@ -118,7 +118,7 @@ example-ts-pkg/ └ README.md ``` -A note about directory organisation: There are a few common practices for placing tests. Principle of least knowledge says to co-locate them (put them adjacent to implementation). Sometimes, that's in the same directory, or within a drawer like a `__test__` (also adjacent to the implementation, "alt 1"). Alternatively, some opt to create a `test/` sibling to `src/` ("alt 2"), either with a mirrored structure or a "junk drawer". +A note about directory organisation: There are a few common practices for placing tests. Principle of least knowledge says to co-locate them (put them adjacent to implementation). Sometimes, that's in the same directory, or within a drawer like a `__test__` (also adjacent to the implementation, "Files co-located but segregated"). Alternatively, some opt to create a `test/` sibling to `src/` ("'src' and 'test' fully segregated"), either with a mirrored structure or a "junk drawer". ## What to do with your types