@teambit/component 0.0.555 → 0.0.559
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/dist/component.graphql.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/package.json +49 -34
- package/tsconfig.json +1 -1
- package/aspect-entry.ts +0 -67
- package/aspect-list.ts +0 -100
- package/aspect.section.tsx +0 -16
- package/component-factory.ts +0 -106
- package/component-fs.ts +0 -60
- package/component-map/component-map.ts +0 -106
- package/component-map/index.ts +0 -1
- package/component-meta.ts +0 -29
- package/component.aspect.ts +0 -9
- package/component.graphql.ts +0 -202
- package/component.main.runtime.ts +0 -162
- package/component.route.ts +0 -26
- package/component.ts +0 -278
- package/component.ui.runtime.tsx +0 -216
- package/config.ts +0 -34
- package/dependencies/dependencies.ts +0 -74
- package/dependencies/index.ts +0 -1
- package/exceptions/could-not-find-latest.ts +0 -8
- package/exceptions/host-not-found.ts +0 -14
- package/exceptions/index.ts +0 -4
- package/exceptions/nothing-to-snap.ts +0 -1
- package/hash.ts +0 -4
- package/head.ts +0 -0
- package/history-graph.ts +0 -1
- package/host/component-host-model.ts +0 -9
- package/host/index.ts +0 -2
- package/host/use-component-host.ts +0 -39
- package/index.ts +0 -32
- package/on-load.ts +0 -0
- package/package-tar/teambit-component-0.0.555.tgz +0 -0
- package/section/index.ts +0 -1
- package/section/section.tsx +0 -8
- package/show/extensions.fragment.ts +0 -23
- package/show/files.fragment.ts +0 -24
- package/show/id.fragment.ts +0 -20
- package/show/index.ts +0 -8
- package/show/main-file.fragment.ts +0 -13
- package/show/name.fragment.ts +0 -13
- package/show/scope.fragment.ts +0 -15
- package/show/show-fragment.ts +0 -44
- package/show/show.cmd.ts +0 -85
- package/snap/author.ts +0 -19
- package/snap/index.ts +0 -2
- package/snap/snap.ts +0 -63
- package/state.ts +0 -73
- package/store.ts +0 -3
- package/tag/index.ts +0 -1
- package/tag/tag.ts +0 -37
- package/tag-map.ts +0 -87
- package/types/asset.d.ts +0 -29
- package/types/style.d.ts +0 -42
- package/ui/aspect-page/aspect-page.tsx +0 -64
- package/ui/aspect-page/index.ts +0 -1
- package/ui/component-error/component-error.tsx +0 -22
- package/ui/component-error/index.ts +0 -1
- package/ui/component-model/component-model.ts +0 -169
- package/ui/component-model/index.ts +0 -1
- package/ui/component.tsx +0 -48
- package/ui/context/component-context.ts +0 -5
- package/ui/context/component-provider.tsx +0 -20
- package/ui/context/index.ts +0 -2
- package/ui/index.ts +0 -3
- package/ui/menu/index.ts +0 -2
- package/ui/menu/menu-nav.tsx +0 -37
- package/ui/menu/menu.tsx +0 -94
- package/ui/menu/nav-plugin.tsx +0 -9
- package/ui/top-bar-nav/index.ts +0 -1
- package/ui/top-bar-nav/top-bar-nav.tsx +0 -26
- package/ui/use-component-query.ts +0 -195
- package/ui/use-component.tsx +0 -34
package/component-meta.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { capitalize } from '@teambit/toolbox.string.capitalize';
|
|
2
|
-
import { ComponentID } from '@teambit/component-id';
|
|
3
|
-
|
|
4
|
-
export class ComponentMeta {
|
|
5
|
-
constructor(
|
|
6
|
-
/**
|
|
7
|
-
* id the component.
|
|
8
|
-
*/
|
|
9
|
-
readonly id: ComponentID
|
|
10
|
-
) {}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* display name of the component.
|
|
14
|
-
*/
|
|
15
|
-
get displayName() {
|
|
16
|
-
const tokens = this.id.name.split('-').map((token) => capitalize(token));
|
|
17
|
-
return tokens.join(' ');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
toObject() {
|
|
21
|
-
return {
|
|
22
|
-
id: this.id.toObject(),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
static from(object: { [key: string]: any }) {
|
|
27
|
-
return new ComponentMeta(ComponentID.fromObject(object.id));
|
|
28
|
-
}
|
|
29
|
-
}
|
package/component.aspect.ts
DELETED
package/component.graphql.ts
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import stripAnsi from 'strip-ansi';
|
|
2
|
-
import gql from 'graphql-tag';
|
|
3
|
-
import { GraphQLJSONObject } from 'graphql-type-json';
|
|
4
|
-
import { pathNormalizeToLinux } from '@teambit/legacy/dist/utils';
|
|
5
|
-
|
|
6
|
-
import { Component } from './component';
|
|
7
|
-
import { ComponentFactory } from './component-factory';
|
|
8
|
-
import { ComponentMain } from './component.main.runtime';
|
|
9
|
-
|
|
10
|
-
export function componentSchema(componentExtension: ComponentMain) {
|
|
11
|
-
return {
|
|
12
|
-
typeDefs: gql`
|
|
13
|
-
scalar JSON
|
|
14
|
-
scalar JSONObject
|
|
15
|
-
|
|
16
|
-
type ComponentID {
|
|
17
|
-
name: String!
|
|
18
|
-
version: String
|
|
19
|
-
scope: String
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type Tag {
|
|
23
|
-
# semver assigned to the tag.
|
|
24
|
-
version: String!
|
|
25
|
-
|
|
26
|
-
# tag hash.
|
|
27
|
-
hash: String!
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
type Snap {
|
|
31
|
-
# hash of the snapshot.
|
|
32
|
-
hash: String!
|
|
33
|
-
|
|
34
|
-
# time of the snapshot.
|
|
35
|
-
timestamp: String!
|
|
36
|
-
|
|
37
|
-
# parents of the snap
|
|
38
|
-
parents: [Snap]!
|
|
39
|
-
|
|
40
|
-
# snapper
|
|
41
|
-
author: Author!
|
|
42
|
-
|
|
43
|
-
# snapshot message
|
|
44
|
-
message: String
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
type LogEntry {
|
|
48
|
-
message: String!
|
|
49
|
-
username: String
|
|
50
|
-
email: String
|
|
51
|
-
date: String
|
|
52
|
-
hash: String!
|
|
53
|
-
tag: String
|
|
54
|
-
# id: String!
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
type Author {
|
|
58
|
-
# display name of the snapper.
|
|
59
|
-
displayName: String!
|
|
60
|
-
|
|
61
|
-
# author of the snapper.
|
|
62
|
-
email: String!
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
type Component {
|
|
66
|
-
# id of the component.
|
|
67
|
-
id: ComponentID!
|
|
68
|
-
|
|
69
|
-
# head snap of the component.
|
|
70
|
-
head: Snap
|
|
71
|
-
|
|
72
|
-
# head tag of the component.
|
|
73
|
-
headTag: Tag
|
|
74
|
-
|
|
75
|
-
# list of all relative component paths.
|
|
76
|
-
fs: [String]
|
|
77
|
-
|
|
78
|
-
# relative path to the main file of the component
|
|
79
|
-
mainFile: String
|
|
80
|
-
|
|
81
|
-
# return specific file contents by relative file path.
|
|
82
|
-
getFile(path: String): String
|
|
83
|
-
|
|
84
|
-
# latest version of the component.
|
|
85
|
-
latest: String
|
|
86
|
-
|
|
87
|
-
# display name of the component
|
|
88
|
-
displayName: String!
|
|
89
|
-
|
|
90
|
-
# component buildStatus
|
|
91
|
-
buildStatus: String
|
|
92
|
-
|
|
93
|
-
# list of component releases.
|
|
94
|
-
tags: [Tag]!
|
|
95
|
-
|
|
96
|
-
aspects: [Aspect]
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
type Aspect {
|
|
100
|
-
id: String!
|
|
101
|
-
icon: String
|
|
102
|
-
config: JSONObject
|
|
103
|
-
data: JSONObject
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
type InvalidComponent {
|
|
107
|
-
id: ComponentID!
|
|
108
|
-
errorName: String!
|
|
109
|
-
errorMessage: String!
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
type ComponentHost {
|
|
113
|
-
id: ID!
|
|
114
|
-
name: String!
|
|
115
|
-
|
|
116
|
-
# load a component.
|
|
117
|
-
get(id: String!, withState: Boolean): Component
|
|
118
|
-
|
|
119
|
-
# list components
|
|
120
|
-
list(offset: Int, limit: Int): [Component]!
|
|
121
|
-
|
|
122
|
-
# list invalid components and their errors
|
|
123
|
-
listInvalid: [InvalidComponent]!
|
|
124
|
-
|
|
125
|
-
# get component logs(snaps) by component id
|
|
126
|
-
snaps(id: String!): [LogEntry]!
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
type Query {
|
|
130
|
-
getHost(id: String): ComponentHost
|
|
131
|
-
}
|
|
132
|
-
`,
|
|
133
|
-
resolvers: {
|
|
134
|
-
JSONObject: GraphQLJSONObject,
|
|
135
|
-
Component: {
|
|
136
|
-
id: (component: Component) => component.id.toObject(),
|
|
137
|
-
displayName: (component: Component) => component.displayName,
|
|
138
|
-
fs: (component: Component) => {
|
|
139
|
-
return component.state.filesystem.files.map((file) => file.relative);
|
|
140
|
-
},
|
|
141
|
-
getFile: (component: Component, { path }: { path: string }) => {
|
|
142
|
-
const maybeFile = component.state.filesystem.files.find(
|
|
143
|
-
(file) => pathNormalizeToLinux(file.relative) === path
|
|
144
|
-
);
|
|
145
|
-
if (!maybeFile) return undefined;
|
|
146
|
-
return maybeFile.contents.toString('utf-8');
|
|
147
|
-
},
|
|
148
|
-
mainFile: (component: Component) => {
|
|
149
|
-
return component.state._consumer.mainFile;
|
|
150
|
-
},
|
|
151
|
-
headTag: (component: Component) => component.headTag?.toObject(),
|
|
152
|
-
latest: (component: Component) => component.latest,
|
|
153
|
-
tags: (component) => {
|
|
154
|
-
// graphql doesn't support map types
|
|
155
|
-
return component.tags.toArray().map((tag) => tag.toObject());
|
|
156
|
-
},
|
|
157
|
-
aspects: (component: Component) => {
|
|
158
|
-
const aspects = component.state.aspects.serialize();
|
|
159
|
-
return aspects;
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
ComponentHost: {
|
|
163
|
-
get: async (host: ComponentFactory, { id }: { id: string }) => {
|
|
164
|
-
try {
|
|
165
|
-
const componentId = await host.resolveComponentId(id);
|
|
166
|
-
const component = await host.get(componentId);
|
|
167
|
-
return component;
|
|
168
|
-
} catch (error: any) {
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
snaps: async (host: ComponentFactory, { id }: { id: string }) => {
|
|
173
|
-
const componentId = await host.resolveComponentId(id);
|
|
174
|
-
// return (await host.getLogs(componentId)).map(log => ({...log, id: log.hash}))
|
|
175
|
-
return host.getLogs(componentId);
|
|
176
|
-
},
|
|
177
|
-
list: async (host: ComponentFactory, filter?: { offset: number; limit: number }) => {
|
|
178
|
-
return host.list(filter);
|
|
179
|
-
},
|
|
180
|
-
listInvalid: async (host: ComponentFactory) => {
|
|
181
|
-
const invalidComps = await host.listInvalid();
|
|
182
|
-
return invalidComps.map(({ id, err }) => ({
|
|
183
|
-
id,
|
|
184
|
-
errorName: err.name,
|
|
185
|
-
errorMessage: err.message ? stripAnsi(err.message) : err.name,
|
|
186
|
-
}));
|
|
187
|
-
},
|
|
188
|
-
id: async (host: ComponentFactory) => {
|
|
189
|
-
return host.name;
|
|
190
|
-
},
|
|
191
|
-
name: async (host: ComponentFactory) => {
|
|
192
|
-
return host.name;
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
Query: {
|
|
196
|
-
getHost: (componentExt: ComponentMain, { id }: { id: string }) => {
|
|
197
|
-
return componentExtension.getHost(id);
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
}
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { CLIAspect, CLIMain, MainRuntime } from '@teambit/cli';
|
|
2
|
-
import { ExpressAspect, ExpressMain, Route } from '@teambit/express';
|
|
3
|
-
import { GraphqlAspect, GraphqlMain } from '@teambit/graphql';
|
|
4
|
-
import { Slot, SlotRegistry } from '@teambit/harmony';
|
|
5
|
-
import { ConfigAspect, Config } from '@teambit/config';
|
|
6
|
-
import { ComponentID } from '@teambit/component-id';
|
|
7
|
-
import { flatten, orderBy } from 'lodash';
|
|
8
|
-
import { ExtensionDataList } from '@teambit/legacy/dist/consumer/config';
|
|
9
|
-
import { ComponentFactory } from './component-factory';
|
|
10
|
-
import { ComponentAspect } from './component.aspect';
|
|
11
|
-
import { componentSchema } from './component.graphql';
|
|
12
|
-
import { ComponentRoute } from './component.route';
|
|
13
|
-
import { AspectList } from './aspect-list';
|
|
14
|
-
import { HostNotFound } from './exceptions';
|
|
15
|
-
import { AspectEntry } from './aspect-entry';
|
|
16
|
-
import {
|
|
17
|
-
ShowCmd,
|
|
18
|
-
ShowFragment,
|
|
19
|
-
NameFragment,
|
|
20
|
-
MainFileFragment,
|
|
21
|
-
IDFragment,
|
|
22
|
-
ScopeFragment,
|
|
23
|
-
FilesFragment,
|
|
24
|
-
ExtensionsFragment,
|
|
25
|
-
} from './show';
|
|
26
|
-
|
|
27
|
-
export type ComponentHostSlot = SlotRegistry<ComponentFactory>;
|
|
28
|
-
|
|
29
|
-
export type ShowFragmentSlot = SlotRegistry<ShowFragment[]>;
|
|
30
|
-
|
|
31
|
-
export class ComponentMain {
|
|
32
|
-
constructor(
|
|
33
|
-
/**
|
|
34
|
-
* slot for component hosts to register.
|
|
35
|
-
*/
|
|
36
|
-
private hostSlot: ComponentHostSlot,
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Express Extension
|
|
40
|
-
*/
|
|
41
|
-
private express: ExpressMain,
|
|
42
|
-
|
|
43
|
-
private showFragmentSlot: ShowFragmentSlot
|
|
44
|
-
) {}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* register a new component host.
|
|
48
|
-
*/
|
|
49
|
-
registerHost(host: ComponentFactory) {
|
|
50
|
-
this.hostSlot.register(host);
|
|
51
|
-
return this;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
createAspectList(legacyExtensionDataList: ExtensionDataList, scope?: string) {
|
|
55
|
-
return AspectList.fromLegacyExtensions(legacyExtensionDataList, scope);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
createAspectListFromEntries(entries: AspectEntry[]) {
|
|
59
|
-
return new AspectList(entries);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
registerRoute(routes: Route[]) {
|
|
63
|
-
const routeEntries = routes.map((route: Route) => {
|
|
64
|
-
return new ComponentRoute(route, this);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
this.express.register(flatten(routeEntries));
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* set the prior host.
|
|
73
|
-
*/
|
|
74
|
-
setHostPriority(id: string) {
|
|
75
|
-
const host = this.hostSlot.get(id);
|
|
76
|
-
if (!host) {
|
|
77
|
-
throw new HostNotFound(id);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this._priorHost = host;
|
|
81
|
-
return this;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* get component host by extension ID.
|
|
86
|
-
*/
|
|
87
|
-
getHost(id?: string): ComponentFactory {
|
|
88
|
-
if (id) {
|
|
89
|
-
const host = this.hostSlot.get(id);
|
|
90
|
-
if (!host) throw new HostNotFound(id);
|
|
91
|
-
return host;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return this.getPriorHost();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
getRoute(id: ComponentID, routeName: string) {
|
|
98
|
-
return `/api/${id.toString()}/~aspect/${routeName}`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* get the prior host.
|
|
103
|
-
*/
|
|
104
|
-
private getPriorHost() {
|
|
105
|
-
if (this._priorHost) return this._priorHost;
|
|
106
|
-
|
|
107
|
-
const hosts = this.hostSlot.values();
|
|
108
|
-
const priorityHost = hosts.find((host) => host.priority);
|
|
109
|
-
return priorityHost || hosts[0];
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
getShowFragments() {
|
|
113
|
-
const fragments = orderBy(flatten(this.showFragmentSlot.values()), ['weight', ['asc']]);
|
|
114
|
-
return fragments;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
isHost(name: string) {
|
|
118
|
-
return !!this.hostSlot.get(name);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* register a show fragment to display further information in the `bit show` command.
|
|
123
|
-
*/
|
|
124
|
-
registerShowFragments(showFragments: ShowFragment[]) {
|
|
125
|
-
this.showFragmentSlot.register(showFragments);
|
|
126
|
-
return this;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private _priorHost: ComponentFactory | undefined;
|
|
130
|
-
|
|
131
|
-
static slots = [Slot.withType<ComponentFactory>(), Slot.withType<Route[]>(), Slot.withType<ShowFragment[]>()];
|
|
132
|
-
|
|
133
|
-
static runtime = MainRuntime;
|
|
134
|
-
static dependencies = [GraphqlAspect, ExpressAspect, CLIAspect, ConfigAspect];
|
|
135
|
-
|
|
136
|
-
static async provider(
|
|
137
|
-
[graphql, express, cli, configAspect]: [GraphqlMain, ExpressMain, CLIMain, Config],
|
|
138
|
-
config,
|
|
139
|
-
[hostSlot, showFragmentSlot]: [ComponentHostSlot, ShowFragmentSlot]
|
|
140
|
-
) {
|
|
141
|
-
const componentExtension = new ComponentMain(hostSlot, express, showFragmentSlot);
|
|
142
|
-
|
|
143
|
-
if ((configAspect.workspaceConfig && !configAspect.workspaceConfig.isLegacy) || configAspect.type === 'scope') {
|
|
144
|
-
cli.unregister('show');
|
|
145
|
-
cli.register(new ShowCmd(componentExtension));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
componentExtension.registerShowFragments([
|
|
149
|
-
new NameFragment(),
|
|
150
|
-
new MainFileFragment(),
|
|
151
|
-
new IDFragment(),
|
|
152
|
-
new ScopeFragment(),
|
|
153
|
-
new FilesFragment(),
|
|
154
|
-
new ExtensionsFragment(),
|
|
155
|
-
]);
|
|
156
|
-
graphql.register(componentSchema(componentExtension));
|
|
157
|
-
|
|
158
|
-
return componentExtension;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
ComponentAspect.addRuntime(ComponentMain);
|
package/component.route.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { NextFunction, Request, Response, Route } from '@teambit/express';
|
|
2
|
-
|
|
3
|
-
import { ComponentMain } from './component.main.runtime';
|
|
4
|
-
|
|
5
|
-
export class ComponentRoute implements Route {
|
|
6
|
-
constructor(private registerRoute: Route, private componentExtension: ComponentMain) {}
|
|
7
|
-
dynamicRouteRegex = '/?[^/@]+/[^~]*';
|
|
8
|
-
readonly route = `/:componentId(${this.dynamicRouteRegex})/~aspect${this.registerRoute.route}`;
|
|
9
|
-
|
|
10
|
-
get componentMiddlewares() {
|
|
11
|
-
return [
|
|
12
|
-
async (req: Request, res: Response, next: NextFunction) => {
|
|
13
|
-
const { componentId } = req.params;
|
|
14
|
-
const host = this.componentExtension.getHost();
|
|
15
|
-
const compId = await host.resolveComponentId(componentId);
|
|
16
|
-
const component = await host.get(compId);
|
|
17
|
-
// @ts-ignore
|
|
18
|
-
req.component = component;
|
|
19
|
-
next();
|
|
20
|
-
},
|
|
21
|
-
];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
method = this.registerRoute.method;
|
|
25
|
-
middlewares = this.componentMiddlewares.concat(this.registerRoute.middlewares);
|
|
26
|
-
}
|
package/component.ts
DELETED
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import { AnyFS } from '@teambit/any-fs';
|
|
2
|
-
import { capitalize } from '@teambit/toolbox.string.capitalize';
|
|
3
|
-
import { SemVer } from 'semver';
|
|
4
|
-
import { ComponentID } from '@teambit/component-id';
|
|
5
|
-
import { BitError } from '@teambit/bit-error';
|
|
6
|
-
import { BuildStatus } from '@teambit/legacy/dist/constants';
|
|
7
|
-
|
|
8
|
-
import { ComponentFactory } from './component-factory';
|
|
9
|
-
import ComponentFS from './component-fs';
|
|
10
|
-
// import { NothingToSnap } from './exceptions';
|
|
11
|
-
import ComponentConfig from './config';
|
|
12
|
-
// eslint-disable-next-line import/no-cycle
|
|
13
|
-
import { Snap } from './snap';
|
|
14
|
-
import { State } from './state';
|
|
15
|
-
import { TagMap } from './tag-map';
|
|
16
|
-
import { Tag } from './tag';
|
|
17
|
-
import { CouldNotFindLatest } from './exceptions';
|
|
18
|
-
// import { Author } from './types';
|
|
19
|
-
|
|
20
|
-
type SnapsIterableOpts = {
|
|
21
|
-
firstParentOnly?: boolean;
|
|
22
|
-
stopFn?: (snap: Snap) => Promise<boolean>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type InvalidComponent = { id: ComponentID; err: Error };
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* in-memory representation of a component.
|
|
29
|
-
*/
|
|
30
|
-
export class Component {
|
|
31
|
-
constructor(
|
|
32
|
-
/**
|
|
33
|
-
* component ID represented by the `ComponentId` type.
|
|
34
|
-
*/
|
|
35
|
-
readonly id: ComponentID,
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* head version of the component. can be `null` for new components.
|
|
39
|
-
*/
|
|
40
|
-
readonly head: Snap | null = null,
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* state of the component.
|
|
44
|
-
*/
|
|
45
|
-
private _state: State,
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* tags of the component.
|
|
49
|
-
*/
|
|
50
|
-
readonly tags: TagMap = new TagMap(),
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* the component factory
|
|
54
|
-
*/
|
|
55
|
-
private factory: ComponentFactory
|
|
56
|
-
) {}
|
|
57
|
-
|
|
58
|
-
get state(): State {
|
|
59
|
-
return this._state;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
set state(state: State) {
|
|
63
|
-
this._state = state;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* component configuration which is later generated to a component `package.json` and `bit.json`.
|
|
68
|
-
*/
|
|
69
|
-
get config(): ComponentConfig {
|
|
70
|
-
return this.state.config;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* in-memory representation of the component current filesystem.
|
|
75
|
-
*/
|
|
76
|
-
get filesystem(): ComponentFS {
|
|
77
|
-
return this.state.filesystem;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* build status of the component
|
|
82
|
-
*/
|
|
83
|
-
get buildStatus(): BuildStatus {
|
|
84
|
-
return this._state._consumer.buildStatus;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
get headTag() {
|
|
88
|
-
if (!this.head) return undefined;
|
|
89
|
-
return this.tags.byHash(this.head.hash);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
get latest(): string | undefined {
|
|
93
|
-
if (!this.head) return undefined;
|
|
94
|
-
try {
|
|
95
|
-
return this.tags.getLatest();
|
|
96
|
-
} catch (err: any) {
|
|
97
|
-
if (err instanceof CouldNotFindLatest) {
|
|
98
|
-
return this.head.toString();
|
|
99
|
-
}
|
|
100
|
-
throw err;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
stringify(): string {
|
|
105
|
-
return JSON.stringify({
|
|
106
|
-
id: this.id,
|
|
107
|
-
head: this.head,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* record component changes in the `Scope`.
|
|
113
|
-
*/
|
|
114
|
-
// snap(author: Author, message = '') {
|
|
115
|
-
// if (!this.isModified()) throw new NothingToSnap();
|
|
116
|
-
// const snap = new Snap(this, author, message);
|
|
117
|
-
|
|
118
|
-
// return new Component(this.id, snap, snap.state);
|
|
119
|
-
// }
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* display name of the component.
|
|
123
|
-
*/
|
|
124
|
-
get displayName() {
|
|
125
|
-
const tokens = this.id.name.split('-').map((token) => capitalize(token));
|
|
126
|
-
return tokens.join(' ');
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* tag a component `Snap` with a semantic version. we follow SemVer specs as defined [here](https://semver.org/)).
|
|
131
|
-
*/
|
|
132
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
133
|
-
tag(version: SemVer) {
|
|
134
|
-
// const snap = this.snap();
|
|
135
|
-
// const tag = new Tag(version, snap);
|
|
136
|
-
// this.tags.set(tag);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* determines whether this component is modified in the workspace.
|
|
141
|
-
*/
|
|
142
|
-
isModified(): Promise<boolean> {
|
|
143
|
-
if (!this.head) return Promise.resolve(true);
|
|
144
|
-
return Promise.resolve(this.state.isModified);
|
|
145
|
-
// return Promise.resolve(this.state.hash !== this.head.hash);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* is component isOutdated
|
|
150
|
-
*/
|
|
151
|
-
isOutdated(): boolean {
|
|
152
|
-
if (!this.latest) return false;
|
|
153
|
-
const latestTag = this.tags.byVersion(this.latest);
|
|
154
|
-
if (!latestTag) return false;
|
|
155
|
-
if (this.head?.hash !== latestTag?.hash) return true;
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* determines whether this component is new.
|
|
161
|
-
*/
|
|
162
|
-
isNew(): Promise<boolean> {
|
|
163
|
-
return Promise.resolve(this.head === null);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// TODO: @david after snap we need to make sure to refactor here.
|
|
167
|
-
loadState(snapId: string): Promise<State> {
|
|
168
|
-
return this.factory.getState(this.id, snapId);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
loadSnap(snapId?: string): Promise<Snap> {
|
|
172
|
-
const snapToGet = snapId || this.head?.hash;
|
|
173
|
-
if (!snapToGet) {
|
|
174
|
-
throw new BitError('could not load snap for new components');
|
|
175
|
-
}
|
|
176
|
-
return this.factory.getSnap(this.id, snapToGet);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Get iterable which iterate over snap parents lazily
|
|
181
|
-
* @param snapId
|
|
182
|
-
* @param options
|
|
183
|
-
*/
|
|
184
|
-
snapsIterable(snapId?: string, options: SnapsIterableOpts = {}): AsyncIterable<Snap> {
|
|
185
|
-
const snapToStart = snapId || this.head?.hash;
|
|
186
|
-
let nextSnaps = [snapToStart];
|
|
187
|
-
let done;
|
|
188
|
-
if (!snapToStart) {
|
|
189
|
-
done = true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const iterator: AsyncIterator<Snap> = {
|
|
193
|
-
next: async () => {
|
|
194
|
-
if (done) {
|
|
195
|
-
return { value: undefined, done };
|
|
196
|
-
}
|
|
197
|
-
const currSnapId = nextSnaps.shift();
|
|
198
|
-
const snap = await this.loadSnap(currSnapId);
|
|
199
|
-
if (snap.parents && snap.parents.length) {
|
|
200
|
-
if (options.firstParentOnly) {
|
|
201
|
-
nextSnaps.push(snap.parents[0]);
|
|
202
|
-
} else {
|
|
203
|
-
nextSnaps = nextSnaps.concat(snap.parents);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
if (!nextSnaps.length) {
|
|
207
|
-
done = true;
|
|
208
|
-
} else if (options.stopFn) {
|
|
209
|
-
done = await options.stopFn(snap);
|
|
210
|
-
}
|
|
211
|
-
return { value: snap, done: undefined };
|
|
212
|
-
},
|
|
213
|
-
};
|
|
214
|
-
return {
|
|
215
|
-
[Symbol.asyncIterator]: () => iterator,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* traverse recursively from the provided snap (or head) upwards until it finds a tag
|
|
221
|
-
* @param snapToStartFrom
|
|
222
|
-
*/
|
|
223
|
-
async getClosestTag(snapToStartFrom?: string): Promise<Tag | undefined> {
|
|
224
|
-
const tagsHashMap = this.tags.getHashMap();
|
|
225
|
-
const stopFn = async (snap: Snap) => {
|
|
226
|
-
if (tagsHashMap.has(snap.hash)) {
|
|
227
|
-
return true;
|
|
228
|
-
}
|
|
229
|
-
return false;
|
|
230
|
-
};
|
|
231
|
-
const iterable = this.snapsIterable(snapToStartFrom, { firstParentOnly: true, stopFn });
|
|
232
|
-
const snaps: Snap[] = [];
|
|
233
|
-
for await (const snap of iterable) {
|
|
234
|
-
snaps.push(snap);
|
|
235
|
-
}
|
|
236
|
-
if (snaps.length) {
|
|
237
|
-
const hashOfLastSnap = snaps[snaps.length - 1].hash;
|
|
238
|
-
return tagsHashMap.get(hashOfLastSnap);
|
|
239
|
-
}
|
|
240
|
-
return undefined;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* checkout the component to a different version in its working tree.
|
|
245
|
-
*/
|
|
246
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
247
|
-
checkout(version: SemVer) {}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* examine difference between two components.
|
|
251
|
-
*/
|
|
252
|
-
// diff(other: Component): Difference {}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* merge two different components
|
|
256
|
-
*/
|
|
257
|
-
// merge(other: Component): Component {}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* write a component to a given file system.
|
|
261
|
-
* @param path root path to write the component
|
|
262
|
-
* @param fs instance of any fs to use.
|
|
263
|
-
*/
|
|
264
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
265
|
-
write(path: string, fs?: AnyFS) {}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
*
|
|
269
|
-
* Check if 2 components are equal
|
|
270
|
-
* @param {Component} component
|
|
271
|
-
* @returns {boolean}
|
|
272
|
-
* @memberof Component
|
|
273
|
-
*/
|
|
274
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
275
|
-
equals(component: Component): boolean {
|
|
276
|
-
return component.id.toString() === this.id.toString();
|
|
277
|
-
}
|
|
278
|
-
}
|