@akanjs/devkit 0.9.41 → 0.9.43
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/cjs/src/builder.js +2 -2
- package/cjs/src/commandDecorators/command.js +14 -3
- package/cjs/src/dependencyScanner.js +29 -3
- package/cjs/src/executors.js +170 -214
- package/cjs/src/index.js +3 -1
- package/cjs/src/scanInfo.js +487 -0
- package/esm/src/builder.js +2 -2
- package/esm/src/commandDecorators/command.js +14 -3
- package/esm/src/dependencyScanner.js +29 -3
- package/esm/src/executors.js +171 -219
- package/esm/src/index.js +1 -0
- package/esm/src/scanInfo.js +451 -0
- package/package.json +1 -1
- package/src/dependencyScanner.d.ts +13 -2
- package/src/executors.d.ts +44 -21
- package/src/index.d.ts +1 -0
- package/src/scanInfo.d.ts +93 -0
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { TypeScriptDependencyScanner } from "./dependencyScanner";
|
|
3
|
+
import { AppExecutor, LibExecutor, PkgExecutor } from "./executors";
|
|
4
|
+
const scalarFileTypes = ["constant", "dictionary", "document", "template", "unit", "util", "view", "zone"];
|
|
5
|
+
const serviceFileTypes = [
|
|
6
|
+
"dictionary",
|
|
7
|
+
"service",
|
|
8
|
+
"signal",
|
|
9
|
+
"store",
|
|
10
|
+
"template",
|
|
11
|
+
"unit",
|
|
12
|
+
"util",
|
|
13
|
+
"view",
|
|
14
|
+
"zone"
|
|
15
|
+
];
|
|
16
|
+
const databaseFileTypes = [
|
|
17
|
+
"constant",
|
|
18
|
+
"dictionary",
|
|
19
|
+
"document",
|
|
20
|
+
"service",
|
|
21
|
+
"signal",
|
|
22
|
+
"store",
|
|
23
|
+
"template",
|
|
24
|
+
"unit",
|
|
25
|
+
"util",
|
|
26
|
+
"view",
|
|
27
|
+
"zone"
|
|
28
|
+
];
|
|
29
|
+
class ScanInfo {
|
|
30
|
+
scanResult;
|
|
31
|
+
name;
|
|
32
|
+
scalar = /* @__PURE__ */ new Map();
|
|
33
|
+
service = /* @__PURE__ */ new Map();
|
|
34
|
+
database = /* @__PURE__ */ new Map();
|
|
35
|
+
file = Object.fromEntries(
|
|
36
|
+
databaseFileTypes.map((type) => [
|
|
37
|
+
type,
|
|
38
|
+
{ all: /* @__PURE__ */ new Set(), databases: /* @__PURE__ */ new Set(), services: /* @__PURE__ */ new Set(), scalars: /* @__PURE__ */ new Set() }
|
|
39
|
+
])
|
|
40
|
+
);
|
|
41
|
+
constants = /* @__PURE__ */ new Set();
|
|
42
|
+
dictionaries = /* @__PURE__ */ new Set();
|
|
43
|
+
documents = /* @__PURE__ */ new Set();
|
|
44
|
+
services = /* @__PURE__ */ new Set();
|
|
45
|
+
signals = /* @__PURE__ */ new Set();
|
|
46
|
+
stores = /* @__PURE__ */ new Set();
|
|
47
|
+
templates = /* @__PURE__ */ new Set();
|
|
48
|
+
units = /* @__PURE__ */ new Set();
|
|
49
|
+
utils = /* @__PURE__ */ new Set();
|
|
50
|
+
views = /* @__PURE__ */ new Set();
|
|
51
|
+
zones = /* @__PURE__ */ new Set();
|
|
52
|
+
static async getScanResult(exec) {
|
|
53
|
+
const akanConfig = await exec.getConfig();
|
|
54
|
+
const tsconfig = exec.getTsConfig();
|
|
55
|
+
const rootPackageJson = exec.workspace.getPackageJson();
|
|
56
|
+
const scanner = new TypeScriptDependencyScanner(exec.cwdPath, { tsconfig, rootPackageJson });
|
|
57
|
+
const { pkgDeps, libDeps, npmDeps } = await scanner.getMonorepoDependencies(exec.name);
|
|
58
|
+
const files = {
|
|
59
|
+
constant: { databases: [], scalars: [] },
|
|
60
|
+
dictionary: { databases: [], services: [], scalars: [] },
|
|
61
|
+
document: { databases: [], scalars: [] },
|
|
62
|
+
service: { databases: [], services: [] },
|
|
63
|
+
signal: { databases: [], services: [] },
|
|
64
|
+
store: { databases: [], services: [] },
|
|
65
|
+
template: { databases: [], services: [], scalars: [] },
|
|
66
|
+
unit: { databases: [], services: [], scalars: [] },
|
|
67
|
+
util: { databases: [], services: [], scalars: [] },
|
|
68
|
+
view: { databases: [], services: [], scalars: [] },
|
|
69
|
+
zone: { databases: [], services: [], scalars: [] }
|
|
70
|
+
};
|
|
71
|
+
const [{ dirs: dirnames }, scalarDirs] = await Promise.all([
|
|
72
|
+
exec.getFilesAndDirs("lib"),
|
|
73
|
+
exec.readdir("lib/__scalar")
|
|
74
|
+
]);
|
|
75
|
+
const databaseDirs = [];
|
|
76
|
+
const serviceDirs = [];
|
|
77
|
+
dirnames.forEach((name) => {
|
|
78
|
+
if (name.startsWith("_")) {
|
|
79
|
+
if (name.startsWith("__"))
|
|
80
|
+
return;
|
|
81
|
+
else
|
|
82
|
+
serviceDirs.push(name);
|
|
83
|
+
} else
|
|
84
|
+
databaseDirs.push(name);
|
|
85
|
+
});
|
|
86
|
+
await Promise.all([
|
|
87
|
+
...databaseDirs.map(async (name) => {
|
|
88
|
+
const filenames = await exec.readdir(path.join("lib", name));
|
|
89
|
+
filenames.forEach((filename) => {
|
|
90
|
+
if (filename.endsWith(".constant.ts"))
|
|
91
|
+
files.constant.databases.push(name);
|
|
92
|
+
else if (filename.endsWith(".dictionary.ts"))
|
|
93
|
+
files.dictionary.databases.push(name);
|
|
94
|
+
else if (filename.endsWith(".document.ts"))
|
|
95
|
+
files.document.databases.push(name);
|
|
96
|
+
else if (filename.endsWith(".service.ts"))
|
|
97
|
+
files.service.databases.push(name);
|
|
98
|
+
else if (filename.endsWith(".signal.ts"))
|
|
99
|
+
files.signal.databases.push(name);
|
|
100
|
+
else if (filename.endsWith(".store.ts"))
|
|
101
|
+
files.store.databases.push(name);
|
|
102
|
+
else if (filename.endsWith(".Template.tsx"))
|
|
103
|
+
files.template.databases.push(name);
|
|
104
|
+
else if (filename.endsWith(".Unit.tsx"))
|
|
105
|
+
files.unit.databases.push(name);
|
|
106
|
+
else if (filename.endsWith(".Util.tsx"))
|
|
107
|
+
files.util.databases.push(name);
|
|
108
|
+
else if (filename.endsWith(".View.tsx"))
|
|
109
|
+
files.view.databases.push(name);
|
|
110
|
+
else if (filename.endsWith(".Zone.tsx"))
|
|
111
|
+
files.zone.databases.push(name);
|
|
112
|
+
});
|
|
113
|
+
}),
|
|
114
|
+
...serviceDirs.map(async (dirname) => {
|
|
115
|
+
const name = dirname.slice(1);
|
|
116
|
+
const filenames = await exec.readdir(path.join("lib", dirname));
|
|
117
|
+
filenames.forEach((filename) => {
|
|
118
|
+
if (filename.endsWith(".dictionary.ts"))
|
|
119
|
+
files.dictionary.services.push(name);
|
|
120
|
+
else if (filename.endsWith(".service.ts"))
|
|
121
|
+
files.service.services.push(name);
|
|
122
|
+
else if (filename.endsWith(".signal.ts"))
|
|
123
|
+
files.signal.services.push(name);
|
|
124
|
+
else if (filename.endsWith(".store.ts"))
|
|
125
|
+
files.store.services.push(name);
|
|
126
|
+
else if (filename.endsWith(".Template.tsx"))
|
|
127
|
+
files.template.services.push(name);
|
|
128
|
+
else if (filename.endsWith(".Unit.tsx"))
|
|
129
|
+
files.unit.services.push(name);
|
|
130
|
+
else if (filename.endsWith(".Util.tsx"))
|
|
131
|
+
files.util.services.push(name);
|
|
132
|
+
else if (filename.endsWith(".View.tsx"))
|
|
133
|
+
files.view.services.push(name);
|
|
134
|
+
else if (filename.endsWith(".Zone.tsx"))
|
|
135
|
+
files.zone.services.push(name);
|
|
136
|
+
});
|
|
137
|
+
}),
|
|
138
|
+
...scalarDirs.map(async (name) => {
|
|
139
|
+
const filenames = await exec.readdir(path.join("lib/__scalar", name));
|
|
140
|
+
filenames.forEach((filename) => {
|
|
141
|
+
if (filename.endsWith(".constant.ts"))
|
|
142
|
+
files.constant.scalars.push(name);
|
|
143
|
+
else if (filename.endsWith(".dictionary.ts"))
|
|
144
|
+
files.dictionary.scalars.push(name);
|
|
145
|
+
else if (filename.endsWith(".document.ts"))
|
|
146
|
+
files.document.scalars.push(name);
|
|
147
|
+
else if (filename.endsWith(".Template.tsx"))
|
|
148
|
+
files.template.scalars.push(name);
|
|
149
|
+
else if (filename.endsWith(".Unit.tsx"))
|
|
150
|
+
files.unit.scalars.push(name);
|
|
151
|
+
else if (filename.endsWith(".Util.tsx"))
|
|
152
|
+
files.util.scalars.push(name);
|
|
153
|
+
else if (filename.endsWith(".View.tsx"))
|
|
154
|
+
files.view.scalars.push(name);
|
|
155
|
+
else if (filename.endsWith(".Zone.tsx"))
|
|
156
|
+
files.zone.scalars.push(name);
|
|
157
|
+
});
|
|
158
|
+
})
|
|
159
|
+
]);
|
|
160
|
+
const missingLibDeps = [];
|
|
161
|
+
libDeps.forEach((libName) => {
|
|
162
|
+
if (!akanConfig.libs.includes(libName))
|
|
163
|
+
missingLibDeps.push(libName);
|
|
164
|
+
});
|
|
165
|
+
if (missingLibDeps.length)
|
|
166
|
+
throw new Error(
|
|
167
|
+
`Missing libs: ${missingLibDeps.join(", ")}, add these dependencies in akan.config.ts as { libs: [...other deps, ${missingLibDeps.join(", ")}] }`
|
|
168
|
+
);
|
|
169
|
+
const scanResult = {
|
|
170
|
+
name: exec.name,
|
|
171
|
+
type: exec.type,
|
|
172
|
+
repoName: exec.workspace.repoName,
|
|
173
|
+
serveDomain: exec.workspace.getBaseDevEnv().serveDomain,
|
|
174
|
+
akanConfig,
|
|
175
|
+
files,
|
|
176
|
+
libDeps,
|
|
177
|
+
pkgDeps,
|
|
178
|
+
dependencies: npmDeps.filter((dep) => !dep.startsWith("@akanjs"))
|
|
179
|
+
};
|
|
180
|
+
return scanResult;
|
|
181
|
+
}
|
|
182
|
+
constructor(scanResult) {
|
|
183
|
+
this.name = scanResult.name;
|
|
184
|
+
this.scanResult = scanResult;
|
|
185
|
+
Object.entries(scanResult.files).forEach(
|
|
186
|
+
([key, value]) => {
|
|
187
|
+
const { databases, services, scalars } = value;
|
|
188
|
+
databases.forEach((modelName) => {
|
|
189
|
+
const model = this.database.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
190
|
+
model.add(key);
|
|
191
|
+
this.database.set(modelName, model);
|
|
192
|
+
this.file[key].all.add(modelName);
|
|
193
|
+
this.file[key].databases.add(modelName);
|
|
194
|
+
});
|
|
195
|
+
services?.forEach((serviceName) => {
|
|
196
|
+
const service = this.service.get(serviceName) ?? /* @__PURE__ */ new Set();
|
|
197
|
+
service.add(key);
|
|
198
|
+
this.service.set(serviceName, service);
|
|
199
|
+
this.file[key].all.add(serviceName);
|
|
200
|
+
this.file[key].services.add(serviceName);
|
|
201
|
+
});
|
|
202
|
+
scalars?.forEach((scalarName) => {
|
|
203
|
+
const scalar = this.scalar.get(scalarName) ?? /* @__PURE__ */ new Set();
|
|
204
|
+
scalar.add(key);
|
|
205
|
+
this.scalar.set(scalarName, scalar);
|
|
206
|
+
this.file[key].all.add(scalarName);
|
|
207
|
+
this.file[key].scalars.add(scalarName);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
getScanResult() {
|
|
213
|
+
return this.scanResult;
|
|
214
|
+
}
|
|
215
|
+
getDatabaseModules() {
|
|
216
|
+
return [...this.database.keys()];
|
|
217
|
+
}
|
|
218
|
+
getServiceModules() {
|
|
219
|
+
return [...this.service.keys()];
|
|
220
|
+
}
|
|
221
|
+
getScalarModules() {
|
|
222
|
+
return [...this.scalar.keys()];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
class AppInfo extends ScanInfo {
|
|
226
|
+
type = "app";
|
|
227
|
+
exec;
|
|
228
|
+
akanConfig;
|
|
229
|
+
static appInfos = /* @__PURE__ */ new Map();
|
|
230
|
+
static async fromExecutor(exec, options = {}) {
|
|
231
|
+
const existingAppInfo = this.appInfos.get(exec.name);
|
|
232
|
+
if (existingAppInfo && !options.refresh)
|
|
233
|
+
return existingAppInfo;
|
|
234
|
+
const scanResult = await super.getScanResult(exec);
|
|
235
|
+
await Promise.all(
|
|
236
|
+
scanResult.libDeps.map(async (libName) => {
|
|
237
|
+
LibInfo.loadedLibs.add(libName);
|
|
238
|
+
const libExecutor = LibExecutor.from(exec, libName);
|
|
239
|
+
LibInfo.libInfos.set(libName, await LibInfo.fromExecutor(libExecutor));
|
|
240
|
+
})
|
|
241
|
+
);
|
|
242
|
+
const appInfo = new AppInfo(exec, scanResult);
|
|
243
|
+
this.appInfos.set(exec.name, appInfo);
|
|
244
|
+
return appInfo;
|
|
245
|
+
}
|
|
246
|
+
constructor(exec, scanResult) {
|
|
247
|
+
super(scanResult);
|
|
248
|
+
this.exec = exec;
|
|
249
|
+
this.akanConfig = scanResult.akanConfig;
|
|
250
|
+
}
|
|
251
|
+
getScanResult() {
|
|
252
|
+
return this.scanResult;
|
|
253
|
+
}
|
|
254
|
+
#sortedLibs = null;
|
|
255
|
+
#getSortedLibs() {
|
|
256
|
+
if (this.#sortedLibs)
|
|
257
|
+
return this.#sortedLibs;
|
|
258
|
+
const libIndices = LibInfo.getSortedLibIndices();
|
|
259
|
+
this.#sortedLibs = this.akanConfig.libs.sort((libNameA, libNameB) => {
|
|
260
|
+
const indexA = libIndices.get(libNameA);
|
|
261
|
+
const indexB = libIndices.get(libNameB);
|
|
262
|
+
if (indexA === void 0 || indexB === void 0)
|
|
263
|
+
throw new Error(`LibInfo not found: ${libNameA} or ${libNameB}`);
|
|
264
|
+
return indexA - indexB;
|
|
265
|
+
});
|
|
266
|
+
return this.#sortedLibs;
|
|
267
|
+
}
|
|
268
|
+
getLibs() {
|
|
269
|
+
return this.#getSortedLibs();
|
|
270
|
+
}
|
|
271
|
+
getLibInfo(libName) {
|
|
272
|
+
const libSet = new Set(this.#getSortedLibs());
|
|
273
|
+
if (!libSet.has(libName))
|
|
274
|
+
throw new Error(`LibInfo is invalid: ${libName}`);
|
|
275
|
+
return LibInfo.libInfos.get(libName);
|
|
276
|
+
}
|
|
277
|
+
getLibInfos() {
|
|
278
|
+
return new Map(
|
|
279
|
+
this.#getSortedLibs().map((libName) => {
|
|
280
|
+
const libInfo = LibInfo.libInfos.get(libName);
|
|
281
|
+
if (!libInfo)
|
|
282
|
+
throw new Error(`LibInfo not found: ${libName}`);
|
|
283
|
+
return [libName, libInfo];
|
|
284
|
+
})
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
class LibInfo extends ScanInfo {
|
|
289
|
+
type = "lib";
|
|
290
|
+
exec;
|
|
291
|
+
akanConfig;
|
|
292
|
+
static loadedLibs = /* @__PURE__ */ new Set();
|
|
293
|
+
static libInfos = /* @__PURE__ */ new Map();
|
|
294
|
+
static #sortedLibIndices = null;
|
|
295
|
+
static getSortedLibIndices() {
|
|
296
|
+
if (this.#sortedLibIndices)
|
|
297
|
+
return this.#sortedLibIndices;
|
|
298
|
+
this.#sortedLibIndices = new Map(
|
|
299
|
+
[...this.libInfos.entries()].sort(([_, libInfoA], [__, libInfoB]) => libInfoA.akanConfig.libs.includes(libInfoB.name) ? 1 : -1).map(([libName], index) => [libName, index])
|
|
300
|
+
);
|
|
301
|
+
return this.#sortedLibIndices;
|
|
302
|
+
}
|
|
303
|
+
static async fromExecutor(exec, { refresh } = {}) {
|
|
304
|
+
const existingLibInfo = this.libInfos.get(exec.name);
|
|
305
|
+
if (existingLibInfo && !refresh)
|
|
306
|
+
return existingLibInfo;
|
|
307
|
+
const scanResult = await super.getScanResult(exec);
|
|
308
|
+
await Promise.all(
|
|
309
|
+
scanResult.libDeps.filter((libName) => !this.loadedLibs.has(libName)).map(async (libName) => {
|
|
310
|
+
this.loadedLibs.add(libName);
|
|
311
|
+
this.libInfos.set(libName, await LibInfo.fromExecutor(exec));
|
|
312
|
+
})
|
|
313
|
+
);
|
|
314
|
+
const libInfo = new LibInfo(exec, scanResult);
|
|
315
|
+
this.libInfos.set(exec.name, libInfo);
|
|
316
|
+
this.#sortedLibIndices = null;
|
|
317
|
+
return libInfo;
|
|
318
|
+
}
|
|
319
|
+
constructor(exec, scanResult) {
|
|
320
|
+
super(scanResult);
|
|
321
|
+
this.exec = exec;
|
|
322
|
+
this.akanConfig = scanResult.akanConfig;
|
|
323
|
+
}
|
|
324
|
+
getScanResult() {
|
|
325
|
+
return this.scanResult;
|
|
326
|
+
}
|
|
327
|
+
#sortedLibs = null;
|
|
328
|
+
#getSortedLibs() {
|
|
329
|
+
if (this.#sortedLibs)
|
|
330
|
+
return this.#sortedLibs;
|
|
331
|
+
const libs = LibInfo.getSortedLibIndices();
|
|
332
|
+
this.#sortedLibs = this.akanConfig.libs.sort((libNameA, libNameB) => {
|
|
333
|
+
const indexA = libs.get(libNameA);
|
|
334
|
+
const indexB = libs.get(libNameB);
|
|
335
|
+
if (indexA === void 0 || indexB === void 0)
|
|
336
|
+
throw new Error(`LibInfo not found: ${libNameA} or ${libNameB}`);
|
|
337
|
+
return indexA - indexB;
|
|
338
|
+
});
|
|
339
|
+
return this.#sortedLibs;
|
|
340
|
+
}
|
|
341
|
+
getLibs() {
|
|
342
|
+
return this.#getSortedLibs();
|
|
343
|
+
}
|
|
344
|
+
getLibInfo(libName) {
|
|
345
|
+
if (!this.getScanResult().akanConfig.libs.includes(libName))
|
|
346
|
+
return void 0;
|
|
347
|
+
const libSet = new Set(this.#getSortedLibs());
|
|
348
|
+
if (!libSet.has(libName))
|
|
349
|
+
throw new Error(`LibInfo is invalid: ${libName}`);
|
|
350
|
+
return LibInfo.libInfos.get(libName);
|
|
351
|
+
}
|
|
352
|
+
getLibInfos() {
|
|
353
|
+
return new Map(
|
|
354
|
+
this.#getSortedLibs().map((libName) => {
|
|
355
|
+
const libInfo = LibInfo.libInfos.get(libName);
|
|
356
|
+
if (!libInfo)
|
|
357
|
+
throw new Error(`LibInfo not found: ${libName}`);
|
|
358
|
+
return [libName, libInfo];
|
|
359
|
+
})
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
class PkgInfo {
|
|
364
|
+
exec;
|
|
365
|
+
name;
|
|
366
|
+
scanResult;
|
|
367
|
+
static async getScanResult(exec) {
|
|
368
|
+
const tsconfig = exec.getTsConfig();
|
|
369
|
+
const rootPackageJson = exec.workspace.getPackageJson();
|
|
370
|
+
const scanner = new TypeScriptDependencyScanner(exec.cwdPath, { tsconfig, rootPackageJson });
|
|
371
|
+
const npmSet = new Set(Object.keys({ ...rootPackageJson.dependencies, ...rootPackageJson.devDependencies }));
|
|
372
|
+
const pkgPathSet = new Set(
|
|
373
|
+
Object.keys(tsconfig.compilerOptions.paths ?? {}).filter((path2) => tsconfig.compilerOptions.paths?.[path2]?.some((resolve) => resolve.startsWith("pkgs/"))).map((path2) => path2.replace("/*", ""))
|
|
374
|
+
);
|
|
375
|
+
const [npmDepSet, pkgPathDepSet] = await scanner.getImportSets([npmSet, pkgPathSet]);
|
|
376
|
+
const pkgDeps = [...pkgPathDepSet].map((path2) => {
|
|
377
|
+
const pathSplitLength = path2.split("/").length;
|
|
378
|
+
return (tsconfig.compilerOptions.paths?.[path2]?.[0] ?? "*").split("/").slice(1, 1 + pathSplitLength).join("/");
|
|
379
|
+
}).filter((pkg) => pkg !== this.name);
|
|
380
|
+
const pkgScanResult = {
|
|
381
|
+
name: this.name,
|
|
382
|
+
pkgDeps,
|
|
383
|
+
dependencies: [...npmDepSet]
|
|
384
|
+
};
|
|
385
|
+
return pkgScanResult;
|
|
386
|
+
}
|
|
387
|
+
static #pkgInfos = /* @__PURE__ */ new Map();
|
|
388
|
+
static async fromExecutor(exec, options = {}) {
|
|
389
|
+
const existingPkgInfo = this.#pkgInfos.get(exec.name);
|
|
390
|
+
if (existingPkgInfo && !options.refresh)
|
|
391
|
+
return existingPkgInfo;
|
|
392
|
+
const scanResult = await this.getScanResult(exec);
|
|
393
|
+
const pkgInfo = new PkgInfo(exec, scanResult);
|
|
394
|
+
this.#pkgInfos.set(exec.name, pkgInfo);
|
|
395
|
+
return pkgInfo;
|
|
396
|
+
}
|
|
397
|
+
constructor(exec, scanResult) {
|
|
398
|
+
this.exec = exec;
|
|
399
|
+
this.name = exec.name;
|
|
400
|
+
this.scanResult = scanResult;
|
|
401
|
+
}
|
|
402
|
+
getScanResult() {
|
|
403
|
+
return this.scanResult;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
class WorkspaceInfo {
|
|
407
|
+
constructor(appInfos = /* @__PURE__ */ new Map(), libInfos = /* @__PURE__ */ new Map(), pkgInfos = /* @__PURE__ */ new Map()) {
|
|
408
|
+
this.appInfos = appInfos;
|
|
409
|
+
this.libInfos = libInfos;
|
|
410
|
+
this.pkgInfos = pkgInfos;
|
|
411
|
+
}
|
|
412
|
+
static #workspaceInfos = /* @__PURE__ */ new Map();
|
|
413
|
+
static async fromExecutor(exec, options = {}) {
|
|
414
|
+
const existingWorkspaceInfo = this.#workspaceInfos.get(exec.name);
|
|
415
|
+
if (existingWorkspaceInfo && !options.refresh)
|
|
416
|
+
return existingWorkspaceInfo;
|
|
417
|
+
const [appNames, libNames, pkgNames] = await Promise.all([exec.getApps(), exec.getLibs(), exec.getPkgs()]);
|
|
418
|
+
const [appInfos, libInfos, pkgInfos] = await Promise.all([
|
|
419
|
+
Promise.all(
|
|
420
|
+
appNames.map(async (appName) => {
|
|
421
|
+
const app = AppExecutor.from(exec, appName);
|
|
422
|
+
return await app.scan();
|
|
423
|
+
})
|
|
424
|
+
),
|
|
425
|
+
Promise.all(
|
|
426
|
+
libNames.map(async (libName) => {
|
|
427
|
+
const lib = LibExecutor.from(exec, libName);
|
|
428
|
+
return await lib.scan();
|
|
429
|
+
})
|
|
430
|
+
),
|
|
431
|
+
Promise.all(
|
|
432
|
+
pkgNames.map(async (pkgName) => {
|
|
433
|
+
return await PkgExecutor.from(exec, pkgName).scan();
|
|
434
|
+
})
|
|
435
|
+
)
|
|
436
|
+
]);
|
|
437
|
+
const workspaceInfo = new WorkspaceInfo(
|
|
438
|
+
new Map(appInfos.map((app) => [app.exec.name, app])),
|
|
439
|
+
new Map(libInfos.map((lib) => [lib.exec.name, lib])),
|
|
440
|
+
new Map(pkgInfos.map((pkg) => [pkg.exec.name, pkg]))
|
|
441
|
+
);
|
|
442
|
+
this.#workspaceInfos.set(exec.name, workspaceInfo);
|
|
443
|
+
return workspaceInfo;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
export {
|
|
447
|
+
AppInfo,
|
|
448
|
+
LibInfo,
|
|
449
|
+
PkgInfo,
|
|
450
|
+
WorkspaceInfo
|
|
451
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
import type { PackageJson, TsConfigJson } from "./types";
|
|
1
2
|
export declare class TypeScriptDependencyScanner {
|
|
2
3
|
#private;
|
|
3
|
-
readonly directory
|
|
4
|
-
|
|
4
|
+
private readonly directory;
|
|
5
|
+
private readonly tsconfig;
|
|
6
|
+
private readonly rootPackageJson;
|
|
7
|
+
constructor(directory: string, { tsconfig, rootPackageJson }: {
|
|
8
|
+
tsconfig: TsConfigJson;
|
|
9
|
+
rootPackageJson: PackageJson;
|
|
10
|
+
});
|
|
11
|
+
getMonorepoDependencies(projectName: string): Promise<{
|
|
12
|
+
pkgDeps: string[];
|
|
13
|
+
libDeps: string[];
|
|
14
|
+
npmDeps: string[];
|
|
15
|
+
}>;
|
|
5
16
|
getImportSets(depSets: Set<string>[]): Promise<Set<string>[]>;
|
|
6
17
|
getDependencies(): Promise<Map<string, string[]>>;
|
|
7
18
|
generateDependencyGraph(): string;
|
package/src/executors.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Logger } from "@akanjs/common";
|
|
2
|
-
import { type AppConfigResult,
|
|
2
|
+
import { type AppConfigResult, type LibConfigResult } from "@akanjs/config";
|
|
3
3
|
import { ChildProcess, type ExecOptions, type ForkOptions, type SpawnOptions } from "child_process";
|
|
4
4
|
import { Linter } from "./linter";
|
|
5
|
+
import { AppInfo, LibInfo, PkgInfo, WorkspaceInfo } from "./scanInfo";
|
|
5
6
|
import { Spinner } from "./spinner";
|
|
6
7
|
import { TypeChecker } from "./typeChecker";
|
|
7
8
|
import type { FileContent, PackageJson, TsConfigJson } from "./types";
|
|
@@ -33,6 +34,10 @@ export declare class Executor {
|
|
|
33
34
|
getPath(filePath: string): string;
|
|
34
35
|
mkdir(dirPath: string): this;
|
|
35
36
|
readdir(dirPath: string): Promise<string[]>;
|
|
37
|
+
getFilesAndDirs(dirPath: string): Promise<{
|
|
38
|
+
files: string[];
|
|
39
|
+
dirs: string[];
|
|
40
|
+
}>;
|
|
36
41
|
exists(filePath: string): boolean;
|
|
37
42
|
remove(filePath: string): this;
|
|
38
43
|
removeDir(dirPath: string): this;
|
|
@@ -54,11 +59,18 @@ export declare class Executor {
|
|
|
54
59
|
indent?: number | undefined;
|
|
55
60
|
enableSpin?: boolean | undefined;
|
|
56
61
|
}): Spinner;
|
|
57
|
-
getTsConfig(pathname?: string
|
|
58
|
-
|
|
62
|
+
getTsConfig(pathname?: string, { refresh }?: {
|
|
63
|
+
refresh?: boolean;
|
|
64
|
+
}): TsConfigJson;
|
|
65
|
+
setTsConfig(tsconfig: TsConfigJson): void;
|
|
66
|
+
getPackageJson({ refresh }?: {
|
|
67
|
+
refresh?: boolean;
|
|
68
|
+
}): PackageJson;
|
|
69
|
+
setPackageJson(packageJson: PackageJson): void;
|
|
70
|
+
_applyTemplate({ basePath, template, scanInfo, dict, overwrite, }: {
|
|
59
71
|
basePath: string;
|
|
60
72
|
template: string;
|
|
61
|
-
|
|
73
|
+
scanInfo?: AppInfo | LibInfo | null;
|
|
62
74
|
dict?: {
|
|
63
75
|
[key: string]: string;
|
|
64
76
|
};
|
|
@@ -100,15 +112,18 @@ export declare class WorkspaceExecutor extends Executor {
|
|
|
100
112
|
repoName: string;
|
|
101
113
|
emoji: string;
|
|
102
114
|
constructor({ workspaceRoot, repoName }: ExecutorOptions);
|
|
103
|
-
static fromRoot(
|
|
115
|
+
static fromRoot({ workspaceRoot, repoName, }?: {
|
|
116
|
+
workspaceRoot?: string;
|
|
117
|
+
repoName?: string;
|
|
118
|
+
}): WorkspaceExecutor;
|
|
104
119
|
getBaseDevEnv(): {
|
|
105
120
|
repoName: string;
|
|
106
121
|
serveDomain: string;
|
|
107
|
-
env: "
|
|
122
|
+
env: "debug" | "testing" | "local" | "develop" | "main";
|
|
108
123
|
portOffset: number;
|
|
109
124
|
name?: string | undefined;
|
|
110
125
|
};
|
|
111
|
-
scan(): Promise<
|
|
126
|
+
scan(): Promise<WorkspaceInfo>;
|
|
112
127
|
getApps(): Promise<string[]>;
|
|
113
128
|
getLibs(): Promise<string[]>;
|
|
114
129
|
getSyss(): Promise<[string[], string[]]>;
|
|
@@ -144,19 +159,21 @@ interface SysExecutorOptions {
|
|
|
144
159
|
type: "app" | "lib";
|
|
145
160
|
}
|
|
146
161
|
export declare class SysExecutor extends Executor {
|
|
162
|
+
#private;
|
|
147
163
|
workspace: WorkspaceExecutor;
|
|
148
164
|
name: string;
|
|
149
165
|
type: "app" | "lib";
|
|
150
166
|
emoji: string;
|
|
151
167
|
constructor({ workspace, name, type }: SysExecutorOptions);
|
|
152
|
-
getConfig(
|
|
168
|
+
getConfig({ refresh }?: {
|
|
169
|
+
refresh?: boolean;
|
|
170
|
+
}): Promise<LibConfigResult>;
|
|
153
171
|
getModules(): Promise<string[]>;
|
|
154
|
-
scan({
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}): Promise<AppScanResult | LibScanResult>;
|
|
172
|
+
scan({ refresh, write, writeLib, }?: {
|
|
173
|
+
refresh?: boolean;
|
|
174
|
+
write?: boolean;
|
|
175
|
+
writeLib?: boolean;
|
|
176
|
+
}): Promise<AppInfo | LibInfo>;
|
|
160
177
|
getLocalFile(targetPath: string): {
|
|
161
178
|
filePath: string;
|
|
162
179
|
content: string;
|
|
@@ -214,12 +231,15 @@ interface AppExecutorOptions {
|
|
|
214
231
|
name: string;
|
|
215
232
|
}
|
|
216
233
|
export declare class AppExecutor extends SysExecutor {
|
|
234
|
+
#private;
|
|
217
235
|
dist: Executor;
|
|
218
236
|
emoji: string;
|
|
219
237
|
constructor({ workspace, name }: AppExecutorOptions);
|
|
220
238
|
static from(executor: SysExecutor | WorkspaceExecutor, name: string): AppExecutor;
|
|
221
|
-
getEnv(): "
|
|
222
|
-
getConfig(
|
|
239
|
+
getEnv(): "debug" | "testing" | "local" | "develop" | "main";
|
|
240
|
+
getConfig({ refresh }?: {
|
|
241
|
+
refresh?: boolean;
|
|
242
|
+
}): Promise<AppConfigResult>;
|
|
223
243
|
syncAssets(libDeps: string[]): Promise<void>;
|
|
224
244
|
}
|
|
225
245
|
interface LibExecutorOptions {
|
|
@@ -227,29 +247,32 @@ interface LibExecutorOptions {
|
|
|
227
247
|
name: string;
|
|
228
248
|
}
|
|
229
249
|
export declare class LibExecutor extends SysExecutor {
|
|
250
|
+
#private;
|
|
230
251
|
workspaceRoot: string;
|
|
231
252
|
repoName: string;
|
|
232
253
|
dist: Executor;
|
|
233
254
|
emoji: string;
|
|
234
255
|
constructor({ workspace, name }: LibExecutorOptions);
|
|
235
256
|
static from(executor: SysExecutor | WorkspaceExecutor, name: string): LibExecutor;
|
|
236
|
-
getConfig(
|
|
257
|
+
getConfig({ refresh }?: {
|
|
258
|
+
refresh?: boolean;
|
|
259
|
+
}): Promise<LibConfigResult>;
|
|
237
260
|
}
|
|
238
261
|
interface PkgExecutorOptions {
|
|
239
262
|
workspace?: WorkspaceExecutor;
|
|
240
263
|
name: string;
|
|
241
264
|
}
|
|
242
265
|
export declare class PkgExecutor extends Executor {
|
|
266
|
+
#private;
|
|
243
267
|
workspace: WorkspaceExecutor;
|
|
244
268
|
name: string;
|
|
245
269
|
dist: Executor;
|
|
246
270
|
emoji: string;
|
|
247
271
|
constructor({ workspace, name }: PkgExecutorOptions);
|
|
248
272
|
static from(executor: SysExecutor | WorkspaceExecutor, name: string): PkgExecutor;
|
|
249
|
-
scan({
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}): Promise<PkgScanResult>;
|
|
273
|
+
scan({ refresh }?: {
|
|
274
|
+
refresh?: boolean;
|
|
275
|
+
}): Promise<PkgInfo>;
|
|
253
276
|
}
|
|
254
277
|
interface ModuleExecutorOptions {
|
|
255
278
|
sys: SysExecutor;
|
package/src/index.d.ts
CHANGED