Skip to content

Commit c5361e8

Browse files
respencer-nclclaude
andcommitted
Add npm packaging via sbt-ossuminc and publish to GitHub Packages
Wire up With.Packaging.npm() and With.Publishing.npm() from sbt-ossuminc 1.2.5-4 for riddlLibJS. Switch Scala.js output from CommonJS to ESModule to match package.json declaration. Simplify npm-publish.yml workflow to use sbt tasks instead of custom shell scripting. Remove misleading export default from TypeScript declarations. Published @ossuminc/riddl-lib@1.2.3-1-aef48695-20260203-2217 to GitHub Packages npm registry. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent aef4869 commit c5361e8

6 files changed

Lines changed: 97 additions & 145 deletions

File tree

.github/workflows/npm-publish.yml

Lines changed: 12 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ on:
88
registry:
99
description: 'Registry to publish to'
1010
required: true
11-
default: 'both'
11+
default: 'github'
1212
type: choice
1313
options:
14-
- npmjs
1514
- github
16-
- both
15+
- npmjs
1716

1817
jobs:
1918
build-and-publish:
@@ -59,146 +58,21 @@ jobs:
5958
with:
6059
node-version: '22'
6160

62-
- name: Build Scala.js
63-
run: sbt --batch riddlLibJS/fullLinkJS
64-
65-
- name: Get version from sbt
66-
id: version
67-
run: |
68-
VERSION=$(sbt --batch "print riddlLibJS/version" 2>/dev/null | grep -v "\[info\]" | grep -v "loading" | tail -1 | tr -d ' ')
69-
echo "version=$VERSION" >> $GITHUB_OUTPUT
70-
echo "Version: $VERSION"
71-
72-
- name: Prepare npm package
73-
run: |
74-
# Find the output directory
75-
OUTPUT_DIR=$(find riddlLib/js/target -type d -name "*-opt" | head -1)
76-
echo "Output directory: $OUTPUT_DIR"
77-
78-
# Copy TypeScript definitions
79-
cp riddlLib/js/types/index.d.ts "$OUTPUT_DIR/"
80-
81-
# Create package.json from template with version and TypeScript support
82-
cat > "$OUTPUT_DIR/package.json" << EOF
83-
{
84-
"name": "@ossuminc/riddl-lib",
85-
"version": "${{ steps.version.outputs.version }}",
86-
"description": "RIDDL Language Library - JavaScript/TypeScript bindings",
87-
"main": "main.js",
88-
"types": "index.d.ts",
89-
"type": "module",
90-
"exports": {
91-
".": {
92-
"types": "./index.d.ts",
93-
"import": "./main.js"
94-
}
95-
},
96-
"files": [
97-
"main.js",
98-
"main.js.map",
99-
"index.d.ts"
100-
],
101-
"keywords": [
102-
"riddl",
103-
"ddd",
104-
"domain-driven-design",
105-
"parser",
106-
"ast",
107-
"typescript"
108-
],
109-
"author": "Ossum Inc.",
110-
"license": "Apache-2.0",
111-
"repository": {
112-
"type": "git",
113-
"url": "https://github.com/ossuminc/riddl.git"
114-
},
115-
"bugs": {
116-
"url": "https://github.com/ossuminc/riddl/issues"
117-
},
118-
"homepage": "https://github.com/ossuminc/riddl#readme",
119-
"publishConfig": {
120-
"access": "public"
121-
}
122-
}
123-
EOF
124-
125-
# Create README
126-
cat > "$OUTPUT_DIR/README.md" << 'EOF'
127-
# @ossuminc/riddl-lib
128-
129-
RIDDL Language Library - JavaScript/TypeScript bindings for the RIDDL parser.
130-
131-
## Installation
132-
133-
```bash
134-
npm install @ossuminc/riddl-lib
135-
```
136-
137-
## Usage
138-
139-
```typescript
140-
import { RiddlAPI } from '@ossuminc/riddl-lib';
141-
142-
// Parse a RIDDL source string
143-
const result = RiddlAPI.parseString(`
144-
domain Banking is {
145-
context Accounts is {
146-
entity Account is { ??? }
147-
}
148-
}
149-
`);
150-
151-
if (result.succeeded) {
152-
console.log("Domains:", result.value.domains);
153-
} else {
154-
console.error("Errors:", RiddlAPI.formatErrorArray(result.errors));
155-
}
156-
```
157-
158-
## API
159-
160-
- `RiddlAPI.parseString(source, origin?, verbose?)` - Parse RIDDL source to AST
161-
- `RiddlAPI.parseNebula(source, origin?, verbose?)` - Parse arbitrary definitions
162-
- `RiddlAPI.parseToTokens(source, origin?, verbose?)` - Tokenize for syntax highlighting
163-
- `RiddlAPI.validateString(source, origin?, verbose?, noANSI?)` - Full validation
164-
- `RiddlAPI.version` - Library version string
165-
- `RiddlAPI.buildInfo` - Detailed build information
166-
- `RiddlAPI.formatErrorArray(errors)` - Format errors as string
167-
- `RiddlAPI.errorsToStrings(errors)` - Convert errors to string array
168-
169-
## Documentation
170-
171-
See [RIDDL Documentation](https://ossum.tech/riddl/) for more information.
172-
173-
## License
174-
175-
Apache-2.0
176-
EOF
177-
178-
echo "PACKAGE_DIR=$OUTPUT_DIR" >> $GITHUB_ENV
61+
- name: Publish to GitHub Packages
62+
if: github.event_name == 'release' || github.event.inputs.registry == 'github'
63+
run: sbt --batch riddlLibJS/npmPublishGithub
17964

18065
- name: Publish to npmjs.com
181-
if: github.event_name == 'release' || github.event.inputs.registry == 'npmjs' || github.event.inputs.registry == 'both'
66+
if: github.event.inputs.registry == 'npmjs'
18267
env:
183-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
184-
run: |
185-
cd "$PACKAGE_DIR"
186-
npm config set //registry.npmjs.org/:_authToken "$NODE_AUTH_TOKEN"
187-
npm publish --access public
188-
continue-on-error: true
68+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
69+
run: sbt --batch riddlLibJS/npmPublishNpmjs
18970

190-
- name: Publish to GitHub Packages
191-
if: github.event_name == 'release' || github.event.inputs.registry == 'github' || github.event.inputs.registry == 'both'
71+
- name: Get version for summary
72+
id: version
19273
run: |
193-
cd "$PACKAGE_DIR"
194-
npm config set //npm.pkg.github.com/:_authToken "$GITHUB_TOKEN"
195-
npm config set @ossuminc:registry https://npm.pkg.github.com
196-
197-
# Update package.json for GitHub Packages
198-
jq '.publishConfig.registry = "https://npm.pkg.github.com"' package.json > package.json.tmp
199-
mv package.json.tmp package.json
200-
201-
npm publish --access public
74+
VERSION=$(sbt --batch "print riddlLibJS/version" 2>/dev/null | grep -v "\[info\]" | grep -v "loading" | tail -1 | tr -d ' ')
75+
echo "version=$VERSION" >> $GITHUB_OUTPUT
20276
20377
- name: Generate summary
20478
run: |

CLAUDE.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,16 @@ The `riddlLib` module exports a TypeScript-friendly API via `RiddlAPI` object.
112112
- Case classes → Plain objects
113113
- `Either``{ succeeded, value, errors }`
114114

115-
**Building npm packages**:
115+
**Building npm packages** (via sbt-ossuminc helpers):
116+
```bash
117+
sbt riddlLibJS/npmPrepare # Assemble package (pure sbt)
118+
sbt riddlLibJS/npmPack # Create .tgz tarball
119+
sbt riddlLibJS/npmPublishGithub # Publish to GH Packages
120+
```
121+
122+
**Legacy script** (still works):
116123
```bash
117124
./scripts/pack-npm-modules.sh riddlLib
118-
# Creates: npm-packages/ossuminc-riddl-lib-<version>.tgz
119125
```
120126

121127
**Documentation**:
@@ -652,3 +658,8 @@ Then add to root aggregation: `.aggregate(..., mymodule, mymoduleJS, mymoduleNat
652658
18. **FileBuilder requires PlatformContext** - `trait FileBuilder(using PlatformContext)` — all subclasses must propagate the using clause
653659
19. **Scala 3.7.4 default param limitation** - Case class defaults can't resolve givens from a subsequent using clause in generated apply; remove defaults or provide explicit givens
654660
20. **@JSExportTopLevel incompatible with using clauses** - Don't use on case classes that have `(using PlatformContext)` in a second parameter list
661+
21. **npm packaging uses sbt-ossuminc helpers** - `With.Packaging.npm()` assembles package, `With.Publishing.npm()` publishes. Tasks: `npmPrepare`, `npmPack`, `npmPublishGithub`
662+
22. **JS variant baseDirectory is `module/js/`** - The `npmTypesDir` convention looks for `baseDir/js/types/` which doubles to `module/js/js/types/`. Override with `.jsSettings(NpmPackaging.Keys.npmTypesDir := baseDirectory.value / "types")`
663+
23. **npm requires --tag for prerelease versions** - sbt-dynver versions like `1.2.3-1-hash` are prerelease per npm semver. Must pass `--tag dev` when publishing
664+
24. **riddlLib JS is ESModule** - Changed from CommonJS (`withCommonJSModule = true` removed). Package.json has `"type": "module"`. Consumers use `import { RiddlAPI } from '@ossuminc/riddl-lib'`
665+
25. **gh auth needs write:packages for npm** - Run `gh auth refresh -s write:packages` if publishing to GH Packages npm registry

NOTEBOOK.md

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This is the central engineering notebook for the RIDDL project. It tracks curren
66

77
## Current Status
88

9-
**Last Updated**: February 3, 2026
9+
**Last Updated**: February 3, 2026 (evening)
1010

1111
**Scala Version**: 3.7.4 (overrides sbt-ossuminc's 3.3.7 LTS default due to
1212
compiler infinite loop bug with opaque types/intersection types in 3.3.x).
@@ -18,6 +18,11 @@ Scala.js. Added `(using PlatformContext)` to `FileBuilder` trait and
1818
propagated through entire hierarchy. All tests pass. Published to
1919
GitHub Packages. Merged to main.
2020

21+
**npm Package Published**: `@ossuminc/riddl-lib@1.2.3-1-aef48695-20260203-2217`
22+
published to GitHub Packages npm registry. ESModule format with TypeScript
23+
declarations. Consumable via `npm install @ossuminc/riddl-lib@dev` with
24+
`@ossuminc:registry=https://npm.pkg.github.com` in `.npmrc`.
25+
2126
**Packaging Infrastructure**: Docker, npm, and TypeScript support added:
2227
- `Dockerfile` — Multi-stage build with custom JRE via jlink (~80-100MB image)
2328
- `docker-publish.yml` — CI workflow for Docker image publishing to ghcr.io
@@ -156,6 +161,56 @@ The `pseudoCodeBlock` parser now allows comments before and/or after `???`:
156161

157162
## Session Log
158163

164+
### February 3, 2026 (npm Package Publishing to GitHub Packages)
165+
166+
**Focus**: Publish `@ossuminc/riddl-lib` as npm package to GH Packages
167+
for consumption by Synapify and ossum.ai
168+
169+
**Key Finding**: Most infrastructure already existed (TypeScript
170+
declarations, package.json template, npm-publish.yml workflow). The
171+
sbt-ossuminc plugin (1.2.5-4) already had `With.Packaging.npm()` and
172+
`With.Publishing.npm()` helpers ready to use.
173+
174+
**Work Completed**:
175+
1. Updated sbt-ossuminc to 1.2.5-4-4a8a48fb-20260203-2208
176+
(locally published version with npm packaging helpers)
177+
2. Fixed Scala.js module kind: changed from CommonJS to ESModule
178+
(`withCommonJSModule = true` removed). Package.json already
179+
declared `"type": "module"` so this resolved the mismatch.
180+
3. Wired up `With.Packaging.npm()` for riddlLibJS with scope
181+
`@ossuminc`, keywords, and ESModule flag
182+
4. Wired up `With.Publishing.npm(registries = Seq("github"))`
183+
5. Fixed `npmTypesDir` convention mismatch: JS variant's
184+
`baseDirectory` is `riddlLib/js/`, so convention looked at
185+
`riddlLib/js/js/types/` (wrong). Overrode to
186+
`baseDirectory / "types"`.
187+
6. Removed `export default RiddlAPI` from index.d.ts (ESModule
188+
uses named exports only)
189+
7. Published `@ossuminc/riddl-lib@1.2.3-1-aef48695-20260203-2217`
190+
to GitHub Packages npm registry with `--tag dev`
191+
192+
**Issues Encountered**:
193+
- npm requires `--tag` for prerelease versions (sbt-dynver format
194+
`1.2.3-1-hash-date` is a prerelease). The `NpmPublishing` helper
195+
in sbt-ossuminc needs updating to handle this automatically.
196+
- `gh auth` needed `write:packages` scope refresh for npm publishing
197+
(`gh auth refresh -s write:packages`)
198+
199+
**Files Modified**:
200+
- `project/plugins.sbt` — sbt-ossuminc version bump
201+
- `build.sbt` — ESModule, npm packaging/publishing config, import
202+
- `riddlLib/js/types/index.d.ts` — removed default export
203+
204+
**Next Steps**:
205+
- Simplify `.github/workflows/npm-publish.yml` to use sbt tasks
206+
- Fix sbt-ossuminc `NpmPublishing` to pass `--tag dev` for
207+
prerelease versions
208+
- Test consumption from Synapify and ossum.ai
209+
- When ready for release, tag a clean version (e.g., `1.2.4`) to
210+
get a proper semver npm version
211+
212+
---
213+
159214
### February 3, 2026 (Release 1.2.3 - System.lineSeparator Fix)
160215

161216
**Focus**: Comprehensive fix for `System.lineSeparator()` returning

build.sbt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import org.scoverage.coveralls.Imports.CoverallsKeys.coverallsTokenFile
22
import com.ossuminc.sbt.OssumIncPlugin
3+
import com.ossuminc.sbt.helpers.NpmPackaging
34
import com.typesafe.tools.mima.core.{ProblemFilters, ReversedMissingMethodProblem}
45
import sbt.Append.{appendSeqImplicit, appendSet}
56
import sbt.Keys.{description, libraryDependencies, scalacOptions}
@@ -306,8 +307,21 @@ lazy val riddlLib_cp: CrossProject = CrossModule("riddlLib", "riddl-lib")(JS, JV
306307
.jvmSettings(
307308
coverageExcludedFiles := """<empty>;$anon"""
308309
)
309-
.jsConfigure(With.ScalaJS("RIDDL: riddl-lib", withCommonJSModule = true))
310+
.jsConfigure(With.ScalaJS("RIDDL: riddl-lib"))
310311
.jsConfigure(With.noMiMa)
312+
.jsConfigure(With.Packaging.npm(
313+
scope = "@ossuminc",
314+
pkgName = "riddl-lib",
315+
pkgDescription = "RIDDL Language Library - JavaScript/TypeScript bindings",
316+
keywords = Seq("riddl", "ddd", "domain-driven-design", "parser", "ast", "typescript"),
317+
esModule = true
318+
))
319+
.jsSettings(
320+
NpmPackaging.Keys.npmTypesDir := Some(baseDirectory.value / "types")
321+
)
322+
.jsConfigure(With.Publishing.npm(
323+
registries = Seq("github")
324+
))
311325
.nativeConfigure(With.Native(mode = "fast", buildTarget = "static"))
312326
.nativeConfigure(With.noMiMa)
313327
val riddlLib = riddlLib_cp.jvm

project/plugins.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// GitHub Packages resolver for sbt-ossuminc
22
resolvers += "GitHub Packages" at "https://maven.pkg.github.com/ossuminc/sbt-ossuminc"
33

4-
addSbtPlugin("com.ossuminc" % "sbt-ossuminc" % "1.2.5")
4+
addSbtPlugin("com.ossuminc" % "sbt-ossuminc" % "1.2.5-4-4a8a48fb-20260203-2208")
55

66
// This enables sbt-bloop to create bloop config files for Metals editors
77
// Uncomment locally if you use metals, otherwise don't slow down other

riddlLib/js/types/index.d.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,5 +387,3 @@ export declare const RiddlAPI: {
387387
formatInfo: string;
388388
};
389389

390-
// Default export for CommonJS compatibility
391-
export default RiddlAPI;

0 commit comments

Comments
 (0)