@temir.ra/create-ts-lib 0.6.1 → 0.7.0
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 +23 -0
- package/README.md +174 -192
- package/buildinfo.txt +1 -1
- package/dist/cli.bundle.js +2 -2
- package/dist/cli.bundle.js.map +3 -3
- package/package.json +11 -7
- package/{template/scripts/build-lib-bundle.ts → scripts/build-bundle.ts} +20 -15
- package/scripts/buildinfo.ts +25 -0
- package/scripts/cdn-rewrite-map.json +1 -0
- package/template/CHANGELOG.md +1 -1
- package/template/README.md +12 -18
- package/template/buildinfo.txt +1 -0
- package/template/gitignore +1 -1
- package/template/package.json +10 -6
- package/template/scripts/build-bundle.ts +161 -0
- package/template/{src → scripts}/dev.ts +1 -1
- package/template/tsconfig.json +4 -5
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -26
- package/dist/constants.d.ts +0 -7
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -8
- package/template/tsconfig.build.json +0 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Version 0
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
2. Removed `CLAUDE.md`, `AGENTS.md`, and `src/dev.ts` from root and template.
|
|
7
|
+
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`.
|
|
8
|
+
4. Updated the generated `tsconfig.json`: changed `target` to `ESNext`; removed `DOM` from `lib`; added `types: ["bun"]`.
|
|
9
|
+
5. Removed generated `tsconfig.build.json`; TSC compilation is now opt-in and documented in `README.md`.
|
|
10
|
+
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.
|
|
11
|
+
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`.
|
|
12
|
+
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.
|
|
13
|
+
9. Refactored `template/tests/buildinfo.test.ts` to use a proper semver regex.
|
|
14
|
+
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.
|
|
15
|
+
11. Updated from `@temir.ra/template@0.1.3` template.
|
|
16
|
+
|
|
17
|
+
## 0.6.3
|
|
18
|
+
|
|
19
|
+
1. Cleaned up dormant package scripts.
|
|
20
|
+
2. Cleaned up minor `README.md` inconsistencies.
|
|
21
|
+
|
|
22
|
+
## 0.6.2
|
|
23
|
+
|
|
24
|
+
1. Updated `clean:tsbuildinfo` script to remove both `tsconfig.tsbuildinfo` and `tsconfig.build.tsbuildinfo`.
|
|
25
|
+
|
|
3
26
|
## 0.6.1
|
|
4
27
|
|
|
5
28
|
1. Cleaned up dormant imports.
|
package/README.md
CHANGED
|
@@ -6,12 +6,15 @@ A template for TypeScript libraries distributed via npm-compatible registries. P
|
|
|
6
6
|
|
|
7
7
|
1. [Quick Start](#quick-start)
|
|
8
8
|
2. [Documentation](#documentation)
|
|
9
|
-
1. [`
|
|
10
|
-
2. [`package.json`](#packagejson)
|
|
11
|
-
3. [
|
|
12
|
-
4. [
|
|
13
|
-
5. [
|
|
14
|
-
|
|
9
|
+
1. [`package.json`](#packagejson)
|
|
10
|
+
2. [`"bin"` field in `package.json`](#bin-field-in-packagejson)
|
|
11
|
+
3. [`scripts/dev.ts`](#scriptsdevts)
|
|
12
|
+
4. [`tsconfig.json`](#tsconfigjson)
|
|
13
|
+
5. [TSC Compilation](#tsc-compilation)
|
|
14
|
+
1. [`tsconfig.build.json`](#tsconfigbuildjson)
|
|
15
|
+
2. [`package.json`](#packagejson-1)
|
|
16
|
+
6. [Script `scripts/build-bundle.ts`](#script-scriptsbuild-bundlets)
|
|
17
|
+
1. [CDN Map `scripts/cdn-rewrite-map.json`](#cdn-map-scriptscdn-rewrite-mapjson)
|
|
15
18
|
7. [Asset Resolution](#asset-resolution)
|
|
16
19
|
1. [Externalized - loaded from CDN or `node_modules/`](#externalized---loaded-from-cdn-or-node_modules)
|
|
17
20
|
2. [Bundled - absorbed into the consumer's output](#bundled---absorbed-into-the-consumers-output)
|
|
@@ -20,108 +23,178 @@ A template for TypeScript libraries distributed via npm-compatible registries. P
|
|
|
20
23
|
2. [Accessing assets](#accessing-assets)
|
|
21
24
|
3. [README statement for library consumers](#readme-statement-for-library-consumers)
|
|
22
25
|
4. [When the library is bundled by the consumer](#when-the-library-is-bundled-by-the-consumer)
|
|
23
|
-
8. [`src/dev.ts`](#srcdevts)
|
|
24
26
|
3. [DevOps](#devops)
|
|
25
27
|
1. [Change Management](#change-management)
|
|
26
28
|
2. [Publish](#publish)
|
|
27
|
-
1. [npmjs.org](#npmjsorg)
|
|
28
|
-
2. [Custom registry](#custom-registry)
|
|
29
29
|
|
|
30
30
|
# Quick Start
|
|
31
31
|
|
|
32
|
-
*`bun create` caches the template package - a newer published version will not be picked up automatically. Pin the version or clear the cache to use the latest.*
|
|
33
|
-
|
|
34
32
|
```bash
|
|
35
33
|
# placeholder:
|
|
34
|
+
# <TEMPLATE_PACKAGE: @temir.ra/create-ts-lib
|
|
35
|
+
# <TEMPLATE_NAME: @temir.ra/ts-lib
|
|
36
36
|
# <NEW_PACKAGE: <NEW_PACKAGE>
|
|
37
|
+
# is used as:
|
|
38
|
+
# - the path where the package is created
|
|
39
|
+
# - the "name" field in the generated package.json
|
|
37
40
|
# <@_VERSION: <@_VERSION>
|
|
38
41
|
|
|
39
|
-
#
|
|
42
|
+
# pinned version
|
|
40
43
|
bun info "@temir.ra/create-ts-lib" version
|
|
41
|
-
# create a new library from the template version
|
|
42
44
|
bun create --no-install --no-git "@temir.ra/ts-lib<@_VERSION>" <NEW_PACKAGE>
|
|
43
45
|
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
# clear package manager cache to ensure the latest template version is used
|
|
46
|
+
# latest
|
|
47
|
+
# clear the cache to pick up the latest version
|
|
47
48
|
bun pm cache rm
|
|
48
|
-
# create a new library from the latest template version
|
|
49
49
|
bun create --no-install --no-git "@temir.ra/ts-lib" <NEW_PACKAGE>
|
|
50
50
|
|
|
51
|
-
#
|
|
51
|
+
# templates only copy files, run install and any setup scripts manually
|
|
52
52
|
cd <NEW_PACKAGE>
|
|
53
53
|
bun install
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
# Documentation
|
|
57
57
|
|
|
58
|
-
The following sections explain the configurations and conventions baked into the generated package. Useful when adapting
|
|
58
|
+
The following sections explain the configurations and conventions baked into the generated package. Useful when adapting it to fit specific needs.
|
|
59
|
+
|
|
60
|
+
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:
|
|
61
|
+
|
|
62
|
+
- **Bundling** (`scripts/build-bundle.ts`) - generated by default; bundles the library to ESM and IIFE formats.
|
|
63
|
+
- **TSC compilation** (`tsconfig.build.json` + `build:tsc`) - optional, not generated by default; compiles source files one-for-one to ESM JavaScript and declaration files.
|
|
64
|
+
|
|
65
|
+
Both strategies can be combined.
|
|
66
|
+
|
|
67
|
+
## `package.json`
|
|
68
|
+
|
|
69
|
+
Selected fields are documented in the [`create-workspace` README](https://www.npmjs.com/package/@temir.ra/create-workspace#packagejson).
|
|
70
|
+
|
|
71
|
+
See npmjs documentation on [package.json](https://docs.npmjs.com/cli/v11/configuring-npm/package-json) for detailed explanations of all fields.
|
|
59
72
|
|
|
60
|
-
|
|
73
|
+
The following lists the additions and overrides relative to [`create-workspace`](https://www.npmjs.com/package/@temir.ra/create-workspace#packagejson).
|
|
61
74
|
|
|
62
|
-
|
|
75
|
+
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.
|
|
63
76
|
|
|
64
77
|
```json
|
|
65
78
|
{
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
// ... ,
|
|
81
|
+
|
|
82
|
+
// the package is anticipated to be published
|
|
83
|
+
"private": false,
|
|
84
|
+
|
|
85
|
+
// treats all .js files as ES modules; use .cjs extension for CommonJS files
|
|
86
|
+
"type": "module",
|
|
87
|
+
|
|
88
|
+
// package entry points
|
|
89
|
+
//
|
|
90
|
+
// scripts/build-bundle.ts (non-standard) export condition:
|
|
91
|
+
// "entrypoint" - locates the source entry point for bundling
|
|
92
|
+
//
|
|
93
|
+
// standard export conditions:
|
|
94
|
+
// "types" - TypeScript consumers; resolves to the declaration files;
|
|
95
|
+
// "browser" - browser bundler consumers; resolves to the bundled output
|
|
96
|
+
// "import" - ESM consumers; resolves to the compiled module output
|
|
97
|
+
"exports": {
|
|
98
|
+
".": {
|
|
99
|
+
"entrypoint": "./src/index.ts",
|
|
100
|
+
"types": "./dist/index.d.ts",
|
|
101
|
+
"browser": "./dist/index.bundle.js",
|
|
102
|
+
"import": "./dist/index.js"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
// convenience alias for source-execution only - does NOT survive transpilation or bundling
|
|
107
|
+
// NOT for use in source files compiled by tsconfig.build.json
|
|
108
|
+
// the .js extension is required in import statements (nodenext compliance)
|
|
109
|
+
"imports": {
|
|
110
|
+
"#src/*.js": "./src/*.ts"
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// CLI entry point
|
|
114
|
+
"bin": "./dist/cli.bundle.js",
|
|
115
|
+
|
|
116
|
+
// files to include in the published package
|
|
117
|
+
"files": [
|
|
118
|
+
"scripts/buildinfo.ts",
|
|
119
|
+
"scripts/build-bundle.ts",
|
|
120
|
+
"scripts/cdn-rewrite-map.json",
|
|
121
|
+
"dist",
|
|
122
|
+
"CHANGELOG.md",
|
|
123
|
+
"buildinfo.txt"
|
|
124
|
+
],
|
|
125
|
+
|
|
126
|
+
"scripts": {
|
|
127
|
+
|
|
128
|
+
// ... ,
|
|
129
|
+
|
|
130
|
+
// executed before build; generates buildinfo.txt
|
|
131
|
+
"prebuild": "bun run buildinfo",
|
|
132
|
+
|
|
133
|
+
// convenience script to run the build steps in sequence
|
|
134
|
+
"build": "bun run build:tsc && bun run build:bundle && bun run build:cli-bundle",
|
|
135
|
+
|
|
136
|
+
// compiles the library to declaration files and ESM JavaScript in dist/
|
|
137
|
+
"build:tsc": "tsc --project tsconfig.build.json",
|
|
68
138
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
139
|
+
// bundles the library into ESM and IIFE formats for distribution
|
|
140
|
+
"build:bundle": "bun run scripts/build-bundle.ts",
|
|
141
|
+
|
|
142
|
+
// bundles the CLI into a single file for distribution; requires the "bin" field to be set to the bundled output
|
|
143
|
+
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external"
|
|
72
144
|
|
|
73
|
-
|
|
74
|
-
// ES module syntax: import/export statements (as opposed to CommonJS require()/module.exports)
|
|
75
|
-
"module": "ESNext",
|
|
145
|
+
}
|
|
76
146
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## `"bin"` field in `package.json`
|
|
151
|
+
|
|
152
|
+
For CLI packages, add the following to `package.json`:
|
|
82
153
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
// ... ,
|
|
157
|
+
"bin": "./dist/cli.bundle.js",
|
|
158
|
+
// ... ,
|
|
159
|
+
"scripts": {
|
|
160
|
+
// ... ,
|
|
161
|
+
"build": "... && bun run build:cli-bundle",
|
|
162
|
+
// ... ,
|
|
163
|
+
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
86
167
|
|
|
87
|
-
|
|
88
|
-
"strict": true,
|
|
168
|
+
`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.
|
|
89
169
|
|
|
90
|
-
|
|
91
|
-
|
|
170
|
+
```typescript
|
|
171
|
+
#!/usr/bin/env node
|
|
172
|
+
```
|
|
92
173
|
|
|
93
|
-
|
|
94
|
-
"noUncheckedIndexedAccess": true,
|
|
174
|
+
If the package exports a CLI only and is not intended to be imported in other packages, the `exports` field can be omitted.
|
|
95
175
|
|
|
96
|
-
|
|
97
|
-
"exactOptionalPropertyTypes": true,
|
|
176
|
+
## `scripts/dev.ts`
|
|
98
177
|
|
|
99
|
-
|
|
100
|
-
"noImplicitOverride": true,
|
|
178
|
+
Development scratchpad. Execute it manually with `bun run --watch scripts/dev.ts`. Useful to test and explore library code during development.
|
|
101
179
|
|
|
102
|
-
|
|
103
|
-
"isolatedDeclarations": true,
|
|
180
|
+
## `tsconfig.json`
|
|
104
181
|
|
|
105
|
-
|
|
106
|
-
"esModuleInterop": true,
|
|
182
|
+
Selected fields are documented in the [`create-workspace` README](https://www.npmjs.com/package/@temir.ra/create-workspace#tsconfigjson).
|
|
107
183
|
|
|
108
|
-
|
|
109
|
-
"composite": true,
|
|
184
|
+
See the TypeScript documentation on [tsconfig.json](https://www.typescriptlang.org/tsconfig) for detailed explanations of all options.
|
|
110
185
|
|
|
111
|
-
|
|
112
|
-
"skipLibCheck": true,
|
|
186
|
+
The following lists the additions and overrides relative to [`create-workspace`](https://www.npmjs.com/package/@temir.ra/create-workspace#tsconfigjson).
|
|
113
187
|
|
|
114
|
-
|
|
115
|
-
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
116
190
|
|
|
117
|
-
|
|
118
|
-
"forceConsistentCasingInFileNames": true,
|
|
191
|
+
"compilerOptions": {
|
|
119
192
|
|
|
120
|
-
//
|
|
121
|
-
"resolveJsonModule": true,
|
|
193
|
+
// ... ,
|
|
122
194
|
|
|
123
195
|
// emit .d.ts declaration files
|
|
124
196
|
"declaration": true,
|
|
197
|
+
|
|
125
198
|
// emit .d.ts.map files mapping declarations back to source
|
|
126
199
|
"declarationMap": true,
|
|
127
200
|
|
|
@@ -129,32 +202,40 @@ See the typescriptlang documentation on [tsconfig.json](https://www.typescriptla
|
|
|
129
202
|
"emitDeclarationOnly": true,
|
|
130
203
|
|
|
131
204
|
// output directory for emitted files
|
|
132
|
-
"outDir": "./dist"
|
|
133
|
-
|
|
134
|
-
// root directory mirrored into outDir; set to project root during development, overridden to src/ in tsconfig.build.json (TS6 default — not set in actual config)
|
|
135
|
-
"rootDir": ".",
|
|
205
|
+
"outDir": "./dist"
|
|
136
206
|
|
|
137
207
|
},
|
|
138
208
|
|
|
139
|
-
// includes src/, tests/, and scripts/ for type-checking and IDE support; overridden in tsconfig.build.json
|
|
140
209
|
"include": [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"scripts/**/*.
|
|
144
|
-
|
|
210
|
+
// ... ,
|
|
211
|
+
// include `scripts/**/*.json` for script configuration files
|
|
212
|
+
"scripts/**/*.json",
|
|
213
|
+
// include `src/**/*.ts` for source files
|
|
214
|
+
"src/**/*.ts"
|
|
145
215
|
],
|
|
146
216
|
"exclude": [
|
|
147
|
-
|
|
217
|
+
// ... ,
|
|
218
|
+
// exclude `dist/`
|
|
148
219
|
"dist"
|
|
149
220
|
]
|
|
150
221
|
|
|
151
222
|
}
|
|
152
223
|
```
|
|
153
224
|
|
|
154
|
-
`tsconfig.json` is the development configuration. `tsconfig.build.json` extends it, narrowing scope to `src/` and enabling JavaScript output for distribution.
|
|
155
|
-
|
|
156
225
|
`declarationMap: true` enables go-to-definition for npm/bun consumers. For this to work, the original `.ts` source files must be accessible to the consumer. Consider adding `src/` to the `files` field in `package.json`.
|
|
157
226
|
|
|
227
|
+
## TSC Compilation
|
|
228
|
+
|
|
229
|
+
Not generated by default. Enables file-for-file tsc compilation of `src/` to ESM JavaScript and declaration files alongside bundling.
|
|
230
|
+
|
|
231
|
+
### `tsconfig.build.json`
|
|
232
|
+
|
|
233
|
+
Extends `tsconfig.json`, narrowing scope to `src/` only and switching to `nodenext` module resolution for strict ESM compliance.
|
|
234
|
+
|
|
235
|
+
Enables JavaScript output alongside declaration files for distribution.
|
|
236
|
+
|
|
237
|
+
Development files (`dev.ts`, `tests/`, `scripts/`) are excluded.
|
|
238
|
+
|
|
158
239
|
```json
|
|
159
240
|
{
|
|
160
241
|
|
|
@@ -174,11 +255,12 @@ See the typescriptlang documentation on [tsconfig.json](https://www.typescriptla
|
|
|
174
255
|
|
|
175
256
|
},
|
|
176
257
|
|
|
258
|
+
// include only src/ files for distribution
|
|
177
259
|
"include": [
|
|
178
260
|
"src/**/*.ts"
|
|
179
261
|
],
|
|
262
|
+
// exclude development files and directories from distribution
|
|
180
263
|
"exclude": [
|
|
181
|
-
"src/dev.ts",
|
|
182
264
|
"node_modules",
|
|
183
265
|
"dist",
|
|
184
266
|
"tests",
|
|
@@ -188,102 +270,30 @@ See the typescriptlang documentation on [tsconfig.json](https://www.typescriptla
|
|
|
188
270
|
}
|
|
189
271
|
```
|
|
190
272
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
See npmjs documentation on [package.json](https://docs.npmjs.com/cli/v11/configuring-npm/package-json) for detailed explanations of all fields.
|
|
273
|
+
### `package.json`
|
|
194
274
|
|
|
195
275
|
```json
|
|
196
276
|
{
|
|
197
|
-
|
|
198
|
-
"version": "0.0.0",
|
|
199
|
-
|
|
200
|
-
"description": "",
|
|
201
|
-
"author": "",
|
|
202
|
-
"license": "",
|
|
203
|
-
|
|
204
|
-
"keywords": ["typescript"],
|
|
205
|
-
|
|
206
|
-
"repository": {
|
|
207
|
-
"type": "git",
|
|
208
|
-
"url": ""
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
// treats all .js files as ES modules; use .cjs extension for CommonJS files
|
|
212
|
-
"type": "module",
|
|
213
|
-
|
|
214
|
-
// package entry points by consumer type
|
|
215
|
-
// "entrypoint" - custom condition; used by the bundle script to locate the source entry point
|
|
216
|
-
// "types" - TypeScript consumers; resolves to the declaration files; must precede "import" so TypeScript matches it before the JS condition
|
|
217
|
-
// "browser" - browser bundler consumers; resolves to the bundled output
|
|
218
|
-
// "import" - ESM consumers; resolves to the compiled module output
|
|
219
|
-
"exports": {
|
|
220
|
-
".": {
|
|
221
|
-
"entrypoint": "./src/index.ts",
|
|
222
|
-
"types": "./dist/index.d.ts",
|
|
223
|
-
"browser": "./dist/index.bundle.js",
|
|
224
|
-
"import": "./dist/index.js"
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
|
|
228
|
-
// package-internal import alias resolved natively by Node.js and Bun at runtime; key must start with #
|
|
229
|
-
// for use in dev.ts, tests/, and scripts/ only - NOT in library source files compiled by tsconfig.build.json
|
|
230
|
-
// the .js extension is required in import statements (nodenext compliance);
|
|
231
|
-
// the runtime maps it to the actual .ts source file via this field
|
|
232
|
-
"imports": {
|
|
233
|
-
"#src/*.js": "./src/*.ts"
|
|
234
|
-
},
|
|
235
|
-
|
|
236
|
-
// CLI entry point; omit if the package is not a CLI tool
|
|
237
|
-
"bin": "./dist/cli.bundle.js",
|
|
238
|
-
|
|
239
|
-
// files to include in the published package
|
|
240
|
-
"files": [
|
|
241
|
-
"dist",
|
|
242
|
-
"CHANGELOG.md",
|
|
243
|
-
"buildinfo.txt"
|
|
244
|
-
],
|
|
245
|
-
|
|
277
|
+
// ... ,
|
|
246
278
|
"scripts": {
|
|
247
|
-
|
|
248
|
-
"
|
|
249
|
-
"
|
|
250
|
-
"clean": "bun run clean:dist && bun run clean:tsbuildinfo",
|
|
251
|
-
|
|
252
|
-
// lifecycle hook; runs automatically before "build"; generates buildinfo.txt
|
|
253
|
-
"prebuild": "bun run scripts/buildinfo.ts",
|
|
254
|
-
|
|
255
|
-
"tests": "bun test",
|
|
256
|
-
|
|
257
|
-
"build": "bun run build:lib && bun run build:lib-bundle",
|
|
258
|
-
|
|
259
|
-
"build:lib": "tsc --project tsconfig.build.json",
|
|
260
|
-
// bundles the library into ESM and IIFE formats for distribution
|
|
261
|
-
"build:lib-bundle": "bun run scripts/build-lib-bundle.ts",
|
|
262
|
-
|
|
263
|
-
"typecheck": "tsc --noEmit",
|
|
264
|
-
|
|
265
|
-
// runs src/dev.ts in watch mode
|
|
266
|
-
"dev": "bun run --watch src/dev.ts"
|
|
267
|
-
|
|
268
|
-
},
|
|
269
|
-
"devDependencies": {
|
|
270
|
-
"@types/bun": "latest",
|
|
271
|
-
"typescript": "^6.0.2"
|
|
279
|
+
// ... ,
|
|
280
|
+
"build": "bun run build:tsc && bun run build:bundle",
|
|
281
|
+
"build:tsc": "tsc --project tsconfig.build.json"
|
|
272
282
|
}
|
|
273
283
|
}
|
|
274
284
|
```
|
|
275
285
|
|
|
276
|
-
## Script `scripts/
|
|
286
|
+
## Script `scripts/build-bundle.ts`
|
|
277
287
|
|
|
278
|
-
|
|
288
|
+
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.
|
|
279
289
|
|
|
280
|
-
|
|
290
|
+
Import specifiers can be rewritten to CDN URLs via `scripts/cdn-rewrite-map.json`.
|
|
281
291
|
|
|
282
|
-
|
|
292
|
+
### CDN Map `scripts/cdn-rewrite-map.json`
|
|
283
293
|
|
|
284
|
-
|
|
294
|
+
Maps import specifiers to CDN URLs. During bundling, matching specifiers in source files are rewritten to their CDN equivalents.
|
|
285
295
|
|
|
286
|
-
|
|
296
|
+
`<VERSION>` in a URL is replaced with the version of the matching package from `package.json`.
|
|
287
297
|
|
|
288
298
|
```json
|
|
289
299
|
{
|
|
@@ -291,25 +301,6 @@ Maps import specifiers to CDN URLs. During bundling, matching specifiers in sour
|
|
|
291
301
|
}
|
|
292
302
|
```
|
|
293
303
|
|
|
294
|
-
## `"bin"` field in `package.json`
|
|
295
|
-
|
|
296
|
-
For CLI packages, add the following to `package.json`:
|
|
297
|
-
|
|
298
|
-
```json
|
|
299
|
-
{
|
|
300
|
-
"exports": ...,
|
|
301
|
-
"bin": "./dist/cli.bundle.js",
|
|
302
|
-
"files": ...,
|
|
303
|
-
"scripts": {
|
|
304
|
-
...,
|
|
305
|
-
"build": "... && bun run build:cli-bundle",
|
|
306
|
-
...,
|
|
307
|
-
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external",
|
|
308
|
-
...,
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
```
|
|
312
|
-
|
|
313
304
|
## Asset Resolution
|
|
314
305
|
|
|
315
306
|
The key question to ask is: **does my library retain its own URL at runtime?** Everything else follows from it.
|
|
@@ -395,7 +386,7 @@ import { fileURLToPath } from 'url';
|
|
|
395
386
|
const asset = JSON.parse(await readFile(fileURLToPath(new URL('<ASSET>', assetsUrl)), 'utf-8'));
|
|
396
387
|
```
|
|
397
388
|
|
|
398
|
-
|
|
389
|
+
#### README statement for library consumers
|
|
399
390
|
|
|
400
391
|
```markdown
|
|
401
392
|
## Asset resolution
|
|
@@ -418,27 +409,18 @@ consumer output/
|
|
|
418
409
|
|
|
419
410
|
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.
|
|
420
411
|
|
|
421
|
-
## `src/dev.ts`
|
|
422
|
-
|
|
423
|
-
Development scratchpad - not published, excluded from `tsconfig.build.json`. Run with `bun run dev` in watch mode. Use it to manually test and explore library code during development.
|
|
424
|
-
|
|
425
412
|
# DevOps
|
|
426
413
|
|
|
427
414
|
```bash
|
|
428
|
-
|
|
429
|
-
bun run clean
|
|
430
|
-
|
|
431
|
-
# remove dist/ only
|
|
432
|
-
bun run clean:dist
|
|
433
|
-
|
|
434
|
-
# remove tsconfig.tsbuildinfo and tsconfig.build.tsbuildinfo only
|
|
435
|
-
bun run clean:tsbuildinfo
|
|
415
|
+
bun install
|
|
436
416
|
|
|
437
|
-
|
|
417
|
+
bun run clean
|
|
438
418
|
bun run build
|
|
419
|
+
bun run tests
|
|
420
|
+
|
|
421
|
+
bun run dev
|
|
439
422
|
|
|
440
|
-
#
|
|
441
|
-
bun run dist/cli.bundle.js -- example
|
|
423
|
+
# see publish section for publish instructions
|
|
442
424
|
```
|
|
443
425
|
|
|
444
426
|
## Change Management
|
|
@@ -448,7 +430,7 @@ bun run dist/cli.bundle.js -- example
|
|
|
448
430
|
3. Bump the version in [`package.json`](package.json).
|
|
449
431
|
4. Add an entry for the new version in [`CHANGELOG.md`](CHANGELOG.md).
|
|
450
432
|
5. Pull request the branch.
|
|
451
|
-
6.
|
|
433
|
+
6. Ensure package artifacts are current.
|
|
452
434
|
7. Publish.
|
|
453
435
|
|
|
454
436
|
## Publish
|
package/buildinfo.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.7.0+b45e7d0
|
package/dist/cli.bundle.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{cpSync as s,readFileSync as f,renameSync as u,writeFileSync as P}from"fs";import{resolve as t}from"path";import{resolve as o}from"path";import{fileURLToPath as h}from"url";var d=new URL("../",import.meta.url),n=o(h(d)),m=o(n,"template/"),p=o(n,"CHANGELOG.md"),g=o(n,"buildinfo.txt"),l=o(n,"README.md");try{let r=process.argv[2];if(!r)throw Error(
|
|
2
|
+
import{cpSync as s,readFileSync as f,renameSync as u,writeFileSync as P}from"fs";import{resolve as t}from"path";import{resolve as o}from"path";import{fileURLToPath as h}from"url";var d=new URL("../",import.meta.url),n=o(h(d)),m=o(n,"template/"),p=o(n,"CHANGELOG.md"),g=o(n,"buildinfo.txt"),l=o(n,"README.md");try{let r=process.argv[2];if(!r)throw Error('First argument must be the package name (e.g. "my-package" or "@my-scope/my-package").');let a=r.replace(/\\/g,"/"),e=t(process.cwd(),a);s(m,e,{recursive:!0}),s(p,t(e,"CHANGELOG-template.md")),s(g,t(e,"buildinfo-template.txt")),s(l,t(e,"README-template.md"));let c=t(e,"package.json"),i=JSON.parse(f(c,"utf-8"));i.name=a,P(c,JSON.stringify(i,null,2)),u(t(e,"gitignore"),t(e,".gitignore")),console.log(`Template has been successfully instantiated at '${e}' with package name '${a}'.`)}catch(r){let a=r instanceof Error?r:Error(String(r));console.error("Error:",a.message),process.exit(1)}
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=C4A0E6EEF1219B4364756E2164756E21
|
package/dist/cli.bundle.js.map
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["..\\src\\cli.ts", "..\\src\\constants.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"#!/usr/bin/env node\r\n\r\nimport { cpSync, readFileSync, renameSync, writeFileSync } from 'fs';\r\nimport { resolve } from 'path';\r\nimport {\r\n templatePath,\r\n changelogPath,\r\n buildinfoPath,\r\n readmePath\r\n} from './constants.js';\r\n\r\n\r\ntry {\r\n\r\n const packageNameArgument = process.argv[2];\r\n if (!packageNameArgument)
|
|
5
|
+
"#!/usr/bin/env node\r\n\r\nimport { cpSync, readFileSync, renameSync, writeFileSync } from 'fs';\r\nimport { resolve } from 'path';\r\nimport {\r\n templatePath,\r\n changelogPath,\r\n buildinfoPath,\r\n readmePath\r\n} from './constants.js';\r\n\r\n\r\ntry {\r\n\r\n const packageNameArgument = process.argv[2];\r\n if (!packageNameArgument)\r\n throw new Error('First argument must be the package name (e.g. \"my-package\" or \"@my-scope/my-package\").');\r\n const packageName = packageNameArgument.replace(/\\\\/g, '/');\r\n\r\n const destinationPath = resolve(process.cwd(), packageName);\r\n\r\n cpSync(templatePath, destinationPath, { recursive: true });\r\n cpSync(changelogPath, resolve(destinationPath, 'CHANGELOG-template.md'));\r\n cpSync(buildinfoPath, resolve(destinationPath, 'buildinfo-template.txt'));\r\n cpSync(readmePath, resolve(destinationPath, 'README-template.md'));\r\n\r\n const packageJsonPath = resolve(destinationPath, 'package.json');\r\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\r\n packageJson.name = packageName;\r\n writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));\r\n\r\n renameSync(resolve(destinationPath, 'gitignore'), resolve(destinationPath, '.gitignore'));\r\n\r\n console.log(`Template has been successfully instantiated at '${destinationPath}' with package name '${packageName}'.`);\r\n\r\n}\r\ncatch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n console.error('Error:', err.message);\r\n process.exit(1);\r\n}\r\n",
|
|
6
6
|
"import { resolve } from 'path';\r\nimport { fileURLToPath } from 'url';\r\n\r\n\r\nexport const packageUrl: URL = new URL('../', import.meta.url);\r\nexport const packagePath: string = resolve(fileURLToPath(packageUrl));\r\n\r\nexport const templatePath: string = resolve(packagePath, 'template/');\r\n\r\nexport const changelogPath: string = resolve(packagePath, 'CHANGELOG.md');\r\nexport const buildinfoPath: string = resolve(packagePath, 'buildinfo.txt');\r\nexport const readmePath: string = resolve(packagePath, 'README.md');\r\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";AAEA,iBAAS,kBAAQ,gBAAc,mBAAY,WAC3C,kBAAS,aCHT,kBAAS,aACT,wBAAS,YAGF,IAAM,EAAkB,IAAI,IAAI,MAAO,YAAY,GAAG,EAChD,EAAsB,EAAQ,EAAc,CAAU,CAAC,EAEvD,EAAuB,EAAQ,EAAa,WAAW,EAEvD,EAAwB,EAAQ,EAAa,cAAc,EAC3D,EAAwB,EAAQ,EAAa,eAAe,EAC5D,EAAqB,EAAQ,EAAa,WAAW,EDClE,GAAI,CAEA,IAAM,EAAsB,QAAQ,KAAK,GACzC,GAAI,CAAC,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": ";AAEA,iBAAS,kBAAQ,gBAAc,mBAAY,WAC3C,kBAAS,aCHT,kBAAS,aACT,wBAAS,YAGF,IAAM,EAAkB,IAAI,IAAI,MAAO,YAAY,GAAG,EAChD,EAAsB,EAAQ,EAAc,CAAU,CAAC,EAEvD,EAAuB,EAAQ,EAAa,WAAW,EAEvD,EAAwB,EAAQ,EAAa,cAAc,EAC3D,EAAwB,EAAQ,EAAa,eAAe,EAC5D,EAAqB,EAAQ,EAAa,WAAW,EDClE,GAAI,CAEA,IAAM,EAAsB,QAAQ,KAAK,GACzC,GAAI,CAAC,EACD,MAAU,MAAM,wFAAwF,EAC5G,IAAM,EAAc,EAAoB,QAAQ,MAAO,GAAG,EAEpD,EAAkB,EAAQ,QAAQ,IAAI,EAAG,CAAW,EAE1D,EAAO,EAAc,EAAiB,CAAE,UAAW,EAAK,CAAC,EACzD,EAAO,EAAe,EAAQ,EAAiB,uBAAuB,CAAC,EACvE,EAAO,EAAe,EAAQ,EAAiB,wBAAwB,CAAC,EACxE,EAAO,EAAY,EAAQ,EAAiB,oBAAoB,CAAC,EAEjE,IAAM,EAAkB,EAAQ,EAAiB,cAAc,EACzD,EAAc,KAAK,MAAM,EAAa,EAAiB,OAAO,CAAC,EACrE,EAAY,KAAO,EACnB,EAAc,EAAiB,KAAK,UAAU,EAAa,KAAM,CAAC,CAAC,EAEnE,EAAW,EAAQ,EAAiB,WAAW,EAAG,EAAQ,EAAiB,YAAY,CAAC,EAExF,QAAQ,IAAI,mDAAmD,yBAAuC,KAAe,EAGzH,MAAO,EAAO,CACV,IAAM,EAAM,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,EACpE,QAAQ,MAAM,SAAU,EAAI,OAAO,EACnC,QAAQ,KAAK,CAAC",
|
|
9
|
+
"debugId": "C4A0E6EEF1219B4364756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temir.ra/create-ts-lib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Typescript library template",
|
|
5
5
|
"author": "temir.ra",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,12 +14,16 @@
|
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "https://git.chimps.quest/trs/create-ts-lib.git"
|
|
16
16
|
},
|
|
17
|
+
"private": false,
|
|
17
18
|
"type": "module",
|
|
18
19
|
"imports": {
|
|
19
20
|
"#src/*.js": "./src/*.ts"
|
|
20
21
|
},
|
|
21
22
|
"bin": "./dist/cli.bundle.js",
|
|
22
23
|
"files": [
|
|
24
|
+
"scripts/buildinfo.ts",
|
|
25
|
+
"scripts/build-bundle.ts",
|
|
26
|
+
"scripts/cdn-rewrite-map.json",
|
|
23
27
|
"dist",
|
|
24
28
|
"CHANGELOG.md",
|
|
25
29
|
"buildinfo.txt",
|
|
@@ -27,15 +31,15 @@
|
|
|
27
31
|
],
|
|
28
32
|
"scripts": {
|
|
29
33
|
"clean:dist": "rm -rf dist/",
|
|
30
|
-
"clean:tsbuildinfo": "rm -f
|
|
34
|
+
"clean:tsbuildinfo": "rm -f *.tsbuildinfo || true",
|
|
31
35
|
"clean": "bun run clean:dist && bun run clean:tsbuildinfo",
|
|
32
|
-
"
|
|
36
|
+
"buildinfo": "bun run scripts/buildinfo.ts",
|
|
33
37
|
"tests": "bun test",
|
|
34
|
-
"build": "bun run build:lib && bun run build:cli-bundle",
|
|
35
|
-
"build:lib": "tsc --project tsconfig.build.json",
|
|
36
|
-
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external",
|
|
37
38
|
"typecheck": "tsc --noEmit",
|
|
38
|
-
"
|
|
39
|
+
"reinstall": "rm -rf node_modules && rm -f bun.lock && bun pm cache rm && bun install && bunx tsc --version",
|
|
40
|
+
"prebuild": "bun run buildinfo",
|
|
41
|
+
"build": "bun run build:cli-bundle",
|
|
42
|
+
"build:cli-bundle": "bun build src/cli.ts --entry-naming \"[dir]/[name].bundle.[ext]\" --outdir dist --target node --format esm --minify --sourcemap=external"
|
|
39
43
|
},
|
|
40
44
|
"devDependencies": {
|
|
41
45
|
"@types/bun": "latest",
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { readFileSync } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
+
|
|
3
4
|
import CDN_REWRITE_MAP from './cdn-rewrite-map.json';
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
interface ExportConditions {
|
|
7
8
|
[key: string]: string | undefined;
|
|
8
|
-
|
|
9
|
+
entrypoint?: string;
|
|
9
10
|
types?: string;
|
|
10
11
|
browser?: string;
|
|
11
|
-
|
|
12
|
+
import?: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
interface DependencyMap {
|
|
@@ -34,9 +35,9 @@ function getManifest(packageIdentifier?: string): PackageManifest {
|
|
|
34
35
|
manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
35
36
|
} catch {
|
|
36
37
|
if (packageIdentifier)
|
|
37
|
-
throw new Error(
|
|
38
|
+
throw new Error(`[scripts/build-bundle.ts] Could not read manifest for '${packageIdentifier}' at '${manifestPath}'.`);
|
|
38
39
|
else
|
|
39
|
-
throw new Error(
|
|
40
|
+
throw new Error(`[scripts/build-bundle.ts] Could not read package manifest at '${manifestPath}'.`);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
return manifest;
|
|
@@ -46,11 +47,13 @@ function getManifest(packageIdentifier?: string): PackageManifest {
|
|
|
46
47
|
function getManifestEntrypoints(packageManifest: PackageManifest): string[] {
|
|
47
48
|
|
|
48
49
|
const exports = packageManifest.exports;
|
|
49
|
-
if (!exports)
|
|
50
|
+
if (!exports)
|
|
51
|
+
throw new Error(`[scripts/build-bundle.ts] No 'exports' field found in the given package manifest.`);
|
|
50
52
|
|
|
51
53
|
const entrypoints = Object.entries(exports)
|
|
52
54
|
.map(([key, conditions]) => {
|
|
53
|
-
if (!conditions.entrypoint)
|
|
55
|
+
if (!conditions.entrypoint)
|
|
56
|
+
throw new Error(`[scripts/build-bundle.ts] Export '${key}' does not have an 'entrypoint' condition.`);
|
|
54
57
|
return conditions.entrypoint;
|
|
55
58
|
});
|
|
56
59
|
|
|
@@ -70,11 +73,13 @@ function getPackageVersion(manifest: PackageManifest, packageIdentifier?: string
|
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
version = dependencies[packageIdentifier];
|
|
73
|
-
if (!version)
|
|
76
|
+
if (!version)
|
|
77
|
+
throw new Error(`[scripts/build-bundle.ts] Package '${packageIdentifier}' is not listed in dependencies.`);
|
|
74
78
|
|
|
75
79
|
}
|
|
76
80
|
else {
|
|
77
|
-
if (!manifest.version)
|
|
81
|
+
if (!manifest.version)
|
|
82
|
+
throw new Error('[scripts/build-bundle.ts] Package manifest does not contain a version field.');
|
|
78
83
|
version = manifest.version;
|
|
79
84
|
}
|
|
80
85
|
|
|
@@ -109,11 +114,11 @@ const cdnRewritePlugin = {
|
|
|
109
114
|
|
|
110
115
|
|
|
111
116
|
const entrypoints = getManifestEntrypoints(getManifest());
|
|
112
|
-
console.log('[scripts/build-
|
|
117
|
+
console.log('[scripts/build-bundle.ts] Entrypoints:', entrypoints);
|
|
113
118
|
|
|
114
119
|
let buildResult;
|
|
115
120
|
|
|
116
|
-
console.log('[scripts/build-
|
|
121
|
+
console.log('[scripts/build-bundle.ts] Starting ESM bundle build...');
|
|
117
122
|
buildResult = await Bun.build({
|
|
118
123
|
entrypoints,
|
|
119
124
|
outdir: 'dist',
|
|
@@ -126,15 +131,15 @@ buildResult = await Bun.build({
|
|
|
126
131
|
});
|
|
127
132
|
|
|
128
133
|
if (!buildResult.success) {
|
|
129
|
-
console.error('[scripts/build-
|
|
134
|
+
console.error('[scripts/build-bundle.ts] Build failed:');
|
|
130
135
|
for (const message of buildResult.logs) {
|
|
131
136
|
console.error(message);
|
|
132
137
|
}
|
|
133
138
|
process.exit(1);
|
|
134
139
|
}
|
|
135
|
-
console.log('[scripts/build-
|
|
140
|
+
console.log('[scripts/build-bundle.ts] ESM bundle build completed successfully.');
|
|
136
141
|
|
|
137
|
-
console.log('[scripts/build-
|
|
142
|
+
console.log('[scripts/build-bundle.ts] Starting IIFE bundle build...');
|
|
138
143
|
buildResult = await Bun.build({
|
|
139
144
|
entrypoints,
|
|
140
145
|
outdir: 'dist',
|
|
@@ -147,10 +152,10 @@ buildResult = await Bun.build({
|
|
|
147
152
|
});
|
|
148
153
|
|
|
149
154
|
if (!buildResult.success) {
|
|
150
|
-
console.error('[scripts/build-
|
|
155
|
+
console.error('[scripts/build-bundle.ts] Build failed:');
|
|
151
156
|
for (const message of buildResult.logs) {
|
|
152
157
|
console.error(message);
|
|
153
158
|
}
|
|
154
159
|
process.exit(1);
|
|
155
160
|
}
|
|
156
|
-
console.log('[scripts/build-
|
|
161
|
+
console.log('[scripts/build-bundle.ts] IIFE bundle build completed successfully.');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { readFileSync, writeFileSync } from 'fs';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
const BUILD_INFO_FILE = 'buildinfo.txt';
|
|
6
|
+
const GIT_COMMAND = 'git rev-parse --short HEAD';
|
|
7
|
+
|
|
8
|
+
const version: string = JSON.parse(readFileSync('package.json', 'utf-8')).version;
|
|
9
|
+
|
|
10
|
+
let gitHash = '';
|
|
11
|
+
try {
|
|
12
|
+
gitHash = execSync(GIT_COMMAND, { stdio: ['ignore', 'pipe', 'ignore'] })
|
|
13
|
+
.toString()
|
|
14
|
+
.trim();
|
|
15
|
+
} catch { }
|
|
16
|
+
|
|
17
|
+
const buildinfo = gitHash
|
|
18
|
+
? version.includes('+')
|
|
19
|
+
? `${version}.${gitHash}`
|
|
20
|
+
: `${version}+${gitHash}`
|
|
21
|
+
: version;
|
|
22
|
+
|
|
23
|
+
writeFileSync(BUILD_INFO_FILE, buildinfo.trim(), 'utf-8');
|
|
24
|
+
|
|
25
|
+
console.log(`'${BUILD_INFO_FILE}' has been updated with build info: ${buildinfo}`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/template/CHANGELOG.md
CHANGED
package/template/README.md
CHANGED
|
@@ -14,31 +14,25 @@
|
|
|
14
14
|
|
|
15
15
|
# Quick Start
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
# remove dist/ and tsconfig.tsbuildinfo and tsconfig.build.tsbuildinfo
|
|
19
|
-
bun run clean
|
|
17
|
+
*<QUICK START INSTRUCTIONS>*
|
|
20
18
|
|
|
21
|
-
#
|
|
22
|
-
bun run clean:dist
|
|
19
|
+
# Documentation
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
bun run clean:tsbuildinfo
|
|
21
|
+
*<DOCUMENTATION>*
|
|
26
22
|
|
|
27
|
-
#
|
|
28
|
-
|
|
23
|
+
# DevOps
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun install
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
bun run clean
|
|
29
|
+
bun run build
|
|
31
30
|
bun run tests
|
|
32
31
|
|
|
33
|
-
# run src/dev.ts in watch mode
|
|
34
32
|
bun run dev
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
# Documentation
|
|
38
33
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
# DevOps
|
|
34
|
+
# see publish section for publish instructions
|
|
35
|
+
```
|
|
42
36
|
|
|
43
37
|
## Change Management
|
|
44
38
|
|
|
@@ -47,7 +41,7 @@ bun run dev
|
|
|
47
41
|
3. Bump the version in [`package.json`](package.json).
|
|
48
42
|
4. Add an entry for the new version in [`CHANGELOG.md`](CHANGELOG.md).
|
|
49
43
|
5. Pull request the branch.
|
|
50
|
-
6.
|
|
44
|
+
6. Ensure package artifacts are current.
|
|
51
45
|
7. Publish.
|
|
52
46
|
|
|
53
47
|
## Publish
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.0.0
|
package/template/gitignore
CHANGED
package/template/package.json
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": ""
|
|
13
13
|
},
|
|
14
|
+
"private": false,
|
|
14
15
|
"type": "module",
|
|
15
16
|
"exports": {
|
|
16
17
|
".": {
|
|
@@ -24,21 +25,24 @@
|
|
|
24
25
|
"#src/*.js": "./src/*.ts"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
28
|
+
"scripts/buildinfo.ts",
|
|
29
|
+
"scripts/build-bundle.ts",
|
|
30
|
+
"scripts/cdn-rewrite-map.json",
|
|
27
31
|
"dist",
|
|
28
32
|
"CHANGELOG.md",
|
|
29
33
|
"buildinfo.txt"
|
|
30
34
|
],
|
|
31
35
|
"scripts": {
|
|
32
36
|
"clean:dist": "rm -rf dist/",
|
|
33
|
-
"clean:tsbuildinfo": "rm -f
|
|
37
|
+
"clean:tsbuildinfo": "rm -f *.tsbuildinfo || true",
|
|
34
38
|
"clean": "bun run clean:dist && bun run clean:tsbuildinfo",
|
|
35
|
-
"
|
|
39
|
+
"buildinfo": "bun run scripts/buildinfo.ts",
|
|
36
40
|
"tests": "bun test",
|
|
37
|
-
"build": "bun run build:lib && bun run build:lib-bundle",
|
|
38
|
-
"build:lib": "tsc --project tsconfig.build.json",
|
|
39
|
-
"build:lib-bundle": "bun run scripts/build-lib-bundle.ts",
|
|
40
41
|
"typecheck": "tsc --noEmit",
|
|
41
|
-
"
|
|
42
|
+
"reinstall": "rm -rf node_modules && rm -f bun.lock && bun pm cache rm && bun install && bunx tsc --version",
|
|
43
|
+
"prebuild": "bun run buildinfo",
|
|
44
|
+
"build": "bun run build:bundle",
|
|
45
|
+
"build:bundle": "bun run scripts/build-bundle.ts"
|
|
42
46
|
},
|
|
43
47
|
"devDependencies": {
|
|
44
48
|
"@types/bun": "latest",
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
import CDN_REWRITE_MAP from './cdn-rewrite-map.json';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
interface ExportConditions {
|
|
8
|
+
[key: string]: string | undefined;
|
|
9
|
+
entrypoint?: string;
|
|
10
|
+
types?: string;
|
|
11
|
+
browser?: string;
|
|
12
|
+
import?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface DependencyMap {
|
|
16
|
+
[packageName: string]: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface PackageManifest {
|
|
20
|
+
version: string;
|
|
21
|
+
exports?: Record<string, ExportConditions>;
|
|
22
|
+
dependencies?: DependencyMap;
|
|
23
|
+
devDependencies?: DependencyMap;
|
|
24
|
+
peerDependencies?: DependencyMap;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getManifest(packageIdentifier?: string): PackageManifest {
|
|
28
|
+
|
|
29
|
+
const manifestPath = packageIdentifier
|
|
30
|
+
? join('node_modules', packageIdentifier, 'package.json')
|
|
31
|
+
: 'package.json';
|
|
32
|
+
|
|
33
|
+
let manifest: PackageManifest;
|
|
34
|
+
try {
|
|
35
|
+
manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
36
|
+
} catch {
|
|
37
|
+
if (packageIdentifier)
|
|
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}'.`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return manifest;
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getManifestEntrypoints(packageManifest: PackageManifest): string[] {
|
|
48
|
+
|
|
49
|
+
const exports = packageManifest.exports;
|
|
50
|
+
if (!exports)
|
|
51
|
+
throw new Error(`[scripts/build-bundle.ts] No 'exports' field found in the given package manifest.`);
|
|
52
|
+
|
|
53
|
+
const entrypoints = Object.entries(exports)
|
|
54
|
+
.map(([key, conditions]) => {
|
|
55
|
+
if (!conditions.entrypoint)
|
|
56
|
+
throw new Error(`[scripts/build-bundle.ts] Export '${key}' does not have an 'entrypoint' condition.`);
|
|
57
|
+
return conditions.entrypoint;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return entrypoints;
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getPackageVersion(manifest: PackageManifest, packageIdentifier?: string): string {
|
|
65
|
+
|
|
66
|
+
let version: string | undefined;
|
|
67
|
+
if (packageIdentifier) {
|
|
68
|
+
|
|
69
|
+
const dependencies = {
|
|
70
|
+
...manifest.dependencies,
|
|
71
|
+
...manifest.devDependencies,
|
|
72
|
+
...manifest.peerDependencies,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
version = dependencies[packageIdentifier];
|
|
76
|
+
if (!version)
|
|
77
|
+
throw new Error(`[scripts/build-bundle.ts] Package '${packageIdentifier}' is not listed in dependencies.`);
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (!manifest.version)
|
|
82
|
+
throw new Error('[scripts/build-bundle.ts] Package manifest does not contain a version field.');
|
|
83
|
+
version = manifest.version;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return version;
|
|
87
|
+
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function resolveCdnUrl(importSpecifier: string, urlTemplate: string): string {
|
|
91
|
+
const manifest = getManifest();
|
|
92
|
+
const version = getPackageVersion(manifest, importSpecifier);
|
|
93
|
+
return urlTemplate.replace('<VERSION>', version);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const cdnRewritePlugin = {
|
|
97
|
+
name: 'cdn-rewrite',
|
|
98
|
+
setup(build: any) {
|
|
99
|
+
|
|
100
|
+
const resolved = new Map<string, string>();
|
|
101
|
+
for (const [importSpecifier, urlTemplate] of Object.entries(CDN_REWRITE_MAP) as [string, string][]) {
|
|
102
|
+
const url = resolveCdnUrl(importSpecifier, urlTemplate);
|
|
103
|
+
resolved.set(importSpecifier, url);
|
|
104
|
+
console.log(`[cdn-rewrite] '${importSpecifier}' → '${url}'`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
build.onResolve({ filter: /\*/ }, (args: any) => {
|
|
108
|
+
const url = resolved.get(args.path);
|
|
109
|
+
if (url) return { path: url, external: true };
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
const entrypoints = getManifestEntrypoints(getManifest());
|
|
117
|
+
console.log('[scripts/build-bundle.ts] Entrypoints:', entrypoints);
|
|
118
|
+
|
|
119
|
+
let buildResult;
|
|
120
|
+
|
|
121
|
+
console.log('[scripts/build-bundle.ts] Starting ESM bundle build...');
|
|
122
|
+
buildResult = await Bun.build({
|
|
123
|
+
entrypoints,
|
|
124
|
+
outdir: 'dist',
|
|
125
|
+
naming: '[dir]/[name].bundle.[ext]',
|
|
126
|
+
target: 'browser',
|
|
127
|
+
format: 'esm',
|
|
128
|
+
minify: true,
|
|
129
|
+
sourcemap: 'external',
|
|
130
|
+
plugins: [cdnRewritePlugin],
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
if (!buildResult.success) {
|
|
134
|
+
console.error('[scripts/build-bundle.ts] Build failed:');
|
|
135
|
+
for (const message of buildResult.logs) {
|
|
136
|
+
console.error(message);
|
|
137
|
+
}
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
console.log('[scripts/build-bundle.ts] ESM bundle build completed successfully.');
|
|
141
|
+
|
|
142
|
+
console.log('[scripts/build-bundle.ts] Starting IIFE bundle build...');
|
|
143
|
+
buildResult = await Bun.build({
|
|
144
|
+
entrypoints,
|
|
145
|
+
outdir: 'dist',
|
|
146
|
+
naming: '[dir]/[name].iife.[ext]',
|
|
147
|
+
target: 'browser',
|
|
148
|
+
format: 'iife',
|
|
149
|
+
minify: true,
|
|
150
|
+
sourcemap: 'external',
|
|
151
|
+
plugins: [cdnRewritePlugin],
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
if (!buildResult.success) {
|
|
155
|
+
console.error('[scripts/build-bundle.ts] Build failed:');
|
|
156
|
+
for (const message of buildResult.logs) {
|
|
157
|
+
console.error(message);
|
|
158
|
+
}
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
console.log('[scripts/build-bundle.ts] IIFE bundle build completed successfully.');
|
package/template/tsconfig.json
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
"target": "ESNext",
|
|
4
4
|
"module": "ESNext",
|
|
5
5
|
"lib": [
|
|
6
|
-
"ESNext"
|
|
7
|
-
"DOM"
|
|
6
|
+
"ESNext"
|
|
8
7
|
],
|
|
9
8
|
"moduleResolution": "bundler",
|
|
10
9
|
"strict": true,
|
|
@@ -24,13 +23,13 @@
|
|
|
24
23
|
"declaration": true,
|
|
25
24
|
"declarationMap": true,
|
|
26
25
|
"emitDeclarationOnly": true,
|
|
27
|
-
"outDir": "./dist"
|
|
26
|
+
"outDir": "./dist"
|
|
28
27
|
},
|
|
29
28
|
"include": [
|
|
30
|
-
"src/**/*.ts",
|
|
31
29
|
"tests/**/*.ts",
|
|
32
30
|
"scripts/**/*.ts",
|
|
33
|
-
"scripts/**/*.json"
|
|
31
|
+
"scripts/**/*.json",
|
|
32
|
+
"src/**/*.ts"
|
|
34
33
|
],
|
|
35
34
|
"exclude": [
|
|
36
35
|
"node_modules",
|
package/dist/cli.d.ts
DELETED
package/dist/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { cpSync, readFileSync, renameSync, writeFileSync } from 'fs';
|
|
3
|
-
import { resolve } from 'path';
|
|
4
|
-
import { templatePath, changelogPath, buildinfoPath, readmePath } from './constants.js';
|
|
5
|
-
try {
|
|
6
|
-
const packageNameArgument = process.argv[2];
|
|
7
|
-
if (!packageNameArgument)
|
|
8
|
-
throw new Error('Package name argument is required. Usage: `create-ts-lib <package-name>`');
|
|
9
|
-
const packageName = packageNameArgument.replace(/\\/g, '/');
|
|
10
|
-
const destinationPath = resolve(process.cwd(), packageName);
|
|
11
|
-
cpSync(templatePath, destinationPath, { recursive: true });
|
|
12
|
-
cpSync(changelogPath, resolve(destinationPath, 'CHANGELOG-template.md'));
|
|
13
|
-
cpSync(buildinfoPath, resolve(destinationPath, 'buildinfo-template.txt'));
|
|
14
|
-
cpSync(readmePath, resolve(destinationPath, 'README-template.md'));
|
|
15
|
-
const packageJsonPath = resolve(destinationPath, 'package.json');
|
|
16
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
17
|
-
packageJson.name = packageName;
|
|
18
|
-
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
19
|
-
renameSync(resolve(destinationPath, 'gitignore'), resolve(destinationPath, '.gitignore'));
|
|
20
|
-
console.log(`Template has been successfully instantiated at '${destinationPath}' with package name '${packageName}'.`);
|
|
21
|
-
}
|
|
22
|
-
catch (error) {
|
|
23
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
24
|
-
console.error('Error:', err.message);
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
package/dist/constants.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare const packageUrl: URL;
|
|
2
|
-
export declare const packagePath: string;
|
|
3
|
-
export declare const templatePath: string;
|
|
4
|
-
export declare const changelogPath: string;
|
|
5
|
-
export declare const buildinfoPath: string;
|
|
6
|
-
export declare const readmePath: string;
|
|
7
|
-
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,EAAE,GAAqC,CAAC;AAC/D,eAAO,MAAM,WAAW,EAAE,MAA2C,CAAC;AAEtE,eAAO,MAAM,YAAY,EAAE,MAA0C,CAAC;AAEtE,eAAO,MAAM,aAAa,EAAE,MAA6C,CAAC;AAC1E,eAAO,MAAM,aAAa,EAAE,MAA8C,CAAC;AAC3E,eAAO,MAAM,UAAU,EAAE,MAA0C,CAAC"}
|
package/dist/constants.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'path';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
export const packageUrl = new URL('../', import.meta.url);
|
|
4
|
-
export const packagePath = resolve(fileURLToPath(packageUrl));
|
|
5
|
-
export const templatePath = resolve(packagePath, 'template/');
|
|
6
|
-
export const changelogPath = resolve(packagePath, 'CHANGELOG.md');
|
|
7
|
-
export const buildinfoPath = resolve(packagePath, 'buildinfo.txt');
|
|
8
|
-
export const readmePath = resolve(packagePath, 'README.md');
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "./tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"rootDir": "./src",
|
|
5
|
-
"module": "nodenext",
|
|
6
|
-
"moduleResolution": "nodenext",
|
|
7
|
-
"emitDeclarationOnly": false,
|
|
8
|
-
},
|
|
9
|
-
"include": [
|
|
10
|
-
"src/**/*.ts"
|
|
11
|
-
],
|
|
12
|
-
"exclude": [
|
|
13
|
-
"src/dev.ts",
|
|
14
|
-
"node_modules",
|
|
15
|
-
"dist",
|
|
16
|
-
"tests",
|
|
17
|
-
"scripts"
|
|
18
|
-
]
|
|
19
|
-
}
|