@travetto/manifest 7.0.2 → 7.0.3

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 CHANGED
@@ -60,8 +60,6 @@ By default, all paths within the framework are assumed to be in a POSIX style, a
60
60
  },
61
61
  "build": {
62
62
  "compilerUrl": "http://127.0.0.1:26803",
63
- "compilerModuleFolder": "module/compiler",
64
- "compilerFolder": ".trv/compiler",
65
63
  "outputFolder": ".trv/output",
66
64
  "toolFolder": ".trv/tool",
67
65
  "typesFolder": ".trv/types"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/manifest",
3
- "version": "7.0.2",
3
+ "version": "7.0.3",
4
4
  "type": "module",
5
5
  "description": "Support for project indexing, manifesting, along with file watching",
6
6
  "keywords": [
@@ -18,9 +18,7 @@
18
18
  },
19
19
  "files": [
20
20
  "__index__.ts",
21
- "bin",
22
- "src",
23
- "support"
21
+ "src"
24
22
  ],
25
23
  "main": "__index__.ts",
26
24
  "engines": {
package/src/context.ts CHANGED
@@ -50,7 +50,7 @@ export function getManifestContext(root: string = process.cwd()): ManifestContex
50
50
  const resolve = createRequire(path.resolve(workspace.path, 'node_modules')).resolve.bind(null);
51
51
  const wsPrefix = `${workspace.path}/`;
52
52
  const moduleName = process.env.TRV_MODULE === workspace.name ? workspace.path : process.env.TRV_MODULE;
53
- const modPkg = (!!workspace.workspaces && moduleName) ?
53
+ const modulePkg = (!!workspace.workspaces && moduleName) ?
54
54
  readPackage(resolve(`${moduleName}/package.json`)) :
55
55
  findPackage(root, pkg => !!pkg) ?? workspace;
56
56
 
@@ -69,17 +69,15 @@ export function getManifestContext(root: string = process.cwd()): ManifestContex
69
69
  },
70
70
  build: {
71
71
  compilerUrl: build.compilerUrl ?? `http://localhost:${toPort(wsPrefix)}`,
72
- compilerModuleFolder: toPosix(path.dirname(resolve('@travetto/compiler/package.json'))).replace(wsPrefix, ''),
73
- compilerFolder: toPosix(build.compilerFolder ?? '.trv/compiler'),
74
72
  outputFolder: toPosix(build.outputFolder ?? '.trv/output'),
75
73
  toolFolder: toPosix(build.toolFolder ?? '.trv/tool'),
76
74
  typesFolder: toPosix(build.typesFolder ?? '.trv/types')
77
75
  },
78
76
  main: {
79
- name: modPkg.name ?? 'untitled',
80
- folder: modPkg.path.replace(wsPrefix, ''),
81
- version: modPkg.version,
82
- description: modPkg.description
77
+ name: modulePkg.name ?? 'untitled',
78
+ folder: modulePkg.path.replace(wsPrefix, ''),
79
+ version: modulePkg.version,
80
+ description: modulePkg.description
83
81
  }
84
82
  };
85
83
  }
package/src/delta.ts CHANGED
@@ -11,7 +11,7 @@ type DeltaEventType = ChangeEventType | 'missing' | 'dirty';
11
11
  type DeltaModule = ManifestModuleCore & { files: Record<string, ManifestModuleFile> };
12
12
  export type DeltaEvent = { file: string, type: DeltaEventType, module: string, sourceFile: string };
13
13
 
14
- const VALID_SOURCE_FOLDERS = new Set<ManifestModuleFolderType>(['bin', 'src', 'test', 'support', '$index', '$package', 'doc']);
14
+ const VALID_SOURCE_FOLDERS = new Set<ManifestModuleFolderType>(['bin', 'src', 'test', 'support', '$index', '$transformer', '$package', 'doc']);
15
15
  const VALID_SOURCE_TYPE = new Set<ManifestModuleFileType>(['js', 'ts', 'package-json']);
16
16
  const VALID_OUTPUT_TYPE = new Set<ManifestModuleFileType>([...VALID_SOURCE_TYPE, 'typings']);
17
17
 
@@ -69,16 +69,16 @@ export class ManifestDeltaUtil {
69
69
 
70
70
  /**
71
71
  * Collapse all files in a module
72
- * @param {ManifestModule} mod
72
+ * @param {ManifestModule} module
73
73
  * @returns {}
74
74
  */
75
- static #flattenModuleFiles(mod: ManifestModule): Record<string, ManifestModuleFile> {
75
+ static #flattenModuleFiles(module: ManifestModule): Record<string, ManifestModuleFile> {
76
76
  const out: Record<string, ManifestModuleFile> = {};
77
- for (const key of TypedObject.keys(mod.files)) {
77
+ for (const key of TypedObject.keys(module.files)) {
78
78
  if (!VALID_SOURCE_FOLDERS.has(key)) {
79
79
  continue;
80
80
  }
81
- for (const [name, type, date] of mod.files?.[key] ?? []) {
81
+ for (const [name, type, date] of module.files?.[key] ?? []) {
82
82
  if (VALID_OUTPUT_TYPE.has(type)) {
83
83
  out[name] = [name, type, date];
84
84
  }
@@ -93,7 +93,7 @@ export class ManifestDeltaUtil {
93
93
  static async produceDelta(manifest: ManifestRoot): Promise<DeltaEvent[]> {
94
94
  const deltaLeft = Object.fromEntries(
95
95
  Object.values(manifest.modules)
96
- .map(mod => [mod.name, { ...mod, files: this.#flattenModuleFiles(mod) }])
96
+ .map(module => [module.name, { ...module, files: this.#flattenModuleFiles(module) }])
97
97
  );
98
98
 
99
99
  const out: DeltaEvent[] = [];
@@ -100,11 +100,11 @@ export class PackageModuleVisitor {
100
100
  /**
101
101
  * Propagate prod, role information through graph
102
102
  */
103
- async #complete(mods: Iterable<PackageModule>): Promise<PackageModule[]> {
104
- const mapping = new Map([...mods].map(item => [item.name, { parent: new Set(item.state.parentSet), item }]));
103
+ async #complete(modules: Iterable<PackageModule>): Promise<PackageModule[]> {
104
+ const mapping = new Map([...modules].map(item => [item.name, { parent: new Set(item.state.parentSet), item }]));
105
105
 
106
106
  // All first-level dependencies should have role filled in (for propagation)
107
- for (const dependency of [...mods].filter(mod => mod.state.roleRoot)) {
107
+ for (const dependency of [...modules].filter(module => module.state.roleRoot)) {
108
108
  dependency.state.roleSet.clear(); // Ensure the roleRoot is empty
109
109
  for (const child of dependency.state.childSet) { // Visit children
110
110
  const childDependency = mapping.get(child)!.item;
@@ -143,11 +143,11 @@ export class PackageModuleVisitor {
143
143
  }
144
144
 
145
145
  // Mark as standard at the end
146
- for (const dependency of [...mods].filter(mod => mod.state.roleRoot)) {
147
- dependency.state.roleSet = new Set(['std']);
146
+ for (const dependency of [...modules].filter(module => module.state.roleRoot)) {
147
+ dependency.state.roleSet = new Set(['std', ...dependency.state.travetto?.roles ?? []]);
148
148
  }
149
149
 
150
- return [...mods].toSorted((a, b) => a.name.localeCompare(b.name));
150
+ return [...modules].toSorted((a, b) => a.name.localeCompare(b.name));
151
151
  }
152
152
 
153
153
  /**
@@ -26,7 +26,7 @@ export class ManifestIndex {
26
26
  #sourceToEntry = new Map<string, IndexedFile>();
27
27
  #importToEntry = new Map<string, IndexedFile>();
28
28
 
29
- constructor(manifest: string = process.env.TRV_MANIFEST!) {
29
+ constructor(manifest: string | ManifestRoot = process.env.TRV_MANIFEST!) {
30
30
  this.init(manifest || path.resolve(import.meta.dirname, './manifest.json'));
31
31
  }
32
32
 
@@ -42,8 +42,8 @@ export class ManifestIndex {
42
42
  return this.#outputRoot;
43
43
  }
44
44
 
45
- init(manifestInput: string): void {
46
- this.#manifest = ManifestUtil.readManifestSync(manifestInput);
45
+ init(manifestInput: string | ManifestRoot): void {
46
+ this.#manifest = typeof manifestInput === 'string' ? ManifestUtil.readManifestSync(manifestInput) : manifestInput;
47
47
  this.#outputRoot = path.resolve(this.#manifest.workspace.path, this.#manifest.build.outputFolder);
48
48
  this.#index();
49
49
  }
@@ -56,19 +56,19 @@ export class ManifestIndex {
56
56
  this.init(`${this.outputRoot}/node_modules/${module}`);
57
57
  }
58
58
 
59
- #moduleFiles(mod: ManifestModule, files: ManifestModuleFile[]): IndexedFile[] {
59
+ #moduleFiles(module: ManifestModule, files: ManifestModuleFile[]): IndexedFile[] {
60
60
  return files.map(([file, type, _ts, role = 'std']) => {
61
61
  const isSource = type === 'ts' || type === 'js';
62
- const sourceFile = path.resolve(this.#manifest.workspace.path, mod.sourceFolder, file);
62
+ const sourceFile = path.resolve(this.#manifest.workspace.path, module.sourceFolder, file);
63
63
  const js = isSource ? ManifestModuleUtil.withOutputExtension(file) : file;
64
- const outputFile = this.#resolveOutput(mod.outputFolder, js);
65
- const modImport = `${mod.name}/${file}`;
66
- let id = `${mod.name}:${file}`;
64
+ const outputFile = this.#resolveOutput(module.outputFolder, js);
65
+ const moduleImport = `${module.name}/${file}`;
66
+ let id = `${module.name}:${file}`;
67
67
  if (isSource) {
68
68
  id = ManifestModuleUtil.withoutSourceExtension(id);
69
69
  }
70
70
 
71
- return { id, type, sourceFile, outputFile, import: modImport, role, relativeFile: file, module: mod.name };
71
+ return { id, type, sourceFile, outputFile, import: moduleImport, role, relativeFile: file, module: module.name };
72
72
  });
73
73
  }
74
74
 
@@ -82,18 +82,18 @@ export class ManifestIndex {
82
82
  this.#arbitraryLookup = undefined;
83
83
 
84
84
  this.#modules = Object.values(this.#manifest.modules)
85
- .map(mod => ({
86
- ...mod,
87
- outputPath: this.#resolveOutput(mod.outputFolder),
88
- sourcePath: path.resolve(this.#manifest.workspace.path, mod.sourceFolder),
85
+ .map(module => ({
86
+ ...module,
87
+ outputPath: this.#resolveOutput(module.outputFolder),
88
+ sourcePath: path.resolve(this.#manifest.workspace.path, module.sourceFolder),
89
89
  children: new Set(),
90
90
  files: TypedObject.fromEntries(
91
- TypedObject.entries(mod.files).map(([folder, files]) => [folder, this.#moduleFiles(mod, files ?? [])])
91
+ TypedObject.entries(module.files).map(([folder, files]) => [folder, this.#moduleFiles(module, files ?? [])])
92
92
  )
93
93
  }));
94
94
 
95
- for (const mod of this.#modules) {
96
- for (const files of Object.values(mod.files ?? {})) {
95
+ for (const module of this.#modules) {
96
+ for (const files of Object.values(module.files ?? {})) {
97
97
  for (const entry of files) {
98
98
  this.#outputToEntry.set(entry.outputFile, entry);
99
99
  this.#sourceToEntry.set(entry.sourceFile, entry);
@@ -103,12 +103,12 @@ export class ManifestIndex {
103
103
  }
104
104
  }
105
105
  }
106
- this.#modulesByName = Object.fromEntries(this.#modules.map(mod => [mod.name, mod]));
106
+ this.#modulesByName = Object.fromEntries(this.#modules.map(module => [module.name, module]));
107
107
 
108
108
  // Store child information
109
- for (const mod of this.#modules) {
110
- for (const parent of mod.parents) {
111
- this.#modulesByName[parent]?.children.add(mod.name);
109
+ for (const module of this.#modules) {
110
+ for (const parent of module.parents) {
111
+ this.#modulesByName[parent]?.children.add(module.name);
112
112
  }
113
113
  }
114
114
  }
@@ -125,7 +125,7 @@ export class ManifestIndex {
125
125
  * @returns
126
126
  */
127
127
  getWorkspaceModules(): IndexedModule[] {
128
- return this.#modules.filter(mod => mod.workspace);
128
+ return this.#modules.filter(module => module.workspace);
129
129
  }
130
130
 
131
131
  /**
@@ -134,9 +134,9 @@ export class ManifestIndex {
134
134
  */
135
135
  find(config: FindConfig): IndexedFile[] {
136
136
  const searchSpace: IndexedFile[] = [];
137
- for (const mod of this.#modules) {
138
- if (config.module?.(mod) ?? true) {
139
- for (const [folder, files] of TypedObject.entries(mod.files)) {
137
+ for (const module of this.#modules) {
138
+ if (config.module?.(module) ?? true) {
139
+ for (const [folder, files] of TypedObject.entries(module.files)) {
140
140
  if (config.folder?.(folder) ?? true) {
141
141
  for (const file of files) {
142
142
  if (
@@ -213,14 +213,14 @@ export class ManifestIndex {
213
213
  * Build module list from an expression list (e.g. `@travetto/web,-@travetto/log)
214
214
  */
215
215
  getModuleList(mode: 'workspace' | 'all', exprList: string = ''): Set<string> {
216
- const allMods = Object.keys(this.#manifest.modules);
217
- const active = new Set<string>(mode === 'workspace' ? this.getWorkspaceModules().map(item => item.name) : allMods);
216
+ const allModules = Object.keys(this.#manifest.modules);
217
+ const active = new Set<string>(mode === 'workspace' ? this.getWorkspaceModules().map(item => item.name) : allModules);
218
218
 
219
219
  for (const expr of exprList.split(/,/g)) {
220
- const [, negative, mod] = expr.trim().match(/(-|[+])?([^+\- ]{1,150})$/) ?? [];
221
- if (mod) {
222
- const pattern = new RegExp(`^${mod.replace(/[*]/g, '.*')}$`);
223
- for (const moduleName of allMods.filter(item => pattern.test(item))) {
220
+ const [, negative, module] = expr.trim().match(/(-|[+])?([^+\- ]{1,150})$/) ?? [];
221
+ if (module) {
222
+ const pattern = new RegExp(`^${module.replace(/[*]/g, '.*')}$`);
223
+ for (const moduleName of allModules.filter(item => pattern.test(item))) {
224
224
  active[negative ? 'delete' : 'add'](moduleName);
225
225
  }
226
226
  }
@@ -239,10 +239,10 @@ export class ManifestIndex {
239
239
  const next = toProcess.shift()!;
240
240
  if (!seen.has(next)) {
241
241
  seen.add(next);
242
- const mod = this.getModule(next)!;
243
- toProcess.push(...mod[field]);
242
+ const module = this.getModule(next)!;
243
+ toProcess.push(...module[field]);
244
244
  if (next !== this.#manifest.main.name) { // Do not include self
245
- out.push(mod);
245
+ out.push(module);
246
246
  }
247
247
  }
248
248
  }
@@ -256,7 +256,7 @@ export class ManifestIndex {
256
256
  const base = this.#manifest.workspace.path;
257
257
  const lookup = this.#arbitraryLookup ??= ManifestUtil.lookupTrie(
258
258
  Object.values(this.#manifest.modules),
259
- mod => mod.sourceFolder.split('/'),
259
+ module => module.sourceFolder.split('/'),
260
260
  sub =>
261
261
  !existsSync(path.resolve(base, ...sub, 'package.json')) &&
262
262
  !existsSync(path.resolve(base, ...sub, '.git'))
@@ -276,8 +276,8 @@ export class ManifestIndex {
276
276
  /**
277
277
  * Get manifest module by name
278
278
  */
279
- getManifestModule(mod: string): ManifestModule {
280
- return this.manifest.modules[mod];
279
+ getManifestModule(module: string): ManifestModule {
280
+ return this.manifest.modules[module];
281
281
  }
282
282
 
283
283
  /**
@@ -302,4 +302,32 @@ export class ManifestIndex {
302
302
  importFile = Array.isArray(importFile) ? importFile.join('/') : importFile;
303
303
  return this.getFromImport(importFile)?.sourceFile ?? importFile;
304
304
  }
305
+
306
+ /**
307
+ * Group by lineage, data can be duplicated
308
+ */
309
+ groupByLineage<T extends { action: string }>(items: { item: T, module: string }[]): Map<string, T[]> {
310
+ const itemsByMod = new Map<string, T[]>();
311
+ for (const event of items) {
312
+ const moduleSet = new Set(this.getDependentModules(event.module, 'parents').map(indexedMod => indexedMod.name));
313
+ moduleSet.add(this.manifest.workspace.name);
314
+ for (const moduleName of moduleSet) {
315
+ if (!itemsByMod.has(moduleName)) {
316
+ itemsByMod.set(moduleName, []);
317
+ }
318
+ itemsByMod.get(moduleName)!.push(event.item);
319
+ }
320
+ }
321
+ return itemsByMod;
322
+ }
323
+
324
+ /**
325
+ * Resolve child manifest relative to current manifest
326
+ */
327
+ resolveDependentManifest(moduleName: string): ManifestRoot {
328
+ const moduleRoot = this.getManifestModule(moduleName)!.sourceFolder;
329
+ const moduleContext = ManifestUtil.getModuleContext(this.manifest, moduleRoot);
330
+ const manifestLocation = ManifestUtil.getManifestLocation(moduleContext, moduleName);
331
+ return ManifestUtil.readManifestSync(manifestLocation);
332
+ }
305
333
  }
package/src/module.ts CHANGED
@@ -77,7 +77,6 @@ export class ManifestModuleUtil {
77
77
  const out: string[] = [];
78
78
 
79
79
  const exclude = new Set([
80
- path.resolve(ctx.workspace.path, ctx.build.compilerFolder),
81
80
  path.resolve(ctx.workspace.path, ctx.build.outputFolder),
82
81
  path.resolve(ctx.workspace.path, ctx.build.toolFolder),
83
82
  ]);
@@ -207,8 +206,8 @@ export class ManifestModuleUtil {
207
206
  /**
208
207
  * Visit a module and describe files, and metadata
209
208
  */
210
- static async describeModule(ctx: ManifestContext, mod: PackageModule): Promise<ManifestModule> {
211
- const { state, ...rest } = mod;
209
+ static async describeModule(ctx: ManifestContext, module: PackageModule): Promise<ManifestModule> {
210
+ const { state, ...rest } = module;
212
211
  const sourcePath = path.resolve(ctx.workspace.path, rest.sourceFolder);
213
212
 
214
213
  const files: ManifestModule['files'] = {};
@@ -234,8 +233,8 @@ export class ManifestModuleUtil {
234
233
  */
235
234
  static async produceModules(ctx: ManifestContext): Promise<Record<string, ManifestModule>> {
236
235
  const pkgs = await PackageModuleVisitor.visit(ctx);
237
- const modules = await Promise.all([...pkgs].map(mod => this.describeModule(ctx, mod)));
238
- return Object.fromEntries(modules.map(mod => [mod.name, mod]));
236
+ const modules = await Promise.all([...pkgs].map(module => this.describeModule(ctx, module)));
237
+ return Object.fromEntries(modules.map(module => [module.name, module]));
239
238
  }
240
239
 
241
240
  /**
@@ -257,4 +256,14 @@ export class ManifestModuleUtil {
257
256
  }
258
257
  return this.#pathToExtension(sourceFile, '');
259
258
  }
259
+
260
+ /**
261
+ * Determine if this type is considered source code
262
+ */
263
+ static isSourceType(type: ManifestModuleFileType | string): boolean {
264
+ if (type.includes('.')) {
265
+ type = this.getFileType(type);
266
+ }
267
+ return type === 'ts' || type === 'package-json' || type === 'js' || type === 'typings';
268
+ }
260
269
  }
package/src/package.ts CHANGED
@@ -107,7 +107,7 @@ export class PackageUtil {
107
107
  case 'yarn':
108
108
  case 'npm': {
109
109
  const workspaces = await this.#exec<{ location: string, name: string }[]>(rootPath, 'npm query .workspace');
110
- out = workspaces.map(mod => ({ path: path.resolve(ctx.workspace.path, mod.location), name: mod.name }));
110
+ out = workspaces.map(module => ({ path: path.resolve(ctx.workspace.path, module.location), name: module.name }));
111
111
  break;
112
112
  }
113
113
  }
@@ -14,10 +14,6 @@ export type ManifestContext = {
14
14
  defaultEnv: string;
15
15
  };
16
16
  build: {
17
- /** Compiler folder, relative to workspace */
18
- compilerFolder: string;
19
- /** Compiler module folder */
20
- compilerModuleFolder: string;
21
17
  /** URL for the compiler server */
22
18
  compilerUrl: string;
23
19
  /** Code output folder, relative to workspace */
@@ -1,6 +1,6 @@
1
1
  import type { ManifestModuleFileType, ManifestModuleFolderType, ManifestModuleRole } from './common.ts';
2
2
  import type { ManifestContext } from './context.ts';
3
- import { Package } from './package.ts';
3
+ import type { Package } from './package.ts';
4
4
 
5
5
  export type ManifestModuleFile =
6
6
  [path: string, type: ManifestModuleFileType, updated: number] |
package/src/util.ts CHANGED
@@ -5,6 +5,7 @@ import { PackageUtil } from './package.ts';
5
5
 
6
6
  import type { ManifestContext } from './types/context.ts';
7
7
  import type { ManifestRoot } from './types/manifest.ts';
8
+ import type { ChangeEventType } from './types/common.ts';
8
9
 
9
10
  const MANIFEST_FILE = 'manifest.json';
10
11
 
@@ -36,8 +37,8 @@ export class ManifestUtil {
36
37
  * Produce a production manifest from a given manifest
37
38
  */
38
39
  static createProductionManifest(manifest: ManifestRoot): ManifestRoot {
39
- const prodModules = Object.values(manifest.modules).filter(mod => mod.prod);
40
- const prodModNames = new Set([...prodModules.map(mod => mod.name)]);
40
+ const prodModules = Object.values(manifest.modules).filter(module => module.prod);
41
+ const prodModNames = new Set([...prodModules.map(module => module.name)]);
41
42
  return {
42
43
  generated: manifest.generated,
43
44
  workspace: manifest.workspace,
@@ -48,8 +49,8 @@ export class ManifestUtil {
48
49
  },
49
50
  main: manifest.main,
50
51
  modules: Object.fromEntries(
51
- prodModules.map(mod => [mod.name, Object.assign(mod, {
52
- parents: mod.parents.filter(parent => prodModNames.has(parent))
52
+ prodModules.map(module => [module.name, Object.assign(module, {
53
+ parents: module.parents.filter(parent => prodModNames.has(parent))
53
54
  })])
54
55
  ),
55
56
  };
@@ -85,6 +86,20 @@ export class ManifestUtil {
85
86
  );
86
87
  }
87
88
 
89
+ /**
90
+ * Write mono repo manifests, return names written
91
+ */
92
+ static async writeDependentManifests(manifest: ManifestRoot): Promise<void> {
93
+ if (manifest.workspace.mono) {
94
+ const modules = Object.values(manifest.modules).filter(module => module.workspace && module.name !== manifest.workspace.name);
95
+ for (const module of modules) {
96
+ const moduleCtx = this.getModuleContext(manifest, module.sourceFolder, true);
97
+ const moduleManifest = await this.buildManifest(moduleCtx);
98
+ await this.writeManifest(moduleManifest);
99
+ }
100
+ }
101
+ }
102
+
88
103
  /**
89
104
  * Write a manifest to a specific file, if no file extension provided, the file is assumed to be a folder
90
105
  */
@@ -117,8 +132,8 @@ export class ManifestUtil {
117
132
  * Produce the manifest context for a given module module
118
133
  */
119
134
  static getModuleContext(ctx: ManifestContext, folder: string, ensureLatest = false): ManifestContext {
120
- const modPath = path.resolve(ctx.workspace.path, folder);
121
- const pkg = PackageUtil.readPackage(modPath, ensureLatest);
135
+ const modulePath = path.resolve(ctx.workspace.path, folder);
136
+ const pkg = PackageUtil.readPackage(modulePath, ensureLatest);
122
137
 
123
138
  return {
124
139
  workspace: ctx.workspace,
@@ -170,4 +185,25 @@ export class ManifestUtil {
170
185
  return value;
171
186
  };
172
187
  }
188
+
189
+ /**
190
+ * Update manifest for a given module and relative file, with a specified action
191
+ */
192
+ static updateManifest(manifest: ManifestRoot, moduleName: string, relativeFile: string, action: ChangeEventType): void {
193
+ if (action === 'update') {
194
+ return; // Do nothing
195
+ }
196
+ const folderKey = ManifestModuleUtil.getFolderKey(relativeFile);
197
+ const fileType = ManifestModuleUtil.getFileType(relativeFile);
198
+ const roleType = ManifestModuleUtil.getFileRole(relativeFile)!;
199
+
200
+ const manifestModuleFiles = manifest.modules[moduleName].files[folderKey] ??= [];
201
+ const idx = manifestModuleFiles.findIndex(indexedFile => indexedFile[0] === relativeFile);
202
+ const wrappedIdx = idx < 0 ? manifestModuleFiles.length : idx;
203
+
204
+ switch (action) {
205
+ case 'create': manifestModuleFiles[wrappedIdx] = [relativeFile, fileType, Date.now(), roleType]; break;
206
+ case 'delete': idx >= 0 && manifestModuleFiles.splice(idx, 1); break;
207
+ }
208
+ }
173
209
  }