DO NOT USE -- Very untested and doesn't work well with deno doc
Module concatenator for large Deno libraries (prototype).
- Concatenates your Deno TypeScript library to a single
.js
file with a corresponding single.d.ts
file.- JS output somewhat similar to input.
- Very simple module concatenation. Code is written in such a way that it will be easy to switch to module declarations in the future once stage 3 and supported in TypeScript.
- JS output somewhat similar to input.
- Unfurls your import map in the output—resolves remote module specifiers.
- Allows you to use import maps in your library.
- Type checks the outputted declaration file.
- Runs integration tests on the outputted JavaScript code using the
corresponding
x.test.ts
file for the entrypoint (ex.mod.test.ts
formod.ts
).
Non goals:
- Minification—instead the output should strive to be human readable.
- Concatenation of remote dependencies and npm packages. These should be left external.
- Bundler optimizations.
- General purpose bundler (ex. web bundler or npm package bundler)
- Performance.
- Type checking only occurs on a single bundled .d.ts file that only contains the public API.
- No waterfalling with internal modules within a library because there is only a single JS file.
- Compiling of TS to JS is done ahead of time.
- Private APIs stay private.
- People can't import your internal modules. Only what's exported from the main entrypoint is available.
This emits a single .d.ts
very quickly by parsing with swc
and analyzing explicit types in the public API's only. This is more primitive
than what the TypeScript compiler is capable of, but it is very fast. The tool
will error when something in your public API is not explicitly typed.
The current implementation of this needs a lot more work, but it will currently error when it finds something not supported.
Add a .gitignore
to your project and ignore the dist
directory, which we'll
be using for the build output:
dist
Set up your library with a mod.ts file. For example:
// mod.ts
export function add(a: number, b: number): number {
return a + b;
}
Add a corresponding integration test file at mod.test.ts:
// mod.test.ts
import { assertEquals } from "$std/testing/asserts.ts";
import { add } from "./mod.ts";
Deno.test("adds numbers", () => {
assertEquals(add(1, 2), 3);
});
Add a libpack
and build
deno task to your deno.json file:
// deno.json
{
"tasks": {
"build": "rm -rf dist && deno task libpack build mod.ts && cp README.md dist/README.md",
"libpack": "deno run -A https://deno.land/x/libpack@{VERSIONGOESHERE}/main.ts --output-folder=dist"
},
"imports": {
"$std/": "https://deno.land/std@0.191.0/"
},
"exclude": [
"dist"
]
}
Then try it out:
deno task build
This will:
- Delete the
dist
directory if it exists. - Build your library to the
dist
directory usingmod.ts
as an entrypoint, type check the output, then run integration tests on the output using mod.test.ts.
NOTE: THIS IS TOO COMPLICATED. I want to simplify this process. See here.
Publishing works by:
- You manually tag the repo with a version number. For example:
1.0.0
.- This can be done via git or via a GitHub release.
- A GH Actions Workflow is triggered for that tag.
- It builds the output to a
dist
directory. - It pushes the
dist
directory to a separate orphanedbuild
branch. - It tags the
build
branch with arelease/
prefix tag (ex. we tag our sources with1.0.0
then this tags the repo withrelease/1.0.0
). - The tagging of the
release/
prefixed tag triggers the webhook which causes a deno.land/x publish.
- It builds the output to a
-
Update your repository webhook's payload URL for https://api.deno.land to have a
version_prefix
query parameter ofrelease/
in Settings > Webhooks:https://api.deno.land/webhook/gh/{your_module_name}?version_prefix=release/
This will cause deno.land/x to only publish when the workflow tags the
build
branch with arelease/
prefix. -
Create a
.github/workflows/ci.yml
file in your repository with content similar to the following:# .github/workflows/ci.yml name: ci on: push: branches: ["main"] tags: ["!release/**"] pull_request: branches: ["main"] # for pushing to the build branch permissions: write-all jobs: deno: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: denoland/setup-deno@v1 - name: Lint run: deno lint - name: Test run: deno test -A - name: Build run: deno task build - name: Push to build branch and release if tag if: github.ref == 'refs/heads/main' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: deno task libpack publish --build-branch=build --release-tag-prefix=release/