UNPKG

9.09 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.nodeFromDep = nodeFromDep;
7exports.nodeFromAssetGroup = nodeFromAssetGroup;
8exports.nodeFromAsset = nodeFromAsset;
9exports.nodeFromEntrySpecifier = nodeFromEntrySpecifier;
10exports.nodeFromEntryFile = nodeFromEntryFile;
11exports.default = void 0;
12
13var _assert = _interopRequireDefault(require("assert"));
14
15var _crypto = _interopRequireDefault(require("crypto"));
16
17var _utils = require("@parcel/utils");
18
19var _Graph = _interopRequireDefault(require("./Graph"));
20
21var _Dependency = require("./Dependency");
22
23function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
25function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
26
27function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
28
29function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
30
31function nodeFromDep(dep) {
32 return {
33 id: dep.id,
34 type: 'dependency',
35 value: dep
36 };
37}
38
39function nodeFromAssetGroup(assetGroup, deferred = false) {
40 return {
41 id: (0, _utils.md5FromObject)(assetGroup),
42 type: 'asset_group',
43 value: assetGroup,
44 deferred
45 };
46}
47
48function nodeFromAsset(asset) {
49 return {
50 id: asset.id,
51 type: 'asset',
52 value: asset
53 };
54}
55
56function nodeFromEntrySpecifier(entry) {
57 return {
58 id: 'entry_specifier:' + entry,
59 type: 'entry_specifier',
60 value: entry
61 };
62}
63
64function nodeFromEntryFile(entry) {
65 return {
66 id: 'entry_file:' + (0, _utils.md5FromObject)(entry),
67 type: 'entry_file',
68 value: entry
69 };
70} // Types that are considered incomplete when they don't have a child node
71
72
73const INCOMPLETE_TYPES = ['entry_specifier', 'entry_file', 'dependency', 'asset_group'];
74
75class AssetGraph extends _Graph.default {
76 constructor(...args) {
77 super(...args);
78
79 _defineProperty(this, "onNodeAdded", void 0);
80
81 _defineProperty(this, "onNodeRemoved", void 0);
82
83 _defineProperty(this, "onIncompleteNode", void 0);
84
85 _defineProperty(this, "incompleteNodeIds", new Set());
86
87 _defineProperty(this, "hash", void 0);
88 }
89
90 // $FlowFixMe
91 static deserialize(opts) {
92 let res = new AssetGraph(opts);
93 res.incompleteNodeIds = opts.incompleteNodeIds;
94 res.hash = opts.hash;
95 return res;
96 } // $FlowFixMe
97
98
99 serialize() {
100 return _objectSpread({}, super.serialize(), {
101 incompleteNodeIds: this.incompleteNodeIds,
102 hash: this.hash
103 });
104 }
105
106 initOptions({
107 onNodeAdded,
108 onNodeRemoved,
109 onIncompleteNode
110 } = {}) {
111 this.onNodeAdded = onNodeAdded;
112 this.onNodeRemoved = onNodeRemoved;
113 this.onIncompleteNode = onIncompleteNode;
114 }
115
116 initialize({
117 entries,
118 assetGroups
119 }) {
120 let rootNode = {
121 id: '@@root',
122 type: 'root',
123 value: null
124 };
125 this.setRootNode(rootNode);
126 let nodes = [];
127
128 if (entries) {
129 for (let entry of entries) {
130 let node = nodeFromEntrySpecifier(entry);
131 nodes.push(node);
132 }
133 } else if (assetGroups) {
134 nodes.push(...assetGroups.map(assetGroup => nodeFromAssetGroup(assetGroup)));
135 }
136
137 this.replaceNodesConnectedTo(rootNode, nodes);
138 }
139
140 addNode(node) {
141 this.hash = null;
142 let existingNode = this.getNode(node.id);
143
144 if (INCOMPLETE_TYPES.includes(node.type) && !node.complete && !node.deferred && (!existingNode || existingNode.deferred)) {
145 this.markIncomplete(node);
146 }
147
148 this.onNodeAdded && this.onNodeAdded(node);
149 return super.addNode(node);
150 }
151
152 removeNode(node) {
153 this.hash = null;
154 this.incompleteNodeIds.delete(node.id);
155 this.onNodeRemoved && this.onNodeRemoved(node);
156 return super.removeNode(node);
157 }
158
159 markIncomplete(node) {
160 this.incompleteNodeIds.add(node.id);
161
162 if (this.onIncompleteNode) {
163 this.onIncompleteNode(node);
164 }
165 }
166
167 hasIncompleteNodes() {
168 return this.incompleteNodeIds.size > 0;
169 }
170
171 resolveEntry(entry, resolved) {
172 let entrySpecifierNode = nodeFromEntrySpecifier(entry);
173 let entryFileNodes = resolved.map(file => nodeFromEntryFile(file));
174 this.replaceNodesConnectedTo(entrySpecifierNode, entryFileNodes);
175 this.incompleteNodeIds.delete(entrySpecifierNode.id);
176 }
177
178 resolveTargets(entry, targets) {
179 let depNodes = targets.map(target => nodeFromDep((0, _Dependency.createDependency)({
180 moduleSpecifier: entry.filePath,
181 pipeline: target.name,
182 target: target,
183 env: target.env,
184 isEntry: true
185 })));
186 let entryNode = nodeFromEntryFile(entry);
187
188 if (this.hasNode(entryNode.id)) {
189 this.replaceNodesConnectedTo(entryNode, depNodes);
190 this.incompleteNodeIds.delete(entryNode.id);
191 }
192 }
193
194 resolveDependency(dependency, assetGroupNode) {
195 let depNode = this.nodes.get(dependency.id);
196 if (!depNode) return;
197 this.incompleteNodeIds.delete(depNode.id);
198
199 if (assetGroupNode) {
200 this.replaceNodesConnectedTo(depNode, [assetGroupNode]);
201 }
202 }
203
204 resolveAssetGroup(assetGroup, assets) {
205 let assetGroupNode = nodeFromAssetGroup(assetGroup);
206 this.incompleteNodeIds.delete(assetGroupNode.id);
207
208 if (!this.hasNode(assetGroupNode.id)) {
209 return;
210 }
211
212 let dependentAssetKeys = [];
213 let assetObjects = [];
214
215 for (let asset of assets) {
216 let isDirect = !dependentAssetKeys.includes(asset.uniqueKey);
217 let dependentAssets = [];
218
219 for (let dep of asset.dependencies.values()) {
220 let dependentAsset = assets.find(a => a.uniqueKey === dep.moduleSpecifier);
221
222 if (dependentAsset) {
223 dependentAssetKeys.push(dependentAsset.uniqueKey);
224 dependentAssets.push(dependentAsset);
225 }
226 }
227
228 assetObjects.push({
229 assetNode: nodeFromAsset(asset),
230 dependentAssets,
231 isDirect
232 });
233 }
234
235 this.replaceNodesConnectedTo(assetGroupNode, assetObjects.filter(a => a.isDirect).map(a => a.assetNode));
236
237 for (let {
238 assetNode,
239 dependentAssets
240 } of assetObjects) {
241 this.resolveAsset(assetNode, dependentAssets);
242 }
243 }
244
245 resolveAsset(assetNode, dependentAssets) {
246 let depNodes = [];
247 let depNodesWithAssets = [];
248
249 for (let dep of assetNode.value.dependencies.values()) {
250 var _this$nodes$get;
251
252 let depNode = nodeFromDep(dep);
253 depNodes.push((_this$nodes$get = this.nodes.get(depNode.id)) !== null && _this$nodes$get !== void 0 ? _this$nodes$get : depNode);
254 let dependentAsset = dependentAssets.find(a => a.uniqueKey === dep.moduleSpecifier);
255
256 if (dependentAsset) {
257 depNode.complete = true;
258 depNodesWithAssets.push([depNode, nodeFromAsset(dependentAsset)]);
259 }
260 }
261
262 this.replaceNodesConnectedTo(assetNode, depNodes);
263
264 for (let [depNode, dependentAssetNode] of depNodesWithAssets) {
265 this.replaceNodesConnectedTo(depNode, [dependentAssetNode]);
266 }
267 }
268
269 getIncomingDependencies(asset) {
270 let node = this.getNode(asset.id);
271
272 if (!node) {
273 return [];
274 }
275
276 return this.findAncestors(node, node => node.type === 'dependency').map(node => {
277 (0, _assert.default)(node.type === 'dependency');
278 return node.value;
279 });
280 }
281
282 traverseAssets(visit, startNode) {
283 return this.filteredTraverse(node => node.type === 'asset' ? node.value : null, visit, startNode);
284 }
285
286 getEntryAssetGroupNodes() {
287 let entryNodes = [];
288 this.traverse((node, _, actions) => {
289 if (node.type === 'asset_group') {
290 entryNodes.push(node);
291 actions.skipChildren();
292 }
293 });
294 return entryNodes;
295 }
296
297 getEntryAssets() {
298 let entries = [];
299 this.traverseAssets((asset, ctx, traversal) => {
300 entries.push(asset);
301 traversal.skipChildren();
302 });
303 return entries;
304 }
305
306 getHash() {
307 if (this.hash != null) {
308 return this.hash;
309 }
310
311 let hash = _crypto.default.createHash('md5'); // TODO: sort??
312
313
314 this.traverse(node => {
315 if (node.type === 'asset') {
316 hash.update(node.value.outputHash);
317 } else if (node.type === 'dependency' && node.value.target) {
318 hash.update(JSON.stringify(node.value.target));
319 }
320 });
321 this.hash = hash.digest('hex');
322 return this.hash;
323 }
324
325}
326
327exports.default = AssetGraph;
\No newline at end of file