@teambit/objects 0.0.710 → 0.0.711

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.
@@ -30,6 +30,9 @@ export type Log = {
30
30
  username: string | undefined;
31
31
  email: string | undefined;
32
32
  };
33
+ export type ObjectsLoader = {
34
+ load(ref: Ref, throws?: boolean): Promise<BitObject | undefined>;
35
+ };
33
36
  export type DepEdgeType = 'prod' | 'dev' | 'peer' | 'ext';
34
37
  export type DepEdge = {
35
38
  source: ComponentID;
@@ -64,6 +67,7 @@ export type VersionProps = {
64
67
  devDependencies?: Dependency[];
65
68
  peerDependencies?: Dependency[];
66
69
  flattenedDependencies?: ComponentIdList;
70
+ flattenedDependenciesRef?: Ref;
67
71
  _flattenedEdges?: DepEdge[];
68
72
  flattenedEdges?: DepEdge[];
69
73
  flattenedEdgesRef?: Ref;
@@ -105,23 +109,22 @@ export default class Version extends BitObject {
105
109
  dependencies: Dependencies;
106
110
  devDependencies: Dependencies;
107
111
  peerDependencies: Dependencies;
108
- flattenedDependencies: ComponentIdList;
112
+ private _flattenedDependencies?;
113
+ private flattenedDependencyIds?;
114
+ /**
115
+ * ref to a Source object with the flattened dependencies, as a JSON array of id strings. when it's set, the Version
116
+ * itself has no flattened dependencies, and they have to be loaded with `loadFlattenedDependencies()`.
117
+ */
118
+ flattenedDependenciesRef?: Ref;
109
119
  dependenciesGraphRef?: Ref;
110
120
  _dependenciesGraph?: DependenciesGraph;
111
121
  flattenedEdgesRef?: Ref;
112
122
  _flattenedEdges?: DepEdge[];
113
123
  /**
114
124
  * @deprecated
115
- * to get the flattenedEdges, please use `this.getFlattenedEdges()`.
116
- * this function handles the backward compatibility and provides the flattened edges regardless whether it was saved
117
- * the `flattenedEdgesRef` introduced or after.
118
- *
119
- * the reason this is left here is not for backward compatibility, but for forward compatibility. meaning, if a
120
- * Version object created by the new version is parsed by an old version that doesn't support the flattenedEdgesRef,
121
- * then, it'll be able to still get the flattenedEdges by this prop.
122
- * this is causing duplication currently. the data is kept in both, `this.flattenedEdges` and the file stored in `flattenedEdgesRef`.
123
- * so it'll be best to delete this prop as soon as all scopes are deployed with the new version.
124
- * (around August 2023 should be safe)
125
+ * to get the flattenedEdges, please use `this.getFlattenedEdges()`, which supports both formats.
126
+ * this holds the edges of old Versions, which were saved inside the Version, before `flattenedEdgesRef` was
127
+ * introduced. Versions that have `flattenedEdgesRef` don't save the edges here (see `toObject()`).
125
128
  */
126
129
  private flattenedEdges;
127
130
  packageDependencies: {
@@ -162,7 +165,40 @@ export default class Version extends BitObject {
162
165
  hash(): Ref;
163
166
  get extensionDependencies(): Dependencies;
164
167
  lastModified(): string;
165
- getAllFlattenedDependencies(): ComponentIdList;
168
+ /**
169
+ * @deprecated use `await version.loadFlattenedDependencies(repo)`, which supports both formats. this getter throws
170
+ * when the flattened dependencies are stored in a separate object (`flattenedDependenciesRef`) and weren't loaded.
171
+ * bit doesn't write this format yet, so until it does (around Oct 2027), the getter keeps working.
172
+ */
173
+ get flattenedDependencies(): ComponentIdList;
174
+ /**
175
+ * the flattened dependencies, when they're stored in the Version itself or were loaded already. throws otherwise,
176
+ * when they're stored in a separate object (`flattenedDependenciesRef`), use `loadFlattenedDependencies()`.
177
+ */
178
+ getLoadedFlattenedDependencies(): ComponentIdList;
179
+ /**
180
+ * a new list is saved in the Version itself, so a ref to a separate object, if there was one, is dropped.
181
+ */
182
+ set flattenedDependencies(flattenedDependencies: ComponentIdList);
183
+ /**
184
+ * the flattened dependencies, if they're available without loading a separate object. otherwise, undefined.
185
+ */
186
+ getFlattenedDependenciesIfLoaded(): ComponentIdList | undefined;
187
+ /**
188
+ * use this to get the flattened dependencies. it supports both formats: stored in the Version itself, or stored in
189
+ * a separate Source object (`flattenedDependenciesRef`). `objects` is usually the scope repository, but can be any
190
+ * container of the objects, such as the objects received from a remote.
191
+ */
192
+ loadFlattenedDependencies(objects: ObjectsLoader): Promise<ComponentIdList>;
193
+ /**
194
+ * same as `loadFlattenedDependencies()`, for code that can't be async.
195
+ */
196
+ loadFlattenedDependenciesSync(repo: Repository): ComponentIdList;
197
+ private setFlattenedDependenciesFromSource;
198
+ /**
199
+ * moves the flattened dependencies out of this Version into a new Source object, which the caller has to persist.
200
+ */
201
+ moveFlattenedDependenciesToSource(): Source | undefined;
166
202
  getAllDependencies(): Dependency[];
167
203
  get depsIdsGroupedByType(): {
168
204
  dependencies: ComponentIdList;
@@ -173,7 +209,6 @@ export default class Version extends BitObject {
173
209
  getAllDependenciesCloned(): Dependencies;
174
210
  getAllDependenciesIds(): ComponentIdList;
175
211
  getDependenciesIdsExcludeExtensions(): ComponentIdList;
176
- updateFlattenedDependency(currentId: ComponentID, newId: ComponentID): void;
177
212
  refs(): Ref[];
178
213
  refsWithOptions(includeParents?: boolean, includeArtifacts?: boolean): Ref[];
179
214
  refsWithoutParents(): Ref[];
@@ -127,6 +127,57 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
127
127
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
128
128
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
129
129
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
130
+ // the same flattened dependencies repeat across versions. in a typical scope, hundreds of thousands of entries are a
131
+ // few thousand unique ids. ids are immutable, so the versions share them instead of each holding its own copies.
132
+ // an id object is looked up by its parts (scope, then name, then version). building a key string for each entry instead
133
+ // is slower than creating a new id.
134
+ const flattenedIdsCache = new Map();
135
+ const flattenedIdStrsCache = new Map();
136
+ const MAX_CACHED_FLATTENED_IDS = 100_000;
137
+ let cachedFlattenedIds = 0;
138
+ function countCachedFlattenedId() {
139
+ if (cachedFlattenedIds >= MAX_CACHED_FLATTENED_IDS) {
140
+ flattenedIdsCache.clear();
141
+ flattenedIdStrsCache.clear();
142
+ cachedFlattenedIds = 0;
143
+ }
144
+ cachedFlattenedIds += 1;
145
+ }
146
+ function getFlattenedId(dep) {
147
+ if (typeof dep === 'string') {
148
+ let id = flattenedIdStrsCache.get(dep);
149
+ if (!id) {
150
+ countCachedFlattenedId();
151
+ id = _componentId().ComponentID.fromString(dep);
152
+ flattenedIdStrsCache.set(dep, id);
153
+ }
154
+ return id;
155
+ }
156
+ if (dep.box) return _componentId().ComponentID.fromObject(dep); // legacy ids, rare. not worth another level.
157
+ let byName = flattenedIdsCache.get(dep.scope);
158
+ if (!byName) {
159
+ byName = new Map();
160
+ flattenedIdsCache.set(dep.scope, byName);
161
+ }
162
+ let byVersion = byName.get(dep.name);
163
+ if (!byVersion) {
164
+ byVersion = new Map();
165
+ byName.set(dep.name, byVersion);
166
+ }
167
+ let id = byVersion.get(dep.version);
168
+ if (!id) {
169
+ countCachedFlattenedId();
170
+ id = _componentId().ComponentID.fromObject(dep);
171
+ byVersion.set(dep.version, id);
172
+ }
173
+ return id;
174
+ }
175
+
176
+ // the deprecated `Version.flattenedDependencies` getter warns only once per process.
177
+ let warnedFlattenedDependenciesGetter = false;
178
+
179
+ // anything objects can be loaded from by their ref: the scope repository, or the objects received from a remote.
180
+
130
181
  /**
131
182
  * Represent a version model in the scope
132
183
  */
@@ -142,7 +193,14 @@ class Version extends _objects().BitObject {
142
193
  _defineProperty(this, "dependencies", void 0);
143
194
  _defineProperty(this, "devDependencies", void 0);
144
195
  _defineProperty(this, "peerDependencies", void 0);
145
- _defineProperty(this, "flattenedDependencies", void 0);
196
+ _defineProperty(this, "_flattenedDependencies", void 0);
197
+ // the flattened dependencies of a parsed Version. the list is built on first access, most commands never read it.
198
+ _defineProperty(this, "flattenedDependencyIds", void 0);
199
+ /**
200
+ * ref to a Source object with the flattened dependencies, as a JSON array of id strings. when it's set, the Version
201
+ * itself has no flattened dependencies, and they have to be loaded with `loadFlattenedDependencies()`.
202
+ */
203
+ _defineProperty(this, "flattenedDependenciesRef", void 0);
146
204
  _defineProperty(this, "dependenciesGraphRef", void 0);
147
205
  _defineProperty(this, "_dependenciesGraph", void 0);
148
206
  // caching for the dependencies graph
@@ -152,16 +210,9 @@ class Version extends _objects().BitObject {
152
210
  // caching for the flattenedEdges
153
211
  /**
154
212
  * @deprecated
155
- * to get the flattenedEdges, please use `this.getFlattenedEdges()`.
156
- * this function handles the backward compatibility and provides the flattened edges regardless whether it was saved
157
- * the `flattenedEdgesRef` introduced or after.
158
- *
159
- * the reason this is left here is not for backward compatibility, but for forward compatibility. meaning, if a
160
- * Version object created by the new version is parsed by an old version that doesn't support the flattenedEdgesRef,
161
- * then, it'll be able to still get the flattenedEdges by this prop.
162
- * this is causing duplication currently. the data is kept in both, `this.flattenedEdges` and the file stored in `flattenedEdgesRef`.
163
- * so it'll be best to delete this prop as soon as all scopes are deployed with the new version.
164
- * (around August 2023 should be safe)
213
+ * to get the flattenedEdges, please use `this.getFlattenedEdges()`, which supports both formats.
214
+ * this holds the edges of old Versions, which were saved inside the Version, before `flattenedEdgesRef` was
215
+ * introduced. Versions that have `flattenedEdgesRef` don't save the edges here (see `toObject()`).
165
216
  */
166
217
  _defineProperty(this, "flattenedEdges", void 0);
167
218
  _defineProperty(this, "packageDependencies", void 0);
@@ -200,7 +251,8 @@ class Version extends _objects().BitObject {
200
251
  this.devDependencies = new (_legacy2().Dependencies)(props.devDependencies);
201
252
  this.peerDependencies = new (_legacy2().Dependencies)(props.peerDependencies);
202
253
  this.docs = props.docs;
203
- this.flattenedDependencies = props.flattenedDependencies || new (_componentId().ComponentIdList)();
254
+ if (props.flattenedDependencies) this.flattenedDependencies = props.flattenedDependencies;
255
+ this.flattenedDependenciesRef = props.flattenedDependenciesRef;
204
256
  this.flattenedEdges = props.flattenedEdges || [];
205
257
  this.flattenedEdgesRef = props.flattenedEdgesRef;
206
258
  this.dependenciesGraphRef = props.dependenciesGraphRef;
@@ -325,8 +377,93 @@ class Version extends _objects().BitObject {
325
377
  if (!this.modified || !this.modified.length) return this.log.date;
326
378
  return this.modified[this.modified.length - 1].date;
327
379
  }
328
- getAllFlattenedDependencies() {
329
- return _componentId().ComponentIdList.fromArray([...this.flattenedDependencies]);
380
+
381
+ /**
382
+ * @deprecated use `await version.loadFlattenedDependencies(repo)`, which supports both formats. this getter throws
383
+ * when the flattened dependencies are stored in a separate object (`flattenedDependenciesRef`) and weren't loaded.
384
+ * bit doesn't write this format yet, so until it does (around Oct 2027), the getter keeps working.
385
+ */
386
+ get flattenedDependencies() {
387
+ if (!warnedFlattenedDependenciesGetter) {
388
+ warnedFlattenedDependenciesGetter = true;
389
+ _legacy4().logger.warn(`Version.flattenedDependencies is deprecated and will throw for newer versions, use "await version.loadFlattenedDependencies(repo)" instead`, new Error().stack);
390
+ }
391
+ return this.getLoadedFlattenedDependencies();
392
+ }
393
+
394
+ /**
395
+ * the flattened dependencies, when they're stored in the Version itself or were loaded already. throws otherwise,
396
+ * when they're stored in a separate object (`flattenedDependenciesRef`), use `loadFlattenedDependencies()`.
397
+ */
398
+ getLoadedFlattenedDependencies() {
399
+ if (!this._flattenedDependencies) {
400
+ if (this.flattenedDependenciesRef) {
401
+ throw new Error(`the flattened dependencies of version ${this._hash} are stored in the object ${this.flattenedDependenciesRef.toString()}, load them with loadFlattenedDependencies()`);
402
+ }
403
+ this._flattenedDependencies = _componentId().ComponentIdList.fromArray(this.flattenedDependencyIds || []);
404
+ this.flattenedDependencyIds = undefined;
405
+ }
406
+ return this._flattenedDependencies;
407
+ }
408
+
409
+ /**
410
+ * a new list is saved in the Version itself, so a ref to a separate object, if there was one, is dropped.
411
+ */
412
+ set flattenedDependencies(flattenedDependencies) {
413
+ this._flattenedDependencies = flattenedDependencies;
414
+ this.flattenedDependencyIds = undefined;
415
+ this.flattenedDependenciesRef = undefined;
416
+ }
417
+
418
+ /**
419
+ * the flattened dependencies, if they're available without loading a separate object. otherwise, undefined.
420
+ */
421
+ getFlattenedDependenciesIfLoaded() {
422
+ if (this.flattenedDependenciesRef && !this._flattenedDependencies) return undefined;
423
+ return this.getLoadedFlattenedDependencies();
424
+ }
425
+
426
+ /**
427
+ * use this to get the flattened dependencies. it supports both formats: stored in the Version itself, or stored in
428
+ * a separate Source object (`flattenedDependenciesRef`). `objects` is usually the scope repository, but can be any
429
+ * container of the objects, such as the objects received from a remote.
430
+ */
431
+ async loadFlattenedDependencies(objects) {
432
+ if (this._flattenedDependencies || !this.flattenedDependenciesRef) return this.getLoadedFlattenedDependencies();
433
+ const source = await objects.load(this.flattenedDependenciesRef, false);
434
+ return this.setFlattenedDependenciesFromSource(source);
435
+ }
436
+
437
+ /**
438
+ * same as `loadFlattenedDependencies()`, for code that can't be async.
439
+ */
440
+ loadFlattenedDependenciesSync(repo) {
441
+ if (this._flattenedDependencies || !this.flattenedDependenciesRef) return this.getLoadedFlattenedDependencies();
442
+ // objects added during tag, or fetched from a remote without being imported, are only in memory, not on the disk.
443
+ const source = repo.getFromMemory(this.flattenedDependenciesRef) || repo.loadSync(this.flattenedDependenciesRef, false);
444
+ return this.setFlattenedDependenciesFromSource(source);
445
+ }
446
+ setFlattenedDependenciesFromSource(source) {
447
+ if (!source) {
448
+ // unlike the flattened edges, there is no fallback here. an empty list would be wrong, not just less efficient.
449
+ throw new Error(`unable to find the object ${this.flattenedDependenciesRef?.toString()} with the flattened dependencies of version ${this._hash}`);
450
+ }
451
+ const ids = JSON.parse(source.contents.toString());
452
+ // not by the setter, which would drop the ref.
453
+ this._flattenedDependencies = _componentId().ComponentIdList.fromArray(ids.map(getFlattenedId));
454
+ this.flattenedDependencyIds = undefined;
455
+ return this._flattenedDependencies;
456
+ }
457
+
458
+ /**
459
+ * moves the flattened dependencies out of this Version into a new Source object, which the caller has to persist.
460
+ */
461
+ moveFlattenedDependenciesToSource() {
462
+ const flattenedDependencies = this.getLoadedFlattenedDependencies();
463
+ if (!flattenedDependencies.length) return undefined;
464
+ const source = _source().default.from(Buffer.from(JSON.stringify(flattenedDependencies.map(id => id.toString()))));
465
+ this.flattenedDependenciesRef = source.hash();
466
+ return source;
330
467
  }
331
468
  getAllDependencies() {
332
469
  return [...this.dependencies.dependencies, ...this.devDependencies.dependencies, ...this.extensionDependencies.dependencies];
@@ -350,16 +487,6 @@ class Version extends _objects().BitObject {
350
487
  getDependenciesIdsExcludeExtensions() {
351
488
  return _componentId().ComponentIdList.fromArray([...this.dependencies.getAllIds(), ...this.devDependencies.getAllIds()]);
352
489
  }
353
- updateFlattenedDependency(currentId, newId) {
354
- const getUpdated = flattenedDependencies => {
355
- const updatedIds = flattenedDependencies.map(depId => {
356
- if (depId.isEqual(currentId)) return newId;
357
- return depId;
358
- });
359
- return _componentId().ComponentIdList.fromArray(updatedIds);
360
- };
361
- this.flattenedDependencies = getUpdated(this.flattenedDependencies);
362
- }
363
490
  refs() {
364
491
  return this.refsWithOptions();
365
492
  }
@@ -380,6 +507,7 @@ class Version extends _objects().BitObject {
380
507
  }
381
508
  if (this.flattenedEdgesRef) allRefs.push(this.flattenedEdgesRef);
382
509
  if (this.dependenciesGraphRef) allRefs.push(this.dependenciesGraphRef);
510
+ if (this.flattenedDependenciesRef) allRefs.push(this.flattenedDependenciesRef);
383
511
  return allRefs;
384
512
  }
385
513
  refsWithoutParents() {
@@ -462,9 +590,8 @@ class Version extends _objects().BitObject {
462
590
  docs: this.docs,
463
591
  dependencies: this.dependencies.cloneAsObject(),
464
592
  devDependencies: this.devDependencies.cloneAsObject(),
465
- flattenedDependencies: this.flattenedDependencies.map(dep => dep.toObject()),
466
- // @todo: uncomment this in the future, once all remotes are updated to support the backward compatibility.
467
- // flattenedDependencies: this.flattenedDependencies.map((dep) => dep.toString()),
593
+ flattenedDependencies: this.flattenedDependenciesRef ? undefined : this.getLoadedFlattenedDependencies().map(dep => dep.toObject()),
594
+ flattenedDependenciesRef: this.flattenedDependenciesRef?.toString(),
468
595
  flattenedEdges: this.flattenedEdgesRef ? undefined : this.flattenedEdges.map(f => Version.depEdgeToObject(f)),
469
596
  flattenedEdgesRef: this.flattenedEdgesRef?.toString(),
470
597
  dependenciesGraphRef: this.dependenciesGraphRef?.toString(),
@@ -519,6 +646,7 @@ class Version extends _objects().BitObject {
519
646
  devDependencies,
520
647
  flattenedDependencies,
521
648
  flattenedDevDependencies,
649
+ flattenedDependenciesRef,
522
650
  flattenedEdges,
523
651
  flattenedEdgesRef,
524
652
  dependenciesGraphRef,
@@ -556,20 +684,6 @@ class Version extends _objects().BitObject {
556
684
  return new (_legacy2().Dependency)(_componentId().ComponentID.fromObject(dependency.id), Array.isArray(dependency.relativePaths) ? dependency.relativePaths.map(getRelativePath) : dependency.relativePaths);
557
685
  });
558
686
  };
559
-
560
- // Accept both string[] and object[] for backward compatibility
561
- const parseFlattenedDeps = (deps = []) => {
562
- if (!deps.length) return [];
563
- if (typeof deps[0] === 'string') return deps.map(dep => _componentId().ComponentID.fromString(dep));
564
- return deps.map(dep => _componentId().ComponentID.fromObject(dep));
565
- };
566
- const _groupFlattenedDependencies = () => {
567
- // support backward compatibility. until v15, there was both flattenedDependencies and
568
- // flattenedDevDependencies. since then, these both were grouped to one flattenedDependencies
569
- const flattenedDeps = parseFlattenedDeps(flattenedDependencies);
570
- const flattenedDevDeps = parseFlattenedDeps(flattenedDevDependencies);
571
- return _componentId().ComponentIdList.fromArray([...flattenedDeps, ...flattenedDevDeps]);
572
- };
573
687
  const parseFile = file => {
574
688
  return {
575
689
  file: _objects().Ref.from(file.file),
@@ -593,7 +707,7 @@ class Version extends _objects().BitObject {
593
707
  }
594
708
  return new (_legacy3().ExtensionDataList)();
595
709
  };
596
- return new Version({
710
+ const version = new Version({
597
711
  mainFile,
598
712
  files: files.map(parseFile),
599
713
  bindingPrefix,
@@ -609,11 +723,11 @@ class Version extends _objects().BitObject {
609
723
  docs,
610
724
  dependencies: _getDependencies(dependencies),
611
725
  devDependencies: _getDependencies(devDependencies),
612
- flattenedDependencies: _groupFlattenedDependencies(),
613
726
  // backward compatibility. before introducing `flattenedEdgesRef`, we only had `flattenedEdges`. see getFlattenedEdges() for more info.
614
727
  flattenedEdges: flattenedEdgesRef ? [] : flattenedEdges?.map(f => Version.depEdgeFromObject(f)) || [],
615
728
  flattenedEdgesRef: flattenedEdgesRef ? _objects().Ref.from(flattenedEdgesRef) : undefined,
616
729
  dependenciesGraphRef: dependenciesGraphRef ? _objects().Ref.from(dependenciesGraphRef) : undefined,
730
+ flattenedDependenciesRef: flattenedDependenciesRef ? _objects().Ref.from(flattenedDependenciesRef) : undefined,
617
731
  devPackageDependencies,
618
732
  peerPackageDependencies,
619
733
  packageDependencies,
@@ -637,6 +751,10 @@ class Version extends _objects().BitObject {
637
751
  hidden,
638
752
  batchId
639
753
  });
754
+ // until v15, there were both flattenedDependencies and flattenedDevDependencies. since then, they're grouped into
755
+ // flattenedDependencies. an entry is either an id string or an id object.
756
+ version.flattenedDependencyIds = [...(flattenedDependencies || []), ...(flattenedDevDependencies || [])].map(getFlattenedId);
757
+ return version;
640
758
  }
641
759
 
642
760
  /**
@@ -678,7 +796,7 @@ class Version extends _objects().BitObject {
678
796
  peerPackageDependencies: component.peerPackageDependencies,
679
797
  dependenciesGraphRef: dependenciesGraph?.hash(),
680
798
  flattenedDependencies: component.flattenedDependencies,
681
- // it's safe to remove this line once the version.flattenedEdges prop is deleted
799
+ // not saved in the Version when `flattenedEdgesRef` is set, see `toObject()`.
682
800
  flattenedEdges: component.flattenedEdges,
683
801
  flattenedEdgesRef: flattenedEdges?.hash(),
684
802
  schema: component.schema,