@ts-ioc-container/bundler 1.4.0 → 2.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/cjm/index.js CHANGED
@@ -1,33 +1,33 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NamespaceNotFoundError = exports.TicConfigError = exports.TicError = exports.globToRegExp = exports.emitBundle = exports.listSourceFiles = exports.findClasses = exports.loadInclusionPredicate = exports.findConventionalPredicate = exports.INCLUSION_CONVENTION = exports.fileTags = exports.byTags = exports.loadExportPredicate = exports.findConventionalExportPredicate = exports.EXPORTS_CONVENTION = exports.ImportPaths = exports.DEFAULT_BUNDLE_NAME = exports.DEFAULT_EXCLUDE = exports.DEFAULT_CONFIG_FILE = exports.resolveConfig = exports.loadConfig = exports.run = exports.build = void 0;
3
+ exports.NamespaceNotFoundError = exports.TicConfigError = exports.TicError = exports.globToRegExp = exports.GENERATED_HEADER = exports.emitBundle = exports.listSourceFiles = exports.isSourceFile = exports.findClasses = exports.loadTsconfig = exports.ImportPaths = exports.toClassName = exports.DEFAULT_DECORATORS = exports.DEFAULT_BUNDLE_NAME = exports.DEFAULT_EXCLUDE = exports.DEFAULT_EXTENDS = exports.findPackageRoot = exports.findConfigFiles = exports.CONFIG_FILE_SUFFIXES = exports.resolveConfig = exports.loadConfig = exports.run = exports.TSCONFIG_FILE = exports.build = void 0;
4
4
  var build_1 = require("./build");
5
5
  Object.defineProperty(exports, "build", { enumerable: true, get: function () { return build_1.build; } });
6
+ Object.defineProperty(exports, "TSCONFIG_FILE", { enumerable: true, get: function () { return build_1.TSCONFIG_FILE; } });
6
7
  var cli_1 = require("./cli");
7
8
  Object.defineProperty(exports, "run", { enumerable: true, get: function () { return cli_1.run; } });
8
9
  var config_1 = require("./config");
9
10
  Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
10
11
  Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return config_1.resolveConfig; } });
11
- Object.defineProperty(exports, "DEFAULT_CONFIG_FILE", { enumerable: true, get: function () { return config_1.DEFAULT_CONFIG_FILE; } });
12
+ Object.defineProperty(exports, "CONFIG_FILE_SUFFIXES", { enumerable: true, get: function () { return config_1.CONFIG_FILE_SUFFIXES; } });
13
+ Object.defineProperty(exports, "findConfigFiles", { enumerable: true, get: function () { return config_1.findConfigFiles; } });
14
+ Object.defineProperty(exports, "findPackageRoot", { enumerable: true, get: function () { return config_1.findPackageRoot; } });
15
+ Object.defineProperty(exports, "DEFAULT_EXTENDS", { enumerable: true, get: function () { return config_1.DEFAULT_EXTENDS; } });
12
16
  Object.defineProperty(exports, "DEFAULT_EXCLUDE", { enumerable: true, get: function () { return config_1.DEFAULT_EXCLUDE; } });
13
17
  Object.defineProperty(exports, "DEFAULT_BUNDLE_NAME", { enumerable: true, get: function () { return config_1.DEFAULT_BUNDLE_NAME; } });
18
+ Object.defineProperty(exports, "DEFAULT_DECORATORS", { enumerable: true, get: function () { return config_1.DEFAULT_DECORATORS; } });
19
+ Object.defineProperty(exports, "toClassName", { enumerable: true, get: function () { return config_1.toClassName; } });
14
20
  var ImportPaths_1 = require("./ImportPaths");
15
21
  Object.defineProperty(exports, "ImportPaths", { enumerable: true, get: function () { return ImportPaths_1.ImportPaths; } });
16
- var exportPredicate_1 = require("./exportPredicate");
17
- Object.defineProperty(exports, "EXPORTS_CONVENTION", { enumerable: true, get: function () { return exportPredicate_1.EXPORTS_CONVENTION; } });
18
- Object.defineProperty(exports, "findConventionalExportPredicate", { enumerable: true, get: function () { return exportPredicate_1.findConventionalExportPredicate; } });
19
- Object.defineProperty(exports, "loadExportPredicate", { enumerable: true, get: function () { return exportPredicate_1.loadExportPredicate; } });
20
- var inclusion_1 = require("./inclusion");
21
- Object.defineProperty(exports, "byTags", { enumerable: true, get: function () { return inclusion_1.byTags; } });
22
- Object.defineProperty(exports, "fileTags", { enumerable: true, get: function () { return inclusion_1.fileTags; } });
23
- Object.defineProperty(exports, "INCLUSION_CONVENTION", { enumerable: true, get: function () { return inclusion_1.INCLUSION_CONVENTION; } });
24
- Object.defineProperty(exports, "findConventionalPredicate", { enumerable: true, get: function () { return inclusion_1.findConventionalPredicate; } });
25
- Object.defineProperty(exports, "loadInclusionPredicate", { enumerable: true, get: function () { return inclusion_1.loadInclusionPredicate; } });
22
+ var tsconfig_1 = require("./tsconfig");
23
+ Object.defineProperty(exports, "loadTsconfig", { enumerable: true, get: function () { return tsconfig_1.loadTsconfig; } });
26
24
  var scan_1 = require("./scan");
27
25
  Object.defineProperty(exports, "findClasses", { enumerable: true, get: function () { return scan_1.findClasses; } });
26
+ Object.defineProperty(exports, "isSourceFile", { enumerable: true, get: function () { return scan_1.isSourceFile; } });
28
27
  Object.defineProperty(exports, "listSourceFiles", { enumerable: true, get: function () { return scan_1.listSourceFiles; } });
29
28
  var emit_1 = require("./emit");
30
29
  Object.defineProperty(exports, "emitBundle", { enumerable: true, get: function () { return emit_1.emitBundle; } });
30
+ Object.defineProperty(exports, "GENERATED_HEADER", { enumerable: true, get: function () { return emit_1.GENERATED_HEADER; } });
31
31
  var glob_1 = require("./glob");
32
32
  Object.defineProperty(exports, "globToRegExp", { enumerable: true, get: function () { return glob_1.globToRegExp; } });
33
33
  var errors_1 = require("./errors");
package/cjm/scan.js CHANGED
@@ -36,6 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.isSourceFile = void 0;
39
40
  exports.listSourceFiles = listSourceFiles;
40
41
  exports.findClasses = findClasses;
41
42
  const node_fs_1 = require("node:fs");
@@ -43,6 +44,8 @@ const node_path_1 = __importDefault(require("node:path"));
43
44
  const ts = __importStar(require("typescript"));
44
45
  const SOURCE_FILE = /\.(tsx?|mts|cts)$/;
45
46
  const DECLARATION_FILE = /\.d\.[mc]?tsx?$/;
47
+ const isSourceFile = (file) => SOURCE_FILE.test(file) && !DECLARATION_FILE.test(file);
48
+ exports.isSourceFile = isSourceFile;
46
49
  function listSourceFiles(dir, recursive, isExcluded) {
47
50
  const files = [];
48
51
  const walk = (current) => {
@@ -52,7 +55,7 @@ function listSourceFiles(dir, recursive, isExcluded) {
52
55
  if (recursive && entry.name !== 'node_modules')
53
56
  walk(full);
54
57
  }
55
- else if (SOURCE_FILE.test(entry.name) && !DECLARATION_FILE.test(entry.name) && !isExcluded(full)) {
58
+ else if ((0, exports.isSourceFile)(entry.name) && !isExcluded(full)) {
56
59
  files.push(full);
57
60
  }
58
61
  }
@@ -143,11 +146,11 @@ function findClasses(file, selector, text = (0, node_fs_1.readFileSync)(file, 'u
143
146
  return false;
144
147
  if (selector.decorators && !selector.decorators.some((name) => decorators.includes(name)))
145
148
  return false;
146
- if (selector.nameGlob && !selector.nameGlob.test(className))
149
+ if (selector.name && !selector.name.test(className))
147
150
  return false;
148
151
  if (selector.excludeClasses?.includes(className))
149
152
  return false;
150
- if (selector.excludeNameGlob?.test(className))
153
+ if (selector.excludeName?.test(className))
151
154
  return false;
152
155
  return true;
153
156
  })
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.loadTsconfig = loadTsconfig;
40
+ const node_fs_1 = require("node:fs");
41
+ const node_path_1 = __importDefault(require("node:path"));
42
+ const ts = __importStar(require("typescript"));
43
+ const errors_1 = require("./errors");
44
+ const ImportPaths_1 = require("./ImportPaths");
45
+ const scan_1 = require("./scan");
46
+ const NO_INPUTS = 18003;
47
+ function commonDir(files) {
48
+ if (files.length === 0)
49
+ return undefined;
50
+ const [first, ...rest] = files.map((file) => node_path_1.default.dirname(file).split(node_path_1.default.sep));
51
+ let length = first.length;
52
+ for (const parts of rest) {
53
+ let i = 0;
54
+ while (i < length && i < parts.length && parts[i] === first[i])
55
+ i++;
56
+ length = i;
57
+ }
58
+ return first.slice(0, length).join(node_path_1.default.sep) || node_path_1.default.sep;
59
+ }
60
+ function loadTsconfig(tsconfig, importExtension) {
61
+ if (!(0, node_fs_1.existsSync)(tsconfig.file)) {
62
+ if (tsconfig.required)
63
+ throw new errors_1.TicConfigError(`tsconfig not found: ${tsconfig.file}`);
64
+ return { importPaths: new ImportPaths_1.ImportPaths([], importExtension ?? '') };
65
+ }
66
+ const { config, error } = ts.readConfigFile(tsconfig.file, ts.sys.readFile);
67
+ const parsed = ts.parseJsonConfigFileContent(config, ts.sys, node_path_1.default.dirname(tsconfig.file), undefined, tsconfig.file);
68
+ const [fatal] = [error, ...parsed.errors].filter((d) => !!d && d.code !== NO_INPUTS);
69
+ if (fatal) {
70
+ throw new errors_1.TicConfigError(`${tsconfig.file}: ${ts.flattenDiagnosticMessageText(fatal.messageText, '\n')}`);
71
+ }
72
+ const fileNames = parsed.fileNames.map((file) => node_path_1.default.resolve(file));
73
+ return {
74
+ importPaths: ImportPaths_1.ImportPaths.fromOptions(parsed.options, tsconfig.file, importExtension),
75
+ fileNames,
76
+ rootDir: parsed.options.rootDir ?? commonDir(fileNames.filter(scan_1.isSourceFile)) ?? node_path_1.default.dirname(tsconfig.file),
77
+ };
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-ioc-container/bundler",
3
- "version": "1.4.0",
3
+ "version": "2.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",
@@ -49,7 +49,8 @@
49
49
  "directory": "packages/bundler"
50
50
  },
51
51
  "dependencies": {
52
- "handlebars": "^4.7.9"
52
+ "handlebars": "^4.7.9",
53
+ "yaml": "^2.8.3"
53
54
  },
54
55
  "peerDependencies": {
55
56
  "typescript": ">=5"
@@ -61,7 +62,7 @@
61
62
  "typescript": "5.8.3",
62
63
  "unplugin-swc": "^1.6.0",
63
64
  "vitest": "^4.1.11",
64
- "ts-ioc-container": "73.1.0"
65
+ "ts-ioc-container": "74.0.0"
65
66
  },
66
67
  "engines": {
67
68
  "node": ">= 18"
package/tic.schema.json CHANGED
@@ -1,162 +1,146 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://github.com/IgorBabkin/ts-ioc-container/tree/main/packages/bundler/tic.schema.json",
4
- "title": "tic.config.json",
5
- "description": "Bundles generated by `tic build` (@ts-ioc-container/bundler). Relative paths resolve against this file's directory.",
4
+ "title": "*.bundle.json / *.bundle.yaml",
5
+ "description": "One bundle generated by `tic build` (@ts-ioc-container/bundler). `tic build` builds every `*.bundle.json` / `*.bundle.yaml` / `*.bundle.yml` at the root of the package it is invoked in, or — with none — one bundle from that package's tsconfig.json with every setting at its default. Relative paths resolve against this file's directory.",
6
6
  "type": "object",
7
- "required": [
8
- "bundles"
9
- ],
10
7
  "additionalProperties": false,
11
8
  "properties": {
12
9
  "$schema": {
13
10
  "type": "string"
14
11
  },
15
- "tsconfig": {
12
+ "output": {
16
13
  "type": "string",
17
- "description": "tsconfig whose `paths` aliases namespaces and imports may use. Default `tsconfig.json`, which may be absent."
14
+ "minLength": 1,
15
+ "description": "The bundle file (convention: *.bundle.ts). Default `<root>/<name>.bundle.ts`: <root> is the tsconfig's rootDir, else the common folder of the files it compiles. Required when there is no tsconfig to extend."
18
16
  },
19
- "importExtension": {
17
+ "name": {
20
18
  "type": "string",
21
- "description": "Extension of generated imports, e.g. \".js\". Inferred from the tsconfig: \".js\" under node16/nodenext resolution, none otherwise."
19
+ "pattern": "^[A-Za-z][\\w-]*$",
20
+ "description": "The bundle's name: letters, digits, \"-\" and \"_\", starting with a letter. Default: this file's stem (production.bundle.json → production), else \"base\". It names the default output (production.bundle.ts) and the generated IContainerModule class (ProductionBundle)."
22
21
  },
23
- "bundles": {
22
+ "tags": {
24
23
  "type": "array",
25
- "minItems": 1,
26
24
  "items": {
27
- "type": "object",
28
- "required": [
29
- "output",
30
- "namespaces"
31
- ],
32
- "additionalProperties": false,
33
- "properties": {
34
- "output": {
35
- "type": "string",
36
- "minLength": 1,
37
- "description": "The bundle file (convention: *.bundle.ts)."
38
- },
39
- "name": {
40
- "type": "string",
41
- "pattern": "^[A-Za-z_$][\\w$]*$",
42
- "default": "Bundle",
43
- "description": "Name of the generated class, an IContainerModule."
44
- },
45
- "namespaces": {
46
- "type": "array",
47
- "minItems": 1,
48
- "description": "Folders to scan: paths relative to this file (./src/services) or tsconfig paths aliases (@app/services).",
49
- "items": {
50
- "oneOf": [
51
- {
52
- "type": "string",
53
- "minLength": 1
54
- },
55
- {
56
- "type": "object",
57
- "required": [
58
- "path"
59
- ],
60
- "additionalProperties": false,
61
- "properties": {
62
- "path": {
63
- "type": "string",
64
- "minLength": 1
65
- },
66
- "recursive": {
67
- "type": "boolean",
68
- "default": true
69
- }
70
- }
71
- }
72
- ]
73
- }
74
- },
75
- "select": {
76
- "type": "object",
77
- "additionalProperties": false,
78
- "description": "How target classes are picked out of a file. A class is selected when it is exported, not abstract, and meets every criterion set here; omit it to register every exported class.",
79
- "properties": {
80
- "export": {
81
- "enum": [
82
- "any",
83
- "named",
84
- "default"
85
- ],
86
- "default": "any",
87
- "description": "Which exports count."
88
- },
89
- "decorators": {
90
- "type": "array",
91
- "minItems": 1,
92
- "items": {
93
- "type": "string",
94
- "minLength": 1
95
- },
96
- "description": "The class must carry one of these decorators, recognised by name (e.g. \"register\", or a composed decorator)."
97
- },
98
- "nameGlob": {
99
- "type": "string",
100
- "minLength": 1,
101
- "description": "Glob the class name must match, e.g. \"*Service\". An anonymous default export is named after its file."
102
- },
103
- "excludeClasses": {
104
- "type": "array",
105
- "minItems": 1,
106
- "items": {
107
- "type": "string",
108
- "minLength": 1
109
- },
110
- "description": "Class names to drop after selection, e.g. one test double sitting next to the real registration in the same file."
111
- },
112
- "excludeNameGlob": {
25
+ "type": "string",
26
+ "minLength": 1
27
+ },
28
+ "description": "Tags associated with the bundle."
29
+ },
30
+ "extends": {
31
+ "type": "string",
32
+ "minLength": 1,
33
+ "default": "./tsconfig.json",
34
+ "description": "The tsconfig this bundle builds on, like a tsconfig's own `extends`: what it compiles (`files` / `include` / `exclude`) is the bundle's file set unless `files.paths` overrides it, and its `paths` aliases and module resolution shape the generated imports. Relative to this file. The default may be absent; a tsconfig named here must exist."
35
+ },
36
+ "importExtension": {
37
+ "type": "string",
38
+ "description": "Extension of generated imports, e.g. \".js\". Inferred from the tsconfig: \".js\" under node16/nodenext resolution, none otherwise."
39
+ },
40
+ "files": {
41
+ "type": "object",
42
+ "additionalProperties": false,
43
+ "description": "Which files this bundle reads and parses — decided by path alone, before parsing. The candidates are what the extended tsconfig compiles, or the folders in `paths` when given. A candidate is parsed when it matches one of `include` and none of `exclude`. Globs are relative to this file. With a file naming convention, `include` keeps every other file unread.",
44
+ "properties": {
45
+ "paths": {
46
+ "type": "array",
47
+ "minItems": 1,
48
+ "description": "Folders to scan instead of the extended tsconfig's file set: paths relative to this file (./src/services) or tsconfig paths aliases (@app/services). Required when there is no tsconfig to extend.",
49
+ "items": {
50
+ "oneOf": [
51
+ {
113
52
  "type": "string",
114
- "minLength": 1,
115
- "description": "Glob the class name must NOT match, e.g. \"*Mock\". An anonymous default export is named after its file."
53
+ "minLength": 1
116
54
  },
117
- "excludeAliases": {
118
- "type": "array",
119
- "minItems": 1,
120
- "items": {
121
- "type": "string",
122
- "minLength": 1
123
- },
124
- "description": "tsconfig paths aliases to drop after selection, e.g. [\"services\"] for a `services/*` (or `@services/*`) alias. A class whose file resolves through one of these aliases is dropped. Names may omit a leading `@` and a trailing `/*`."
55
+ {
56
+ "type": "object",
57
+ "required": [
58
+ "path"
59
+ ],
60
+ "additionalProperties": false,
61
+ "properties": {
62
+ "path": {
63
+ "type": "string",
64
+ "minLength": 1
65
+ },
66
+ "recursive": {
67
+ "type": "boolean",
68
+ "default": true
69
+ }
70
+ }
125
71
  }
126
- }
127
- },
128
- "exclude": {
129
- "type": "array",
130
- "items": {
131
- "type": "string"
132
- },
133
- "default": [
134
- "**/*.spec.ts",
135
- "**/*.test.ts",
136
- "**/*.spec.tsx",
137
- "**/*.test.tsx",
138
- "**/__tests__/**",
139
- "**/node_modules/**"
140
- ],
141
- "description": "Globs, relative to this file, of files never scanned. Replaces the default when given; prefer additionalExclude to add one exclusion without restating the defaults. A non-empty list that omits a default glob makes `tic build` warn."
72
+ ]
73
+ }
74
+ },
75
+ "include": {
76
+ "type": "array",
77
+ "minItems": 1,
78
+ "items": {
79
+ "type": "string",
80
+ "minLength": 1
142
81
  },
143
- "additionalExclude": {
144
- "type": "array",
145
- "items": {
146
- "type": "string"
147
- },
148
- "description": "Globs, relative to this file, of files never scanned, added on top of `exclude` (or the default excludes when `exclude` is omitted)."
82
+ "description": "Globs a file must match one of, e.g. [\"**/*.service.ts\", \"**/*.repository.ts\"]. Default: every source file."
83
+ },
84
+ "exclude": {
85
+ "type": "array",
86
+ "items": {
87
+ "type": "string"
149
88
  },
150
- "include": {
89
+ "default": [
90
+ "**/*.spec.ts",
91
+ "**/*.test.ts",
92
+ "**/*.spec.tsx",
93
+ "**/*.test.tsx",
94
+ "**/__tests__/**",
95
+ "**/node_modules/**"
96
+ ],
97
+ "description": "Globs of files never read. Replaces the default when given. A non-empty list that omits a default glob makes `tic build` warn."
98
+ }
99
+ }
100
+ },
101
+ "classes": {
102
+ "type": "object",
103
+ "additionalProperties": false,
104
+ "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.",
105
+ "properties": {
106
+ "export": {
107
+ "enum": [
108
+ "any",
109
+ "named",
110
+ "default"
111
+ ],
112
+ "default": "any",
113
+ "description": "Which exports count."
114
+ },
115
+ "decorators": {
116
+ "type": "array",
117
+ "items": {
151
118
  "type": "string",
152
- "minLength": 1,
153
- "description": "A file exporting an InclusionPredicate ((context: { filename }) => boolean), relative to this file. Overrides the conventional tic.include.* next to this file. A file takes part only when it matches no `exclude` glob and the predicate returns true."
119
+ "minLength": 1
154
120
  },
155
- "filterExports": {
121
+ "description": "The class must carry one of these decorators, recognised by name (e.g. \"register\", or a composed decorator). Default [\"register\"]; [] requires none.",
122
+ "default": [
123
+ "register"
124
+ ]
125
+ },
126
+ "name": {
127
+ "type": "string",
128
+ "minLength": 1,
129
+ "description": "Glob the class name must match, e.g. \"*Service\". An anonymous default export is named after its file."
130
+ },
131
+ "excludeClasses": {
132
+ "type": "array",
133
+ "minItems": 1,
134
+ "items": {
156
135
  "type": "string",
157
- "minLength": 1,
158
- "description": "A file exporting an ExportPredicate ((context: { filename, exportName, className, isDefault, decorators, tags }) => boolean), relative to this file. Runs on every exported, non-abstract class that passes `select`, right after parsing. Overrides the conventional tic.exports.* next to this file."
159
- }
136
+ "minLength": 1
137
+ },
138
+ "description": "Class names to drop after selection, e.g. one test double sitting next to the real registration in the same file."
139
+ },
140
+ "excludeName": {
141
+ "type": "string",
142
+ "minLength": 1,
143
+ "description": "Glob the class name must NOT match, e.g. \"*Mock\". An anonymous default export is named after its file."
160
144
  }
161
145
  }
162
146
  }
package/tpl/index.cjs CHANGED
@@ -1,7 +1,27 @@
1
1
  var Handlebars = require("handlebars"); var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
2
2
  templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,partials,data) {
3
- return ", Registration";
3
+ var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) {
4
+ if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
5
+ return parent[propertyName];
6
+ }
7
+ return undefined
8
+ };
9
+
10
+ return "// Paths: "
11
+ + ((stack1 = (lookupProperty(helpers,"join")||(depth0 && lookupProperty(depth0,"join"))||container.hooks.helperMissing).call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"paths") : depth0),", ",{"name":"join","hash":{},"data":data,"loc":{"start":{"line":2,"column":23},"end":{"line":2,"column":44}}})) != null ? stack1 : "");
4
12
  },"1":function(container,depth0,helpers,partials,data) {
13
+ var stack1, helper, lookupProperty = container.lookupProperty || function(parent, propertyName) {
14
+ if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
15
+ return parent[propertyName];
16
+ }
17
+ return undefined
18
+ };
19
+
20
+ return "// Files: as compiled by "
21
+ + ((stack1 = ((helper = (helper = lookupProperty(helpers,"tsconfigPath") || (depth0 != null ? lookupProperty(depth0,"tsconfigPath") : depth0)) != null ? helper : container.hooks.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"tsconfigPath","hash":{},"data":data,"loc":{"start":{"line":2,"column":77},"end":{"line":2,"column":95}}}) : helper))) != null ? stack1 : "");
22
+ },"2":function(container,depth0,helpers,partials,data) {
23
+ return ", Registration";
24
+ },"3":function(container,depth0,helpers,partials,data) {
5
25
  var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), lookupProperty = container.lookupProperty || function(parent, propertyName) {
6
26
  if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
7
27
  return parent[propertyName];
@@ -10,12 +30,12 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
10
30
  };
11
31
 
12
32
  return "import "
13
- + ((stack1 = lookupProperty(helpers,"if").call(alias1,(depth0 != null ? lookupProperty(depth0,"defaultName") : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":5,"column":7},"end":{"line":5,"column":79}}})) != null ? stack1 : "")
14
- + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"named") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":5,"column":79},"end":{"line":5,"column":131}}})) != null ? stack1 : "")
33
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,(depth0 != null ? lookupProperty(depth0,"defaultName") : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":5,"column":7},"end":{"line":5,"column":79}}})) != null ? stack1 : "")
34
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"named") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":5,"column":79},"end":{"line":5,"column":131}}})) != null ? stack1 : "")
15
35
  + " from '"
16
36
  + ((stack1 = ((helper = (helper = lookupProperty(helpers,"specifier") || (depth0 != null ? lookupProperty(depth0,"specifier") : depth0)) != null ? helper : container.hooks.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"specifier","hash":{},"data":data,"loc":{"start":{"line":5,"column":138},"end":{"line":5,"column":153}}}) : helper))) != null ? stack1 : "")
17
37
  + "';\n";
18
- },"2":function(container,depth0,helpers,partials,data) {
38
+ },"4":function(container,depth0,helpers,partials,data) {
19
39
  var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), lookupProperty = container.lookupProperty || function(parent, propertyName) {
20
40
  if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
21
41
  return parent[propertyName];
@@ -24,10 +44,10 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
24
44
  };
25
45
 
26
46
  return ((stack1 = ((helper = (helper = lookupProperty(helpers,"defaultName") || (depth0 != null ? lookupProperty(depth0,"defaultName") : depth0)) != null ? helper : container.hooks.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"defaultName","hash":{},"data":data,"loc":{"start":{"line":5,"column":26},"end":{"line":5,"column":43}}}) : helper))) != null ? stack1 : "")
27
- + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"named") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":5,"column":43},"end":{"line":5,"column":72}}})) != null ? stack1 : "");
28
- },"3":function(container,depth0,helpers,partials,data) {
47
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"named") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":5,"column":43},"end":{"line":5,"column":72}}})) != null ? stack1 : "");
48
+ },"5":function(container,depth0,helpers,partials,data) {
29
49
  return ", ";
30
- },"4":function(container,depth0,helpers,partials,data) {
50
+ },"6":function(container,depth0,helpers,partials,data) {
31
51
  var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) {
32
52
  if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
33
53
  return parent[propertyName];
@@ -38,7 +58,7 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
38
58
  return "{ "
39
59
  + ((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
60
  + " }";
41
- },"5":function(container,depth0,helpers,partials,data) {
61
+ },"7":function(container,depth0,helpers,partials,data) {
42
62
  var stack1, lookupProperty = container.lookupProperty || function(parent, propertyName) {
43
63
  if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {
44
64
  return parent[propertyName];
@@ -47,15 +67,15 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
47
67
  };
48
68
 
49
69
  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 : "")
70
+ + ((stack1 = lookupProperty(helpers,"each").call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? lookupProperty(depth0,"registrations") : depth0),{"name":"each","hash":{},"fn":container.program(8, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":10,"column":0},"end":{"line":12,"column":9}}})) != null ? stack1 : "")
51
71
  + "];\n";
52
- },"6":function(container,depth0,helpers,partials,data) {
72
+ },"8":function(container,depth0,helpers,partials,data) {
53
73
  var stack1;
54
74
 
55
75
  return " Registration.fromClass("
56
76
  + ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : "")
57
77
  + "),\n";
58
- },"7":function(container,depth0,helpers,partials,data) {
78
+ },"9":function(container,depth0,helpers,partials,data) {
59
79
  return "export const registrations: IRegistration[] = [];\n";
60
80
  },"compiler":[8,">= 4.3.0"],"main":function(container,depth0,helpers,partials,data) {
61
81
  var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=container.hooks.helperMissing, alias3="function", lookupProperty = container.lookupProperty || function(parent, propertyName) {
@@ -67,14 +87,14 @@ templates["Bundle.ts.hbs"] = template({"0":function(container,depth0,helpers,par
67
87
 
68
88
  return "// Generated by `tic build` from "
69
89
  + ((stack1 = ((helper = (helper = lookupProperty(helpers,"configPath") || (depth0 != null ? lookupProperty(depth0,"configPath") : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"configPath","hash":{},"data":data,"loc":{"start":{"line":1,"column":33},"end":{"line":1,"column":49}}}) : helper))) != null ? stack1 : "")
70
- + ". Do not edit by hand.\n// Namespaces: "
71
- + ((stack1 = (lookupProperty(helpers,"join")||(depth0 && lookupProperty(depth0,"join"))||alias2).call(alias1,(depth0 != null ? lookupProperty(depth0,"namespaces") : depth0),", ",{"name":"join","hash":{},"data":data,"loc":{"start":{"line":2,"column":15},"end":{"line":2,"column":41}}})) != null ? stack1 : "")
90
+ + ". Do not edit by hand.\n"
91
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,(depth0 != null ? lookupProperty(depth0,"paths") : depth0),{"name":"if","hash":{},"fn":container.program(0, data, 0),"inverse":container.program(1, data, 0),"data":data,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":102}}})) != null ? stack1 : "")
72
92
  + "\nimport { type IContainer, type IContainerModule, type IRegistration"
73
- + ((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":67},"end":{"line":3,"column":116}}})) != null ? stack1 : "")
93
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"registrations") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":3,"column":67},"end":{"line":3,"column":116}}})) != null ? stack1 : "")
74
94
  + " } from 'ts-ioc-container';\n"
75
- + ((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 : "")
95
+ + ((stack1 = lookupProperty(helpers,"each").call(alias1,(depth0 != null ? lookupProperty(depth0,"imports") : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data,"loc":{"start":{"line":4,"column":0},"end":{"line":6,"column":9}}})) != null ? stack1 : "")
76
96
  + "\n"
77
- + ((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 : "")
97
+ + ((stack1 = lookupProperty(helpers,"if").call(alias1,((stack1 = (depth0 != null ? lookupProperty(depth0,"registrations") : depth0)) != null ? lookupProperty(stack1,"length") : stack1),{"name":"if","hash":{},"fn":container.program(7, data, 0),"inverse":container.program(9, data, 0),"data":data,"loc":{"start":{"line":8,"column":0},"end":{"line":16,"column":7}}})) != null ? stack1 : "")
78
98
  + "\nexport class "
79
99
  + ((stack1 = ((helper = (helper = lookupProperty(helpers,"name") || (depth0 != null ? lookupProperty(depth0,"name") : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data,"loc":{"start":{"line":18,"column":13},"end":{"line":18,"column":23}}}) : helper))) != null ? stack1 : "")
80
100
  + " implements IContainerModule {\n applyTo(container: IContainer): void {\n for (const registration of registrations) container.addRegistration(registration);\n }\n}\n";