@temir.ra/create-workspace 0.2.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 ADDED
@@ -0,0 +1,17 @@
1
+ # Version 0
2
+
3
+ ## 0.2.0
4
+
5
+ 1. Removed **AI Assistant Context** section from the `README.md` files.
6
+ 2. Alligned `README.md` with the `ts-lib@0.6.2` template.
7
+ 3. Cleaned up **Publish** section in `README.md`.
8
+ 4. Rephrased the `README.md` to reflect that the generated package is workspace-aware but not necessarily a root package.
9
+ 5. Renamed the package from `create-monorepo` to `create-workspace`.
10
+
11
+ ## 0.1.1
12
+
13
+ 1. Fixed upstream repository URL in package.json.
14
+
15
+ ## 0.1.0
16
+
17
+ 1. First version of the template.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Temir Ra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,320 @@
1
+ # Introduction
2
+
3
+ A template for a package with build metadata, tests, and workspace-aware scripts. The generated package works standalone; add a `workspaces` field to scale it into a monorepo.
4
+
5
+ The following templates are available in this ecosystem:
6
+
7
+ | Template | Purpose |
8
+ |---|---|
9
+ | [`create-ts-lib`](#create-ts-lib) | TypeScript library distributed via registry |
10
+ | [`create-hono-server`](#create-hono-server) | Bun/Hono HTTP server |
11
+ | [`create-hono-spa`](#create-hono-spa) | Frontend SPA as a Hono sub-app library |
12
+ | [`create-workspace`](#packagejson) | Package with workspace support *(this template)* |
13
+
14
+ ## Table of Contents
15
+
16
+ 1. [Quick Start](#quick-start)
17
+ 2. [Documentation](#documentation)
18
+ 1. [`package.json`](#packagejson)
19
+ 2. [Workspaces](#workspaces)
20
+ 3. [Cross-workspace Dependencies](#cross-workspace-dependencies)
21
+ 4. [Scaffolding Patterns](#scaffolding-patterns)
22
+ 1. [Library](#library)
23
+ 2. [Server](#server)
24
+ 3. [Server + SPA](#server--spa)
25
+ 4. [Full-Stack with Shared Types](#full-stack-with-shared-types)
26
+ 3. [DevOps](#devops)
27
+ 1. [Change Management](#change-management)
28
+ 2. [Publish](#publish)
29
+
30
+ # Quick Start
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
+ ```bash
35
+ # placeholder:
36
+ # <PACKAGE: <PACKAGE>
37
+ # <@_VERSION: <@_VERSION>
38
+
39
+ # identify the latest version of the template package as <@_VERSION.
40
+ bun info "@temir.ra/create-workspace" version
41
+ # create a new package from the template version
42
+ bun create --no-install --no-git "@temir.ra/create-workspace<@_VERSION>" <PACKAGE>
43
+
44
+ # or
45
+
46
+ # clear package manager cache to ensure the latest template version is used
47
+ bun pm cache rm
48
+ # create a new package from the latest template version
49
+ bun create --no-install --no-git "@temir.ra/create-workspace" <PACKAGE>
50
+
51
+ # dependencies must be installed manually
52
+ cd <PACKAGE>
53
+ bun install
54
+ ```
55
+
56
+ # Documentation
57
+
58
+ The following sections explain the configurations and conventions baked into the generated package. Useful when adapting it to fit specific needs.
59
+
60
+ ## `package.json`
61
+
62
+ See npmjs documentation on [package.json](https://docs.npmjs.com/cli/v11/configuring-npm/package-json) for detailed explanations of all fields.
63
+
64
+ ```json
65
+ {
66
+ "name": "",
67
+ "version": "0.0.0",
68
+
69
+ "description": "",
70
+ "author": "",
71
+ "license": "",
72
+
73
+ // prevents publishing to a registry
74
+ "private": true,
75
+
76
+ "scripts": {
77
+
78
+ // removes dist/
79
+ "clean:dist": "rm -rf dist/",
80
+
81
+ // removes dist/ and propagates clean to any workspace packages
82
+ "clean": "bun run clean:dist && bun run --filter '*' clean",
83
+
84
+ // generates buildinfo.txt before each build
85
+ "prebuild": "bun run scripts/buildinfo.ts",
86
+
87
+ // propagates build to any workspace packages
88
+ "build": "bun run --filter '*' build",
89
+
90
+ // runs local tests and propagates tests to any workspace packages
91
+ "tests": "bun test && bun run --filter '*' tests",
92
+
93
+ // propagates typecheck to any workspace packages
94
+ "typecheck": "bun run --filter '*' typecheck"
95
+
96
+ }
97
+
98
+ }
99
+ ```
100
+
101
+ The `--filter '*'` scripts forward to any workspace packages when a `workspaces` field is present; they are no-ops otherwise. See [Workspaces](#workspaces) for how to opt in.
102
+
103
+ ## Workspaces
104
+
105
+ To extend the package into a monorepo, add a `workspaces` field to `package.json` and run `bun install`:
106
+
107
+ ```json
108
+ {
109
+ "workspaces": [
110
+ "packages/*"
111
+ ]
112
+ }
113
+ ```
114
+
115
+ The execution environment installs all workspace dependencies into a single shared `node_modules/` at the root and symlinks each workspace package by its `name` field. Cross-workspace imports resolve by package name without path aliases or module mapping.
116
+
117
+ ```
118
+ <PACKAGE>/
119
+ ├── package.json ← root
120
+ └── packages/
121
+ ├── pkg-a/
122
+ │ ├── package.json
123
+ │ └── ...
124
+ └── pkg-b/
125
+ ├── package.json
126
+ └── ...
127
+ ```
128
+
129
+ ### Cross-workspace Dependencies
130
+
131
+ To use one workspace package from another, declare it as a dependency using the `workspace:` protocol:
132
+
133
+ ```json
134
+ // packages/pkg-a/package.json
135
+ {
136
+ "dependencies": {
137
+
138
+ // workspace: resolves to the local package instead of fetching from a registry;
139
+ // workspace:* tracks the exact local version;
140
+ // workspace:^ is replaced by ^version on publish, tracking the semver range in the registry
141
+ "@scope/pkg-b": "workspace:*"
142
+
143
+ }
144
+ }
145
+ ```
146
+
147
+ Run `bun install` after adding the entry. The execution environment creates the symlink in `node_modules/` so imports resolve by package name at runtime and at the type level - no path alias or `paths` mapping required.
148
+
149
+ ### Scaffolding Patterns
150
+
151
+ Scaffold the package first, add `workspaces` to `package.json`, then scaffold workspace packages inside it. After scaffolding each workspace package, update its `package.json` with the correct `name`, `version`, `description`, `author`, `license`, and `repository` fields. To wire cross-workspace dependencies, add the `workspace:*` entry to the consuming package's `package.json` and run `bun install` from the root.
152
+
153
+ #### Library
154
+
155
+ ```
156
+ <package>/
157
+ └── packages/
158
+ └── my-lib/ ← create-ts-lib
159
+ ```
160
+
161
+ ```bash
162
+ bun create --no-install --no-git "@temir.ra/create-workspace" <package>
163
+ cd <package>
164
+ bun create --no-install --no-git "@temir.ra/ts-lib" packages/my-lib
165
+ bun install
166
+ ```
167
+
168
+ ##### `create-ts-lib`
169
+
170
+ Starting point for any package distributed via a registry. See the full documentation at [`@temir.ra/create-ts-lib`](https://www.npmjs.com/package/@temir.ra/create-ts-lib).
171
+
172
+ - Dual `tsconfig`: `tsconfig.json` (dev, `bundler` resolution, includes `tests/` + `scripts/`) and `tsconfig.build.json` (prod, `nodenext`, `src/` only, emits JS + `.d.ts`)
173
+ - `exports` conditions: `entrypoint` (custom, source entry for the bundle script), `types`, `browser` (bundled output), `import` (compiled ESM)
174
+ - `imports` field: `#src/*.js` → `./src/*.ts` - runtime alias for `dev.ts`, `tests/`, `scripts/` only
175
+ - Build metadata: `scripts/buildinfo.ts` generates `buildinfo.txt` (version + git hash) as a `prebuild` hook
176
+ - Bundle script: `scripts/build-lib-bundle.ts` bundles via Bun; supports CDN specifier rewriting via `cdn-rewrite-map.json`
177
+ - Asset resolution contract: assets under `assets/@scope/lib-name/`, accessed via `import.meta.url` + `fetch()`
178
+ - Optional CLI entry point via `bin` field and `build:cli-bundle` script
179
+
180
+ #### Server
181
+
182
+ ```
183
+ <package>/
184
+ └── packages/
185
+ └── server/ ← create-hono-server
186
+ ```
187
+
188
+ ```bash
189
+ bun create --no-install --no-git "@temir.ra/create-workspace" <package>
190
+ cd <package>
191
+ bun create --no-install --no-git "@temir.ra/hono-server" packages/server
192
+ bun install
193
+ ```
194
+
195
+ ##### `create-hono-server`
196
+
197
+ Starting point for any HTTP backend. See the full documentation at [`@temir.ra/create-hono-server`](https://www.npmjs.com/package/@temir.ra/create-hono-server).
198
+
199
+ - `createAppHost(options)` - configures and returns a `Hono<AppEnv>` instance
200
+ - Built-in middleware pipeline: `Logging`, `requestId`, `RequestLogger`, `compress`, `secureHeaders`
201
+ - Built-in endpoints: `/health`, `/buildinfo`, OpenAPI spec, Scalar UI
202
+ - `endpointGroups` - mounts additional `Hono` sub-apps; integration point for SPA packages
203
+ - `AppEnv` - exported, extensible context type; extend it to carry custom variables through the context
204
+ - `startServerHost(options)` - wraps `Bun.serve()`, default port 7200, graceful shutdown on SIGINT/SIGTERM
205
+
206
+ #### Server + SPA
207
+
208
+ ```
209
+ <package>/
210
+ └── packages/
211
+ ├── server/ ← create-hono-server
212
+ └── spa/ ← create-hono-spa
213
+ ```
214
+
215
+ ```bash
216
+ bun create --no-install --no-git "@temir.ra/create-workspace" <package>
217
+ cd <package>
218
+ bun create --no-install --no-git "@temir.ra/hono-server" packages/server
219
+ bun create --no-install --no-git "@temir.ra/hono-spa" packages/spa
220
+ bun install
221
+ ```
222
+
223
+ Add the SPA as a dependency of the server, then reinstall:
224
+
225
+ ```json
226
+ // packages/server/package.json
227
+ {
228
+ "dependencies": {
229
+ "@scope/spa": "workspace:*"
230
+ }
231
+ }
232
+ ```
233
+
234
+ ```bash
235
+ bun install
236
+ ```
237
+
238
+ ##### `create-hono-spa`
239
+
240
+ Starting point for a frontend SPA distributed as a Hono sub-app library. See the full documentation at [`@temir.ra/create-hono-spa`](https://www.npmjs.com/package/@temir.ra/create-hono-spa).
241
+
242
+ - `createSpa(options)` - returns a `Hono` sub-app serving the SPA shell
243
+ - `/app/*` wildcard handles client-side routing; `<base href>` patched at request time from `basePath` and `path`
244
+ - Assets resolved via `import.meta.url`; no file copying or static serving config needed on the consuming server
245
+ - PWA scaffold in `assets/`: `index.html`, `favicon.svg`, `manifest.webmanifest`, screenshots
246
+ - Distributed as a library (`exports` + `dist/` + `assets/`); consumed via `workspace:*` in the server
247
+
248
+ #### Full-Stack with Shared Types
249
+
250
+ ```
251
+ <package>/
252
+ └── packages/
253
+ ├── server/ ← create-hono-server
254
+ ├── spa/ ← create-hono-spa
255
+ └── types/ ← create-ts-lib
256
+ ```
257
+
258
+ ```bash
259
+ bun create --no-install --no-git "@temir.ra/create-workspace" <package>
260
+ cd <package>
261
+ bun create --no-install --no-git "@temir.ra/hono-server" packages/server
262
+ bun create --no-install --no-git "@temir.ra/hono-spa" packages/spa
263
+ bun create --no-install --no-git "@temir.ra/ts-lib" packages/types
264
+ bun install
265
+ ```
266
+
267
+ Add the types package as a dependency of both the server and the SPA, then reinstall:
268
+
269
+ ```json
270
+ // packages/server/package.json and packages/spa/package.json
271
+ {
272
+ "dependencies": {
273
+ "@scope/types": "workspace:*"
274
+ }
275
+ }
276
+ ```
277
+
278
+ ```bash
279
+ bun install
280
+ ```
281
+
282
+ # DevOps
283
+
284
+ ```bash
285
+ # remove dist/ and tsconfig.tsbuildinfo and tsconfig.build.tsbuildinfo
286
+ bun run clean
287
+
288
+ # remove dist/ only
289
+ bun run clean:dist
290
+
291
+ # remove tsconfig.tsbuildinfo and tsconfig.build.tsbuildinfo only
292
+ bun run clean:tsbuildinfo
293
+
294
+ # compile + bundle
295
+ bun run build
296
+
297
+ # create a new test package in example/
298
+ bun run dist/cli.bundle.js -- example
299
+ ```
300
+
301
+ ## Change Management
302
+
303
+ 1. Create a new branch for the change.
304
+ 2. Make the changes and commit.
305
+ 3. Bump the version in [`package.json`](package.json).
306
+ 4. Add an entry for the new version in [`CHANGELOG.md`](CHANGELOG.md).
307
+ 5. Pull request the branch.
308
+ 6. After merge, run `bun run build` - ensures artifacts are current before publish.
309
+ 7. Publish.
310
+
311
+ ## Publish
312
+
313
+ Publish to the public npm registry.
314
+
315
+ ```powershell
316
+ # authenticate
317
+ npm login
318
+ # publish
319
+ bun publish --registry https://registry.npmjs.org/ --access public
320
+ ```
package/buildinfo.txt ADDED
@@ -0,0 +1 @@
1
+ 0.2.0+19ecc29
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { cpSync, readFileSync, renameSync, writeFileSync } from 'fs';
3
+ import { resolve, basename } 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-workspace <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
+ }
@@ -0,0 +1,7 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,8 @@
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');
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@temir.ra/create-workspace",
3
+ "version": "0.2.0",
4
+ "description": "Package scaffold with workspace support",
5
+ "author": "temir.ra",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "typescript",
9
+ "template",
10
+ "workspace",
11
+ "bun"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://git.chimps.quest/trs/create-workspace.git"
16
+ },
17
+ "type": "module",
18
+ "imports": {
19
+ "#src/*.js": "./src/*.ts"
20
+ },
21
+ "bin": "./dist/cli.bundle.js",
22
+ "files": [
23
+ "dist",
24
+ "CHANGELOG.md",
25
+ "buildinfo.txt",
26
+ "template"
27
+ ],
28
+ "scripts": {
29
+ "clean:dist": "rm -rf dist/",
30
+ "clean:tsbuildinfo": "rm -f tsconfig.build.tsbuildinfo",
31
+ "clean": "bun run clean:dist && bun run clean:tsbuildinfo",
32
+ "prebuild": "bun run scripts/buildinfo.ts",
33
+ "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
+ "typecheck": "tsc --noEmit",
38
+ "dev": "bun run --watch src/dev.ts"
39
+ },
40
+ "devDependencies": {
41
+ "@types/bun": "latest",
42
+ "typescript": "^6.0.2"
43
+ }
44
+ }
@@ -0,0 +1,5 @@
1
+ # Version 0
2
+
3
+ ## 0.0.0
4
+
5
+ 1. Versioning initialized.
@@ -0,0 +1,76 @@
1
+ # Introduction
2
+
3
+ *&lt;INTRO TEXT&gt;*
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Quick Start](#quick-start)
8
+ 2. [Documentation](#documentation)
9
+ 3. [DevOps](#devops)
10
+ 1. [Change Management](#change-management)
11
+ 2. [Publish](#publish)
12
+ 1. [npmjs.org](#npmjsorg)
13
+ 2. [Custom registry](#custom-registry)
14
+
15
+ # Quick Start
16
+
17
+ *&lt;QUICK START INSTRUCTIONS&gt;*
18
+
19
+ # Documentation
20
+
21
+ *&lt;DOCUMENTATION&gt;*
22
+
23
+ # DevOps
24
+
25
+ ## Change Management
26
+
27
+ 1. Create a new branch for the change.
28
+ 2. Make the changes and commit.
29
+ 3. Bump the version in [`package.json`](package.json).
30
+ 4. Add an entry for the new version in [`CHANGELOG.md`](CHANGELOG.md).
31
+ 5. Pull request the branch.
32
+ 6. After merge, run `bun run build` - ensures artifacts are current before publish.
33
+ 7. Publish.
34
+
35
+ ## Publish
36
+
37
+ See the following sources to configure the target registry and authentication.
38
+
39
+ - [Configuring npm - `npmrc`](https://docs.npmjs.com/cli/v10/configuring-npm/npmrc)
40
+ - [Bun package manager - `install.registry`](https://bun.com/docs/runtime/bunfig#install-scopes)
41
+
42
+ ⚠️ Package Scope and the authentication for the target registry must be aligned.
43
+
44
+ ### `npmjs.org`
45
+
46
+ Publish to the public npm registry.
47
+
48
+ ```powershell
49
+ # authenticate
50
+ npm login
51
+ # publish
52
+ bun publish --registry https://registry.npmjs.org/ --access public
53
+ ```
54
+
55
+ ### Custom registry
56
+
57
+ ```bash
58
+ # placeholder:
59
+ # <SCOPE_WITHOUT_AT: <SCOPE_WITHOUT_AT>
60
+ # <REGISTRY_URL: <REGISTRY_URL>
61
+ # <BUN_PUBLISH_AUTH_TOKEN: <BUN_PUBLISH_AUTH_TOKEN>
62
+ ```
63
+
64
+ `~/.bunfig.toml` or `bunfig.toml`:
65
+
66
+ ```toml
67
+ [install.scopes]
68
+ "<SCOPE_WITHOUT_AT>" = { url = "<REGISTRY_URL>", token = "$BUN_PUBLISH_AUTH_TOKEN" }
69
+ ```
70
+
71
+ ```powershell
72
+ # authenticate
73
+ $env:BUN_PUBLISH_AUTH_TOKEN = "<BUN_PUBLISH_AUTH_TOKEN>"
74
+ # publish
75
+ bun publish
76
+ ```
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1 @@
1
+ node_modules
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "",
3
+ "version": "0.0.0",
4
+ "description": "",
5
+ "author": "",
6
+ "license": "",
7
+ "private": true,
8
+ "scripts": {
9
+ "clean:dist": "rm -rf dist/",
10
+ "clean": "bun run clean:dist && bun run --filter '*' clean",
11
+ "prebuild": "bun run scripts/buildinfo.ts",
12
+ "build": "bun run --filter '*' build",
13
+ "tests": "bun test && bun run --filter '*' tests",
14
+ "typecheck": "bun run --filter '*' typecheck"
15
+ }
16
+ }
@@ -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,23 @@
1
+ import { describe, it, expect } from 'bun:test';
2
+ import { readFileSync } from 'fs';
3
+ import { fileURLToPath } from 'url';
4
+
5
+
6
+ const buildinfoUrl = new URL('../buildinfo.txt', import.meta.url);
7
+
8
+ // taken from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
9
+ // Captures: [1]=major, [2]=minor, [3]=patch, [4]=pre-release, [5]=build-metadata
10
+ const SEMVER_REGEX =
11
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
12
+
13
+ function readBuildinfo(): string {
14
+ return readFileSync(fileURLToPath(buildinfoUrl), 'utf-8').trim();
15
+ }
16
+
17
+ describe('buildInfo', () => {
18
+
19
+ it('should be a valid semver string', () => {
20
+ expect(readBuildinfo()).toMatch(SEMVER_REGEX);
21
+ });
22
+
23
+ });
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "lib": [
6
+ "ESNext",
7
+ "DOM"
8
+ ],
9
+ "moduleResolution": "bundler",
10
+ "strict": true,
11
+ "verbatimModuleSyntax": true,
12
+ "noUncheckedIndexedAccess": true,
13
+ "exactOptionalPropertyTypes": true,
14
+ "noImplicitOverride": true,
15
+ "isolatedDeclarations": true,
16
+ "esModuleInterop": true,
17
+ "composite": true,
18
+ "skipLibCheck": true,
19
+ "forceConsistentCasingInFileNames": true,
20
+ "resolveJsonModule": true
21
+ },
22
+ "include": [
23
+ "tests/**/*.ts",
24
+ "scripts/**/*.ts"
25
+ ],
26
+ "exclude": [
27
+ "node_modules"
28
+ ]
29
+ }