import type { CLIMain } from '@teambit/cli'; import type { ScopeMain } from '@teambit/scope'; import type { GraphqlMain } from '@teambit/graphql'; import type { ExpressMain } from '@teambit/express'; import type { Workspace } from '@teambit/workspace'; import type { LaneDiffResults } from '@teambit/lanes.modules.diff'; import type { TrackLane, LaneData } from '@teambit/legacy.scope'; import { LaneId } from '@teambit/lane-id'; import type { Logger, LoggerMain } from '@teambit/logger'; import type { DiffOptions } from '@teambit/legacy.component-diff'; import type { MergeStrategy } from '@teambit/component.modules.merge-helper'; import type { MergingMain } from '@teambit/merging'; import type { ImporterMain } from '@teambit/importer'; import { ComponentID } from '@teambit/component-id'; import type { Component, ComponentMain } from '@teambit/component'; import type { LaneHistory } from '@teambit/objects'; import { Lane } from '@teambit/objects'; import type { SnapsDistance } from '@teambit/component.snap-distance'; import type { ExportMain } from '@teambit/export'; import type { ComponentCompareMain } from '@teambit/component-compare'; import type { ComponentWriterMain } from '@teambit/component-writer'; import type { RemoveMain } from '@teambit/remove'; import type { CheckoutMain } from '@teambit/checkout'; import { ChangeType } from '@teambit/lanes.entities.lane-diff'; import type { ComponentsList } from '@teambit/legacy.component-list'; import type { LaneCheckoutOpts } from './lane.cmd'; import type { InstallMain } from '@teambit/install'; export { Lane }; export type SnapsDistanceObj = { onSource: string[]; onTarget: string[]; common?: string; }; export type LaneResults = { lanes: LaneData[]; currentLane?: string | null; }; export type CreateLaneOptions = { scope?: string; alias?: string; forkLaneNewScope?: boolean; }; export type SwitchLaneOptions = { skipFetch?: boolean; alias?: string; merge?: MergeStrategy; forceOurs?: boolean; forceTheirs?: boolean; workspaceOnly?: boolean; pattern?: string; /** switch only the lane components from these scopes (see `SwitchProps.restrictToScopes`) */ restrictToScopes?: string[]; skipDependencyInstallation?: boolean; verbose?: boolean; override?: boolean; branch?: boolean; }; /** where the base was resolved from: `workspace` (already local) or `scope` (fetched from remote). */ export type DiffBaseSource = 'workspace' | 'scope'; export type LaneComponentDiffStatus = { componentId: ComponentID; sourceHead: string; targetHead?: string; /** where the base was resolved from (workspace vs remote scope). @see DiffBaseSource */ baseSource?: DiffBaseSource; /** * @deprecated * use changes to get list of all the changes */ changeType?: ChangeType; changes?: ChangeType[]; upToDate?: boolean; snapsDistance?: SnapsDistanceObj; unrelated?: boolean; /** * internal context for deferred derivation of `changes`. not exposed on the GraphQL schema — * the `changes` field resolver consumes this via `deriveComponentChanges` so the heavy * `componentCompare.compare()` + `getAPIDiff()` work only runs when the field is selected, * lazily per-component, in parallel via graphql-js list resolution. */ changesContext?: { commonSnap?: { hash: string; } | null; skipped?: boolean; pending?: Promise; }; }; export type LaneDiffStatusOptions = { /** skip importing the common snaps and computing `changes` entirely */ skipChanges?: boolean; /** * drop components where the snaps-distance says the source already includes everything on the * target. these contribute nothing to a target→source merge view but each costs an * `importWithoutDeps` round trip + an `apiDiff` schema extraction. */ skipUpToDate?: boolean; /** * still classify snap distance, but don't compute `changes` eagerly. callers derive them lazily * via `deriveComponentChanges` (used by GraphQL field resolvers). */ deferChanges?: boolean; /** * after computing the result, eagerly warm the compare/host caches the lane-compare UI will hit next. * UI-only: it fans out concurrent component loads, so CLI/programmatic callers (which never make those * follow-up queries) must leave it off to avoid paying — and multiplying — that cold-load cost. */ prewarmCaches?: boolean; }; export type DivergeDataPerId = { id: ComponentID; divergeData: SnapsDistance; }; export type LaneDiffStatus = { source: LaneId; target: LaneId; componentsStatus: LaneComponentDiffStatus[]; }; export type MarkRemoveOnLaneResult = { removedFromWs: ComponentID[]; markedRemoved: ComponentID[]; }; export type CreateLaneResult = { lane: Lane; laneId: LaneId; hash: string; alias?: string; }; export declare class LanesMain { readonly workspace: Workspace | undefined; private scope; private merging; private componentAspect; logger: Logger; readonly importer: ImporterMain; private exporter; private componentCompare; readonly componentWriter: ComponentWriterMain; private remove; readonly checkout: CheckoutMain; private install; constructor(workspace: Workspace | undefined, scope: ScopeMain, merging: MergingMain, componentAspect: ComponentMain, logger: Logger, importer: ImporterMain, exporter: ExportMain, componentCompare: ComponentCompareMain, componentWriter: ComponentWriterMain, remove: RemoveMain, checkout: CheckoutMain, install: InstallMain); /** * disk-persisted memo layer for the lane-diff computation (snaps-distance, change-types and the * top-level result). extracted to its own class — see `LaneDiffCache` in lanes/diff. */ private _laneDiffCache?; private get laneDiffCache(); /** * Bound the parallelism of `deriveChangeTypes` across all in-flight requests. graphql-js resolves * list fields in parallel via `Promise.all`, so an uncapped derivation fires one `compare()` per * component at once. The old cap of 4 existed because derivation also ran `getAPIDiff` (serial * tsserver schema extraction) — that's now deferred to the API view, so derivation only does the * I/O+CPU-bound `compare()`, which parallelizes well. Cap to the component concurrency limit. */ private deriveChangesLimit; /** single-flight for concurrent `deriveComponentChanges` calls on the same memo key. */ private changeTypesInflight; private tryDiffStatusResultMemo; /** * Pre-warm the downstream caches the lane-compare UI hits right after `LaneDiffStatus`: * - the scope's `ScopeComponentLoader.componentsCache` via `host.getMany([…])` * - `componentCompare`'s disk-persisted result memo via `compareComponents(pairs)` * * Fire-and-forget. The UI's follow-up `Component` and `CompareComponents` queries arrive ~50–200 ms * after we return; this kickoff happens *before* we return, so the work overlaps the UI's render * tick and the response serialization. By the time the UI's queries land on the server, the caches * are populated (or, worst case, the pre-warm work is in-flight and the resolver-level single-flight * in `componentCompare` dedupes the load). */ private prewarmCompareCaches; private populateDiffStatusMemoAsync; /** * return the lane data without the deleted components. * the deleted components are filtered out in legacyScope.lanes.getLanesData() */ getLanes({ name, remote, merged, showDefaultLane, notMerged, }: { name?: string; remote?: string; merged?: boolean; showDefaultLane?: boolean; notMerged?: boolean; }): Promise; parseLaneId(idStr: string): Promise; getLaneHistory(laneId: LaneId): Promise; checkoutHistory(historyId: string, options?: LaneCheckoutOpts): Promise; revertHistory(historyId: string, options?: LaneCheckoutOpts): Promise; private getHistoryItemOfCurrentLane; importLaneHistory(laneId: LaneId): Promise; isLaneExistsOnRemote(laneId: LaneId): Promise; getCurrentLaneName(): string | null; getCurrentLaneNameOrAlias(): string | null; getCurrentLaneId(): LaneId | null; /** * get the currently checked out lane object, if on main - return null. */ getCurrentLane(): Promise; getDefaultLaneId(): LaneId; setCurrentLane(laneId: LaneId, alias?: string, exported?: boolean): void; createLane(name: string, { scope, alias, forkLaneNewScope }?: CreateLaneOptions): Promise; loadLane(id: LaneId): Promise; trackLane(localName: string, remoteScope: string, remoteName?: string): Promise<{ beforeTrackData?: TrackLane; afterTrackData: TrackLane; }>; aliasLane(laneName: string, alias: string): Promise<{ laneId: LaneId; }>; changeScope(remoteScope: string, laneName?: string): Promise<{ remoteScopeBefore: string; localName: string; }>; /** * change a lane-name and if possible, export the lane to the remote */ rename(newName: string, laneName?: string): Promise<{ currentName: string; }>; exportLane(lane: Lane): Promise; importLaneObject(laneId: LaneId, persistIfNotExists?: boolean, includeLaneHistory?: boolean): Promise; eject(pattern: string): Promise; /** head hash of main, with remote-scope fallback. undefined only for a genuinely-new component. */ getHeadOnMain(componentId: ComponentID): Promise; /** * fetch the lane object and its components from the remote. * save the objects and the lane to the local scope. * this method doesn't change anything in the workspace. */ fetchLaneWithItsComponents(laneId: LaneId): Promise; removeLanes(laneNames: string[], opts?: { remote: boolean; force: boolean; }): Promise; /** * when deleting a lane object, it is sent into the "trash" directory in the scope. * this method restores it and put it back in the "objects" directory. * as an argument, it needs a hash. the reason for not supporting lane-id is because the trash may have multiple * lanes with the same lane-id but different hashes. */ restoreLane(laneHash: string): Promise; /** * switch to a different local or remote lane. * switching to a remote lane also imports and writes the components of that remote lane. * by default, only the components existing on the workspace will be imported from that lane, unless the "getAll" * flag is true. */ switchLanes(laneName: string, { alias, merge, forceOurs, forceTheirs, pattern, workspaceOnly, restrictToScopes, skipDependencyInstallation, skipFetch, branch, }: SwitchLaneOptions): Promise; private createGitBranchForLane; /** * the values array may include zero to two values and will be processed as following: * [] => diff between the current lane and default lane. (only inside workspace). * [to] => diff between the current lane (or default-lane when in scope) and "to" lane. * [from, to] => diff between "from" lane and "to" lane. */ getDiff(values: string[], diffOptions?: DiffOptions, pattern?: string): Promise; getLaneComponentModels(lane: LaneData): Promise; getLaneComponentIds(lane: LaneData): Promise; /** * hidden lane.updateDependents are intentionally excluded from `getLaneComponentIds` so the * default GraphQL `Lane.components` field stays workspace-facing. Consumers that need the full * lane graph (e.g. a CI dashboard surfacing cascade entries) opt in via this method or its * `updateDependentIds` / `updateDependentComponents` GraphQL counterparts. No bitmap filter * here — hidden entries by definition don't live in the bitmap. */ getLaneUpdateDependentIds(lane: LaneData): Promise; getLaneUpdateDependentComponents(lane: LaneData): Promise; getLaneReadmeComponent(lane: LaneData): Promise; removeLaneReadme(laneName?: string): Promise<{ result: boolean; message?: string; }>; diffStatus(sourceLaneId: LaneId, targetLaneId?: LaneId, options?: LaneDiffStatusOptions): Promise; private componentDiffStatus; /** * Lazily derive the change types for a single component diff status. Used by the GraphQL `changes` * field resolver so the (expensive) derivation only runs when the field is selected. Memoized per * status object via `changesContext.pending`, so selecting both `changes` and `changeType` computes * the value once. */ deriveComponentChanges(status: LaneComponentDiffStatus): Promise; private deriveChangeTypes; private recreateNewLaneIfDeleted; /** * if the local lane was forked from another lane, this gets the differences between the two. * it also fetches the original lane from the remote to make sure the data is up to date. */ listUpdatesFromForked(componentsList: ComponentsList): Promise; /** * list components on a lane that their main got updates. */ listUpdatesFromMainPending(componentsList: ComponentsList): Promise; /** * default to remove all of them. * returns true if the lane has changed */ removeUpdateDependents(laneId: LaneId, ids?: ComponentID[]): Promise; private getLaneDataOfDefaultLane; get createRoutePath(): string; get deleteRoutePath(): string; get restoreRoutePath(): string; static slots: never[]; static dependencies: import("@teambit/harmony").Aspect[]; static runtime: import("@teambit/harmony").RuntimeDefinition; static provider([cli, scope, workspace, graphql, merging, component, loggerMain, importer, exporter, express, componentCompare, componentWriter, remove, checkout, install,]: [ CLIMain, ScopeMain, Workspace, GraphqlMain, MergingMain, ComponentMain, LoggerMain, ImporterMain, ExportMain, ExpressMain, ComponentCompareMain, ComponentWriterMain, RemoveMain, CheckoutMain, InstallMain ]): Promise; } export default LanesMain;