@ts-ioc-container/bundler 5.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 CHANGED
@@ -37,7 +37,9 @@ IContainerModule`, applied with `container.useModule(new AppBundle())`.
37
37
  non-empty list) names the folders scanned, always with their sub-folders —
38
38
  relative to the config file (`./src/services`) or tsconfig aliases
39
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; default: test files, `__tests__/`,
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__/`,
41
43
  `node_modules/`; a non-empty value replaces it, and the build warns if it drops
42
44
  a default). There is no `include`. Files `tic build` generated are never input.
43
45
  - `className: { export, decorators, glob, exclude }` (or `className: '*Service'`
package/README.md CHANGED
@@ -194,12 +194,16 @@ glob: # the object form, for a custom exclude
194
194
  ```
195
195
 
196
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.
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.
198
202
 
199
- | Rule | Default | Meaning |
200
- | --------- | ----------------------------------------- | ------------------------------------------------------------------------------- |
201
- | `glob` | — (required) | Folder, or folders, to scan |
202
- | `exclude` | test files, `__tests__/`, `node_modules/` | A glob, or a list of them, 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 |
203
207
 
204
208
  A non-empty `exclude` replaces the defaults, so restate the ones you still want:
205
209
 
@@ -212,7 +216,8 @@ A non-empty `exclude` replaces the defaults, so restate the ones you still want:
212
216
  "**/*.test.tsx",
213
217
  "**/__tests__/**",
214
218
  "**/node_modules/**",
215
- "frontend/api/generated/**"
219
+ "frontend/api/generated/**",
220
+ "@generated"
216
221
  ]
217
222
  }
218
223
  ```
@@ -48,7 +48,7 @@ const GLOB_OBJECT_SCHEMA = zod_1.z.strictObject({
48
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
49
  exclude: globList('a glob or an array of globs', 0)
50
50
  .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.'),
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
52
  }, expected('an object'));
53
53
  const GLOB_SCHEMA = zod_1.z
54
54
  .union([
@@ -129,7 +129,7 @@ function toGlobObject(glob) {
129
129
  function toGlobSelector(glob) {
130
130
  return {
131
131
  glob: toList(glob.glob),
132
- exclude: toList(glob.exclude).map(glob_1.globToRegExp),
132
+ exclude: toList(glob.exclude),
133
133
  };
134
134
  }
135
135
  function toClassSelector(className) {
@@ -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);
@@ -56,7 +56,7 @@ 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 { exclude } = config.glob;
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
62
  return exclude.some((glob) => glob.test(filename));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-ioc-container/bundler",
3
- "version": "5.0.0",
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
@@ -68,7 +68,7 @@
68
68
  "**/__tests__/**",
69
69
  "**/node_modules/**"
70
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.",
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
72
  "anyOf": [
73
73
  {
74
74
  "type": "string",
@@ -11,14 +11,18 @@ export interface GlobSelector {
11
11
  * or tsconfig `paths` aliases (`@app/services`).
12
12
  */
13
13
  glob: string | string[];
14
- /** Glob, or globs, of files never read. Replaces {@link DEFAULT_EXCLUDE} when given. */
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
20
  /** A {@link GlobSelector} with its defaults filled in and its globs compiled. */
18
21
  export interface ResolvedGlobSelector {
19
22
  /** The folders to scan, as written in the config. */
20
23
  glob: string[];
21
- exclude: RegExp[];
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';
@@ -1 +1 @@
1
- {"version":3,"file":"BuildConfig.d.ts","sourceRoot":"","sources":["../../../lib/features/build/BuildConfig.ts"],"names":[],"mappings":"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"}
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,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,iFAAiF;AACjF,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iHAAiH;IACjH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,iGAAiG;AACjG,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC7B;AAED,kFAAkF;AAClF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oGAAoG;IACpG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,YAAY,CAAC;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,aAAa,CAAC;CAC/C;AAED,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAClD,wFAAwF;AACxF,eAAO,MAAM,kBAAkB,UAAe,CAAC;AAC/C,eAAO,MAAM,eAAe,UAO3B,CAAC;AAEF,wFAAwF;AACxF,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;IACxB,8FAA8F;IAC9F,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,oBAAoB,CAAC;IAC3B,SAAS,EAAE,qBAAqB,CAAC;IACjC,sGAAsG;IACtG,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAqHD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;kBA2BhC,CAAC;AAiFF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,UAAkD,CAAC;AAUpF,qFAAqF;AACrF,eAAO,MAAM,KAAK,MAAM,CAAC;AAEzB,iFAAiF;AACjF,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,KAAG,YAAY,GAAG,SAC6C,CAAC;AAEzG,+CAA+C;AAC/C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAMvE;AAED,iHAAiH;AACjH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,CAyB5E"}
@@ -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;IAWpB,yGAAyG;IACzG,OAAO,CAAC,UAAU;CAanB"}
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"}