@ts-ioc-container/bundler 6.0.0 → 7.0.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/AGENTS.md +26 -13
- package/README.md +63 -28
- package/cjm/app.js +2 -2
- package/cjm/cli/usage.js +6 -4
- package/cjm/features/build/BuildConfig.js +42 -10
- package/cjm/features/build/BuildController.js +11 -6
- package/cjm/features/build/domain/tokenCollisions.js +1 -1
- package/cjm/features/build/services/BundleBuilder.js +2 -2
- package/cjm/features/build/services/TicConfigService.js +16 -5
- package/cjm/index.js +4 -2
- package/cjm/schema/ticConfigSchema.js +2 -2
- package/package.json +2 -2
- package/tic.schema.json +4 -10
- package/typings/app.d.ts +5 -4
- package/typings/cli/usage.d.ts.map +1 -1
- package/typings/features/build/BuildConfig.d.ts +47 -4
- package/typings/features/build/BuildConfig.d.ts.map +1 -1
- package/typings/features/build/BuildController.d.ts +14 -9
- package/typings/features/build/BuildController.d.ts.map +1 -1
- package/typings/features/build/services/BundleBuilder.d.ts +8 -5
- package/typings/features/build/services/BundleBuilder.d.ts.map +1 -1
- package/typings/features/build/services/TicConfigService.d.ts +11 -5
- package/typings/features/build/services/TicConfigService.d.ts.map +1 -1
- package/typings/index.d.ts +1 -1
- package/typings/schema/ticConfigSchema.d.ts.map +1 -1
package/AGENTS.md
CHANGED
|
@@ -7,10 +7,11 @@ nothing here runs inside the container, and the core package is not changed by
|
|
|
7
7
|
it.
|
|
8
8
|
|
|
9
9
|
- The CLI is `ts-ioc-container`, with `tic` as a shortcut (both `bin` entries,
|
|
10
|
-
same program): `tic build [<config
|
|
11
|
-
file `<config>` (JSON for `.json`, YAML for `.yaml` / `.yml`) —
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
same program): `tic build [<config>...]` is a Unix filter. It reads the config
|
|
11
|
+
file `<config>` (JSON for `.json`, YAML for `.yaml` / `.yml`) — several are
|
|
12
|
+
merged left to right into one bundle — or, without one or with `-`, config
|
|
13
|
+
text from stdin (parsed as YAML, which covers JSON; never merged) — and
|
|
14
|
+
prints the bundle to **stdout**; it writes nothing. Saving is the shell's
|
|
14
15
|
job: `tic build app.bundle.json > src/di/app.bundle.ts`,
|
|
15
16
|
`cat dev.bundle.json | tic build > src/di/dev.bundle.ts`; CI checks with
|
|
16
17
|
`tic build app.bundle.json | diff - src/di/app.bundle.ts`. Warnings and errors
|
|
@@ -20,7 +21,7 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
20
21
|
bundle works wherever it is saved; a selected class no alias covers fails the
|
|
21
22
|
build naming its file. There are no relative imports.
|
|
22
23
|
- Config fields (schema: `tic.schema.json`), flat: `paths` with `paths.include`
|
|
23
|
-
required; `
|
|
24
|
+
required; `match`, `name`, `tsconfig`, `importExtension` optional.
|
|
24
25
|
Relative paths resolve against the config file; for piped text, against the
|
|
25
26
|
working directory. `name` defaults to the file's stem (`prod.bundle.json` →
|
|
26
27
|
`prod`) and is required for piped text or a file named otherwise; the class
|
|
@@ -31,9 +32,9 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
31
32
|
name and generated imports are written in (most specific alias, else a
|
|
32
33
|
relative path) — and the module resolution that sets the import extension.
|
|
33
34
|
- Selection has two stages, `paths: { include, exclude }` and
|
|
34
|
-
`
|
|
35
|
-
or a list in its place is an error); `
|
|
36
|
-
list as a shortcut for `
|
|
35
|
+
`match: { ..., glob, exclude }`. `paths` is always an object (a string
|
|
36
|
+
or a list in its place is an error); `match` also takes a string or a
|
|
37
|
+
list as a shortcut for `match.glob`. `paths` decides by path which files
|
|
37
38
|
are read and parsed at all. `paths.include` (required: one folder or a
|
|
38
39
|
non-empty list) names the folders scanned, always with their sub-folders —
|
|
39
40
|
relative to the config file (`./src/services`) or tsconfig aliases
|
|
@@ -43,8 +44,8 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
43
44
|
catch-all `"*"` aliases are skipped; default: test files, `__tests__/`,
|
|
44
45
|
`node_modules/`; a non-empty value replaces it, and the build warns if it drops
|
|
45
46
|
a default). Files `tic build` generated are never input.
|
|
46
|
-
- `
|
|
47
|
-
/ `['*Service', '*Repository']` = `
|
|
47
|
+
- `match: { export, decorators, glob, exclude }` (or `match: '*Service'`
|
|
48
|
+
/ `['*Service', '*Repository']` = `match.glob`, default `export` and
|
|
48
49
|
`decorators`) then picks classes of the parsed files; default is every exported,
|
|
49
50
|
non-abstract class decorated with `@register` (`decorators` defaults to
|
|
50
51
|
`["register"]`; `[]` requires none); positive criteria must all hold — `glob` is one glob
|
|
@@ -54,12 +55,23 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
54
55
|
two selected classes pass the same plain-identifier first decorator argument (a
|
|
55
56
|
same-token heuristic), unless a decorator they share has differing arguments
|
|
56
57
|
(scope-gated, e.g. `@perPage('a')` vs `@perPage('b')`).
|
|
58
|
+
- Several configs merge like webpack-merge (`mergeConfigs`):
|
|
59
|
+
`tic build common.bundle.yml prod.bundle.yml > src/di/prod.bundle.ts`.
|
|
60
|
+
Objects merge field by field; the list fields `paths.include`,
|
|
61
|
+
`paths.exclude`, `match.glob`, `match.exclude` and `match.decorators`
|
|
62
|
+
concatenate without duplicates (a later config only adds); any other value
|
|
63
|
+
set later replaces an earlier one; the `match` shorthand merges as
|
|
64
|
+
`match.glob`. Each file is validated alone (`BUNDLE_CONFIG_FILE_SCHEMA`:
|
|
65
|
+
`paths` optional; errors name the file), the merged result as one config
|
|
66
|
+
(`BUNDLE_CONFIG_SCHEMA`). Defaults apply to the merged config only. The last
|
|
67
|
+
file names the bundle unless one sets `name`; all must sit in one folder.
|
|
57
68
|
- Never edit a `*.bundle.ts` by hand — change the classes or the config and
|
|
58
69
|
rerun `tic build`.
|
|
59
70
|
- Unknown config fields are errors, at every level.
|
|
60
|
-
- Programmatic API: `build({ config, cwd })`
|
|
71
|
+
- Programmatic API: `build({ config, cwd })` (`config`: a file or a list merged
|
|
72
|
+
left to right) or `build({ text, cwd })` returns
|
|
61
73
|
`{ content, bundle, registrations, warnings }` and writes nothing;
|
|
62
|
-
`loadConfig(file)`, `run(argv, io)` (`io.stdin` backs piped configs); every error the
|
|
74
|
+
`loadConfig(file | files)`, `run(argv, io)` (`io.stdin` backs piped configs); every error the
|
|
63
75
|
bundler raises on purpose is a `TicError` with a stable `code`
|
|
64
76
|
(`TicConfigError` = `INVALID_CONFIG`, `NamespaceNotFoundError`, `UsageError`,
|
|
65
77
|
…).
|
|
@@ -72,4 +84,5 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
72
84
|
services behind tokens (`IBundleBuilderKey`, `ITicConfigServiceKey`, …); pure
|
|
73
85
|
logic in `lib/features/build/domain/`. A new command is a controller plus a module.
|
|
74
86
|
- The config schema is `BUNDLE_CONFIG_SCHEMA` (zod); `tic.schema.json` is generated
|
|
75
|
-
from
|
|
87
|
+
from its per-file variant `BUNDLE_CONFIG_FILE_SCHEMA` with `pnpm run generate:schema`
|
|
88
|
+
— never edit it by hand.
|
package/README.md
CHANGED
|
@@ -33,11 +33,12 @@ below use the shortcut.
|
|
|
33
33
|
## Build
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
|
-
tic build [<config
|
|
36
|
+
tic build [<config>...]
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
`tic build` prints the bundle to **stdout** and writes nothing. `<config>` is a
|
|
40
|
-
config file — JSON for `.json`, YAML for `.yaml` / `.yml`.
|
|
40
|
+
config file — JSON for `.json`, YAML for `.yaml` / `.yml`. Several are
|
|
41
|
+
[merged](#merging-configs) left to right into one bundle. Without one (or with
|
|
41
42
|
`-`) the config is read from **stdin**. Warnings and errors go to stderr, so
|
|
42
43
|
they never end up in the bundle.
|
|
43
44
|
|
|
@@ -46,6 +47,9 @@ they never end up in the bundle.
|
|
|
46
47
|
tic build app.bundle.json > src/di/app.bundle.ts
|
|
47
48
|
tic build prod.bundle.yml > src/di/prod.bundle.ts
|
|
48
49
|
|
|
50
|
+
# several configs merged into one bundle, like webpack-merge
|
|
51
|
+
tic build common.bundle.yml prod.bundle.yml > src/di/prod.bundle.ts
|
|
52
|
+
|
|
49
53
|
# the config piped in — it has no file name, so it sets `name` ("name": "dev")
|
|
50
54
|
cat dev.bundle.json | tic build > src/di/dev.bundle.ts
|
|
51
55
|
tic build < dev.bundle.yml > src/di/dev.bundle.ts
|
|
@@ -69,8 +73,9 @@ covers is an error naming its file; add a `paths` entry for its folder.
|
|
|
69
73
|
|
|
70
74
|
Relative paths in a config file resolve against the file; in a piped config,
|
|
71
75
|
against the working directory. The bundle is named after the config file —
|
|
72
|
-
`prod.bundle.json` exports `ProdBundle
|
|
73
|
-
piped config, or a file not named
|
|
76
|
+
`prod.bundle.json` exports `ProdBundle`; of several merged, after the last —
|
|
77
|
+
unless the config sets `name`, which a piped config, or a file not named
|
|
78
|
+
`<name>.bundle.json`, must.
|
|
74
79
|
|
|
75
80
|
## Configure
|
|
76
81
|
|
|
@@ -94,8 +99,8 @@ paths:
|
|
|
94
99
|
|
|
95
100
|
| Field | Default | Meaning |
|
|
96
101
|
| ----------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
97
|
-
| `paths` | — (required) | Which files are parsed — see [Selecting files](#selecting-files)
|
|
98
|
-
| `
|
|
102
|
+
| `paths` | — (required) | Which files are parsed — see [Selecting files](#selecting-files). Merged configs need it in one of them |
|
|
103
|
+
| `match` | exported classes with `@register` | Which classes of a parsed file are registered — see [Selecting classes](#selecting-classes) |
|
|
99
104
|
| `name` | the config file's (`app.bundle.json` → `app`) | The bundle's name: names the class, `AppBundle`. Required for a piped config or a file named otherwise |
|
|
100
105
|
| `tsconfig` | `./tsconfig.json` | Source of the `paths` aliases every import is written through, and of the import extension — never of files |
|
|
101
106
|
| `importExtension` | `.js` under node16/nodenext, else none | Extension of generated imports |
|
|
@@ -105,31 +110,37 @@ unnoticed.
|
|
|
105
110
|
|
|
106
111
|
## Several bundles
|
|
107
112
|
|
|
108
|
-
Need more than one bundle — per environment, per app? Keep
|
|
109
|
-
and build each
|
|
113
|
+
Need more than one bundle — per environment, per app? Keep what they share in
|
|
114
|
+
one config, what each adds in another, and build each environment from both:
|
|
110
115
|
|
|
111
116
|
```bash
|
|
112
117
|
for env in prod dev test; do
|
|
113
|
-
tic build "$env.bundle.yml" > "src/di/$env.bundle.ts"
|
|
118
|
+
tic build common.bundle.yml "$env.bundle.yml" > "src/di/$env.bundle.ts"
|
|
114
119
|
done
|
|
115
120
|
```
|
|
116
121
|
|
|
117
122
|
```json
|
|
118
123
|
{
|
|
119
124
|
"scripts": {
|
|
120
|
-
"bundle": "tic build
|
|
121
|
-
"bundle:check": "tic build
|
|
125
|
+
"bundle": "tic build common.bundle.yml prod.bundle.yml > src/di/prod.bundle.ts",
|
|
126
|
+
"bundle:check": "tic build common.bundle.yml prod.bundle.yml | diff - src/di/prod.bundle.ts"
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
129
|
```
|
|
125
130
|
|
|
126
|
-
Each config selects its own files and classes:
|
|
127
|
-
|
|
128
131
|
```yaml
|
|
129
|
-
#
|
|
132
|
+
# common.bundle.yml: what every environment registers
|
|
130
133
|
paths:
|
|
131
134
|
include:
|
|
132
135
|
- '@app/services'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Each environment's config adds its own files and classes:
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
# prod.bundle.yml: + the adapters, minus dev-only *.dev.ts files
|
|
142
|
+
paths:
|
|
143
|
+
include:
|
|
133
144
|
- ./src/infra
|
|
134
145
|
exclude:
|
|
135
146
|
- '**/*.dev.ts'
|
|
@@ -142,15 +153,39 @@ paths:
|
|
|
142
153
|
```
|
|
143
154
|
|
|
144
155
|
```yaml
|
|
145
|
-
# dev.bundle.yml: the *.dev.ts logger replaces the production one, dropped by class name
|
|
156
|
+
# dev.bundle.yml: + the adapters; the *.dev.ts logger replaces the production one, dropped by class name
|
|
146
157
|
paths:
|
|
147
158
|
include:
|
|
148
|
-
- '@app/services'
|
|
149
159
|
- ./src/infra
|
|
150
|
-
|
|
160
|
+
match:
|
|
151
161
|
exclude: JsonLogger
|
|
152
162
|
```
|
|
153
163
|
|
|
164
|
+
`tic build common.bundle.yml prod.bundle.yml` then scans `@app/services` and
|
|
165
|
+
`./src/infra`, and exports `ProdBundle`.
|
|
166
|
+
|
|
167
|
+
### Merging configs
|
|
168
|
+
|
|
169
|
+
`tic build a.bundle.yml b.bundle.yml c.bundle.yml` merges the configs left to
|
|
170
|
+
right, the way webpack-merge merges webpack configs:
|
|
171
|
+
|
|
172
|
+
- objects merge field by field;
|
|
173
|
+
- list fields — `paths.include`, `paths.exclude`, `match.glob`, `match.exclude`,
|
|
174
|
+
`match.decorators` — concatenate in order, without duplicates (one folder or
|
|
175
|
+
glob counts as a list of one), so a later config can only add to them;
|
|
176
|
+
- any other value (`name`, `tsconfig`, `importExtension`, `match.export`) set
|
|
177
|
+
by a later config replaces an earlier one;
|
|
178
|
+
- the `match` shorthand merges as `match.glob`.
|
|
179
|
+
|
|
180
|
+
Each config is validated on its own — an error names the file it is in — so a
|
|
181
|
+
shared config may leave `paths` out; the merged config must have
|
|
182
|
+
`paths.include`. Defaults apply to the merged config only: a `paths.exclude` in
|
|
183
|
+
any of them replaces the default excludes, as it does in a single config, so
|
|
184
|
+
list the defaults in the shared config to keep them. The bundle is named after
|
|
185
|
+
the last config, unless one sets `name` — so leave `name` out of a shared
|
|
186
|
+
config. Merged configs must sit in one folder, which their relative paths
|
|
187
|
+
resolve against. A piped config (`-`) is never merged.
|
|
188
|
+
|
|
154
189
|
A saved bundle is never registered by another build, even when it sits in a
|
|
155
190
|
folder that build scans.
|
|
156
191
|
|
|
@@ -160,7 +195,7 @@ A bundle picks its registrations in two stages:
|
|
|
160
195
|
|
|
161
196
|
1. **`paths`** — decided by path alone, before anything is read. Only files that
|
|
162
197
|
pass are parsed.
|
|
163
|
-
2. **`
|
|
198
|
+
2. **`match`** — decided per class, on the files stage 1 let through.
|
|
164
199
|
|
|
165
200
|
Parsing is where the time goes, so point `paths` at the folders that hold your
|
|
166
201
|
registrations, and `exclude` what they should not contribute:
|
|
@@ -171,7 +206,7 @@ registrations, and `exclude` what they should not contribute:
|
|
|
171
206
|
"include": "@app/services",
|
|
172
207
|
"exclude": ["**/*.spec.ts", "**/*.test.ts", "**/__tests__/**", "**/node_modules/**", "**/legacy/**"]
|
|
173
208
|
},
|
|
174
|
-
"
|
|
209
|
+
"match": { "decorators": ["register"] }
|
|
175
210
|
}
|
|
176
211
|
```
|
|
177
212
|
|
|
@@ -233,11 +268,11 @@ parses everything, including tests.
|
|
|
233
268
|
## Selecting classes
|
|
234
269
|
|
|
235
270
|
By default every exported, non-abstract class of a parsed file that carries
|
|
236
|
-
`@register` is registered. `
|
|
271
|
+
`@register` is registered. `match` changes that; a class must meet every
|
|
237
272
|
criterion that is set:
|
|
238
273
|
|
|
239
274
|
```json
|
|
240
|
-
"
|
|
275
|
+
"match": {
|
|
241
276
|
"export": "named",
|
|
242
277
|
"decorators": ["register", "repository"],
|
|
243
278
|
"glob": "*Service"
|
|
@@ -261,7 +296,7 @@ bind the same token, registration is last-wins and the stand-in silently wins.
|
|
|
261
296
|
matches only itself, so one list drops a class by name and a family by pattern:
|
|
262
297
|
|
|
263
298
|
```json
|
|
264
|
-
"
|
|
299
|
+
"match": {
|
|
265
300
|
"decorators": ["repository", "service"],
|
|
266
301
|
"exclude": ["MockDashboardRepository", "*Fake"]
|
|
267
302
|
}
|
|
@@ -270,18 +305,18 @@ matches only itself, so one list drops a class by name and a family by pattern:
|
|
|
270
305
|
`exclude` applies after every other criterion, so it combines with
|
|
271
306
|
`decorators` and `glob` freely.
|
|
272
307
|
|
|
273
|
-
### The `
|
|
308
|
+
### The `match` shortcut
|
|
274
309
|
|
|
275
|
-
When the default `export` and `decorators` are all you need, `
|
|
310
|
+
When the default `export` and `decorators` are all you need, `match`
|
|
276
311
|
itself can be the class-name globs — a string or a list is a shortcut for
|
|
277
|
-
`
|
|
312
|
+
`match.glob`:
|
|
278
313
|
|
|
279
314
|
```yaml
|
|
280
|
-
|
|
315
|
+
match: '*Service' # = match: { glob: '*Service' }
|
|
281
316
|
```
|
|
282
317
|
|
|
283
318
|
```yaml
|
|
284
|
-
|
|
319
|
+
match: ['*Service', '*Repository'] # = match: { glob: ['*Service', '*Repository'] }
|
|
285
320
|
```
|
|
286
321
|
|
|
287
322
|
As a safety net, the build warns when two selected classes pass the same
|
|
@@ -292,7 +327,7 @@ are not resolved), so it can only be a heuristic:
|
|
|
292
327
|
```text
|
|
293
328
|
tic: warning: app.bundle.json: decorator token "IDashboardRepositoryToken" is passed by
|
|
294
329
|
HttpDashboardRepository, MockDashboardRepository; registration is last-wins,
|
|
295
|
-
exclude one with
|
|
330
|
+
exclude one with match.exclude
|
|
296
331
|
```
|
|
297
332
|
|
|
298
333
|
Classes that are scope-gated are not last-wins, so they do not warn: when the
|
package/cjm/app.js
CHANGED
|
@@ -34,6 +34,6 @@ function run(argv, io = (0, CliIo_1.processIo)()) {
|
|
|
34
34
|
function build({ cwd = process.cwd(), ...request }) {
|
|
35
35
|
return withContainer({ ...(0, CliIo_1.processIo)(), cwd }, (container) => BundleBuilder_1.IBundleBuilderKey.resolve(container).build(request));
|
|
36
36
|
}
|
|
37
|
-
function loadConfig(
|
|
38
|
-
return withContainer((0, CliIo_1.processIo)(), (container) => TicConfigService_1.ITicConfigServiceKey.resolve(container).load(
|
|
37
|
+
function loadConfig(files) {
|
|
38
|
+
return withContainer((0, CliIo_1.processIo)(), (container) => TicConfigService_1.ITicConfigServiceKey.resolve(container).load(files));
|
|
39
39
|
}
|
package/cjm/cli/usage.js
CHANGED
|
@@ -6,10 +6,11 @@ exports.USAGE = [
|
|
|
6
6
|
' tic is a shortcut for ts-ioc-container',
|
|
7
7
|
'',
|
|
8
8
|
'Commands:',
|
|
9
|
-
' ts-ioc-container build [<config
|
|
10
|
-
'
|
|
11
|
-
'
|
|
12
|
-
' ts-ioc-container
|
|
9
|
+
' ts-ioc-container build [<config>...] print the bundle a config file (.json, .yaml, .yml) describes;',
|
|
10
|
+
' several are merged left to right into one bundle;',
|
|
11
|
+
' without one (or with -), read the config from stdin',
|
|
12
|
+
' ts-ioc-container help show this help',
|
|
13
|
+
' ts-ioc-container version show the version',
|
|
13
14
|
'',
|
|
14
15
|
'Options:',
|
|
15
16
|
' -h, --help show this help',
|
|
@@ -17,6 +18,7 @@ exports.USAGE = [
|
|
|
17
18
|
'',
|
|
18
19
|
'The bundle goes to stdout and warnings to stderr; saving it is up to you:',
|
|
19
20
|
' tic build app.bundle.json > src/di/app.bundle.ts',
|
|
21
|
+
' tic build common.bundle.yml prod.bundle.yml > src/di/prod.bundle.ts # merged left to right',
|
|
20
22
|
' cat app.bundle.yml | tic build > src/di/app.bundle.ts # config from stdin (must set name)',
|
|
21
23
|
' tic build app.bundle.json | diff - src/di/app.bundle.ts # CI: is it current?',
|
|
22
24
|
].join('\n');
|
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.configFormat = exports.STDIN = exports.CONFIG_FILE_SUFFIXES = exports.BUNDLE_CONFIG_SCHEMA = exports.DEFAULT_EXCLUDE = exports.DEFAULT_DECORATORS = exports.DEFAULT_TSCONFIG = void 0;
|
|
6
|
+
exports.configFormat = exports.STDIN = exports.CONFIG_FILE_SUFFIXES = exports.BUNDLE_CONFIG_FILE_SCHEMA = exports.BUNDLE_CONFIG_SCHEMA = exports.DEFAULT_EXCLUDE = exports.DEFAULT_DECORATORS = exports.DEFAULT_TSCONFIG = void 0;
|
|
7
7
|
exports.parseConfig = parseConfig;
|
|
8
8
|
exports.toClassName = toClassName;
|
|
9
|
+
exports.mergeConfigs = mergeConfigs;
|
|
9
10
|
exports.resolveConfig = resolveConfig;
|
|
10
11
|
const node_path_1 = __importDefault(require("node:path"));
|
|
11
12
|
const yaml_1 = require("yaml");
|
|
@@ -42,6 +43,7 @@ const globs = () => globList('a glob or a non-empty array of globs', 1);
|
|
|
42
43
|
const toList = (value) => (Array.isArray(value) ? value : [value]);
|
|
43
44
|
const toGlobs = (value) => value === undefined ? undefined : toList(value).map(glob_1.globToRegExp);
|
|
44
45
|
const FOLDERS_SCHEMA = zod_1.z.array(nonEmptyString(), expected('a non-empty array')).min(1, expected('a non-empty array'));
|
|
46
|
+
const PATHS_DESCRIPTION = 'Which files this bundle reads and parses — decided by path alone, before parsing. `include` names the folders the files come from; within them a file is parsed unless it matches one of `exclude`. Globs are relative to the config file.';
|
|
45
47
|
const PATHS_SCHEMA = zod_1.z
|
|
46
48
|
.strictObject({
|
|
47
49
|
include: zod_1.z
|
|
@@ -51,7 +53,7 @@ const PATHS_SCHEMA = zod_1.z
|
|
|
51
53
|
.default(exports.DEFAULT_EXCLUDE)
|
|
52
54
|
.describe('Glob, or globs, of files never read, relative to the config file or starting with a tsconfig paths alias (@generated/**, or @generated for the whole folder). Replaces the default when given. A non-empty value that omits a default glob makes `tic build` warn.'),
|
|
53
55
|
}, expected('an object with "include"'))
|
|
54
|
-
.describe(
|
|
56
|
+
.describe(PATHS_DESCRIPTION);
|
|
55
57
|
const CLASS_OBJECT_SCHEMA = zod_1.z.strictObject({
|
|
56
58
|
export: zod_1.z
|
|
57
59
|
.enum(['any', 'named', 'default'], expected('"any", "named" or "default"'))
|
|
@@ -93,8 +95,11 @@ exports.BUNDLE_CONFIG_SCHEMA = zod_1.z.strictObject({
|
|
|
93
95
|
.optional()
|
|
94
96
|
.describe('Extension of generated imports, e.g. ".js". Inferred from the tsconfig: ".js" under node16/nodenext resolution, none otherwise.'),
|
|
95
97
|
paths: PATHS_SCHEMA,
|
|
96
|
-
|
|
98
|
+
match: CLASSES_SCHEMA.optional(),
|
|
97
99
|
}, expected('an object'));
|
|
100
|
+
exports.BUNDLE_CONFIG_FILE_SCHEMA = exports.BUNDLE_CONFIG_SCHEMA.extend({
|
|
101
|
+
paths: PATHS_SCHEMA.partial().optional().describe(`${PATHS_DESCRIPTION} Required in the merged config.`),
|
|
102
|
+
});
|
|
98
103
|
function formatPath(segments) {
|
|
99
104
|
const formatted = segments
|
|
100
105
|
.map((segment) => (typeof segment === 'number' ? `[${segment}]` : `.${String(segment)}`))
|
|
@@ -122,13 +127,13 @@ function toPathSelector(paths) {
|
|
|
122
127
|
exclude: toList(paths.exclude),
|
|
123
128
|
};
|
|
124
129
|
}
|
|
125
|
-
function toClassSelector(
|
|
126
|
-
if (
|
|
130
|
+
function toClassSelector(match) {
|
|
131
|
+
if (match === undefined)
|
|
127
132
|
return { export: 'any', decorators: exports.DEFAULT_DECORATORS };
|
|
128
|
-
if (typeof
|
|
129
|
-
return { export: 'any', decorators: exports.DEFAULT_DECORATORS, glob: toGlobs(
|
|
133
|
+
if (typeof match === 'string' || Array.isArray(match)) {
|
|
134
|
+
return { export: 'any', decorators: exports.DEFAULT_DECORATORS, glob: toGlobs(match) };
|
|
130
135
|
}
|
|
131
|
-
const { decorators, glob, exclude, ...rest } =
|
|
136
|
+
const { decorators, glob, exclude, ...rest } = match;
|
|
132
137
|
return {
|
|
133
138
|
...rest,
|
|
134
139
|
decorators: decorators.length > 0 ? decorators : undefined,
|
|
@@ -170,11 +175,38 @@ function toClassName(name) {
|
|
|
170
175
|
const words = name.split(/[-_]+/).filter(Boolean);
|
|
171
176
|
return `${words.map((word) => word[0].toUpperCase() + word.slice(1)).join('')}Bundle`;
|
|
172
177
|
}
|
|
178
|
+
const LIST_FIELDS = new Set(['paths.include', 'paths.exclude', 'match.decorators', 'match.glob', 'match.exclude']);
|
|
179
|
+
const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
180
|
+
function mergeInto(base, next, at = '') {
|
|
181
|
+
const merged = { ...base };
|
|
182
|
+
for (const [key, value] of Object.entries(next)) {
|
|
183
|
+
const field = `${at}${key}`;
|
|
184
|
+
const previous = merged[key];
|
|
185
|
+
if (LIST_FIELDS.has(field)) {
|
|
186
|
+
merged[key] = [
|
|
187
|
+
...new Set([...toList((previous ?? [])), ...toList(value)]),
|
|
188
|
+
];
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
merged[key] = isObject(previous) && isObject(value) ? mergeInto(previous, value, `${field}.`) : value;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return merged;
|
|
195
|
+
}
|
|
196
|
+
const expandMatch = ({ match, ...rest }) => match === undefined ? rest : { ...rest, match: isObject(match) ? match : { glob: match } };
|
|
197
|
+
function mergeConfigs(configs) {
|
|
198
|
+
return configs.reduce((merged, { file, content }) => {
|
|
199
|
+
const result = exports.BUNDLE_CONFIG_FILE_SCHEMA.safeParse(content);
|
|
200
|
+
if (!result.success)
|
|
201
|
+
throw new DomainException_1.TicConfigError(`${node_path_1.default.basename(file)}: ${formatIssues(result.error)}`);
|
|
202
|
+
return mergeInto(merged, expandMatch(content));
|
|
203
|
+
}, {});
|
|
204
|
+
}
|
|
173
205
|
function resolveConfig(content, file) {
|
|
174
206
|
const result = exports.BUNDLE_CONFIG_SCHEMA.safeParse(content);
|
|
175
207
|
if (!result.success)
|
|
176
208
|
throw new DomainException_1.TicConfigError(formatIssues(result.error));
|
|
177
|
-
const { name, tsconfig, importExtension, paths,
|
|
209
|
+
const { name, tsconfig, importExtension, paths, match } = result.data;
|
|
178
210
|
const bundleName = name ?? configStem(file);
|
|
179
211
|
if (bundleName === undefined) {
|
|
180
212
|
throw new DomainException_1.TicConfigError(node_path_1.default.basename(file) === exports.STDIN
|
|
@@ -190,7 +222,7 @@ function resolveConfig(content, file) {
|
|
|
190
222
|
tsconfig: { file: node_path_1.default.resolve(dir, tsconfig ?? exports.DEFAULT_TSCONFIG), required: tsconfig !== undefined },
|
|
191
223
|
importExtension,
|
|
192
224
|
paths: toPathSelector(paths),
|
|
193
|
-
|
|
225
|
+
match: toClassSelector(match),
|
|
194
226
|
warnings: excludeWarnings(paths),
|
|
195
227
|
};
|
|
196
228
|
}
|
|
@@ -23,11 +23,15 @@ const OutputService_1 = require("../../services/OutputService");
|
|
|
23
23
|
const BuildConfig_1 = require("./BuildConfig");
|
|
24
24
|
const BundleBuilder_1 = require("./services/BundleBuilder");
|
|
25
25
|
exports.BUILD_OPTIONS = zod_1.z.object({ positionals: zod_1.z.array(zod_1.z.string().min(1)) }).transform(({ positionals }, ctx) => {
|
|
26
|
-
if (positionals.length > 1) {
|
|
27
|
-
ctx.addIssue({
|
|
26
|
+
if (positionals.length > 1 && positionals.includes(BuildConfig_1.STDIN)) {
|
|
27
|
+
ctx.addIssue({
|
|
28
|
+
code: 'custom',
|
|
29
|
+
path: ['config'],
|
|
30
|
+
message: `${BuildConfig_1.STDIN} reads one config from stdin and cannot be merged with config files`,
|
|
31
|
+
});
|
|
28
32
|
return zod_1.z.NEVER;
|
|
29
33
|
}
|
|
30
|
-
return {
|
|
34
|
+
return { configs: positionals.length > 0 ? positionals : [BuildConfig_1.STDIN] };
|
|
31
35
|
});
|
|
32
36
|
const buildArgs = (0, cli_1.parseOptions)({}, { positionals: true });
|
|
33
37
|
let BuildController = class BuildController {
|
|
@@ -41,10 +45,11 @@ let BuildController = class BuildController {
|
|
|
41
45
|
this.output = output;
|
|
42
46
|
this.logger = logger;
|
|
43
47
|
}
|
|
44
|
-
build({
|
|
45
|
-
const
|
|
48
|
+
build({ configs }) {
|
|
49
|
+
const stdin = configs[0] === BuildConfig_1.STDIN;
|
|
50
|
+
const label = stdin ? '<stdin>' : configs.join(' + ');
|
|
46
51
|
try {
|
|
47
|
-
const { content, warnings } = this.builder.build(
|
|
52
|
+
const { content, warnings } = this.builder.build(stdin ? { text: this.stdin() } : { config: configs });
|
|
48
53
|
for (const warning of warnings)
|
|
49
54
|
this.logger.warn(`${label}: ${warning}`);
|
|
50
55
|
this.output.write(content.replace(/\n$/, ''));
|
|
@@ -17,7 +17,7 @@ function tokenCollisions(classes) {
|
|
|
17
17
|
.map(([token, group]) => {
|
|
18
18
|
const names = group.map((cls) => cls.className);
|
|
19
19
|
return (`decorator token "${token}" is passed by ${names.join(', ')}; ` +
|
|
20
|
-
`registration is last-wins, exclude one with
|
|
20
|
+
`registration is last-wins, exclude one with match.exclude`);
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
function scopeDisjoint(group) {
|
|
@@ -43,7 +43,7 @@ let BundleBuilder = class BundleBuilder {
|
|
|
43
43
|
build(request) {
|
|
44
44
|
const resolved = 'text' in request
|
|
45
45
|
? this.configs.parse(request.text, this.cwd)
|
|
46
|
-
: this.configs.load(node_path_1.default.resolve(this.cwd,
|
|
46
|
+
: this.configs.load([request.config].flat().map((file) => node_path_1.default.resolve(this.cwd, file)));
|
|
47
47
|
const { content, registrations, warnings } = this.generate(resolved);
|
|
48
48
|
return {
|
|
49
49
|
config: 'text' in request ? undefined : resolved.file,
|
|
@@ -71,7 +71,7 @@ let BundleBuilder = class BundleBuilder {
|
|
|
71
71
|
.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
|
|
72
72
|
.flatMap((file) => {
|
|
73
73
|
const text = this.fs.readFile(file);
|
|
74
|
-
return text.startsWith(emit_1.GENERATED_HEADER) ? [] : (0, scan_1.findClasses)(file, config.
|
|
74
|
+
return text.startsWith(emit_1.GENERATED_HEADER) ? [] : (0, scan_1.findClasses)(file, config.match, text);
|
|
75
75
|
})
|
|
76
76
|
.map((cls) => ({ ...cls, specifier: paths.specifier(cls.file) }));
|
|
77
77
|
const uncovered = [...new Set(classes.filter((cls) => cls.specifier === undefined).map((cls) => cls.file))];
|
|
@@ -27,16 +27,27 @@ let TicConfigService = class TicConfigService {
|
|
|
27
27
|
constructor(fs) {
|
|
28
28
|
this.fs = fs;
|
|
29
29
|
}
|
|
30
|
-
load(
|
|
30
|
+
load(files) {
|
|
31
|
+
if (typeof files === 'string' || files.length === 1) {
|
|
32
|
+
const [file] = [files].flat();
|
|
33
|
+
return (0, BuildConfig_1.resolveConfig)(this.read(file), file);
|
|
34
|
+
}
|
|
35
|
+
const folders = [...new Set(files.map((file) => node_path_1.default.dirname(file)))];
|
|
36
|
+
if (folders.length > 1) {
|
|
37
|
+
throw new DomainException_1.TicConfigError(`configs merged into one bundle must sit in one folder, since their relative paths resolve against it: ${folders.join(', ')}`);
|
|
38
|
+
}
|
|
39
|
+
return (0, BuildConfig_1.resolveConfig)((0, BuildConfig_1.mergeConfigs)(files.map((file) => ({ file, content: this.read(file) }))), files[files.length - 1]);
|
|
40
|
+
}
|
|
41
|
+
parse(text, dir) {
|
|
42
|
+
return (0, BuildConfig_1.resolveConfig)((0, BuildConfig_1.parseConfig)(text, 'yaml'), node_path_1.default.join(dir, BuildConfig_1.STDIN));
|
|
43
|
+
}
|
|
44
|
+
read(file) {
|
|
31
45
|
const format = (0, BuildConfig_1.configFormat)(file);
|
|
32
46
|
if (format === undefined)
|
|
33
47
|
throw new DomainException_1.TicConfigError(`expected a .json, .yaml or .yml config file: ${file}`);
|
|
34
48
|
if (!this.fs.fileExists(file))
|
|
35
49
|
throw new DomainException_1.TicConfigError(`config file not found: ${file}`);
|
|
36
|
-
return (0, BuildConfig_1.
|
|
37
|
-
}
|
|
38
|
-
parse(text, dir) {
|
|
39
|
-
return (0, BuildConfig_1.resolveConfig)((0, BuildConfig_1.parseConfig)(text, 'yaml'), node_path_1.default.join(dir, BuildConfig_1.STDIN));
|
|
50
|
+
return (0, BuildConfig_1.parseConfig)(this.fs.readFile(file), format);
|
|
40
51
|
}
|
|
41
52
|
};
|
|
42
53
|
exports.TicConfigService = TicConfigService;
|
package/cjm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.ExceptionHandler = exports.UsageError = exports.UnknownActionError = exports.UnknownCommandError = exports.MissingCommandError = exports.NamespaceNotFoundError = exports.TicConfigError = exports.TicError = exports.renderProtocol = exports.HandlebarsRenderService = exports.IRenderServiceKey = exports.NodeFileSystemService = exports.IFileSystemServiceKey = exports.ConsoleLogger = void 0;
|
|
3
|
+
exports.IOutputServiceKey = exports.CommonModule = exports.HelpModule = exports.globToRegExp = exports.tokenCollisions = exports.GENERATED_HEADER = exports.BUNDLE_PROTOCOL = exports.bundleView = exports.emitBundle = exports.listSourceFiles = exports.isSourceFile = exports.findClasses = exports.loadImportPaths = exports.ImportPaths = exports.ticConfigJsonSchema = exports.toClassName = exports.DEFAULT_DECORATORS = exports.DEFAULT_EXCLUDE = exports.DEFAULT_TSCONFIG = exports.configFormat = exports.STDIN = exports.CONFIG_FILE_SUFFIXES = exports.parseConfig = exports.mergeConfigs = exports.BUNDLE_CONFIG_FILE_SCHEMA = exports.BUNDLE_CONFIG_SCHEMA = exports.resolveConfig = exports.ITicConfigServiceKey = exports.TicConfigService = exports.IBundleBuilderKey = exports.BundleBuilder = exports.BUILD_OPTIONS = exports.BuildController = exports.BuildModule = exports.USAGE = exports.IErrorHandlerKey = exports.validate = exports.parseOptions = exports.commandArgs = exports.DEFAULT_ACTION = exports.onDefault = exports.action = exports.Application = exports.globalConfig = exports.GlobalConfigKey = exports.CliIoKey = exports.createContainer = exports.loadConfig = exports.run = exports.build = void 0;
|
|
4
|
+
exports.ExceptionHandler = exports.UsageError = exports.UnknownActionError = exports.UnknownCommandError = exports.MissingCommandError = exports.NamespaceNotFoundError = exports.TicConfigError = exports.TicError = exports.renderProtocol = exports.HandlebarsRenderService = exports.IRenderServiceKey = exports.NodeFileSystemService = exports.IFileSystemServiceKey = exports.ConsoleLogger = exports.ILoggerKey = exports.StdOutputService = void 0;
|
|
5
5
|
var app_1 = require("./app");
|
|
6
6
|
Object.defineProperty(exports, "build", { enumerable: true, get: function () { return app_1.build; } });
|
|
7
7
|
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return app_1.run; } });
|
|
@@ -36,6 +36,8 @@ Object.defineProperty(exports, "ITicConfigServiceKey", { enumerable: true, get:
|
|
|
36
36
|
var BuildConfig_1 = require("./features/build/BuildConfig");
|
|
37
37
|
Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return BuildConfig_1.resolveConfig; } });
|
|
38
38
|
Object.defineProperty(exports, "BUNDLE_CONFIG_SCHEMA", { enumerable: true, get: function () { return BuildConfig_1.BUNDLE_CONFIG_SCHEMA; } });
|
|
39
|
+
Object.defineProperty(exports, "BUNDLE_CONFIG_FILE_SCHEMA", { enumerable: true, get: function () { return BuildConfig_1.BUNDLE_CONFIG_FILE_SCHEMA; } });
|
|
40
|
+
Object.defineProperty(exports, "mergeConfigs", { enumerable: true, get: function () { return BuildConfig_1.mergeConfigs; } });
|
|
39
41
|
Object.defineProperty(exports, "parseConfig", { enumerable: true, get: function () { return BuildConfig_1.parseConfig; } });
|
|
40
42
|
Object.defineProperty(exports, "CONFIG_FILE_SUFFIXES", { enumerable: true, get: function () { return BuildConfig_1.CONFIG_FILE_SUFFIXES; } });
|
|
41
43
|
Object.defineProperty(exports, "STDIN", { enumerable: true, get: function () { return BuildConfig_1.STDIN; } });
|
|
@@ -4,7 +4,7 @@ exports.ticConfigJsonSchema = ticConfigJsonSchema;
|
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const BuildConfig_1 = require("../features/build/BuildConfig");
|
|
6
6
|
function ticConfigJsonSchema() {
|
|
7
|
-
const schema = zod_1.z.toJSONSchema(BuildConfig_1.
|
|
7
|
+
const schema = zod_1.z.toJSONSchema(BuildConfig_1.BUNDLE_CONFIG_FILE_SCHEMA, {
|
|
8
8
|
io: 'input',
|
|
9
9
|
target: 'draft-7',
|
|
10
10
|
unrepresentable: 'any',
|
|
@@ -18,7 +18,7 @@ function ticConfigJsonSchema() {
|
|
|
18
18
|
$schema,
|
|
19
19
|
$id: 'https://github.com/IgorBabkin/ts-ioc-container/tree/main/packages/bundler/tic.schema.json',
|
|
20
20
|
title: '*.bundle.json / *.bundle.yaml',
|
|
21
|
-
description: "One bundle generated by `tic build` (@ts-ioc-container/bundler). `tic build app.bundle.json` prints the bundle to stdout, and `cat app.bundle.json | tic build` reads the config from stdin. Relative paths resolve against this file's directory (for piped text, the working directory).",
|
|
21
|
+
description: "One bundle generated by `tic build` (@ts-ioc-container/bundler). `tic build app.bundle.json` prints the bundle to stdout, `tic build common.bundle.json prod.bundle.json` merges several configs left to right, and `cat app.bundle.json | tic build` reads the config from stdin. Relative paths resolve against this file's directory (for piped text, the working directory).",
|
|
22
22
|
...rest,
|
|
23
23
|
};
|
|
24
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-ioc-container/bundler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Bundles your dependencies into a single container module for ts-ioc-container: the `tic` CLI scans folders (by path or tsconfig alias) and generates one typed bundle that registers every class — `container.useModule(new AppBundle())`.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"reflect-metadata": "^0.2.2",
|
|
53
53
|
"yaml": "^2.8.3",
|
|
54
54
|
"zod": "^4.6.5",
|
|
55
|
-
"ts-ioc-container": "76.0.
|
|
55
|
+
"ts-ioc-container": "76.0.2"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"typescript": ">=5"
|
package/tic.schema.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"$id": "https://github.com/IgorBabkin/ts-ioc-container/tree/main/packages/bundler/tic.schema.json",
|
|
4
4
|
"title": "*.bundle.json / *.bundle.yaml",
|
|
5
|
-
"description": "One bundle generated by `tic build` (@ts-ioc-container/bundler). `tic build app.bundle.json` prints the bundle to stdout, and `cat app.bundle.json | tic build` reads the config from stdin. Relative paths resolve against this file's directory (for piped text, the working directory).",
|
|
5
|
+
"description": "One bundle generated by `tic build` (@ts-ioc-container/bundler). `tic build app.bundle.json` prints the bundle to stdout, `tic build common.bundle.json prod.bundle.json` merges several configs left to right, and `cat app.bundle.json | tic build` reads the config from stdin. Relative paths resolve against this file's directory (for piped text, the working directory).",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"properties": {
|
|
8
8
|
"$schema": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"type": "string"
|
|
25
25
|
},
|
|
26
26
|
"paths": {
|
|
27
|
+
"description": "Which files this bundle reads and parses — decided by path alone, before parsing. `include` names the folders the files come from; within them a file is parsed unless it matches one of `exclude`. Globs are relative to the config file. Required in the merged config.",
|
|
27
28
|
"type": "object",
|
|
28
29
|
"properties": {
|
|
29
30
|
"include": {
|
|
@@ -68,13 +69,9 @@
|
|
|
68
69
|
]
|
|
69
70
|
}
|
|
70
71
|
},
|
|
71
|
-
"
|
|
72
|
-
"include"
|
|
73
|
-
],
|
|
74
|
-
"additionalProperties": false,
|
|
75
|
-
"description": "Which files this bundle reads and parses — decided by path alone, before parsing. `include` names the folders the files come from; within them a file is parsed unless it matches one of `exclude`. Globs are relative to the config file."
|
|
72
|
+
"additionalProperties": false
|
|
76
73
|
},
|
|
77
|
-
"
|
|
74
|
+
"match": {
|
|
78
75
|
"anyOf": [
|
|
79
76
|
{
|
|
80
77
|
"type": "string",
|
|
@@ -155,8 +152,5 @@
|
|
|
155
152
|
"description": "Which classes of a parsed file are registered. A class is selected when it is exported, not abstract, and meets every criterion set here; by default that is every exported class decorated with @register. A glob, or a list of globs, is shorthand for { \"glob\": ... }."
|
|
156
153
|
}
|
|
157
154
|
},
|
|
158
|
-
"required": [
|
|
159
|
-
"paths"
|
|
160
|
-
],
|
|
161
155
|
"additionalProperties": false
|
|
162
156
|
}
|
package/typings/app.d.ts
CHANGED
|
@@ -11,14 +11,15 @@ export declare function run(argv: string[], io?: CliIo): number;
|
|
|
11
11
|
* Generates the bundle a config file describes — `tic build` as a function — and returns
|
|
12
12
|
* it; nothing is written.
|
|
13
13
|
*
|
|
14
|
-
* @throws {TicConfigError} when
|
|
14
|
+
* @throws {TicConfigError} when a config file is missing or unreadable, several are in different folders, the config or its tsconfig is invalid, the bundle has no name, or no tsconfig paths alias covers a selected class's file.
|
|
15
15
|
* @throws {NamespaceNotFoundError} when a path is neither a folder nor a tsconfig paths alias of one.
|
|
16
16
|
*/
|
|
17
17
|
export declare function build({ cwd, ...request }: BuildOptions): BuildResult;
|
|
18
18
|
/**
|
|
19
|
-
* Reads and validates a config file: JSON for `.json`, YAML for `.yaml` / `.yml`.
|
|
19
|
+
* Reads and validates a config file: JSON for `.json`, YAML for `.yaml` / `.yml`. Given several
|
|
20
|
+
* in one folder, it merges them left to right, as `tic build a.bundle.yml b.bundle.yml` does.
|
|
20
21
|
*
|
|
21
|
-
* @throws {TicConfigError} when
|
|
22
|
+
* @throws {TicConfigError} when a file is missing, has another extension, cannot be parsed, or does not match the config shape; when several files are in different folders.
|
|
22
23
|
*/
|
|
23
|
-
export declare function loadConfig(
|
|
24
|
+
export declare function loadConfig(files: string | string[]): ResolvedConfig;
|
|
24
25
|
//# sourceMappingURL=app.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../lib/cli/usage.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../lib/cli/usage.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,QAoBN,CAAC"}
|
|
@@ -63,6 +63,8 @@ export interface ResolvedClassSelector {
|
|
|
63
63
|
* A bundle config file: one bundle, described explicitly — the folders it scans and the
|
|
64
64
|
* classes it registers. `tic build <config>` prints the bundle to stdout; where it is
|
|
65
65
|
* saved is the caller's choice (`tic build app.bundle.json > src/di/app.bundle.ts`).
|
|
66
|
+
* `tic build common.bundle.yml prod.bundle.yml` merges several into one, left to right
|
|
67
|
+
* (see {@link mergeConfigs}).
|
|
66
68
|
*/
|
|
67
69
|
export interface BundleConfig {
|
|
68
70
|
$schema?: string;
|
|
@@ -85,16 +87,17 @@ export interface BundleConfig {
|
|
|
85
87
|
/**
|
|
86
88
|
* Which files are parsed: the folders in `paths.include`, minus {@link DEFAULT_EXCLUDE} unless
|
|
87
89
|
* `exclude` says otherwise. Always an object: there is no folder or folder-list shorthand.
|
|
90
|
+
* Required — though in a config merged with others, only the merged config must have it.
|
|
88
91
|
*/
|
|
89
92
|
paths: PathSelector;
|
|
90
93
|
/**
|
|
91
94
|
* Which classes of a parsed file are registered. Default: every exported class decorated
|
|
92
95
|
* with `@register`. A glob or a list of globs is shorthand for `{ glob }`.
|
|
93
96
|
*/
|
|
94
|
-
|
|
97
|
+
match?: string | string[] | ClassSelector;
|
|
95
98
|
}
|
|
96
99
|
export declare const DEFAULT_TSCONFIG = "./tsconfig.json";
|
|
97
|
-
/** What `
|
|
100
|
+
/** What `match.decorators` requires when omitted: the library's own `@register`. */
|
|
98
101
|
export declare const DEFAULT_DECORATORS: string[];
|
|
99
102
|
export declare const DEFAULT_EXCLUDE: string[];
|
|
100
103
|
/** A {@link BundleConfig} whose defaults are filled in and whose paths are absolute. */
|
|
@@ -114,7 +117,7 @@ export interface ResolvedConfig {
|
|
|
114
117
|
};
|
|
115
118
|
importExtension?: string;
|
|
116
119
|
paths: ResolvedPathSelector;
|
|
117
|
-
|
|
120
|
+
match: ResolvedClassSelector;
|
|
118
121
|
/** Non-fatal problems found while resolving, e.g. a `paths.exclude` that drops a default test glob. */
|
|
119
122
|
warnings: string[];
|
|
120
123
|
}
|
|
@@ -132,7 +135,7 @@ export declare const BUNDLE_CONFIG_SCHEMA: z.ZodObject<{
|
|
|
132
135
|
include: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
133
136
|
exclude: z.ZodDefault<z.ZodCustom<string | string[], string | string[]>>;
|
|
134
137
|
}, z.core.$strict>;
|
|
135
|
-
|
|
138
|
+
match: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
136
139
|
export: z.ZodDefault<z.ZodEnum<{
|
|
137
140
|
default: "default";
|
|
138
141
|
any: "any";
|
|
@@ -143,6 +146,31 @@ export declare const BUNDLE_CONFIG_SCHEMA: z.ZodObject<{
|
|
|
143
146
|
exclude: z.ZodOptional<z.ZodCustom<string | string[], string | string[]>>;
|
|
144
147
|
}, z.core.$strict>]>>;
|
|
145
148
|
}, z.core.$strict>;
|
|
149
|
+
/**
|
|
150
|
+
* One config file among several merged into one bundle: it may leave `paths.include`, or
|
|
151
|
+
* `paths` altogether, to another — only the merged config must have it. The published
|
|
152
|
+
* `tic.schema.json` is generated from it, so editors accept a shared config.
|
|
153
|
+
*/
|
|
154
|
+
export declare const BUNDLE_CONFIG_FILE_SCHEMA: z.ZodObject<{
|
|
155
|
+
$schema: z.ZodOptional<z.ZodString>;
|
|
156
|
+
name: z.ZodOptional<z.ZodString>;
|
|
157
|
+
tsconfig: z.ZodOptional<z.ZodString>;
|
|
158
|
+
importExtension: z.ZodOptional<z.ZodString>;
|
|
159
|
+
match: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
160
|
+
export: z.ZodDefault<z.ZodEnum<{
|
|
161
|
+
default: "default";
|
|
162
|
+
any: "any";
|
|
163
|
+
named: "named";
|
|
164
|
+
}>>;
|
|
165
|
+
decorators: z.ZodDefault<z.ZodCustom<string[], string[]>>;
|
|
166
|
+
glob: z.ZodOptional<z.ZodCustom<string | string[], string | string[]>>;
|
|
167
|
+
exclude: z.ZodOptional<z.ZodCustom<string | string[], string | string[]>>;
|
|
168
|
+
}, z.core.$strict>]>>;
|
|
169
|
+
paths: z.ZodOptional<z.ZodObject<{
|
|
170
|
+
include: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
171
|
+
exclude: z.ZodOptional<z.ZodDefault<z.ZodCustom<string | string[], string | string[]>>>;
|
|
172
|
+
}, z.core.$strict>>;
|
|
173
|
+
}, z.core.$strict>;
|
|
146
174
|
/**
|
|
147
175
|
* A config file is named `<name>.bundle.json`, `<name>.bundle.yaml` or `<name>.bundle.yml`
|
|
148
176
|
* by convention, e.g. `app.bundle.json`; any `.json` / `.yaml` / `.yml` file works.
|
|
@@ -162,6 +190,21 @@ export type ConfigFormat = 'json' | 'yaml';
|
|
|
162
190
|
export declare function parseConfig(text: string, format: ConfigFormat): unknown;
|
|
163
191
|
/** The generated class for a bundle name: `production` -> `ProductionBundle`, `my-app_v2` -> `MyAppV2Bundle`. */
|
|
164
192
|
export declare function toClassName(name: string): string;
|
|
193
|
+
/**
|
|
194
|
+
* Merges the contents of several config files into one, left to right, as webpack-merge
|
|
195
|
+
* does: objects merge field by field, a list field — `paths.include`, `paths.exclude`,
|
|
196
|
+
* `match.glob`, `match.exclude`, `match.decorators` — concatenates without duplicates
|
|
197
|
+
* (one glob or folder counting as a list of one), and any other value set by a later file
|
|
198
|
+
* replaces an earlier one. The `match` shorthand merges as `match.glob`. Each file is
|
|
199
|
+
* validated alone first, so a shared file may leave out `paths`; defaults apply to the
|
|
200
|
+
* merged config only, so a `paths.exclude` in any file replaces {@link DEFAULT_EXCLUDE}.
|
|
201
|
+
*
|
|
202
|
+
* @throws {TicConfigError} when a file's content does not match the config file shape; the message names the file and the field.
|
|
203
|
+
*/
|
|
204
|
+
export declare function mergeConfigs(configs: {
|
|
205
|
+
file: string;
|
|
206
|
+
content: unknown;
|
|
207
|
+
}[]): unknown;
|
|
165
208
|
/**
|
|
166
209
|
* Validates parsed config content and resolves its paths against `file`'s directory.
|
|
167
210
|
* Without a `name` the bundle is named after the file: `production.bundle.json` -> `production`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuildConfig.d.ts","sourceRoot":"","sources":["../../../lib/features/build/BuildConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,0DAA0D;AAC1D,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iHAAiH;IACjH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,iGAAiG;AACjG,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED
|
|
1
|
+
{"version":3,"file":"BuildConfig.d.ts","sourceRoot":"","sources":["../../../lib/features/build/BuildConfig.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,0DAA0D;AAC1D,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iHAAiH;IACjH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,iGAAiG;AACjG,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,YAAY,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,aAAa,CAAC;CAC3C;AAED,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAClD,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,UAAe,CAAC;AAC/C,eAAO,MAAM,eAAe,UAO3B,CAAC;AAEF,wFAAwF;AACxF,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;IACxB,8FAA8F;IAC9F,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,KAAK,EAAE,qBAAqB,CAAC;IAC7B,uGAAuG;IACvG,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA6GD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;kBA2BhC,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;kBAEpC,CAAC;AAyEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB,UAAkD,CAAC;AAUpF,qFAAqF;AACrF,eAAO,MAAM,KAAK,MAAM,CAAC;AAEzB,iFAAiF;AACjF,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,YAAY,GAAG,SAC6C,CAAC;AAEzG,+CAA+C;AAC/C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAMvE;AAED,iHAAiH;AACjH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AA6BD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,EAAE,GAAG,OAAO,CAMnF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,CAwB5E"}
|
|
@@ -6,12 +6,15 @@ import { type IBundleBuilder } from './services/BundleBuilder.js';
|
|
|
6
6
|
export declare const BUILD_OPTIONS: z.ZodPipe<z.ZodObject<{
|
|
7
7
|
positionals: z.ZodArray<z.ZodString>;
|
|
8
8
|
}, z.core.$strip>, z.ZodTransform<{
|
|
9
|
-
|
|
9
|
+
configs: string[];
|
|
10
10
|
}, {
|
|
11
11
|
positionals: string[];
|
|
12
12
|
}>>;
|
|
13
13
|
export type BuildCliOptions = z.output<typeof BUILD_OPTIONS>;
|
|
14
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* `tic build [<config>... | -]`: the bundle goes to stdout; several configs are merged left to right
|
|
16
|
+
* into one, and without a config file the config comes from stdin.
|
|
17
|
+
*/
|
|
15
18
|
export declare class BuildController {
|
|
16
19
|
private readonly io;
|
|
17
20
|
private readonly builder;
|
|
@@ -19,16 +22,18 @@ export declare class BuildController {
|
|
|
19
22
|
private readonly logger;
|
|
20
23
|
constructor(io: CliIo, builder: IBundleBuilder, output: IOutputService, logger: ILogger);
|
|
21
24
|
/**
|
|
22
|
-
* Builds the bundle the config file `<config>` describes —
|
|
23
|
-
* the config piped into stdin — and prints it to
|
|
24
|
-
* `tic build app.bundle.json > src/di/app.bundle.ts`,
|
|
25
|
-
*
|
|
25
|
+
* Builds the bundle the config file `<config>` describes — several merged left to right
|
|
26
|
+
* into one, or without one (or with `-`), the config piped into stdin — and prints it to
|
|
27
|
+
* stdout. Saving it is the shell's job: `tic build app.bundle.json > src/di/app.bundle.ts`,
|
|
28
|
+
* `tic build common.bundle.yml prod.bundle.yml > src/di/prod.bundle.ts`,
|
|
29
|
+
* `cat app.bundle.yml | tic build > out.ts`.
|
|
30
|
+
* Warnings go to stderr, so they never end up in the bundle; an error names the configs.
|
|
26
31
|
*
|
|
27
|
-
* @throws {UsageError} when an option is unknown,
|
|
28
|
-
* @throws {TicConfigError} when
|
|
32
|
+
* @throws {UsageError} when an option is unknown, `-` is given with config files, or the config should come from stdin and nothing is piped in.
|
|
33
|
+
* @throws {TicConfigError} when a config file is missing or unreadable, several are in different folders, the config or its tsconfig is invalid, the bundle has no name, or no tsconfig paths alias covers a selected class's file.
|
|
29
34
|
* @throws {NamespaceNotFoundError} when a path is neither a folder nor a tsconfig paths alias of one.
|
|
30
35
|
*/
|
|
31
|
-
build({
|
|
36
|
+
build({ configs }: BuildCliOptions): void;
|
|
32
37
|
/**
|
|
33
38
|
* @throws {UsageError} when nothing is piped into stdin.
|
|
34
39
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BuildController.d.ts","sourceRoot":"","sources":["../../../lib/features/build/BuildController.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,KAAK,EAAY,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,0BAA0B,CAAC;AAElF,eAAO,MAAM,aAAa;;;;;;
|
|
1
|
+
{"version":3,"file":"BuildController.d.ts","sourceRoot":"","sources":["../../../lib/features/build/BuildController.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,KAAK,KAAK,EAAY,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,8BAA8B,CAAC;AAEtF,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,0BAA0B,CAAC;AAElF,eAAO,MAAM,aAAa;;;;;;GAWxB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAI7D;;;GAGG;AACH,qBACa,eAAe;IAEF,OAAO,CAAC,QAAQ,CAAC,EAAE;IACV,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAHR,EAAE,EAAE,KAAK,EACA,OAAO,EAAE,cAAc,EACvB,MAAM,EAAE,cAAc,EAC7B,MAAM,EAAE,OAAO;IAG1D;;;;;;;;;;;OAWG;IAEH,KAAK,CAAgE,EAAE,OAAO,EAAE,EAAE,eAAe,GAAG,IAAI;IAcxG;;OAEG;IACH,OAAO,CAAC,KAAK;CAOd"}
|
|
@@ -4,8 +4,11 @@ import { type IFileSystemService } from '../../../services/NodeFileSystemService
|
|
|
4
4
|
import { type ITicConfigService } from './TicConfigService.js';
|
|
5
5
|
/** What one build does. Paths resolve against the run's working directory. */
|
|
6
6
|
export type BuildRequest = {
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Path of the config file — `*.json`, `*.yaml` or `*.yml` — relative to the working directory;
|
|
9
|
+
* or of several in one folder, merged left to right into one bundle.
|
|
10
|
+
*/
|
|
11
|
+
config: string | string[];
|
|
9
12
|
} | {
|
|
10
13
|
/**
|
|
11
14
|
* The config as text, e.g. read from stdin: YAML or JSON. Its relative paths resolve
|
|
@@ -18,7 +21,7 @@ export type BuildOptions = BuildRequest & {
|
|
|
18
21
|
cwd?: string;
|
|
19
22
|
};
|
|
20
23
|
export interface BuildResult {
|
|
21
|
-
/** Absolute path of the config file that was built; `undefined` for config text. */
|
|
24
|
+
/** Absolute path of the config file that was built — of several merged, the last; `undefined` for config text. */
|
|
22
25
|
config?: string;
|
|
23
26
|
/** Name of the generated class. */
|
|
24
27
|
bundle: string;
|
|
@@ -35,7 +38,7 @@ export interface IBundleBuilder {
|
|
|
35
38
|
/**
|
|
36
39
|
* Generates the bundle a config describes and returns it; nothing is written.
|
|
37
40
|
*
|
|
38
|
-
* @throws {TicConfigError} when
|
|
41
|
+
* @throws {TicConfigError} when a config file is missing or unreadable, several are in different folders, the config or its tsconfig is invalid, the bundle has no name, or no tsconfig paths alias covers a selected class's file.
|
|
39
42
|
* @throws {NamespaceNotFoundError} when a path is neither a folder nor a tsconfig paths alias of one.
|
|
40
43
|
*/
|
|
41
44
|
build(request: BuildRequest): BuildResult;
|
|
@@ -48,7 +51,7 @@ export declare class BundleBuilder implements IBundleBuilder {
|
|
|
48
51
|
private readonly renderer;
|
|
49
52
|
constructor(cwd: string, configs: ITicConfigService, fs: IFileSystemService, renderer: IRenderService);
|
|
50
53
|
/**
|
|
51
|
-
* @throws {TicConfigError} when
|
|
54
|
+
* @throws {TicConfigError} when a config file is missing or unreadable, several are in different folders, the config or its tsconfig is invalid, the bundle has no name, or no tsconfig paths alias covers a selected class's file.
|
|
52
55
|
* @throws {NamespaceNotFoundError} when a path is neither a folder nor a tsconfig paths alias of one.
|
|
53
56
|
*/
|
|
54
57
|
build(request: BuildRequest): BuildResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BundleBuilder.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/services/BundleBuilder.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAErE,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,2CAA2C,CAAC;AACnG,OAAO,EAAE,KAAK,kBAAkB,EAAyB,MAAM,yCAAyC,CAAC;AAGzG,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,oBAAoB,CAAC;AAOlF,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GACpB;IACE
|
|
1
|
+
{"version":3,"file":"BundleBuilder.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/services/BundleBuilder.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAErE,OAAO,EAAE,KAAK,cAAc,EAAqB,MAAM,2CAA2C,CAAC;AACnG,OAAO,EAAE,KAAK,kBAAkB,EAAyB,MAAM,yCAAyC,CAAC;AAGzG,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,oBAAoB,CAAC;AAOlF,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GACpB;IACE;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3B,GACD;IACE;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG;IACxC,+BAA+B;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,kHAAkH;IAClH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,oIAAoI;IACpI,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CAAC;CAC3C;AAED,eAAO,MAAM,iBAAiB,6BAAoD,CAAC;AAEnF,qBACa,aAAc,YAAW,cAAc;IAEnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;IACvB,OAAO,CAAC,QAAQ,CAAC,EAAE;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAHV,GAAG,EAAE,MAAM,EACN,OAAO,EAAE,iBAAiB,EACzB,EAAE,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,cAAc;IAG1E;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IAezC;;;OAGG;IACH,OAAO,CAAC,QAAQ;CA0CjB"}
|
|
@@ -3,11 +3,13 @@ import { type IFileSystemService } from '../../../services/NodeFileSystemService
|
|
|
3
3
|
import { type ResolvedConfig } from '../BuildConfig.js';
|
|
4
4
|
export interface ITicConfigService {
|
|
5
5
|
/**
|
|
6
|
-
* Reads and validates a config file: JSON for `.json`, YAML for `.yaml` / `.yml`.
|
|
6
|
+
* Reads and validates a config file: JSON for `.json`, YAML for `.yaml` / `.yml`. Given several,
|
|
7
|
+
* it merges them left to right (see `mergeConfigs`); they must sit in one folder, which their
|
|
8
|
+
* relative paths resolve against, and the last one names the bundle unless one sets `name`.
|
|
7
9
|
*
|
|
8
|
-
* @throws {TicConfigError} when
|
|
10
|
+
* @throws {TicConfigError} when a file is missing, has another extension, cannot be parsed, or does not match the config shape; when several files are in different folders.
|
|
9
11
|
*/
|
|
10
|
-
load(
|
|
12
|
+
load(files: string | string[]): ResolvedConfig;
|
|
11
13
|
/**
|
|
12
14
|
* Validates config text from somewhere other than a file — stdin, say. It is parsed as YAML,
|
|
13
15
|
* which JSON is a subset of; its relative paths resolve against `dir`, and it has no file
|
|
@@ -22,12 +24,16 @@ export declare class TicConfigService implements ITicConfigService {
|
|
|
22
24
|
private readonly fs;
|
|
23
25
|
constructor(fs: IFileSystemService);
|
|
24
26
|
/**
|
|
25
|
-
* @throws {TicConfigError} when
|
|
27
|
+
* @throws {TicConfigError} when a file is missing, has another extension, cannot be parsed, or does not match the config shape; when several files are in different folders.
|
|
26
28
|
*/
|
|
27
|
-
load(
|
|
29
|
+
load(files: string | string[]): ResolvedConfig;
|
|
28
30
|
/**
|
|
29
31
|
* @throws {TicConfigError} when the text cannot be parsed, does not match the config shape, or has no `name`.
|
|
30
32
|
*/
|
|
31
33
|
parse(text: string, dir: string): ResolvedConfig;
|
|
34
|
+
/**
|
|
35
|
+
* @throws {TicConfigError} when the file is missing, has another extension, or cannot be parsed.
|
|
36
|
+
*/
|
|
37
|
+
private read;
|
|
32
38
|
}
|
|
33
39
|
//# sourceMappingURL=TicConfigService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TicConfigService.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/services/TicConfigService.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAErE,OAAO,EAAE,KAAK,kBAAkB,EAAyB,MAAM,yCAAyC,CAAC;AACzG,OAAO,
|
|
1
|
+
{"version":3,"file":"TicConfigService.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/services/TicConfigService.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAErE,OAAO,EAAE,KAAK,kBAAkB,EAAyB,MAAM,yCAAyC,CAAC;AACzG,OAAO,EAA2C,KAAK,cAAc,EAAwB,MAAM,gBAAgB,CAAC;AAEpH,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC;IAE/C;;;;;;OAMG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc,CAAC;CAClD;AAED,eAAO,MAAM,oBAAoB,gCAA0D,CAAC;AAE5F,qBACa,gBAAiB,YAAW,iBAAiB;IACT,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,kBAAkB;IAEtF;;OAEG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,cAAc;IAiB9C;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,cAAc;IAIhD;;OAEG;IACH,OAAO,CAAC,IAAI;CAMb"}
|
package/typings/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { BuildModule } from './features/build/BuildModule.js';
|
|
|
6
6
|
export { BuildController, BUILD_OPTIONS, type BuildCliOptions } from './features/build/BuildController.js';
|
|
7
7
|
export { BundleBuilder, IBundleBuilderKey, type IBundleBuilder, type BuildRequest, type BuildOptions, type BuildResult, } from './features/build/services/BundleBuilder.js';
|
|
8
8
|
export { TicConfigService, ITicConfigServiceKey, type ITicConfigService, } from './features/build/services/TicConfigService.js';
|
|
9
|
-
export { resolveConfig, BUNDLE_CONFIG_SCHEMA, parseConfig, CONFIG_FILE_SUFFIXES, STDIN, configFormat, DEFAULT_TSCONFIG, DEFAULT_EXCLUDE, DEFAULT_DECORATORS, toClassName, type BundleConfig, type ClassSelector, type ExportKind, type ResolvedClassSelector, type PathSelector, type ResolvedPathSelector, type ResolvedConfig, type ConfigFormat, } from './features/build/BuildConfig.js';
|
|
9
|
+
export { resolveConfig, BUNDLE_CONFIG_SCHEMA, BUNDLE_CONFIG_FILE_SCHEMA, mergeConfigs, parseConfig, CONFIG_FILE_SUFFIXES, STDIN, configFormat, DEFAULT_TSCONFIG, DEFAULT_EXCLUDE, DEFAULT_DECORATORS, toClassName, type BundleConfig, type ClassSelector, type ExportKind, type ResolvedClassSelector, type PathSelector, type ResolvedPathSelector, type ResolvedConfig, type ConfigFormat, } from './features/build/BuildConfig.js';
|
|
10
10
|
export { ticConfigJsonSchema } from './schema/ticConfigSchema.js';
|
|
11
11
|
export { ImportPaths } from './features/build/domain/ImportPaths.js';
|
|
12
12
|
export { loadImportPaths } from './features/build/domain/tsconfig.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ticConfigSchema.d.ts","sourceRoot":"","sources":["../../lib/schema/ticConfigSchema.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"ticConfigSchema.d.ts","sourceRoot":"","sources":["../../lib/schema/ticConfigSchema.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqB7D"}
|