@teambit/objects 0.0.0-15acf3f9b295a985a00bf4c313c939bf7adc1310

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.
Files changed (121) hide show
  1. package/dist/fixtures/version-model-extended.json +48 -0
  2. package/dist/fixtures/version-model-object.json +87 -0
  3. package/dist/index.d.ts +19 -0
  4. package/dist/index.js +371 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/models/dependencies-graph.d.ts +46 -0
  7. package/dist/models/dependencies-graph.js +105 -0
  8. package/dist/models/dependencies-graph.js.map +1 -0
  9. package/dist/models/detach-heads.d.ts +25 -0
  10. package/dist/models/detach-heads.js +84 -0
  11. package/dist/models/detach-heads.js.map +1 -0
  12. package/dist/models/export-metadata.d.ts +24 -0
  13. package/dist/models/export-metadata.js +76 -0
  14. package/dist/models/export-metadata.js.map +1 -0
  15. package/dist/models/index.d.ts +10 -0
  16. package/dist/models/index.js +125 -0
  17. package/dist/models/index.js.map +1 -0
  18. package/dist/models/lane-history.d.ts +40 -0
  19. package/dist/models/lane-history.js +117 -0
  20. package/dist/models/lane-history.js.map +1 -0
  21. package/dist/models/lane.d.ts +124 -0
  22. package/dist/models/lane.js +461 -0
  23. package/dist/models/lane.js.map +1 -0
  24. package/dist/models/model-component.d.ts +318 -0
  25. package/dist/models/model-component.js +1375 -0
  26. package/dist/models/model-component.js.map +1 -0
  27. package/dist/models/model-component.spec.d.ts +1 -0
  28. package/dist/models/model-component.spec.js +71 -0
  29. package/dist/models/model-component.spec.js.map +1 -0
  30. package/dist/models/scopeMeta.d.ts +20 -0
  31. package/dist/models/scopeMeta.js +71 -0
  32. package/dist/models/scopeMeta.js.map +1 -0
  33. package/dist/models/source.d.ts +10 -0
  34. package/dist/models/source.js +43 -0
  35. package/dist/models/source.js.map +1 -0
  36. package/dist/models/symlink.d.ts +30 -0
  37. package/dist/models/symlink.js +91 -0
  38. package/dist/models/symlink.js.map +1 -0
  39. package/dist/models/version-history.d.ts +59 -0
  40. package/dist/models/version-history.js +287 -0
  41. package/dist/models/version-history.js.map +1 -0
  42. package/dist/models/version.d.ts +284 -0
  43. package/dist/models/version.js +786 -0
  44. package/dist/models/version.js.map +1 -0
  45. package/dist/models/version.spec.d.ts +1 -0
  46. package/dist/models/version.spec.js +340 -0
  47. package/dist/models/version.spec.js.map +1 -0
  48. package/dist/objects/bit-object-list.d.ts +24 -0
  49. package/dist/objects/bit-object-list.js +65 -0
  50. package/dist/objects/bit-object-list.js.map +1 -0
  51. package/dist/objects/index.d.ts +5 -0
  52. package/dist/objects/index.js +60 -0
  53. package/dist/objects/index.js.map +1 -0
  54. package/dist/objects/object-list-to-graph.d.ts +13 -0
  55. package/dist/objects/object-list-to-graph.js +93 -0
  56. package/dist/objects/object-list-to-graph.js.map +1 -0
  57. package/dist/objects/object-list.d.ts +52 -0
  58. package/dist/objects/object-list.js +369 -0
  59. package/dist/objects/object-list.js.map +1 -0
  60. package/dist/objects/object.d.ts +35 -0
  61. package/dist/objects/object.js +190 -0
  62. package/dist/objects/object.js.map +1 -0
  63. package/dist/objects/objects-readable-generator.d.ts +31 -0
  64. package/dist/objects/objects-readable-generator.js +192 -0
  65. package/dist/objects/objects-readable-generator.js.map +1 -0
  66. package/dist/objects/raw-object.d.ts +23 -0
  67. package/dist/objects/raw-object.js +155 -0
  68. package/dist/objects/raw-object.js.map +1 -0
  69. package/dist/objects/ref.d.ts +14 -0
  70. package/dist/objects/ref.js +45 -0
  71. package/dist/objects/ref.js.map +1 -0
  72. package/dist/objects/repository-hooks.d.ts +4 -0
  73. package/dist/objects/repository-hooks.js +56 -0
  74. package/dist/objects/repository-hooks.js.map +1 -0
  75. package/dist/objects/repository.d.ts +149 -0
  76. package/dist/objects/repository.js +847 -0
  77. package/dist/objects/repository.js.map +1 -0
  78. package/dist/objects/scope-index.d.ts +74 -0
  79. package/dist/objects/scope-index.js +256 -0
  80. package/dist/objects/scope-index.js.map +1 -0
  81. package/dist/objects/scope-index.spec.d.ts +1 -0
  82. package/dist/objects/scope-index.spec.js +152 -0
  83. package/dist/objects/scope-index.spec.js.map +1 -0
  84. package/dist/objects.aspect.d.ts +2 -0
  85. package/dist/objects.aspect.js +18 -0
  86. package/dist/objects.aspect.js.map +1 -0
  87. package/dist/objects.main.runtime.d.ts +7 -0
  88. package/dist/objects.main.runtime.js +36 -0
  89. package/dist/objects.main.runtime.js.map +1 -0
  90. package/dist/preview-1752106620913.js +7 -0
  91. package/fixtures/version-model-extended.json +48 -0
  92. package/fixtures/version-model-object.json +87 -0
  93. package/models/dependencies-graph.ts +120 -0
  94. package/models/detach-heads.ts +79 -0
  95. package/models/export-metadata.ts +57 -0
  96. package/models/index.ts +11 -0
  97. package/models/lane-history.ts +106 -0
  98. package/models/lane.ts +367 -0
  99. package/models/model-component.spec.ts +55 -0
  100. package/models/model-component.ts +1387 -0
  101. package/models/scopeMeta.ts +60 -0
  102. package/models/source.ts +32 -0
  103. package/models/symlink.ts +66 -0
  104. package/models/version-history.ts +271 -0
  105. package/models/version.spec.ts +288 -0
  106. package/models/version.ts +826 -0
  107. package/objects/bit-object-list.ts +59 -0
  108. package/objects/index.ts +6 -0
  109. package/objects/object-list-to-graph.ts +69 -0
  110. package/objects/object-list.ts +313 -0
  111. package/objects/object.ts +153 -0
  112. package/objects/objects-readable-generator.ts +167 -0
  113. package/objects/raw-object.ts +142 -0
  114. package/objects/ref.ts +45 -0
  115. package/objects/repository-hooks.ts +42 -0
  116. package/objects/repository.ts +760 -0
  117. package/objects/scope-index.spec.ts +95 -0
  118. package/objects/scope-index.ts +198 -0
  119. package/package.json +97 -0
  120. package/types/asset.d.ts +41 -0
  121. package/types/style.d.ts +42 -0
@@ -0,0 +1,826 @@
1
+ import { isEmpty, pickBy } from 'lodash';
2
+ import { isSnap } from '@teambit/component-version';
3
+ import { ComponentID, ComponentIdList } from '@teambit/component-id';
4
+ import { LaneId } from '@teambit/lane-id';
5
+ import { v4 } from 'uuid';
6
+ import { BuildStatus, DEFAULT_BUNDLE_FILENAME, Extensions } from '@teambit/legacy.constants';
7
+ import {
8
+ isSchemaSupport,
9
+ SchemaFeature,
10
+ SchemaName,
11
+ Dependencies,
12
+ Dependency,
13
+ ConsumerComponent,
14
+ } from '@teambit/legacy.consumer-component';
15
+ import { getRefsFromExtensions, SourceFile } from '@teambit/component.sources';
16
+ import { ComponentOverridesData } from '@teambit/legacy.consumer-config';
17
+ import { ExtensionDataEntry, ExtensionDataList } from '@teambit/legacy.extension-data';
18
+ import type { Doclet } from '@teambit/semantics.doc-parser';
19
+ import { logger } from '@teambit/legacy.logger';
20
+ import { getStringifyArgs, PathLinux, pathNormalizeToLinux } from '@teambit/legacy.utils';
21
+ import { sha1 } from '@teambit/toolbox.crypto.sha1';
22
+ import { BitObject, Ref, Repository } from '../objects';
23
+ import { ObjectItem } from '../objects/object-list';
24
+ import { BitIdCompIdError, VersionInvalid, validateVersionInstance } from '@teambit/legacy.scope';
25
+ import Source from './source';
26
+ import { DependenciesGraph } from './dependencies-graph';
27
+ import { getBitVersion } from '@teambit/bit.get-bit-version';
28
+
29
+ export type SourceFileModel = {
30
+ name: string;
31
+ relativePath: PathLinux;
32
+ test: boolean;
33
+ file: Ref;
34
+ };
35
+
36
+ export type DistFileModel = SourceFileModel;
37
+
38
+ export type ArtifactFileModel = {
39
+ relativePath: PathLinux;
40
+ file: Ref;
41
+ };
42
+
43
+ export type Log = {
44
+ message: string;
45
+ date: string;
46
+ username: string | undefined;
47
+ email: string | undefined;
48
+ };
49
+
50
+ export type DepEdgeType = 'prod' | 'dev' | 'peer' | 'ext';
51
+ export type DepEdge = { source: ComponentID; target: ComponentID; type: DepEdgeType };
52
+
53
+ type ExternalHead = { head: Ref; laneId: LaneId };
54
+ type SquashData = { previousParents: Ref[]; laneId: LaneId };
55
+ type VersionOrigin = { id: { scope: string; name: string }; lane?: { scope: string; name: string; hash: string } };
56
+
57
+ export type VersionProps = {
58
+ mainFile: PathLinux;
59
+ files: Array<SourceFileModel>;
60
+ log: Log;
61
+ docs?: Doclet[];
62
+ dependencies?: Dependency[];
63
+ devDependencies?: Dependency[];
64
+ peerDependencies?: Dependency[];
65
+ flattenedDependencies?: ComponentIdList;
66
+ _flattenedEdges?: DepEdge[];
67
+ flattenedEdges?: DepEdge[];
68
+ flattenedEdgesRef?: Ref;
69
+ dependenciesGraphRef?: Ref;
70
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
71
+ packageDependencies?: { [key: string]: string };
72
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
73
+ devPackageDependencies?: { [key: string]: string };
74
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
75
+ peerPackageDependencies?: { [key: string]: string };
76
+ bindingPrefix: string;
77
+ schema?: string;
78
+ overrides: ComponentOverridesData;
79
+ packageJsonChangedProps?: Record<string, any>;
80
+ hash?: string;
81
+ parents?: Ref[];
82
+ squashed?: SquashData;
83
+ unrelated?: ExternalHead;
84
+ extensions?: ExtensionDataList;
85
+ buildStatus?: BuildStatus;
86
+ componentId?: ComponentID;
87
+ bitVersion?: string;
88
+ modified?: Log[];
89
+ origin?: VersionOrigin;
90
+ hidden?: boolean;
91
+ };
92
+
93
+ /**
94
+ * Represent a version model in the scope
95
+ */
96
+ export default class Version extends BitObject {
97
+ mainFile: PathLinux;
98
+ files: Array<SourceFileModel>;
99
+ log: Log;
100
+ docs: Doclet[] | undefined;
101
+ dependencies: Dependencies;
102
+ devDependencies: Dependencies;
103
+ peerDependencies: Dependencies;
104
+ flattenedDependencies: ComponentIdList;
105
+ dependenciesGraphRef?: Ref;
106
+ _dependenciesGraph?: DependenciesGraph; // caching for the dependencies graph
107
+ flattenedEdgesRef?: Ref; // ref to a BitObject Source file, which is a JSON object containing the flattened edge
108
+ _flattenedEdges?: DepEdge[]; // caching for the flattenedEdges
109
+ /**
110
+ * @deprecated
111
+ * to get the flattenedEdges, please use `this.getFlattenedEdges()`.
112
+ * this function handles the backward compatibility and provides the flattened edges regardless whether it was saved
113
+ * the `flattenedEdgesRef` introduced or after.
114
+ *
115
+ * the reason this is left here is not for backward compatibility, but for forward compatibility. meaning, if a
116
+ * Version object created by the new version is parsed by an old version that doesn't support the flattenedEdgesRef,
117
+ * then, it'll be able to still get the flattenedEdges by this prop.
118
+ * this is causing duplication currently. the data is kept in both, `this.flattenedEdges` and the file stored in `flattenedEdgesRef`.
119
+ * so it'll be best to delete this prop as soon as all scopes are deployed with the new version.
120
+ * (around August 2023 should be safe)
121
+ */
122
+ private flattenedEdges: DepEdge[];
123
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
124
+ packageDependencies: { [key: string]: string };
125
+ devPackageDependencies: { [key: string]: string };
126
+ peerPackageDependencies: { [key: string]: string };
127
+ bindingPrefix: string;
128
+ schema: string | undefined;
129
+ overrides: ComponentOverridesData;
130
+ packageJsonChangedProps: Record<string, any>;
131
+ _hash: string; // reason for the underscore prefix is that we already have hash as a method
132
+ parents: Ref[];
133
+ squashed?: SquashData; // when a component is squashed during lane-merge
134
+ unrelated?: ExternalHead; // when a component from a lane was created with the same name/scope as main, this ref points to the component of the lane
135
+ extensions: ExtensionDataList;
136
+ buildStatus?: BuildStatus;
137
+ componentId?: ComponentID; // can help debugging errors when validating Version object
138
+ bitVersion?: string;
139
+ modified: Log[] = []; // currently mutation could happen as a result of either "squash" or "sign".
140
+ origin?: VersionOrigin; // for debugging purposes
141
+ hidden?: boolean; // whether the version is hidden from commands such as "bit log", "bit blame". (needed for un-meaningful snaps, such as merged-lane snap prior to the tag)
142
+
143
+ constructor(props: VersionProps) {
144
+ super();
145
+ this.mainFile = props.mainFile;
146
+ this.files = props.files;
147
+ this.log = props.log;
148
+ this.dependencies = new Dependencies(props.dependencies);
149
+ this.devDependencies = new Dependencies(props.devDependencies);
150
+ this.peerDependencies = new Dependencies(props.peerDependencies);
151
+ this.docs = props.docs;
152
+ this.flattenedDependencies = props.flattenedDependencies || new ComponentIdList();
153
+ this.flattenedEdges = props.flattenedEdges || [];
154
+ this.flattenedEdgesRef = props.flattenedEdgesRef;
155
+ this.dependenciesGraphRef = props.dependenciesGraphRef;
156
+ this.packageDependencies = props.packageDependencies || {};
157
+ this.devPackageDependencies = props.devPackageDependencies || {};
158
+ this.peerPackageDependencies = props.peerPackageDependencies || {};
159
+ this.bindingPrefix = props.bindingPrefix;
160
+ this.schema = props.schema;
161
+ this.overrides = props.overrides || {};
162
+ this.packageJsonChangedProps = props.packageJsonChangedProps || {};
163
+ // @ts-ignore yes, props.hash can be undefined here, but it gets populated as soon as Version is created
164
+ this._hash = props.hash;
165
+ this.parents = props.parents || [];
166
+ this.squashed = props.squashed;
167
+ this.unrelated = props.unrelated;
168
+ this.extensions = props.extensions || ExtensionDataList.fromArray([]);
169
+ this.buildStatus = props.buildStatus;
170
+ this.componentId = props.componentId;
171
+ this.bitVersion = props.bitVersion;
172
+ this.modified = props.modified || [];
173
+ this.origin = props.origin;
174
+ this.hidden = props.hidden;
175
+ this.validateVersion();
176
+ }
177
+
178
+ /**
179
+ * use only this method to get the flattened edges (graph of flattened dependencies).
180
+ * it's backward compatible with the previous way this was stored on the Version object itself.
181
+ */
182
+ async getFlattenedEdges(repo: Repository): Promise<DepEdge[]> {
183
+ const getWithBackwardCompatibility = async (): Promise<DepEdge[]> => {
184
+ if (this.flattenedEdgesRef) {
185
+ // it's possible that there is a ref but the file is not there.
186
+ // it can happen if the remote-scope uses an older version that doesn't know to collect this ref.
187
+ // in which case, the client will get the Version object with the ref prop, but not the Source object.
188
+ const throws = false;
189
+ const flattenedEdgesSource = (await repo.load(this.flattenedEdgesRef, throws)) as Source | undefined;
190
+ if (flattenedEdgesSource) {
191
+ const flattenedEdgesJson = JSON.parse(flattenedEdgesSource.contents.toString());
192
+ return flattenedEdgesJson.map((item) =>
193
+ Array.isArray(item) ? Version.depEdgeFromArray(item) : Version.depEdgeFromObject(item)
194
+ );
195
+ }
196
+ }
197
+ return this.flattenedEdges || [];
198
+ };
199
+
200
+ if (!this._flattenedEdges) {
201
+ this._flattenedEdges = await getWithBackwardCompatibility();
202
+ }
203
+
204
+ return this._flattenedEdges;
205
+ }
206
+
207
+ async loadDependenciesGraph(repo: Repository): Promise<DependenciesGraph | undefined> {
208
+ if (!this._dependenciesGraph) {
209
+ if (this.dependenciesGraphRef) {
210
+ // it's possible that there is a ref but the file is not there.
211
+ // it can happen if the remote-scope uses an older version that doesn't know to collect this ref.
212
+ // in which case, the client will get the Version object with the ref prop, but not the Source object.
213
+ const throws = false;
214
+ const dependenciesGraphSource = (await repo.load(this.dependenciesGraphRef, throws)) as Source | undefined;
215
+ if (dependenciesGraphSource) {
216
+ this._dependenciesGraph = DependenciesGraph.deserialize(dependenciesGraphSource.contents.toString());
217
+ }
218
+ }
219
+ }
220
+ return this._dependenciesGraph;
221
+ }
222
+
223
+ validateVersion() {
224
+ const nonEmptyFields = ['mainFile', 'files'];
225
+ nonEmptyFields.forEach((field) => {
226
+ if (!this[field]) {
227
+ throw new VersionInvalid(`failed creating a version object, the field "${field}" can't be empty`);
228
+ }
229
+ });
230
+ }
231
+
232
+ id() {
233
+ const obj = this.toObject();
234
+
235
+ // @todo: remove the entire dependencies.relativePaths from the ID (it's going to be a breaking change)
236
+ const getDependencies = (deps: Dependencies) => {
237
+ const clonedDependencies = deps.cloneAsString();
238
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
239
+ return clonedDependencies.map((dependency: Dependency) => {
240
+ return {
241
+ id: dependency.id,
242
+ relativePaths: dependency.relativePaths.map((relativePath) => {
243
+ return {
244
+ sourceRelativePath: relativePath.sourceRelativePath,
245
+ destinationRelativePath: relativePath.destinationRelativePath,
246
+ };
247
+ }),
248
+ };
249
+ });
250
+ };
251
+
252
+ const getExtensions = (extensions: ExtensionDataList) => {
253
+ const sortedConfigOnly = extensions.sortById().toConfigArray();
254
+ return sortedConfigOnly;
255
+ };
256
+
257
+ const filterFunction = (val, key) => {
258
+ if (
259
+ key === 'devDependencies' ||
260
+ key === 'extensionDependencies' ||
261
+ key === 'devPackageDependencies' ||
262
+ key === 'peerPackageDependencies' ||
263
+ key === 'overrides' ||
264
+ key === 'extensions'
265
+ ) {
266
+ return !isEmpty(val);
267
+ }
268
+ return !!val;
269
+ };
270
+
271
+ return JSON.stringify(
272
+ pickBy(
273
+ {
274
+ mainFile: obj.mainFile,
275
+ files: obj.files,
276
+ log: obj.log,
277
+ dependencies: getDependencies(this.dependencies),
278
+ devDependencies: getDependencies(this.devDependencies),
279
+ extensionDependencies: getDependencies(this.extensionDependencies),
280
+ packageDependencies: obj.packageDependencies,
281
+ devPackageDependencies: obj.devPackageDependencies,
282
+ peerPackageDependencies: obj.peerPackageDependencies,
283
+ bindingPrefix: obj.bindingPrefix,
284
+ overrides: obj.overrides,
285
+ extensions: getExtensions(this.extensions),
286
+ },
287
+ filterFunction
288
+ )
289
+ );
290
+ }
291
+
292
+ calculateHash(): Ref {
293
+ return new Ref(BitObject.makeHash(this.id()));
294
+ }
295
+
296
+ hash(): Ref {
297
+ if (!this._hash) {
298
+ throw new Error('hash is missing from a Version object');
299
+ }
300
+ return new Ref(this._hash);
301
+ }
302
+
303
+ get extensionDependencies() {
304
+ return new Dependencies(this.extensions.extensionsBitIds.map((id) => new Dependency(id, [])));
305
+ }
306
+
307
+ lastModified(): string {
308
+ if (!this.modified || !this.modified.length) return this.log.date;
309
+ return this.modified[this.modified.length - 1].date;
310
+ }
311
+
312
+ getAllFlattenedDependencies(): ComponentIdList {
313
+ return ComponentIdList.fromArray([...this.flattenedDependencies]);
314
+ }
315
+
316
+ getAllDependencies(): Dependency[] {
317
+ return [
318
+ ...this.dependencies.dependencies,
319
+ ...this.devDependencies.dependencies,
320
+ ...this.extensionDependencies.dependencies,
321
+ ];
322
+ }
323
+
324
+ get depsIdsGroupedByType(): {
325
+ dependencies: ComponentIdList;
326
+ devDependencies: ComponentIdList;
327
+ peerDependencies: ComponentIdList;
328
+ extensionDependencies: ComponentIdList;
329
+ } {
330
+ return {
331
+ dependencies: this.dependencies.getAllIds(),
332
+ devDependencies: this.devDependencies.getAllIds(),
333
+ peerDependencies: this.peerDependencies.getAllIds(),
334
+ extensionDependencies: this.extensions.extensionsBitIds,
335
+ };
336
+ }
337
+
338
+ getAllDependenciesCloned(): Dependencies {
339
+ const dependencies = [...this.dependencies.getClone(), ...this.devDependencies.getClone()];
340
+ return new Dependencies(dependencies);
341
+ }
342
+
343
+ getAllDependenciesIds(): ComponentIdList {
344
+ const allDependencies = Object.values(this.depsIdsGroupedByType).flat();
345
+ return ComponentIdList.fromArray(allDependencies);
346
+ }
347
+
348
+ getDependenciesIdsExcludeExtensions(): ComponentIdList {
349
+ return ComponentIdList.fromArray([...this.dependencies.getAllIds(), ...this.devDependencies.getAllIds()]);
350
+ }
351
+
352
+ updateFlattenedDependency(currentId: ComponentID, newId: ComponentID) {
353
+ const getUpdated = (flattenedDependencies: ComponentIdList): ComponentIdList => {
354
+ const updatedIds = flattenedDependencies.map((depId) => {
355
+ if (depId.isEqual(currentId)) return newId;
356
+ return depId;
357
+ });
358
+ return ComponentIdList.fromArray(updatedIds);
359
+ };
360
+ this.flattenedDependencies = getUpdated(this.flattenedDependencies);
361
+ }
362
+
363
+ refs(): Ref[] {
364
+ return this.refsWithOptions();
365
+ }
366
+
367
+ refsWithOptions(includeParents = true, includeArtifacts = true): Ref[] {
368
+ const allRefs: Ref[] = [];
369
+ const extractRefsFromFiles = (files) => {
370
+ const refs = files ? files.map((file) => file.file) : [];
371
+ return refs;
372
+ };
373
+ const files = extractRefsFromFiles(this.files);
374
+ allRefs.push(...files);
375
+ if (includeParents) {
376
+ allRefs.push(...this.parents);
377
+ }
378
+ if (includeArtifacts) {
379
+ const artifacts = getRefsFromExtensions(this.extensions);
380
+ allRefs.push(...artifacts);
381
+ }
382
+ if (this.flattenedEdgesRef) allRefs.push(this.flattenedEdgesRef);
383
+ if (this.dependenciesGraphRef) allRefs.push(this.dependenciesGraphRef);
384
+ return allRefs;
385
+ }
386
+
387
+ refsWithoutParents(): Ref[] {
388
+ const extractRefsFromFiles = (files) => {
389
+ const refs = files ? files.map((file) => file.file) : [];
390
+ return refs;
391
+ };
392
+ const files = extractRefsFromFiles(this.files);
393
+ const artifacts = getRefsFromExtensions(this.extensions);
394
+ return [...files, ...artifacts].filter((ref) => ref);
395
+ }
396
+
397
+ async collectManyObjects(repo: Repository, refs: Ref[]): Promise<ObjectItem[]> {
398
+ return repo.loadManyRaw(refs);
399
+ }
400
+
401
+ static depEdgeToObject(depEdge: DepEdge): Record<string, any> {
402
+ return {
403
+ source: depEdge.source.serialize(),
404
+ target: depEdge.target.serialize(),
405
+ type: depEdge.type,
406
+ };
407
+ }
408
+ static depEdgeFromObject(depEdgeObj: Record<string, any>): DepEdge {
409
+ return {
410
+ source: ComponentID.fromObject(depEdgeObj.source),
411
+ target: ComponentID.fromObject(depEdgeObj.target),
412
+ type: depEdgeObj.type,
413
+ };
414
+ }
415
+ /**
416
+ * until 1.9.86, we used depEdgeToObject.
417
+ * this one makes this object much much smaller (for 604 edges, it's now 143KB, with the array format it's 6KB!)
418
+ * this format has been supported (but not used) since v1.6.97.
419
+ */
420
+ static depEdgeToArray(depEdge: DepEdge): Record<string, any> {
421
+ return [depEdge.source.toString(), depEdge.target.toString(), depEdge.type];
422
+ }
423
+ static depEdgeFromArray(depEdgeArr: string[]): DepEdge {
424
+ const [sourceStr, targetStr, type] = depEdgeArr;
425
+ return {
426
+ source: ComponentID.fromString(sourceStr),
427
+ target: ComponentID.fromString(targetStr),
428
+ type: type as DepEdgeType,
429
+ };
430
+ }
431
+ static flattenedEdgeToSource(flattenedEdges?: DepEdge[]): Source | undefined {
432
+ if (!flattenedEdges) return undefined;
433
+ // const flattenedEdgesObj = flattenedEdges.map((f) => Version.depEdgeToArray(f));
434
+ const flattenedEdgesObj = flattenedEdges.map((f) => Version.depEdgeToObject(f));
435
+ const flattenedEdgesBuffer = Buffer.from(JSON.stringify(flattenedEdgesObj));
436
+ return Source.from(flattenedEdgesBuffer);
437
+ }
438
+ static dependenciesGraphToSource(dependenciesGraph?: DependenciesGraph): Source | undefined {
439
+ if (!dependenciesGraph) return undefined;
440
+ const dependenciesGraphBuffer = Buffer.from(dependenciesGraph.serialize());
441
+ return Source.from(dependenciesGraphBuffer);
442
+ }
443
+
444
+ toObject() {
445
+ const _convertFileToObject = (file) => {
446
+ return {
447
+ file: file.file.toString(),
448
+ relativePath: file.relativePath,
449
+ name: file.name,
450
+ test: file.test,
451
+ };
452
+ };
453
+
454
+ return pickBy(
455
+ {
456
+ files: this.files ? this.files.map(_convertFileToObject) : null,
457
+ mainFile: this.mainFile,
458
+ bindingPrefix: this.bindingPrefix,
459
+ schema: this.schema,
460
+ log: {
461
+ message: this.log.message,
462
+ date: this.log.date,
463
+ username: this.log.username,
464
+ email: this.log.email,
465
+ },
466
+ docs: this.docs,
467
+ dependencies: this.dependencies.cloneAsObject(),
468
+ devDependencies: this.devDependencies.cloneAsObject(),
469
+ flattenedDependencies: this.flattenedDependencies.map((dep) => dep.toObject()),
470
+ // @todo: uncomment this in the future, once all remotes are updated to support the backward compatibility.
471
+ // flattenedDependencies: this.flattenedDependencies.map((dep) => dep.toString()),
472
+ flattenedEdges: this.flattenedEdgesRef ? undefined : this.flattenedEdges.map((f) => Version.depEdgeToObject(f)),
473
+ flattenedEdgesRef: this.flattenedEdgesRef?.toString(),
474
+ dependenciesGraphRef: this.dependenciesGraphRef?.toString(),
475
+ extensions: this.extensions.toModelObjects(),
476
+ packageDependencies: this.packageDependencies,
477
+ devPackageDependencies: this.devPackageDependencies,
478
+ peerPackageDependencies: this.peerPackageDependencies,
479
+ overrides: this.overrides,
480
+ buildStatus: this.buildStatus,
481
+ packageJsonChangedProps: this.packageJsonChangedProps,
482
+ parents: this.parents.map((p) => p.toString()),
483
+ squashed: this.squashed
484
+ ? {
485
+ previousParents: this.squashed.previousParents.map((p) => p.toString()),
486
+ laneId: this.squashed.laneId.toObject(),
487
+ }
488
+ : undefined,
489
+ unrelated: this.unrelated
490
+ ? { head: this.unrelated.head.toString(), laneId: this.unrelated.laneId.toObject() }
491
+ : undefined,
492
+ bitVersion: this.bitVersion,
493
+ modified: this.modified,
494
+ origin: this.origin,
495
+ hidden: this.hidden,
496
+ },
497
+ (val) => !!val
498
+ );
499
+ }
500
+
501
+ validateBeforePersisting(versionStr: string): void {
502
+ logger.trace(`validating version object, hash: ${this.hash().hash}`);
503
+ const version = Version.parse(versionStr, this._hash);
504
+ version.validate();
505
+ }
506
+
507
+ toBuffer(pretty: boolean): Buffer {
508
+ const obj = this.toObject();
509
+ const args = getStringifyArgs(pretty);
510
+ const str = JSON.stringify(obj, ...args);
511
+ if (this.validateBeforePersist) this.validateBeforePersisting(str);
512
+ return Buffer.from(str);
513
+ }
514
+ /**
515
+ * used by the super class BitObject
516
+ */
517
+ static parse(contents: string, hash: string): Version {
518
+ const contentParsed = JSON.parse(contents);
519
+ const {
520
+ mainFile,
521
+ files,
522
+ bindingPrefix,
523
+ schema,
524
+ log,
525
+ docs,
526
+ dependencies,
527
+ devDependencies,
528
+ flattenedDependencies,
529
+ flattenedDevDependencies,
530
+ flattenedEdges,
531
+ flattenedEdgesRef,
532
+ dependenciesGraphRef,
533
+ devPackageDependencies,
534
+ peerPackageDependencies,
535
+ packageDependencies,
536
+ overrides,
537
+ packageJsonChangedProps,
538
+ extensions,
539
+ buildStatus,
540
+ parents,
541
+ squashed,
542
+ unrelated,
543
+ bitVersion,
544
+ modified,
545
+ origin,
546
+ hidden,
547
+ } = contentParsed;
548
+
549
+ const _getDependencies = (deps = []): Dependency[] => {
550
+ const getRelativePath = (relativePath) => {
551
+ if (relativePath.importSpecifiers) {
552
+ // backward compatibility. Before the massive validation was added, an item of
553
+ // relativePath.importSpecifiers array could be missing the mainFile property, which is
554
+ // an invalid ImportSpecifier. (instead the mainFile it had another importSpecifiers object).
555
+ relativePath.importSpecifiers = relativePath.importSpecifiers.filter(
556
+ (importSpecifier) => importSpecifier.mainFile
557
+ );
558
+ if (!relativePath.importSpecifiers.length) delete relativePath.importSpecifiers;
559
+ }
560
+
561
+ return relativePath;
562
+ };
563
+
564
+ return deps.map((dependency: any) => {
565
+ if (!dependency.id.scope) {
566
+ throw new BitIdCompIdError(dependency.id.name);
567
+ }
568
+ return new Dependency(
569
+ ComponentID.fromObject(dependency.id),
570
+ Array.isArray(dependency.relativePaths)
571
+ ? dependency.relativePaths.map(getRelativePath)
572
+ : dependency.relativePaths
573
+ );
574
+ });
575
+ };
576
+
577
+ // Accept both string[] and object[] for backward compatibility
578
+ const parseFlattenedDeps = (deps = []): ComponentID[] => {
579
+ if (!deps.length) return [];
580
+ if (typeof deps[0] === 'string') return deps.map((dep) => ComponentID.fromString(dep));
581
+ return deps.map((dep) => ComponentID.fromObject(dep));
582
+ };
583
+
584
+ const _groupFlattenedDependencies = () => {
585
+ // support backward compatibility. until v15, there was both flattenedDependencies and
586
+ // flattenedDevDependencies. since then, these both were grouped to one flattenedDependencies
587
+ const flattenedDeps = parseFlattenedDeps(flattenedDependencies);
588
+ const flattenedDevDeps = parseFlattenedDeps(flattenedDevDependencies);
589
+ return ComponentIdList.fromArray([...flattenedDeps, ...flattenedDevDeps]);
590
+ };
591
+
592
+ const parseFile = (file) => {
593
+ return {
594
+ file: Ref.from(file.file),
595
+ relativePath: file.relativePath,
596
+ name: file.name,
597
+ test: file.test,
598
+ };
599
+ };
600
+ const _getExtensions = (exts = []): ExtensionDataList => {
601
+ if (exts.length) {
602
+ const newExts = exts.map((extension: any) => {
603
+ if (extension.extensionId) {
604
+ const extensionId = ComponentID.fromObject(extension.extensionId);
605
+ const entry = new ExtensionDataEntry(undefined, extensionId, undefined, extension.config, extension.data);
606
+ return entry;
607
+ }
608
+ const entry = new ExtensionDataEntry(
609
+ extension.id,
610
+ undefined,
611
+ extension.name,
612
+ extension.config,
613
+ extension.data
614
+ );
615
+ return entry;
616
+ });
617
+ return ExtensionDataList.fromModelObject(newExts);
618
+ }
619
+ return new ExtensionDataList();
620
+ };
621
+
622
+ return new Version({
623
+ mainFile,
624
+ files: files.map(parseFile),
625
+ bindingPrefix,
626
+ schema: schema || undefined,
627
+ log: {
628
+ // workaround for a bug where the log.message was saved as boolean when running `bit tag -m ""`
629
+ // the bug was fixed since v0.1.27, but old objects might still have this bug
630
+ message: typeof log.message !== 'string' ? '' : log.message,
631
+ date: log.date,
632
+ username: log.username,
633
+ email: log.email,
634
+ },
635
+ docs,
636
+ dependencies: _getDependencies(dependencies),
637
+ devDependencies: _getDependencies(devDependencies),
638
+ flattenedDependencies: _groupFlattenedDependencies(),
639
+ // backward compatibility. before introducing `flattenedEdgesRef`, we only had `flattenedEdges`. see getFlattenedEdges() for more info.
640
+ flattenedEdges: flattenedEdgesRef ? [] : flattenedEdges?.map((f) => Version.depEdgeFromObject(f)) || [],
641
+ flattenedEdgesRef: flattenedEdgesRef ? Ref.from(flattenedEdgesRef) : undefined,
642
+ dependenciesGraphRef: dependenciesGraphRef ? Ref.from(dependenciesGraphRef) : undefined,
643
+ devPackageDependencies,
644
+ peerPackageDependencies,
645
+ packageDependencies,
646
+ overrides,
647
+ packageJsonChangedProps,
648
+ hash,
649
+ parents: parents ? parents.map((p) => Ref.from(p)) : [],
650
+ squashed: squashed
651
+ ? { previousParents: squashed.previousParents.map((r) => Ref.from(r)), laneId: new LaneId(squashed.laneId) }
652
+ : undefined,
653
+ unrelated: unrelated ? { head: Ref.from(unrelated.head), laneId: new LaneId(unrelated.laneId) } : undefined,
654
+ extensions: _getExtensions(extensions),
655
+ buildStatus,
656
+ bitVersion,
657
+ modified,
658
+ origin,
659
+ hidden,
660
+ });
661
+ }
662
+
663
+ /**
664
+ * used by raw-object.toRealObject()
665
+ */
666
+ static from(versionProps: VersionProps, hash: string): Version {
667
+ return Version.parse(JSON.stringify(versionProps), hash);
668
+ }
669
+
670
+ /**
671
+ * Create version model object from consumer component
672
+ * @param {*} param0
673
+ */
674
+ static fromComponent({
675
+ component,
676
+ files,
677
+ flattenedEdges,
678
+ dependenciesGraph,
679
+ }: {
680
+ component: ConsumerComponent;
681
+ files: Array<SourceFileModel>;
682
+ flattenedEdges?: Source;
683
+ dependenciesGraph?: Source;
684
+ }) {
685
+ const parseFile = (file) => {
686
+ return {
687
+ file: file.file.hash(),
688
+ relativePath: file.relativePath,
689
+ name: file.name,
690
+ test: file.test,
691
+ };
692
+ };
693
+
694
+ if (!component.log) throw new Error('Version.fromComponent - component.log is missing');
695
+ const version = new Version({
696
+ mainFile: pathNormalizeToLinux(component.mainFile),
697
+ files: files.map(parseFile),
698
+ bindingPrefix: component.bindingPrefix,
699
+ log: component.log as Log,
700
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
701
+ docs: component.docs,
702
+ dependencies: component.dependencies.get(),
703
+ devDependencies: component.devDependencies.get(),
704
+ packageDependencies: component.packageDependencies,
705
+ devPackageDependencies: component.devPackageDependencies,
706
+ peerPackageDependencies: component.peerPackageDependencies,
707
+ dependenciesGraphRef: dependenciesGraph?.hash(),
708
+ flattenedDependencies: component.flattenedDependencies,
709
+ // it's safe to remove this line once the version.flattenedEdges prop is deleted
710
+ flattenedEdges: component.flattenedEdges,
711
+ flattenedEdgesRef: flattenedEdges?.hash(),
712
+ schema: component.schema,
713
+ overrides: component.overrides.componentOverridesData,
714
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
715
+ packageJsonChangedProps: component.packageJsonChangedProps,
716
+ extensions: component.extensions,
717
+ buildStatus: component.buildStatus,
718
+ componentId: component.id,
719
+ bitVersion: getBitVersion(),
720
+ });
721
+ if (isSnap(component.version)) {
722
+ version._hash = component.version as string;
723
+ } else {
724
+ version.setNewHash();
725
+ }
726
+
727
+ return version;
728
+ }
729
+
730
+ setNewHash() {
731
+ this._hash = sha1(v4());
732
+ }
733
+
734
+ get ignoreSharedDir(): boolean {
735
+ return !isSchemaSupport(SchemaFeature.sharedDir, this.schema);
736
+ }
737
+
738
+ get isLegacy(): boolean {
739
+ return !this.schema || this.schema === SchemaName.Legacy;
740
+ }
741
+
742
+ get originLaneId(): LaneId | undefined {
743
+ return this.origin?.lane ? new LaneId({ name: this.origin.lane.name, scope: this.origin.lane.scope }) : undefined;
744
+ }
745
+ get originId(): ComponentID | undefined {
746
+ return this.origin?.id
747
+ ? ComponentID.fromObject({ scope: this.origin.id.scope, name: this.origin.id.name })
748
+ : undefined;
749
+ }
750
+
751
+ setDist(dist: Source | undefined) {
752
+ // @ts-ignore AUTO-ADDED-AFTER-MIGRATION-PLEASE-FIX!
753
+ this.dist = dist
754
+ ? {
755
+ file: dist.hash(),
756
+ name: DEFAULT_BUNDLE_FILENAME,
757
+ }
758
+ : null;
759
+ }
760
+
761
+ hasParent(ref: Ref) {
762
+ return this.parents.find((p) => p.toString() === ref.toString());
763
+ }
764
+
765
+ addParent(ref: Ref) {
766
+ if (this.isLegacy) return;
767
+ if (this.hasParent(ref)) {
768
+ return; // make sure to not add twice
769
+ }
770
+ this.parents.push(ref);
771
+ }
772
+
773
+ setSquashed(squashData: SquashData, log: Log, replaceMessage?: string) {
774
+ this.squashed = squashData;
775
+ this.addModifiedLog(log);
776
+ if (replaceMessage) {
777
+ this.addModifiedLog({
778
+ username: undefined,
779
+ email: undefined,
780
+ date: Date.now().toString(),
781
+ message: `squashing: replacing the original log.message, which was: "${this.log.message || '<empty>'}"`,
782
+ });
783
+ this.log.message = replaceMessage;
784
+ }
785
+ }
786
+
787
+ setUnrelated(externalHead: ExternalHead) {
788
+ this.unrelated = externalHead;
789
+ }
790
+
791
+ addModifiedLog(log: Log) {
792
+ this.modified.push(log);
793
+ }
794
+
795
+ addAsOnlyParent(ref: Ref) {
796
+ if (this.isLegacy) return;
797
+ this.parents = [ref];
798
+ }
799
+
800
+ removeParent(ref: Ref) {
801
+ this.parents = this.parents.filter((p) => p.toString() !== ref.toString());
802
+ }
803
+
804
+ removeAllParents() {
805
+ this.parents = [];
806
+ }
807
+
808
+ modelFilesToSourceFiles(repository: Repository): Promise<SourceFile[]> {
809
+ return Promise.all(this.files.map((file) => SourceFile.loadFromSourceFileModel(file, repository)));
810
+ }
811
+
812
+ isRemoved(): boolean {
813
+ return Boolean(this.extensions.findCoreExtension(Extensions.remove)?.config?.removed);
814
+ }
815
+ shouldRemoveFromMain(): boolean {
816
+ return Boolean(this.extensions.findCoreExtension(Extensions.remove)?.config?.removeOnMain);
817
+ }
818
+
819
+ /**
820
+ * Validate the version model properties, to make sure we are not inserting something
821
+ * in the wrong format
822
+ */
823
+ validate(): void {
824
+ validateVersionInstance(this);
825
+ }
826
+ }