@ts-ioc-container/bundler 5.0.0 → 6.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 +11 -8
- package/README.md +46 -38
- package/cjm/features/build/BuildConfig.js +17 -28
- package/cjm/features/build/domain/ImportPaths.js +11 -1
- package/cjm/features/build/domain/emit.js +2 -2
- package/cjm/features/build/services/BundleBuilder.js +3 -3
- package/package.json +2 -2
- package/tic.schema.json +47 -65
- package/tpl/index.cjs +11 -20
- package/typings/features/build/BuildConfig.d.ts +24 -20
- 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/emit.d.ts +1 -1
- package/typings/features/build/domain/emit.d.ts.map +1 -1
- package/typings/features/build/services/BundleBuilder.d.ts +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: `
|
|
22
|
+
- Config fields (schema: `tic.schema.json`), flat: `paths` with `paths.include`
|
|
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,22 @@ 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 `
|
|
30
|
+
explicitly must exist) only supplies `paths` aliases — which `paths.include` 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
|
-
|
|
33
|
+
- Selection has two stages, `paths: { include, exclude }` and
|
|
34
|
+
`className: { ..., glob, exclude }`. `paths` is always an object (a string
|
|
35
|
+
or a list in its place is an error); `className` also takes a string or a
|
|
36
|
+
list as a shortcut for `className.glob`. `paths` decides by path which files
|
|
37
|
+
are read and parsed at all. `paths.include` (required: one folder or a
|
|
37
38
|
non-empty list) names the folders scanned, always with their sub-folders —
|
|
38
39
|
relative to the config file (`./src/services`) or tsconfig aliases
|
|
39
40
|
(`@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
|
|
41
|
+
of `exclude` (one glob or a list, each relative to the config file or starting
|
|
42
|
+
with a tsconfig alias — `@generated/**`, or `@generated` for the whole folder;
|
|
43
|
+
catch-all `"*"` aliases are skipped; default: test files, `__tests__/`,
|
|
41
44
|
`node_modules/`; a non-empty value replaces it, and the build warns if it drops
|
|
42
|
-
a default).
|
|
45
|
+
a default). Files `tic build` generated are never input.
|
|
43
46
|
- `className: { export, decorators, glob, exclude }` (or `className: '*Service'`
|
|
44
47
|
/ `['*Service', '*Repository']` = `className.glob`, default `export` and
|
|
45
48
|
`decorators`) then picks classes of the parsed files; default is every exported,
|
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\
|
|
58
|
+
printf 'name: app\npaths:\n include: "@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,18 +80,21 @@ 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
|
-
"
|
|
83
|
+
"paths": { "include": ["@app/services", "./src/infra"] }
|
|
84
84
|
}
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
```yaml
|
|
88
88
|
# yaml-language-server: $schema=./node_modules/@ts-ioc-container/bundler/tic.schema.json
|
|
89
|
-
|
|
89
|
+
paths:
|
|
90
|
+
include:
|
|
91
|
+
- '@app/services'
|
|
92
|
+
- ./src/infra
|
|
90
93
|
```
|
|
91
94
|
|
|
92
95
|
| Field | Default | Meaning |
|
|
93
96
|
| ----------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
94
|
-
| `
|
|
97
|
+
| `paths` | — (required) | Which files are parsed — see [Selecting files](#selecting-files) |
|
|
95
98
|
| `className` | exported classes with `@register` | Which classes of a parsed file are registered — see [Selecting classes](#selecting-classes) |
|
|
96
99
|
| `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 |
|
|
97
100
|
| `tsconfig` | `./tsconfig.json` | Source of the `paths` aliases every import is written through, and of the import extension — never of files |
|
|
@@ -124,8 +127,10 @@ Each config selects its own files and classes:
|
|
|
124
127
|
|
|
125
128
|
```yaml
|
|
126
129
|
# prod.bundle.yml: services + adapters, minus dev-only *.dev.ts files
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
paths:
|
|
131
|
+
include:
|
|
132
|
+
- '@app/services'
|
|
133
|
+
- ./src/infra
|
|
129
134
|
exclude:
|
|
130
135
|
- '**/*.dev.ts'
|
|
131
136
|
- '**/*.spec.ts'
|
|
@@ -138,7 +143,10 @@ glob:
|
|
|
138
143
|
|
|
139
144
|
```yaml
|
|
140
145
|
# dev.bundle.yml: the *.dev.ts logger replaces the production one, dropped by class name
|
|
141
|
-
|
|
146
|
+
paths:
|
|
147
|
+
include:
|
|
148
|
+
- '@app/services'
|
|
149
|
+
- ./src/infra
|
|
142
150
|
className:
|
|
143
151
|
exclude: JsonLogger
|
|
144
152
|
```
|
|
@@ -150,17 +158,17 @@ folder that build scans.
|
|
|
150
158
|
|
|
151
159
|
A bundle picks its registrations in two stages:
|
|
152
160
|
|
|
153
|
-
1. **`
|
|
161
|
+
1. **`paths`** — decided by path alone, before anything is read. Only files that
|
|
154
162
|
pass are parsed.
|
|
155
163
|
2. **`className`** — decided per class, on the files stage 1 let through.
|
|
156
164
|
|
|
157
|
-
Parsing is where the time goes, so point `
|
|
165
|
+
Parsing is where the time goes, so point `paths` at the folders that hold your
|
|
158
166
|
registrations, and `exclude` what they should not contribute:
|
|
159
167
|
|
|
160
168
|
```json
|
|
161
169
|
{
|
|
162
|
-
"
|
|
163
|
-
"
|
|
170
|
+
"paths": {
|
|
171
|
+
"include": "@app/services",
|
|
164
172
|
"exclude": ["**/*.spec.ts", "**/*.test.ts", "**/__tests__/**", "**/node_modules/**", "**/legacy/**"]
|
|
165
173
|
},
|
|
166
174
|
"className": { "decorators": ["register"] }
|
|
@@ -169,42 +177,42 @@ registrations, and `exclude` what they should not contribute:
|
|
|
169
177
|
|
|
170
178
|
## Selecting files
|
|
171
179
|
|
|
172
|
-
`
|
|
173
|
-
`{ glob, exclude }`. `glob.glob` names the folders a bundle's files come from,
|
|
180
|
+
`paths` is `{ include, exclude }`. `paths.include` names the folders a bundle's files come from,
|
|
174
181
|
and the only ones: what your tsconfig compiles plays no part. It is one folder
|
|
175
182
|
or a list, each relative to the config file (`./src/services`) or a tsconfig
|
|
176
183
|
`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`:
|
|
184
|
+
always scanned with its sub-folders. `paths` is always an object — a folder or a
|
|
185
|
+
list in place of it is an error — and `exclude` may be left out to keep the default:
|
|
181
186
|
|
|
182
187
|
```yaml
|
|
183
|
-
|
|
188
|
+
paths:
|
|
189
|
+
include: ./src/services # one folder
|
|
184
190
|
```
|
|
185
191
|
|
|
186
192
|
```yaml
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
glob: ['@app/services', ./src/infra]
|
|
193
|
-
exclude: '**/*.dev.ts'
|
|
193
|
+
paths:
|
|
194
|
+
include: # or a list
|
|
195
|
+
- '@app/services'
|
|
196
|
+
- ./src/infra
|
|
197
|
+
exclude: '**/*.dev.ts' # a custom exclude
|
|
194
198
|
```
|
|
195
199
|
|
|
196
200
|
Within them, a file is parsed unless it matches **one of** `exclude`. Globs are relative to the config file and `/`-separated; `**`
|
|
197
|
-
spans folders.
|
|
201
|
+
spans folders. Like a folder in `paths.include`, an exclude glob may start with a
|
|
202
|
+
tsconfig `paths` alias: with `"@generated/*": ["./src/.generated/*"]`,
|
|
203
|
+
`@generated/**` reads `src/.generated/**`, and `@generated` (or `@generated/`)
|
|
204
|
+
drops the whole folder. A catch-all `"*"` alias is never applied, so plain globs
|
|
205
|
+
such as `**/*.spec.ts` keep their meaning.
|
|
198
206
|
|
|
199
|
-
| Rule | Default | Meaning
|
|
200
|
-
| --------- | ----------------------------------------- |
|
|
201
|
-
| `
|
|
202
|
-
| `exclude` | test files, `__tests__/`, `node_modules/` | A glob, or a list of them, of files never read; replaces the default when given |
|
|
207
|
+
| Rule | Default | Meaning |
|
|
208
|
+
| --------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
209
|
+
| `include` | — (required) | Folder, or folders, to scan |
|
|
210
|
+
| `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 |
|
|
203
211
|
|
|
204
212
|
A non-empty `exclude` replaces the defaults, so restate the ones you still want:
|
|
205
213
|
|
|
206
214
|
```json
|
|
207
|
-
"
|
|
215
|
+
"paths": {
|
|
208
216
|
"exclude": [
|
|
209
217
|
"**/*.spec.ts",
|
|
210
218
|
"**/*.test.ts",
|
|
@@ -212,7 +220,8 @@ A non-empty `exclude` replaces the defaults, so restate the ones you still want:
|
|
|
212
220
|
"**/*.test.tsx",
|
|
213
221
|
"**/__tests__/**",
|
|
214
222
|
"**/node_modules/**",
|
|
215
|
-
"frontend/api/generated/**"
|
|
223
|
+
"frontend/api/generated/**",
|
|
224
|
+
"@generated"
|
|
216
225
|
]
|
|
217
226
|
}
|
|
218
227
|
```
|
|
@@ -265,7 +274,7 @@ matches only itself, so one list drops a class by name and a family by pattern:
|
|
|
265
274
|
|
|
266
275
|
When the default `export` and `decorators` are all you need, `className`
|
|
267
276
|
itself can be the class-name globs — a string or a list is a shortcut for
|
|
268
|
-
`className.glob
|
|
277
|
+
`className.glob`:
|
|
269
278
|
|
|
270
279
|
```yaml
|
|
271
280
|
className: '*Service' # = className: { glob: '*Service' }
|
|
@@ -299,15 +308,14 @@ The output is plain TypeScript over the public `ts-ioc-container` API:
|
|
|
299
308
|
// src/di/app.bundle.ts
|
|
300
309
|
// Generated by `tic build`. Do not edit by hand.
|
|
301
310
|
// Paths: @app/services, @app/infra
|
|
302
|
-
import { type IContainer, type IContainerModule,
|
|
311
|
+
import { type IContainer, type IContainerModule, Registration } from 'ts-ioc-container';
|
|
303
312
|
import { MemoryLogger } from '@app/infra/logging/MemoryLogger';
|
|
304
313
|
import { Greeter } from '@app/services/Greeter';
|
|
305
314
|
|
|
306
|
-
export const registrations: IRegistration[] = [Registration.fromClass(MemoryLogger), Registration.fromClass(Greeter)];
|
|
307
|
-
|
|
308
315
|
export class AppBundle implements IContainerModule {
|
|
309
316
|
applyTo(container: IContainer): void {
|
|
310
|
-
|
|
317
|
+
container.addRegistration(Registration.fromClass(MemoryLogger));
|
|
318
|
+
container.addRegistration(Registration.fromClass(Greeter));
|
|
311
319
|
}
|
|
312
320
|
}
|
|
313
321
|
```
|
|
@@ -336,5 +344,5 @@ const { content, warnings } = build({ config: 'app.bundle.json' });
|
|
|
336
344
|
writeFileSync('src/di/app.bundle.ts', content);
|
|
337
345
|
|
|
338
346
|
// or config text, as `tic build` reads from stdin
|
|
339
|
-
build({ text: 'name: app\
|
|
347
|
+
build({ text: 'name: app\npaths:\n include: ["@app/services"]\n' });
|
|
340
348
|
```
|
|
@@ -42,21 +42,16 @@ const globs = () => globList('a glob or a non-empty array of globs', 1);
|
|
|
42
42
|
const toList = (value) => (Array.isArray(value) ? value : [value]);
|
|
43
43
|
const toGlobs = (value) => value === undefined ? undefined : toList(value).map(glob_1.globToRegExp);
|
|
44
44
|
const FOLDERS_SCHEMA = zod_1.z.array(nonEmptyString(), expected('a non-empty array')).min(1, expected('a non-empty array'));
|
|
45
|
-
const
|
|
46
|
-
|
|
45
|
+
const PATHS_SCHEMA = zod_1.z
|
|
46
|
+
.strictObject({
|
|
47
|
+
include: zod_1.z
|
|
47
48
|
.union([nonEmptyString(), FOLDERS_SCHEMA], expected('a folder or a non-empty array of folders'))
|
|
48
49
|
.describe('Folder, or folders, to scan, sub-folders included: paths relative to the config file (./src/services) or tsconfig paths aliases (@app/services).'),
|
|
49
50
|
exclude: globList('a glob or an array of globs', 0)
|
|
50
51
|
.default(exports.DEFAULT_EXCLUDE)
|
|
51
|
-
.describe('Glob, or globs, of files never read. Replaces the default when given. A non-empty value that omits a default glob makes `tic build` warn.'),
|
|
52
|
-
}, expected('an object'))
|
|
53
|
-
|
|
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": [...] }.');
|
|
52
|
+
.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
|
+
}, expected('an object with "include"'))
|
|
54
|
+
.describe('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.');
|
|
60
55
|
const CLASS_OBJECT_SCHEMA = zod_1.z.strictObject({
|
|
61
56
|
export: zod_1.z
|
|
62
57
|
.enum(['any', 'named', 'default'], expected('"any", "named" or "default"'))
|
|
@@ -92,12 +87,12 @@ exports.BUNDLE_CONFIG_SCHEMA = zod_1.z.strictObject({
|
|
|
92
87
|
tsconfig: nonEmptyString()
|
|
93
88
|
.optional()
|
|
94
89
|
.meta({ default: exports.DEFAULT_TSCONFIG })
|
|
95
|
-
.describe('The tsconfig whose `paths` aliases
|
|
90
|
+
.describe('The tsconfig whose `paths` aliases paths.include may name and generated imports are written in, and whose module resolution sets the import extension. It adds no files: the bundle scans paths.include alone. Relative to the config file. The default may be absent; a tsconfig named here must exist.'),
|
|
96
91
|
importExtension: zod_1.z
|
|
97
92
|
.string(expected('a string'))
|
|
98
93
|
.optional()
|
|
99
94
|
.describe('Extension of generated imports, e.g. ".js". Inferred from the tsconfig: ".js" under node16/nodenext resolution, none otherwise.'),
|
|
100
|
-
|
|
95
|
+
paths: PATHS_SCHEMA,
|
|
101
96
|
className: CLASSES_SCHEMA.optional(),
|
|
102
97
|
}, expected('an object'));
|
|
103
98
|
function formatPath(segments) {
|
|
@@ -121,15 +116,10 @@ function formatIssue(issue, prefix = []) {
|
|
|
121
116
|
return [`${formatPath(at)}: ${issue.message}`];
|
|
122
117
|
}
|
|
123
118
|
const formatIssues = (error) => error.issues.flatMap((issue) => formatIssue(issue)).join('; ');
|
|
124
|
-
function
|
|
125
|
-
if (typeof glob === 'string' || Array.isArray(glob))
|
|
126
|
-
return { glob, exclude: exports.DEFAULT_EXCLUDE };
|
|
127
|
-
return glob;
|
|
128
|
-
}
|
|
129
|
-
function toGlobSelector(glob) {
|
|
119
|
+
function toPathSelector(paths) {
|
|
130
120
|
return {
|
|
131
|
-
|
|
132
|
-
exclude: toList(
|
|
121
|
+
include: toList(paths.include),
|
|
122
|
+
exclude: toList(paths.exclude),
|
|
133
123
|
};
|
|
134
124
|
}
|
|
135
125
|
function toClassSelector(className) {
|
|
@@ -146,15 +136,15 @@ function toClassSelector(className) {
|
|
|
146
136
|
exclude: toGlobs(exclude),
|
|
147
137
|
};
|
|
148
138
|
}
|
|
149
|
-
function excludeWarnings(
|
|
150
|
-
const exclude = toList(
|
|
139
|
+
function excludeWarnings(paths) {
|
|
140
|
+
const exclude = toList(paths.exclude);
|
|
151
141
|
if (exclude.length === 0)
|
|
152
142
|
return [];
|
|
153
143
|
const missing = exports.DEFAULT_EXCLUDE.filter((glob) => !exclude.includes(glob));
|
|
154
144
|
if (missing.length === 0)
|
|
155
145
|
return [];
|
|
156
146
|
return [
|
|
157
|
-
`
|
|
147
|
+
`paths.exclude replaces the default excludes and omits ${missing.map((glob) => `"${glob}"`).join(', ')}; ` +
|
|
158
148
|
`add them back`,
|
|
159
149
|
];
|
|
160
150
|
}
|
|
@@ -184,7 +174,7 @@ function resolveConfig(content, file) {
|
|
|
184
174
|
const result = exports.BUNDLE_CONFIG_SCHEMA.safeParse(content);
|
|
185
175
|
if (!result.success)
|
|
186
176
|
throw new DomainException_1.TicConfigError(formatIssues(result.error));
|
|
187
|
-
const { name, tsconfig, importExtension,
|
|
177
|
+
const { name, tsconfig, importExtension, paths, className } = result.data;
|
|
188
178
|
const bundleName = name ?? configStem(file);
|
|
189
179
|
if (bundleName === undefined) {
|
|
190
180
|
throw new DomainException_1.TicConfigError(node_path_1.default.basename(file) === exports.STDIN
|
|
@@ -192,7 +182,6 @@ function resolveConfig(content, file) {
|
|
|
192
182
|
: `name: required when the config file is not named <name>${exports.CONFIG_FILE_SUFFIXES.join(' / ')}`);
|
|
193
183
|
}
|
|
194
184
|
const dir = node_path_1.default.dirname(file);
|
|
195
|
-
const globObject = toGlobObject(glob);
|
|
196
185
|
return {
|
|
197
186
|
file,
|
|
198
187
|
dir,
|
|
@@ -200,8 +189,8 @@ function resolveConfig(content, file) {
|
|
|
200
189
|
bundleClassName: toClassName(bundleName),
|
|
201
190
|
tsconfig: { file: node_path_1.default.resolve(dir, tsconfig ?? exports.DEFAULT_TSCONFIG), required: tsconfig !== undefined },
|
|
202
191
|
importExtension,
|
|
203
|
-
|
|
192
|
+
paths: toPathSelector(paths),
|
|
204
193
|
className: toClassSelector(className),
|
|
205
|
-
warnings: excludeWarnings(
|
|
194
|
+
warnings: excludeWarnings(paths),
|
|
206
195
|
};
|
|
207
196
|
}
|
|
@@ -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);
|
|
@@ -6,9 +6,9 @@ exports.emitBundle = emitBundle;
|
|
|
6
6
|
const HandlebarsRenderService_1 = require("../../../services/HandlebarsRenderService");
|
|
7
7
|
exports.GENERATED_HEADER = '// Generated by `tic build`';
|
|
8
8
|
exports.BUNDLE_PROTOCOL = 'Bundle.ts.hbs';
|
|
9
|
-
const RUNTIME_IMPORTS = ['IContainer', 'IContainerModule', '
|
|
9
|
+
const RUNTIME_IMPORTS = ['IContainer', 'IContainerModule', 'Registration'];
|
|
10
10
|
function bundleView({ name, paths, classes }) {
|
|
11
|
-
const taken = new Set([...RUNTIME_IMPORTS, '
|
|
11
|
+
const taken = new Set([...RUNTIME_IMPORTS, 'container', name]);
|
|
12
12
|
const uniqueName = (wanted) => {
|
|
13
13
|
let candidate = wanted;
|
|
14
14
|
for (let n = 2; taken.has(candidate); n++)
|
|
@@ -56,13 +56,13 @@ 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.paths.exclude.flatMap((glob) => paths.resolveGlob(glob, config.dir)).map(glob_1.globToRegExp);
|
|
60
60
|
const isExcluded = (file) => {
|
|
61
61
|
const filename = relative(file);
|
|
62
62
|
return exclude.some((glob) => glob.test(filename));
|
|
63
63
|
};
|
|
64
64
|
const files = new Set();
|
|
65
|
-
for (const folder of config.
|
|
65
|
+
for (const folder of config.paths.include) {
|
|
66
66
|
const dir = paths.resolveNamespace(folder, config.dir);
|
|
67
67
|
for (const file of (0, scan_1.listSourceFiles)(dir, isExcluded))
|
|
68
68
|
files.add(file);
|
|
@@ -81,7 +81,7 @@ let BundleBuilder = class BundleBuilder {
|
|
|
81
81
|
}
|
|
82
82
|
const content = this.renderer.render(emit_1.BUNDLE_PROTOCOL, (0, emit_1.bundleView)({
|
|
83
83
|
name: config.bundleClassName,
|
|
84
|
-
paths: config.
|
|
84
|
+
paths: config.paths.include,
|
|
85
85
|
classes: classes.map((cls) => ({ ...cls, specifier: cls.specifier })),
|
|
86
86
|
}));
|
|
87
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": "6.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.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"typescript": ">=5"
|
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
|
|
18
|
+
"description": "The tsconfig whose `paths` aliases paths.include may name and generated imports are written in, and whose module resolution sets the import extension. It adds no files: the bundle scans paths.include 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
|
},
|
|
@@ -23,74 +23,56 @@
|
|
|
23
23
|
"description": "Extension of generated imports, e.g. \".js\". Inferred from the tsconfig: \".js\" under node16/nodenext resolution, none otherwise.",
|
|
24
24
|
"type": "string"
|
|
25
25
|
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"minItems": 1,
|
|
35
|
-
"type": "array",
|
|
36
|
-
"items": {
|
|
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": {
|
|
55
|
-
"type": "string",
|
|
56
|
-
"minLength": 1
|
|
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)."
|
|
26
|
+
"paths": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"properties": {
|
|
29
|
+
"include": {
|
|
30
|
+
"anyOf": [
|
|
31
|
+
{
|
|
32
|
+
"type": "string",
|
|
33
|
+
"minLength": 1
|
|
61
34
|
},
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
"**/node_modules/**"
|
|
70
|
-
],
|
|
71
|
-
"description": "Glob, or globs, of files never read. 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
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"type": "array",
|
|
79
|
-
"items": {
|
|
80
|
-
"type": "string",
|
|
81
|
-
"minLength": 1
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
]
|
|
35
|
+
{
|
|
36
|
+
"minItems": 1,
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"minLength": 1
|
|
41
|
+
}
|
|
85
42
|
}
|
|
86
|
-
},
|
|
87
|
-
"required": [
|
|
88
|
-
"glob"
|
|
89
43
|
],
|
|
90
|
-
"
|
|
44
|
+
"description": "Folder, or folders, to scan, sub-folders included: paths relative to the config file (./src/services) or tsconfig paths aliases (@app/services)."
|
|
45
|
+
},
|
|
46
|
+
"exclude": {
|
|
47
|
+
"default": [
|
|
48
|
+
"**/*.spec.ts",
|
|
49
|
+
"**/*.test.ts",
|
|
50
|
+
"**/*.spec.tsx",
|
|
51
|
+
"**/*.test.tsx",
|
|
52
|
+
"**/__tests__/**",
|
|
53
|
+
"**/node_modules/**"
|
|
54
|
+
],
|
|
55
|
+
"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.",
|
|
56
|
+
"anyOf": [
|
|
57
|
+
{
|
|
58
|
+
"type": "string",
|
|
59
|
+
"minLength": 1
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"minLength": 1
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
]
|
|
91
69
|
}
|
|
70
|
+
},
|
|
71
|
+
"required": [
|
|
72
|
+
"include"
|
|
92
73
|
],
|
|
93
|
-
"
|
|
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."
|
|
94
76
|
},
|
|
95
77
|
"className": {
|
|
96
78
|
"anyOf": [
|
|
@@ -174,7 +156,7 @@
|
|
|
174
156
|
}
|
|
175
157
|
},
|
|
176
158
|
"required": [
|
|
177
|
-
"
|
|
159
|
+
"paths"
|
|
178
160
|
],
|
|
179
161
|
"additionalProperties": false
|
|
180
162
|
}
|
package/tpl/index.cjs
CHANGED
|
@@ -39,24 +39,13 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
|
|
|
39
39
|
+ ((stack1 = (lookupProperty(helpers,"join")||(depth0 && lookupProperty(depth0,"join"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"named") : depth0),", ",{"name":"join","hash":{},"data":data,"loc":{"start":{"line":5,"column":101},"end":{"line":5,"column":122}}})) != null ? stack1 : "")
|
|
40
40
|
+ " }";
|
|
41
41
|
},"5":function(container,depth0,helpers,partials,data) {
|
|
42
|
-
|
|
43
|
-
if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
|
|
44
|
-
return parent[propertyName];
|
|
45
|
-
}
|
|
46
|
-
return undefined
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
return "export const registrations: IRegistration[] = [\n"
|
|
50
|
-
+ ((stack1 = lookupProperty(helpers,"each").call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"registrations") : depth0),{"name":"each","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":10,"column":0},"end":{"line":12,"column":9}}})) != null ? stack1 : "")
|
|
51
|
-
+ "];\n";
|
|
42
|
+
return "_";
|
|
52
43
|
},"6":function(container,depth0,helpers,partials,data) {
|
|
53
44
|
var stack1;
|
|
54
45
|
|
|
55
|
-
return "
|
|
46
|
+
return " container.addRegistration(Registration.fromClass("
|
|
56
47
|
+ ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : "")
|
|
57
|
-
+ ")
|
|
58
|
-
},"7":function(container,depth0,helpers,partials,data) {
|
|
59
|
-
return "export const registrations: IRegistration[] = [];\n";
|
|
48
|
+
+ "));\n";
|
|
60
49
|
},"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
|
|
61
50
|
var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, lookupProperty = container.lookupProperty || function(parent, propertyName) {
|
|
62
51
|
if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
|
|
@@ -67,13 +56,15 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
|
|
|
67
56
|
|
|
68
57
|
return "// Generated by `tic build`. Do not edit by hand.\n// Paths: "
|
|
69
58
|
+ ((stack1 = (lookupProperty(helpers,"join")||(depth0 && lookupProperty(depth0,"join"))||alias2).call(alias1,(depth0 != null ? lookupProperty(depth0,"paths") : depth0),", ",{"name":"join","hash":{},"data":data,"loc":{"start":{"line":2,"column":10},"end":{"line":2,"column":31}}})) != null ? stack1 : "")
|
|
70
|
-
+ "\nimport { type IContainer, type IContainerModule
|
|
71
|
-
+ ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"registrations") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(0, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":3,"column":
|
|
59
|
+
+ "\nimport { type IContainer, type IContainerModule"
|
|
60
|
+
+ ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"registrations") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(0, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":3,"column":47},"end":{"line":3,"column":96}}})) != null ? stack1 : "")
|
|
72
61
|
+ " } from 'ts-ioc-container';\n"
|
|
73
62
|
+ ((stack1 = lookupProperty(helpers,"each").call(alias1,(depth0 != null ? lookupProperty(depth0,"imports") : depth0),{"name":"each","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":4,"column":0},"end":{"line":6,"column":9}}})) != null ? stack1 : "")
|
|
74
|
-
+ "\n"
|
|
75
|
-
+ ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"registrations") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(7, data, 0),"data":data,"loc":{"start":{"line":8,"column":0},"end":{"line":16,"column":7}}})) != null ? stack1 : "")
|
|
76
63
|
+ "\nexport class "
|
|
77
|
-
+ ((stack1 = ((helper = (helper = lookupProperty(helpers,"name") || (depth0 != null ? lookupProperty(depth0,"name") : depth0)) != null ? helper : alias2),(typeof helper === "function" ? helper.call(alias1,{"name":"name","hash":{},"data":data,"loc":{"start":{"line":
|
|
78
|
-
+ " implements IContainerModule {\n applyTo(
|
|
64
|
+
+ ((stack1 = ((helper = (helper = lookupProperty(helpers,"name") || (depth0 != null ? lookupProperty(depth0,"name") : depth0)) != null ? helper : alias2),(typeof helper === "function" ? helper.call(alias1,{"name":"name","hash":{},"data":data,"loc":{"start":{"line":8,"column":13},"end":{"line":8,"column":23}}}) : helper))) != null ? stack1 : "")
|
|
65
|
+
+ " implements IContainerModule {\n applyTo("
|
|
66
|
+
+ ((stack1 = lookupProperty(helpers,"unless").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"registrations") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"unless","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":9,"column":10},"end":{"line":9,"column":54}}})) != null ? stack1 : "")
|
|
67
|
+
+ "container: IContainer): void {\n"
|
|
68
|
+
+ ((stack1 = lookupProperty(helpers,"each").call(alias1,(depth0 != null ? lookupProperty(depth0,"registrations") : depth0),{"name":"each","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":10,"column":0},"end":{"line":12,"column":9}}})) != null ? stack1 : "")
|
|
69
|
+
+ " }\n}\n";
|
|
79
70
|
},"useData":true});
|
|
@@ -1,30 +1,34 @@
|
|
|
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. `
|
|
4
|
+
* decided by path alone. `include` names the folders the files come from; within them
|
|
5
5
|
* a file is parsed unless it matches one of `exclude`. Globs are relative to the
|
|
6
6
|
* config file and `/`-separated.
|
|
7
7
|
*/
|
|
8
|
-
export interface
|
|
8
|
+
export interface PathSelector {
|
|
9
9
|
/**
|
|
10
10
|
* Folder, or folders, to scan recursively: relative to the config file (`./src/services`),
|
|
11
11
|
* or tsconfig `paths` aliases (`@app/services`).
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
/**
|
|
13
|
+
include: 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
|
+
*/
|
|
15
18
|
exclude?: string | string[];
|
|
16
19
|
}
|
|
17
|
-
/** A {@link
|
|
18
|
-
export interface
|
|
20
|
+
/** A {@link PathSelector} with its defaults filled in. */
|
|
21
|
+
export interface ResolvedPathSelector {
|
|
19
22
|
/** The folders to scan, as written in the config. */
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
include: 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';
|
|
25
29
|
/**
|
|
26
30
|
* Which classes of a parsed file are registered: the second stage of selection,
|
|
27
|
-
* run on the files {@link
|
|
31
|
+
* run on the files {@link PathSelector} let through. A class is selected when
|
|
28
32
|
* it is exported, not abstract, and meets every criterion set here; an empty
|
|
29
33
|
* rule selects every exported class.
|
|
30
34
|
*/
|
|
@@ -70,22 +74,22 @@ export interface BundleConfig {
|
|
|
70
74
|
*/
|
|
71
75
|
name?: string;
|
|
72
76
|
/**
|
|
73
|
-
* The tsconfig whose `paths` aliases `
|
|
77
|
+
* The tsconfig whose `paths` aliases `paths.include` may name and generated imports are
|
|
74
78
|
* written in, and whose `moduleResolution` sets the import extension. It contributes
|
|
75
|
-
* nothing else: the files scanned are `
|
|
79
|
+
* nothing else: the files scanned are `paths.include` alone. Relative to the config file.
|
|
76
80
|
* Default `./tsconfig.json`, which may be absent; a tsconfig named here must exist.
|
|
77
81
|
*/
|
|
78
82
|
tsconfig?: string;
|
|
79
83
|
/** Extension of generated imports. Inferred from the tsconfig's `moduleResolution` when omitted. */
|
|
80
84
|
importExtension?: string;
|
|
81
85
|
/**
|
|
82
|
-
* Which files are parsed: the folders in `
|
|
83
|
-
* `exclude` says otherwise.
|
|
86
|
+
* Which files are parsed: the folders in `paths.include`, minus {@link DEFAULT_EXCLUDE} unless
|
|
87
|
+
* `exclude` says otherwise. Always an object: there is no folder or folder-list shorthand.
|
|
84
88
|
*/
|
|
85
|
-
|
|
89
|
+
paths: PathSelector;
|
|
86
90
|
/**
|
|
87
91
|
* Which classes of a parsed file are registered. Default: every exported class decorated
|
|
88
|
-
* with `@register`. A glob or a list of globs is shorthand for `{ glob }
|
|
92
|
+
* with `@register`. A glob or a list of globs is shorthand for `{ glob }`.
|
|
89
93
|
*/
|
|
90
94
|
className?: string | string[] | ClassSelector;
|
|
91
95
|
}
|
|
@@ -109,9 +113,9 @@ export interface ResolvedConfig {
|
|
|
109
113
|
required: boolean;
|
|
110
114
|
};
|
|
111
115
|
importExtension?: string;
|
|
112
|
-
|
|
116
|
+
paths: ResolvedPathSelector;
|
|
113
117
|
className: ResolvedClassSelector;
|
|
114
|
-
/** Non-fatal problems found while resolving, e.g. a `
|
|
118
|
+
/** Non-fatal problems found while resolving, e.g. a `paths.exclude` that drops a default test glob. */
|
|
115
119
|
warnings: string[];
|
|
116
120
|
}
|
|
117
121
|
/**
|
|
@@ -124,10 +128,10 @@ 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
|
-
|
|
128
|
-
|
|
131
|
+
paths: z.ZodObject<{
|
|
132
|
+
include: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
129
133
|
exclude: z.ZodDefault<z.ZodCustom<string | string[], string | string[]>>;
|
|
130
|
-
}, z.core.$strict
|
|
134
|
+
}, z.core.$strict>;
|
|
131
135
|
className: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodObject<{
|
|
132
136
|
export: z.ZodDefault<z.ZodEnum<{
|
|
133
137
|
default: "default";
|
|
@@ -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,
|
|
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,7 +29,7 @@ export declare const BUNDLE_PROTOCOL = "Bundle.ts.hbs";
|
|
|
29
29
|
*/
|
|
30
30
|
export declare function bundleView({ name, paths, classes }: EmitInput): BundleView;
|
|
31
31
|
/**
|
|
32
|
-
* Renders the generated bundle — static imports,
|
|
32
|
+
* Renders the generated bundle — static imports, and the bundle registering each selected class —
|
|
33
33
|
* from its protocol, `protocols/Bundle.ts.hbs`.
|
|
34
34
|
*/
|
|
35
35
|
export declare function emitBundle(input: EmitInput): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/domain/emit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CACtD;AAED,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAE9D,8CAA8C;AAC9C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACxE,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,8CAA8C;AAC9C,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAI/C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../../lib/features/build/domain/emit.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAE9C,MAAM,WAAW,SAAS;IACxB,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CACtD;AAED,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,gCAAgC,CAAC;AAE9D,8CAA8C;AAC9C,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACxE,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,8CAA8C;AAC9C,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAI/C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,GAAG,UAAU,CAsB1E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAEnD"}
|
|
@@ -26,7 +26,7 @@ export interface BuildResult {
|
|
|
26
26
|
/** The generated bundle. Nothing is written: saving it is the caller's job (`tic build app.bundle.json > src/di/app.bundle.ts`). */
|
|
27
27
|
content: string;
|
|
28
28
|
/**
|
|
29
|
-
* Non-fatal problems found while building, e.g. a `
|
|
29
|
+
* Non-fatal problems found while building, e.g. a `paths.exclude` that drops a default
|
|
30
30
|
* test glob or two selected classes passing the same decorator token.
|
|
31
31
|
*/
|
|
32
32
|
warnings: string[];
|
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
|
|
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';
|
|
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';
|