@ts-ioc-container/bundler 4.0.0 → 5.1.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 +17 -12
- package/README.md +61 -33
- package/cjm/features/build/BuildConfig.js +51 -39
- package/cjm/features/build/domain/ImportPaths.js +11 -1
- package/cjm/features/build/domain/scan.js +2 -2
- package/cjm/features/build/services/BundleBuilder.js +5 -7
- package/package.json +1 -1
- package/tic.schema.json +119 -97
- package/typings/features/build/BuildConfig.d.ts +35 -35
- package/typings/features/build/BuildConfig.d.ts.map +1 -1
- package/typings/features/build/domain/ImportPaths.d.ts +8 -0
- package/typings/features/build/domain/ImportPaths.d.ts.map +1 -1
- package/typings/features/build/domain/scan.d.ts +2 -2
- package/typings/features/build/domain/scan.d.ts.map +1 -1
- package/typings/features/build/services/BundleBuilder.d.ts.map +1 -1
- package/typings/index.d.ts +1 -1
package/AGENTS.md
CHANGED
|
@@ -19,7 +19,7 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
19
19
|
- Every import in a bundle is written through a tsconfig `paths` alias, so the
|
|
20
20
|
bundle works wherever it is saved; a selected class no alias covers fails the
|
|
21
21
|
build naming its file. There are no relative imports.
|
|
22
|
-
- Config fields (schema: `tic.schema.json`), flat: `glob` with `glob.
|
|
22
|
+
- Config fields (schema: `tic.schema.json`), flat: `glob` with `glob.glob`
|
|
23
23
|
required; `className`, `name`, `tsconfig`, `importExtension` optional.
|
|
24
24
|
Relative paths resolve against the config file; for piped text, against the
|
|
25
25
|
working directory. `name` defaults to the file's stem (`prod.bundle.json` →
|
|
@@ -27,19 +27,24 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
|
|
|
27
27
|
is `toClassName(name)` — `ProdBundle`.
|
|
28
28
|
- A config does **not** extend its tsconfig and never takes files from it. The
|
|
29
29
|
`tsconfig` field (default `./tsconfig.json`, may be absent; one named
|
|
30
|
-
explicitly must exist) only supplies `paths` aliases — which `glob.
|
|
30
|
+
explicitly must exist) only supplies `paths` aliases — which `glob.glob` may
|
|
31
31
|
name and generated imports are written in (most specific alias, else a
|
|
32
32
|
relative path) — and the module resolution that sets the import extension.
|
|
33
|
-
- Selection has two stages
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
33
|
+
- Selection has two stages, both shaped `{ glob, exclude }`, and both taking
|
|
34
|
+
a string or a list as a shortcut for their `glob`. `glob: { glob, exclude }`
|
|
35
|
+
decides by path which files are read and parsed at all (`glob: ./src` /
|
|
36
|
+
`glob: [./a, ./b]` = `glob.glob`). `glob.glob` (required: one folder or a
|
|
37
|
+
non-empty list) names the folders scanned, always with their sub-folders —
|
|
38
|
+
relative to the config file (`./src/services`) or tsconfig aliases
|
|
39
|
+
(`@app/services`); there is no `{ path, recursive }` form. A file in them is parsed unless it matches one
|
|
40
|
+
of `exclude` (one glob or a list, each relative to the config file or starting
|
|
41
|
+
with a tsconfig alias — `@generated/**`, or `@generated` for the whole folder;
|
|
42
|
+
catch-all `"*"` aliases are skipped; default: test files, `__tests__/`,
|
|
43
|
+
`node_modules/`; a non-empty value replaces it, and the build warns if it drops
|
|
44
|
+
a default). There is no `include`. Files `tic build` generated are never input.
|
|
45
|
+
- `className: { export, decorators, glob, exclude }` (or `className: '*Service'`
|
|
46
|
+
/ `['*Service', '*Repository']` = `className.glob`, default `export` and
|
|
47
|
+
`decorators`) then picks classes of the parsed files; default is every exported,
|
|
43
48
|
non-abstract class decorated with `@register` (`decorators` defaults to
|
|
44
49
|
`["register"]`; `[]` requires none); positive criteria must all hold — `glob` is one glob
|
|
45
50
|
or a list the class name must match one of — and then `exclude` (one glob or a
|
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ tic build app.bundle.json | npx prettier --stdin-filepath app.bundle.ts > src/di
|
|
|
55
55
|
cat dev.bundle.json | tic build | tee src/di/dev.bundle.ts
|
|
56
56
|
|
|
57
57
|
# a config built on the fly
|
|
58
|
-
printf 'name: app\nglob
|
|
58
|
+
printf 'name: app\nglob: "@app/services"\n' | tic build > src/di/app.bundle.ts
|
|
59
59
|
jq '.name = "admin"' app.bundle.json | tic build > src/di/admin.bundle.ts
|
|
60
60
|
|
|
61
61
|
# CI: is the saved bundle current?
|
|
@@ -80,22 +80,18 @@ registers. Point your editor at the schema:
|
|
|
80
80
|
```json
|
|
81
81
|
{
|
|
82
82
|
"$schema": "./node_modules/@ts-ioc-container/bundler/tic.schema.json",
|
|
83
|
-
"glob":
|
|
84
|
-
"paths": ["@app/services", { "path": "./src/infra", "recursive": false }]
|
|
85
|
-
}
|
|
83
|
+
"glob": ["@app/services", "./src/infra"]
|
|
86
84
|
}
|
|
87
85
|
```
|
|
88
86
|
|
|
89
87
|
```yaml
|
|
90
88
|
# yaml-language-server: $schema=./node_modules/@ts-ioc-container/bundler/tic.schema.json
|
|
91
|
-
glob:
|
|
92
|
-
paths: ['@app/services', ./src/infra]
|
|
93
|
-
include: ['**/*.service.ts']
|
|
89
|
+
glob: ['@app/services', ./src/infra]
|
|
94
90
|
```
|
|
95
91
|
|
|
96
92
|
| Field | Default | Meaning |
|
|
97
93
|
| ----------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
98
|
-
| `glob` | — (required
|
|
94
|
+
| `glob` | — (required) | Which files are parsed — see [Selecting files](#selecting-files) |
|
|
99
95
|
| `className` | exported classes with `@register` | Which classes of a parsed file are registered — see [Selecting classes](#selecting-classes) |
|
|
100
96
|
| `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 |
|
|
101
97
|
| `tsconfig` | `./tsconfig.json` | Source of the `paths` aliases every import is written through, and of the import extension — never of files |
|
|
@@ -129,7 +125,7 @@ Each config selects its own files and classes:
|
|
|
129
125
|
```yaml
|
|
130
126
|
# prod.bundle.yml: services + adapters, minus dev-only *.dev.ts files
|
|
131
127
|
glob:
|
|
132
|
-
|
|
128
|
+
glob: ['@app/services', ./src/infra]
|
|
133
129
|
exclude:
|
|
134
130
|
- '**/*.dev.ts'
|
|
135
131
|
- '**/*.spec.ts'
|
|
@@ -142,8 +138,7 @@ glob:
|
|
|
142
138
|
|
|
143
139
|
```yaml
|
|
144
140
|
# dev.bundle.yml: the *.dev.ts logger replaces the production one, dropped by class name
|
|
145
|
-
glob:
|
|
146
|
-
paths: ['@app/services', ./src/infra]
|
|
141
|
+
glob: ['@app/services', ./src/infra]
|
|
147
142
|
className:
|
|
148
143
|
exclude: JsonLogger
|
|
149
144
|
```
|
|
@@ -159,15 +154,14 @@ A bundle picks its registrations in two stages:
|
|
|
159
154
|
pass are parsed.
|
|
160
155
|
2. **`className`** — decided per class, on the files stage 1 let through.
|
|
161
156
|
|
|
162
|
-
Parsing is where the time goes, so
|
|
163
|
-
|
|
164
|
-
bundler never reads anything else:
|
|
157
|
+
Parsing is where the time goes, so point `glob` at the folders that hold your
|
|
158
|
+
registrations, and `exclude` what they should not contribute:
|
|
165
159
|
|
|
166
160
|
```json
|
|
167
161
|
{
|
|
168
162
|
"glob": {
|
|
169
|
-
"
|
|
170
|
-
"
|
|
163
|
+
"glob": "@app/services",
|
|
164
|
+
"exclude": ["**/*.spec.ts", "**/*.test.ts", "**/__tests__/**", "**/node_modules/**", "**/legacy/**"]
|
|
171
165
|
},
|
|
172
166
|
"className": { "decorators": ["register"] }
|
|
173
167
|
}
|
|
@@ -175,21 +169,41 @@ bundler never reads anything else:
|
|
|
175
169
|
|
|
176
170
|
## Selecting files
|
|
177
171
|
|
|
178
|
-
`
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
`
|
|
172
|
+
`glob` takes the same shape as [`className`](#selecting-classes):
|
|
173
|
+
`{ glob, exclude }`. `glob.glob` names the folders a bundle's files come from,
|
|
174
|
+
and the only ones: what your tsconfig compiles plays no part. It is one folder
|
|
175
|
+
or a list, each relative to the config file (`./src/services`) or a tsconfig
|
|
176
|
+
`paths` alias (`@app/services`, for a `"@app/*": ["./src/*"]` alias), and
|
|
177
|
+
always scanned with its sub-folders.
|
|
178
|
+
|
|
179
|
+
When the default `exclude` is all you need, `glob` itself can be the folders —
|
|
180
|
+
a string or a list is a shortcut for `glob.glob`:
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
glob: ./src/services # = glob: { glob: ./src/services }
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
```yaml
|
|
187
|
+
glob: ['@app/services', ./src/infra] # = glob: { glob: ['@app/services', ./src/infra] }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
glob: # the object form, for a custom exclude
|
|
192
|
+
glob: ['@app/services', ./src/infra]
|
|
193
|
+
exclude: '**/*.dev.ts'
|
|
194
|
+
```
|
|
183
195
|
|
|
184
|
-
Within them, a file is parsed
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
Within them, a file is parsed unless it matches **one of** `exclude`. Globs are relative to the config file and `/`-separated; `**`
|
|
197
|
+
spans folders. Like a folder in `glob.glob`, an exclude glob may start with a
|
|
198
|
+
tsconfig `paths` alias: with `"@generated/*": ["./src/.generated/*"]`,
|
|
199
|
+
`@generated/**` reads `src/.generated/**`, and `@generated` (or `@generated/`)
|
|
200
|
+
drops the whole folder. A catch-all `"*"` alias is never applied, so plain globs
|
|
201
|
+
such as `**/*.spec.ts` keep their meaning.
|
|
187
202
|
|
|
188
|
-
| Rule | Default | Meaning
|
|
189
|
-
| --------- | ----------------------------------------- |
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `exclude` | test files, `__tests__/`, `node_modules/` | Globs of files never read; replaces the default when given |
|
|
203
|
+
| Rule | Default | Meaning |
|
|
204
|
+
| --------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
205
|
+
| `glob` | — (required) | Folder, or folders, to scan |
|
|
206
|
+
| `exclude` | test files, `__tests__/`, `node_modules/` | A glob, or a list of them, of files never read; may start with a tsconfig alias; replaces the default when given |
|
|
193
207
|
|
|
194
208
|
A non-empty `exclude` replaces the defaults, so restate the ones you still want:
|
|
195
209
|
|
|
@@ -202,15 +216,15 @@ A non-empty `exclude` replaces the defaults, so restate the ones you still want:
|
|
|
202
216
|
"**/*.test.tsx",
|
|
203
217
|
"**/__tests__/**",
|
|
204
218
|
"**/node_modules/**",
|
|
205
|
-
"frontend/api/generated/**"
|
|
219
|
+
"frontend/api/generated/**",
|
|
220
|
+
"@generated"
|
|
206
221
|
]
|
|
207
222
|
}
|
|
208
223
|
```
|
|
209
224
|
|
|
210
225
|
If it omits a default glob the build warns, since test classes usually carry
|
|
211
226
|
the same `@register` decorators as production ones. `"exclude": []` deliberately
|
|
212
|
-
parses everything, including tests.
|
|
213
|
-
`exclude`, so `**/*.service.ts` still skips `user.service.spec.ts`.
|
|
227
|
+
parses everything, including tests.
|
|
214
228
|
|
|
215
229
|
## Selecting classes
|
|
216
230
|
|
|
@@ -252,6 +266,20 @@ matches only itself, so one list drops a class by name and a family by pattern:
|
|
|
252
266
|
`exclude` applies after every other criterion, so it combines with
|
|
253
267
|
`decorators` and `glob` freely.
|
|
254
268
|
|
|
269
|
+
### The `className` shortcut
|
|
270
|
+
|
|
271
|
+
When the default `export` and `decorators` are all you need, `className`
|
|
272
|
+
itself can be the class-name globs — a string or a list is a shortcut for
|
|
273
|
+
`className.glob`, just as on `glob`:
|
|
274
|
+
|
|
275
|
+
```yaml
|
|
276
|
+
className: '*Service' # = className: { glob: '*Service' }
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
```yaml
|
|
280
|
+
className: ['*Service', '*Repository'] # = className: { glob: ['*Service', '*Repository'] }
|
|
281
|
+
```
|
|
282
|
+
|
|
255
283
|
As a safety net, the build warns when two selected classes pass the same
|
|
256
284
|
plain-identifier first argument to a decorator — usually the binding token, as in
|
|
257
285
|
`@repository(IDashboardRepositoryToken)`. The check is syntactic (aliased imports
|
|
@@ -313,5 +341,5 @@ const { content, warnings } = build({ config: 'app.bundle.json' });
|
|
|
313
341
|
writeFileSync('src/di/app.bundle.ts', content);
|
|
314
342
|
|
|
315
343
|
// or config text, as `tic build` reads from stdin
|
|
316
|
-
build({ text: 'name: app\nglob:\n
|
|
344
|
+
build({ text: 'name: app\nglob:\n glob: ["@app/services"]\n' });
|
|
317
345
|
```
|
|
@@ -30,39 +30,34 @@ const strings = (what, minItems) => zod_1.z
|
|
|
30
30
|
.custom((value) => Array.isArray(value) && value.length >= minItems && value.every(isNonEmptyString), expected(what))
|
|
31
31
|
.meta({ type: 'array', items: { type: 'string', minLength: 1 }, ...(minItems > 0 && { minItems }) });
|
|
32
32
|
const stringList = () => strings('an array of strings', 0);
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
.custom((value) => isNonEmptyString(value) || (Array.isArray(value) && value.length > 0 && value.every(isNonEmptyString)), expected('a glob or a non-empty array of globs'))
|
|
33
|
+
const globList = (what, minItems) => zod_1.z
|
|
34
|
+
.custom((value) => isNonEmptyString(value) || (Array.isArray(value) && value.length >= minItems && value.every(isNonEmptyString)), expected(what))
|
|
36
35
|
.meta({
|
|
37
36
|
anyOf: [
|
|
38
37
|
{ type: 'string', minLength: 1 },
|
|
39
|
-
{ type: 'array', items: { type: 'string', minLength: 1 }, minItems
|
|
38
|
+
{ type: 'array', items: { type: 'string', minLength: 1 }, ...(minItems > 0 && { minItems }) },
|
|
40
39
|
],
|
|
41
40
|
});
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
.strictObject({
|
|
52
|
-
paths: zod_1.z
|
|
53
|
-
.array(PATH_SCHEMA, expected('a non-empty array'))
|
|
54
|
-
.min(1, expected('a non-empty array'))
|
|
55
|
-
.describe('Folders to scan: paths relative to the config file (./src/services) or tsconfig paths aliases (@app/services). Sub-folders are scanned too unless an entry says { "path": "...", "recursive": false }.'),
|
|
56
|
-
include: nonEmptyStringList()
|
|
57
|
-
.optional()
|
|
58
|
-
.describe('Globs a file must match one of, e.g. ["**/*.service.ts", "**/*.repository.ts"]. Default: every source file.'),
|
|
59
|
-
exclude: stringList()
|
|
41
|
+
const globs = () => globList('a glob or a non-empty array of globs', 1);
|
|
42
|
+
const toList = (value) => (Array.isArray(value) ? value : [value]);
|
|
43
|
+
const toGlobs = (value) => value === undefined ? undefined : toList(value).map(glob_1.globToRegExp);
|
|
44
|
+
const FOLDERS_SCHEMA = zod_1.z.array(nonEmptyString(), expected('a non-empty array')).min(1, expected('a non-empty array'));
|
|
45
|
+
const GLOB_OBJECT_SCHEMA = zod_1.z.strictObject({
|
|
46
|
+
glob: zod_1.z
|
|
47
|
+
.union([nonEmptyString(), FOLDERS_SCHEMA], expected('a folder or a non-empty array of folders'))
|
|
48
|
+
.describe('Folder, or folders, to scan, sub-folders included: paths relative to the config file (./src/services) or tsconfig paths aliases (@app/services).'),
|
|
49
|
+
exclude: globList('a glob or an array of globs', 0)
|
|
60
50
|
.default(exports.DEFAULT_EXCLUDE)
|
|
61
|
-
.describe('
|
|
62
|
-
}, expected('an object'))
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
.
|
|
51
|
+
.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.'),
|
|
52
|
+
}, expected('an object'));
|
|
53
|
+
const GLOB_SCHEMA = zod_1.z
|
|
54
|
+
.union([
|
|
55
|
+
nonEmptyString().describe('One folder to scan, with the default exclude: shorthand for { "glob": [...] }.'),
|
|
56
|
+
FOLDERS_SCHEMA.describe('Folders to scan, with the default exclude: shorthand for { "glob": [...] }.'),
|
|
57
|
+
GLOB_OBJECT_SCHEMA,
|
|
58
|
+
], expected('a folder, a non-empty array of folders or an object with "glob"'))
|
|
59
|
+
.describe('Which files this bundle reads and parses — decided by path alone, before parsing. `glob` 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. A folder, or a list of folders, is shorthand for { "glob": [...] }.');
|
|
60
|
+
const CLASS_OBJECT_SCHEMA = zod_1.z.strictObject({
|
|
66
61
|
export: zod_1.z
|
|
67
62
|
.enum(['any', 'named', 'default'], expected('"any", "named" or "default"'))
|
|
68
63
|
.default('any')
|
|
@@ -76,8 +71,17 @@ const CLASSES_SCHEMA = zod_1.z
|
|
|
76
71
|
exclude: globs()
|
|
77
72
|
.optional()
|
|
78
73
|
.describe('Glob, or globs, the class name must match none of, applied after every other criterion. A plain name is a glob too: ["MockUserRepository", "*Fake"].'),
|
|
79
|
-
}, expected('an object'))
|
|
80
|
-
|
|
74
|
+
}, expected('an object'));
|
|
75
|
+
const CLASSES_SCHEMA = zod_1.z
|
|
76
|
+
.union([
|
|
77
|
+
nonEmptyString().describe('One class-name glob, with the default export and decorators: shorthand for { "glob": "..." }.'),
|
|
78
|
+
zod_1.z
|
|
79
|
+
.array(nonEmptyString(), expected('a non-empty array'))
|
|
80
|
+
.min(1, expected('a non-empty array'))
|
|
81
|
+
.describe('Class-name globs, with the default export and decorators: shorthand for { "glob": [...] }.'),
|
|
82
|
+
CLASS_OBJECT_SCHEMA,
|
|
83
|
+
], expected('a glob, a non-empty array of globs or an object'))
|
|
84
|
+
.describe('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": ... }.');
|
|
81
85
|
exports.BUNDLE_CONFIG_SCHEMA = zod_1.z.strictObject({
|
|
82
86
|
$schema: zod_1.z.string().optional(),
|
|
83
87
|
name: zod_1.z
|
|
@@ -88,7 +92,7 @@ exports.BUNDLE_CONFIG_SCHEMA = zod_1.z.strictObject({
|
|
|
88
92
|
tsconfig: nonEmptyString()
|
|
89
93
|
.optional()
|
|
90
94
|
.meta({ default: exports.DEFAULT_TSCONFIG })
|
|
91
|
-
.describe('The tsconfig whose `paths` aliases glob.
|
|
95
|
+
.describe('The tsconfig whose `paths` aliases glob.glob may name and generated imports are written in, and whose module resolution sets the import extension. It adds no files: the bundle scans glob.glob alone. Relative to the config file. The default may be absent; a tsconfig named here must exist.'),
|
|
92
96
|
importExtension: zod_1.z
|
|
93
97
|
.string(expected('a string'))
|
|
94
98
|
.optional()
|
|
@@ -117,17 +121,24 @@ function formatIssue(issue, prefix = []) {
|
|
|
117
121
|
return [`${formatPath(at)}: ${issue.message}`];
|
|
118
122
|
}
|
|
119
123
|
const formatIssues = (error) => error.issues.flatMap((issue) => formatIssue(issue)).join('; ');
|
|
124
|
+
function toGlobObject(glob) {
|
|
125
|
+
if (typeof glob === 'string' || Array.isArray(glob))
|
|
126
|
+
return { glob, exclude: exports.DEFAULT_EXCLUDE };
|
|
127
|
+
return glob;
|
|
128
|
+
}
|
|
120
129
|
function toGlobSelector(glob) {
|
|
121
130
|
return {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
exclude: glob.exclude.map(glob_1.globToRegExp),
|
|
131
|
+
glob: toList(glob.glob),
|
|
132
|
+
exclude: toList(glob.exclude),
|
|
125
133
|
};
|
|
126
134
|
}
|
|
127
|
-
function toClassSelector(
|
|
128
|
-
if (
|
|
135
|
+
function toClassSelector(className) {
|
|
136
|
+
if (className === undefined)
|
|
129
137
|
return { export: 'any', decorators: exports.DEFAULT_DECORATORS };
|
|
130
|
-
|
|
138
|
+
if (typeof className === 'string' || Array.isArray(className)) {
|
|
139
|
+
return { export: 'any', decorators: exports.DEFAULT_DECORATORS, glob: toGlobs(className) };
|
|
140
|
+
}
|
|
141
|
+
const { decorators, glob, exclude, ...rest } = className;
|
|
131
142
|
return {
|
|
132
143
|
...rest,
|
|
133
144
|
decorators: decorators.length > 0 ? decorators : undefined,
|
|
@@ -136,7 +147,7 @@ function toClassSelector(classes) {
|
|
|
136
147
|
};
|
|
137
148
|
}
|
|
138
149
|
function excludeWarnings(glob) {
|
|
139
|
-
const
|
|
150
|
+
const exclude = toList(glob.exclude);
|
|
140
151
|
if (exclude.length === 0)
|
|
141
152
|
return [];
|
|
142
153
|
const missing = exports.DEFAULT_EXCLUDE.filter((glob) => !exclude.includes(glob));
|
|
@@ -181,6 +192,7 @@ function resolveConfig(content, file) {
|
|
|
181
192
|
: `name: required when the config file is not named <name>${exports.CONFIG_FILE_SUFFIXES.join(' / ')}`);
|
|
182
193
|
}
|
|
183
194
|
const dir = node_path_1.default.dirname(file);
|
|
195
|
+
const globObject = toGlobObject(glob);
|
|
184
196
|
return {
|
|
185
197
|
file,
|
|
186
198
|
dir,
|
|
@@ -188,8 +200,8 @@ function resolveConfig(content, file) {
|
|
|
188
200
|
bundleClassName: toClassName(bundleName),
|
|
189
201
|
tsconfig: { file: node_path_1.default.resolve(dir, tsconfig ?? exports.DEFAULT_TSCONFIG), required: tsconfig !== undefined },
|
|
190
202
|
importExtension,
|
|
191
|
-
glob: toGlobSelector(
|
|
203
|
+
glob: toGlobSelector(globObject),
|
|
192
204
|
className: toClassSelector(className),
|
|
193
|
-
warnings: excludeWarnings(
|
|
205
|
+
warnings: excludeWarnings(globObject),
|
|
194
206
|
};
|
|
195
207
|
}
|
|
@@ -77,6 +77,14 @@ class ImportPaths {
|
|
|
77
77
|
}
|
|
78
78
|
throw new DomainException_1.NamespaceNotFoundError(`namespace "${namespace}" is neither a folder relative to ${baseDir} nor a tsconfig paths alias of one`);
|
|
79
79
|
}
|
|
80
|
+
resolveGlob(glob, baseDir) {
|
|
81
|
+
if (isRelative(glob))
|
|
82
|
+
return [glob];
|
|
83
|
+
const targets = [glob, `${glob}/`].map((spec) => this.aliasTargets(spec, true)).find((found) => found.length > 0);
|
|
84
|
+
if (!targets)
|
|
85
|
+
return [glob];
|
|
86
|
+
return targets.map((target) => (0, glob_1.toPosix)(node_path_1.default.relative(baseDir, target.endsWith('/') ? `${target}**` : target)));
|
|
87
|
+
}
|
|
80
88
|
specifier(file) {
|
|
81
89
|
const target = (0, glob_1.toPosix)(file);
|
|
82
90
|
return this.bestAlias(target, target.replace(SOURCE_EXTENSION, ''))?.spec;
|
|
@@ -92,12 +100,14 @@ class ImportPaths {
|
|
|
92
100
|
}
|
|
93
101
|
return best;
|
|
94
102
|
}
|
|
95
|
-
aliasTargets(spec) {
|
|
103
|
+
aliasTargets(spec, prefixed = false) {
|
|
96
104
|
return this.aliases.flatMap(({ pattern, targets }) => {
|
|
97
105
|
const wildcard = splitWildcard(pattern);
|
|
98
106
|
if (!wildcard)
|
|
99
107
|
return pattern === spec ? targets : [];
|
|
100
108
|
const [prefix, suffix] = wildcard;
|
|
109
|
+
if (prefixed && prefix === '')
|
|
110
|
+
return [];
|
|
101
111
|
if (!spec.startsWith(prefix) || !spec.endsWith(suffix) || spec.length < prefix.length + suffix.length)
|
|
102
112
|
return [];
|
|
103
113
|
const captured = spec.slice(prefix.length, spec.length - suffix.length);
|
|
@@ -46,13 +46,13 @@ const SOURCE_FILE = /\.(tsx?|mts|cts)$/;
|
|
|
46
46
|
const DECLARATION_FILE = /\.d\.[mc]?tsx?$/;
|
|
47
47
|
const isSourceFile = (file) => SOURCE_FILE.test(file) && !DECLARATION_FILE.test(file);
|
|
48
48
|
exports.isSourceFile = isSourceFile;
|
|
49
|
-
function listSourceFiles(dir,
|
|
49
|
+
function listSourceFiles(dir, isExcluded) {
|
|
50
50
|
const files = [];
|
|
51
51
|
const walk = (current) => {
|
|
52
52
|
for (const entry of (0, node_fs_1.readdirSync)(current, { withFileTypes: true })) {
|
|
53
53
|
const full = node_path_1.default.join(current, entry.name);
|
|
54
54
|
if (entry.isDirectory()) {
|
|
55
|
-
if (
|
|
55
|
+
if (entry.name !== 'node_modules')
|
|
56
56
|
walk(full);
|
|
57
57
|
}
|
|
58
58
|
else if ((0, exports.isSourceFile)(entry.name) && !isExcluded(full)) {
|
|
@@ -56,17 +56,15 @@ let BundleBuilder = class BundleBuilder {
|
|
|
56
56
|
generate(config) {
|
|
57
57
|
const paths = (0, tsconfig_1.loadImportPaths)(config.tsconfig, config.importExtension);
|
|
58
58
|
const relative = (file) => (0, glob_1.toPosix)(node_path_1.default.relative(config.dir, file));
|
|
59
|
-
const
|
|
59
|
+
const exclude = config.glob.exclude.flatMap((glob) => paths.resolveGlob(glob, config.dir)).map(glob_1.globToRegExp);
|
|
60
60
|
const isExcluded = (file) => {
|
|
61
61
|
const filename = relative(file);
|
|
62
|
-
if (include && !include.some((glob) => glob.test(filename)))
|
|
63
|
-
return true;
|
|
64
62
|
return exclude.some((glob) => glob.test(filename));
|
|
65
63
|
};
|
|
66
64
|
const files = new Set();
|
|
67
|
-
for (const
|
|
68
|
-
const dir = paths.resolveNamespace(
|
|
69
|
-
for (const file of (0, scan_1.listSourceFiles)(dir,
|
|
65
|
+
for (const folder of config.glob.glob) {
|
|
66
|
+
const dir = paths.resolveNamespace(folder, config.dir);
|
|
67
|
+
for (const file of (0, scan_1.listSourceFiles)(dir, isExcluded))
|
|
70
68
|
files.add(file);
|
|
71
69
|
}
|
|
72
70
|
const classes = [...files]
|
|
@@ -83,7 +81,7 @@ let BundleBuilder = class BundleBuilder {
|
|
|
83
81
|
}
|
|
84
82
|
const content = this.renderer.render(emit_1.BUNDLE_PROTOCOL, (0, emit_1.bundleView)({
|
|
85
83
|
name: config.bundleClassName,
|
|
86
|
-
paths: config.glob.
|
|
84
|
+
paths: config.glob.glob,
|
|
87
85
|
classes: classes.map((cls) => ({ ...cls, specifier: cls.specifier })),
|
|
88
86
|
}));
|
|
89
87
|
return { content, registrations: classes.length, warnings: (0, tokenCollisions_1.tokenCollisions)(classes) };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ts-ioc-container/bundler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.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",
|
package/tic.schema.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"tsconfig": {
|
|
17
17
|
"default": "./tsconfig.json",
|
|
18
|
-
"description": "The tsconfig whose `paths` aliases glob.
|
|
18
|
+
"description": "The tsconfig whose `paths` aliases glob.glob may name and generated imports are written in, and whose module resolution sets the import extension. It adds no files: the bundle scans glob.glob alone. Relative to the config file. The default may be absent; a tsconfig named here must exist.",
|
|
19
19
|
"type": "string",
|
|
20
20
|
"minLength": 1
|
|
21
21
|
},
|
|
@@ -24,131 +24,153 @@
|
|
|
24
24
|
"type": "string"
|
|
25
25
|
},
|
|
26
26
|
"glob": {
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
"anyOf": [
|
|
28
|
+
{
|
|
29
|
+
"type": "string",
|
|
30
|
+
"minLength": 1,
|
|
31
|
+
"description": "One folder to scan, with the default exclude: shorthand for { \"glob\": [...] }."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
30
34
|
"minItems": 1,
|
|
31
35
|
"type": "array",
|
|
32
36
|
"items": {
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
"type": "string",
|
|
38
|
+
"minLength": 1
|
|
39
|
+
},
|
|
40
|
+
"description": "Folders to scan, with the default exclude: shorthand for { \"glob\": [...] }."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "object",
|
|
44
|
+
"properties": {
|
|
45
|
+
"glob": {
|
|
46
|
+
"anyOf": [
|
|
47
|
+
{
|
|
48
|
+
"type": "string",
|
|
49
|
+
"minLength": 1
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"minItems": 1,
|
|
53
|
+
"type": "array",
|
|
54
|
+
"items": {
|
|
42
55
|
"type": "string",
|
|
43
56
|
"minLength": 1
|
|
44
|
-
},
|
|
45
|
-
"recursive": {
|
|
46
|
-
"default": true,
|
|
47
|
-
"type": "boolean"
|
|
48
57
|
}
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"description": "Folder, or folders, to scan, sub-folders included: paths relative to the config file (./src/services) or tsconfig paths aliases (@app/services)."
|
|
61
|
+
},
|
|
62
|
+
"exclude": {
|
|
63
|
+
"default": [
|
|
64
|
+
"**/*.spec.ts",
|
|
65
|
+
"**/*.test.ts",
|
|
66
|
+
"**/*.spec.tsx",
|
|
67
|
+
"**/*.test.tsx",
|
|
68
|
+
"**/__tests__/**",
|
|
69
|
+
"**/node_modules/**"
|
|
70
|
+
],
|
|
71
|
+
"description": "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.",
|
|
72
|
+
"anyOf": [
|
|
73
|
+
{
|
|
74
|
+
"type": "string",
|
|
75
|
+
"minLength": 1
|
|
49
76
|
},
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"include": {
|
|
60
|
-
"description": "Globs a file must match one of, e.g. [\"**/*.service.ts\", \"**/*.repository.ts\"]. Default: every source file.",
|
|
61
|
-
"type": "array",
|
|
62
|
-
"items": {
|
|
63
|
-
"type": "string",
|
|
64
|
-
"minLength": 1
|
|
77
|
+
{
|
|
78
|
+
"type": "array",
|
|
79
|
+
"items": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"minLength": 1
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
}
|
|
65
86
|
},
|
|
66
|
-
"
|
|
67
|
-
|
|
68
|
-
"exclude": {
|
|
69
|
-
"default": [
|
|
70
|
-
"**/*.spec.ts",
|
|
71
|
-
"**/*.test.ts",
|
|
72
|
-
"**/*.spec.tsx",
|
|
73
|
-
"**/*.test.tsx",
|
|
74
|
-
"**/__tests__/**",
|
|
75
|
-
"**/node_modules/**"
|
|
87
|
+
"required": [
|
|
88
|
+
"glob"
|
|
76
89
|
],
|
|
77
|
-
"
|
|
78
|
-
"type": "array",
|
|
79
|
-
"items": {
|
|
80
|
-
"type": "string",
|
|
81
|
-
"minLength": 1
|
|
82
|
-
}
|
|
90
|
+
"additionalProperties": false
|
|
83
91
|
}
|
|
84
|
-
},
|
|
85
|
-
"required": [
|
|
86
|
-
"paths"
|
|
87
92
|
],
|
|
88
|
-
"
|
|
89
|
-
"description": "Which files this bundle reads and parses — decided by path alone, before parsing. `paths` are the folders the files come from; within them a file is parsed when it matches one of `include` and none of `exclude`. Globs are relative to the config file. With a file naming convention, `include` keeps every other file unread."
|
|
93
|
+
"description": "Which files this bundle reads and parses — decided by path alone, before parsing. `glob` 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. A folder, or a list of folders, is shorthand for { \"glob\": [...] }."
|
|
90
94
|
},
|
|
91
95
|
"className": {
|
|
92
|
-
"
|
|
93
|
-
|
|
94
|
-
"export": {
|
|
95
|
-
"default": "any",
|
|
96
|
-
"description": "Which exports count.",
|
|
96
|
+
"anyOf": [
|
|
97
|
+
{
|
|
97
98
|
"type": "string",
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
"named",
|
|
101
|
-
"default"
|
|
102
|
-
]
|
|
99
|
+
"minLength": 1,
|
|
100
|
+
"description": "One class-name glob, with the default export and decorators: shorthand for { \"glob\": \"...\" }."
|
|
103
101
|
},
|
|
104
|
-
|
|
105
|
-
"
|
|
106
|
-
"register"
|
|
107
|
-
],
|
|
108
|
-
"description": "The class must carry one of these decorators, recognised by name (e.g. \"register\", or a composed decorator). Default [\"register\"]; [] requires none.",
|
|
102
|
+
{
|
|
103
|
+
"minItems": 1,
|
|
109
104
|
"type": "array",
|
|
110
105
|
"items": {
|
|
111
106
|
"type": "string",
|
|
112
107
|
"minLength": 1
|
|
113
|
-
}
|
|
108
|
+
},
|
|
109
|
+
"description": "Class-name globs, with the default export and decorators: shorthand for { \"glob\": [...] }."
|
|
114
110
|
},
|
|
115
|
-
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
{
|
|
111
|
+
{
|
|
112
|
+
"type": "object",
|
|
113
|
+
"properties": {
|
|
114
|
+
"export": {
|
|
115
|
+
"default": "any",
|
|
116
|
+
"description": "Which exports count.",
|
|
119
117
|
"type": "string",
|
|
120
|
-
"
|
|
118
|
+
"enum": [
|
|
119
|
+
"any",
|
|
120
|
+
"named",
|
|
121
|
+
"default"
|
|
122
|
+
]
|
|
121
123
|
},
|
|
122
|
-
{
|
|
124
|
+
"decorators": {
|
|
125
|
+
"default": [
|
|
126
|
+
"register"
|
|
127
|
+
],
|
|
128
|
+
"description": "The class must carry one of these decorators, recognised by name (e.g. \"register\", or a composed decorator). Default [\"register\"]; [] requires none.",
|
|
123
129
|
"type": "array",
|
|
124
130
|
"items": {
|
|
125
131
|
"type": "string",
|
|
126
132
|
"minLength": 1
|
|
127
|
-
}
|
|
128
|
-
"minItems": 1
|
|
129
|
-
}
|
|
130
|
-
]
|
|
131
|
-
},
|
|
132
|
-
"exclude": {
|
|
133
|
-
"description": "Glob, or globs, the class name must match none of, applied after every other criterion. A plain name is a glob too: [\"MockUserRepository\", \"*Fake\"].",
|
|
134
|
-
"anyOf": [
|
|
135
|
-
{
|
|
136
|
-
"type": "string",
|
|
137
|
-
"minLength": 1
|
|
133
|
+
}
|
|
138
134
|
},
|
|
139
|
-
{
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
135
|
+
"glob": {
|
|
136
|
+
"description": "Glob, or globs, the class name must match one of, e.g. \"*Service\" or [\"*Service\", \"*Repository\"]. An anonymous default export is named after its file.",
|
|
137
|
+
"anyOf": [
|
|
138
|
+
{
|
|
139
|
+
"type": "string",
|
|
140
|
+
"minLength": 1
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"type": "array",
|
|
144
|
+
"items": {
|
|
145
|
+
"type": "string",
|
|
146
|
+
"minLength": 1
|
|
147
|
+
},
|
|
148
|
+
"minItems": 1
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
"exclude": {
|
|
153
|
+
"description": "Glob, or globs, the class name must match none of, applied after every other criterion. A plain name is a glob too: [\"MockUserRepository\", \"*Fake\"].",
|
|
154
|
+
"anyOf": [
|
|
155
|
+
{
|
|
156
|
+
"type": "string",
|
|
157
|
+
"minLength": 1
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"type": "array",
|
|
161
|
+
"items": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"minLength": 1
|
|
164
|
+
},
|
|
165
|
+
"minItems": 1
|
|
166
|
+
}
|
|
167
|
+
]
|
|
146
168
|
}
|
|
147
|
-
|
|
169
|
+
},
|
|
170
|
+
"additionalProperties": false
|
|
148
171
|
}
|
|
149
|
-
|
|
150
|
-
"
|
|
151
|
-
"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."
|
|
172
|
+
],
|
|
173
|
+
"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\": ... }."
|
|
152
174
|
}
|
|
153
175
|
},
|
|
154
176
|
"required": [
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
/**
|
|
3
3
|
* Which files a bundle reads and parses: the first, cheap stage of selection,
|
|
4
|
-
* decided by path alone. `
|
|
5
|
-
* a file is parsed
|
|
6
|
-
*
|
|
7
|
-
* (`*.service.ts`), `include` keeps the bundler from reading anything else.
|
|
4
|
+
* decided by path alone. `glob` names the folders the files come from; within them
|
|
5
|
+
* a file is parsed unless it matches one of `exclude`. Globs are relative to the
|
|
6
|
+
* config file and `/`-separated.
|
|
8
7
|
*/
|
|
9
8
|
export interface GlobSelector {
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Folder, or folders, to scan recursively: relative to the config file (`./src/services`),
|
|
11
|
+
* or tsconfig `paths` aliases (`@app/services`).
|
|
12
|
+
*/
|
|
13
|
+
glob: string | string[];
|
|
14
|
+
/**
|
|
15
|
+
* Glob, or globs, of files never read; one may start with a tsconfig `paths` alias
|
|
16
|
+
* (`@generated/**`, or `@generated` for the whole folder). Replaces {@link DEFAULT_EXCLUDE} when given.
|
|
17
|
+
*/
|
|
18
|
+
exclude?: string | string[];
|
|
16
19
|
}
|
|
17
20
|
/** A {@link GlobSelector} with its defaults filled in and its globs compiled. */
|
|
18
21
|
export interface ResolvedGlobSelector {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
/** The folders to scan, as written in the config. */
|
|
23
|
+
glob: string[];
|
|
24
|
+
/** As written in the config: an alias in one is resolved, and the glob compiled, once the tsconfig is loaded. */
|
|
25
|
+
exclude: string[];
|
|
22
26
|
}
|
|
23
27
|
/** Which exports of a file count: both kinds, only named exports, or only the default export. */
|
|
24
28
|
export type ExportKind = 'any' | 'named' | 'default';
|
|
@@ -55,12 +59,6 @@ export interface ResolvedClassSelector {
|
|
|
55
59
|
glob?: RegExp[];
|
|
56
60
|
exclude?: RegExp[];
|
|
57
61
|
}
|
|
58
|
-
export interface PathConfig {
|
|
59
|
-
/** A folder relative to the config file (`./src/services`) or a tsconfig `paths` alias (`@app/services`). */
|
|
60
|
-
path: string;
|
|
61
|
-
/** Scan sub-folders too. Default `true`. */
|
|
62
|
-
recursive?: boolean;
|
|
63
|
-
}
|
|
64
62
|
/**
|
|
65
63
|
* A bundle config file: one bundle, described explicitly — the folders it scans and the
|
|
66
64
|
* classes it registers. `tic build <config>` prints the bundle to stdout; where it is
|
|
@@ -76,18 +74,24 @@ export interface BundleConfig {
|
|
|
76
74
|
*/
|
|
77
75
|
name?: string;
|
|
78
76
|
/**
|
|
79
|
-
* The tsconfig whose `paths` aliases `glob.
|
|
77
|
+
* The tsconfig whose `paths` aliases `glob.glob` may name and generated imports are
|
|
80
78
|
* written in, and whose `moduleResolution` sets the import extension. It contributes
|
|
81
|
-
* nothing else: the files scanned are `glob.
|
|
79
|
+
* nothing else: the files scanned are `glob.glob` alone. Relative to the config file.
|
|
82
80
|
* Default `./tsconfig.json`, which may be absent; a tsconfig named here must exist.
|
|
83
81
|
*/
|
|
84
82
|
tsconfig?: string;
|
|
85
83
|
/** Extension of generated imports. Inferred from the tsconfig's `moduleResolution` when omitted. */
|
|
86
84
|
importExtension?: string;
|
|
87
|
-
/**
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
/**
|
|
86
|
+
* Which files are parsed: the folders in `glob.glob`, minus {@link DEFAULT_EXCLUDE} unless
|
|
87
|
+
* `exclude` says otherwise. A folder or a list of folders is shorthand for `{ glob }`, as on {@link ClassSelector}.
|
|
88
|
+
*/
|
|
89
|
+
glob: string | string[] | GlobSelector;
|
|
90
|
+
/**
|
|
91
|
+
* Which classes of a parsed file are registered. Default: every exported class decorated
|
|
92
|
+
* with `@register`. A glob or a list of globs is shorthand for `{ glob }`, as on `glob`.
|
|
93
|
+
*/
|
|
94
|
+
className?: string | string[] | ClassSelector;
|
|
91
95
|
}
|
|
92
96
|
export declare const DEFAULT_TSCONFIG = "./tsconfig.json";
|
|
93
97
|
/** What `className.decorators` requires when omitted: the library's own `@register`. */
|
|
@@ -124,15 +128,11 @@ export declare const BUNDLE_CONFIG_SCHEMA: z.ZodObject<{
|
|
|
124
128
|
name: z.ZodOptional<z.ZodString>;
|
|
125
129
|
tsconfig: z.ZodOptional<z.ZodString>;
|
|
126
130
|
importExtension: z.ZodOptional<z.ZodString>;
|
|
127
|
-
glob: z.ZodObject<{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
include: z.ZodOptional<z.ZodCustom<string[], string[]>>;
|
|
133
|
-
exclude: z.ZodDefault<z.ZodCustom<string[], string[]>>;
|
|
134
|
-
}, z.core.$strict>;
|
|
135
|
-
className: z.ZodOptional<z.ZodObject<{
|
|
131
|
+
glob: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
132
|
+
glob: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
133
|
+
exclude: z.ZodDefault<z.ZodCustom<string | string[], string | string[]>>;
|
|
134
|
+
}, z.core.$strict>]>;
|
|
135
|
+
className: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
136
136
|
export: z.ZodDefault<z.ZodEnum<{
|
|
137
137
|
default: "default";
|
|
138
138
|
any: "any";
|
|
@@ -141,7 +141,7 @@ export declare const BUNDLE_CONFIG_SCHEMA: z.ZodObject<{
|
|
|
141
141
|
decorators: z.ZodDefault<z.ZodCustom<string[], string[]>>;
|
|
142
142
|
glob: z.ZodOptional<z.ZodCustom<string | string[], string | string[]>>;
|
|
143
143
|
exclude: z.ZodOptional<z.ZodCustom<string | string[], string | string[]>>;
|
|
144
|
-
}, z.core.$strict>>;
|
|
144
|
+
}, z.core.$strict>]>>;
|
|
145
145
|
}, z.core.$strict>;
|
|
146
146
|
/**
|
|
147
147
|
* A config file is named `<name>.bundle.json`, `<name>.bundle.yaml` or `<name>.bundle.yml`
|
|
@@ -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
|
|
1
|
+
{"version":3,"file":"BuildConfig.d.ts","sourceRoot":"","sources":["../../../lib/features/build/BuildConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,13 @@ export declare class ImportPaths {
|
|
|
23
23
|
* @throws {NamespaceNotFoundError} when the namespace is neither an existing folder nor an alias of one.
|
|
24
24
|
*/
|
|
25
25
|
resolveNamespace(namespace: string, baseDir: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* An exclude glob as a glob relative to `baseDir`. One that starts with a `paths` alias
|
|
28
|
+
* reads from the folder the alias names — `@generated/**` -> `src/.generated/**` — and an
|
|
29
|
+
* alias naming a folder alone (`@generated`, `@generated/`) covers everything in it. An
|
|
30
|
+
* alias with several targets yields one glob per target; any other glob is returned as is.
|
|
31
|
+
*/
|
|
32
|
+
resolveGlob(glob: string, baseDir: string): string[];
|
|
26
33
|
/**
|
|
27
34
|
* The specifier `file` is imported by: its most specific `paths` alias. `undefined` when no
|
|
28
35
|
* alias covers it — a bundle is written to stdout, so it has no location a relative import
|
|
@@ -30,6 +37,7 @@ export declare class ImportPaths {
|
|
|
30
37
|
*/
|
|
31
38
|
specifier(file: string): string | undefined;
|
|
32
39
|
private bestAlias;
|
|
40
|
+
/** `prefixed` skips catch-all aliases (`"*"`), which would claim every plain glob such as `**\/*.spec.ts`. */
|
|
33
41
|
private aliasTargets;
|
|
34
42
|
/** A longer matched target prefix is a more specific alias; an exact file alias beats every wildcard. */
|
|
35
43
|
private matchAlias;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImportPaths.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/domain/ImportPaths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAIjC,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAaD;;;GAGG;AACH,qBAAa,WAAW;IAmBpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAnB5B;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,WAAW;gBAczF,OAAO,EAAE,KAAK,EAAE,EACxB,SAAS,EAAE,MAAM;IAG5B;;;;OAIG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAa5D;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3C,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,YAAY;
|
|
1
|
+
{"version":3,"file":"ImportPaths.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/domain/ImportPaths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAIjC,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAaD;;;GAGG;AACH,qBAAa,WAAW;IAmBpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM;IAnB5B;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,EAAE,YAAY,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,WAAW;gBAczF,OAAO,EAAE,KAAK,EAAE,EACxB,SAAS,EAAE,MAAM;IAG5B;;;;OAIG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAa5D;;;;;OAKG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE;IAOpD;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK3C,OAAO,CAAC,SAAS;IAWjB,8GAA8G;IAC9G,OAAO,CAAC,YAAY;IAYpB,yGAAyG;IACzG,OAAO,CAAC,UAAU;CAanB"}
|
|
@@ -29,8 +29,8 @@ export interface DiscoveredClass {
|
|
|
29
29
|
}
|
|
30
30
|
/** A TypeScript source file the bundler may parse: not a declaration file. */
|
|
31
31
|
export declare const isSourceFile: (file: string) => boolean;
|
|
32
|
-
/** Source files of `dir
|
|
33
|
-
export declare function listSourceFiles(dir: string,
|
|
32
|
+
/** Source files of `dir` and its sub-folders, sorted by path so the generated output is stable across machines. */
|
|
33
|
+
export declare function listSourceFiles(dir: string, isExcluded: (file: string) => boolean): string[];
|
|
34
34
|
/**
|
|
35
35
|
* The exported, non-abstract classes of one file that `selector` selects, in
|
|
36
36
|
* declaration order. Syntax only: decorators are recognised by name, not by type.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/domain/scan.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CACpD;AAKD,8EAA8E;AAC9E,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,OAAiE,CAAC;AAE9G
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/domain/scan.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,cAAc,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;CACpD;AAKD,8EAA8E;AAC9E,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,OAAiE,CAAC;AAE9G,mHAAmH;AACnH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,EAAE,CAc5F;AA2BD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,SAA6B,GAChC,eAAe,EAAE,CAkFnB"}
|
|
@@ -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,mGAAmG;IACnG,MAAM,EAAE,MAAM,CAAC;CAChB,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,oFAAoF;IACpF,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;
|
|
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,mGAAmG;IACnG,MAAM,EAAE,MAAM,CAAC;CAChB,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,oFAAoF;IACpF,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"}
|
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
|
|
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 GlobSelector, type ResolvedGlobSelector, 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';
|