Skip to content

Commit 3ccc208

Browse files
committed
feat: publish to NPM instead of JSR
The package is published to NPM now, instead of JSR. The TypeScript sources are compiled to JavaScript using `@swc/core` and the type declarations are emitted using TypeScript 7. Both steps run from the `prepublishOnly` hook into the `npm/` folder, which is what `exports` points to. This mirrors the setup used in `nRFCloud/billing-service-proto`. `semantic-release` publishes via `@semantic-release/npm` instead of `@sebbo2002/semantic-release-jsr`.
1 parent fc35ff1 commit 3ccc208

12 files changed

Lines changed: 405 additions & 19 deletions

.github/workflows/test-and-release.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ jobs:
2121
with:
2222
node-version: ">=24.18.1 <25"
2323
cache: "npm"
24+
registry-url: "https://registry.npmjs.org"
2425

2526
- name: Install NPM version specified in package.json
2627
uses: ./.github/actions/install-npm
@@ -33,6 +34,4 @@ jobs:
3334
- run: npm test
3435

3536
- name: Semantic release
36-
run: |
37-
npm install -D @sebbo2002/semantic-release-jsr
38-
npx semantic-release
37+
run: npx semantic-release

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
node_modules/
2+
npm/

.npm/compile.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Compile source for NPM
3+
*/
4+
5+
import swc from '@swc/core'
6+
import { mkdirSync, rmSync, writeFileSync } from 'node:fs'
7+
import { glob } from 'node:fs/promises'
8+
import path, { dirname } from 'node:path'
9+
import { fileURLToPath } from 'node:url'
10+
import tsconfig from './tsconfig.npm.json' with { type: 'json' }
11+
import { updateImports } from './updateImports.ts'
12+
13+
const __dirname = dirname(fileURLToPath(import.meta.url))
14+
15+
const outDir = path.join(__dirname, '..', 'npm')
16+
17+
try {
18+
rmSync(outDir, { recursive: true, force: true })
19+
} catch {
20+
// pass
21+
}
22+
23+
for await (const file of glob(
24+
tsconfig.include.map((include) => path.join('.npm', include)),
25+
)) {
26+
if (file.endsWith('.spec.ts') || file.endsWith('.test.ts')) continue
27+
let compiled = (
28+
await swc.transformFile(file, {
29+
jsc: {
30+
parser: {
31+
syntax: 'typescript',
32+
},
33+
target: 'es2024',
34+
},
35+
module: {
36+
type: 'es6',
37+
},
38+
})
39+
).code
40+
41+
compiled = updateImports(compiled)
42+
43+
const targetFile = path.join(outDir, file.replace(/\.ts$/, '.js'))
44+
45+
mkdirSync(dirname(targetFile), { recursive: true })
46+
47+
writeFileSync(targetFile, compiled, 'utf8')
48+
49+
console.log(file)
50+
}

.npm/tsconfig.npm.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"compilerOptions": {
4+
"emitDeclarationOnly": true,
5+
"declaration": true,
6+
"noEmit": false,
7+
"rootDir": ".."
8+
},
9+
"include": ["../*.ts"],
10+
"exclude": ["../*.spec.ts", "../*.test.ts"]
11+
}

.npm/updateImports.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import assert from 'node:assert'
2+
import { describe, it } from 'node:test'
3+
import { updateImports } from './updateImports.ts'
4+
5+
void describe('updateImports', () => {
6+
void it('replaces .ts with .js in relative imports', () => {
7+
const input = `import { foo } from './bar.ts';`
8+
const expected = `import { foo } from './bar.js';`
9+
assert.equal(updateImports(input), expected)
10+
})
11+
})

.npm/updateImports.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const updateImports = (source: string): string =>
2+
source.replace(/from ['"](.+?)\.ts['"]/g, "from '$1.js'")

CONTRIBUTING.md

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Contributing
22

33
`@nrfcloud/validate-with-typebox` is a published library. Releases are published
4-
to [JSR](https://jsr.io/@nrfcloud/validate-with-typebox) automatically by
5-
`semantic-release` on merge to `main`.
4+
to [NPM](https://www.npmjs.com/package/@nrfcloud/validate-with-typebox)
5+
automatically by `semantic-release` on merge to `main`.
66

77
## Development setup
88

@@ -28,11 +28,24 @@ to [JSR](https://jsr.io/@nrfcloud/validate-with-typebox) automatically by
2828
1. Get the code reviewed.
2929
1. Once approved and CI passes, rebase or squash away!
3030

31+
## Building the NPM package
32+
33+
The package is published as compiled JavaScript with type declarations in the
34+
`npm/` folder, which is created by the `prepublishOnly` hook:
35+
36+
1. [`.npm/compile.ts`](.npm/compile.ts) transpiles the TypeScript sources using
37+
[`@swc/core`](https://www.npmjs.com/package/@swc/core) and rewrites the `.ts`
38+
import specifiers to `.js`.
39+
1. [TypeScript 7](https://www.npmjs.com/package/typescript) emits the type
40+
declarations, using [`.npm/tsconfig.npm.json`](.npm/tsconfig.npm.json).
41+
42+
Run `npm run prepublishOnly` to build it locally.
43+
3144
## Releasing a new version
3245

3346
1. [`semantic-release` in the Test&Release workflow](.github/workflows/test-and-release.yaml)
3447
takes care of creating a new GitHub release and publishing the package to
35-
[JSR](https://jsr.io/@nrfcloud/validate-with-typebox).
48+
[NPM](https://www.npmjs.com/package/@nrfcloud/validate-with-typebox).
3649

3750
Once a new version is published, consumers can bump the
3851
`@nrfcloud/validate-with-typebox` dependency to pick it up.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# `@nrfcloud/validate-with-typebox`
22

3-
<https://jsr.io/@nrfcloud/validate-with-typebox>
3+
<https://www.npmjs.com/package/@nrfcloud/validate-with-typebox>
44

55
Helper function to validate data with TypeBox schemas.
66

77
## Install with NPM
88

99
```bash
10-
npx jsr add (--save-prod|--save-dev) @nrfcloud/validate-with-typebox
10+
npm i (--save-prod|--save-dev) @nrfcloud/validate-with-typebox
1111
```
1212

1313
## Usage

jsr.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)