@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.
- package/aspect.ts +52 -0
- package/config/config.ts +36 -0
- package/config/index.ts +1 -0
- package/container.ts +22 -0
- package/dist/aspect.d.ts +27 -0
- package/dist/aspect.js +33 -0
- package/dist/aspect.js.map +1 -0
- package/dist/config/config.d.ts +22 -0
- package/dist/config/config.js +37 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/container.d.ts +8 -0
- package/dist/container.js +22 -0
- package/dist/container.js.map +1 -0
- package/dist/exceptions/extension-init-error.d.ts +2 -0
- package/dist/exceptions/extension-init-error.js +7 -0
- package/dist/exceptions/extension-init-error.js.map +1 -0
- package/dist/exceptions/extension-load-error.d.ts +29 -0
- package/dist/exceptions/extension-load-error.js +29 -0
- package/dist/exceptions/extension-load-error.js.map +1 -0
- package/dist/exceptions/extension-potential-circular.d.ts +22 -0
- package/dist/exceptions/extension-potential-circular.js +25 -0
- package/dist/exceptions/extension-potential-circular.js.map +1 -0
- package/dist/exceptions/harmony-already-running.d.ts +2 -0
- package/dist/exceptions/harmony-already-running.js +7 -0
- package/dist/exceptions/harmony-already-running.js.map +1 -0
- package/dist/exceptions/harmony-error.d.ts +2 -0
- package/dist/exceptions/harmony-error.js +7 -0
- package/dist/exceptions/harmony-error.js.map +1 -0
- package/dist/exceptions/hook-not-found.d.ts +2 -0
- package/dist/exceptions/hook-not-found.js +7 -0
- package/dist/exceptions/hook-not-found.js.map +1 -0
- package/dist/exceptions/index.d.ts +5 -0
- package/dist/exceptions/index.js +17 -0
- package/dist/exceptions/index.js.map +1 -0
- package/dist/exceptions/runtime-not-defined.d.ts +0 -0
- package/dist/exceptions/runtime-not-defined.js +1 -0
- package/dist/exceptions/runtime-not-defined.js.map +1 -0
- package/dist/extension/any-extension.d.ts +5 -0
- package/dist/extension/any-extension.js +8 -0
- package/dist/extension/any-extension.js.map +1 -0
- package/dist/extension/decorator.d.ts +27 -0
- package/dist/extension/decorator.js +109 -0
- package/dist/extension/decorator.js.map +1 -0
- package/dist/extension/extension-manifest.d.ts +41 -0
- package/dist/extension/extension-manifest.js +3 -0
- package/dist/extension/extension-manifest.js.map +1 -0
- package/dist/extension/extension.d.ts +50 -0
- package/dist/extension/extension.js +128 -0
- package/dist/extension/extension.js.map +1 -0
- package/dist/extension/index.d.ts +3 -0
- package/dist/extension/index.js +13 -0
- package/dist/extension/index.js.map +1 -0
- package/dist/extension-graph/extension-graph.d.ts +34 -0
- package/dist/extension-graph/extension-graph.js +152 -0
- package/dist/extension-graph/extension-graph.js.map +1 -0
- package/dist/extension-graph/from-extension.d.ts +31 -0
- package/dist/extension-graph/from-extension.js +63 -0
- package/dist/extension-graph/from-extension.js.map +1 -0
- package/dist/extension-graph/index.d.ts +1 -0
- package/dist/extension-graph/index.js +9 -0
- package/dist/extension-graph/index.js.map +1 -0
- package/dist/factory/extension-factory.d.ts +3 -0
- package/dist/factory/extension-factory.js +11 -0
- package/dist/factory/extension-factory.js.map +1 -0
- package/dist/factory/index.d.ts +1 -0
- package/dist/factory/index.js +6 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/fixtures/aspects/babel/babel.aspect.d.ts +5 -0
- package/dist/fixtures/aspects/babel/babel.aspect.js +13 -0
- package/dist/fixtures/aspects/babel/babel.aspect.js.map +1 -0
- package/dist/fixtures/aspects/babel/babel.cli.d.ts +5 -0
- package/dist/fixtures/aspects/babel/babel.cli.js +28 -0
- package/dist/fixtures/aspects/babel/babel.cli.js.map +1 -0
- package/dist/fixtures/aspects/react/react.aspect.d.ts +6 -0
- package/dist/fixtures/aspects/react/react.aspect.js +19 -0
- package/dist/fixtures/aspects/react/react.aspect.js.map +1 -0
- package/dist/fixtures/aspects/react/react.cli.d.ts +11 -0
- package/dist/fixtures/aspects/react/react.cli.js +71 -0
- package/dist/fixtures/aspects/react/react.cli.js.map +1 -0
- package/dist/fixtures/aspects/react/react.ui.d.ts +5 -0
- package/dist/fixtures/aspects/react/react.ui.js +31 -0
- package/dist/fixtures/aspects/react/react.ui.js.map +1 -0
- package/dist/fixtures/aspects/ui/ui.aspect.d.ts +4 -0
- package/dist/fixtures/aspects/ui/ui.aspect.js +15 -0
- package/dist/fixtures/aspects/ui/ui.aspect.js.map +1 -0
- package/dist/fixtures/aspects/ui/ui.ui.d.ts +4 -0
- package/dist/fixtures/aspects/ui/ui.ui.js +24 -0
- package/dist/fixtures/aspects/ui/ui.ui.js.map +1 -0
- package/dist/fixtures/babel/babel.extension.d.ts +9 -0
- package/dist/fixtures/babel/babel.extension.js +30 -0
- package/dist/fixtures/babel/babel.extension.js.map +1 -0
- package/dist/fixtures/babel/index.d.ts +0 -0
- package/dist/fixtures/babel/index.js +1 -0
- package/dist/fixtures/babel/index.js.map +1 -0
- package/dist/fixtures/base-compiler/base-compiler.extension.d.ts +13 -0
- package/dist/fixtures/base-compiler/base-compiler.extension.js +30 -0
- package/dist/fixtures/base-compiler/base-compiler.extension.js.map +1 -0
- package/dist/fixtures/base-compiler/index.d.ts +1 -0
- package/dist/fixtures/base-compiler/index.js +6 -0
- package/dist/fixtures/base-compiler/index.js.map +1 -0
- package/dist/fixtures/cli/cli.extension.d.ts +18 -0
- package/dist/fixtures/cli/cli.extension.js +24 -0
- package/dist/fixtures/cli/cli.extension.js.map +1 -0
- package/dist/fixtures/cli/command.d.ts +6 -0
- package/dist/fixtures/cli/command.js +1 -0
- package/dist/fixtures/cli/command.js.map +1 -0
- package/dist/fixtures/cli/index.d.ts +1 -0
- package/dist/fixtures/cli/index.js +18 -0
- package/dist/fixtures/cli/index.js.map +1 -0
- package/dist/fixtures/typescript/index.d.ts +0 -0
- package/dist/fixtures/typescript/index.js +1 -0
- package/dist/fixtures/typescript/index.js.map +1 -0
- package/dist/fixtures/typescript/typescript.d.ts +7 -0
- package/dist/fixtures/typescript/typescript.js +31 -0
- package/dist/fixtures/typescript/typescript.js.map +1 -0
- package/dist/harmony-config/config-reader.d.ts +1 -0
- package/dist/harmony-config/config-reader.js +21 -0
- package/dist/harmony-config/config-reader.js.map +1 -0
- package/dist/harmony-config/exceptions/index.d.ts +1 -0
- package/dist/harmony-config/exceptions/index.js +6 -0
- package/dist/harmony-config/exceptions/index.js.map +1 -0
- package/dist/harmony-config/exceptions/read-config-error.d.ts +5 -0
- package/dist/harmony-config/exceptions/read-config-error.js +14 -0
- package/dist/harmony-config/exceptions/read-config-error.js.map +1 -0
- package/dist/harmony-config/harmony-config.d.ts +17 -0
- package/dist/harmony-config/harmony-config.js +36 -0
- package/dist/harmony-config/harmony-config.js.map +1 -0
- package/dist/harmony-config/index.d.ts +1 -0
- package/dist/harmony-config/index.js +6 -0
- package/dist/harmony-config/index.js.map +1 -0
- package/dist/harmony-config/locator.d.ts +0 -0
- package/dist/harmony-config/locator.js +1 -0
- package/dist/harmony-config/locator.js.map +1 -0
- package/dist/harmony.d.ts +63 -0
- package/dist/harmony.docs.mdx +250 -0
- package/dist/harmony.js +151 -0
- package/dist/harmony.js.map +1 -0
- package/dist/harmony.spec.old.d.ts +1 -0
- package/dist/harmony.spec.old.js +144 -0
- package/dist/harmony.spec.old.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/preview-1782314412027.js +7 -0
- package/dist/readme.md +80 -0
- package/dist/runtimes/exceptions/index.d.ts +2 -0
- package/dist/runtimes/exceptions/index.js +8 -0
- package/dist/runtimes/exceptions/index.js.map +1 -0
- package/dist/runtimes/exceptions/runtime-module-error.d.ts +5 -0
- package/dist/runtimes/exceptions/runtime-module-error.js +14 -0
- package/dist/runtimes/exceptions/runtime-module-error.js.map +1 -0
- package/dist/runtimes/exceptions/runtime-not-defined.d.ts +3 -0
- package/dist/runtimes/exceptions/runtime-not-defined.js +8 -0
- package/dist/runtimes/exceptions/runtime-not-defined.js.map +1 -0
- package/dist/runtimes/index.d.ts +3 -0
- package/dist/runtimes/index.js +8 -0
- package/dist/runtimes/index.js.map +1 -0
- package/dist/runtimes/runtime-definition.d.ts +11 -0
- package/dist/runtimes/runtime-definition.js +27 -0
- package/dist/runtimes/runtime-definition.js.map +1 -0
- package/dist/runtimes/runtime-manifest.d.ts +13 -0
- package/dist/runtimes/runtime-manifest.js +3 -0
- package/dist/runtimes/runtime-manifest.js.map +1 -0
- package/dist/runtimes/runtimes.d.ts +14 -0
- package/dist/runtimes/runtimes.js +43 -0
- package/dist/runtimes/runtimes.js.map +1 -0
- package/dist/slots/index.d.ts +2 -0
- package/dist/slots/index.js +8 -0
- package/dist/slots/index.js.map +1 -0
- package/dist/slots/registry.d.ts +21 -0
- package/dist/slots/registry.js +36 -0
- package/dist/slots/registry.js.map +1 -0
- package/dist/slots/slot.d.ts +5 -0
- package/dist/slots/slot.js +13 -0
- package/dist/slots/slot.js.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/async-for-each.d.ts +5 -0
- package/dist/utils/async-for-each.js +25 -0
- package/dist/utils/async-for-each.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/exceptions/extension-init-error.ts +1 -0
- package/exceptions/extension-load-error.ts +28 -0
- package/exceptions/extension-potential-circular.ts +24 -0
- package/exceptions/harmony-already-running.ts +1 -0
- package/exceptions/harmony-error.ts +1 -0
- package/exceptions/hook-not-found.ts +1 -0
- package/exceptions/index.ts +5 -0
- package/exceptions/runtime-not-defined.ts +0 -0
- package/extension/any-extension.ts +8 -0
- package/extension/decorator.ts +126 -0
- package/extension/extension-manifest.ts +51 -0
- package/extension/extension.ts +142 -0
- package/extension/index.ts +3 -0
- package/extension-graph/extension-graph.ts +165 -0
- package/extension-graph/from-extension.ts +72 -0
- package/extension-graph/index.ts +1 -0
- package/factory/extension-factory.ts +8 -0
- package/factory/index.ts +1 -0
- package/fixtures/aspects/babel/babel.aspect.ts +14 -0
- package/fixtures/aspects/babel/babel.cli.ts +16 -0
- package/fixtures/aspects/react/react.aspect.ts +22 -0
- package/fixtures/aspects/react/react.cli.ts +26 -0
- package/fixtures/aspects/react/react.ui.ts +16 -0
- package/fixtures/aspects/ui/ui.aspect.ts +13 -0
- package/fixtures/aspects/ui/ui.ui.ts +11 -0
- package/fixtures/babel/babel.extension.ts +20 -0
- package/fixtures/babel/index.ts +0 -0
- package/fixtures/base-compiler/base-compiler.extension.ts +31 -0
- package/fixtures/base-compiler/index.ts +1 -0
- package/fixtures/cli/cli.extension.ts +25 -0
- package/fixtures/cli/command.ts +6 -0
- package/fixtures/cli/index.ts +1 -0
- package/fixtures/typescript/index.ts +0 -0
- package/fixtures/typescript/typescript.ts +20 -0
- package/harmony-config/config-reader.ts +18 -0
- package/harmony-config/exceptions/index.ts +1 -0
- package/harmony-config/exceptions/read-config-error.ts +9 -0
- package/harmony-config/harmony-config.ts +49 -0
- package/harmony-config/index.ts +1 -0
- package/harmony-config/locator.ts +0 -0
- package/harmony.docs.mdx +250 -0
- package/harmony.spec.old.ts +177 -0
- package/harmony.ts +148 -0
- package/index.ts +13 -0
- package/package.json +68 -0
- package/readme.md +80 -0
- package/runtimes/exceptions/index.ts +2 -0
- package/runtimes/exceptions/runtime-module-error.ts +9 -0
- package/runtimes/exceptions/runtime-not-defined.ts +5 -0
- package/runtimes/index.ts +3 -0
- package/runtimes/runtime-definition.ts +32 -0
- package/runtimes/runtime-manifest.ts +12 -0
- package/runtimes/runtimes.ts +34 -0
- package/slots/index.ts +2 -0
- package/slots/registry.ts +36 -0
- package/slots/slot.ts +11 -0
- package/types/asset.d.ts +29 -0
- package/types/style.d.ts +42 -0
- package/types.ts +7 -0
- package/utils/async-for-each.ts +10 -0
- 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,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,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>;
|
package/types/asset.d.ts
ADDED
|
@@ -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
|
+
}
|