@atlaspack/query 2.12.1-canary.3354

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/src/cli.js ADDED
@@ -0,0 +1,1128 @@
1
+ // @flow strict-local
2
+ /* eslint-disable no-console, monorepo/no-internal-import */
3
+ import type {ContentGraph, ContentKey, NodeId} from '@atlaspack/graph';
4
+ import type {BundleGraphEdgeType} from '@atlaspack/core/src/BundleGraph';
5
+ import type {AssetGraphNode, BundleGraphNode} from '@atlaspack/core/src/types';
6
+
7
+ import path from 'path';
8
+ import fs from 'fs';
9
+ import repl from 'repl';
10
+ import os from 'os';
11
+ import nullthrows from 'nullthrows';
12
+ import invariant from 'assert';
13
+ import {serialize} from 'v8';
14
+ // $FlowFixMe
15
+ import {table} from 'table';
16
+
17
+ import {loadGraphs} from './index.js';
18
+
19
+ const {
20
+ BundleGraph: {bundleGraphEdgeTypes: bundleGraphEdgeTypes},
21
+ Priority,
22
+ fromProjectPathRelative,
23
+ } = require('./deep-imports.js');
24
+
25
+ export async function run(input: string[]) {
26
+ let args = input;
27
+ let cacheDir = path.join(process.cwd(), '.atlaspack-cache');
28
+ if (args[0] === '--cache') {
29
+ cacheDir = path.resolve(process.cwd(), args[1]);
30
+ args = args.slice(2);
31
+ }
32
+ let initialCmd = args[0];
33
+
34
+ try {
35
+ fs.accessSync(cacheDir);
36
+ } catch (e) {
37
+ console.error("Can't find cache dir", cacheDir);
38
+ process.exit(1);
39
+ }
40
+
41
+ console.log('Loading graphs...');
42
+ let {assetGraph, bundleGraph, bundleInfo, requestTracker, cacheInfo} =
43
+ await loadGraphs(cacheDir);
44
+
45
+ function hasRequestTracker() {
46
+ if (requestTracker == null) {
47
+ console.error('Request Graph could not be found');
48
+ return false;
49
+ }
50
+ return true;
51
+ }
52
+
53
+ function hasBundleGraph() {
54
+ if (bundleGraph == null) {
55
+ console.error('Bundle Graph could not be found');
56
+ return false;
57
+ }
58
+ return true;
59
+ }
60
+
61
+ function hasAssetGraph() {
62
+ if (assetGraph == null) {
63
+ console.error('Asset Graph could not be found');
64
+ return false;
65
+ }
66
+ return true;
67
+ }
68
+
69
+ function hasBundleInfo() {
70
+ if (bundleInfo == null) {
71
+ console.error('Bundle Info could not be found');
72
+ return false;
73
+ }
74
+ return true;
75
+ }
76
+
77
+ // -------------------------------------------------------
78
+
79
+ function getBundleFilePath(id: ContentKey) {
80
+ if (!hasBundleInfo()) {
81
+ return;
82
+ }
83
+ invariant(bundleInfo != null);
84
+ return fromProjectPathRelative(nullthrows(bundleInfo.get(id)?.filePath));
85
+ }
86
+
87
+ function parseAssetLocator(v: string) {
88
+ let id: ?string = null;
89
+ if (v.length === 16) {
90
+ id = v;
91
+ } else {
92
+ if (!hasBundleGraph()) {
93
+ return;
94
+ }
95
+ invariant(bundleGraph != null);
96
+ for (let [assetId, publicId] of bundleGraph._publicIdByAssetId) {
97
+ if (publicId === v) {
98
+ id = assetId;
99
+ break;
100
+ }
101
+ }
102
+ }
103
+
104
+ if (id == null && v.length > 0) {
105
+ if (!hasAssetGraph()) {
106
+ return;
107
+ }
108
+ invariant(assetGraph != null);
109
+ let assetRegex = new RegExp(v);
110
+ for (let node of assetGraph.nodes.values()) {
111
+ if (
112
+ node?.type === 'asset' &&
113
+ assetRegex.test(fromProjectPathRelative(node.value.filePath))
114
+ ) {
115
+ id = node.id;
116
+ break;
117
+ }
118
+ }
119
+ }
120
+ return id;
121
+ }
122
+
123
+ function parseBundleLocator(v: string) {
124
+ if (!hasBundleGraph()) {
125
+ return;
126
+ }
127
+ invariant(bundleGraph != null);
128
+ let bundleRegex = new RegExp(v);
129
+ for (let b of bundleGraph.getBundles()) {
130
+ let bundleFilePath = getBundleFilePath(b.id);
131
+ if (
132
+ (bundleFilePath !== undefined && bundleRegex.test(bundleFilePath)) ||
133
+ b.id === v
134
+ ) {
135
+ return b.id;
136
+ }
137
+ }
138
+ }
139
+
140
+ function getAsset(v: string) {
141
+ let id: ?string = parseAssetLocator(v);
142
+
143
+ if (id == null) {
144
+ console.log(null);
145
+ } else {
146
+ try {
147
+ if (!hasBundleGraph()) {
148
+ return;
149
+ }
150
+ invariant(bundleGraph != null);
151
+ let asset = bundleGraph.getAssetById(id);
152
+ console.log('Public id', bundleGraph.getAssetPublicId(asset));
153
+ console.log(asset);
154
+ } catch (e) {
155
+ if (!hasAssetGraph()) {
156
+ return;
157
+ }
158
+ invariant(assetGraph != null);
159
+ let node = nullthrows(assetGraph.getNodeByContentKey(id));
160
+ invariant(node.type === 'asset');
161
+ console.log(node.value);
162
+ }
163
+ }
164
+ }
165
+
166
+ function _findAssetNode(v: string) {
167
+ if (!hasAssetGraph()) {
168
+ return;
169
+ }
170
+ invariant(assetGraph != null);
171
+ let assetRegex = new RegExp(v);
172
+ for (let node of assetGraph.nodes.values()) {
173
+ if (
174
+ node?.type === 'asset' &&
175
+ assetRegex.test(fromProjectPathRelative(node.value.filePath))
176
+ ) {
177
+ return node;
178
+ }
179
+ }
180
+ }
181
+
182
+ function findAsset(v: string) {
183
+ let node = _findAssetNode(v);
184
+ if (node) {
185
+ try {
186
+ if (!hasBundleGraph()) {
187
+ return;
188
+ }
189
+ invariant(bundleGraph != null);
190
+ console.log(
191
+ `${bundleGraph.getAssetPublicId(
192
+ bundleGraph.getAssetById(node.id),
193
+ )} ${fromProjectPathRelative(node.value.filePath)}`,
194
+ );
195
+ } catch (e) {
196
+ console.log(fromProjectPathRelative(node.value.filePath));
197
+ }
198
+ }
199
+ }
200
+
201
+ function findAssetWithSymbol(local: string) {
202
+ if (!hasBundleGraph() || !hasAssetGraph()) {
203
+ return;
204
+ }
205
+ invariant(bundleGraph != null);
206
+ invariant(assetGraph != null);
207
+ let [, assetId, binding, ref] = nullthrows(
208
+ local.match(/^\$([^$]+)\$([^$]+)\$(.*)$/),
209
+ `symbol ${local} could not be resolved`,
210
+ );
211
+
212
+ let asset;
213
+ // Search against the id used by the JSTransformer and ScopeHoistingPackager,
214
+ // not the final asset id, as it may have changed with further transformation.
215
+ for (let node of assetGraph.nodes.values()) {
216
+ if (node?.type === 'asset' && node.value.meta.id === assetId) {
217
+ asset = node;
218
+ break;
219
+ }
220
+ }
221
+
222
+ // If the asset couldn't be found by searching for the id,
223
+ // search for the local name in asset used symbols.
224
+ if (asset == null) {
225
+ outer: for (let node of assetGraph.nodes.values()) {
226
+ if (node?.type === 'asset' && node.value.symbols) {
227
+ for (let symbol of node.value.symbols.values()) {
228
+ if (symbol.local === local) {
229
+ asset = node;
230
+ break outer;
231
+ }
232
+ }
233
+ }
234
+ }
235
+ }
236
+
237
+ invariant(asset, `An asset for ${assetId} could not be found`);
238
+ invariant(
239
+ asset.type === 'asset',
240
+ `Expected ${assetId} to be an asset, but found a ${asset.type}`,
241
+ );
242
+
243
+ try {
244
+ console.log(
245
+ `${bundleGraph.getAssetPublicId(
246
+ bundleGraph.getAssetById(asset.id),
247
+ )} ${fromProjectPathRelative(asset.value.filePath)}`,
248
+ );
249
+ } catch (e) {
250
+ console.log(fromProjectPathRelative(asset.value.filePath));
251
+ }
252
+ if (binding === 'export' && asset.value.symbols) {
253
+ for (let [symbolName, symbol] of asset.value.symbols) {
254
+ if (symbol.local === local) {
255
+ if (symbol.loc) {
256
+ let locPath = symbol.loc.filePath;
257
+ let locAsset = _findAssetNode(String(locPath));
258
+ if (locAsset != null) {
259
+ try {
260
+ console.log(
261
+ `${bundleGraph.getAssetPublicId(
262
+ bundleGraph.getAssetById(locAsset.id),
263
+ )} ${fromProjectPathRelative(locAsset.value.filePath)}`,
264
+ );
265
+ } catch (e) {
266
+ console.log(
267
+ `imported as ${symbolName} from ${fromProjectPathRelative(
268
+ locAsset.value.filePath,
269
+ )}`,
270
+ );
271
+ }
272
+ } else {
273
+ console.log(
274
+ `imported as ${symbolName} from ${fromProjectPathRelative(
275
+ locPath,
276
+ )}`,
277
+ );
278
+ }
279
+ } else {
280
+ console.log(`imported as ${symbolName}`);
281
+ }
282
+ }
283
+ }
284
+ } else if (ref) {
285
+ console.log(`possibly defined as ${ref}`);
286
+ }
287
+ }
288
+
289
+ function getNodeAssetGraph(v: string) {
290
+ if (!hasAssetGraph()) {
291
+ return;
292
+ }
293
+ invariant(assetGraph != null);
294
+ console.log(assetGraph.getNodeByContentKey(v));
295
+ }
296
+ function getNodeBundleGraph(v: string) {
297
+ if (!hasBundleGraph()) {
298
+ return;
299
+ }
300
+ invariant(bundleGraph != null);
301
+ console.log(bundleGraph._graph.getNodeByContentKey(v));
302
+ }
303
+
304
+ class Paths<T> {
305
+ value: T;
306
+ label: string;
307
+ suffix: string;
308
+ children: Array<Paths<T>> = [];
309
+ constructor(value: T, label = '-', suffix = '') {
310
+ this.value = value;
311
+ this.label = label;
312
+ this.suffix = suffix;
313
+ }
314
+ add(v: T, label: string | void, suffix: string | void): Paths<T> {
315
+ let next = new Paths(v, label, suffix);
316
+ this.children.push(next);
317
+ return next;
318
+ }
319
+ print(format: T => string, prefix = '') {
320
+ console.log(
321
+ `${prefix}${this.label} ${format(this.value)} ${this.suffix}`,
322
+ );
323
+ for (let i = 0; i < this.children.length; i++) {
324
+ this.children[i].print(format, prefix + ' ');
325
+ }
326
+ }
327
+ }
328
+
329
+ function _findEntries(
330
+ graph:
331
+ | ContentGraph<BundleGraphNode, BundleGraphEdgeType>
332
+ | ContentGraph<AssetGraphNode>,
333
+ v: string,
334
+ ) {
335
+ let asset = nullthrows(parseAssetLocator(v), 'Asset not found');
336
+
337
+ let paths = new Paths<NodeId>(graph.getNodeIdByContentKey(asset), ' ');
338
+ let cb = (id, ctx, revisiting) => {
339
+ let {paths, lazyOutgoing} = ctx;
340
+ let node = nullthrows(graph.getNode(id));
341
+ if (node.id === asset) return ctx;
342
+ if (node.type === 'asset') {
343
+ paths = paths.add(
344
+ id,
345
+ lazyOutgoing ? '<' : undefined,
346
+ revisiting ? '(revisiting)' : undefined,
347
+ );
348
+ lazyOutgoing = false;
349
+ } else if (node.type === 'dependency') {
350
+ if (node.value.priority === Priority.lazy) {
351
+ lazyOutgoing = true;
352
+ }
353
+ }
354
+ return {paths, lazyOutgoing};
355
+ };
356
+
357
+ // like graph.dfs, but revisiting nodes and skipping its children
358
+ let seen = new Set();
359
+ function walk(id, ctx) {
360
+ let revisiting = seen.has(id);
361
+ let newCtx = cb(id, ctx, revisiting);
362
+ if (revisiting) return;
363
+ seen.add(id);
364
+
365
+ for (let parent of graph.getNodeIdsConnectedTo(id)) {
366
+ walk(parent, newCtx);
367
+ }
368
+ }
369
+ walk(graph.getNodeIdByContentKey(asset), {paths, lazyOutgoing: false});
370
+
371
+ paths.print(id => {
372
+ let node = nullthrows(graph.getNode(id));
373
+ invariant(node.type === 'asset');
374
+ return fromProjectPathRelative(node.value.filePath);
375
+ });
376
+ }
377
+
378
+ function findEntriesAssetGraph(v: string) {
379
+ if (!hasAssetGraph()) {
380
+ return;
381
+ }
382
+ invariant(assetGraph != null);
383
+ _findEntries(assetGraph, v);
384
+ }
385
+ function findEntriesBundleGraph(v: string) {
386
+ if (!hasBundleGraph()) {
387
+ return;
388
+ }
389
+ invariant(bundleGraph != null);
390
+ _findEntries(bundleGraph._graph, v);
391
+ }
392
+ function findEntries(v: string) {
393
+ findEntriesBundleGraph(v);
394
+ }
395
+
396
+ function getBundlesWithAsset(v: string) {
397
+ if (!hasBundleGraph()) {
398
+ return;
399
+ }
400
+ invariant(bundleGraph != null);
401
+ let asset = nullthrows(parseAssetLocator(v), 'Asset not found');
402
+ for (let b of bundleGraph.getBundlesWithAsset(
403
+ bundleGraph.getAssetById(asset),
404
+ )) {
405
+ let bundleFilePath = getBundleFilePath(b.id);
406
+ if (bundleFilePath !== undefined) {
407
+ console.log(
408
+ `${b.id} ${bundleFilePath} ${
409
+ b.mainEntryId != null ? `(main: ${b.mainEntryId})` : ''
410
+ }`,
411
+ );
412
+ }
413
+ }
414
+ }
415
+
416
+ function getBundlesWithDependency(v: string) {
417
+ if (!hasBundleGraph()) {
418
+ return;
419
+ }
420
+ invariant(bundleGraph != null);
421
+ let node = nullthrows(bundleGraph._graph.getNodeByContentKey(v));
422
+ invariant(node.type === 'dependency');
423
+
424
+ for (let b of bundleGraph.getBundlesWithDependency(node.value)) {
425
+ let bundleFilePath = getBundleFilePath(b.id);
426
+ if (bundleFilePath !== undefined) {
427
+ console.log(
428
+ `${b.id} ${bundleFilePath} ${
429
+ b.mainEntryId != null ? `(main: ${b.mainEntryId})` : ''
430
+ }`,
431
+ );
432
+ }
433
+ }
434
+ }
435
+
436
+ // eslint-disable-next-line no-unused-vars
437
+ function getBundles(_) {
438
+ if (!hasBundleGraph()) {
439
+ return;
440
+ }
441
+ invariant(bundleGraph != null);
442
+ for (let b of bundleGraph.getBundles()) {
443
+ let bundleFilePath = getBundleFilePath(b.id);
444
+ if (bundleFilePath !== undefined) {
445
+ console.log(
446
+ `${b.id} ${bundleFilePath} ${
447
+ b.mainEntryId != null ? `(main: ${b.mainEntryId})` : ''
448
+ }`,
449
+ );
450
+ }
451
+ }
452
+ }
453
+
454
+ function getReferencingBundles(v: string) {
455
+ if (!hasBundleGraph()) {
456
+ return;
457
+ }
458
+ invariant(bundleGraph != null);
459
+ let bundleId = nullthrows(parseBundleLocator(v), 'Bundle not found');
460
+ let bundleNodeId = bundleGraph._graph.getNodeIdByContentKey(bundleId);
461
+ let bundleNode = nullthrows(
462
+ bundleGraph._graph.getNode(bundleNodeId),
463
+ 'Bundle not found',
464
+ );
465
+ invariant(bundleNode.type === 'bundle', 'Not a bundle');
466
+
467
+ for (let b of bundleGraph.getReferencingBundles(bundleNode.value)) {
468
+ let bundleFilePath = getBundleFilePath(b.id);
469
+ if (bundleFilePath !== undefined) {
470
+ console.log(
471
+ `${b.id} ${bundleFilePath} ${
472
+ b.mainEntryId != null ? `(main: ${b.mainEntryId})` : ''
473
+ }`,
474
+ );
475
+ }
476
+ }
477
+ }
478
+
479
+ function getIncomingDependenciesAssetGraph(v: string) {
480
+ if (!hasAssetGraph()) {
481
+ return;
482
+ }
483
+ invariant(assetGraph != null);
484
+ let asset = nullthrows(parseAssetLocator(v), 'Asset not found');
485
+ let node = nullthrows(assetGraph.getNodeByContentKey(asset));
486
+ invariant(node.type === 'asset');
487
+
488
+ console.log(assetGraph.getIncomingDependencies(node.value));
489
+ }
490
+ function getIncomingDependenciesBundleGraph(v: string) {
491
+ if (!hasBundleGraph()) {
492
+ return;
493
+ }
494
+ invariant(bundleGraph != null);
495
+ let asset = nullthrows(parseAssetLocator(v), 'Asset not found');
496
+ let value = nullthrows(bundleGraph.getAssetById(asset));
497
+
498
+ console.log(bundleGraph.getIncomingDependencies(value));
499
+ }
500
+
501
+ function getIncomingDependencies(v: string) {
502
+ getIncomingDependenciesBundleGraph(v);
503
+ }
504
+
505
+ function getResolvedAsset(v: string) {
506
+ if (!hasBundleGraph()) {
507
+ return;
508
+ }
509
+ invariant(bundleGraph != null);
510
+ let node = nullthrows(
511
+ bundleGraph._graph.getNodeByContentKey(v),
512
+ 'Dependency not found',
513
+ );
514
+ invariant(
515
+ node.type === 'dependency',
516
+ 'Node is not a dependency, but a ' + node.type,
517
+ );
518
+ console.log(bundleGraph.getResolvedAsset(node.value));
519
+ }
520
+
521
+ function getAssetWithDependency(v: string) {
522
+ if (!hasBundleGraph()) {
523
+ return;
524
+ }
525
+ invariant(bundleGraph != null);
526
+ let node = nullthrows(
527
+ bundleGraph._graph.getNodeByContentKey(v),
528
+ 'Dependency not found',
529
+ );
530
+ invariant(
531
+ node.type === 'dependency',
532
+ 'Node is not a dependency, but a ' + node.type,
533
+ );
534
+ console.log(bundleGraph.getAssetWithDependency(node.value));
535
+ }
536
+
537
+ function traverseAssets(v: string) {
538
+ if (!hasBundleGraph()) {
539
+ return;
540
+ }
541
+ invariant(bundleGraph != null);
542
+ let bundleId = nullthrows(parseBundleLocator(v), 'Bundle not found');
543
+ let node = nullthrows(
544
+ bundleGraph._graph.getNodeByContentKey(bundleId),
545
+ 'Bundle not found',
546
+ );
547
+ invariant(
548
+ node.type === 'bundle',
549
+ 'Node is not a bundle, but a ' + node.type,
550
+ );
551
+
552
+ bundleGraph.traverseAssets(node.value, asset => {
553
+ console.log(asset.id, asset.filePath);
554
+ });
555
+ }
556
+ function traverseBundle(v: string) {
557
+ if (!hasBundleGraph()) {
558
+ return;
559
+ }
560
+ invariant(bundleGraph != null);
561
+ let bundleId = nullthrows(parseBundleLocator(v), 'Bundle not found');
562
+ let node = nullthrows(
563
+ bundleGraph._graph.getNodeByContentKey(bundleId),
564
+ 'Bundle not found',
565
+ );
566
+ invariant(
567
+ node.type === 'bundle',
568
+ 'Node is not a bundle, but a ' + node.type,
569
+ );
570
+
571
+ bundleGraph.traverseBundle(node.value, node => {
572
+ if (node.type === 'asset') {
573
+ console.log(node.id, node.value.filePath);
574
+ } else {
575
+ console.log(
576
+ node.id,
577
+ node.value.sourcePath,
578
+ '->',
579
+ node.value.specifier,
580
+ node.value.symbols
581
+ ? `(${[...node.value.symbols.keys()].join(',')})`
582
+ : '',
583
+ node.excluded ? `- excluded` : '',
584
+ );
585
+ }
586
+ });
587
+ }
588
+
589
+ function getBundle(v: string) {
590
+ if (!hasBundleGraph()) {
591
+ return;
592
+ }
593
+ invariant(bundleGraph != null);
594
+ let bundleRegex = new RegExp(v);
595
+ for (let b of bundleGraph.getBundles()) {
596
+ let bundleFilePath = getBundleFilePath(b.id);
597
+ if (
598
+ (bundleFilePath !== undefined && bundleRegex.test(bundleFilePath)) ||
599
+ b.id === v
600
+ ) {
601
+ console.log(getBundleFilePath(b.id), b);
602
+ }
603
+ }
604
+ }
605
+
606
+ function findBundleReason(bundle: string, asset: string) {
607
+ if (!hasBundleGraph()) {
608
+ return;
609
+ }
610
+ invariant(bundleGraph != null);
611
+ let bundleId = nullthrows(parseBundleLocator(bundle), 'Bundle not found');
612
+ let bundleNodeId = bundleGraph._graph.getNodeIdByContentKey(bundleId);
613
+ let bundleNode = nullthrows(
614
+ bundleGraph._graph.getNode(bundleNodeId),
615
+ 'Bundle not found',
616
+ );
617
+ invariant(bundleNode.type === 'bundle', 'Not a bundle');
618
+ let assetId = nullthrows(parseAssetLocator(asset), 'Asset not found');
619
+ let assetNodeId = bundleGraph._graph.getNodeIdByContentKey(assetId);
620
+ let assetNode = nullthrows(
621
+ bundleGraph._graph.getNode(assetNodeId),
622
+ 'Asset not found',
623
+ );
624
+ invariant(assetNode.type === 'asset', 'Not an asset');
625
+
626
+ invariant(
627
+ bundleGraph._graph.hasEdge(
628
+ bundleNodeId,
629
+ assetNodeId,
630
+ bundleGraphEdgeTypes.contains,
631
+ ),
632
+ 'Asset is not part of the bundle',
633
+ );
634
+
635
+ console.log(
636
+ '# Asset is main entry of bundle:',
637
+ bundleNode.value.mainEntryId === assetId,
638
+ );
639
+
640
+ console.log(
641
+ '# Asset is an entry of bundle:',
642
+ bundleNode.value.entryAssetIds.includes(assetId),
643
+ );
644
+
645
+ console.log('# Incoming dependencies contained in the bundle:');
646
+ for (let incoming of bundleGraph._graph.getNodeIdsConnectedTo(
647
+ assetNodeId,
648
+ )) {
649
+ if (
650
+ bundleGraph._graph.hasEdge(
651
+ bundleNodeId,
652
+ incoming,
653
+ bundleGraphEdgeTypes.contains,
654
+ )
655
+ ) {
656
+ console.log(bundleGraph._graph.getNode(incoming));
657
+ }
658
+ }
659
+
660
+ console.log(
661
+ '# Incoming dependencies contained in referencing bundles (using this bundle as a shared bundle)',
662
+ );
663
+ let referencingBundles = bundleGraph.getReferencingBundles(
664
+ bundleNode.value,
665
+ );
666
+ for (let incoming of bundleGraph._graph.getNodeIdsConnectedTo(
667
+ assetNodeId,
668
+ )) {
669
+ if (
670
+ referencingBundles.some(ref =>
671
+ bundleGraph._graph.hasEdge(
672
+ bundleGraph._graph.getNodeIdByContentKey(ref.id),
673
+ incoming,
674
+ bundleGraphEdgeTypes.contains,
675
+ ),
676
+ )
677
+ ) {
678
+ console.log(bundleGraph._graph.getNode(incoming));
679
+ }
680
+ }
681
+ }
682
+
683
+ function _getIncomingNodeOfType(bundleGraph, node, type: string) {
684
+ if (!hasBundleGraph()) {
685
+ return;
686
+ }
687
+ invariant(bundleGraph != null);
688
+ const bundleGraphNodeId = bundleGraph._graph.getNodeIdByContentKey(node.id);
689
+ return bundleGraph._graph
690
+ .getNodeIdsConnectedTo(bundleGraphNodeId, -1)
691
+ .map(id => nullthrows(bundleGraph._graph.getNode(id)))
692
+ .find(node => node.type == type);
693
+ }
694
+
695
+ // We find the priority of a Bundle or BundleGroup by looking at its incoming dependencies.
696
+ // If a Bundle does not have an incoming dependency, we look for an incoming BundleGroup and its dependency
697
+ // e.g. Dep(priority = 1) -> BundleGroup -> Bundle means that the Bundle has priority 1.
698
+ function _getBundlePriority(bundleGraph, bundle) {
699
+ if (!hasBundleGraph()) {
700
+ return;
701
+ }
702
+ invariant(bundleGraph != null);
703
+ let node = _getIncomingNodeOfType(bundleGraph, bundle, 'dependency');
704
+
705
+ if (node == null) {
706
+ node = _getIncomingNodeOfType(bundleGraph, bundle, 'bundle_group');
707
+ if (node == null) return null;
708
+ node = _getIncomingNodeOfType(bundleGraph, node, 'dependency');
709
+ }
710
+
711
+ if (node == null) return null;
712
+
713
+ invariant(node.type === 'dependency', 'Not a dependency');
714
+
715
+ return node.value.priority;
716
+ }
717
+
718
+ function _findEntryBundle(bundleGraph, node) {
719
+ if (!hasBundleGraph()) {
720
+ return;
721
+ }
722
+ invariant(bundleGraph != null);
723
+ const bundleGraphNodeId = bundleGraph._graph.getNodeIdByContentKey(node.id);
724
+ const entryBundleGroup = bundleGraph._graph
725
+ .getNodeIdsConnectedTo(bundleGraphNodeId, -1)
726
+ .map(id => nullthrows(bundleGraph._graph.getNode(id)))
727
+ .find(
728
+ node =>
729
+ node.type === 'bundle_group' &&
730
+ bundleGraph.isEntryBundleGroup(node.value),
731
+ );
732
+
733
+ return entryBundleGroup;
734
+ }
735
+ // eslint-disable-next-line no-unused-vars
736
+ function inspectCache(_) {
737
+ // displays sizing of various entries of the cache
738
+ let table: Array<Array<string | number>> = [];
739
+ table.push([
740
+ 'Graphs',
741
+ 'Size (bytes)',
742
+ 'Deserialize (ms)',
743
+ 'Serialize (ms)',
744
+ ]);
745
+ let serialized: Map<string, number> = new Map();
746
+ serialized.set('RequestGraph', timeSerialize(requestTracker));
747
+ serialized.set('BundleGraph', timeSerialize(bundleGraph));
748
+ serialized.set('AssetGraph', timeSerialize(assetGraph));
749
+ for (let [name, info] of nullthrows(cacheInfo).entries()) {
750
+ if (
751
+ (name === 'RequestGraph' && !hasRequestTracker()) ||
752
+ (name === 'BundleGraph' && !hasBundleGraph()) ||
753
+ (name === 'AssetGraph' && !hasAssetGraph())
754
+ ) {
755
+ continue;
756
+ }
757
+ let s = serialized.get(name);
758
+ invariant(s != null);
759
+ table.push([name, ...info, s]);
760
+ }
761
+ function getColumnSum(t: Array<Array<string | number>>, col: number) {
762
+ if (t == null) {
763
+ return '';
764
+ }
765
+ const initialValue = 0;
766
+ let column = t.map(r => r[col]);
767
+ column.shift();
768
+ invariant(column != null);
769
+ return column.reduce(
770
+ (accumulator, currentValue) => accumulator + currentValue,
771
+ initialValue,
772
+ );
773
+ }
774
+ table.push([
775
+ 'Totals',
776
+ getColumnSum(table, 1),
777
+ getColumnSum(table, 2),
778
+ getColumnSum(table, 3),
779
+ ]);
780
+ _printStatsTable('Cache Info', table);
781
+ }
782
+
783
+ function timeSerialize(graph) {
784
+ let date = Date.now();
785
+ serialize(graph);
786
+ date = Date.now() - date;
787
+ return date;
788
+ }
789
+ function _printStatsTable(header, data) {
790
+ const config = {
791
+ columnDefault: {
792
+ width: 18,
793
+ },
794
+ header: {
795
+ alignment: 'center',
796
+ content: header,
797
+ },
798
+ };
799
+
800
+ console.log(table(data, config));
801
+ }
802
+
803
+ // eslint-disable-next-line no-unused-vars
804
+ function stats(_) {
805
+ let ag = {
806
+ asset: 0,
807
+ dependency: 0,
808
+ asset_group: 0,
809
+ };
810
+
811
+ if (hasAssetGraph()) {
812
+ invariant(assetGraph != null);
813
+ for (let n of assetGraph.nodes) {
814
+ if (n && n.type in ag) {
815
+ // $FlowFixMe
816
+ ag[n.type]++;
817
+ }
818
+ }
819
+ _printStatsTable('# Asset Graph Node Counts', Object.entries(ag));
820
+ }
821
+
822
+ if (!hasBundleGraph()) {
823
+ return;
824
+ }
825
+ invariant(bundleGraph != null);
826
+ let bg = {
827
+ dependency: 0,
828
+ bundle: 0,
829
+ bundle_group: 0,
830
+ asset_node_modules: 0,
831
+ asset_source: 0,
832
+ };
833
+
834
+ let b_type = {
835
+ entry: 0,
836
+ shared: 0,
837
+ async: 0,
838
+ parallel: 0,
839
+ sync: 0,
840
+ };
841
+
842
+ let b_ext = {};
843
+
844
+ const entries = new Set();
845
+
846
+ for (let n of bundleGraph._graph.nodes) {
847
+ if (n?.type === 'bundle_group') {
848
+ bg.bundle_group++;
849
+ } else if (n?.type === 'bundle') {
850
+ bg.bundle++;
851
+
852
+ // $FlowFixMe
853
+ b_ext[n.value.type] = (b_ext[n.value.type] || 0) + 1;
854
+
855
+ // $FlowFixMe
856
+ const entry_group = _findEntryBundle(bundleGraph, n);
857
+
858
+ if (entry_group != null && !entries.has(entry_group.id)) {
859
+ b_type.entry++;
860
+ entries.add(entry_group.id);
861
+ } else if (n.value.mainEntryId == null) {
862
+ // In general, !bundle.mainEntryId means that it is shared. In the case of an async and shared bundle, only count it as shared.
863
+ b_type.shared++;
864
+ } else {
865
+ const priority = _getBundlePriority(bundleGraph, n);
866
+
867
+ if (priority == Priority.lazy) {
868
+ b_type.async++;
869
+ } else if (priority == Priority.parallel) {
870
+ b_type.parallel++;
871
+ } else if (priority == Priority.sync) {
872
+ b_type.sync++;
873
+ }
874
+ }
875
+ } else if (n?.type === 'asset') {
876
+ if (
877
+ // $FlowFixMe
878
+ fromProjectPathRelative(n.value.filePath).includes('node_modules')
879
+ ) {
880
+ bg.asset_node_modules++;
881
+ } else {
882
+ bg.asset_source++;
883
+ }
884
+ } else if (n?.type === 'dependency') {
885
+ bg.dependency++;
886
+ }
887
+ }
888
+
889
+ _printStatsTable('# Bundle Graph Node Counts', Object.entries(bg));
890
+ _printStatsTable('# Bundles By Type', Object.entries(b_type));
891
+ _printStatsTable('# Bundles By Extension', Object.entries(b_ext));
892
+
893
+ // Assert that counts for each breakdown are correct
894
+
895
+ let sum_b_ext = 0;
896
+ for (let k in b_ext) {
897
+ sum_b_ext += b_ext[k];
898
+ }
899
+
900
+ let sum_b_type = 0;
901
+ for (let k in b_type) {
902
+ sum_b_type += b_type[k];
903
+ }
904
+
905
+ invariant(
906
+ bg.bundle == sum_b_type,
907
+ `Bundles by type ${sum_b_type} does not equal total ${bg.bundle}`,
908
+ );
909
+ invariant(
910
+ bg.bundle == sum_b_ext,
911
+ `Bundles by extension ${sum_b_ext} does not equal total ${bg.bundle}`,
912
+ );
913
+ }
914
+
915
+ // -------------------------------------------------------
916
+
917
+ if (initialCmd != null) {
918
+ (async () => {
919
+ await eval(initialCmd);
920
+ process.exit(0);
921
+ })();
922
+ } else {
923
+ console.log(
924
+ 'See .help. The graphs can be accessed via `assetGraph`, `bundleGraph` and `requestTracker`.',
925
+ );
926
+ process.on('uncaughtException', function (err) {
927
+ console.error(err);
928
+ server.displayPrompt();
929
+ });
930
+
931
+ const server = repl.start({useColors: true, useGlobal: true});
932
+ // $FlowFixMe[prop-missing]
933
+ server.setupHistory(
934
+ path.join(os.homedir(), '.atlaspack_query_history'),
935
+ () => {},
936
+ );
937
+
938
+ // $FlowFixMe[prop-missing]
939
+ server.context.bundleGraph = bundleGraph;
940
+ // $FlowFixMe[prop-missing]
941
+ server.context.assetGraph = assetGraph;
942
+ // $FlowFixMe[prop-missing]
943
+ server.context.requestTracker = requestTracker;
944
+ // $FlowFixMe[prop-missing]
945
+ server.context.cacheInfo = cacheInfo;
946
+ for (let [name, cmd] of new Map([
947
+ [
948
+ 'getAsset',
949
+ {
950
+ help: 'args: <id | public id | filepath>',
951
+ action: getAsset,
952
+ },
953
+ ],
954
+ [
955
+ 'getNodeAssetGraph',
956
+ {
957
+ help: 'args: <content key>. Find node by content key in the asset graph',
958
+ action: getNodeAssetGraph,
959
+ },
960
+ ],
961
+ [
962
+ 'getNodeBundleGraph',
963
+ {
964
+ help: 'args: <content key>. Find node by content key in the bundle graph',
965
+ action: getNodeBundleGraph,
966
+ },
967
+ ],
968
+ [
969
+ 'findEntriesAssetGraph',
970
+ {
971
+ help: 'args: <id | public id | filepath>. List paths from an asset to entry points (in asset graph)',
972
+ action: findEntriesAssetGraph,
973
+ },
974
+ ],
975
+ [
976
+ 'findEntriesBundleGraph',
977
+ {
978
+ help: 'args: <id | public id | filepath>. List paths from an asset to entry points (in bundle graph)',
979
+ action: findEntriesBundleGraph,
980
+ },
981
+ ],
982
+ [
983
+ 'findEntries',
984
+ {
985
+ help: '= findEntriesBundleGraph',
986
+ action: findEntries,
987
+ },
988
+ ],
989
+ [
990
+ 'getBundlesWithAsset',
991
+ {
992
+ help: 'args: <id | public id | filepath>. Gets bundles containing the asset',
993
+ action: getBundlesWithAsset,
994
+ },
995
+ ],
996
+ [
997
+ 'getBundlesWithDependency',
998
+ {
999
+ help: 'args: <id>. Gets bundles containing the dependency',
1000
+ action: getBundlesWithDependency,
1001
+ },
1002
+ ],
1003
+ [
1004
+ 'getIncomingDependenciesAssetGraph',
1005
+ {
1006
+ help: 'args: <asset: id | public id | filepath regex>',
1007
+ action: getIncomingDependenciesAssetGraph,
1008
+ },
1009
+ ],
1010
+ [
1011
+ 'getIncomingDependenciesBundleGraph',
1012
+ {
1013
+ help: 'args: <asset: id | public id | filepath regex>',
1014
+ action: getIncomingDependenciesBundleGraph,
1015
+ },
1016
+ ],
1017
+ [
1018
+ 'getIncomingDependencies',
1019
+ {
1020
+ help: '= getIncomingDependenciesBundleGraph',
1021
+ action: getIncomingDependencies,
1022
+ },
1023
+ ],
1024
+ [
1025
+ 'getResolvedAsset',
1026
+ {
1027
+ help: 'args: <dependency id>. Resolve the dependency',
1028
+ action: getResolvedAsset,
1029
+ },
1030
+ ],
1031
+ [
1032
+ 'getAssetWithDependency',
1033
+ {
1034
+ help: 'args: <dependency id>. Show which asset created the dependency',
1035
+ action: getAssetWithDependency,
1036
+ },
1037
+ ],
1038
+ [
1039
+ 'traverseAssets',
1040
+ {
1041
+ help: 'args: <bundle id>. List assets in bundle',
1042
+ action: traverseAssets,
1043
+ },
1044
+ ],
1045
+ [
1046
+ 'traverseBundle',
1047
+ {
1048
+ help: 'args: <bundle id>. List assets and dependencies in bundle',
1049
+ action: traverseBundle,
1050
+ },
1051
+ ],
1052
+ [
1053
+ 'getBundle',
1054
+ {
1055
+ help: 'args: <name prefix|bundle id>. List matching bundles',
1056
+ action: getBundle,
1057
+ },
1058
+ ],
1059
+ [
1060
+ 'findBundleReason',
1061
+ {
1062
+ help: 'args: <bundle> <asset>. Why is the asset in the bundle',
1063
+ action: v => findBundleReason(...v.split(' ')),
1064
+ },
1065
+ ],
1066
+ [
1067
+ 'getBundles',
1068
+ {
1069
+ help: 'List all bundles',
1070
+ action: getBundles,
1071
+ },
1072
+ ],
1073
+ [
1074
+ 'getReferencingBundles',
1075
+ {
1076
+ help: 'args: <bundle>. List bundles that reference the bundle',
1077
+ action: getReferencingBundles,
1078
+ },
1079
+ ],
1080
+ [
1081
+ 'stats',
1082
+ {
1083
+ help: 'Statistics',
1084
+ action: stats,
1085
+ },
1086
+ ],
1087
+ [
1088
+ 'findAsset',
1089
+ {
1090
+ help: 'args: <regex>. List assets matching the filepath regex',
1091
+ action: findAsset,
1092
+ },
1093
+ ],
1094
+ [
1095
+ 'inspectCache',
1096
+ {
1097
+ help: 'Cache Information',
1098
+ action: inspectCache,
1099
+ },
1100
+ ],
1101
+ [
1102
+ 'findAssetWithSymbol',
1103
+ {
1104
+ help: 'args: <local>. Get the asset that defines the symbol with the given local name',
1105
+ action: findAssetWithSymbol,
1106
+ },
1107
+ ],
1108
+ ])) {
1109
+ // $FlowFixMe
1110
+ server.context[name] = cmd.action;
1111
+ // $FlowFixMe
1112
+ server.defineCommand(name, {
1113
+ // $FlowFixMe
1114
+ help: '📦 ' + cmd.help,
1115
+ action: v => {
1116
+ // $FlowFixMe
1117
+ server.clearBufferedCommand();
1118
+ // $FlowFixMe
1119
+ try {
1120
+ cmd.action(v);
1121
+ } finally {
1122
+ server.displayPrompt();
1123
+ }
1124
+ },
1125
+ });
1126
+ }
1127
+ }
1128
+ }