@temir.ra/create-ts-lib 0.2.3 → 0.2.5
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 +12 -0
- package/README.md +80 -82
- package/buildinfo.txt +1 -1
- package/package.json +2 -2
- package/template/CLAUDE.md +55 -7
- package/template/README.md +12 -2
- package/template/tests/buildinfo.test.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Version 0
|
|
2
2
|
|
|
3
|
+
## 0.2.5
|
|
4
|
+
|
|
5
|
+
1. Minor README updates.
|
|
6
|
+
2. Fixed `buildinfo.txt` in published package.
|
|
7
|
+
3. Fixed `buildinfo.test.ts` regex to accept semver prerelease identifiers.
|
|
8
|
+
|
|
9
|
+
## 0.2.4
|
|
10
|
+
|
|
11
|
+
1. Documented template caching in the Quick Start section with commands to pin the version or clear the cache.
|
|
12
|
+
2. Minor README updates: Revised Asset Resolution sections in root and template; Added introductory paragraph to Documentation section;
|
|
13
|
+
3. Moved git-upstream to `https://git.chimps.quest/trs/create-ts-lib.git`.
|
|
14
|
+
|
|
3
15
|
## 0.2.3
|
|
4
16
|
|
|
5
17
|
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.
|
package/README.md
CHANGED
|
@@ -11,9 +11,17 @@ A template for TypeScript libraries distributed via npm-compatible registries. P
|
|
|
11
11
|
3. [Script `scripts/buildinfo.ts`](#script-scriptsbuildinfots)
|
|
12
12
|
4. [Script `scripts/build-lib-bundle.ts`](#script-scriptsbuild-lib-bundlets)
|
|
13
13
|
5. [CDN Map `scripts/cdn-rewrite-map.json`](#cdn-map-scriptscdn-rewrite-mapjson)
|
|
14
|
-
6. [
|
|
15
|
-
7. [
|
|
16
|
-
|
|
14
|
+
6. [`"bin"` field in `package.json`](#bin-field-in-packagejson)
|
|
15
|
+
7. [Asset Resolution](#asset-resolution)
|
|
16
|
+
1. [Externalized - loaded from CDN or `node_modules/`](#externalized---loaded-from-cdn-or-node_modules)
|
|
17
|
+
2. [Bundled - absorbed into the consumer's output](#bundled---absorbed-into-the-consumers-output)
|
|
18
|
+
3. [Contract](#contract)
|
|
19
|
+
1. [Scoped assets directory convention](#scoped-assets-directory-convention)
|
|
20
|
+
2. [Accessing assets](#accessing-assets)
|
|
21
|
+
3. [README statement for library consumers](#readme-statement-for-library-consumers)
|
|
22
|
+
4. [When the library is bundled by the consumer](#when-the-library-is-bundled-by-the-consumer)
|
|
23
|
+
8. [`src/dev.ts`](#srcdevts)
|
|
24
|
+
9. [`CLAUDE.md` / `AGENTS.md`](#claudemd--agentsmd)
|
|
17
25
|
3. [DevOps](#devops)
|
|
18
26
|
1. [Build](#build)
|
|
19
27
|
2. [Change Management](#change-management)
|
|
@@ -23,17 +31,34 @@ A template for TypeScript libraries distributed via npm-compatible registries. P
|
|
|
23
31
|
|
|
24
32
|
# Quick Start
|
|
25
33
|
|
|
34
|
+
*`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.*
|
|
35
|
+
|
|
26
36
|
```bash
|
|
27
37
|
# placeholder:
|
|
28
|
-
# <
|
|
38
|
+
# <NEW_PACKAGE: <NEW_PACKAGE>
|
|
39
|
+
# <@_VERSION: <@_VERSION>
|
|
40
|
+
|
|
41
|
+
# identify the latest version of the template package as <@_VERSION.
|
|
42
|
+
bun info "@temir.ra/create-ts-lib" version
|
|
43
|
+
# create a new library from the template version
|
|
44
|
+
bun create --no-install --no-git "@temir.ra/ts-lib<@_VERSION>" <NEW_PACKAGE>
|
|
45
|
+
|
|
46
|
+
# or
|
|
47
|
+
|
|
48
|
+
# clear package manager cache to ensure the latest template version is used
|
|
49
|
+
bun pm cache rm
|
|
50
|
+
# create a new library from the latest template version
|
|
51
|
+
bun create --no-install --no-git "@temir.ra/ts-lib" <NEW_PACKAGE>
|
|
29
52
|
|
|
30
|
-
|
|
31
|
-
cd <
|
|
53
|
+
# dependencies must be installed manually
|
|
54
|
+
cd <NEW_PACKAGE>
|
|
32
55
|
bun install
|
|
33
56
|
```
|
|
34
57
|
|
|
35
58
|
# Documentation
|
|
36
59
|
|
|
60
|
+
The following sections explain the configurations and conventions baked into the generated package. Useful when adapting the generated package to fit a specific library's needs.
|
|
61
|
+
|
|
37
62
|
## `tsconfig.json` and `tsconfig.build.json`
|
|
38
63
|
|
|
39
64
|
```json
|
|
@@ -286,25 +311,42 @@ For CLI packages, add the following to `package.json`:
|
|
|
286
311
|
|
|
287
312
|
## Asset Resolution
|
|
288
313
|
|
|
289
|
-
The key question to ask is: **does my library retain its own URL at runtime?**
|
|
314
|
+
The key question to ask is: **does my library retain its own URL at runtime?** Everything else follows from it.
|
|
290
315
|
|
|
291
|
-
### Externalized - loaded from CDN or node_modules
|
|
316
|
+
### Externalized - loaded from CDN or `node_modules/`
|
|
292
317
|
|
|
293
318
|
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:
|
|
294
319
|
|
|
295
320
|
```
|
|
296
|
-
https://cdn.jsdelivr.net/npm/@scope/lib@1.0.0/dist/index.js
|
|
297
|
-
file:///project/node_modules/@scope/lib/dist/index.js
|
|
298
|
-
https://your-own-cdn.com/lib/index.js
|
|
321
|
+
https://cdn.jsdelivr.net/npm/@scope/lib-name@1.0.0/dist/index.js
|
|
322
|
+
file:///project/node_modules/@scope/lib-name/dist/index.js
|
|
323
|
+
https://your-own-cdn.com/lib-name/index.js
|
|
299
324
|
```
|
|
300
325
|
|
|
301
|
-
`import.meta.url` is reliable in all these cases.
|
|
326
|
+
`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.
|
|
327
|
+
|
|
328
|
+
### Bundled - absorbed into the consumer's output
|
|
329
|
+
|
|
330
|
+
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 build output at the same relative path the library expects, `import.meta.url` resolution continues to work correctly.
|
|
331
|
+
|
|
332
|
+
### Contract
|
|
333
|
+
|
|
334
|
+
If the library has runtime assets, the following contract applies:
|
|
302
335
|
|
|
303
|
-
|
|
336
|
+
**The library must:**
|
|
337
|
+
1. **Place assets in a scoped assets directory** - see [Scoped assets directory convention](#scoped-assets-directory-convention) below.
|
|
338
|
+
2. **Access assets via `import.meta.url`** - see [Accessing assets](#accessing-assets) below.
|
|
339
|
+
3. **Document the bundled case** - see [README statement for library consumers](#readme-statement-for-library-consumers) below.
|
|
304
340
|
|
|
305
|
-
The consumer
|
|
341
|
+
**The consumer must,**
|
|
342
|
+
- **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/`).
|
|
343
|
+
- **when bundling the library:**
|
|
344
|
+
1. **Copy the assets** - see [When the library is bundled by the consumer](#when-the-library-is-bundled-by-the-consumer) below.
|
|
345
|
+
2. **Ensure the assets are served**
|
|
346
|
+
- if the consumer is a web server, ensure the copied assets are served as static files
|
|
347
|
+
- if the consumer is a bundler, ensure the copied assets are included in the bundle output
|
|
306
348
|
|
|
307
|
-
|
|
349
|
+
#### Scoped assets directory convention
|
|
308
350
|
|
|
309
351
|
Place all runtime assets under a scoped directory that mirrors the package name:
|
|
310
352
|
|
|
@@ -312,13 +354,12 @@ Place all runtime assets under a scoped directory that mirrors the package name:
|
|
|
312
354
|
assets/
|
|
313
355
|
└── @scope/
|
|
314
356
|
└── lib-name/
|
|
315
|
-
|
|
316
|
-
└── data.json
|
|
357
|
+
└── <ASSETS>
|
|
317
358
|
```
|
|
318
359
|
|
|
319
360
|
This prevents naming collisions when multiple libraries are bundled into the same consumer app. Each library's assets live under their own namespace; no library can shadow another's files.
|
|
320
361
|
|
|
321
|
-
Add `assets/` to the `files` field in `package.json` so
|
|
362
|
+
Add `assets/` to the `files` field in `package.json` so that the assets are included in the published package:
|
|
322
363
|
|
|
323
364
|
```json
|
|
324
365
|
"files": [
|
|
@@ -329,93 +370,50 @@ Add `assets/` to the `files` field in `package.json` so npm publishes it:
|
|
|
329
370
|
],
|
|
330
371
|
```
|
|
331
372
|
|
|
332
|
-
|
|
373
|
+
#### Accessing assets
|
|
333
374
|
|
|
334
|
-
Construct asset URLs directly from `import.meta.url`.
|
|
375
|
+
Construct asset URLs directly from `import.meta.url`.
|
|
335
376
|
|
|
336
377
|
```typescript
|
|
337
378
|
const packageUrl = new URL('../', import.meta.url);
|
|
338
379
|
const assetsUrl = new URL('assets/@scope/lib-name/', packageUrl);
|
|
339
380
|
|
|
340
|
-
//
|
|
341
|
-
const
|
|
381
|
+
// for --target browser
|
|
382
|
+
const asset = await fetch(new URL('<ASSET>', assetsUrl)).then(r => r.json());
|
|
342
383
|
|
|
343
|
-
//
|
|
384
|
+
// for --target node
|
|
344
385
|
import { readFile } from 'node:fs/promises';
|
|
345
386
|
import { fileURLToPath } from 'url';
|
|
346
|
-
const
|
|
387
|
+
const asset = JSON.parse(await readFile(fileURLToPath(new URL('<ASSET>', assetsUrl)), 'utf-8'));
|
|
347
388
|
```
|
|
348
389
|
|
|
349
|
-
|
|
390
|
+
### README statement for library consumers
|
|
391
|
+
|
|
392
|
+
```markdown
|
|
393
|
+
<!-- placeholder:
|
|
394
|
+
<SCOPE: <SCOPE>
|
|
395
|
+
<LIB_NAME: <LIB_NAME>
|
|
396
|
+
-->
|
|
350
397
|
|
|
351
|
-
|
|
398
|
+
## Asset resolution
|
|
352
399
|
|
|
353
|
-
|
|
400
|
+
This library resolves assets at runtime using `import.meta.url`. If you bundle this library into your application, copy `node_modules/<SCOPE>/<LIB_NAME>/assets/<SCOPE>/<LIB_NAME>/` into your build output directory alongside your bundle.
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
#### When the library is bundled by the consumer
|
|
354
404
|
|
|
355
405
|
The consumer must copy the assets into their build output at the same relative path the library expects:
|
|
356
406
|
|
|
357
407
|
```
|
|
358
408
|
consumer output/
|
|
359
|
-
├── bundle.js
|
|
409
|
+
├── bundle.js ← import.meta.url points here
|
|
360
410
|
└── assets/
|
|
361
411
|
└── @scope/
|
|
362
412
|
└── lib-name/
|
|
363
|
-
|
|
364
|
-
└── data.json
|
|
413
|
+
└── <ASSETS> ← copied; relative path preserved
|
|
365
414
|
```
|
|
366
415
|
|
|
367
|
-
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
|
|
368
|
-
|
|
369
|
-
### Setup
|
|
370
|
-
|
|
371
|
-
If your library has runtime assets, the steps to wire everything up:
|
|
372
|
-
|
|
373
|
-
1. **Create the scoped directory** `assets/@scope/lib-name/` and place asset files inside (replace `@scope/lib-name` with your actual package name).
|
|
374
|
-
|
|
375
|
-
2. **Access assets via `import.meta.url`** - see [Accessing assets](#accessing-assets) above.
|
|
376
|
-
|
|
377
|
-
3. **Publish the assets** - add `assets/` to the `files` field in `package.json`:
|
|
378
|
-
```json
|
|
379
|
-
"files": [
|
|
380
|
-
"dist",
|
|
381
|
-
"CHANGELOG.md",
|
|
382
|
-
"buildinfo.txt",
|
|
383
|
-
"assets"
|
|
384
|
-
],
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
4. **Document the bundled case** - copy the [README statement](#readme-statement-for-your-consumers) into your library's README.
|
|
388
|
-
|
|
389
|
-
### Contract
|
|
390
|
-
|
|
391
|
-
**The library must:**
|
|
392
|
-
- Place assets under `assets/@scope/lib-name/` (mirroring the package name)
|
|
393
|
-
- Resolve asset paths via `import.meta.url` - no shared helper file required
|
|
394
|
-
- Include `assets/` in `package.json` `files`
|
|
395
|
-
- Document the bundled-case copy requirement in its README
|
|
396
|
-
|
|
397
|
-
**The consumer must, when bundling the library:**
|
|
398
|
-
- Copy `node_modules/@scope/lib-name/assets/` into their build output alongside the bundle
|
|
399
|
-
- Ensure assets are served
|
|
400
|
-
|
|
401
|
-
**The consumer must do nothing when loading the library externalized.** Asset resolution is automatic.
|
|
402
|
-
|
|
403
|
-
### Checklist
|
|
404
|
-
|
|
405
|
-
- [ ] Assets live under `assets/@scope/lib-name/` (matching the package name)
|
|
406
|
-
- [ ] `assets/` is listed in `package.json` `files`
|
|
407
|
-
- [ ] All asset access resolves paths via `import.meta.url` - no hardcoded paths
|
|
408
|
-
- [ ] Library README documents the bundled-case copy requirement (see statement below)
|
|
409
|
-
|
|
410
|
-
### README statement for your consumers
|
|
411
|
-
|
|
412
|
-
Copy this into your library's README:
|
|
413
|
-
|
|
414
|
-
> **Asset resolution**
|
|
415
|
-
>
|
|
416
|
-
> This library resolves assets at runtime using `import.meta.url`. It works automatically when the library is loaded as an external module (from CDN or node_modules).
|
|
417
|
-
>
|
|
418
|
-
> If you bundle this library into your application, copy `node_modules/@scope/lib-name/assets/@scope/lib-name/` into your build output directory alongside your bundle. No code configuration is required.
|
|
416
|
+
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/<ASSETS>', import.meta.url)` resolves correctly. No code configuration is needed - only the file copy.
|
|
419
417
|
|
|
420
418
|
## `src/dev.ts`
|
|
421
419
|
|
package/buildinfo.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.2.
|
|
1
|
+
0.2.5+8056892
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@temir.ra/create-ts-lib",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Typescript library template",
|
|
5
5
|
"author": "temir.ra",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "https://git.
|
|
15
|
+
"url": "https://git.chimps.quest/trs/create-ts-lib.git"
|
|
16
16
|
},
|
|
17
17
|
"type": "module",
|
|
18
18
|
"sideEffects": false,
|
package/template/CLAUDE.md
CHANGED
|
@@ -77,30 +77,78 @@ import { Foo } from "./foo.js" // ✗ — if Foo is only used as a ty
|
|
|
77
77
|
|
|
78
78
|
### Asset Resolution (if the library has runtime assets)
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
The key question: **does your library retain its own URL at runtime?** Everything else follows from it.
|
|
81
|
+
|
|
82
|
+
- **Externalized** (loaded from CDN or `node_modules/`): `import.meta.url` is reliable as-is — no consumer action needed.
|
|
83
|
+
- **Bundled** (absorbed into the consumer's output): `import.meta.url` points to the consumer's bundle, not the library's file. The path relationship can be preserved by convention — if the consumer copies the library's assets into their build output at the same relative path, resolution continues to work correctly.
|
|
84
|
+
|
|
85
|
+
#### Contract
|
|
86
|
+
|
|
87
|
+
**The library must:**
|
|
88
|
+
1. Place assets in a scoped directory — `assets/@scope/lib-name/` (mirrors the package name, prevents collisions when multiple libraries share a consumer bundle).
|
|
89
|
+
2. Access assets via `import.meta.url` — see code below.
|
|
90
|
+
3. Document the bundled case in the library's README — see [README statement](#readme-statement-for-consumers) below.
|
|
91
|
+
|
|
92
|
+
**The consumer must,**
|
|
93
|
+
- **when loading the library externalized:** do nothing.
|
|
94
|
+
- **when bundling the library:** copy `node_modules/@scope/lib-name/assets/` into their build output alongside the bundle, and ensure the assets are served.
|
|
95
|
+
|
|
96
|
+
#### Scoped assets directory
|
|
81
97
|
|
|
82
98
|
```
|
|
83
|
-
assets
|
|
84
|
-
|
|
85
|
-
└──
|
|
99
|
+
assets/
|
|
100
|
+
└── @scope/
|
|
101
|
+
└── lib-name/
|
|
102
|
+
└── <ASSETS>
|
|
86
103
|
```
|
|
87
104
|
|
|
105
|
+
Add `assets/` to `files` in `package.json` so it is included in the published package:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
"files": ["dist", "CHANGELOG.md", "buildinfo.txt", "assets"]
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Accessing assets
|
|
112
|
+
|
|
88
113
|
Resolve asset URLs inline from `import.meta.url` — no shared helper file:
|
|
89
114
|
|
|
90
115
|
```typescript
|
|
91
116
|
const packageUrl = new URL('../', import.meta.url);
|
|
92
117
|
const assetsUrl = new URL('assets/@scope/lib-name/', packageUrl);
|
|
93
118
|
|
|
94
|
-
//
|
|
119
|
+
// for --target browser
|
|
95
120
|
const data = await fetch(new URL('data.json', assetsUrl)).then(r => r.json());
|
|
96
121
|
|
|
97
|
-
//
|
|
122
|
+
// for --target node
|
|
98
123
|
import { readFile } from 'node:fs/promises';
|
|
99
124
|
import { fileURLToPath } from 'url';
|
|
100
125
|
const raw = await readFile(fileURLToPath(new URL('data.json', assetsUrl)), 'utf-8');
|
|
101
126
|
```
|
|
102
127
|
|
|
103
|
-
|
|
128
|
+
#### When the library is bundled by the consumer
|
|
129
|
+
|
|
130
|
+
The consumer must copy assets into their build output at the same relative path:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
consumer output/
|
|
134
|
+
├── bundle.js ← import.meta.url points here
|
|
135
|
+
└── assets/
|
|
136
|
+
└── @scope/
|
|
137
|
+
└── lib-name/
|
|
138
|
+
└── <ASSETS> ← copied; relative path preserved
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
No code configuration needed — only the file copy.
|
|
142
|
+
|
|
143
|
+
#### README statement for consumers
|
|
144
|
+
|
|
145
|
+
Copy the following into the library's README (replace `<SCOPE>` and `<LIB_NAME>`):
|
|
146
|
+
|
|
147
|
+
```markdown
|
|
148
|
+
## Asset resolution
|
|
149
|
+
|
|
150
|
+
This library resolves assets at runtime using `import.meta.url`. If you bundle this library into your application, copy `node_modules/<SCOPE>/<LIB_NAME>/assets/<SCOPE>/<LIB_NAME>/` into your build output directory alongside your bundle.
|
|
151
|
+
```
|
|
104
152
|
|
|
105
153
|
### Tests
|
|
106
154
|
|
package/template/README.md
CHANGED
|
@@ -36,10 +36,20 @@ bun run dev
|
|
|
36
36
|
|
|
37
37
|
# Documentation
|
|
38
38
|
|
|
39
|
-
> If this library has runtime assets, see the **Asset Resolution** section in the create-ts-lib README for the setup guide, code examples, checklist, and consumer README statement.
|
|
40
|
-
|
|
41
39
|
*<DOCUMENTATION>*
|
|
42
40
|
|
|
41
|
+
## Asset Resolution
|
|
42
|
+
|
|
43
|
+
*<!-- Remove this section if the library has no runtime assets. Replace `@scope/lib-name` throughout with the actual package name. -->*
|
|
44
|
+
|
|
45
|
+
Assets are placed under `assets/@scope/lib-name/` (scoped to the package name to prevent collisions). They are resolved at runtime via `import.meta.url` and loaded with `fetch()` (browser) or `readFile` (Node). `assets/` must be listed in `files` in `package.json`.
|
|
46
|
+
|
|
47
|
+
`import.meta.url` is reliable when the library is loaded as a discrete module (from CDN or `node_modules/`). When the consumer bundles the library, they must copy the assets — see below.
|
|
48
|
+
|
|
49
|
+
### For consumers bundling this library
|
|
50
|
+
|
|
51
|
+
Copy `node_modules/@scope/lib-name/assets/` into your build output alongside the bundle, preserving the relative path. No code configuration is required — only the file copy.
|
|
52
|
+
|
|
43
53
|
# DevOps
|
|
44
54
|
|
|
45
55
|
## Change Management
|
|
@@ -10,7 +10,7 @@ describe('buildInfo', () => {
|
|
|
10
10
|
it('should follow semantic versioning format with optional commit hash', () => {
|
|
11
11
|
const buildinfoPath = fileURLToPath(buildinfoUrl);
|
|
12
12
|
const buildinfo = readFileSync(buildinfoPath, 'utf-8').trim();
|
|
13
|
-
expect(buildinfo).toMatch(/^\d+\.\d+\.\d+(\+[
|
|
13
|
+
expect(buildinfo).toMatch(/^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
it('should not contain whitespace', () => {
|