@teambit/harmony 0.2.11 → 0.3.0

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 (205) hide show
  1. package/aspect.ts +49 -0
  2. package/config/config.ts +36 -0
  3. package/config/index.ts +1 -0
  4. package/container.ts +22 -0
  5. package/dist/aspect.js +1 -0
  6. package/dist/aspect.js.map +1 -0
  7. package/dist/config/config.d.ts +1 -1
  8. package/dist/config/config.js +1 -0
  9. package/dist/config/config.js.map +1 -0
  10. package/dist/config/index.js +2 -0
  11. package/dist/config/index.js.map +1 -0
  12. package/dist/container.js +1 -0
  13. package/dist/container.js.map +1 -0
  14. package/dist/exceptions/extension-init-error.js +1 -0
  15. package/dist/exceptions/extension-init-error.js.map +1 -0
  16. package/dist/exceptions/extension-load-error.d.ts +1 -1
  17. package/dist/exceptions/extension-load-error.js +1 -0
  18. package/dist/exceptions/extension-load-error.js.map +1 -0
  19. package/dist/exceptions/extension-potential-circular.js +1 -0
  20. package/dist/exceptions/extension-potential-circular.js.map +1 -0
  21. package/dist/exceptions/harmony-already-running.js +1 -0
  22. package/dist/exceptions/harmony-already-running.js.map +1 -0
  23. package/dist/exceptions/harmony-error.js +1 -0
  24. package/dist/exceptions/harmony-error.js.map +1 -0
  25. package/dist/exceptions/hook-not-found.js +1 -0
  26. package/dist/exceptions/hook-not-found.js.map +1 -0
  27. package/dist/exceptions/index.js +7 -2
  28. package/dist/exceptions/index.js.map +1 -0
  29. package/dist/exceptions/runtime-not-defined.js +1 -1
  30. package/dist/exceptions/runtime-not-defined.js.map +1 -0
  31. package/dist/extension/any-extension.js +1 -0
  32. package/dist/extension/any-extension.js.map +1 -0
  33. package/dist/extension/decorator.d.ts +2 -2
  34. package/dist/extension/decorator.js +1 -0
  35. package/dist/extension/decorator.js.map +1 -0
  36. package/dist/extension/extension-manifest.js +1 -0
  37. package/dist/extension/extension-manifest.js.map +1 -0
  38. package/dist/extension/extension.d.ts +2 -2
  39. package/dist/extension/extension.js +1 -0
  40. package/dist/extension/extension.js.map +1 -0
  41. package/dist/extension/index.js +2 -0
  42. package/dist/extension/index.js.map +1 -0
  43. package/dist/extension-graph/extension-graph.d.ts +2 -2
  44. package/dist/extension-graph/extension-graph.js +5 -4
  45. package/dist/extension-graph/extension-graph.js.map +1 -0
  46. package/dist/extension-graph/from-extension.js +3 -2
  47. package/dist/extension-graph/from-extension.js.map +1 -0
  48. package/dist/extension-graph/index.js +6 -1
  49. package/dist/extension-graph/index.js.map +1 -0
  50. package/dist/factory/extension-factory.js +1 -0
  51. package/dist/factory/extension-factory.js.map +1 -0
  52. package/dist/factory/index.js +2 -0
  53. package/dist/factory/index.js.map +1 -0
  54. package/dist/fixtures/aspects/babel/babel.aspect.js +1 -0
  55. package/dist/fixtures/aspects/babel/babel.aspect.js.map +1 -0
  56. package/dist/fixtures/aspects/babel/babel.cli.js +1 -0
  57. package/dist/fixtures/aspects/babel/babel.cli.js.map +1 -0
  58. package/dist/fixtures/aspects/react/react.aspect.js +1 -0
  59. package/dist/fixtures/aspects/react/react.aspect.js.map +1 -0
  60. package/dist/fixtures/aspects/react/react.cli.js +2 -1
  61. package/dist/fixtures/aspects/react/react.cli.js.map +1 -0
  62. package/dist/fixtures/aspects/react/react.ui.js +1 -0
  63. package/dist/fixtures/aspects/react/react.ui.js.map +1 -0
  64. package/dist/fixtures/aspects/ui/ui.aspect.js +1 -0
  65. package/dist/fixtures/aspects/ui/ui.aspect.js.map +1 -0
  66. package/dist/fixtures/aspects/ui/ui.ui.js +1 -0
  67. package/dist/fixtures/aspects/ui/ui.ui.js.map +1 -0
  68. package/dist/fixtures/babel/babel.extension.d.ts +1 -1
  69. package/dist/fixtures/babel/babel.extension.js +8 -26
  70. package/dist/fixtures/babel/babel.extension.js.map +1 -0
  71. package/dist/fixtures/babel/index.js +1 -1
  72. package/dist/fixtures/babel/index.js.map +1 -0
  73. package/dist/fixtures/base-compiler/base-compiler.extension.js +5 -23
  74. package/dist/fixtures/base-compiler/base-compiler.extension.js.map +1 -0
  75. package/dist/fixtures/base-compiler/index.js +2 -0
  76. package/dist/fixtures/base-compiler/index.js.map +1 -0
  77. package/dist/fixtures/cli/cli.extension.js +5 -12
  78. package/dist/fixtures/cli/cli.extension.js.map +1 -0
  79. package/dist/fixtures/cli/command.js +1 -1
  80. package/dist/fixtures/cli/command.js.map +1 -0
  81. package/dist/fixtures/cli/index.js +2 -1
  82. package/dist/fixtures/cli/index.js.map +1 -0
  83. package/dist/fixtures/typescript/index.js +1 -1
  84. package/dist/fixtures/typescript/index.js.map +1 -0
  85. package/dist/fixtures/typescript/typescript.js +8 -22
  86. package/dist/fixtures/typescript/typescript.js.map +1 -0
  87. package/dist/harmony-config/config-reader.js +3 -2
  88. package/dist/harmony-config/config-reader.js.map +1 -0
  89. package/dist/harmony-config/exceptions/index.js +2 -0
  90. package/dist/harmony-config/exceptions/index.js.map +1 -0
  91. package/dist/harmony-config/exceptions/read-config-error.d.ts +1 -1
  92. package/dist/harmony-config/exceptions/read-config-error.js +1 -0
  93. package/dist/harmony-config/exceptions/read-config-error.js.map +1 -0
  94. package/dist/harmony-config/harmony-config.js +5 -4
  95. package/dist/harmony-config/harmony-config.js.map +1 -0
  96. package/dist/harmony-config/index.js +2 -0
  97. package/dist/harmony-config/index.js.map +1 -0
  98. package/dist/harmony-config/locator.js +1 -1
  99. package/dist/harmony-config/locator.js.map +1 -0
  100. package/dist/harmony.docs.mdx +249 -0
  101. package/dist/harmony.js +3 -2
  102. package/dist/harmony.js.map +1 -0
  103. package/dist/{factory/extension-factory.spec.d.ts → harmony.spec.old.d.ts} +0 -0
  104. package/dist/{harmony.spec.js → harmony.spec.old.js} +12 -23
  105. package/dist/harmony.spec.old.js.map +1 -0
  106. package/dist/index.js +6 -1
  107. package/dist/index.js.map +1 -0
  108. package/dist/readme.md +80 -0
  109. package/dist/runtimes/exceptions/index.js +2 -0
  110. package/dist/runtimes/exceptions/index.js.map +1 -0
  111. package/dist/runtimes/exceptions/runtime-module-error.d.ts +1 -1
  112. package/dist/runtimes/exceptions/runtime-module-error.js +1 -0
  113. package/dist/runtimes/exceptions/runtime-module-error.js.map +1 -0
  114. package/dist/runtimes/exceptions/runtime-not-defined.js +1 -0
  115. package/dist/runtimes/exceptions/runtime-not-defined.js.map +1 -0
  116. package/dist/runtimes/index.js +2 -0
  117. package/dist/runtimes/index.js.map +1 -0
  118. package/dist/runtimes/runtime-definition.js +1 -0
  119. package/dist/runtimes/runtime-definition.js.map +1 -0
  120. package/dist/runtimes/runtime-manifest.js +1 -0
  121. package/dist/runtimes/runtime-manifest.js.map +1 -0
  122. package/dist/runtimes/runtimes.js +1 -0
  123. package/dist/runtimes/runtimes.js.map +1 -0
  124. package/dist/slots/index.js +2 -0
  125. package/dist/slots/index.js.map +1 -0
  126. package/dist/slots/registry.js +1 -0
  127. package/dist/slots/registry.js.map +1 -0
  128. package/dist/slots/slot.js +1 -0
  129. package/dist/slots/slot.js.map +1 -0
  130. package/dist/types.js +1 -0
  131. package/dist/types.js.map +1 -0
  132. package/dist/utils/async-for-each.js +1 -0
  133. package/dist/utils/async-for-each.js.map +1 -0
  134. package/dist/utils/index.js +2 -0
  135. package/dist/utils/index.js.map +1 -0
  136. package/exceptions/extension-init-error.ts +1 -0
  137. package/exceptions/extension-load-error.ts +28 -0
  138. package/exceptions/extension-potential-circular.ts +24 -0
  139. package/exceptions/harmony-already-running.ts +1 -0
  140. package/exceptions/harmony-error.ts +1 -0
  141. package/exceptions/hook-not-found.ts +1 -0
  142. package/exceptions/index.ts +5 -0
  143. package/{dist/extension-graph/extension-graph.spec.d.ts → exceptions/runtime-not-defined.ts} +0 -0
  144. package/extension/any-extension.ts +8 -0
  145. package/extension/decorator.ts +126 -0
  146. package/extension/extension-manifest.ts +51 -0
  147. package/extension/extension.ts +138 -0
  148. package/extension/index.ts +3 -0
  149. package/extension-graph/extension-graph.ts +151 -0
  150. package/extension-graph/from-extension.ts +72 -0
  151. package/extension-graph/index.ts +1 -0
  152. package/factory/extension-factory.ts +8 -0
  153. package/factory/index.ts +1 -0
  154. package/fixtures/aspects/babel/babel.aspect.ts +14 -0
  155. package/fixtures/aspects/babel/babel.cli.ts +16 -0
  156. package/fixtures/aspects/react/react.aspect.ts +22 -0
  157. package/fixtures/aspects/react/react.cli.ts +26 -0
  158. package/fixtures/aspects/react/react.ui.ts +16 -0
  159. package/fixtures/aspects/ui/ui.aspect.ts +13 -0
  160. package/fixtures/aspects/ui/ui.ui.ts +11 -0
  161. package/fixtures/babel/babel.extension.ts +20 -0
  162. package/{dist/extension/extension.spec.d.ts → fixtures/babel/index.ts} +0 -0
  163. package/fixtures/base-compiler/base-compiler.extension.ts +31 -0
  164. package/fixtures/base-compiler/index.ts +1 -0
  165. package/fixtures/cli/cli.extension.ts +25 -0
  166. package/fixtures/cli/command.ts +6 -0
  167. package/fixtures/cli/index.ts +1 -0
  168. package/fixtures/typescript/index.ts +0 -0
  169. package/fixtures/typescript/typescript.ts +20 -0
  170. package/harmony-config/config-reader.ts +17 -0
  171. package/harmony-config/exceptions/index.ts +1 -0
  172. package/harmony-config/exceptions/read-config-error.ts +9 -0
  173. package/harmony-config/harmony-config.ts +49 -0
  174. package/harmony-config/index.ts +1 -0
  175. package/harmony-config/locator.ts +0 -0
  176. package/harmony.docs.mdx +249 -0
  177. package/harmony.spec.old.ts +177 -0
  178. package/harmony.ts +146 -0
  179. package/index.ts +10 -0
  180. package/package-tar/teambit-harmony-0.3.0.tgz +0 -0
  181. package/package.json +41 -28
  182. package/preview-1649080456374.js +1 -0
  183. package/readme.md +58 -137
  184. package/runtimes/exceptions/index.ts +2 -0
  185. package/runtimes/exceptions/runtime-module-error.ts +9 -0
  186. package/runtimes/exceptions/runtime-not-defined.ts +5 -0
  187. package/runtimes/index.ts +3 -0
  188. package/runtimes/runtime-definition.ts +32 -0
  189. package/runtimes/runtime-manifest.ts +12 -0
  190. package/runtimes/runtimes.ts +34 -0
  191. package/slots/index.ts +2 -0
  192. package/slots/registry.ts +36 -0
  193. package/slots/slot.ts +11 -0
  194. package/tsconfig.json +26 -0
  195. package/types/asset.d.ts +29 -0
  196. package/types/style.d.ts +42 -0
  197. package/types.ts +7 -0
  198. package/utils/async-for-each.ts +10 -0
  199. package/utils/index.ts +1 -0
  200. package/dist/extension/extension.spec.js +0 -1
  201. package/dist/extension-graph/extension-graph.spec.js +0 -1
  202. package/dist/factory/extension-factory.spec.js +0 -6
  203. package/dist/harmony-config/harmony-config.spec.d.ts +0 -1
  204. package/dist/harmony-config/harmony-config.spec.js +0 -8
  205. package/dist/harmony.spec.d.ts +0 -1
@@ -0,0 +1,138 @@
1
+ import { ProviderFn } from '../types';
2
+ import { Harmony } from '../harmony';
3
+ import { ExtensionManifest } from './extension-manifest';
4
+ import { ExtensionInstantiationException } from '../exceptions/extension-init-error';
5
+ import { RuntimeDefinition } from '../runtimes';
6
+
7
+ export type ExtensionProps = {
8
+ name: string;
9
+ // TODO: changes from any to something meaningful
10
+ dependencies: any[];
11
+ provider: ProviderFn;
12
+ };
13
+
14
+ /**
15
+ * harmony's extension definition. this can be used to define and extend `Harmony` applications.
16
+ */
17
+ export class Extension {
18
+ constructor(
19
+ /**
20
+ * manifest of the extension.
21
+ */
22
+ readonly manifest: ExtensionManifest
23
+ ) {}
24
+
25
+ private _instance = null;
26
+
27
+ private _loaded = false;
28
+
29
+ /**
30
+ * returns the instance of the extension
31
+ */
32
+ get instance() {
33
+ return this._instance;
34
+ }
35
+
36
+ get name() {
37
+ const metadata = Reflect.getMetadata('harmony:name', this.manifest);
38
+ return metadata || this.manifest.id || this.manifest.name;
39
+ }
40
+
41
+ get id() {
42
+ return this.name;
43
+ }
44
+
45
+ get dependencies(): Extension[] {
46
+ const metadata = Reflect.getMetadata('harmony:dependencies', this.manifest);
47
+ return metadata || this.manifest.dependencies || [];
48
+ }
49
+
50
+ get provider() {
51
+ const metadata = Reflect.getMetadata('harmony:provider', this.manifest);
52
+ return metadata || this.manifest.provider;
53
+ }
54
+
55
+ get files() {
56
+ return this.manifest.files;
57
+ }
58
+
59
+ /**
60
+ * returns an indication of the extension already loaded (the provider run)
61
+ * We don't rely on the instance since an extension provider might return null
62
+ */
63
+ get loaded() {
64
+ return this._loaded;
65
+ }
66
+
67
+ toString(): string {
68
+ return JSON.stringify(this.name);
69
+ }
70
+
71
+ private buildSlotRegistries(slots: ((registerFn: () => void) => any)[], context: Harmony) {
72
+ return slots.map((slot) => {
73
+ return slot(() => {
74
+ return context.current;
75
+ });
76
+ });
77
+ }
78
+
79
+ get declareRuntime() {
80
+ return this.manifest.declareRuntime;
81
+ }
82
+
83
+ getRuntime(runtime: RuntimeDefinition) {
84
+ return this.manifest.getRuntime(runtime);
85
+ }
86
+
87
+ getSlots(extensionRuntime: any) {
88
+ if (extensionRuntime.slots && extensionRuntime.slots.length) {
89
+ return extensionRuntime.slots;
90
+ }
91
+
92
+ return this.manifest.slots || [];
93
+ }
94
+
95
+ getConfig(context: Harmony, extensionRuntime: any) {
96
+ const defaultConfig = extensionRuntime.defaultConfig || this.manifest.defaultConfig || {};
97
+ const config = context.config.get(this.name) || {};
98
+ return Object.assign({}, defaultConfig, config);
99
+ }
100
+
101
+ /**
102
+ * initiate Harmony in run-time.
103
+ */
104
+ async __run(dependencies: any[], context: Harmony, runtime: RuntimeDefinition) {
105
+ const name = this.name;
106
+ context.initExtension(name);
107
+ const extensionRuntime = this.getRuntime(runtime);
108
+
109
+ if (!extensionRuntime) {
110
+ return undefined;
111
+ }
112
+
113
+ // @ts-ignore
114
+ const registries = this.buildSlotRegistries(this.getSlots(extensionRuntime), context);
115
+ const config = this.getConfig(context, extensionRuntime);
116
+
117
+ if (!this.loaded) {
118
+ if (extensionRuntime.provider) this._instance = await extensionRuntime.provider(dependencies, config, registries, context);
119
+ else {
120
+ try {
121
+ // @ts-ignore
122
+ this._instance = new extensionRuntime.manifest(...dependencies);
123
+ } catch(err) {
124
+ throw new ExtensionInstantiationException(err.toString());
125
+ }
126
+ };
127
+ // @ts-ignore adding the extension ID to the instance.
128
+ // this._instance.id = this.manifest.name;
129
+ // @ts-ignore adding the extension ID to the instance.
130
+ // this._instance.config = config;
131
+ this._loaded = true;
132
+ return this._instance;
133
+ }
134
+
135
+ context.endExtension();
136
+ return Promise.resolve(this.instance);
137
+ }
138
+ }
@@ -0,0 +1,3 @@
1
+ export { Extension, ExtensionProps } from './extension';
2
+ export { ExtensionManifest } from './extension-manifest';
3
+ export { ExtensionDecorator, register, hook, HookRegistry, provider, createHook } from './decorator';
@@ -0,0 +1,151 @@
1
+ import { Graph } from 'cleargraph';
2
+ import { fromExtension, fromExtensions } from './from-extension';
3
+ import { ExtensionManifest } from '../extension';
4
+ import { Extension } from '../extension';
5
+ import { RuntimeDefinition, Runtimes } from '../runtimes';
6
+ import { RequireFn } from '../harmony';
7
+
8
+ function getName(manifest: any) {
9
+ return Reflect.getMetadata('harmony:name', manifest) || manifest.id || manifest.name;
10
+ }
11
+
12
+ export type Edge = {
13
+ type: string,
14
+ runtime?: string
15
+ };
16
+
17
+ export default class DependencyGraph extends Graph<Extension, Edge> {
18
+ private cache = new Map<string, Extension>();
19
+
20
+ getRuntimeDependencies(aspect: Extension, runtime: RuntimeDefinition): Extension[] {
21
+ const dependencies = this.successors(aspect.name);
22
+ const runtimeDeps = this.successors(aspect.name, (edge) => {
23
+ if (!edge.runtime) return false;
24
+ return edge.runtime === runtime.name;
25
+ });
26
+ const runtimeManifest = aspect.getRuntime(runtime);
27
+ if (!runtimeManifest) return Array.from(dependencies.values());
28
+
29
+ if (runtimeDeps && runtimeDeps.size) return this.sortDeps(runtimeManifest.dependencies, Array.from(runtimeDeps.values()));
30
+ return this.sortDeps(runtimeManifest.dependencies, Array.from(dependencies.values()));
31
+ }
32
+
33
+ private sortDeps(originalDependencies: any[], targetDependencies: any[]) {
34
+ return targetDependencies.sort((a, b) => {
35
+ return originalDependencies.findIndex(item => item.id === a.id) - originalDependencies.findIndex(item => item.id === b.id);
36
+ });
37
+ }
38
+
39
+ byExecutionOrder() {
40
+ return this.toposort(true);
41
+ }
42
+
43
+ private async enrichRuntimeExtension(id: string, aspect: Extension, runtime: RuntimeDefinition, runtimes: Runtimes, requireFn: RequireFn) {
44
+ await requireFn(aspect, runtime);
45
+ const runtimeManifest = aspect.getRuntime(runtime)
46
+ if (!runtimeManifest) return;
47
+ const deps = runtimeManifest.dependencies;
48
+ if (!deps) return;
49
+ const promises = deps.map(async (dep: any) => {
50
+ if (!this.hasNode(dep.id)) {
51
+ this.add(dep);
52
+ if (dep.declareRuntime) {
53
+ runtimes.add(dep.declareRuntime);
54
+ }
55
+
56
+ await requireFn(this.get(dep.id), runtime);
57
+ await this.enrichRuntimeExtension(dep.id, this.get(dep.id), runtime, runtimes, requireFn);
58
+ }
59
+
60
+ this.setEdge(id, dep.id, {
61
+ runtime: runtime.name,
62
+ type: 'runtime-dependency'
63
+ });
64
+ });
65
+
66
+ return Promise.all(promises);
67
+ }
68
+
69
+ async enrichRuntime(runtime: RuntimeDefinition, runtimes: Runtimes, requireFn: RequireFn) {
70
+ const promises = Array.from(this.nodes.entries()).map(async ([id, aspect]) => {
71
+ return this.enrichRuntimeExtension(id, aspect, runtime, runtimes, requireFn);
72
+ });
73
+
74
+ return Promise.all(promises);
75
+ }
76
+
77
+ add(manifest: ExtensionManifest) {
78
+ const { vertices, edges } = fromExtension(manifest);
79
+ this.setNodes(vertices);
80
+ this.setEdges(edges);
81
+
82
+ return this;
83
+ }
84
+
85
+ load(extensions: ExtensionManifest[]) {
86
+ const newExtensions = extensions.filter((extension) => {
87
+ if (!extension.id) return false;
88
+ return !this.get(extension.id);
89
+ });
90
+ const { vertices, edges } = fromExtensions(newExtensions);
91
+ // Only set new vertices
92
+ this.setNodes(vertices, false); // false because we don't want to override already-loaded extensions
93
+ this.setEdges(edges);
94
+
95
+ return this;
96
+ }
97
+
98
+ // :TODO refactor this asap
99
+ getExtension(manifest: ExtensionManifest) {
100
+ const id = getName(manifest);
101
+ const cachedVertex = this.cache.get(id);
102
+ if (cachedVertex) return cachedVertex;
103
+
104
+ const res = this.node(id);
105
+ if (res) {
106
+ this.cache.set(res.name, res);
107
+ return res;
108
+ }
109
+
110
+ return null;
111
+ }
112
+
113
+ get extensions(): ExtensionManifest[] {
114
+ return Array.from(this.nodes.values());
115
+ }
116
+
117
+ get aspects() {
118
+ return this.extensions;
119
+ }
120
+
121
+ get(id: string): any {
122
+ const cachedVertex = this.cache.get(id);
123
+ if (cachedVertex) return cachedVertex;
124
+
125
+ const res = this.node(id);
126
+ if (res) {
127
+ this.cache.set(res.name, res);
128
+ return res;
129
+ }
130
+
131
+ return null;
132
+ }
133
+
134
+ /**
135
+ * build Harmony from a single extension.
136
+ */
137
+ static fromRoot(extension: ExtensionManifest) {
138
+ const { vertices, edges } = fromExtension(extension);
139
+
140
+ return new DependencyGraph(vertices, edges);
141
+ }
142
+
143
+ /**
144
+ * build Harmony from set of extensions
145
+ */
146
+ static from(extensions: ExtensionManifest[]) {
147
+ const { vertices, edges } = fromExtensions(extensions);
148
+
149
+ return new DependencyGraph(vertices, edges);
150
+ }
151
+ }
@@ -0,0 +1,72 @@
1
+ import { ExtensionManifest } from '../extension';
2
+ import { extensionFactory } from '../factory';
3
+ import ExtensionPotentialCircular from '../exceptions/extension-potential-circular';
4
+ import { Extension } from '../extension';
5
+ import { Edge } from './extension-graph';
6
+
7
+ function getName(manifest: any) {
8
+ return Reflect.getMetadata('harmony:name', manifest) || manifest.id || manifest.name;
9
+ }
10
+
11
+ /**
12
+ * build vertices and edges from the given extension
13
+ */
14
+ export function fromExtension(extension: ExtensionManifest) {
15
+ const vertices: { [id: string]: Extension } = {};
16
+ let edges: { sourceId: string; targetId: string; edge: Edge }[] = [];
17
+
18
+ function iterate(root: ExtensionManifest) {
19
+ const id = getName(root);
20
+ if (vertices[id]) return;
21
+
22
+ const instance = extensionFactory(root);
23
+ const validDeps = instance.dependencies.filter(dep => dep).map(dep => extensionFactory(dep));
24
+ if (instance.dependencies.length > validDeps.length) {
25
+ throw new ExtensionPotentialCircular(instance, validDeps);
26
+ }
27
+ vertices[id] = instance;
28
+ const newEdges = validDeps.map(dep => {
29
+ return {
30
+ sourceId: id,
31
+ targetId: dep.name,
32
+ edge: {
33
+ type: 'dependency'
34
+ }
35
+ };
36
+ });
37
+
38
+ edges = edges.concat(newEdges);
39
+
40
+ // @ts-ignore
41
+ instance.dependencies.forEach(dep => iterate(dep));
42
+ }
43
+
44
+ iterate(extension);
45
+
46
+ let vertexArray: { id: string; node: Extension }[] = [];
47
+ for (let [key, value] of Object.entries(vertices)) {
48
+ vertexArray.push({ id: key, node: value });
49
+ }
50
+
51
+ return {
52
+ vertices: vertexArray,
53
+ edges
54
+ };
55
+ }
56
+
57
+ /**
58
+ * build vertices and edges from the given list of extensions
59
+ */
60
+ export function fromExtensions(extensions: ExtensionManifest[]) {
61
+ const perExtension = extensions.map(ext => fromExtension(ext));
62
+
63
+ return perExtension.reduce(
64
+ (acc, subgraph) => {
65
+ acc.edges = acc.edges.concat(subgraph.edges);
66
+ acc.vertices = acc.vertices.concat(subgraph.vertices);
67
+
68
+ return acc;
69
+ },
70
+ { vertices: [], edges: [] }
71
+ );
72
+ }
@@ -0,0 +1 @@
1
+ export { default as DependencyGraph } from './extension-graph';
@@ -0,0 +1,8 @@
1
+ import { ExtensionManifest } from '../extension/extension-manifest';
2
+ import { Extension } from '../extension/extension';
3
+
4
+ export function extensionFactory(manifest: ExtensionManifest) {
5
+ // to allow the use of `provide` as an alias to `provider` in ExtensionManifest
6
+ if (manifest.provide) manifest.provider = manifest.provide;
7
+ return new Extension(manifest);
8
+ }
@@ -0,0 +1 @@
1
+ export { extensionFactory } from './extension-factory';
@@ -0,0 +1,14 @@
1
+ import type { BabelCLI } from './babel.cli';
2
+ import { Aspect } from '../../../aspect';
3
+
4
+ export type { BabelCLI };
5
+
6
+ export const BabelAspect = Aspect.create({
7
+ id: '@teambit/babel',
8
+ dependencies: [],
9
+ files: [
10
+ require.resolve('./babel.cli')
11
+ ]
12
+ });
13
+
14
+ export default BabelAspect;
@@ -0,0 +1,16 @@
1
+ import { BabelAspect } from './babel.aspect';
2
+ import { CLIRuntime } from '../react/react.aspect';
3
+
4
+ export class BabelCLI {
5
+ compile() {
6
+ console.log('compiled!');
7
+ }
8
+
9
+ static runtime = CLIRuntime;
10
+
11
+ static async provider() {
12
+ return new BabelCLI();
13
+ }
14
+ }
15
+
16
+ BabelAspect.addRuntime(BabelCLI);
@@ -0,0 +1,22 @@
1
+ import { BabelAspect } from '../babel/babel.aspect';
2
+ import { Aspect } from '../../../aspect';
3
+ import { Slot } from '../../../slots';
4
+ import { RuntimeDefinition } from '../../../runtimes';
5
+ import { UIAspect } from '../ui/ui.aspect';
6
+
7
+ export type Config = {};
8
+
9
+ export const CLIRuntime = RuntimeDefinition.create({ name: 'cli' })
10
+
11
+ export const ReactAspect = Aspect.create({
12
+ id: '@teambit/react',
13
+ dependencies: [UIAspect],
14
+ defaultConfig: {},
15
+ declareRuntime: CLIRuntime,
16
+ files: [
17
+ require.resolve('./react.cli'),
18
+ require.resolve('./react.ui')
19
+ ]
20
+ });
21
+
22
+ export default ReactAspect;
@@ -0,0 +1,26 @@
1
+ import ReactAspect, { CLIRuntime } from './react.aspect';
2
+ import BabelAspect, { BabelCLI } from '../babel/babel.aspect';
3
+ import { Slot, SlotRegistry } from '../../../slots';
4
+
5
+ export class ReactCLI {
6
+ constructor(
7
+ private babel: BabelCLI
8
+ ) {}
9
+
10
+ static runtime = CLIRuntime;
11
+
12
+ hello() {
13
+ return this.babel.compile();
14
+ }
15
+
16
+ static dependencies = [BabelAspect];
17
+
18
+ static slots = [Slot.withType<string>()];
19
+
20
+ static async provider([babelCli]: [BabelCLI], config: {}, [stringSlot]: [SlotRegistry<string>]) {
21
+ stringSlot.register('hi there');
22
+ return new ReactCLI(babelCli);
23
+ }
24
+ }
25
+
26
+ ReactAspect.addRuntime(ReactCLI);
@@ -0,0 +1,16 @@
1
+ import ReactAspect from './react.aspect';
2
+ import { UIRuntime } from '../ui/ui.aspect';
3
+
4
+ export class ReactUI {
5
+ static runtime = UIRuntime;
6
+
7
+ render() {
8
+ return 'rendering something!';
9
+ }
10
+
11
+ static async provider() {
12
+ return new ReactUI();
13
+ }
14
+ }
15
+
16
+ ReactAspect.addRuntime(ReactUI);
@@ -0,0 +1,13 @@
1
+ import { Aspect } from '../../../aspect';
2
+ import { RuntimeDefinition } from '../../../runtimes';
3
+
4
+ export const UIRuntime = RuntimeDefinition.create({ name: 'ui' });
5
+
6
+ export const UIAspect = Aspect.create({
7
+ id: '@teambit/ui',
8
+ dependencies: [],
9
+ declareRuntime: UIRuntime,
10
+ files: [
11
+ require.resolve('./ui.ui')
12
+ ]
13
+ });
@@ -0,0 +1,11 @@
1
+ import { UIAspect, UIRuntime } from './ui.aspect';
2
+
3
+ export class UiUI {
4
+ static runtime = UIRuntime;
5
+
6
+ static async provider() {
7
+ return new UiUI();
8
+ }
9
+ }
10
+
11
+ UIAspect.addRuntime(UiUI);
@@ -0,0 +1,20 @@
1
+ import { Extension, provider } from '../..';
2
+ import { BaseCompiler } from '../base-compiler';
3
+
4
+ class Mock {
5
+
6
+ }
7
+
8
+ // @Extension({
9
+ // dependencies: [BaseCompiler]
10
+ // })
11
+ export class Babel {
12
+ constructor(
13
+ private mock?: Mock
14
+ ) {}
15
+
16
+ // @provider()
17
+ async provide([baseCompiler]: [BaseCompiler]) {
18
+ return new Babel();
19
+ }
20
+ }
@@ -0,0 +1,31 @@
1
+ import { Extension } from "../..";
2
+ import { CLI, Command } from '../cli';
3
+
4
+ // @Extension()
5
+ export class BaseCompiler {
6
+ constructor(
7
+ private cli: CLI
8
+ ) {}
9
+
10
+ // @Config()
11
+ config() {
12
+ return {
13
+ cjs: 'blue/green'
14
+ };
15
+ }
16
+
17
+ // @Command
18
+ main() {
19
+ return {
20
+ synopsis: 'compile <id>',
21
+ report: () => {
22
+ return 'compiled in 0.1 secs';
23
+ }
24
+ };
25
+ }
26
+
27
+ compile() {
28
+ this.cli.run();
29
+ return 'hello world';
30
+ }
31
+ }
@@ -0,0 +1 @@
1
+ export { BaseCompiler } from './base-compiler.extension';
@@ -0,0 +1,25 @@
1
+ import { Extension, createHook } from '../..';
2
+ import { HookRegistry, hook } from '../..';
3
+
4
+ /**
5
+ * hook for registering new CLI commands.
6
+ */
7
+ export const Command = createHook();
8
+
9
+ export type CommandDefinition = {
10
+ synopsis: string,
11
+ report: string
12
+ };
13
+
14
+ // @Extension()
15
+ export class CLI {
16
+ /**
17
+ * registry for the commands hook
18
+ */
19
+ private commands = HookRegistry.of<CommandDefinition>(Command);
20
+
21
+ run() {
22
+ const commands = this.commands.list();
23
+ return commands;
24
+ }
25
+ }
@@ -0,0 +1,6 @@
1
+ interface Command {
2
+ command(): {
3
+ synopsis: string,
4
+ run: () => Promise<any>
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ export * from './cli.extension';
File without changes
@@ -0,0 +1,20 @@
1
+ import { Extension } from '../..';
2
+ import { BaseCompiler } from '../base-compiler';
3
+
4
+ // @Extension({
5
+ // name: 'typescript',
6
+ // dependencies: [BaseCompiler]
7
+ // })
8
+ export class TypeScript {
9
+ constructor(
10
+ private compiler: string
11
+ ) {}
12
+
13
+ compile() {
14
+ return this.compiler;
15
+ }
16
+
17
+ static async provider([baseCompiler]: [BaseCompiler]) {
18
+ return new TypeScript(baseCompiler.compile());
19
+ }
20
+ }
@@ -0,0 +1,17 @@
1
+ import { parse } from 'comment-json';
2
+ import { readFileSync, existsSync } from 'fs-extra';
3
+ import { ReadConfigError } from './exceptions/read-config-error';
4
+
5
+ export function readConfigFile(path: string, mustExist = true) {
6
+ if (!mustExist && !existsSync(path)) {
7
+ return {};
8
+ }
9
+
10
+ try {
11
+ const json = parse(readFileSync(path, 'utf8'));
12
+ delete json.$schema;
13
+ return json;
14
+ } catch (err) {
15
+ throw new ReadConfigError(path, err);
16
+ }
17
+ }
@@ -0,0 +1 @@
1
+ export { ReadConfigError } from './read-config-error';
@@ -0,0 +1,9 @@
1
+ export class ReadConfigError extends Error {
2
+ constructor(path: string, private err: Error) {
3
+ super(`failed to read config from path: ${path}`);
4
+ }
5
+
6
+ get stack() {
7
+ return this.err.stack;
8
+ }
9
+ }