@teambit/harmony 0.0.0-19ea14143ef7d5f4e4daa6e8ac8a8c97c9d683d5

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 (248) hide show
  1. package/aspect.ts +52 -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.d.ts +27 -0
  6. package/dist/aspect.js +33 -0
  7. package/dist/aspect.js.map +1 -0
  8. package/dist/config/config.d.ts +22 -0
  9. package/dist/config/config.js +37 -0
  10. package/dist/config/config.js.map +1 -0
  11. package/dist/config/index.d.ts +1 -0
  12. package/dist/config/index.js +6 -0
  13. package/dist/config/index.js.map +1 -0
  14. package/dist/container.d.ts +8 -0
  15. package/dist/container.js +22 -0
  16. package/dist/container.js.map +1 -0
  17. package/dist/exceptions/extension-init-error.d.ts +2 -0
  18. package/dist/exceptions/extension-init-error.js +7 -0
  19. package/dist/exceptions/extension-init-error.js.map +1 -0
  20. package/dist/exceptions/extension-load-error.d.ts +29 -0
  21. package/dist/exceptions/extension-load-error.js +29 -0
  22. package/dist/exceptions/extension-load-error.js.map +1 -0
  23. package/dist/exceptions/extension-potential-circular.d.ts +22 -0
  24. package/dist/exceptions/extension-potential-circular.js +25 -0
  25. package/dist/exceptions/extension-potential-circular.js.map +1 -0
  26. package/dist/exceptions/harmony-already-running.d.ts +2 -0
  27. package/dist/exceptions/harmony-already-running.js +7 -0
  28. package/dist/exceptions/harmony-already-running.js.map +1 -0
  29. package/dist/exceptions/harmony-error.d.ts +2 -0
  30. package/dist/exceptions/harmony-error.js +7 -0
  31. package/dist/exceptions/harmony-error.js.map +1 -0
  32. package/dist/exceptions/hook-not-found.d.ts +2 -0
  33. package/dist/exceptions/hook-not-found.js +7 -0
  34. package/dist/exceptions/hook-not-found.js.map +1 -0
  35. package/dist/exceptions/index.d.ts +5 -0
  36. package/dist/exceptions/index.js +17 -0
  37. package/dist/exceptions/index.js.map +1 -0
  38. package/dist/exceptions/runtime-not-defined.d.ts +0 -0
  39. package/dist/exceptions/runtime-not-defined.js +1 -0
  40. package/dist/exceptions/runtime-not-defined.js.map +1 -0
  41. package/dist/extension/any-extension.d.ts +5 -0
  42. package/dist/extension/any-extension.js +8 -0
  43. package/dist/extension/any-extension.js.map +1 -0
  44. package/dist/extension/decorator.d.ts +27 -0
  45. package/dist/extension/decorator.js +109 -0
  46. package/dist/extension/decorator.js.map +1 -0
  47. package/dist/extension/extension-manifest.d.ts +41 -0
  48. package/dist/extension/extension-manifest.js +3 -0
  49. package/dist/extension/extension-manifest.js.map +1 -0
  50. package/dist/extension/extension.d.ts +50 -0
  51. package/dist/extension/extension.js +128 -0
  52. package/dist/extension/extension.js.map +1 -0
  53. package/dist/extension/index.d.ts +3 -0
  54. package/dist/extension/index.js +13 -0
  55. package/dist/extension/index.js.map +1 -0
  56. package/dist/extension-graph/extension-graph.d.ts +34 -0
  57. package/dist/extension-graph/extension-graph.js +152 -0
  58. package/dist/extension-graph/extension-graph.js.map +1 -0
  59. package/dist/extension-graph/from-extension.d.ts +31 -0
  60. package/dist/extension-graph/from-extension.js +63 -0
  61. package/dist/extension-graph/from-extension.js.map +1 -0
  62. package/dist/extension-graph/index.d.ts +1 -0
  63. package/dist/extension-graph/index.js +9 -0
  64. package/dist/extension-graph/index.js.map +1 -0
  65. package/dist/factory/extension-factory.d.ts +3 -0
  66. package/dist/factory/extension-factory.js +11 -0
  67. package/dist/factory/extension-factory.js.map +1 -0
  68. package/dist/factory/index.d.ts +1 -0
  69. package/dist/factory/index.js +6 -0
  70. package/dist/factory/index.js.map +1 -0
  71. package/dist/fixtures/aspects/babel/babel.aspect.d.ts +5 -0
  72. package/dist/fixtures/aspects/babel/babel.aspect.js +13 -0
  73. package/dist/fixtures/aspects/babel/babel.aspect.js.map +1 -0
  74. package/dist/fixtures/aspects/babel/babel.cli.d.ts +5 -0
  75. package/dist/fixtures/aspects/babel/babel.cli.js +28 -0
  76. package/dist/fixtures/aspects/babel/babel.cli.js.map +1 -0
  77. package/dist/fixtures/aspects/react/react.aspect.d.ts +6 -0
  78. package/dist/fixtures/aspects/react/react.aspect.js +19 -0
  79. package/dist/fixtures/aspects/react/react.aspect.js.map +1 -0
  80. package/dist/fixtures/aspects/react/react.cli.d.ts +11 -0
  81. package/dist/fixtures/aspects/react/react.cli.js +71 -0
  82. package/dist/fixtures/aspects/react/react.cli.js.map +1 -0
  83. package/dist/fixtures/aspects/react/react.ui.d.ts +5 -0
  84. package/dist/fixtures/aspects/react/react.ui.js +31 -0
  85. package/dist/fixtures/aspects/react/react.ui.js.map +1 -0
  86. package/dist/fixtures/aspects/ui/ui.aspect.d.ts +4 -0
  87. package/dist/fixtures/aspects/ui/ui.aspect.js +15 -0
  88. package/dist/fixtures/aspects/ui/ui.aspect.js.map +1 -0
  89. package/dist/fixtures/aspects/ui/ui.ui.d.ts +4 -0
  90. package/dist/fixtures/aspects/ui/ui.ui.js +24 -0
  91. package/dist/fixtures/aspects/ui/ui.ui.js.map +1 -0
  92. package/dist/fixtures/babel/babel.extension.d.ts +9 -0
  93. package/dist/fixtures/babel/babel.extension.js +30 -0
  94. package/dist/fixtures/babel/babel.extension.js.map +1 -0
  95. package/dist/fixtures/babel/index.d.ts +0 -0
  96. package/dist/fixtures/babel/index.js +1 -0
  97. package/dist/fixtures/babel/index.js.map +1 -0
  98. package/dist/fixtures/base-compiler/base-compiler.extension.d.ts +13 -0
  99. package/dist/fixtures/base-compiler/base-compiler.extension.js +30 -0
  100. package/dist/fixtures/base-compiler/base-compiler.extension.js.map +1 -0
  101. package/dist/fixtures/base-compiler/index.d.ts +1 -0
  102. package/dist/fixtures/base-compiler/index.js +6 -0
  103. package/dist/fixtures/base-compiler/index.js.map +1 -0
  104. package/dist/fixtures/cli/cli.extension.d.ts +18 -0
  105. package/dist/fixtures/cli/cli.extension.js +24 -0
  106. package/dist/fixtures/cli/cli.extension.js.map +1 -0
  107. package/dist/fixtures/cli/command.d.ts +6 -0
  108. package/dist/fixtures/cli/command.js +1 -0
  109. package/dist/fixtures/cli/command.js.map +1 -0
  110. package/dist/fixtures/cli/index.d.ts +1 -0
  111. package/dist/fixtures/cli/index.js +18 -0
  112. package/dist/fixtures/cli/index.js.map +1 -0
  113. package/dist/fixtures/typescript/index.d.ts +0 -0
  114. package/dist/fixtures/typescript/index.js +1 -0
  115. package/dist/fixtures/typescript/index.js.map +1 -0
  116. package/dist/fixtures/typescript/typescript.d.ts +7 -0
  117. package/dist/fixtures/typescript/typescript.js +31 -0
  118. package/dist/fixtures/typescript/typescript.js.map +1 -0
  119. package/dist/harmony-config/config-reader.d.ts +1 -0
  120. package/dist/harmony-config/config-reader.js +21 -0
  121. package/dist/harmony-config/config-reader.js.map +1 -0
  122. package/dist/harmony-config/exceptions/index.d.ts +1 -0
  123. package/dist/harmony-config/exceptions/index.js +6 -0
  124. package/dist/harmony-config/exceptions/index.js.map +1 -0
  125. package/dist/harmony-config/exceptions/read-config-error.d.ts +5 -0
  126. package/dist/harmony-config/exceptions/read-config-error.js +14 -0
  127. package/dist/harmony-config/exceptions/read-config-error.js.map +1 -0
  128. package/dist/harmony-config/harmony-config.d.ts +17 -0
  129. package/dist/harmony-config/harmony-config.js +36 -0
  130. package/dist/harmony-config/harmony-config.js.map +1 -0
  131. package/dist/harmony-config/index.d.ts +1 -0
  132. package/dist/harmony-config/index.js +6 -0
  133. package/dist/harmony-config/index.js.map +1 -0
  134. package/dist/harmony-config/locator.d.ts +0 -0
  135. package/dist/harmony-config/locator.js +1 -0
  136. package/dist/harmony-config/locator.js.map +1 -0
  137. package/dist/harmony.d.ts +63 -0
  138. package/dist/harmony.docs.mdx +250 -0
  139. package/dist/harmony.js +151 -0
  140. package/dist/harmony.js.map +1 -0
  141. package/dist/harmony.spec.old.d.ts +1 -0
  142. package/dist/harmony.spec.old.js +144 -0
  143. package/dist/harmony.spec.old.js.map +1 -0
  144. package/dist/index.d.ts +9 -0
  145. package/dist/index.js +32 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/preview-1782314412027.js +7 -0
  148. package/dist/readme.md +80 -0
  149. package/dist/runtimes/exceptions/index.d.ts +2 -0
  150. package/dist/runtimes/exceptions/index.js +8 -0
  151. package/dist/runtimes/exceptions/index.js.map +1 -0
  152. package/dist/runtimes/exceptions/runtime-module-error.d.ts +5 -0
  153. package/dist/runtimes/exceptions/runtime-module-error.js +14 -0
  154. package/dist/runtimes/exceptions/runtime-module-error.js.map +1 -0
  155. package/dist/runtimes/exceptions/runtime-not-defined.d.ts +3 -0
  156. package/dist/runtimes/exceptions/runtime-not-defined.js +8 -0
  157. package/dist/runtimes/exceptions/runtime-not-defined.js.map +1 -0
  158. package/dist/runtimes/index.d.ts +3 -0
  159. package/dist/runtimes/index.js +8 -0
  160. package/dist/runtimes/index.js.map +1 -0
  161. package/dist/runtimes/runtime-definition.d.ts +11 -0
  162. package/dist/runtimes/runtime-definition.js +27 -0
  163. package/dist/runtimes/runtime-definition.js.map +1 -0
  164. package/dist/runtimes/runtime-manifest.d.ts +13 -0
  165. package/dist/runtimes/runtime-manifest.js +3 -0
  166. package/dist/runtimes/runtime-manifest.js.map +1 -0
  167. package/dist/runtimes/runtimes.d.ts +14 -0
  168. package/dist/runtimes/runtimes.js +43 -0
  169. package/dist/runtimes/runtimes.js.map +1 -0
  170. package/dist/slots/index.d.ts +2 -0
  171. package/dist/slots/index.js +8 -0
  172. package/dist/slots/index.js.map +1 -0
  173. package/dist/slots/registry.d.ts +21 -0
  174. package/dist/slots/registry.js +36 -0
  175. package/dist/slots/registry.js.map +1 -0
  176. package/dist/slots/slot.d.ts +5 -0
  177. package/dist/slots/slot.js +13 -0
  178. package/dist/slots/slot.js.map +1 -0
  179. package/dist/types.d.ts +5 -0
  180. package/dist/types.js +3 -0
  181. package/dist/types.js.map +1 -0
  182. package/dist/utils/async-for-each.d.ts +5 -0
  183. package/dist/utils/async-for-each.js +25 -0
  184. package/dist/utils/async-for-each.js.map +1 -0
  185. package/dist/utils/index.d.ts +1 -0
  186. package/dist/utils/index.js +6 -0
  187. package/dist/utils/index.js.map +1 -0
  188. package/exceptions/extension-init-error.ts +1 -0
  189. package/exceptions/extension-load-error.ts +28 -0
  190. package/exceptions/extension-potential-circular.ts +24 -0
  191. package/exceptions/harmony-already-running.ts +1 -0
  192. package/exceptions/harmony-error.ts +1 -0
  193. package/exceptions/hook-not-found.ts +1 -0
  194. package/exceptions/index.ts +5 -0
  195. package/exceptions/runtime-not-defined.ts +0 -0
  196. package/extension/any-extension.ts +8 -0
  197. package/extension/decorator.ts +126 -0
  198. package/extension/extension-manifest.ts +51 -0
  199. package/extension/extension.ts +142 -0
  200. package/extension/index.ts +3 -0
  201. package/extension-graph/extension-graph.ts +165 -0
  202. package/extension-graph/from-extension.ts +72 -0
  203. package/extension-graph/index.ts +1 -0
  204. package/factory/extension-factory.ts +8 -0
  205. package/factory/index.ts +1 -0
  206. package/fixtures/aspects/babel/babel.aspect.ts +14 -0
  207. package/fixtures/aspects/babel/babel.cli.ts +16 -0
  208. package/fixtures/aspects/react/react.aspect.ts +22 -0
  209. package/fixtures/aspects/react/react.cli.ts +26 -0
  210. package/fixtures/aspects/react/react.ui.ts +16 -0
  211. package/fixtures/aspects/ui/ui.aspect.ts +13 -0
  212. package/fixtures/aspects/ui/ui.ui.ts +11 -0
  213. package/fixtures/babel/babel.extension.ts +20 -0
  214. package/fixtures/babel/index.ts +0 -0
  215. package/fixtures/base-compiler/base-compiler.extension.ts +31 -0
  216. package/fixtures/base-compiler/index.ts +1 -0
  217. package/fixtures/cli/cli.extension.ts +25 -0
  218. package/fixtures/cli/command.ts +6 -0
  219. package/fixtures/cli/index.ts +1 -0
  220. package/fixtures/typescript/index.ts +0 -0
  221. package/fixtures/typescript/typescript.ts +20 -0
  222. package/harmony-config/config-reader.ts +18 -0
  223. package/harmony-config/exceptions/index.ts +1 -0
  224. package/harmony-config/exceptions/read-config-error.ts +9 -0
  225. package/harmony-config/harmony-config.ts +49 -0
  226. package/harmony-config/index.ts +1 -0
  227. package/harmony-config/locator.ts +0 -0
  228. package/harmony.docs.mdx +250 -0
  229. package/harmony.spec.old.ts +177 -0
  230. package/harmony.ts +148 -0
  231. package/index.ts +13 -0
  232. package/package.json +68 -0
  233. package/readme.md +80 -0
  234. package/runtimes/exceptions/index.ts +2 -0
  235. package/runtimes/exceptions/runtime-module-error.ts +9 -0
  236. package/runtimes/exceptions/runtime-not-defined.ts +5 -0
  237. package/runtimes/index.ts +3 -0
  238. package/runtimes/runtime-definition.ts +32 -0
  239. package/runtimes/runtime-manifest.ts +12 -0
  240. package/runtimes/runtimes.ts +34 -0
  241. package/slots/index.ts +2 -0
  242. package/slots/registry.ts +36 -0
  243. package/slots/slot.ts +11 -0
  244. package/types/asset.d.ts +29 -0
  245. package/types/style.d.ts +42 -0
  246. package/types.ts +7 -0
  247. package/utils/async-for-each.ts +10 -0
  248. package/utils/index.ts +1 -0
@@ -0,0 +1,177 @@
1
+ import { Harmony } from './harmony';
2
+ // import { BitExt } from '../../bit/dist/extensions/bit';
3
+ // import { BaseCompiler } from './fixtures/base-compiler';
4
+ // import { TypeScript } from './fixtures/typescript/typescript';
5
+ // import { Babel } from './fixtures/babel/babel.extension';
6
+ // import { Slot, SlotRegistry } from './slots';
7
+ // import { start } from 'repl';
8
+ // import { ExtensionManifest } from './extension';
9
+ import { ReactAspect } from './fixtures/aspects/react/react.aspect';
10
+ import { ReactCLI } from './fixtures/aspects/react/react.cli';
11
+ import { ReactUI } from './fixtures/aspects/react/react.ui';
12
+
13
+ describe('Harmony', () => {
14
+ describe('run()', () => {
15
+ // it('should return a string', async () => {
16
+ // const manifest = {
17
+ // name: 'HelloWorld',
18
+ // provider: async () => 'hello world'
19
+ // };
20
+ // await harmony.run(manifest);
21
+ // expect(harmony.get('HelloWorld')).eql('hello world');
22
+ // });
23
+
24
+ // it('should load an array of different extensions', async () => {
25
+ // await harmony.run([BaseCompiler, TypeScript]);
26
+ // const compiler = harmony.get<BaseCompiler>('BaseCompiler')
27
+ // const typescript = harmony.get<TypeScript>('typescript')
28
+
29
+ // expect(typescript.compile()).to.eq('hello world');
30
+ // expect(compiler.compile()).to.eq('hello world');
31
+ // });
32
+
33
+ // it('should load extensions with slots', async () => {
34
+ // class Env {
35
+ // build () {
36
+ // return 'react built';
37
+ // }
38
+ // }
39
+
40
+ // it('extension instance should include an ID', async () => {
41
+ // const React = {
42
+ // name: '@teambit/react',
43
+ // dependencies: [],
44
+ // provide: async () => {}
45
+ // };
46
+
47
+ // await harmony.run([React]);
48
+ // const react = harmony.get<any>(React.name);
49
+ // expect(react.id).to.eq(React.name);
50
+ // });
51
+
52
+ // const Envs: ExtensionManifest = {
53
+ // name: '@teambit/envs',
54
+ // slots: [Slot.withType<Env>()],
55
+ // provider: async ([], config: {env: string}, [envSlot]: [SlotRegistry<Env>]) => {
56
+ // return {
57
+ // register: (env: Env) => {
58
+ // envSlot.register(env);
59
+ // },
60
+
61
+ // start() {
62
+ // const instance = envSlot.get(config.env);
63
+ // if (!instance) throw new Error('could not find envs');
64
+ // return instance.build();
65
+ // }
66
+ // };
67
+ // }
68
+ // };
69
+
70
+ // const React = {
71
+ // name: '@teambit/react',
72
+ // dependencies: [Envs],
73
+ // provide: async ([envs]: [{ register: (env: Env) => void }], config: {}) => {
74
+ // envs.register(new Env());
75
+ // }
76
+ // };
77
+
78
+ // const harmony = Harmony.load([Envs, React], {
79
+ // '@teambit/envs': {
80
+ // env: '@teambit/react'
81
+ // }
82
+ // });
83
+
84
+ // await harmony.run([Envs, React]);
85
+
86
+ // const envs = harmony.get<any>(Envs.name);
87
+ // expect(envs.start()).to.eq('react built');
88
+ // });
89
+
90
+ // it('should load extensions with config', async () => {
91
+ // const e1 = {
92
+ // name: '@teambit/typescript',
93
+
94
+ // provider: async ([], config: { declarations: boolean }) => {
95
+ // return {
96
+ // get: () => {
97
+ // return config.declarations || false
98
+ // }
99
+ // };
100
+ // }
101
+ // };
102
+
103
+ // const e2 = { name: '@teambit/react', defaultConfig: {ts: false}, provide: async ([], config: any) => {
104
+ // return {
105
+ // config: config.ts
106
+ // };
107
+ // }
108
+ // };
109
+
110
+ // const harmony = Harmony.load([e1], {
111
+ // '@teambit/typescript': {
112
+ // declarations: true
113
+ // },
114
+ // });
115
+ // await harmony.run([e1]);
116
+
117
+ // const ts = harmony.get<{get: () => {}}>('@teambit/typescript');
118
+ // expect(ts.get()).to.eq(true);
119
+
120
+ // harmony.config.set('@teambit/react', {ts: true});
121
+ // await harmony.set([e2]);
122
+ // const react = harmony.get<{[key: string]: object}>('@teambit/react');
123
+ // expect(react.config).to.eq(true);
124
+ // });
125
+
126
+ // it('should invoke a class extension method', async () => {
127
+ // await harmony.run(BaseCompiler);
128
+ // const compiler = harmony.get<BaseCompiler>('BaseCompiler')
129
+ // expect(compiler.compile()).to.eq('hello world');
130
+ // });
131
+
132
+ // it('should invoke a class extension with configured dependencies', async () => {
133
+ // await harmony.run(TypeScript);
134
+ // const typescript = harmony.get<TypeScript>('typescript')
135
+ // expect(typescript.compile()).to.eq('hello world');
136
+ // });
137
+
138
+ // it('should use prefer id over name', async () => {
139
+ // const dependency = {
140
+ // name: 'dependencyName',
141
+ // id: 'dependencyId',
142
+ // provider: async () => 'hello world'
143
+ // };
144
+ // const dependent = {
145
+ // name: 'dependentName',
146
+ // id: 'dependentId',
147
+ // dependencies: [dependency],
148
+ // provider: async () => 'hello world'
149
+ // };
150
+ // await harmony.run(dependent);
151
+ // const ids = harmony.extensionsIds;
152
+ // expect(ids).to.contain('dependencyId');
153
+ // expect(ids).to.contain('dependentId');
154
+ // });
155
+
156
+ // it('should execute bit core extension graph', async () => {
157
+ // // const bit = await Harmony.run(BitExt);
158
+ // });
159
+
160
+ // it('should register during run', async () => {
161
+ // const compiler = await harmony.run(Babel);
162
+ // });
163
+
164
+ // it('should execute an aspect in the cli runtime', async() => {
165
+ // const harmony = await Harmony.load([ReactAspect], 'cli', {});
166
+ // await harmony.run();
167
+ // const react = harmony.get<ReactCLI>('@teambit/react');
168
+ // })
169
+
170
+ // it('should execute an aspect in the ui runtime', async() => {
171
+ // const harmony = await Harmony.load([ReactAspect], 'ui', {});
172
+ // await harmony.run();
173
+ // const react = harmony.get<ReactUI>('@teambit/react');
174
+ // expect(react.render()).toBeTruthy;
175
+ // })
176
+ });
177
+ });
package/harmony.ts ADDED
@@ -0,0 +1,148 @@
1
+ import 'reflect-metadata';
2
+ import ExtensionGraph, { DependencyGraphOptions } from './extension-graph/extension-graph';
3
+ import { ExtensionLoadError } from './exceptions';
4
+ import { Extension, ExtensionManifest } from './extension';
5
+ import { asyncForEach } from './utils';
6
+ import { Config } from './config';
7
+ import { Aspect } from './aspect';
8
+ import { Runtimes } from './runtimes/runtimes';
9
+ import { RuntimeDefinition } from './runtimes/runtime-definition';
10
+ import { RuntimeNotDefined } from './runtimes/exceptions';
11
+
12
+ export type GlobalConfig = {
13
+ [key: string]: object
14
+ };
15
+
16
+ export type RequireFn = (aspect: Extension, runtime: RuntimeDefinition) => Promise<void>;
17
+
18
+ export class Harmony {
19
+ constructor(
20
+ /**
21
+ * extension graph
22
+ */
23
+ readonly graph: ExtensionGraph,
24
+
25
+ /**
26
+ * harmony top level config
27
+ */
28
+ readonly config: Config,
29
+
30
+ readonly runtimes: Runtimes,
31
+
32
+ readonly activeRuntime: string,
33
+
34
+ private depOptions: DependencyGraphOptions
35
+ ) {}
36
+
37
+ public current: string|null = null;
38
+
39
+ private runtime: RuntimeDefinition | undefined;
40
+
41
+ /**
42
+ * list all registered extensions
43
+ */
44
+ get extensions() {
45
+ return this.graph.nodes;
46
+ }
47
+
48
+ /**
49
+ * list all registered extensions ids
50
+ */
51
+ get extensionsIds() {
52
+ return [...this.graph.nodes.keys()];
53
+ }
54
+
55
+ /**
56
+ * load an Aspect into the dependency graph.
57
+ */
58
+ async load(extensions: ExtensionManifest[]) {
59
+ return this.set(extensions);
60
+ }
61
+
62
+ /**
63
+ * set extensions during Harmony runtime.
64
+ * hack!
65
+ */
66
+ async set(extensions: ExtensionManifest[]) {
67
+ this.graph.load(extensions);
68
+ // Only load new extensions and their dependencies
69
+ const extensionsToLoad = extensions.map((ext) => {
70
+ // @ts-ignore
71
+ return Reflect.getMetadata('harmony:name', ext) || ext.id || ext.name;
72
+ });
73
+
74
+ // @ts-ignore
75
+ await this.graph.enrichRuntime(this.runtime, this.runtimes, () => {});
76
+ // @ts-ignore
77
+ const subgraphs = this.graph.successorsSubgraph(extensionsToLoad);
78
+ if (subgraphs) {
79
+ const executionOrder = subgraphs.toposort(true);
80
+ await asyncForEach(executionOrder, async (ext: Extension) => {
81
+ if (!this.runtime) throw new RuntimeNotDefined(this.activeRuntime);
82
+ await this.runOne(ext, this.runtime);
83
+ });
84
+ }
85
+ }
86
+
87
+ private async runOne(extension: Extension, runtime: RuntimeDefinition) {
88
+ if (extension.loaded) return;
89
+ // create an index of all vertices in dependency graph
90
+ const deps = this.graph.getRuntimeDependencies(extension, runtime, this.depOptions);
91
+ const instances = deps.map(extension => extension.instance);
92
+
93
+ try {
94
+ return extension.__run(instances, this, runtime);
95
+ } catch (err) {
96
+ throw new ExtensionLoadError(extension, err instanceof Error ? err : new Error(String(err)));
97
+ }
98
+ }
99
+
100
+ getDependencies(aspect: Extension) {
101
+ if (!this.runtime) throw new RuntimeNotDefined(this.activeRuntime);
102
+ return this.graph.getRuntimeDependencies(aspect, this.runtime, this.depOptions);
103
+ }
104
+
105
+ initExtension(id: string) {
106
+ this.current = id;
107
+ }
108
+
109
+ endExtension() {
110
+ this.current = null;
111
+ }
112
+
113
+ /**
114
+ * get an extension from harmony.
115
+ */
116
+ get<T>(id: string): T {
117
+ const extension = this.graph.get(id);
118
+ if (!extension || !extension.instance) throw new Error(`failed loading extension ${id}`);
119
+ return extension.instance;
120
+ }
121
+
122
+ resolveRuntime(name: string): RuntimeDefinition {
123
+ return this.runtimes.get(name);
124
+ }
125
+
126
+ async run(requireFn?: RequireFn) {
127
+ const runtime = this.resolveRuntime(this.activeRuntime);
128
+ this.runtime = runtime;
129
+ const defaultRequireFn: RequireFn = async (aspect: Extension, runtime: RuntimeDefinition) => {
130
+ const runtimeFile = runtime.getRuntimeFile(aspect.files);
131
+ if (!runtimeFile) return;
132
+ // runtime.require(runtimeFile);
133
+ };
134
+ // requireFn ? await requireFn(aspect, runtime) : defaultRequireFn(this.graph);
135
+ await this.graph.enrichRuntime(runtime, this.runtimes, requireFn || defaultRequireFn, this.depOptions);
136
+
137
+ const executionOrder = this.graph.byExecutionOrder();
138
+ await asyncForEach(executionOrder, async (ext: Extension) => {
139
+ await this.runOne(ext, runtime);
140
+ });
141
+ }
142
+
143
+ static async load(aspects: Aspect[], runtime: string, globalConfig: GlobalConfig, options: DependencyGraphOptions = {}) {
144
+ const aspectGraph = ExtensionGraph.from(aspects as any, options);
145
+ const runtimes = await Runtimes.load(aspectGraph);
146
+ return new Harmony(aspectGraph, Config.from(globalConfig), runtimes, runtime, options);
147
+ }
148
+ }
package/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export { ExtensionDecorator, Extension, register, HookRegistry, hook, provider, createHook } from './extension';
2
+ export { Harmony, GlobalConfig } from './harmony';
3
+ export { Slot, SlotRegistry } from './slots';
4
+ export { ProviderFn } from './types';
5
+ export { ExtensionManifest } from './extension/extension-manifest';
6
+ export { HarmonyError } from './exceptions/harmony-error';
7
+ export { Aspect } from './aspect';
8
+ export { RuntimeDefinition, RuntimeManifest } from './runtimes';
9
+ export { default as AspectGraph } from './extension-graph/extension-graph';
10
+ // `Config` / `ConfigOptions` are not re-exported from the root because they
11
+ // pull in node-only modules and would break browser bundles. They are exposed
12
+ // via the subpath `@teambit/harmony/harmony-config` with a `node` exports
13
+ // condition — see this component's `packageJson.exports` in component.json.
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@teambit/harmony",
3
+ "version": "0.0.0-19ea14143ef7d5f4e4daa6e8ac8a8c97c9d683d5",
4
+ "homepage": "https://bit.cloud/teambit/harmony/harmony",
5
+ "main": "dist/index.js",
6
+ "componentId": {
7
+ "scope": "teambit.harmony",
8
+ "name": "harmony",
9
+ "version": "19ea14143ef7d5f4e4daa6e8ac8a8c97c9d683d5"
10
+ },
11
+ "dependencies": {
12
+ "reflect-metadata": "0.1.14",
13
+ "comment-json": "4.2.5",
14
+ "user-home": "3.0.0",
15
+ "cleargraph": "5.8.0"
16
+ },
17
+ "devDependencies": {
18
+ "@types/comment-json": "^2.4.5",
19
+ "@types/jest": "26.0.20",
20
+ "@types/node": "22.10.5"
21
+ },
22
+ "peerDependencies": {},
23
+ "license": "Apache-2.0",
24
+ "optionalDependencies": {},
25
+ "peerDependenciesMeta": {},
26
+ "private": false,
27
+ "engines": {
28
+ "node": ">=12.22.0"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/teambit/harmony"
33
+ },
34
+ "description": "abstract extension system",
35
+ "keywords": [
36
+ "bit",
37
+ "bit-aspect",
38
+ "components",
39
+ "collaboration",
40
+ "harmony",
41
+ "aspects",
42
+ "extensions"
43
+ ],
44
+ "exports": {
45
+ ".": {
46
+ "types": "./index.ts",
47
+ "node": {
48
+ "require": "./dist/index.js",
49
+ "import": "./dist/esm.mjs"
50
+ },
51
+ "default": "./dist/index.js"
52
+ },
53
+ "./harmony-config": {
54
+ "node": {
55
+ "types": "./dist/harmony-config/index.d.ts",
56
+ "default": "./dist/harmony-config/index.js"
57
+ }
58
+ },
59
+ "./harmony-config/config-reader": {
60
+ "node": {
61
+ "types": "./dist/harmony-config/config-reader.d.ts",
62
+ "default": "./dist/harmony-config/config-reader.js"
63
+ }
64
+ },
65
+ "./dist/harmony-config": "./dist/harmony-config/index.js",
66
+ "./dist/harmony-config/config-reader": "./dist/harmony-config/config-reader.js"
67
+ }
68
+ }
package/readme.md ADDED
@@ -0,0 +1,80 @@
1
+ # Harmony
2
+ Harmony is the engine that drives Bit extensibility and composability.
3
+ It's an abstract extension system indended to make any software extendable and composable.
4
+
5
+ Harmony takes a "micro-kernel" approach and implements the near-minimum amount of software required to build any JavaScript system from independent components through composition.
6
+
7
+ ## Installation
8
+ ```bash
9
+ $ bit install @teambit/harmony
10
+ ```
11
+
12
+ ## Quick start
13
+ ```ts
14
+ import { Harmony, Extension } from 'harmony';
15
+
16
+ @Extensioin
17
+ class Person {
18
+ sayHello(name = 'world') {
19
+ return `hello ${name}!`;
20
+ }
21
+ }
22
+
23
+ const person = Harmony.load(Person);
24
+ helloWorld.sayHello(); // returns 'hello world!'
25
+ ```
26
+
27
+ ## Component composition
28
+
29
+ ### DI
30
+ ```ts
31
+ class Dude {
32
+ constructor(
33
+ private person: Person
34
+ ) {}
35
+
36
+ sayHello() {
37
+ return this.person.sayHello('dude');
38
+ }
39
+ };
40
+
41
+ Harmony.load([Dude]).sayHello(); // echos 'hello dude!'
42
+ ```
43
+
44
+ ### Hooks
45
+ ```ts
46
+ @Extension()
47
+ class CLI {
48
+ // @hook('command') commands = Hook.create<Command>();
49
+ static command() {
50
+ return Hook.create<Command>();
51
+ }
52
+
53
+ run() {
54
+ const allCommands = this.commands.list(); // outputs all hook subscribers
55
+ }
56
+ }
57
+
58
+ @Extension()
59
+ class Compiler {
60
+
61
+ @command()
62
+ main() {
63
+ return {
64
+ synopsis: 'compile <path>',
65
+ render: () => <Box></Box>
66
+ };
67
+ }
68
+ }
69
+ ```
70
+
71
+ ## Extension configuration
72
+
73
+ ## Extension metadata
74
+
75
+ ## API reference
76
+
77
+ ## License
78
+ Apache License, Version 2.0
79
+
80
+ Made with ❤ to open software by Team Bit.
@@ -0,0 +1,2 @@
1
+ export { RuntimeNotDefined } from './runtime-not-defined';
2
+ export { RuntimeModuleError } from './runtime-module-error';
@@ -0,0 +1,9 @@
1
+ export class RuntimeModuleError extends Error {
2
+ constructor(
3
+ private err: Error
4
+ ) { super(`failed to load Harmony aspect with error message: ${err.message}`) }
5
+
6
+ get stack() {
7
+ return this.err.stack;
8
+ }
9
+ }
@@ -0,0 +1,5 @@
1
+ export class RuntimeNotDefined extends Error {
2
+ constructor(
3
+ name: string
4
+ ) { super(`runtime: '${name}' was not defined by any aspect`) }
5
+ }
@@ -0,0 +1,3 @@
1
+ export { RuntimeManifest } from './runtime-manifest';
2
+ export { Runtimes } from './runtimes';
3
+ export { RuntimeDefinition } from './runtime-definition';
@@ -0,0 +1,32 @@
1
+ import { RuntimeModuleError } from './exceptions';
2
+
3
+ export type RuntimeDefProps = {
4
+ name: string
5
+ };
6
+
7
+ const DEFAULT_PREDICATE = (filePath: string, name: string) => {
8
+ return filePath.includes(`.${name}.`);
9
+ }
10
+
11
+ export class RuntimeDefinition {
12
+ constructor(
13
+ readonly name: string,
14
+ readonly filePredicate: (filePath: string, name: string) => boolean = DEFAULT_PREDICATE
15
+ ) {}
16
+
17
+ getRuntimeFile(paths: string[]): string|undefined {
18
+ return paths.find(path => this.filePredicate(path, this.name));
19
+ }
20
+
21
+ require(file: string) {
22
+ // try {
23
+ // require(file);
24
+ // } catch(err) {
25
+ // throw new RuntimeModuleError(err);
26
+ // }
27
+ }
28
+
29
+ static create(def: RuntimeDefProps) {
30
+ return new RuntimeDefinition(def.name);
31
+ }
32
+ }
@@ -0,0 +1,12 @@
1
+ import { RuntimeDefinition } from './runtime-definition';
2
+ import { ProviderFn } from '../types';
3
+ import { Aspect } from '../aspect';
4
+ import { SlotProvider } from '../slots';
5
+
6
+ export interface RuntimeManifest {
7
+ runtime: RuntimeDefinition|string
8
+ provider: ProviderFn,
9
+ dependencies?: Aspect[],
10
+ slots?: SlotProvider<unknown>[],
11
+ defaultConfig?: {[key: string]: any},
12
+ }
@@ -0,0 +1,34 @@
1
+ import { RuntimeDefinition } from './runtime-definition';
2
+ import DependencyGraph from '../extension-graph/extension-graph';
3
+ import { RuntimeNotDefined } from './exceptions';
4
+
5
+ export class Runtimes {
6
+ constructor(
7
+ readonly runtimeDefinition: {[key: string]: RuntimeDefinition}
8
+ ) {}
9
+
10
+ add(runtime: RuntimeDefinition) {
11
+ this.runtimeDefinition[runtime.name] = runtime;
12
+ return this;
13
+ }
14
+
15
+ get(name: string): RuntimeDefinition {
16
+ const runtime = this.runtimeDefinition[name];
17
+ if (!runtime) throw new RuntimeNotDefined(name);
18
+ return this.runtimeDefinition[name];
19
+ }
20
+
21
+ dispose() {
22
+
23
+ }
24
+
25
+ static async load(graph: DependencyGraph) {
26
+ const runtimes: { [key: string]: RuntimeDefinition } = {};
27
+ graph.extensions.forEach(manifest => {
28
+ if (!manifest.declareRuntime) return;
29
+ runtimes[manifest.declareRuntime.name] = manifest.declareRuntime;
30
+ });
31
+
32
+ return new Runtimes(runtimes);
33
+ }
34
+ }
package/slots/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { Slot, SlotProvider } from './slot';
2
+ export { SlotRegistry } from './registry';
@@ -0,0 +1,36 @@
1
+
2
+ export class SlotRegistry<T> {
3
+ constructor(
4
+ private registerFn: () => string,
5
+ readonly map = new Map<string, T>()
6
+ ) {}
7
+
8
+ /**
9
+ * get a slot value by extension id.
10
+ */
11
+ get(id: string): T|undefined {
12
+ return this.map.get(id);
13
+ }
14
+
15
+ /**
16
+ * return an array of all slots.
17
+ */
18
+ toArray() {
19
+ return Array.from(this.map.entries());
20
+ }
21
+
22
+ /**
23
+ * get all registered values.
24
+ */
25
+ values() {
26
+ return Array.from(this.map.values());
27
+ }
28
+
29
+ /**
30
+ * register a new entry to the slot registry
31
+ */
32
+ register(value: T) {
33
+ const id = this.registerFn();
34
+ this.map.set(id, value);
35
+ }
36
+ }
package/slots/slot.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { SlotRegistry } from './registry';
2
+
3
+ export class Slot {
4
+ static withType<T>() {
5
+ return (registerFn: () => string) => {
6
+ return new SlotRegistry<T>(registerFn);
7
+ }
8
+ }
9
+ }
10
+
11
+ export type SlotProvider<T> = (registerFn: () => string) => SlotRegistry<T>;
@@ -0,0 +1,29 @@
1
+ declare module '*.png' {
2
+ const value: any;
3
+ export = value;
4
+ }
5
+ declare module '*.svg' {
6
+ import type { FunctionComponent, SVGProps } from 'react';
7
+
8
+ export const ReactComponent: FunctionComponent<SVGProps<SVGSVGElement> & { title?: string }>;
9
+ const src: string;
10
+ export default src;
11
+ }
12
+
13
+ // @TODO Gilad
14
+ declare module '*.jpg' {
15
+ const value: any;
16
+ export = value;
17
+ }
18
+ declare module '*.jpeg' {
19
+ const value: any;
20
+ export = value;
21
+ }
22
+ declare module '*.gif' {
23
+ const value: any;
24
+ export = value;
25
+ }
26
+ declare module '*.bmp' {
27
+ const value: any;
28
+ export = value;
29
+ }