@decohere/workspace 0.0.1-dev.126 → 0.0.1-dev.5
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/README.md +1 -1
- package/package.json +3 -13
- package/src/const.ts +19 -0
- package/src/errors.ts +1 -0
- package/src/factories/config.factory.ts +21 -0
- package/src/factories/find-workspace-root.ts +32 -0
- package/src/factories/project.factory.ts +75 -0
- package/src/factories/workspace.factory.ts +44 -0
- package/{types/src/index.d.ts → src/index.ts} +7 -1
- package/src/models/has-package-json.mixin.ts +30 -0
- package/src/models/has-tsconfig.mixin.ts +48 -0
- package/src/models/package-aliases.ts +130 -0
- package/src/models/package-json.model.ts +231 -0
- package/src/models/project-file-event.ts +9 -0
- package/src/models/project.model.ts +340 -0
- package/src/models/source-extensions.ts +59 -0
- package/src/models/tsconfig.model.ts +81 -0
- package/src/models/workspace-config.type.ts +57 -0
- package/src/models/workspace.model.ts +178 -0
- package/tests/find-workspace-root.spec.ts +30 -0
- package/tests/package-aliases.spec.ts +160 -0
- package/tests/package-json.model.spec.ts +78 -0
- package/tests/project.factory.spec.ts +100 -0
- package/tests/source-extensions.spec.ts +33 -0
- package/tests/workspace.factory.spec.ts +147 -0
- package/LICENSE +0 -15
- package/commonjs/src/const.js +0 -69
- package/commonjs/src/errors.js +0 -12
- package/commonjs/src/factories/config.factory.js +0 -90
- package/commonjs/src/factories/find-workspace-root.js +0 -37
- package/commonjs/src/factories/project.factory.js +0 -73
- package/commonjs/src/factories/workspace.factory.js +0 -50
- package/commonjs/src/index.js +0 -74
- package/commonjs/src/models/has-package-json.mixin.js +0 -50
- package/commonjs/src/models/has-tsconfig.mixin.js +0 -75
- package/commonjs/src/models/package-aliases.js +0 -112
- package/commonjs/src/models/package-json.model.js +0 -202
- package/commonjs/src/models/project-file-event.js +0 -4
- package/commonjs/src/models/project.model.js +0 -316
- package/commonjs/src/models/source-extensions.js +0 -81
- package/commonjs/src/models/tsconfig.model.js +0 -97
- package/commonjs/src/models/workspace-config.type.js +0 -7
- package/commonjs/src/models/workspace.model.js +0 -153
- package/es6/src/const.js +0 -36
- package/es6/src/errors.js +0 -2
- package/es6/src/factories/config.factory.js +0 -34
- package/es6/src/factories/find-workspace-root.js +0 -26
- package/es6/src/factories/project.factory.js +0 -58
- package/es6/src/factories/workspace.factory.js +0 -35
- package/es6/src/index.js +0 -14
- package/es6/src/models/has-package-json.mixin.js +0 -35
- package/es6/src/models/has-tsconfig.mixin.js +0 -60
- package/es6/src/models/package-aliases.js +0 -97
- package/es6/src/models/package-json.model.js +0 -192
- package/es6/src/models/project-file-event.js +0 -1
- package/es6/src/models/project.model.js +0 -301
- package/es6/src/models/source-extensions.js +0 -66
- package/es6/src/models/tsconfig.model.js +0 -74
- package/es6/src/models/workspace-config.type.js +0 -4
- package/es6/src/models/workspace.model.js +0 -143
- package/types/src/const.d.ts +0 -8
- package/types/src/errors.d.ts +0 -2
- package/types/src/factories/config.factory.d.ts +0 -6
- package/types/src/factories/find-workspace-root.d.ts +0 -6
- package/types/src/factories/project.factory.d.ts +0 -8
- package/types/src/factories/workspace.factory.d.ts +0 -9
- package/types/src/models/has-package-json.mixin.d.ts +0 -9
- package/types/src/models/has-tsconfig.mixin.d.ts +0 -11
- package/types/src/models/package-aliases.d.ts +0 -28
- package/types/src/models/package-json.model.d.ts +0 -40
- package/types/src/models/project-file-event.d.ts +0 -9
- package/types/src/models/project.model.d.ts +0 -64
- package/types/src/models/source-extensions.d.ts +0 -22
- package/types/src/models/tsconfig.model.d.ts +0 -11
- package/types/src/models/workspace-config.type.d.ts +0 -52
- package/types/src/models/workspace.model.d.ts +0 -40
|
@@ -1,316 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "Project", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return Project;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nodefs = require("node:fs");
|
|
12
|
-
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
13
|
-
const _caching = require("@decohere/core/caching");
|
|
14
|
-
const _extensibility = require("@decohere/core/extensibility");
|
|
15
|
-
const _io = require("@decohere/devkit/io");
|
|
16
|
-
const _picomatch = /*#__PURE__*/ _interop_require_default(require("picomatch"));
|
|
17
|
-
const _rxjs = require("rxjs");
|
|
18
|
-
const _errors = require("../errors.js");
|
|
19
|
-
const _haspackagejsonmixin = require("./has-package-json.mixin.js");
|
|
20
|
-
const _hastsconfigmixin = require("./has-tsconfig.mixin.js");
|
|
21
|
-
const _packagejsonmodel = require("./package-json.model.js");
|
|
22
|
-
const _sourceextensions = require("./source-extensions.js");
|
|
23
|
-
function _interop_require_default(obj) {
|
|
24
|
-
return obj && obj.__esModule ? obj : {
|
|
25
|
-
default: obj
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
29
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
30
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
32
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
33
|
-
}
|
|
34
|
-
function _ts_metadata(k, v) {
|
|
35
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
36
|
-
}
|
|
37
|
-
class Project extends (0, _extensibility.mixwith)(_haspackagejsonmixin.HasPackageJson, _hastsconfigmixin.HasTsConfig) {
|
|
38
|
-
packageJson;
|
|
39
|
-
#projectFileChangedSubject = new _rxjs.Subject();
|
|
40
|
-
#sourceFiles = new Map();
|
|
41
|
-
#projectConfig;
|
|
42
|
-
#name;
|
|
43
|
-
#projectDirectory;
|
|
44
|
-
#selectedConfiguration;
|
|
45
|
-
#hasLoadedSourceFiles = false;
|
|
46
|
-
#watcher;
|
|
47
|
-
constructor(name, config = {}, selectedConfigurationName){
|
|
48
|
-
super();
|
|
49
|
-
this.#name = name;
|
|
50
|
-
this.#projectDirectory = config?.projectDir ?? name;
|
|
51
|
-
this.#projectConfig = config;
|
|
52
|
-
this.#selectedConfiguration = this.resolveConfiguration(selectedConfigurationName);
|
|
53
|
-
this.packageJson = config.packageJson ?? new _packagejsonmodel.PackageJson();
|
|
54
|
-
}
|
|
55
|
-
get name() {
|
|
56
|
-
return this.#name;
|
|
57
|
-
}
|
|
58
|
-
get isPrivate() {
|
|
59
|
-
return this.packageJson?.private === true;
|
|
60
|
-
}
|
|
61
|
-
toString() {
|
|
62
|
-
return `Project(${this.#name})`;
|
|
63
|
-
}
|
|
64
|
-
get projectDirectory() {
|
|
65
|
-
return this.#projectDirectory;
|
|
66
|
-
}
|
|
67
|
-
get projectRoot() {
|
|
68
|
-
return _nodepath.default.resolve(this.#projectConfig.rootDir ?? "./", this.#projectDirectory);
|
|
69
|
-
}
|
|
70
|
-
get configuration() {
|
|
71
|
-
return this.#selectedConfiguration;
|
|
72
|
-
}
|
|
73
|
-
get packageJsonDirectory() {
|
|
74
|
-
return this.#absoluteProjectDir;
|
|
75
|
-
}
|
|
76
|
-
get tsConfigDirectory() {
|
|
77
|
-
return this.#absoluteProjectDir;
|
|
78
|
-
}
|
|
79
|
-
get fallbackTsConfigDirectory() {
|
|
80
|
-
return this.#projectConfig.rootDir;
|
|
81
|
-
}
|
|
82
|
-
get rootDir() {
|
|
83
|
-
return this.#projectConfig.rootDir ?? "./";
|
|
84
|
-
}
|
|
85
|
-
get #absoluteProjectDir() {
|
|
86
|
-
return this.projectRoot;
|
|
87
|
-
}
|
|
88
|
-
get include() {
|
|
89
|
-
return this.#selectedConfiguration.include ?? this.#projectConfig.include ?? [];
|
|
90
|
-
}
|
|
91
|
-
get ignore() {
|
|
92
|
-
const baseIgnore = this.#projectConfig.ignore ?? [];
|
|
93
|
-
const selectedIgnore = this.#selectedConfiguration.ignore ?? [];
|
|
94
|
-
return [
|
|
95
|
-
...baseIgnore,
|
|
96
|
-
...selectedIgnore
|
|
97
|
-
];
|
|
98
|
-
}
|
|
99
|
-
get copyFiles() {
|
|
100
|
-
const base = this.#projectConfig.copyFiles ?? [];
|
|
101
|
-
const selected = this.#selectedConfiguration.copyFiles ?? [];
|
|
102
|
-
return [
|
|
103
|
-
...base,
|
|
104
|
-
...selected
|
|
105
|
-
];
|
|
106
|
-
}
|
|
107
|
-
get dockerConfig() {
|
|
108
|
-
return this.#projectConfig.docker;
|
|
109
|
-
}
|
|
110
|
-
get uiConfig() {
|
|
111
|
-
return this.#projectConfig.ui;
|
|
112
|
-
}
|
|
113
|
-
get configurations() {
|
|
114
|
-
return this.#projectConfig.configurations ?? [];
|
|
115
|
-
}
|
|
116
|
-
get projectFileChanged$() {
|
|
117
|
-
return this.#projectFileChangedSubject.asObservable();
|
|
118
|
-
}
|
|
119
|
-
async getAllFiles() {
|
|
120
|
-
const files = await (0, _io.findFiles)(this.include, {
|
|
121
|
-
cwd: this.#absoluteProjectDir,
|
|
122
|
-
ignore: this.ignore
|
|
123
|
-
});
|
|
124
|
-
this.#sourceFiles.clear();
|
|
125
|
-
for (const file of files){
|
|
126
|
-
this.#sourceFiles.set(file.relativePath, file);
|
|
127
|
-
}
|
|
128
|
-
this.#hasLoadedSourceFiles = true;
|
|
129
|
-
return files;
|
|
130
|
-
}
|
|
131
|
-
isSourceFile(file) {
|
|
132
|
-
return this.#sourceFiles.has(file.relativePath);
|
|
133
|
-
}
|
|
134
|
-
async watch(configuration) {
|
|
135
|
-
if (this.#watcher != null) {
|
|
136
|
-
return this.#watcher;
|
|
137
|
-
}
|
|
138
|
-
if (!this.#hasLoadedSourceFiles) {
|
|
139
|
-
await this.getAllFiles();
|
|
140
|
-
}
|
|
141
|
-
const watcher = (0, _io.watch)(this.#absoluteProjectDir, {
|
|
142
|
-
ignoreInitial: true
|
|
143
|
-
});
|
|
144
|
-
this.#watcher = watcher;
|
|
145
|
-
watcher.on(_io.WatchEvents.add, (file)=>{
|
|
146
|
-
const fileEx = file;
|
|
147
|
-
this.updateSourceFileCache(_io.WatchEvents.add, fileEx);
|
|
148
|
-
this.#projectFileChangedSubject.next({
|
|
149
|
-
project: this,
|
|
150
|
-
configuration,
|
|
151
|
-
eventName: _io.WatchEvents.add,
|
|
152
|
-
file: fileEx
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
watcher.on(_io.WatchEvents.change, (file)=>{
|
|
156
|
-
const fileEx = file;
|
|
157
|
-
this.updateSourceFileCache(_io.WatchEvents.change, fileEx);
|
|
158
|
-
this.#projectFileChangedSubject.next({
|
|
159
|
-
project: this,
|
|
160
|
-
configuration,
|
|
161
|
-
eventName: _io.WatchEvents.change,
|
|
162
|
-
file: fileEx
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
watcher.on(_io.WatchEvents.unlink, (file)=>{
|
|
166
|
-
const fileEx = file;
|
|
167
|
-
this.updateSourceFileCache(_io.WatchEvents.unlink, fileEx);
|
|
168
|
-
this.#projectFileChangedSubject.next({
|
|
169
|
-
project: this,
|
|
170
|
-
configuration,
|
|
171
|
-
eventName: _io.WatchEvents.unlink,
|
|
172
|
-
file: fileEx
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
return watcher;
|
|
176
|
-
}
|
|
177
|
-
stopWatching() {
|
|
178
|
-
this.#watcher?.close();
|
|
179
|
-
this.#watcher = undefined;
|
|
180
|
-
}
|
|
181
|
-
getRootOut() {
|
|
182
|
-
return _nodepath.default.join(this.getWorkspaceOut(), this.#selectedConfiguration.name);
|
|
183
|
-
}
|
|
184
|
-
getOutDir(target = "") {
|
|
185
|
-
const targetDir = this.#selectedConfiguration.pack ? _nodepath.default.join(this.projectDirectory, target) : _nodepath.default.join(this.projectDirectory);
|
|
186
|
-
const out = _nodepath.default.join(this.getRootOut(), targetDir);
|
|
187
|
-
return out;
|
|
188
|
-
}
|
|
189
|
-
getConfiguration(name) {
|
|
190
|
-
return this.configurations.find((b)=>b.name === name);
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* The package's entry source file. A TypeScript `main` (the workspace convention,
|
|
194
|
-
* `src/index.ts`) is used as written. A `main` or `exports["."]` that describes the published
|
|
195
|
-
* layout (`index.js`, `./es6/src/index.js`) is mapped back to the source it was built from,
|
|
196
|
-
* falling back to `src/index.ts`.
|
|
197
|
-
*/ getSourceEntryPath() {
|
|
198
|
-
const projectRoot = _nodepath.default.join(this.rootDir, this.projectDirectory);
|
|
199
|
-
const main = this.packageJson?.main;
|
|
200
|
-
if (main != null && _sourceextensions.sourceExtensions.isSource(main)) {
|
|
201
|
-
return _nodepath.default.join(projectRoot, main);
|
|
202
|
-
}
|
|
203
|
-
const exports1 = this.packageJson?.exports;
|
|
204
|
-
const root = exports1 == null ? undefined : typeof exports1 === "string" ? exports1 : exports1["."] ?? (Object.keys(exports1).some((k)=>k.startsWith(".")) ? undefined : exports1);
|
|
205
|
-
for (const built of [
|
|
206
|
-
root == null ? undefined : firstExportTarget(root),
|
|
207
|
-
main
|
|
208
|
-
]){
|
|
209
|
-
const fromSrc = built?.match(/(?:^|\/)(src\/.+)$/)?.[1];
|
|
210
|
-
const source = fromSrc == null ? undefined : sourceFileFor(_nodepath.default.join(projectRoot, fromSrc));
|
|
211
|
-
if (source != null) return source;
|
|
212
|
-
}
|
|
213
|
-
const conventional = _nodepath.default.join(projectRoot, "src/index.ts");
|
|
214
|
-
if (main == null || (0, _nodefs.existsSync)(conventional)) return conventional;
|
|
215
|
-
return _nodepath.default.join(projectRoot, main);
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* The source file each subpath in package.json `exports` names, such as `./auth` →
|
|
219
|
-
* `<project>/src/auth/auth.extensions.ts`. Exports point at the release layout
|
|
220
|
-
* (`./es6/src/auth/auth.extensions.js`); the source is the part from `src/`, with its
|
|
221
|
-
* TypeScript extension. Wildcard subpaths, and targets with no such source file, are left out.
|
|
222
|
-
*/ getSourceExports() {
|
|
223
|
-
const exports1 = this.packageJson?.exports;
|
|
224
|
-
if (exports1 == null || typeof exports1 === "string") return {};
|
|
225
|
-
const projectRoot = _nodepath.default.join(this.rootDir, this.projectDirectory);
|
|
226
|
-
const sources = {};
|
|
227
|
-
for (const [subpath, target] of Object.entries(exports1)){
|
|
228
|
-
if (!subpath.startsWith("./") || subpath.includes("*")) continue;
|
|
229
|
-
const built = firstExportTarget(target);
|
|
230
|
-
const fromSrc = built?.match(/(?:^|\/)(src\/.+)$/)?.[1];
|
|
231
|
-
if (fromSrc == null) continue;
|
|
232
|
-
const source = sourceFileFor(_nodepath.default.join(projectRoot, fromSrc));
|
|
233
|
-
if (source != null) sources[subpath] = source;
|
|
234
|
-
}
|
|
235
|
-
return sources;
|
|
236
|
-
}
|
|
237
|
-
[Symbol.dispose]() {
|
|
238
|
-
this.stopWatching();
|
|
239
|
-
}
|
|
240
|
-
getWorkspaceOut() {
|
|
241
|
-
const out = _nodepath.default.join(this.#projectConfig.rootDir ?? "./", this.#projectConfig.outDir);
|
|
242
|
-
return out;
|
|
243
|
-
}
|
|
244
|
-
updateSourceFileCache(eventName, file) {
|
|
245
|
-
if (!this.#hasLoadedSourceFiles) {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
switch(eventName){
|
|
249
|
-
case _io.WatchEvents.unlink:
|
|
250
|
-
this.#sourceFiles.delete(file.relativePath);
|
|
251
|
-
return;
|
|
252
|
-
case _io.WatchEvents.add:
|
|
253
|
-
case _io.WatchEvents.change:
|
|
254
|
-
if (this.matchesSourcePattern(file.relativePath)) {
|
|
255
|
-
this.#sourceFiles.set(file.relativePath, file);
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
this.#sourceFiles.delete(file.relativePath);
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
matchesSourcePattern(relativePath) {
|
|
263
|
-
if (_picomatch.default.isMatch(relativePath, this.ignore)) {
|
|
264
|
-
return false;
|
|
265
|
-
}
|
|
266
|
-
return _picomatch.default.isMatch(relativePath, this.include);
|
|
267
|
-
}
|
|
268
|
-
resolveConfiguration(configurationName) {
|
|
269
|
-
const resolvedConfigurationName = configurationName ?? "debug";
|
|
270
|
-
const configuration = this.configurations.find((c)=>c.name === resolvedConfigurationName);
|
|
271
|
-
if (configuration == null) {
|
|
272
|
-
throw new _errors.WorkspaceConfigurationError(`Configuration "${resolvedConfigurationName}" was not found for project "${this.name}"`);
|
|
273
|
-
}
|
|
274
|
-
return configuration;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
_ts_decorate([
|
|
278
|
-
(0, _caching.memoize)(),
|
|
279
|
-
_ts_metadata("design:type", Function),
|
|
280
|
-
_ts_metadata("design:paramtypes", []),
|
|
281
|
-
_ts_metadata("design:returntype", Promise)
|
|
282
|
-
], Project.prototype, "getAllFiles", null);
|
|
283
|
-
_ts_decorate([
|
|
284
|
-
(0, _caching.cache)(),
|
|
285
|
-
_ts_metadata("design:type", Function),
|
|
286
|
-
_ts_metadata("design:paramtypes", []),
|
|
287
|
-
_ts_metadata("design:returntype", void 0)
|
|
288
|
-
], Project.prototype, "getRootOut", null);
|
|
289
|
-
_ts_decorate([
|
|
290
|
-
(0, _caching.cache)(),
|
|
291
|
-
_ts_metadata("design:type", Function),
|
|
292
|
-
_ts_metadata("design:paramtypes", [
|
|
293
|
-
void 0
|
|
294
|
-
]),
|
|
295
|
-
_ts_metadata("design:returntype", void 0)
|
|
296
|
-
], Project.prototype, "getOutDir", null);
|
|
297
|
-
/** The first path an exports value gives, preferring the conditions that name runtime code. */ function firstExportTarget(value) {
|
|
298
|
-
if (typeof value === "string") return value;
|
|
299
|
-
for (const condition of [
|
|
300
|
-
"import",
|
|
301
|
-
"default",
|
|
302
|
-
"require",
|
|
303
|
-
"node",
|
|
304
|
-
"types"
|
|
305
|
-
]){
|
|
306
|
-
const nested = value[condition];
|
|
307
|
-
if (nested != null) return firstExportTarget(nested);
|
|
308
|
-
}
|
|
309
|
-
return undefined;
|
|
310
|
-
}
|
|
311
|
-
/** The TypeScript source a built or declaration path came from, if it exists. */ function sourceFileFor(builtPath) {
|
|
312
|
-
// A declaration names the file its JavaScript sits next to: `x.d.ts` is `x.js`.
|
|
313
|
-
const declaration = builtPath.match(/^(.*)\.d\.([mc]?)ts$/);
|
|
314
|
-
const built = declaration == null ? builtPath : `${declaration[1]}.${declaration[2]}js`;
|
|
315
|
-
return _sourceextensions.sourceExtensions.candidates(built).find((candidate)=>(0, _nodefs.existsSync)(candidate));
|
|
316
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "sourceExtensions", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return sourceExtensions;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
12
|
-
function _interop_require_default(obj) {
|
|
13
|
-
return obj && obj.__esModule ? obj : {
|
|
14
|
-
default: obj
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
/** TypeScript source extensions a workspace compiles. */ const SOURCE = [
|
|
18
|
-
".ts",
|
|
19
|
-
".tsx",
|
|
20
|
-
".mts",
|
|
21
|
-
".cts"
|
|
22
|
-
];
|
|
23
|
-
/** The sources an import's extension can name: `./a.js` is `a.ts` or `a.tsx`, `./a.mjs` is `a.mts`. */ const SOURCES_FOR = {
|
|
24
|
-
".js": [
|
|
25
|
-
".ts",
|
|
26
|
-
".tsx"
|
|
27
|
-
],
|
|
28
|
-
".jsx": [
|
|
29
|
-
".tsx"
|
|
30
|
-
],
|
|
31
|
-
".mjs": [
|
|
32
|
-
".mts"
|
|
33
|
-
],
|
|
34
|
-
".cjs": [
|
|
35
|
-
".cts"
|
|
36
|
-
],
|
|
37
|
-
"": [
|
|
38
|
-
".ts",
|
|
39
|
-
".tsx"
|
|
40
|
-
]
|
|
41
|
-
};
|
|
42
|
-
/** Whether a path is a TypeScript source (not a declaration file). */ function isSource(file) {
|
|
43
|
-
return SOURCE.some((ext)=>file.endsWith(ext)) && !/\.d\.[mc]?ts$/.test(file);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* The source files a path written in an import (or a built path) could name, most likely first:
|
|
47
|
-
* itself when it is already a source, else the same stem with each matching source extension.
|
|
48
|
-
*/ function candidates(file) {
|
|
49
|
-
if (isSource(file)) return [
|
|
50
|
-
file
|
|
51
|
-
];
|
|
52
|
-
const ext = _nodepath.default.extname(file);
|
|
53
|
-
const known = SOURCES_FOR[ext];
|
|
54
|
-
if (known == null) return [
|
|
55
|
-
`${file}.ts`,
|
|
56
|
-
`${file}.tsx`
|
|
57
|
-
];
|
|
58
|
-
const stem = ext === "" ? file : file.slice(0, -ext.length);
|
|
59
|
-
return known.map((sourceExt)=>`${stem}${sourceExt}`);
|
|
60
|
-
}
|
|
61
|
-
/** The extension a source builds to: `.mts` to `.mjs`, `.cts` to `.cjs`, the rest to `.js`. */ function outputExtension(file) {
|
|
62
|
-
if (file.endsWith(".mts")) return ".mjs";
|
|
63
|
-
if (file.endsWith(".cts")) return ".cjs";
|
|
64
|
-
return ".js";
|
|
65
|
-
}
|
|
66
|
-
/** The path a source builds to: `a.mts` to `a.mjs`, `a.cts` to `a.cjs`, `a.ts` and `a.tsx` to `a.js`. */ function outputPath(file) {
|
|
67
|
-
const ext = _nodepath.default.extname(file);
|
|
68
|
-
const stem = ext === "" ? file : file.slice(0, -ext.length);
|
|
69
|
-
return `${stem}${outputExtension(file)}`;
|
|
70
|
-
}
|
|
71
|
-
/** Whether a source is CommonJS (`.cts`); everything else compiles as an ES module. */ function isCommonJs(file) {
|
|
72
|
-
return file.endsWith(".cts");
|
|
73
|
-
}
|
|
74
|
-
const sourceExtensions = {
|
|
75
|
-
SOURCE,
|
|
76
|
-
isSource,
|
|
77
|
-
candidates,
|
|
78
|
-
outputExtension,
|
|
79
|
-
outputPath,
|
|
80
|
-
isCommonJs
|
|
81
|
-
};
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get DEFAULT_COMPILER_OPTIONS () {
|
|
13
|
-
return DEFAULT_COMPILER_OPTIONS;
|
|
14
|
-
},
|
|
15
|
-
get Tsconfig () {
|
|
16
|
-
return Tsconfig;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
|
|
20
|
-
const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
21
|
-
const _io = require("@decohere/core/io");
|
|
22
|
-
const _typescript = /*#__PURE__*/ _interop_require_default(require("typescript"));
|
|
23
|
-
const _errors = require("../errors.js");
|
|
24
|
-
function _interop_require_default(obj) {
|
|
25
|
-
return obj && obj.__esModule ? obj : {
|
|
26
|
-
default: obj
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
const host = _typescript.default.sys;
|
|
30
|
-
host.readFile = (file)=>{
|
|
31
|
-
return _nodefs.default.readFileSync(file, {
|
|
32
|
-
encoding: "utf8"
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
host.readDirectory = (directoryName)=>{
|
|
36
|
-
return _nodefs.default.readdirSync(directoryName, {
|
|
37
|
-
withFileTypes: true
|
|
38
|
-
}).filter((entry)=>entry.isDirectory()).map((entry)=>entry.name);
|
|
39
|
-
};
|
|
40
|
-
const DEFAULT_COMPILER_OPTIONS = {
|
|
41
|
-
emitDeclarationOnly: true,
|
|
42
|
-
declaration: true,
|
|
43
|
-
baseUrl: "./"
|
|
44
|
-
};
|
|
45
|
-
class Tsconfig {
|
|
46
|
-
static default() {
|
|
47
|
-
return new Tsconfig();
|
|
48
|
-
}
|
|
49
|
-
static async parse(filePath) {
|
|
50
|
-
if (!await _io.io.fileExists(filePath)) {
|
|
51
|
-
throw new _errors.WorkspaceConfigurationError(`TSConfig not found ${filePath}`);
|
|
52
|
-
}
|
|
53
|
-
const configFileText = await _io.io.readFile(filePath);
|
|
54
|
-
const result = _typescript.default.parseConfigFileTextToJson(filePath, configFileText);
|
|
55
|
-
if (result.error) {
|
|
56
|
-
const errorMessage = result.error.messageText.toString();
|
|
57
|
-
throw new _errors.WorkspaceConfigurationError(`Error parsing ${filePath}. ${errorMessage}`);
|
|
58
|
-
}
|
|
59
|
-
const dirName = _nodepath.default.resolve(_nodepath.default.dirname(filePath));
|
|
60
|
-
const configParseResult = _typescript.default.parseJsonConfigFileContent(result.config, host, dirName);
|
|
61
|
-
return new Tsconfig({
|
|
62
|
-
compilerOptions: configParseResult.options,
|
|
63
|
-
errors: configParseResult.errors
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
static parseSync(filePath) {
|
|
67
|
-
if (!Tsconfig.fileExistsSync(filePath)) {
|
|
68
|
-
throw new _errors.WorkspaceConfigurationError(`TSConfig not found ${filePath}`);
|
|
69
|
-
}
|
|
70
|
-
const configFileText = _nodefs.default.readFileSync(filePath, "utf8");
|
|
71
|
-
const result = _typescript.default.parseConfigFileTextToJson(filePath, configFileText);
|
|
72
|
-
if (result.error) {
|
|
73
|
-
const errorMessage = result.error.messageText.toString();
|
|
74
|
-
throw new _errors.WorkspaceConfigurationError(`Error parsing ${filePath}. ${errorMessage}`);
|
|
75
|
-
}
|
|
76
|
-
const dirName = _nodepath.default.resolve(_nodepath.default.dirname(filePath));
|
|
77
|
-
const configParseResult = _typescript.default.parseJsonConfigFileContent(result.config, host, dirName);
|
|
78
|
-
return new Tsconfig({
|
|
79
|
-
compilerOptions: configParseResult.options,
|
|
80
|
-
errors: configParseResult.errors
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
static fileExistsSync(filePath) {
|
|
84
|
-
try {
|
|
85
|
-
return _nodefs.default.statSync(filePath).isFile();
|
|
86
|
-
} catch {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
constructor(data = {
|
|
91
|
-
compilerOptions: DEFAULT_COMPILER_OPTIONS
|
|
92
|
-
}){
|
|
93
|
-
Object.assign(this, data);
|
|
94
|
-
}
|
|
95
|
-
compilerOptions;
|
|
96
|
-
errors;
|
|
97
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "Workspace", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return Workspace;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _decorators = require("@decohere/crucible/decorators");
|
|
12
|
-
const _collections = require("@decohere/core/collections");
|
|
13
|
-
const _extensibility = require("@decohere/core/extensibility");
|
|
14
|
-
const _rxjs = require("rxjs");
|
|
15
|
-
const _errors = require("../errors.js");
|
|
16
|
-
const _haspackagejsonmixin = require("./has-package-json.mixin.js");
|
|
17
|
-
const _hastsconfigmixin = require("./has-tsconfig.mixin.js");
|
|
18
|
-
const _packagealiases = require("./package-aliases.js");
|
|
19
|
-
const _packagejsonmodel = require("./package-json.model.js");
|
|
20
|
-
const _projectmodel = require("./project.model.js");
|
|
21
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
22
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
23
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
24
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
25
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
26
|
-
}
|
|
27
|
-
function _ts_metadata(k, v) {
|
|
28
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
29
|
-
}
|
|
30
|
-
class Workspace extends (0, _extensibility.mixwith)(_haspackagejsonmixin.HasPackageJson, _hastsconfigmixin.HasTsConfig) {
|
|
31
|
-
packageJson;
|
|
32
|
-
#name;
|
|
33
|
-
#config;
|
|
34
|
-
#projectSeeds = [];
|
|
35
|
-
#projectCache = new Map();
|
|
36
|
-
/**
|
|
37
|
-
* Each project's source file paths as a set, so `findProject` is a lookup rather than a scan
|
|
38
|
-
* of every file: the Vitest plugin asks once per transformed file. Keyed by the list
|
|
39
|
-
* `getAllFiles` returns, so a new list (after its cache is flushed) gets a new set.
|
|
40
|
-
*/ #sourcePaths = new WeakMap();
|
|
41
|
-
#projectFileChangedSubject = new _rxjs.Subject();
|
|
42
|
-
#projectWatchSubscriptions = new Map();
|
|
43
|
-
#watchedProjects = [];
|
|
44
|
-
constructor(options = {}){
|
|
45
|
-
super();
|
|
46
|
-
const { packageJson, config, projects } = options;
|
|
47
|
-
this.#name = packageJson?.name ?? "WORKSPACE";
|
|
48
|
-
this.packageJson = packageJson ?? new _packagejsonmodel.PackageJson();
|
|
49
|
-
this.#config = config ?? {};
|
|
50
|
-
this.#projectSeeds = projects ?? [];
|
|
51
|
-
this.validateWorkspace();
|
|
52
|
-
}
|
|
53
|
-
get name() {
|
|
54
|
-
return this.#name;
|
|
55
|
-
}
|
|
56
|
-
get projectSeeds() {
|
|
57
|
-
return this.#projectSeeds;
|
|
58
|
-
}
|
|
59
|
-
getProjects(configuration) {
|
|
60
|
-
const cached = this.#projectCache.get(configuration);
|
|
61
|
-
if (cached != null) {
|
|
62
|
-
return cached;
|
|
63
|
-
}
|
|
64
|
-
const projects = this.#projectSeeds.map((seed)=>new _projectmodel.Project(seed.name, seed.config ?? {}, configuration));
|
|
65
|
-
this.#projectCache.set(configuration, projects);
|
|
66
|
-
return projects;
|
|
67
|
-
}
|
|
68
|
-
get rootDir() {
|
|
69
|
-
return this.#config.rootDir ?? "./";
|
|
70
|
-
}
|
|
71
|
-
get packageJsonDirectory() {
|
|
72
|
-
return this.rootDir;
|
|
73
|
-
}
|
|
74
|
-
get tsConfigDirectory() {
|
|
75
|
-
return this.rootDir;
|
|
76
|
-
}
|
|
77
|
-
get fallbackTsConfigDirectory() {
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Package-name aliases for this configuration: workspace convention, then
|
|
82
|
-
* workspace `tsconfig.json` `paths` overrides. Forge and Flux must use this
|
|
83
|
-
* instead of assembling the map themselves.
|
|
84
|
-
*/ getPackageAliases(configuration) {
|
|
85
|
-
const tsconfig = this.findTsConfigPath() != null ? this.getTsConfigSync() : undefined;
|
|
86
|
-
const baseUrl = typeof tsconfig?.compilerOptions?.baseUrl === "string" && tsconfig.compilerOptions.baseUrl.length > 0 ? tsconfig.compilerOptions.baseUrl : this.rootDir;
|
|
87
|
-
return _packagealiases.packageAliases.build(this.getProjects(configuration), {
|
|
88
|
-
baseUrl,
|
|
89
|
-
tsconfigPaths: tsconfig?.compilerOptions?.paths
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
async watch(configuration) {
|
|
93
|
-
this.stopWatching();
|
|
94
|
-
const projects = this.getProjects(configuration);
|
|
95
|
-
this.#watchedProjects = projects;
|
|
96
|
-
for (const project of projects){
|
|
97
|
-
await project.watch(configuration);
|
|
98
|
-
const subscription = project.projectFileChanged$.subscribe((evt)=>this.#projectFileChangedSubject.next(evt));
|
|
99
|
-
this.#projectWatchSubscriptions.set(project.projectDirectory, subscription);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
stopWatching() {
|
|
103
|
-
for (const subscription of this.#projectWatchSubscriptions.values()){
|
|
104
|
-
subscription.unsubscribe();
|
|
105
|
-
}
|
|
106
|
-
for (const project of this.#watchedProjects){
|
|
107
|
-
project.stopWatching();
|
|
108
|
-
}
|
|
109
|
-
this.#watchedProjects = [];
|
|
110
|
-
this.#projectWatchSubscriptions.clear();
|
|
111
|
-
}
|
|
112
|
-
[Symbol.dispose]() {
|
|
113
|
-
this.stopWatching();
|
|
114
|
-
}
|
|
115
|
-
get projectFileChanged$() {
|
|
116
|
-
return this.#projectFileChangedSubject.asObservable();
|
|
117
|
-
}
|
|
118
|
-
async findProject(filePath, buildConfig) {
|
|
119
|
-
for (const project of this.getProjects(buildConfig)){
|
|
120
|
-
if ((await this.sourcePathsOf(project)).has(filePath)) {
|
|
121
|
-
return project;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return undefined;
|
|
125
|
-
}
|
|
126
|
-
async sourcePathsOf(project) {
|
|
127
|
-
const files = await project.getAllFiles();
|
|
128
|
-
const cached = this.#sourcePaths.get(files);
|
|
129
|
-
if (cached != null) return cached;
|
|
130
|
-
const paths = new Set(files.map((file)=>file.fullPath));
|
|
131
|
-
this.#sourcePaths.set(files, paths);
|
|
132
|
-
return paths;
|
|
133
|
-
}
|
|
134
|
-
validateWorkspace() {
|
|
135
|
-
const errors = this.findDuplicateProjectSeeds(this.#projectSeeds);
|
|
136
|
-
if (errors.length > 0) {
|
|
137
|
-
throw new _errors.WorkspaceConfigurationError(errors.join("\n"));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
findDuplicateProjectSeeds(seeds) {
|
|
141
|
-
const duplicates = _collections.collections.findDuplicatesByKey([
|
|
142
|
-
...seeds
|
|
143
|
-
], "name");
|
|
144
|
-
return duplicates.map(([name, group])=>`Duplicate project name "${name}" found at: ${group.map((seed)=>seed.config?.projectDir ?? name).join(", ")}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
Workspace = _ts_decorate([
|
|
148
|
-
(0, _decorators.injectable)(),
|
|
149
|
-
_ts_metadata("design:type", Function),
|
|
150
|
-
_ts_metadata("design:paramtypes", [
|
|
151
|
-
typeof Partial === "undefined" ? Object : Partial
|
|
152
|
-
])
|
|
153
|
-
], Workspace);
|
package/es6/src/const.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export const TS_CONFIG = "tsconfig.json";
|
|
2
|
-
export const PACKAGE_JSON = "package.json";
|
|
3
|
-
export const NODE_MODULES = "node_modules";
|
|
4
|
-
export const FIXTURES = "__fixtures__";
|
|
5
|
-
export const WORKSPACE_CONFIG = ".decohere.js";
|
|
6
|
-
export const PROJECTS_DIR = "projects";
|
|
7
|
-
export const WorkspaceDefaults = {
|
|
8
|
-
rootDir: "./",
|
|
9
|
-
outDir: "dist",
|
|
10
|
-
includeProjects: [
|
|
11
|
-
`${PROJECTS_DIR}/**/${PACKAGE_JSON}`
|
|
12
|
-
],
|
|
13
|
-
ignoreProjects: [
|
|
14
|
-
`**/${NODE_MODULES}/**`,
|
|
15
|
-
`**/${FIXTURES}/**`,
|
|
16
|
-
"**/dist/**"
|
|
17
|
-
],
|
|
18
|
-
include: [
|
|
19
|
-
"**/*.ts",
|
|
20
|
-
"**/*.tsx",
|
|
21
|
-
"**/*.mts",
|
|
22
|
-
"**/*.cts"
|
|
23
|
-
],
|
|
24
|
-
ignore: [
|
|
25
|
-
"**/*.d.ts",
|
|
26
|
-
"**/*.d.mts",
|
|
27
|
-
"**/*.d.cts",
|
|
28
|
-
`**/${NODE_MODULES}/**`
|
|
29
|
-
],
|
|
30
|
-
copyFiles: [],
|
|
31
|
-
configurations: [
|
|
32
|
-
{
|
|
33
|
-
name: "debug"
|
|
34
|
-
}
|
|
35
|
-
]
|
|
36
|
-
};
|
package/es6/src/errors.js
DELETED