@travetto/manifest 4.0.0-rc.0 → 4.0.0-rc.1

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.
@@ -1,36 +1,11 @@
1
+ import { existsSync } from 'node:fs';
2
+
1
3
  import { ManifestModuleUtil } from './module';
2
4
  import { path } from './path';
3
-
4
- import {
5
- ManifestModule, ManifestModuleCore, ManifestModuleFile,
6
- ManifestModuleFileType, ManifestModuleFolderType, ManifestModuleRole, ManifestRoot
7
- } from './types';
8
-
9
5
  import { ManifestUtil } from './util';
10
6
 
11
- export type FindConfig = {
12
- folder?: (folder: ManifestModuleFolderType) => boolean;
13
- module?: (module: IndexedModule) => boolean;
14
- file?: (file: IndexedFile) => boolean;
15
- sourceOnly?: boolean;
16
- };
17
-
18
- export type IndexedFile = {
19
- id: string;
20
- import: string;
21
- module: string;
22
- sourceFile: string;
23
- outputFile: string;
24
- relativeFile: string;
25
- role: ManifestModuleRole;
26
- type: ManifestModuleFileType;
27
- };
28
-
29
- export type IndexedModule = ManifestModuleCore & {
30
- sourcePath: string;
31
- outputPath: string;
32
- files: Record<ManifestModuleFolderType, IndexedFile[]>;
33
- };
7
+ import type { ManifestModuleFolderType } from './types/common';
8
+ import type { ManifestModule, ManifestRoot, ManifestModuleFile, IndexedModule, IndexedFile, FindConfig } from './types/manifest';
34
9
 
35
10
  const TypedObject: {
36
11
  keys<T = unknown, K extends keyof T = keyof T>(o: T): K[];
@@ -43,7 +18,7 @@ const TypedObject: {
43
18
  */
44
19
  export class ManifestIndex {
45
20
 
46
- #manifestFile: string;
21
+ #arbitraryLookup?: (parts: string[]) => ManifestModule | undefined;
47
22
  #manifest: ManifestRoot;
48
23
  #modules: IndexedModule[];
49
24
  #modulesByName: Record<string, IndexedModule> = {};
@@ -69,14 +44,8 @@ export class ManifestIndex {
69
44
  return this.#outputRoot;
70
45
  }
71
46
 
72
- get manifestFile(): string {
73
- return this.#manifestFile;
74
- }
75
-
76
47
  init(manifestInput: string): void {
77
- const { manifest, file } = ManifestUtil.readManifestSync(manifestInput);
78
- this.#manifest = manifest;
79
- this.#manifestFile = file;
48
+ this.#manifest = ManifestUtil.readManifestSync(manifestInput);
80
49
  this.#outputRoot = path.resolve(this.#manifest.workspace.path, this.#manifest.build.outputFolder);
81
50
  this.#index();
82
51
  }
@@ -104,12 +73,14 @@ export class ManifestIndex {
104
73
  this.#outputToEntry.clear();
105
74
  this.#importToEntry.clear();
106
75
  this.#sourceToEntry.clear();
76
+ this.#arbitraryLookup = undefined;
107
77
 
108
78
  this.#modules = Object.values(this.#manifest.modules)
109
79
  .map(m => ({
110
80
  ...m,
111
81
  outputPath: this.#resolveOutput(m.outputFolder),
112
82
  sourcePath: path.resolve(this.#manifest.workspace.path, m.sourceFolder),
83
+ children: new Set(),
113
84
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
114
85
  files: Object.fromEntries(
115
86
  Object.entries(m.files).map(([folder, files]) => [folder, this.#moduleFiles(m, files ?? [])])
@@ -128,6 +99,13 @@ export class ManifestIndex {
128
99
  }
129
100
  this.#modulesByName = Object.fromEntries(this.#modules.map(x => [x.name, x]));
130
101
  this.#modulesByFolder = Object.fromEntries(this.#modules.map(x => [x.sourceFolder, x]));
102
+
103
+ // Store child information
104
+ for (const mod of this.#modules) {
105
+ for (const p of mod.parents) {
106
+ this.#modulesByName[p]?.children.add(mod.name);
107
+ }
108
+ }
131
109
  }
132
110
 
133
111
  /**
@@ -138,11 +116,11 @@ export class ManifestIndex {
138
116
  }
139
117
 
140
118
  /**
141
- * Get all local modules
119
+ * Get all workspace modules
142
120
  * @returns
143
121
  */
144
- getLocalModules(): IndexedModule[] {
145
- return this.#modules.filter(x => x.local);
122
+ getWorkspaceModules(): IndexedModule[] {
123
+ return this.#modules.filter(x => x.workspace);
146
124
  }
147
125
 
148
126
  /**
@@ -237,12 +215,9 @@ export class ManifestIndex {
237
215
  /**
238
216
  * Build module list from an expression list (e.g. `@travetto/rest,-@travetto/log)
239
217
  */
240
- getModuleList(mode: 'local' | 'all', exprList: string = ''): Set<string> {
218
+ getModuleList(mode: 'workspace' | 'all', exprList: string = ''): Set<string> {
241
219
  const allMods = Object.keys(this.#manifest.modules);
242
- const active = new Set<string>(
243
- mode === 'local' ? this.getLocalModules().map(x => x.name) :
244
- (mode === 'all' ? allMods : [])
245
- );
220
+ const active = new Set<string>(mode === 'workspace' ? this.getWorkspaceModules().map(x => x.name) : allMods);
246
221
 
247
222
  for (const expr of exprList.split(/\s*,\s*/g)) {
248
223
  const [, neg, mod] = expr.match(/(-|[+])?([^+\- ]+)$/) ?? [];
@@ -257,21 +232,38 @@ export class ManifestIndex {
257
232
  }
258
233
 
259
234
  /**
260
- * Get all modules (transitively) that depend on this module
235
+ * Get all modules, parents or children, (transitively) of the provided root, in a DFS fashion
261
236
  */
262
- getDependentModules(root: IndexedModule): Set<IndexedModule> {
237
+ getDependentModules(root: IndexedModule | string, field: 'parents' | 'children'): IndexedModule[] {
263
238
  const seen = new Set<string>();
264
- const out = new Set<IndexedModule>();
265
- const toProcess = [root.name];
239
+ const out: IndexedModule[] = [];
240
+ const toProcess = [typeof root === 'string' ? root : root.name];
266
241
  while (toProcess.length) {
267
242
  const next = toProcess.shift()!;
268
- if (seen.has(next)) {
269
- continue;
243
+ if (!seen.has(next)) {
244
+ seen.add(next);
245
+ const mod = this.getModule(next)!;
246
+ toProcess.push(...mod[field]);
247
+ if (next !== this.#manifest.main.name) { // Do not include self
248
+ out.push(mod);
249
+ }
270
250
  }
271
- const mod = this.getModule(next)!;
272
- toProcess.push(...mod.parents);
273
- out.add(mod);
274
251
  }
275
252
  return out;
276
253
  }
254
+
255
+ /**
256
+ * Find the module for an arbitrary source file, if it falls under a given workspace module
257
+ */
258
+ findModuleForArbitraryFile(file: string): ManifestModule | undefined {
259
+ const base = this.#manifest.workspace.path;
260
+ const lookup = this.#arbitraryLookup ??= ManifestUtil.lookupTrie(
261
+ Object.values(this.#manifest.modules),
262
+ x => x.sourceFolder.split('/'),
263
+ sub =>
264
+ !existsSync(path.resolve(base, ...sub, 'package.json')) &&
265
+ !existsSync(path.resolve(base, ...sub, '.git'))
266
+ );
267
+ return lookup(file.replace(`${base}/`, '').split('/'));
268
+ }
277
269
  }
package/src/module.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import fs from 'node:fs/promises';
2
2
 
3
3
  import { path } from './path';
4
- import {
5
- ManifestContext,
6
- ManifestModule, ManifestModuleFile, ManifestModuleFileType,
7
- ManifestModuleFolderType,
8
- ManifestModuleRole
9
- } from './types';
10
- import { ModuleDep, ModuleDependencyVisitor } from './dependencies';
11
4
  import { PackageUtil } from './package';
5
+ import { PackageModuleVisitor } from './dependencies';
6
+
7
+ import type { ManifestModuleFileType, ManifestModuleRole, ManifestModuleFolderType } from './types/common';
8
+ import type { ManifestModuleFile, ManifestModule, PackageModule } from './types/manifest';
9
+ import type { ManifestContext } from './types/context';
12
10
 
13
11
  const EXT_MAPPING: Record<string, ManifestModuleFileType> = {
14
12
  '.js': 'js',
@@ -47,9 +45,10 @@ export class ManifestModuleUtil {
47
45
  /**
48
46
  * Simple file scanning
49
47
  */
50
- static async scanFolder(folder: string, mainLike = false): Promise<string[]> {
51
- if (!mainLike && folder in this.#scanCache) {
52
- return this.#scanCache[folder];
48
+ static async scanFolder(folder: string, full = false): Promise<string[]> {
49
+ const key = `${folder}|${full}`;
50
+ if (key in this.#scanCache) {
51
+ return this.#scanCache[key];
53
52
  }
54
53
 
55
54
  if (!await fs.stat(folder).catch(() => false)) {
@@ -73,7 +72,7 @@ export class ManifestModuleUtil {
73
72
  }
74
73
 
75
74
  for (const sub of await fs.readdir(top)) {
76
- const valid = !sub.startsWith('.') && (depth > 0 || mainLike);
75
+ const valid = !sub.startsWith('.') && (depth > 0 || full);
77
76
  const stat = await fs.stat(`${top}/${sub}`);
78
77
  if (stat.isFile()) {
79
78
  if (valid || STD_TOP_FILES.has(sub)) {
@@ -87,11 +86,7 @@ export class ManifestModuleUtil {
87
86
  }
88
87
  }
89
88
 
90
- if (!mainLike) {
91
- this.#scanCache[folder] = out;
92
- }
93
-
94
- return out;
89
+ return this.#scanCache[key] = out;
95
90
  }
96
91
 
97
92
  /**
@@ -177,12 +172,13 @@ export class ManifestModuleUtil {
177
172
  /**
178
173
  * Visit a module and describe files, and metadata
179
174
  */
180
- static async describeModule(ctx: ManifestContext, dep: ModuleDep): Promise<ManifestModule> {
181
- const { main, mainLike, local, name, version, sourcePath, roleSet, prod, parentSet, internal } = dep;
175
+ static async describeModule(ctx: ManifestContext, mod: PackageModule): Promise<ManifestModule> {
176
+ const { state, ...rest } = mod;
177
+ const sourcePath = path.resolve(ctx.workspace.path, rest.sourceFolder);
182
178
 
183
179
  const files: ManifestModule['files'] = {};
184
180
 
185
- for (const file of await this.scanFolder(sourcePath, mainLike)) {
181
+ for (const file of await this.scanFolder(sourcePath, rest.main)) {
186
182
  // Group by top folder
187
183
  const moduleFile = file.replace(`${sourcePath}/`, '');
188
184
  const entry = await this.transformFile(moduleFile, file);
@@ -190,30 +186,20 @@ export class ManifestModuleUtil {
190
186
  (files[key] ??= []).push(entry);
191
187
  }
192
188
 
193
- // Refine non-main source, remove anything in root that is source (doesn't include $index)
194
- if (!mainLike) {
195
- files.$root = files.$root?.filter(([file, type]) => type !== 'ts');
196
- }
197
-
198
- const roles = [...roleSet ?? []].sort();
199
- const parents = [...parentSet].sort();
200
- const outputFolder = `node_modules/${name}`;
201
- const sourceFolder = sourcePath === ctx.workspace.path ? '' : sourcePath.replace(`${ctx.workspace.path}/`, '');
202
-
203
- const res: ManifestModule = {
204
- main, name, version, local, internal, sourceFolder, outputFolder, roles, parents, prod, files
189
+ return {
190
+ ...rest,
191
+ roles: [...state.roleSet].sort(),
192
+ parents: [...state.parentSet].sort(),
193
+ files
205
194
  };
206
- return res;
207
195
  }
208
196
 
209
197
  /**
210
198
  * Produce all modules for a given manifest folder, adding in some given modules when developing framework
211
199
  */
212
200
  static async produceModules(ctx: ManifestContext): Promise<Record<string, ManifestModule>> {
213
- const visitor = new ModuleDependencyVisitor(ctx);
214
- const declared = await PackageUtil.visitPackages(visitor);
215
- const sorted = [...declared].sort((a, b) => a.name.localeCompare(b.name));
216
- const modules = await Promise.all(sorted.map(x => this.describeModule(ctx, x)));
201
+ const pkgs = await PackageUtil.visitPackages(new PackageModuleVisitor(ctx));
202
+ const modules = await Promise.all([...pkgs].map(x => this.describeModule(ctx, x)));
217
203
  return Object.fromEntries(modules.map(m => [m.name, m]));
218
204
  }
219
205
 
package/src/package.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { execSync } from 'node:child_process';
3
3
 
4
- import type { ManifestContext, NodePackageManager, Package, PackageVisitor, PackageVisitReq, PackageWorkspaceEntry } from './types';
5
4
  import { path } from './path';
6
5
  import { ManifestFileUtil } from './file';
7
6
 
7
+ import { PackagePath, type Package, type PackageVisitor, type PackageWorkspaceEntry } from './types/package';
8
+ import type { ManifestContext } from './types/context';
9
+ import type { NodePackageManager } from './types/common';
10
+
8
11
  /**
9
12
  * Utilities for querying, traversing and reading package.json files.
10
13
  */
@@ -31,9 +34,9 @@ export class PackageUtil {
31
34
  /**
32
35
  * Resolve version path, if file: url
33
36
  */
34
- static resolveVersionPath(rootPath: string, ver: string): string | undefined {
37
+ static resolveVersionPath(root: Package, ver: string): string | undefined {
35
38
  if (ver.startsWith('file:')) {
36
- return path.resolve(rootPath, ver.replace('file:', ''));
39
+ return path.resolve(this.getPackagePath(root), ver.replace('file:', ''));
37
40
  } else {
38
41
  return;
39
42
  }
@@ -54,31 +57,6 @@ export class PackageUtil {
54
57
  throw new Error(`Unable to resolve: ${name}`);
55
58
  }
56
59
 
57
- /**
58
- * Build a package visit req
59
- */
60
- static packageReq<T>(sourcePath: string, prod: boolean, topLevel?: boolean): PackageVisitReq<T> {
61
- return { pkg: this.readPackage(sourcePath), sourcePath, prod, topLevel };
62
- }
63
-
64
- /**
65
- * Extract all dependencies from a package
66
- */
67
- static getAllDependencies<T = unknown>(modulePath: string, local: boolean): PackageVisitReq<T>[] {
68
- const pkg = this.readPackage(modulePath);
69
- const children: Record<string, PackageVisitReq<T>> = {};
70
- for (const [deps, prod] of [
71
- [pkg.dependencies, true],
72
- ...(local ? [[pkg.devDependencies, false] as const] : []),
73
- ] as const) {
74
- for (const [name, version] of Object.entries(deps ?? {})) {
75
- const depPath = this.resolveVersionPath(modulePath, version) ?? this.resolvePackagePath(name);
76
- children[`${name}#${version}`] = this.packageReq<T>(depPath, prod, false);
77
- }
78
- }
79
- return Object.values(children).sort((a, b) => a.pkg.name.localeCompare(b.pkg.name));
80
- }
81
-
82
60
  /**
83
61
  * Read a package.json from a given folder
84
62
  */
@@ -92,86 +70,69 @@ export class PackageUtil {
92
70
 
93
71
  res.name ??= 'untitled'; // If a package.json (root-only) is missing a name, allows for npx execution
94
72
 
73
+ res[PackagePath] = modulePath;
95
74
  return res;
96
75
  }
97
76
 
98
77
  /**
99
- * import a package.json from a given module name
78
+ * Get the package path
100
79
  */
101
- static importPackage(moduleName: string): Package {
102
- return this.readPackage(this.resolvePackagePath(moduleName));
80
+ static getPackagePath(pkg: Package): string {
81
+ return pkg[PackagePath];
103
82
  }
104
83
 
105
84
  /**
106
85
  * Visit packages with ability to track duplicates
107
86
  */
108
- static async visitPackages<T>(visitor: PackageVisitor<T>): Promise<Set<T>> {
109
-
110
- const root = this.packageReq<T>(visitor.rootPath, false, true);
111
-
112
- const seen = new Map<string, T>();
113
- const queue: PackageVisitReq<T>[] = [...await visitor.init?.(root) ?? [], root];
114
- const out = new Set<T>();
87
+ static async visitPackages<T>(visitor: PackageVisitor<T>): Promise<Iterable<T>> {
88
+ const seen = new Set<T>();
89
+ const queue = [...await visitor.init()];
115
90
 
116
91
  while (queue.length) {
117
- const req = queue.pop();
92
+ const node = queue.shift()!; // Visit initial set first
118
93
 
119
- if (!req || (visitor.valid && !visitor.valid(req))) {
94
+ if (!visitor.valid(node)) {
120
95
  continue;
121
96
  }
122
97
 
123
- const key = req.sourcePath;
124
- if (seen.has(key)) {
125
- await visitor.visit?.(req, seen.get(key)!);
98
+ visitor.visit(node);
99
+
100
+ if (seen.has(node.value)) {
101
+ continue;
126
102
  } else {
127
- const dep = await visitor.create(req);
128
- out.add(dep);
129
- await visitor.visit?.(req, dep);
130
- seen.set(key, dep);
131
- const children = this.getAllDependencies<T>(
132
- req.sourcePath,
133
- // We consider a module local if its not in the node_modules
134
- !req.sourcePath.includes('node_modules') && (
135
- // And its the root or we are in a monorepo
136
- root.sourcePath === req.sourcePath ||
137
- !!root.pkg.workspaces
138
- )
139
- );
140
- queue.push(...children.map(x => ({ ...x, parent: dep })));
103
+ seen.add(node.value);
141
104
  }
105
+
106
+ const children = Object.entries(node.children)
107
+ .map(([n, v]) => this.readPackage(this.resolveVersionPath(node.pkg, v) ?? this.resolvePackagePath(n)))
108
+ .map(pkg => ({ ...visitor.create(pkg), parent: node.value }));
109
+
110
+ queue.push(...children);
142
111
  }
143
- return (await visitor.complete?.(out)) ?? out;
112
+
113
+ return await visitor.complete(seen);
144
114
  }
145
115
 
146
116
  /**
147
117
  * Find workspace values from rootPath
148
118
  */
149
- static async resolveWorkspaces(ctx: ManifestContext, rootPath: string): Promise<PackageWorkspaceEntry[]> {
150
- if (!this.#workspaces[rootPath]) {
151
- const cache = path.resolve(ctx.workspace.path, ctx.build.outputFolder, 'workspaces.json');
152
- try {
153
- return await ManifestFileUtil.readAsJson(cache);
154
- } catch (err) {
119
+ static async resolveWorkspaces(ctx: ManifestContext): Promise<PackageWorkspaceEntry[]> {
120
+ const rootPath = ctx.workspace.path;
121
+ const cache = path.resolve(rootPath, ctx.build.outputFolder, 'workspaces.json');
122
+ return this.#workspaces[rootPath] ??= await ManifestFileUtil.readAsJson<PackageWorkspaceEntry[]>(cache)
123
+ .catch(async () => {
155
124
  let out: PackageWorkspaceEntry[];
156
125
  switch (ctx.workspace.manager) {
126
+ case 'yarn':
157
127
  case 'npm': {
158
128
  const res = await this.#exec<{ location: string, name: string }[]>(rootPath, 'npm query .workspace');
159
- out = res.map(d => ({ sourcePath: d.location, name: d.name }));
160
- break;
161
- }
162
- case 'yarn': {
163
- const res = await this.#exec<Record<string, { location: string }>>(rootPath, 'npm query .workspace');
164
- out = Object.entries(res).map(([name, { location }]) => ({ sourcePath: location, name }));
129
+ out = res.map(d => ({ path: path.resolve(ctx.workspace.path, d.location), name: d.name }));
165
130
  break;
166
131
  }
167
132
  }
168
-
169
- this.#workspaces[rootPath] = out;
170
-
171
133
  await ManifestFileUtil.bufferedFileWrite(cache, out);
172
- }
173
- }
174
- return this.#workspaces[rootPath];
134
+ return out;
135
+ });
175
136
  }
176
137
 
177
138
  /**
package/src/runtime.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  import { path } from './path';
2
- import { IndexedModule, ManifestIndex } from './manifest-index';
3
- import { FunctionMetadata, ManifestContext, ManifestModule } from './types';
2
+ import { ManifestIndex } from './manifest-index';
3
+
4
+ import type { FunctionMetadata } from './types/common';
5
+ import type { IndexedModule, ManifestModule } from './types/manifest';
6
+ import type { ManifestContext } from './types/context';
4
7
 
5
8
  const METADATA = Symbol.for('@travetto/manifest:metadata');
6
9
  type Metadated = { [METADATA]: FunctionMetadata };
@@ -122,5 +125,19 @@ export const RuntimeContext = build({
122
125
  */
123
126
  workspaceRelative(...rel: string[]): string {
124
127
  return path.resolve(RuntimeIndex.manifest.workspace.path, ...rel);
128
+ },
129
+ /**
130
+ * Produce a workspace path for tooling, with '@' being replaced by node_module/name folder
131
+ * @param rel The relative path
132
+ */
133
+ toolPath(...rel: string[]): string {
134
+ rel = rel.flatMap(x => x === '@' ? ['node_modules', RuntimeIndex.manifest.main.name] : [x]);
135
+ return path.resolve(RuntimeIndex.manifest.workspace.path, RuntimeIndex.manifest.build.toolFolder, ...rel);
136
+ },
137
+ /**
138
+ * Are we running from a mono-root?
139
+ */
140
+ get monoRoot(): boolean {
141
+ return !!RuntimeIndex.manifest.workspace.mono && !RuntimeIndex.manifest.main.folder;
125
142
  }
126
143
  }, ['main', 'workspace']);
@@ -0,0 +1,20 @@
1
+ export type NodeModuleType = 'module' | 'commonjs';
2
+ export type NodePackageManager = 'yarn' | 'npm';
3
+
4
+ export type ManifestModuleFileType = 'typings' | 'ts' | 'js' | 'json' | 'package-json' | 'unknown' | 'fixture' | 'md';
5
+ export type ManifestModuleFolderType =
6
+ '$root' | '$index' | '$package' |
7
+ 'src' | 'bin' | 'support' | 'resources' | 'test' | 'doc' |
8
+ 'test/fixtures' | 'support/fixtures' | 'support/resources' |
9
+ '$other' | '$transformer';
10
+
11
+ export type ManifestModuleRole = 'std' | 'test' | 'doc' | 'compile' | 'build';
12
+
13
+ export type FunctionMetadata = {
14
+ id: string;
15
+ source: string;
16
+ hash?: number;
17
+ methods?: Record<string, { hash: number }>;
18
+ synthetic?: boolean;
19
+ abstract?: boolean;
20
+ };
@@ -0,0 +1,40 @@
1
+ import type { NodeModuleType, NodePackageManager } from './common';
2
+
3
+ export type ManifestContext = {
4
+ workspace: {
5
+ /** Workspace path for module */
6
+ path: string;
7
+ /** The module name for the workspace root */
8
+ name: string;
9
+ /** Is the workspace a monorepo? */
10
+ mono?: boolean;
11
+ /** The module type of the workspace */
12
+ type: NodeModuleType;
13
+ /** The package manager of the workspace */
14
+ manager: NodePackageManager;
15
+ /** The default env name */
16
+ defaultEnv: string;
17
+ };
18
+ build: {
19
+ /** Compiler folder, relative to workspace */
20
+ compilerFolder: string;
21
+ /** Compiler module folder */
22
+ compilerModuleFolder: string;
23
+ /** URL for the compiler server */
24
+ compilerUrl: string;
25
+ /** Code output folder, relative to workspace */
26
+ outputFolder: string;
27
+ /** Location of development-time tool output */
28
+ toolFolder: string;
29
+ };
30
+ main: {
31
+ /** Main module for manifest */
32
+ name: string;
33
+ /** Folder, relative to workspace for main module */
34
+ folder: string;
35
+ /** Description of the main module */
36
+ description?: string;
37
+ /** Version of the main module */
38
+ version: string;
39
+ };
40
+ };
@@ -0,0 +1,79 @@
1
+ import type { ManifestModuleFileType, ManifestModuleFolderType, ManifestModuleRole } from './common';
2
+ import type { ManifestContext } from './context';
3
+ import { Package } from './package';
4
+
5
+ export type ManifestModuleFile = [string, ManifestModuleFileType, number] | [string, ManifestModuleFileType, number, ManifestModuleRole];
6
+
7
+ export type ManifestDepCore = {
8
+ /** Package name */
9
+ name: string;
10
+ /** Package version */
11
+ version: string;
12
+ /** Is this the main module */
13
+ main?: boolean;
14
+ /** Is this a module that is part of the workspace */
15
+ workspace?: boolean;
16
+ /** Should this module be deployed to prod? */
17
+ prod: boolean;
18
+ /** Is the module intended to be published? */
19
+ internal?: boolean;
20
+ };
21
+
22
+ export type ManifestModuleCore = ManifestDepCore & {
23
+ sourceFolder: string;
24
+ outputFolder: string;
25
+ roles: ManifestModuleRole[];
26
+ parents: string[];
27
+ };
28
+
29
+ export type ManifestModule = ManifestModuleCore & {
30
+ files: Partial<Record<ManifestModuleFolderType, ManifestModuleFile[]>>;
31
+ };
32
+
33
+ export type ManifestRoot = ManifestContext & {
34
+ generated: number;
35
+ modules: Record<string, ManifestModule>;
36
+ };
37
+
38
+ export type FindConfig = {
39
+ folder?: (folder: ManifestModuleFolderType) => boolean;
40
+ module?: (module: IndexedModule) => boolean;
41
+ file?: (file: IndexedFile) => boolean;
42
+ sourceOnly?: boolean;
43
+ };
44
+
45
+ export type IndexedFile = {
46
+ id: string;
47
+ import: string;
48
+ module: string;
49
+ sourceFile: string;
50
+ outputFile: string;
51
+ relativeFile: string;
52
+ role: ManifestModuleRole;
53
+ type: ManifestModuleFileType;
54
+ };
55
+
56
+ export type IndexedModule = ManifestModuleCore & {
57
+ sourcePath: string;
58
+ outputPath: string;
59
+ files: Record<ManifestModuleFolderType, IndexedFile[]>;
60
+ children: Set<string>;
61
+ };
62
+
63
+ /** Module dependency, used in dependency visiting */
64
+ export type PackageModule = Omit<ManifestModule, 'files' | 'parents' | 'roles'> & {
65
+ state: {
66
+ /** Role root? */
67
+ roleRoot?: boolean;
68
+ /** Travetto package info */
69
+ travetto?: Package['travetto'];
70
+ /** Prod dependencies */
71
+ prodDeps: Set<string>;
72
+ /** Set of parent package names */
73
+ parentSet: Set<string>;
74
+ /** Set of child package names */
75
+ childSet: Set<string>;
76
+ /** Defined roles for a given module */
77
+ roleSet: Set<ManifestModuleRole>;
78
+ };
79
+ };