@travetto/manifest 4.0.0-rc.4 → 4.0.0-rc.6

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
@@ -53,7 +53,7 @@ const tslib_1 = require("tslib");
53
53
  const Ⲑ_runtime_1 = tslib_1.__importStar(require("@travetto/manifest/src/runtime.js"));
54
54
  var ᚕf = "@travetto/manifest/doc/test-class.js";
55
55
  class TestClass {
56
- static Ⲑinit = Ⲑ_runtime_1.RuntimeIndex.registerFunction(TestClass, ᚕf, 197152026, { doStuff: { hash: 51337554 } }, false, false);
56
+ static Ⲑinit = Ⲑ_runtime_1.RuntimeIndex.registerFunction(TestClass, ᚕf, { hash: 197152026, lines: [1, 3] }, { doStuff: { hash: 51337554, lines: [2, 2] } }, false, false);
57
57
  async doStuff() { }
58
58
  }
59
59
  exports.TestClass = TestClass;
@@ -67,7 +67,8 @@ $ trv main ./doc/lookup.ts
67
67
  id: '@travetto/manifest:doc/test-class○TestClass',
68
68
  source: './doc/test-class.ts',
69
69
  hash: 197152026,
70
- methods: { doStuff: { hash: 51337554 } },
70
+ lines: [ 1, 3 ],
71
+ methods: { doStuff: { hash: 51337554, lines: [Array] } },
71
72
  abstract: false,
72
73
  synthetic: false
73
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/manifest",
3
- "version": "4.0.0-rc.4",
3
+ "version": "4.0.0-rc.6",
4
4
  "description": "Support for project indexing, manifesting, along with file watching",
5
5
  "keywords": [
6
6
  "path",
@@ -23,23 +23,56 @@ type Req = {
23
23
  */
24
24
  export class PackageModuleVisitor {
25
25
 
26
- constructor(public ctx: ManifestContext) {
27
- this.#mainSourcePath = path.resolve(this.ctx.workspace.path, this.ctx.main.folder);
26
+ static async visit(ctx: ManifestContext): Promise<Iterable<PackageModule>> {
27
+ const visitor = new PackageModuleVisitor(ctx, Object.fromEntries((await PackageUtil.resolveWorkspaces(ctx)).map(x => [x.name, x.path])));
28
+ return visitor.visit();
28
29
  }
29
30
 
30
31
  #mainSourcePath: string;
31
32
  #cache: Record<string, PackageModule> = {};
32
- #workspaceModules: Map<string, string>;
33
+ #workspaceModules: Record<string, string>;
34
+ #ctx: ManifestContext;
35
+
36
+ constructor(ctx: ManifestContext, workspaceModules: Record<string, string>) {
37
+ this.#mainSourcePath = path.resolve(ctx.workspace.path, ctx.main.folder);
38
+ this.#ctx = ctx;
39
+ this.#workspaceModules = workspaceModules;
40
+ }
41
+
42
+ /**
43
+ * Build a package module
44
+ */
45
+ #create(sourcePath: string, { main, workspace, prod = false, roleRoot = false, parent }: CreateOpts = {}): Req {
46
+ const pkg = PackageUtil.readPackage(sourcePath);
47
+ const value = this.#cache[sourcePath] ??= {
48
+ main,
49
+ prod,
50
+ name: pkg.name,
51
+ version: pkg.version,
52
+ workspace: workspace ?? (pkg.name in this.#workspaceModules),
53
+ internal: pkg.private === true,
54
+ sourceFolder: sourcePath === this.#ctx.workspace.path ? '' : sourcePath.replace(`${this.#ctx.workspace.path}/`, ''),
55
+ outputFolder: `node_modules/${pkg.name}`,
56
+ state: {
57
+ childSet: new Set(), parentSet: new Set(), roleSet: new Set(), roleRoot,
58
+ travetto: pkg.travetto, prodDeps: new Set(Object.keys(pkg.dependencies ?? {}))
59
+ }
60
+ };
61
+
62
+ const deps: PackageDepType[] = ['dependencies', ...(value.main ? ['devDependencies'] as const : [])];
63
+ const children = Object.fromEntries(deps.flatMap(x => Object.entries(pkg[x] ?? {})));
64
+ return { pkg, value, children, parent };
65
+ }
33
66
 
34
67
  /**
35
68
  * Get monorepo root includes
36
69
  */
37
70
  #getMonoRootIncludes(parent: Req): Req[] {
38
- if (!(this.ctx.workspace.mono && !this.ctx.main.folder)) { // If not mono root, bail
71
+ if (!(this.#ctx.workspace.mono && !this.#ctx.main.folder)) { // If not mono root, bail
39
72
  return [];
40
73
  }
41
74
 
42
- return [...this.#workspaceModules.values()]
75
+ return Object.values(this.#workspaceModules)
43
76
  .map(loc => this.#create(loc, { main: true, workspace: true, roleRoot: true, parent: parent.value }));
44
77
  }
45
78
 
@@ -47,63 +80,22 @@ export class PackageModuleVisitor {
47
80
  * Determine default includes
48
81
  */
49
82
  #getIncludes(parent: Req): Req[] {
50
- if (this.ctx.workspace.mono && !this.ctx.main.folder) { // If mono and not at mono root, bail
83
+ if (this.#ctx.workspace.mono && !this.#ctx.main.folder) { // If mono and not at mono root, bail
51
84
  return [];
52
85
  }
53
86
 
54
- const root = PackageUtil.readPackage(this.ctx.workspace.path);
87
+ const root = PackageUtil.readPackage(this.#ctx.workspace.path);
55
88
  if (root.travetto?.build?.includes) {
56
89
  return Object.entries(root.travetto.build.includes).map(([name, type]) =>
57
90
  this.#create(PackageUtil.resolvePackagePath(name), { main: type === 'main', workspace: true, parent: parent.value })
58
91
  );
59
92
  } else {
60
- return [...this.#workspaceModules.values()]
93
+ return Object.values(this.#workspaceModules)
61
94
  .filter((loc) => PackageUtil.readPackage(loc).travetto?.workspaceInclude)
62
95
  .map(loc => this.#create(loc, { workspace: true, parent: parent.value }));
63
96
  }
64
97
  }
65
98
 
66
- /**
67
- * Initialize visitor, and provide global dependencies
68
- */
69
- async init(): Promise<Iterable<Req>> {
70
- const mainReq = this.#create(this.#mainSourcePath, { main: true, workspace: true, roleRoot: true, prod: true });
71
- this.#workspaceModules = new Map(
72
- (await PackageUtil.resolveWorkspaces(this.ctx)).map(x => [x.name, x.path])
73
- );
74
-
75
- return [
76
- mainReq,
77
- ...this.#getMonoRootIncludes(mainReq),
78
- ...this.#getIncludes(mainReq)
79
- ];
80
- }
81
-
82
- /**
83
- * Build a package module
84
- */
85
- #create(sourcePath: string, { main, workspace, prod = false, roleRoot = false, parent }: CreateOpts = {}): Req {
86
- const pkg = PackageUtil.readPackage(sourcePath);
87
- const value = this.#cache[sourcePath] ??= {
88
- main,
89
- prod,
90
- name: pkg.name,
91
- version: pkg.version,
92
- workspace: workspace ?? this.#workspaceModules.has(pkg.name),
93
- internal: pkg.private === true,
94
- sourceFolder: sourcePath === this.ctx.workspace.path ? '' : sourcePath.replace(`${this.ctx.workspace.path}/`, ''),
95
- outputFolder: `node_modules/${pkg.name}`,
96
- state: {
97
- childSet: new Set(), parentSet: new Set(), roleSet: new Set(), roleRoot,
98
- travetto: pkg.travetto, prodDeps: new Set(Object.keys(pkg.dependencies ?? {}))
99
- }
100
- };
101
-
102
- const deps: PackageDepType[] = ['dependencies', ...(value.main ? ['devDependencies'] as const : [])];
103
- const children = Object.fromEntries(deps.flatMap(x => Object.entries(pkg[x] ?? {})));
104
- return { pkg, value, children, parent };
105
- }
106
-
107
99
  /**
108
100
  * Propagate prod, role information through graph
109
101
  */
@@ -163,7 +155,13 @@ export class PackageModuleVisitor {
163
155
  */
164
156
  async visit(): Promise<Iterable<PackageModule>> {
165
157
  const seen = new Set<PackageModule>();
166
- const queue = [...await this.init()];
158
+ const mainReq = this.#create(this.#mainSourcePath, { main: true, workspace: true, roleRoot: true, prod: true });
159
+
160
+ const queue = [
161
+ mainReq,
162
+ ...this.#getMonoRootIncludes(mainReq),
163
+ ...this.#getIncludes(mainReq)
164
+ ];
167
165
 
168
166
  while (queue.length) {
169
167
  const { value: node, parent, children, pkg } = queue.shift()!; // Visit initial set first
@@ -172,7 +170,7 @@ export class PackageModuleVisitor {
172
170
  }
173
171
 
174
172
  // Track parentage
175
- if (node.name !== this.ctx.main.name && parent) {
173
+ if (node.name !== this.#ctx.main.name && parent) {
176
174
  node.state.parentSet.add(parent.name);
177
175
  parent.state.childSet.add(node.name);
178
176
  }
package/src/module.ts CHANGED
@@ -197,7 +197,7 @@ export class ManifestModuleUtil {
197
197
  * Produce all modules for a given manifest folder, adding in some given modules when developing framework
198
198
  */
199
199
  static async produceModules(ctx: ManifestContext): Promise<Record<string, ManifestModule>> {
200
- const pkgs = await new PackageModuleVisitor(ctx).visit();
200
+ const pkgs = await PackageModuleVisitor.visit(ctx);
201
201
  const modules = await Promise.all([...pkgs].map(x => this.describeModule(ctx, x)));
202
202
  return Object.fromEntries(modules.map(m => [m.name, m]));
203
203
  }
package/src/package.ts CHANGED
@@ -78,7 +78,7 @@ export class PackageUtil {
78
78
  * Get the package path
79
79
  */
80
80
  static getPackagePath(pkg: Package): string {
81
- return pkg[PackagePath];
81
+ return pkg[PackagePath]!;
82
82
  }
83
83
 
84
84
  /**
package/src/runtime.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { path } from './path';
2
2
  import { ManifestIndex } from './manifest-index';
3
3
 
4
- import type { FunctionMetadata } from './types/common';
4
+ import type { FunctionMetadata, FunctionMetadataTag } from './types/common';
5
5
  import type { IndexedModule, ManifestModule } from './types/manifest';
6
6
  import type { ManifestContext } from './types/context';
7
7
 
@@ -52,16 +52,21 @@ class $RuntimeIndex extends ManifestIndex {
52
52
  * @param cls Class
53
53
  * @param `file` Filename
54
54
  * @param `hash` Hash of class contents
55
+ * @param `line` Line number in source
55
56
  * @param `methods` Methods and their hashes
56
57
  * @param `abstract` Is the class abstract
58
+ * @param `synthetic` Is this code generated at build time
57
59
  */
58
- registerFunction(cls: Function, fileOrImport: string, hash: number, methods?: Record<string, { hash: number }>, abstract?: boolean, synthetic?: boolean): boolean {
60
+ registerFunction(
61
+ cls: Function, fileOrImport: string, tag: FunctionMetadataTag,
62
+ methods?: Record<string, FunctionMetadataTag>, abstract?: boolean, synthetic?: boolean
63
+ ): boolean {
59
64
  const source = this.getSourceFile(fileOrImport);
60
65
  const id = this.getId(source, cls.name);
61
66
  Object.defineProperty(cls, 'Ⲑid', { value: id });
62
67
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
63
- (cls as unknown as Metadated)[METADATA] = { id, source, hash, methods, abstract, synthetic };
64
- this.#metadata.set(id, { id, source, hash, methods, abstract, synthetic });
68
+ (cls as unknown as Metadated)[METADATA] = { id, source, ...tag, methods, abstract, synthetic };
69
+ this.#metadata.set(id, { id, source, ...tag, methods, abstract, synthetic });
65
70
  return true;
66
71
  }
67
72
 
@@ -10,11 +10,11 @@ export type ManifestModuleFolderType =
10
10
 
11
11
  export type ManifestModuleRole = 'std' | 'test' | 'doc' | 'compile' | 'build';
12
12
 
13
- export type FunctionMetadata = {
13
+ export type FunctionMetadataTag = { hash: number, lines: [number, number] };
14
+ export type FunctionMetadata = FunctionMetadataTag & {
14
15
  id: string;
15
16
  source: string;
16
- hash?: number;
17
- methods?: Record<string, { hash: number }>;
17
+ methods?: Record<string, FunctionMetadataTag>;
18
18
  synthetic?: boolean;
19
19
  abstract?: boolean;
20
20
  };
@@ -4,7 +4,7 @@ import type { ManifestContext } from './context';
4
4
  export const PackagePath = Symbol.for('@travetto/manifest:package-path');
5
5
 
6
6
  export type Package = {
7
- [PackagePath]: string;
7
+ [PackagePath]?: string;
8
8
  name: string;
9
9
  type?: NodeModuleType;
10
10
  version: string;
package/src/util.ts CHANGED
@@ -116,9 +116,9 @@ export class ManifestUtil {
116
116
  /**
117
117
  * Produce the manifest context for a given module module
118
118
  */
119
- static getModuleContext(ctx: ManifestContext, folder: string): ManifestContext {
119
+ static getModuleContext(ctx: ManifestContext, folder: string, ensureLatest = false): ManifestContext {
120
120
  const modPath = path.resolve(ctx.workspace.path, folder);
121
- const pkg = PackageUtil.readPackage(modPath);
121
+ const pkg = PackageUtil.readPackage(modPath, ensureLatest);
122
122
 
123
123
  return {
124
124
  workspace: ctx.workspace,
@@ -5,6 +5,8 @@ import {
5
5
  AfterFunction, CoreUtil, SystemUtil, Import
6
6
  } from '@travetto/transformer';
7
7
 
8
+ import type { FunctionMetadataTag } from '../src/types/common';
9
+
8
10
  const MANIFEST_MOD = '@travetto/manifest';
9
11
  const MANIFEST_IDX = `${MANIFEST_MOD}/__index__`;
10
12
 
@@ -18,10 +20,8 @@ const runtimeIdx = Symbol.for(`${MANIFEST_MOD}:runtimeIndex`);
18
20
 
19
21
  interface MetadataInfo {
20
22
  [runtimeIdx]?: Import;
21
- [methods]?: {
22
- [key: string]: { hash: number };
23
- };
24
- [cls]?: number;
23
+ [methods]?: Record<string, FunctionMetadataTag>;
24
+ [cls]?: FunctionMetadataTag;
25
25
  [fn]?: number;
26
26
  }
27
27
 
@@ -30,6 +30,16 @@ interface MetadataInfo {
30
30
  */
31
31
  export class RegisterTransformer {
32
32
 
33
+ static #tag(state: TransformerState, node: ts.Node): FunctionMetadataTag {
34
+ const hash = SystemUtil.naiveHash(node.getText());
35
+ try {
36
+ const range = CoreUtil.getRangeOf(state.source, node) ?? [0, 0];
37
+ return { hash, lines: range };
38
+ } catch (err) {
39
+ return { hash, lines: [0, 0] };
40
+ }
41
+ }
42
+
33
43
  static #valid({ importName: imp }: TransformerState): boolean {
34
44
  return !imp.startsWith(MANIFEST_MOD) || !(/[/](src|support)[/]/.test(imp) || imp === MANIFEST_IDX);
35
45
  }
@@ -42,7 +52,7 @@ export class RegisterTransformer {
42
52
  if (!this.#valid(state)) {
43
53
  return node; // Exclude self
44
54
  }
45
- state[cls] = SystemUtil.naiveHash(node.getText());
55
+ state[cls] = this.#tag(state, node);
46
56
  return node;
47
57
  }
48
58
 
@@ -52,10 +62,8 @@ export class RegisterTransformer {
52
62
  @OnMethod()
53
63
  static collectMethodMetadata(state: TransformerState & MetadataInfo, node: ts.MethodDeclaration): ts.MethodDeclaration {
54
64
  if (state[cls] && ts.isIdentifier(node.name) && !CoreUtil.isAbstract(node) && ts.isClassDeclaration(node.parent)) {
55
- const hash = SystemUtil.naiveHash(node.getText());
56
- const conf = { hash };
57
65
  state[methods] ??= {};
58
- state[methods]![node.name.escapedText.toString()] = conf;
66
+ state[methods]![node.name.escapedText.toString()] = this.#tag(state, node);
59
67
  }
60
68
  return node;
61
69
  }
@@ -80,7 +88,7 @@ export class RegisterTransformer {
80
88
  [
81
89
  state.createIdentifier(name),
82
90
  state.getFilenameIdentifier(),
83
- state.fromLiteral(state[cls]!),
91
+ state.fromLiteral(state[cls]),
84
92
  state.extendObjectLiteral(state[methods] || {}),
85
93
  state.fromLiteral(CoreUtil.isAbstract(node)),
86
94
  state.fromLiteral(name.endsWith(TransformerState.SYNTHETIC_EXT))
@@ -116,13 +124,14 @@ export class RegisterTransformer {
116
124
  // If we have a class like function
117
125
  state[runtimeIdx] ??= state.importFile(RUNTIME_IDX_IMPORT);
118
126
  const ident = state.createAccess(state[runtimeIdx].ident, RUNTIME_IDX_CLS);
127
+ const tag = this.#tag(state, node);
119
128
  const meta = state.factory.createCallExpression(
120
129
  state.createAccess(ident, 'registerFunction'),
121
130
  [],
122
131
  [
123
132
  state.createIdentifier(node.name),
124
133
  state.getFilenameIdentifier(),
125
- state.fromLiteral(SystemUtil.naiveHash(node.getText())),
134
+ state.fromLiteral(tag),
126
135
  ]
127
136
  );
128
137
  state.addStatements([state.factory.createExpressionStatement(meta)]);