limina 0.0.1 → 0.0.2
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/LICENSE.md +21 -0
- package/README.md +384 -0
- package/bin/limina.js +0 -0
- package/chunks/{dep-DoSHsBSP.js → dep-uPXyoC0V.js} +654 -206
- package/cli.js +225 -150
- package/config.d.ts +7 -41
- package/index.d.ts +20 -2
- package/index.js +2 -2
- package/package.json +14 -2
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present, Senao Xi. and docs islands contributors.
|
|
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,384 @@
|
|
|
1
|
+
# limina
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="https://npmjs.com/package/limina"><img src="https://img.shields.io/npm/v/limina.svg" alt="npm package"></a>
|
|
5
|
+
<a href="https://nodejs.org/en/about/previous-releases"><img src="https://img.shields.io/node/v/limina.svg" alt="node compatibility"></a>
|
|
6
|
+
<a href="https://github.com/XiSenao/docs-islands/actions/workflows/ci.yml"><img src="https://github.com/XiSenao/docs-islands/actions/workflows/ci.yml/badge.svg?branch=main" alt="build status"></a>
|
|
7
|
+
<a href="https://github.com/XiSenao/docs-islands/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/limina.svg" alt="license"></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
English | [简体中文](./README.zh-CN.md)
|
|
11
|
+
|
|
12
|
+
`limina` is a configurable governance CLI for TypeScript monorepos. It keeps TypeScript project references, source typechecks, compatibility paths, package export policy, and publish-time package checks in one explicit `limina.config.mjs` file.
|
|
13
|
+
|
|
14
|
+
Limina is not a bundler and does not replace `tsc`, `vue-tsc`, tests, or release tooling. It coordinates them and verifies that the architecture they depend on stays consistent.
|
|
15
|
+
|
|
16
|
+
## Why Limina?
|
|
17
|
+
|
|
18
|
+
Large TypeScript workspaces often need more than `tsc --noEmit`:
|
|
19
|
+
|
|
20
|
+
- project references must match real cross-project imports;
|
|
21
|
+
- production graph projects should not depend on tools or tests;
|
|
22
|
+
- browser/runtime output should not import Node builtins;
|
|
23
|
+
- `workspace:*` dependencies should resolve to source during graph checks;
|
|
24
|
+
- generated compatibility `paths` should not silently drift;
|
|
25
|
+
- built package outputs need consumer-facing checks before release;
|
|
26
|
+
- Vue, docs, playground, and smoke checks may need checker-specific tooling outside native `tsc -b`.
|
|
27
|
+
|
|
28
|
+
Limina makes these rules reviewable, runnable, and suitable for CI.
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- **Project graph validation**: checks reachable TypeScript declaration leaves, references, graph-owned imports, package boundaries, and label-based deny rules.
|
|
33
|
+
- **Typecheck coverage proof**: verifies that reachable declaration leaves match strict local typecheck companions and that source files are covered by checker entries or allowlist entries.
|
|
34
|
+
- **Compatibility path generation**: writes opt-in `tsconfig.dts.paths.generated.json` files for `workspace:*` dependencies whose package exports still point at build artifacts.
|
|
35
|
+
- **Checker target runner**: runs configured TypeScript and UI-framework checker entries in `typecheck` or `build` execution mode.
|
|
36
|
+
- **Published package checks**: validates built package outputs with `publint`, Are The Types Wrong, and a runtime import boundary audit.
|
|
37
|
+
- **Composable pipelines**: combines built-in checks and shell commands into named workflows such as `typecheck`, `package`, and `publish`.
|
|
38
|
+
- **Typed configuration**: ships `defineConfig(...)` for editor hints and typed user configs.
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
- Node.js `^20.19.0 || >=22.12.0`
|
|
43
|
+
- pnpm workspace with `pnpm-workspace.yaml`
|
|
44
|
+
- TypeScript installed in the consuming repository
|
|
45
|
+
- ESM-compatible `limina.config.mjs`
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pnpm add -D limina typescript
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
Create `limina.config.mjs` at the workspace root:
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
import { defineConfig } from 'limina';
|
|
59
|
+
|
|
60
|
+
export default defineConfig({
|
|
61
|
+
config: {
|
|
62
|
+
checkers: {
|
|
63
|
+
typescript: {
|
|
64
|
+
preset: 'tsc',
|
|
65
|
+
entry: 'tsconfig.build.json',
|
|
66
|
+
},
|
|
67
|
+
vue: {
|
|
68
|
+
preset: 'vue-tsc',
|
|
69
|
+
entry: 'tsconfig.vue.build.json',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
graph: {
|
|
75
|
+
rules: {
|
|
76
|
+
'runtime-client': {
|
|
77
|
+
deny: {
|
|
78
|
+
refs: [
|
|
79
|
+
{
|
|
80
|
+
path: 'packages/app/src/node/tsconfig.lib.dts.json',
|
|
81
|
+
reason: 'client runtime must not depend on the Node runtime',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
proof: {
|
|
90
|
+
allowlist: [
|
|
91
|
+
{
|
|
92
|
+
file: 'src/generated/runtime.d.ts',
|
|
93
|
+
reason: 'Generated declaration stub covered by the runtime build process.',
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
packageChecks: {
|
|
99
|
+
targets: [
|
|
100
|
+
{
|
|
101
|
+
name: '@acme/core',
|
|
102
|
+
outDir: 'packages/core/dist',
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
pipelines: {
|
|
108
|
+
package: ['package:check'],
|
|
109
|
+
publish: ['graph:check', 'proof:check', 'package:check'],
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Add scripts:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"scripts": {
|
|
119
|
+
"typecheck": "limina check",
|
|
120
|
+
"lint:package": "limina package check",
|
|
121
|
+
"prepublishOnly": "limina check publish"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Run checks:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
pnpm typecheck
|
|
130
|
+
pnpm exec limina graph check
|
|
131
|
+
pnpm exec limina package check --package @acme/core
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Concepts
|
|
135
|
+
|
|
136
|
+
### Checker entry
|
|
137
|
+
|
|
138
|
+
Each checker has one required `config.checkers.<name>.entry`, usually a `tsconfig*.build.json` graph aggregator. `limina checker build` runs the checker's build execution from that entry when the preset supports it. `limina checker typecheck` walks the same entry, finds reachable `tsconfig*.dts.json` declaration leaves, and checks their paired local companions.
|
|
139
|
+
|
|
140
|
+
### Declaration leaf and local companion
|
|
141
|
+
|
|
142
|
+
Declaration leaves should have strict local companions. For example, `tsconfig.lib.dts.json` pairs with `tsconfig.lib.json`, and `tsconfig.dts.json` pairs with `tsconfig.json`.
|
|
143
|
+
|
|
144
|
+
The default `tsconfig.json` is the IDE/typecheck entry for its directory. A single-environment directory should use it as the local leaf; a multi-environment directory should make it a pure aggregator with `files: []` and `references`.
|
|
145
|
+
|
|
146
|
+
### Source dependencies and artifact dependencies
|
|
147
|
+
|
|
148
|
+
A dependency declared as `workspace:*` is considered a source dependency. It should be represented by project references and source-facing package exports.
|
|
149
|
+
|
|
150
|
+
A dependency declared as `link:`, `file:`, `catalog:`, or normal semver is treated as an artifact dependency. It should not be modeled as a project reference unless it is intentionally consumed as source.
|
|
151
|
+
|
|
152
|
+
### Package checks
|
|
153
|
+
|
|
154
|
+
Source graph checks do not prove that an installed package works for consumers. `limina package check` inspects built package outputs under `packageChecks.targets[].outDir` and checks the actual package manifest, exports, type resolution, and runtime imports. Publishable outputs whose `package.json` does not set `private: true` must also include root `README.md` and `LICENSE.md` files.
|
|
155
|
+
|
|
156
|
+
## CLI
|
|
157
|
+
|
|
158
|
+
```sh
|
|
159
|
+
limina [--config limina.config.mjs] [--mode mode] <command>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
| Command | Description |
|
|
163
|
+
| ----------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
164
|
+
| `limina check` | Run the built-in default check pipeline. |
|
|
165
|
+
| `limina check <pipeline>` | Run a named user pipeline from `pipelines`. |
|
|
166
|
+
| `limina graph check` | Validate project references and architecture import rules. |
|
|
167
|
+
| `limina proof check` | Prove declaration configs, local typecheck configs, and source coverage stay aligned. |
|
|
168
|
+
| `limina paths generate` | Generate compatibility source `paths` configs for artifact-facing workspace exports. |
|
|
169
|
+
| `limina paths apply` | Compatibility alias for `paths generate`. |
|
|
170
|
+
| `limina paths check` | Fail when generated path files are stale. |
|
|
171
|
+
| `limina checker typecheck` | Run typecheck targets derived from checker entries. |
|
|
172
|
+
| `limina checker build` | Run build execution for checker entries that support it. |
|
|
173
|
+
| `limina checker typecheck --concurrency <n>` | Limit concurrent checker processes. |
|
|
174
|
+
| `limina package check` | Run configured package output checks. |
|
|
175
|
+
| `limina package check --package <name>` | Check one configured package target. |
|
|
176
|
+
| `limina package check --tool <tool>` | Run only `publint`, `attw`, or `boundary`. |
|
|
177
|
+
| `limina package check --attw-profile <profile>` | Override the ATTW profile: `strict`, `node16`, or `esm-only`. |
|
|
178
|
+
|
|
179
|
+
## Configuration reference
|
|
180
|
+
|
|
181
|
+
### `config`
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
config: {
|
|
185
|
+
checkers: {
|
|
186
|
+
typescript: {
|
|
187
|
+
preset: 'tsc',
|
|
188
|
+
entry: 'tsconfig.build.json',
|
|
189
|
+
},
|
|
190
|
+
vue: {
|
|
191
|
+
preset: 'vue-tsc',
|
|
192
|
+
entry: 'tsconfig.vue.build.json',
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
source: {
|
|
196
|
+
exclude: ['node_modules', 'dist', '.tsbuild'],
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`config.checkers` defines checker entries. Every configured checker must declare a non-empty `entry`. Built-in presets can omit `extensions`; if `source.include` is omitted, Limina derives the source boundary from configured checker extensions, then applies `source.exclude`.
|
|
202
|
+
|
|
203
|
+
### `graph`
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
graph: {
|
|
207
|
+
rules: {
|
|
208
|
+
'runtime-client': {
|
|
209
|
+
deny: {
|
|
210
|
+
refs: [
|
|
211
|
+
{
|
|
212
|
+
path: 'packages/app/src/node/tsconfig.lib.dts.json',
|
|
213
|
+
reason: 'client runtime must stay independent from Node runtime',
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
deps: [
|
|
217
|
+
{
|
|
218
|
+
name: '@acme/internal-node',
|
|
219
|
+
reason: 'client runtime must not consume Node-only packages',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
name: 'node:*',
|
|
223
|
+
reason: 'client runtime must not import Node builtins',
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: '#server/*',
|
|
227
|
+
reason: 'client runtime must not use server-only package imports',
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
A declaration leaf opts into a rule by adding a `limina` label:
|
|
237
|
+
|
|
238
|
+
```jsonc
|
|
239
|
+
{
|
|
240
|
+
"limina": "runtime-client",
|
|
241
|
+
"extends": ["./tsconfig.json", "../../tsconfig.dts.base.json"],
|
|
242
|
+
"references": [],
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### `paths`
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
paths: {
|
|
250
|
+
generatedFileName: 'tsconfig.dts.paths.generated.json',
|
|
251
|
+
conditionPriority: ['source', 'development', 'types'],
|
|
252
|
+
artifactDirectories: ['dist', 'build', 'lib', 'esm', 'cjs', 'out'],
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Use generated paths only when a workspace package must keep artifact-facing exports while still being consumed as a graph-owned source dependency.
|
|
257
|
+
|
|
258
|
+
### `proof`
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
proof: {
|
|
262
|
+
allowlist: [
|
|
263
|
+
{
|
|
264
|
+
file: 'src/generated/runtime.d.ts',
|
|
265
|
+
reason: 'Generated file validated by the build pipeline.',
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Checker entries cover files validated by TypeScript or framework-aware tools. Allowlist entries are the final fallback after all configured checker entries fail to cover a source file; they should be rare and must include a reason.
|
|
272
|
+
|
|
273
|
+
### `packageChecks`
|
|
274
|
+
|
|
275
|
+
```js
|
|
276
|
+
packageChecks: {
|
|
277
|
+
targets: [
|
|
278
|
+
{
|
|
279
|
+
name: '@acme/core',
|
|
280
|
+
outDir: 'packages/core/dist',
|
|
281
|
+
checks: ['publint', 'attw', 'boundary'],
|
|
282
|
+
publint: { strict: true },
|
|
283
|
+
attw: { profile: 'esm-only' },
|
|
284
|
+
boundary: {
|
|
285
|
+
environment: (file) => file.startsWith('node/') ? 'node' : 'browser',
|
|
286
|
+
ignoredExternalPackages: ['@acme/runtime-shim'],
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
`outDir` must point at the built package directory that contains the publish-ready `package.json`. If that manifest does not set `private: true`, the same directory must also contain `README.md` and `LICENSE.md`.
|
|
294
|
+
|
|
295
|
+
### `pipelines`
|
|
296
|
+
|
|
297
|
+
```js
|
|
298
|
+
pipelines: {
|
|
299
|
+
package: [
|
|
300
|
+
{ type: 'command', command: 'pnpm', args: ['build'] },
|
|
301
|
+
'package:check',
|
|
302
|
+
],
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
`limina check` runs the built-in default pipeline: `graph:check`, `source:check`, `proof:check`, and `checker:typecheck`. `limina check <pipeline>` only runs user pipelines from `limina.config.mjs#pipelines`; if the name is missing, Limina reports the missing pipeline and asks you to define it there.
|
|
307
|
+
|
|
308
|
+
String steps can be built-in task names or simple commands. Use object command steps when arguments, `cwd`, or `env` need to be explicit.
|
|
309
|
+
|
|
310
|
+
## CI example
|
|
311
|
+
|
|
312
|
+
```yaml
|
|
313
|
+
name: Typecheck
|
|
314
|
+
|
|
315
|
+
on:
|
|
316
|
+
pull_request:
|
|
317
|
+
push:
|
|
318
|
+
branches: [main]
|
|
319
|
+
|
|
320
|
+
jobs:
|
|
321
|
+
typecheck:
|
|
322
|
+
runs-on: ubuntu-latest
|
|
323
|
+
steps:
|
|
324
|
+
- uses: actions/checkout@v4
|
|
325
|
+
- uses: pnpm/action-setup@v4
|
|
326
|
+
- uses: actions/setup-node@v4
|
|
327
|
+
with:
|
|
328
|
+
node-version: 20.19.0
|
|
329
|
+
cache: pnpm
|
|
330
|
+
- run: pnpm install --frozen-lockfile
|
|
331
|
+
- run: pnpm exec limina check
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Programmatic API
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
import { defineConfig, loadConfig } from 'limina';
|
|
338
|
+
|
|
339
|
+
export default defineConfig({
|
|
340
|
+
pipelines: {
|
|
341
|
+
typecheck: ['graph:check'],
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
const config = await loadConfig();
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
Most users only need `defineConfig(...)`. `loadConfig(...)` is available for custom wrappers and tests.
|
|
349
|
+
|
|
350
|
+
## Troubleshooting
|
|
351
|
+
|
|
352
|
+
### `Unable to find limina config`
|
|
353
|
+
|
|
354
|
+
Run the command from inside the workspace, or pass `--config ./limina.config.mjs`.
|
|
355
|
+
|
|
356
|
+
### `no pnpm-workspace.yaml was found`
|
|
357
|
+
|
|
358
|
+
Limina infers the workspace root from `pnpm-workspace.yaml`. Place the config inside the workspace or pass a config path located under the workspace root.
|
|
359
|
+
|
|
360
|
+
### `packageChecks.targets[x].outDir` is invalid
|
|
361
|
+
|
|
362
|
+
Set `outDir` to the built package directory, not the source package directory, unless that directory is itself the publish-ready package output.
|
|
363
|
+
|
|
364
|
+
### Generated paths are stale
|
|
365
|
+
|
|
366
|
+
Run:
|
|
367
|
+
|
|
368
|
+
```sh
|
|
369
|
+
pnpm exec limina paths generate
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Then add the generated file to the first position of the listed `extends` arrays and commit the generated file if your repository policy requires reproducible `tsc -b` without a pre-generation step.
|
|
373
|
+
|
|
374
|
+
## Design principles
|
|
375
|
+
|
|
376
|
+
- Explicit policy is better than hidden presets.
|
|
377
|
+
- Source graph checks and package artifact checks validate different surfaces.
|
|
378
|
+
- Build graph configs should be strict, small, and directly referenced.
|
|
379
|
+
- Generated compatibility paths should be transitional, not the default architecture.
|
|
380
|
+
- Limina should fail with actionable messages instead of silently accepting graph drift.
|
|
381
|
+
|
|
382
|
+
## License
|
|
383
|
+
|
|
384
|
+
MIT
|
package/bin/limina.js
CHANGED
|
File without changes
|