@temir.ra/create-template 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/buildinfo.txt +1 -1
- package/package.json +1 -1
- package/scripts/build-bundle.ts +26 -24
- package/template/scripts/build-bundle.ts +26 -24
- package/template/tests/buildinfo.test.ts +2 -2
- package/template/CHANGELOG-template.md +0 -157
- package/template/README-template.md +0 -458
- package/template/buildinfo-template.txt +0 -1
package/CHANGELOG.md
CHANGED
package/buildinfo.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.10+55bf9cf
|
package/package.json
CHANGED
package/scripts/build-bundle.ts
CHANGED
|
@@ -28,16 +28,14 @@ function getManifest(packageIdentifier?: string): PackageManifest {
|
|
|
28
28
|
|
|
29
29
|
const manifestPath = packageIdentifier
|
|
30
30
|
? join('node_modules', packageIdentifier, 'package.json')
|
|
31
|
-
: 'package.json'
|
|
31
|
+
: 'package.json'
|
|
32
|
+
;
|
|
32
33
|
|
|
33
34
|
let manifest: PackageManifest;
|
|
34
35
|
try {
|
|
35
36
|
manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
36
37
|
} catch {
|
|
37
|
-
|
|
38
|
-
throw new Error(`[scripts/build-bundle.ts] Could not read manifest for '${packageIdentifier}' at '${manifestPath}'.`);
|
|
39
|
-
else
|
|
40
|
-
throw new Error(`[scripts/build-bundle.ts] Could not read package manifest at '${manifestPath}'.`);
|
|
38
|
+
throw new Error(`[scripts/build-bundle.ts] Failed to read package manifest at '${manifestPath}'.`);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
return manifest;
|
|
@@ -104,7 +102,7 @@ const cdnRewritePlugin = {
|
|
|
104
102
|
console.log(`[cdn-rewrite] '${importSpecifier}' → '${url}'`);
|
|
105
103
|
}
|
|
106
104
|
|
|
107
|
-
build.onResolve({ filter:
|
|
105
|
+
build.onResolve({ filter: /.*/ }, (args: any) => {
|
|
108
106
|
const url = resolved.get(args.path);
|
|
109
107
|
if (url) return { path: url, external: true };
|
|
110
108
|
});
|
|
@@ -116,6 +114,8 @@ const cdnRewritePlugin = {
|
|
|
116
114
|
const entrypoints = getManifestEntrypoints(getManifest());
|
|
117
115
|
console.log('[scripts/build-bundle.ts] Entrypoints:', entrypoints);
|
|
118
116
|
|
|
117
|
+
const omitIife = process.argv.includes('--omit-iife');
|
|
118
|
+
|
|
119
119
|
let buildResult;
|
|
120
120
|
|
|
121
121
|
console.log('[scripts/build-bundle.ts] Starting ESM bundle build...');
|
|
@@ -139,23 +139,25 @@ if (!buildResult.success) {
|
|
|
139
139
|
}
|
|
140
140
|
console.log('[scripts/build-bundle.ts] ESM bundle build completed successfully.');
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
142
|
+
if (!omitIife) {
|
|
143
|
+
console.log('[scripts/build-bundle.ts] Starting IIFE bundle build...');
|
|
144
|
+
buildResult = await Bun.build({
|
|
145
|
+
entrypoints,
|
|
146
|
+
outdir: 'dist',
|
|
147
|
+
naming: '[dir]/[name].iife.[ext]',
|
|
148
|
+
target: 'browser',
|
|
149
|
+
format: 'iife',
|
|
150
|
+
minify: true,
|
|
151
|
+
sourcemap: 'external',
|
|
152
|
+
plugins: [cdnRewritePlugin],
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
if (!buildResult.success) {
|
|
156
|
+
console.error('[scripts/build-bundle.ts] Build failed:');
|
|
157
|
+
for (const message of buildResult.logs) {
|
|
158
|
+
console.error(message);
|
|
159
|
+
}
|
|
160
|
+
process.exit(1);
|
|
158
161
|
}
|
|
159
|
-
|
|
162
|
+
console.log('[scripts/build-bundle.ts] IIFE bundle build completed successfully.');
|
|
160
163
|
}
|
|
161
|
-
console.log('[scripts/build-bundle.ts] IIFE bundle build completed successfully.');
|
|
@@ -28,16 +28,14 @@ function getManifest(packageIdentifier?: string): PackageManifest {
|
|
|
28
28
|
|
|
29
29
|
const manifestPath = packageIdentifier
|
|
30
30
|
? join('node_modules', packageIdentifier, 'package.json')
|
|
31
|
-
: 'package.json'
|
|
31
|
+
: 'package.json'
|
|
32
|
+
;
|
|
32
33
|
|
|
33
34
|
let manifest: PackageManifest;
|
|
34
35
|
try {
|
|
35
36
|
manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
36
37
|
} catch {
|
|
37
|
-
|
|
38
|
-
throw new Error(`[scripts/build-bundle.ts] Could not read manifest for '${packageIdentifier}' at '${manifestPath}'.`);
|
|
39
|
-
else
|
|
40
|
-
throw new Error(`[scripts/build-bundle.ts] Could not read package manifest at '${manifestPath}'.`);
|
|
38
|
+
throw new Error(`[scripts/build-bundle.ts] Failed to read package manifest at '${manifestPath}'.`);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
return manifest;
|
|
@@ -104,7 +102,7 @@ const cdnRewritePlugin = {
|
|
|
104
102
|
console.log(`[cdn-rewrite] '${importSpecifier}' → '${url}'`);
|
|
105
103
|
}
|
|
106
104
|
|
|
107
|
-
build.onResolve({ filter:
|
|
105
|
+
build.onResolve({ filter: /.*/ }, (args: any) => {
|
|
108
106
|
const url = resolved.get(args.path);
|
|
109
107
|
if (url) return { path: url, external: true };
|
|
110
108
|
});
|
|
@@ -116,6 +114,8 @@ const cdnRewritePlugin = {
|
|
|
116
114
|
const entrypoints = getManifestEntrypoints(getManifest());
|
|
117
115
|
console.log('[scripts/build-bundle.ts] Entrypoints:', entrypoints);
|
|
118
116
|
|
|
117
|
+
const omitIife = process.argv.includes('--omit-iife');
|
|
118
|
+
|
|
119
119
|
let buildResult;
|
|
120
120
|
|
|
121
121
|
console.log('[scripts/build-bundle.ts] Starting ESM bundle build...');
|
|
@@ -139,23 +139,25 @@ if (!buildResult.success) {
|
|
|
139
139
|
}
|
|
140
140
|
console.log('[scripts/build-bundle.ts] ESM bundle build completed successfully.');
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
142
|
+
if (!omitIife) {
|
|
143
|
+
console.log('[scripts/build-bundle.ts] Starting IIFE bundle build...');
|
|
144
|
+
buildResult = await Bun.build({
|
|
145
|
+
entrypoints,
|
|
146
|
+
outdir: 'dist',
|
|
147
|
+
naming: '[dir]/[name].iife.[ext]',
|
|
148
|
+
target: 'browser',
|
|
149
|
+
format: 'iife',
|
|
150
|
+
minify: true,
|
|
151
|
+
sourcemap: 'external',
|
|
152
|
+
plugins: [cdnRewritePlugin],
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
if (!buildResult.success) {
|
|
156
|
+
console.error('[scripts/build-bundle.ts] Build failed:');
|
|
157
|
+
for (const message of buildResult.logs) {
|
|
158
|
+
console.error(message);
|
|
159
|
+
}
|
|
160
|
+
process.exit(1);
|
|
158
161
|
}
|
|
159
|
-
|
|
162
|
+
console.log('[scripts/build-bundle.ts] IIFE bundle build completed successfully.');
|
|
160
163
|
}
|
|
161
|
-
console.log('[scripts/build-bundle.ts] IIFE bundle build completed successfully.');
|
|
@@ -14,9 +14,9 @@ function readBuildinfo(): string {
|
|
|
14
14
|
return readFileSync(fileURLToPath(buildinfoUrl), 'utf-8').trim();
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
describe('
|
|
17
|
+
describe('buildinfo.txt', () => {
|
|
18
18
|
|
|
19
|
-
it('MUST
|
|
19
|
+
it('MUST contain a valid semver string', () => {
|
|
20
20
|
expect(readBuildinfo()).toMatch(SEMVER_REGEX);
|
|
21
21
|
});
|
|
22
22
|
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# Version 0
|
|
2
|
-
|
|
3
|
-
## 0.8.1
|
|
4
|
-
|
|
5
|
-
1. Added `DOM` to the `lib` array in the generated `tsconfig.json`.
|
|
6
|
-
|
|
7
|
-
## 0.8.0
|
|
8
|
-
|
|
9
|
-
1. Updated wording in the Publish section of the generated README.
|
|
10
|
-
2. `build:tsc` step is now generated per default.
|
|
11
|
-
3. Added `./constants` entrypoint to `package.json`.
|
|
12
|
-
|
|
13
|
-
## 0.7.6
|
|
14
|
-
|
|
15
|
-
1. Updated `typescript` to `6.0.3`.
|
|
16
|
-
2. Cleaned up minor `README.md` inconsistencies.
|
|
17
|
-
3. Aligned wording with [`RFC 2119`](https://datatracker.ietf.org/doc/html/rfc2119).
|
|
18
|
-
4. Updated files from `template` template.
|
|
19
|
-
|
|
20
|
-
## 0.7.5
|
|
21
|
-
|
|
22
|
-
1. Updated files from `@temir.ra/template@0.1.6` template.
|
|
23
|
-
|
|
24
|
-
## 0.7.4
|
|
25
|
-
|
|
26
|
-
1. Updated `keywords` in `template/package.json`.
|
|
27
|
-
2. Restored docs for `build*` and `tests` `package.json` scripts in `README.md`.
|
|
28
|
-
3. Reduced `scripts/dev.ts` section to a DevOps command.
|
|
29
|
-
4. Added clarification on the `files` field recommendation for `tests/` in the README.
|
|
30
|
-
5. Updated from `@temir.ra/template@0.1.5` template.
|
|
31
|
-
|
|
32
|
-
## 0.7.3
|
|
33
|
-
|
|
34
|
-
1. Updated from `@temir.ra/template@0.1.4` template.
|
|
35
|
-
|
|
36
|
-
## 0.7.2
|
|
37
|
-
|
|
38
|
-
1. Cleaned up `*-template.*` files from the template directory.
|
|
39
|
-
|
|
40
|
-
## 0.7.1
|
|
41
|
-
|
|
42
|
-
1. Updated `template/` files from `@temir.ra/workspace@0.4.1` template.
|
|
43
|
-
|
|
44
|
-
## 0.7.0
|
|
45
|
-
|
|
46
|
-
1. Updated `.gitignore`: added `bun.lock`, `buildinfo-template.txt`, `CHANGELOG-template.md`, `README-template.md`; replaced nested `template/.gitignore` with `template/gitignore` to prevent template files from being excluded during distribution.
|
|
47
|
-
2. Removed `CLAUDE.md`, `AGENTS.md`, and `src/dev.ts` from root and template.
|
|
48
|
-
3. Overhauled the generated `package.json`: added `private: false`; removed `sideEffects: false`; added build scripts to published `files`; updated `clean:tsbuildinfo` to `rm -f *.tsbuildinfo || true`; renamed `build:lib-bundle` to `build:bundle`; removed `build:lib` and `dev` scripts; added `reinstall` script; bumped typescript to `^6.0.2`.
|
|
49
|
-
4. Updated the generated `tsconfig.json`: changed `target` to `ESNext`; removed `DOM` from `lib`; added `types: ["bun"]`.
|
|
50
|
-
5. Removed generated `tsconfig.build.json`; TSC compilation is now opt-in and documented in `README.md`.
|
|
51
|
-
6. Renamed `scripts/build-lib-bundle.ts` to `scripts/build-bundle.ts` in root and template; updated to produce ESM and IIFE browser bundles; added to published `files`; updated CDN rewrite plugin filter.
|
|
52
|
-
7. Extracted path constants from `src/cli.ts` to `src/constants.ts`; CLI now copies `README.md` as `README-template.md` to generated projects; improved error message for missing package name argument; moved `template/src/dev.ts` to `template/scripts/dev.ts`.
|
|
53
|
-
8. Updated `scripts/buildinfo.ts` in root and template: reads version from `package.json` instead of `npm_package_version` env var; handles pre-existing `+` in version string.
|
|
54
|
-
9. Refactored `template/tests/buildinfo.test.ts` to use a proper semver regex.
|
|
55
|
-
10. Overhauled `README.md`: new documentation structure with build strategies overview, `package.json` and `tsconfig.json` sections referencing `create-workspace`, opt-in TSC Compilation section, `bin` field documentation, `scripts/dev.ts` section; removed `CLAUDE.md`/`AGENTS.md` section.
|
|
56
|
-
11. Updated from `@temir.ra/template@0.1.3` template.
|
|
57
|
-
|
|
58
|
-
## 0.6.3
|
|
59
|
-
|
|
60
|
-
1. Cleaned up dormant package scripts.
|
|
61
|
-
2. Cleaned up minor `README.md` inconsistencies.
|
|
62
|
-
|
|
63
|
-
## 0.6.2
|
|
64
|
-
|
|
65
|
-
1. Updated `clean:tsbuildinfo` script to remove both `tsconfig.tsbuildinfo` and `tsconfig.build.tsbuildinfo`.
|
|
66
|
-
|
|
67
|
-
## 0.6.1
|
|
68
|
-
|
|
69
|
-
1. Cleaned up dormant imports.
|
|
70
|
-
2. Cleaned up / updated minor `README.md` inconsistencies.
|
|
71
|
-
3. Updated placeholders in `README.md` in the **Asset resolution** section.
|
|
72
|
-
4. Removed **Asset resolution** section from the generated `README.md`, as the operational passage is given in the template `README.md`.
|
|
73
|
-
5. Removed **AI Assistant Context** section from the `README.md` files.
|
|
74
|
-
7. Cleaned up **Publish** section in the `README.md`.
|
|
75
|
-
|
|
76
|
-
## 0.6.0
|
|
77
|
-
|
|
78
|
-
1. Updated documentation and configs to TypeScript 6.
|
|
79
|
-
|
|
80
|
-
## 0.5.0
|
|
81
|
-
|
|
82
|
-
1. Changed `buildinfo.txt` generation and testing to align with [https://semver.org](https://semver.org).
|
|
83
|
-
|
|
84
|
-
## 0.4.1
|
|
85
|
-
|
|
86
|
-
1. Fixed `destinationPath` resolution in `cli.ts` to use the full resolved path instead of just the basename.
|
|
87
|
-
|
|
88
|
-
## 0.4.0
|
|
89
|
-
|
|
90
|
-
1. Added support for scoped package names in the CLI argument parsing and asset resolution.
|
|
91
|
-
|
|
92
|
-
## 0.3.1-pre.1 (unreleased)
|
|
93
|
-
|
|
94
|
-
1. Removed `dev.ts` file.
|
|
95
|
-
|
|
96
|
-
## 0.3.0
|
|
97
|
-
|
|
98
|
-
1. Removed AI Assistant Context files to be generated by the user with the provided prompts in the README.
|
|
99
|
-
|
|
100
|
-
## 0.2.8 (unreleased)
|
|
101
|
-
|
|
102
|
-
1. CLI now copies root `README.md` into the generated project as `README-template.md`.
|
|
103
|
-
2. Added `README-template.md` to `template/gitignore`.
|
|
104
|
-
3. Added `# AI Assistant Context` section to root `README.md` and `template/README.md` with prompts for generating AI coding assistant context files.
|
|
105
|
-
4. Revised Change Management step 6 in root `README.md` and `template/README.md`.
|
|
106
|
-
5. `.gitignore`'ing `bun.lock`.
|
|
107
|
-
|
|
108
|
-
## 0.2.8-pre.2
|
|
109
|
-
|
|
110
|
-
1. Removed `sideEffects` property from `package.json` as it is not a standard field.
|
|
111
|
-
2. Added references to npmjs and typescriptlang documentation for `package.json` and `tsconfig.json` in the README.
|
|
112
|
-
|
|
113
|
-
## 0.2.7
|
|
114
|
-
|
|
115
|
-
1. Changed `filter` property in `cdnRewritePlugin` in `scripts/build-lib-bundle.ts` to take import identifiers into account that do not have file extensions.
|
|
116
|
-
2. Changed `buildinfo.txt` generation in `scripts/buildinfo.ts` to read the version from `package.json` instead of relying on the `npm_package_version` environment variable. Enables correct version capture in monorepo setups.
|
|
117
|
-
|
|
118
|
-
## 0.2.6
|
|
119
|
-
|
|
120
|
-
1. Minor ToC and typo fixes in both README.md files (root and template).
|
|
121
|
-
2. Revised the Publish section in both README.md files.
|
|
122
|
-
|
|
123
|
-
## 0.2.5
|
|
124
|
-
|
|
125
|
-
1. Minor README updates.
|
|
126
|
-
2. Fixed `buildinfo.txt` in published package.
|
|
127
|
-
3. Fixed `buildinfo.test.ts` regex to accept semver prerelease identifiers.
|
|
128
|
-
|
|
129
|
-
## 0.2.4
|
|
130
|
-
|
|
131
|
-
1. Documented template caching in the Quick Start section with commands to pin the version or clear the cache.
|
|
132
|
-
2. Minor README updates: Revised Asset Resolution sections in root and template; Added introductory paragraph to Documentation section;
|
|
133
|
-
3. Moved git-upstream to `https://git.chimps.quest/trs/create-ts-lib.git`.
|
|
134
|
-
|
|
135
|
-
## 0.2.3
|
|
136
|
-
|
|
137
|
-
1. Updated change management workflow in `README.md` and `template/README.md`: build step now happens after merge (not before PR), so `buildinfo.txt` captures the correct git hash and artifacts are up to date before publish.
|
|
138
|
-
2. Added Change Management section to root and template `CLAUDE.md`.
|
|
139
|
-
|
|
140
|
-
## 0.2.2
|
|
141
|
-
|
|
142
|
-
1. Fixed `CHANGELOG.md` and `buildinfo.txt` copy paths in `cli.ts`: they were resolved relative to `template/` instead of the package root, causing the copy to fail. Refactored URL/path construction to derive all paths from a single `packageUrl`, eliminating redundant `fileURLToPath` calls at each copy site.
|
|
143
|
-
2. Added `buildinfo-template.txt` and `CHANGELOG-template.md` to `template/gitignore` so generated libraries do not track template files.
|
|
144
|
-
3. Added `example/` to the root `.gitignore` to exclude local test scaffold output.
|
|
145
|
-
4. Added a `bun run dist/cli.bundle.js -- example` snippet to the DevOps section of the README for quick local testing.
|
|
146
|
-
|
|
147
|
-
## 0.2.1
|
|
148
|
-
|
|
149
|
-
1. Added asset resolution documentation to root README: scoped asset folder convention, inline `import.meta.url` resolution, `fetch()` for isomorphic I/O, setup steps, checklist, and consumer README statement.
|
|
150
|
-
2. Updated template README with a reference to the asset resolution docs in the create-ts-lib README.
|
|
151
|
-
3. Updated both `CLAUDE.md` files.
|
|
152
|
-
4. Updated both `dev.ts` files to use inline `new URL('../', import.meta.url)`.
|
|
153
|
-
5. Removed `src/urls.ts` from root and template (not needed - inline resolution is sufficient).
|
|
154
|
-
|
|
155
|
-
## 0.1.0
|
|
156
|
-
|
|
157
|
-
1. First version of the template.
|
|
@@ -1,458 +0,0 @@
|
|
|
1
|
-
# Introduction
|
|
2
|
-
|
|
3
|
-
A template for TypeScript libraries distributed via npm-compatible registries. Provides TypeScript configuration, build tooling for ESM and bundled outputs, and build metadata generation.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
1. [Quick Start](#quick-start)
|
|
8
|
-
2. [Documentation](#documentation)
|
|
9
|
-
1. [`package.json`](#packagejson)
|
|
10
|
-
2. [Script `scripts/build-bundle.ts`](#script-scriptsbuild-bundlets)
|
|
11
|
-
1. [CDN Map `scripts/cdn-rewrite-map.json`](#cdn-map-scriptscdn-rewrite-mapjson)
|
|
12
|
-
3. [`tsconfig.build.json`](#tsconfigbuildjson)
|
|
13
|
-
4. [Asset Resolution](#asset-resolution)
|
|
14
|
-
1. [Externalized - loaded from CDN or `node_modules/`](#externalized---loaded-from-cdn-or-node_modules)
|
|
15
|
-
2. [Bundled - absorbed into the consumer's output](#bundled---absorbed-into-the-consumers-output)
|
|
16
|
-
3. [Contract](#contract)
|
|
17
|
-
1. [Scoped assets directory convention](#scoped-assets-directory-convention)
|
|
18
|
-
2. [Accessing assets](#accessing-assets)
|
|
19
|
-
3. [README statement for library consumers](#readme-statement-for-library-consumers)
|
|
20
|
-
4. [When the library is bundled by the consumer](#when-the-library-is-bundled-by-the-consumer)
|
|
21
|
-
5. [`"bin"` field in `package.json`](#bin-field-in-packagejson)
|
|
22
|
-
3. [DevOps](#devops)
|
|
23
|
-
1. [Change Management](#change-management)
|
|
24
|
-
2. [Publish](#publish)
|
|
25
|
-
|
|
26
|
-
# Quick Start
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# placeholder:
|
|
30
|
-
# <TEMPLATE_PACKAGE: @temir.ra/create-ts-lib
|
|
31
|
-
# <TEMPLATE_NAME: @temir.ra/ts-lib
|
|
32
|
-
# <NEW_PACKAGE: <NEW_PACKAGE>
|
|
33
|
-
# is used as:
|
|
34
|
-
# - the path where the package is created
|
|
35
|
-
# - the "name" field in the generated package.json
|
|
36
|
-
# <@_VERSION: <@_VERSION>
|
|
37
|
-
|
|
38
|
-
# pinned version
|
|
39
|
-
bun info "@temir.ra/create-ts-lib" version
|
|
40
|
-
bun create --no-install --no-git "@temir.ra/ts-lib<@_VERSION>" <NEW_PACKAGE>
|
|
41
|
-
|
|
42
|
-
# latest
|
|
43
|
-
# clear the cache to pick up the latest version
|
|
44
|
-
bun pm cache rm
|
|
45
|
-
bun create --no-install --no-git "@temir.ra/ts-lib" <NEW_PACKAGE>
|
|
46
|
-
|
|
47
|
-
# templates only copy files, run install and any setup scripts manually
|
|
48
|
-
cd <NEW_PACKAGE>
|
|
49
|
-
bun install
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
# Documentation
|
|
53
|
-
|
|
54
|
-
The following sections explain the configurations and conventions baked into the generated package. Useful when adapting it to fit specific needs.
|
|
55
|
-
|
|
56
|
-
The central addition over [`create-workspace`](https://www.npmjs.com/package/@temir.ra/create-workspace) is a build pipeline for distributing the library. Two build strategies are supported:
|
|
57
|
-
|
|
58
|
-
- **Bundling** (`scripts/build-bundle.ts`) - generated by default; bundles the library to ESM and IIFE formats.
|
|
59
|
-
- **TSC compilation** (`tsconfig.build.json` + `build:tsc`) - optional, not generated by default; compiles source files one-for-one to ESM JavaScript and declaration files.
|
|
60
|
-
|
|
61
|
-
Both strategies can be combined.
|
|
62
|
-
|
|
63
|
-
## `package.json`
|
|
64
|
-
|
|
65
|
-
Selected fields are documented in the [`create-workspace` README](https://www.npmjs.com/package/@temir.ra/create-workspace#packagejson).
|
|
66
|
-
|
|
67
|
-
See npmjs documentation on [package.json](https://docs.npmjs.com/cli/v11/configuring-npm/package-json) for detailed explanations of all fields.
|
|
68
|
-
|
|
69
|
-
The following lists the additions and overrides relative to [`create-workspace`](https://www.npmjs.com/package/@temir.ra/create-workspace#packagejson).
|
|
70
|
-
|
|
71
|
-
The generated package is pre-configured with `build:bundle` only. See [TSC Compilation](#tsc-compilation) and [`"bin"` field](#bin-field-in-packagejson) for extending it.
|
|
72
|
-
|
|
73
|
-
```json
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
// ... ,
|
|
77
|
-
|
|
78
|
-
// the package is anticipated to be published
|
|
79
|
-
"private": false,
|
|
80
|
-
|
|
81
|
-
// treats all .js files as ES modules; use .cjs extension for CommonJS files
|
|
82
|
-
"type": "module",
|
|
83
|
-
|
|
84
|
-
// package entry points
|
|
85
|
-
// multiple entry points can be configured (".", "./module/", etc.)
|
|
86
|
-
//
|
|
87
|
-
// scripts/build-bundle.ts (non-standard) export condition:
|
|
88
|
-
// "entrypoint" - locates the source entry point for bundling
|
|
89
|
-
//
|
|
90
|
-
// standard export conditions:
|
|
91
|
-
// "types" - TypeScript consumers; resolves to the declaration files;
|
|
92
|
-
// "browser" - browser bundler consumers; resolves to the bundled output
|
|
93
|
-
// "import" - ESM consumers; resolves to the bundled/compiled output
|
|
94
|
-
"exports": {
|
|
95
|
-
".": {
|
|
96
|
-
"entrypoint": "./src/index.ts",
|
|
97
|
-
"types": "./dist/index.d.ts",
|
|
98
|
-
"browser": "./dist/index.bundle.js",
|
|
99
|
-
"import": "./dist/index.bundle.js"
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
// convenience alias for source-execution only - does NOT survive transpilation or bundling
|
|
104
|
-
// NOT for use in source files compiled by tsconfig.build.json
|
|
105
|
-
// the .js extension is required in import statements (nodenext compliance)
|
|
106
|
-
"imports": {
|
|
107
|
-
"#src/*.js": "./src/*.ts"
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
// CLI entry point
|
|
111
|
-
"bin": "./dist/cli.bundle.js",
|
|
112
|
-
|
|
113
|
-
// files to include in the published package
|
|
114
|
-
"files": [
|
|
115
|
-
"scripts/buildinfo.ts",
|
|
116
|
-
"scripts/build-bundle.ts",
|
|
117
|
-
"scripts/cdn-rewrite-map.json",
|
|
118
|
-
"CHANGELOG.md",
|
|
119
|
-
"buildinfo.txt",
|
|
120
|
-
"dist/",
|
|
121
|
-
"tests/"
|
|
122
|
-
],
|
|
123
|
-
|
|
124
|
-
"scripts": {
|
|
125
|
-
|
|
126
|
-
// ... ,
|
|
127
|
-
|
|
128
|
-
// removes the dist/ directory generated by the build steps
|
|
129
|
-
"clean:dist": "rm -rf dist/",
|
|
130
|
-
|
|
131
|
-
// removes .tsbuildinfo files generated by TypeScript's incremental build feature
|
|
132
|
-
"clean:tsbuildinfo": "rm -f *.tsbuildinfo || true",
|
|
133
|
-
|
|
134
|
-
// convenience script to run the clean steps in sequence
|
|
135
|
-
"clean": "bun run clean:dist && bun run clean:tsbuildinfo",
|
|
136
|
-
|
|
137
|
-
// discovers and runs test files
|
|
138
|
-
"tests": "bun test",
|
|
139
|
-
|
|
140
|
-
// executed before build; generates buildinfo.txt
|
|
141
|
-
"prebuild": "bun run buildinfo",
|
|
142
|
-
|
|
143
|
-
// convenience script to run the build steps in sequence
|
|
144
|
-
"build": "bun run build:bundle && bun run build:tsc && bun run build:cli-bundle",
|
|
145
|
-
|
|
146
|
-
// bundles the library into ESM and IIFE formats for distribution
|
|
147
|
-
"build:bundle": "bun run scripts/build-bundle.ts",
|
|
148
|
-
|
|
149
|
-
// compiles the library to declaration files and ESM JavaScript in dist/
|
|
150
|
-
"build:tsc": "tsc --project tsconfig.build.json",
|
|
151
|
-
|
|
152
|
-
// bundles the CLI into a single file for distribution; requires the "bin" field to be set to the bundled output
|
|
153
|
-
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external"
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
It is highly recommended to include `tests/` in the `files` field. Note, that `tests/` is not included by default in the generated `package.json`.
|
|
161
|
-
|
|
162
|
-
## Script `scripts/build-bundle.ts`
|
|
163
|
-
|
|
164
|
-
Bundles the library to ESM and IIFE formats. Entry points are resolved from the `entrypoint` condition in the `exports` field of `package.json`. Note, the `entrypoint` condition is a custom, non-standard export condition used solely for build tooling.
|
|
165
|
-
|
|
166
|
-
Import specifiers can be rewritten to CDN URLs via `scripts/cdn-rewrite-map.json`.
|
|
167
|
-
|
|
168
|
-
### CDN Map `scripts/cdn-rewrite-map.json`
|
|
169
|
-
|
|
170
|
-
Maps import specifiers to CDN URLs. During bundling, matching specifiers in source files are rewritten to their CDN equivalents.
|
|
171
|
-
|
|
172
|
-
`<VERSION>` in a URL is replaced with the version of the matching package from `package.json`.
|
|
173
|
-
|
|
174
|
-
```json
|
|
175
|
-
{
|
|
176
|
-
"import-specifier": "https://cdn.jsdelivr.net/npm/package-name@<VERSION>/dist/index.bundle.js"
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## `tsconfig.build.json`
|
|
181
|
-
|
|
182
|
-
`tsconfig.json` provided by [`workspace` template](https://www.npmjs.com/package/@temir.ra/create-workspace) is intended for development only. `tsconfig.build.json` extends it with settings for compiling the source files for distribution.
|
|
183
|
-
|
|
184
|
-
See [`create-workspace` README](https://www.npmjs.com/package/@temir.ra/create-workspace#tsconfigjson) and [tsconfig.json](https://www.typescriptlang.org/tsconfig) for detailed explanations of all options.
|
|
185
|
-
|
|
186
|
-
```json
|
|
187
|
-
{
|
|
188
|
-
|
|
189
|
-
"extends": "./tsconfig.json",
|
|
190
|
-
|
|
191
|
-
"compilerOptions": {
|
|
192
|
-
|
|
193
|
-
// narrows root to src/ for distribution output
|
|
194
|
-
"rootDir": "./src/",
|
|
195
|
-
|
|
196
|
-
// nodenext enforces strict ESM compliance; imports must use explicit .js file extensions
|
|
197
|
-
"module": "nodenext",
|
|
198
|
-
"moduleResolution": "nodenext",
|
|
199
|
-
|
|
200
|
-
// emit .d.ts declaration files
|
|
201
|
-
"declaration": true,
|
|
202
|
-
|
|
203
|
-
// emit .d.ts.map files mapping declarations back to source
|
|
204
|
-
"declarationMap": true,
|
|
205
|
-
|
|
206
|
-
// emit only .d.ts files, no JavaScript
|
|
207
|
-
"emitDeclarationOnly": true,
|
|
208
|
-
|
|
209
|
-
// output directory for emitted files
|
|
210
|
-
"outDir": "./dist/"
|
|
211
|
-
|
|
212
|
-
},
|
|
213
|
-
|
|
214
|
-
// include only src/ files for distribution
|
|
215
|
-
"include": [
|
|
216
|
-
"src/**/*.ts"
|
|
217
|
-
],
|
|
218
|
-
// exclude development files and directories from distribution
|
|
219
|
-
"exclude": [
|
|
220
|
-
"node_modules/",
|
|
221
|
-
"dist/",
|
|
222
|
-
"tests/",
|
|
223
|
-
"scripts/"
|
|
224
|
-
]
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### `package.json`
|
|
230
|
-
|
|
231
|
-
```json
|
|
232
|
-
{
|
|
233
|
-
// ... ,
|
|
234
|
-
"scripts": {
|
|
235
|
-
// ... ,
|
|
236
|
-
"build": "... && bun run build:tsc",
|
|
237
|
-
"build:tsc": "tsc --project tsconfig.build.json"
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
Exports condition `import` may point to the compiled output instead of the bundled output `./dist/index.bundle.js` if `"emitDeclarationOnly": false`:
|
|
243
|
-
|
|
244
|
-
```json
|
|
245
|
-
{
|
|
246
|
-
// ... ,
|
|
247
|
-
"exports": {
|
|
248
|
-
".": {
|
|
249
|
-
// ... ,
|
|
250
|
-
"import": "./dist/index.js"
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
// ... ,
|
|
254
|
-
}
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
When `"declaration": true`, then exports condition `types` can be added to point to the declaration files:
|
|
258
|
-
|
|
259
|
-
```json
|
|
260
|
-
{
|
|
261
|
-
// ... ,
|
|
262
|
-
"exports": {
|
|
263
|
-
".": {
|
|
264
|
-
// ... ,
|
|
265
|
-
"types": "./dist/index.d.ts",
|
|
266
|
-
// ... ,
|
|
267
|
-
}
|
|
268
|
-
},
|
|
269
|
-
// ... ,
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
## Asset Resolution
|
|
274
|
-
|
|
275
|
-
The key question to ask is: **does my library retain its own URL at runtime?** Everything else follows from it.
|
|
276
|
-
|
|
277
|
-
```bash
|
|
278
|
-
# placeholder:
|
|
279
|
-
# <@SCOPE: <@SCOPE>
|
|
280
|
-
# <LIB_NAME: <LIB_NAME>
|
|
281
|
-
# <VERSION: <VERSION>
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Externalized - loaded from CDN or `node_modules/`
|
|
285
|
-
|
|
286
|
-
The consumer does not bundle the library. It is loaded as a discrete module at runtime. Module identity is preserved regardless of the URL form:
|
|
287
|
-
|
|
288
|
-
```
|
|
289
|
-
https://cdn.jsdelivr.net/npm/<@SCOPE>/<LIB_NAME>@<VERSION>/dist/index.js
|
|
290
|
-
file:///project/node_modules/<@SCOPE>/<LIB_NAME>/dist/index.js
|
|
291
|
-
https://your-own-cdn.com/<LIB_NAME>/index.js
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
`import.meta.url` is reliable in all these cases. `fetch()` is the correct I/O mechanism because it accepts both `https://` and `file://` URLs, making it universally correct for isomorphic (`--target node` or `--target browser`) libraries.
|
|
295
|
-
|
|
296
|
-
### Bundled - absorbed into the consumer's output
|
|
297
|
-
|
|
298
|
-
The consumer's bundler absorbs the library into their own output. Module identity is destroyed - `import.meta.url` now points to the consumer's bundle, not the library's. However, **the path relationship can be preserved by convention**: if the consumer copies the library's assets into their output directory at the same relative path the library expects, `import.meta.url` resolution continues to work correctly.
|
|
299
|
-
|
|
300
|
-
### Contract
|
|
301
|
-
|
|
302
|
-
If the library has runtime assets, the following contract applies:
|
|
303
|
-
|
|
304
|
-
**The library must:**
|
|
305
|
-
1. **Place assets in a scoped assets directory** - see [Scoped assets directory convention](#scoped-assets-directory-convention) below.
|
|
306
|
-
2. **Access assets via `import.meta.url`** - see [Accessing assets](#accessing-assets) below.
|
|
307
|
-
3. **Document the bundled case** - see [README statement for library consumers](#readme-statement-for-library-consumers) below.
|
|
308
|
-
|
|
309
|
-
**The consumer must,**
|
|
310
|
-
- **when loading the library externalized:** do nothing - the library's `import.meta.url` works as-is, and assets load from their original location (CDN or `node_modules/`).
|
|
311
|
-
- **when bundling the library:**
|
|
312
|
-
1. **Copy the assets** - see [When the library is bundled by the consumer](#when-the-library-is-bundled-by-the-consumer) below.
|
|
313
|
-
2. **Ensure the assets are served**
|
|
314
|
-
- if the consumer is a web server, ensure the copied assets are served as static files
|
|
315
|
-
- if the consumer is a bundler, ensure the copied assets are included in the output directory
|
|
316
|
-
|
|
317
|
-
#### Scoped assets directory convention
|
|
318
|
-
|
|
319
|
-
Place all runtime assets under a scoped directory that mirrors the package name:
|
|
320
|
-
|
|
321
|
-
```
|
|
322
|
-
assets/
|
|
323
|
-
└── <@SCOPE>/
|
|
324
|
-
└── <LIB_NAME>/
|
|
325
|
-
└── ...
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
Add `assets/` to the `files` field in `package.json` so that the assets are included in the published package:
|
|
329
|
-
|
|
330
|
-
```json
|
|
331
|
-
{
|
|
332
|
-
// ... ,
|
|
333
|
-
"files": [
|
|
334
|
-
// ... ,
|
|
335
|
-
"assets/"
|
|
336
|
-
],
|
|
337
|
-
// ... ,
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
#### Accessing assets
|
|
342
|
-
|
|
343
|
-
Construct asset URLs directly from `import.meta.url`:
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
const packageUrl = new URL('../', import.meta.url);
|
|
347
|
-
const assetsUrl = new URL('assets/<@SCOPE>/<LIB_NAME>/', packageUrl);
|
|
348
|
-
|
|
349
|
-
// for `--target browser` and `--target node` (isomorphic)
|
|
350
|
-
const assetUrl = new URL('<ASSET>', assetsUrl);
|
|
351
|
-
const asset = await fetch(assetUrl).then(response => response.body);
|
|
352
|
-
|
|
353
|
-
// for `--target node` only
|
|
354
|
-
import { readFile } from 'fs/promises';
|
|
355
|
-
import { fileURLToPath } from 'url';
|
|
356
|
-
const assetUrl = new URL('<ASSET>', assetsUrl);
|
|
357
|
-
const assetPath = fileURLToPath(assetUrl);
|
|
358
|
-
const asset = await readFile(assetPath);
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
The generated `./src/constants.ts` scaffolds the isomorphic approach and `./constants` is configured as an additional entry point in `package.json` for direct imports:
|
|
362
|
-
|
|
363
|
-
```json
|
|
364
|
-
{
|
|
365
|
-
// ... ,
|
|
366
|
-
"exports": {
|
|
367
|
-
// ... ,
|
|
368
|
-
"./constants": {
|
|
369
|
-
"entrypoint": "./src/constants.ts",
|
|
370
|
-
"types": "./dist/constants.d.ts",
|
|
371
|
-
"browser": "./dist/constants.bundle.js",
|
|
372
|
-
"import": "./dist/constants.bundle.js"
|
|
373
|
-
}
|
|
374
|
-
},
|
|
375
|
-
// ... ,
|
|
376
|
-
}
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
#### README statement for library consumers
|
|
380
|
-
|
|
381
|
-
```markdown
|
|
382
|
-
## Asset resolution
|
|
383
|
-
|
|
384
|
-
This library resolves assets at runtime using `import.meta.url`. If you include this library into your bundle, copy `node_modules/<@SCOPE>/<LIB_NAME>/assets/<@SCOPE>/<LIB_NAME>/` to your output directory as `assets/<@SCOPE>/<LIB_NAME>/`.
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
#### When the library is bundled by the consumer
|
|
388
|
-
|
|
389
|
-
The consumer must copy the assets into their build output at the same relative path the library expects:
|
|
390
|
-
|
|
391
|
-
```
|
|
392
|
-
consumer output/
|
|
393
|
-
├── bundle.js ← import.meta.url points here
|
|
394
|
-
└── assets/
|
|
395
|
-
└── <@SCOPE>/
|
|
396
|
-
└── <LIB_NAME>/
|
|
397
|
-
└── ... ← copied; relative path preserved
|
|
398
|
-
```
|
|
399
|
-
|
|
400
|
-
From the bundle's perspective `assets/<@SCOPE>/<LIB_NAME>/` is at the same directory level as `bundle.js`, so `new URL('assets/<@SCOPE>/<LIB_NAME>/...', import.meta.url)` resolves correctly. No code configuration is needed - only the file copy.
|
|
401
|
-
|
|
402
|
-
## `"bin"` field in `package.json`
|
|
403
|
-
|
|
404
|
-
For CLI packages, add the following to `package.json`:
|
|
405
|
-
|
|
406
|
-
```json
|
|
407
|
-
{
|
|
408
|
-
// ... ,
|
|
409
|
-
"bin": "./dist/cli.bundle.js",
|
|
410
|
-
"scripts": {
|
|
411
|
-
// ... ,
|
|
412
|
-
"build": "... && bun run build:cli-bundle",
|
|
413
|
-
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external"
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
`src/cli.ts` must begin with a hashbang so the OS knows which interpreter to invoke when the binary is executed directly. Bun preserves it in the bundled output.
|
|
419
|
-
|
|
420
|
-
```typescript
|
|
421
|
-
#!/usr/bin/env node
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
If the package exports a CLI only and is not intended to be imported in other packages, the `exports` field can be omitted.
|
|
425
|
-
|
|
426
|
-
# DevOps
|
|
427
|
-
|
|
428
|
-
```bash
|
|
429
|
-
bun update
|
|
430
|
-
bun install
|
|
431
|
-
|
|
432
|
-
bun run clean
|
|
433
|
-
bun run build
|
|
434
|
-
bun run tests
|
|
435
|
-
|
|
436
|
-
# see publish section for publish instructions
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
## Change Management
|
|
440
|
-
|
|
441
|
-
1. Create a new branch for the change.
|
|
442
|
-
2. Make the changes and commit.
|
|
443
|
-
3. Bump the version in [`package.json`](package.json).
|
|
444
|
-
4. Add an entry for the new version in [`CHANGELOG.md`](CHANGELOG.md).
|
|
445
|
-
5. Pull request the branch.
|
|
446
|
-
6. Ensure package artifacts are current.
|
|
447
|
-
7. Publish.
|
|
448
|
-
|
|
449
|
-
## Publish
|
|
450
|
-
|
|
451
|
-
Publish to the public npm registry.
|
|
452
|
-
|
|
453
|
-
```powershell
|
|
454
|
-
# authenticate
|
|
455
|
-
npm login
|
|
456
|
-
# publish
|
|
457
|
-
bun publish --registry https://registry.npmjs.org/ --access public
|
|
458
|
-
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.8.0+545e022
|