@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,5 @@
1
+ /**
2
+ * asynchronously iterate an array.
3
+ * :TODO improve function singature
4
+ */
5
+ export declare function asyncForEach(array: any[], callback: any): Promise<void>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.asyncForEach = asyncForEach;
13
+ /**
14
+ * asynchronously iterate an array.
15
+ * :TODO improve function singature
16
+ */
17
+ function asyncForEach(array, callback) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ for (let index = 0; index < array.length; index += 1) {
20
+ // eslint-disable-next-line no-await-in-loop
21
+ yield callback(array[index], index, array);
22
+ }
23
+ });
24
+ }
25
+ //# sourceMappingURL=async-for-each.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-for-each.js","sourceRoot":"","sources":["../../utils/async-for-each.ts"],"names":[],"mappings":";;;;;;;;;;;AAIA,oCAKC;AATD;;;GAGG;AACH,SAAsB,YAAY,CAAC,KAAY,EAAE,QAAa;;QAC5D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACrD,4CAA4C;YAC5C,MAAM,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;CAAA"}
@@ -0,0 +1 @@
1
+ export { asyncForEach } from './async-for-each';
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.asyncForEach = void 0;
4
+ var async_for_each_1 = require("./async-for-each");
5
+ Object.defineProperty(exports, "asyncForEach", { enumerable: true, get: function () { return async_for_each_1.asyncForEach; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../utils/index.ts"],"names":[],"mappings":";;;AAAA,mDAAgD;AAAvC,8GAAA,YAAY,OAAA"}
@@ -0,0 +1 @@
1
+ export class ExtensionInstantiationException extends Error {}
@@ -0,0 +1,28 @@
1
+ import { Extension } from '../extension/extension';
2
+
3
+ export default class ExtensionLoadError extends Error {
4
+ constructor(
5
+ /**
6
+ * failed extension
7
+ */
8
+ private extension: Extension,
9
+
10
+ /**
11
+ * extension error
12
+ */
13
+ private originalError: Error,
14
+
15
+ /**
16
+ * extension formatted / handled error message
17
+ */
18
+ private msg?: string
19
+ ) {
20
+ super();
21
+ }
22
+
23
+ toString() {
24
+ return `failed to load extension: ${this.extension.name} with error:
25
+
26
+ ${this.msg || this.originalError.stack}`;
27
+ }
28
+ }
@@ -0,0 +1,24 @@
1
+ import { Extension } from '../extension/extension';
2
+ import { HarmonyError } from './harmony-error';
3
+
4
+ export default class ExtensionPotentialCircular extends HarmonyError {
5
+ constructor(
6
+ /**
7
+ * failed extension
8
+ */
9
+ private extension: Extension,
10
+
11
+ /**
12
+ * valid extensions dependencies
13
+ */
14
+ private validDeps: Extension[]
15
+ ) {
16
+ super();
17
+ }
18
+
19
+ toString() {
20
+ return `Failed to load the dependencies for extension .
21
+ This may result from a wrong import or from circular dependencies in imports.
22
+ The following dependencies succeeded loading:`;
23
+ }
24
+ }
@@ -0,0 +1 @@
1
+ export class HarmonyAlreadyRunning extends Error {}
@@ -0,0 +1 @@
1
+ export class HarmonyError extends Error {}
@@ -0,0 +1 @@
1
+ export class HookNotFound extends Error {}
@@ -0,0 +1,5 @@
1
+ export { default as ExtensionLoadError } from './extension-load-error';
2
+ export { default as ExtensionPotentialCircular } from './extension-potential-circular';
3
+ export { HarmonyAlreadyRunning } from './harmony-already-running';
4
+ export { HookNotFound } from './hook-not-found';
5
+ export { ExtensionInstantiationException } from './extension-init-error';
File without changes
@@ -0,0 +1,8 @@
1
+ import { Extension } from '../index';
2
+
3
+ /**
4
+ * Class extension of type any. this class is indended for use inside Harmony
5
+ * where extension generics type relevance is low.
6
+ */
7
+
8
+ // export class AnyExtension extends Extension {}
@@ -0,0 +1,126 @@
1
+ import { HookNotFound } from '../exceptions';
2
+ import { ExtensionManifest } from "./extension-manifest";
3
+ // :TODO refactor this file asap
4
+
5
+ export type ExtensionOptions = {
6
+ dependencies?: ExtensionManifest[],
7
+ name?: string
8
+ }
9
+
10
+ const map: any = {};
11
+
12
+ /**
13
+ * decorator for an Harmony extension.
14
+ */
15
+ export function ExtensionDecorator({ name, dependencies }: ExtensionOptions = {}) {
16
+ function classDecorator<T extends {new(...args:any[]): {}}>(constructor:T) {
17
+ Reflect.defineMetadata('harmony:name', name || constructor.name, constructor);
18
+ Reflect.defineMetadata('harmony:dependencies', calculateDependnecies(constructor, dependencies), constructor)
19
+ }
20
+
21
+ return classDecorator;
22
+ }
23
+
24
+ export function provider() {
25
+ return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
26
+ const keys = Reflect.getMetadata('design:paramtypes', descriptor);
27
+ }
28
+ }
29
+
30
+ // @hack todo: must be defined and assigned from a single location
31
+ function providerFn(classExtension: any) {
32
+ return classExtension.provide ? classExtension.provide : classExtension.provider;
33
+ }
34
+
35
+ function calculateDependnecies(classExtension: any, deps?: ExtensionManifest[]): ExtensionManifest[] {
36
+ function fromMetadata() {
37
+ const provider = providerFn(classExtension)
38
+ if (provider) {
39
+ // // TODO: check why Reflect.getMetadataKeys(provider) is empty and how to access method param types.
40
+ // console.log(Reflect.getMetadataKeys(classExtension.provide))
41
+ return [];
42
+ }
43
+
44
+ return Reflect.getMetadata('design:paramtypes', classExtension);
45
+ }
46
+
47
+ const dependnecies = deps ? deps : fromMetadata() || [];
48
+ const hookDeps = classExtension.__hookDeps ? classExtension.__hookDeps : [];
49
+ return dependnecies.concat(hookDeps) || [];
50
+ }
51
+
52
+ // :TODO refactor this asap to handle harmony objects properly
53
+ export function register(extension: ExtensionManifest, name?: string) {
54
+ return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
55
+ // if (!target.constructor.__hookDeps) Reflect.defineMetadata('harmony:subscriptions', [extension], target.constructor);
56
+ // else target.constructor.__hookDeps.push(extension);
57
+
58
+ const extensionName = Reflect.getMetadata('harmony:name', extension);
59
+ if (!map[extensionName]) {
60
+ map[extensionName] = {};
61
+ }
62
+
63
+ const hook = map[extensionName][name || propertyKey];
64
+ // if (!hook) throw new HookNotFound();
65
+ if (!hook) return;
66
+ hook.register(target[propertyKey]);
67
+ }
68
+ }
69
+
70
+ export function createHook() {
71
+ const randomId = Math.random().toString(36).substring(2);
72
+ map[randomId] = HookRegistry.create();
73
+ const decorator = function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
74
+ const registry = map[randomId];
75
+ registry.register(descriptor.value);
76
+ }
77
+
78
+ decorator.hash = randomId;
79
+
80
+ return decorator;
81
+ }
82
+
83
+ export function hook(name?: string) {
84
+ return function(target: any, propertyKey: string) {
85
+ let instance = HookRegistry.create();
86
+ const extensionName = Reflect.getMetadata('harmony:name', target.constructor);
87
+ const hookName = name || propertyKey;
88
+
89
+ if (!map[extensionName]) map[extensionName] = {[hookName]: instance};
90
+ else map[extensionName][hookName] = instance;
91
+
92
+ Object.defineProperty(target, propertyKey, {
93
+ get: () => {
94
+ return instance;
95
+ },
96
+ set: (value) => {
97
+ instance = value;
98
+ }
99
+ });
100
+ }
101
+ }
102
+
103
+ export class HookRegistry<T> {
104
+ constructor(
105
+ private fillers: T[],
106
+ readonly hash?: string
107
+ ) {}
108
+
109
+ register(filler: T) {
110
+ this.fillers.push(filler);
111
+ }
112
+
113
+ list() {
114
+ // return map[this.name][name] || [];
115
+ return this.fillers;
116
+ }
117
+
118
+ static of<T>(hook: any): HookRegistry<T> {
119
+ return map[hook.hash];
120
+ }
121
+
122
+ // hack due to https://github.com/microsoft/TypeScript/issues/4881
123
+ static create<T>() {
124
+ return new HookRegistry<T>([]);
125
+ }
126
+ }
@@ -0,0 +1,51 @@
1
+ import { ProviderFn } from '../types';
2
+ import { Slot, SlotProvider } from '../slots';
3
+
4
+ export type ExtensionManifest = {
5
+ /**
6
+ * extension name.
7
+ */
8
+ name: string;
9
+
10
+ /**
11
+ * extension unique ID.
12
+ */
13
+ id?: string;
14
+
15
+ /**
16
+ * version of the extension
17
+ */
18
+ // version: string;
19
+
20
+ /**
21
+ * array of extension dependencies.
22
+ * these other extensions will be installed and resolved prior to this extension activation.
23
+ */
24
+ dependencies?: ExtensionManifest[];
25
+
26
+ /**
27
+ * reference to the extension factory function.
28
+ */
29
+ provider?: ProviderFn;
30
+
31
+ /**
32
+ *
33
+ * default config of the extension.
34
+ */
35
+ defaultConfig?: object;
36
+
37
+ /**
38
+ * alias to provider.
39
+ */
40
+ provide?: ProviderFn;
41
+
42
+ /**
43
+ * array of slots the extension is exposing.
44
+ */
45
+ slots?: SlotProvider<unknown>[],
46
+
47
+ /**
48
+ * any further keys which might be expected by other extensions.
49
+ */
50
+ [key: string]: any;
51
+ }
@@ -0,0 +1,142 @@
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
+ getRuntimes() {
88
+ return this.manifest.getRuntimes();
89
+ }
90
+
91
+ getSlots(extensionRuntime: any) {
92
+ if (extensionRuntime.slots && extensionRuntime.slots.length) {
93
+ return extensionRuntime.slots;
94
+ }
95
+
96
+ return this.manifest.slots || [];
97
+ }
98
+
99
+ getConfig(context: Harmony, extensionRuntime: any) {
100
+ const defaultConfig = extensionRuntime.defaultConfig || this.manifest.defaultConfig || {};
101
+ const config = context.config.get(this.name) || {};
102
+ return Object.assign({}, defaultConfig, config);
103
+ }
104
+
105
+ /**
106
+ * initiate Harmony in run-time.
107
+ */
108
+ async __run(dependencies: any[], context: Harmony, runtime: RuntimeDefinition) {
109
+ const name = this.name;
110
+ context.initExtension(name);
111
+ const extensionRuntime = this.getRuntime(runtime);
112
+
113
+ if (!extensionRuntime) {
114
+ return undefined;
115
+ }
116
+
117
+ // @ts-ignore
118
+ const registries = this.buildSlotRegistries(this.getSlots(extensionRuntime), context);
119
+ const config = this.getConfig(context, extensionRuntime);
120
+
121
+ if (!this.loaded) {
122
+ if (extensionRuntime.provider) this._instance = await extensionRuntime.provider(dependencies, config, registries, context);
123
+ else {
124
+ try {
125
+ // @ts-ignore
126
+ this._instance = new extensionRuntime.manifest(...dependencies);
127
+ } catch(err) {
128
+ throw new ExtensionInstantiationException(err instanceof Error ? err.toString() : String(err));
129
+ }
130
+ };
131
+ // @ts-ignore adding the extension ID to the instance.
132
+ // this._instance.id = this.manifest.name;
133
+ // @ts-ignore adding the extension ID to the instance.
134
+ // this._instance.config = config;
135
+ this._loaded = true;
136
+ return this._instance;
137
+ }
138
+
139
+ context.endExtension();
140
+ return Promise.resolve(this.instance);
141
+ }
142
+ }
@@ -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,165 @@
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
+ export type DependencyGraphOptions = {
9
+ getName?: (manifest: any) => string;
10
+ };
11
+
12
+ function getName(manifest: any) {
13
+ return Reflect.getMetadata('harmony:name', manifest) || manifest.id || manifest.name;
14
+ }
15
+
16
+ export type Edge = {
17
+ type: string,
18
+ runtime?: string
19
+ };
20
+
21
+ export default class DependencyGraph extends Graph<Extension, Edge> {
22
+ private cache = new Map<string, Extension>();
23
+
24
+ getRuntimeDependencies(aspect: Extension, runtime: RuntimeDefinition, options: DependencyGraphOptions = {}): Extension[] {
25
+ const dependencies = this.successors(aspect.name);
26
+ const runtimeDeps = this.successors(aspect.name, (edge) => {
27
+ if (!edge.runtime) return false;
28
+ return edge.runtime === runtime.name;
29
+ });
30
+ const runtimeManifest = aspect.getRuntime(runtime);
31
+ if (!runtimeManifest) return Array.from(dependencies.values());
32
+
33
+ if (runtimeDeps && runtimeDeps.size) return this.sortDeps(runtimeManifest.dependencies, Array.from(runtimeDeps.values()), options);
34
+ return this.sortDeps(runtimeManifest.dependencies, Array.from(dependencies.values()), options);
35
+ }
36
+
37
+ private sortDeps(originalDependencies: any[], targetDependencies: any[], options: DependencyGraphOptions = {}) {
38
+ const _originalDependencies = options.getName ? originalDependencies?.map((aspect) => {
39
+ if (!options.getName) return aspect;
40
+ aspect.id = options.getName(aspect);
41
+ return aspect;
42
+ }) || [] : originalDependencies;
43
+
44
+ return targetDependencies.sort((a, b) => {
45
+ return _originalDependencies.findIndex(item => item.id === a.id) - _originalDependencies.findIndex(item => item.id === b.id);
46
+ });
47
+ }
48
+
49
+ byExecutionOrder() {
50
+ return this.toposort(true);
51
+ }
52
+
53
+ private async enrichRuntimeExtension(id: string, aspect: Extension, runtime: RuntimeDefinition, runtimes: Runtimes, requireFn: RequireFn, options: DependencyGraphOptions = {}) {
54
+ await requireFn(aspect, runtime);
55
+ const runtimeManifest = aspect.getRuntime(runtime)
56
+ if (!runtimeManifest) return;
57
+ const deps = runtimeManifest.dependencies;
58
+ if (!deps) return;
59
+ const promises = deps.map(async (dep: any) => {
60
+ const depId = options.getName ? options.getName(dep): dep.id;
61
+ if (!this.hasNode(depId)) {
62
+ this.add(dep);
63
+ if (dep.declareRuntime) {
64
+ runtimes.add(dep.declareRuntime);
65
+ }
66
+
67
+ const node = this.get(depId);
68
+ if (!node) return;
69
+ await requireFn(node, runtime);
70
+ await this.enrichRuntimeExtension(depId, this.get(depId), runtime, runtimes, requireFn);
71
+ }
72
+
73
+ this.setEdge(id, depId, {
74
+ runtime: runtime.name,
75
+ type: 'runtime-dependency'
76
+ });
77
+ });
78
+
79
+ return Promise.all(promises);
80
+ }
81
+
82
+ async enrichRuntime(runtime: RuntimeDefinition, runtimes: Runtimes, requireFn: RequireFn, options: DependencyGraphOptions = {}) {
83
+ const promises = Array.from(this.nodes.entries()).map(async ([id, aspect]) => {
84
+ return this.enrichRuntimeExtension(id, aspect, runtime, runtimes, requireFn, options);
85
+ });
86
+
87
+ return Promise.all(promises);
88
+ }
89
+
90
+ add(manifest: ExtensionManifest) {
91
+ const { vertices, edges } = fromExtension(manifest);
92
+ this.setNodes(vertices);
93
+ this.setEdges(edges);
94
+
95
+ return this;
96
+ }
97
+
98
+ load(extensions: ExtensionManifest[]) {
99
+ const newExtensions = extensions.filter((extension) => {
100
+ if (!extension.id) return false;
101
+ return !this.get(extension.id);
102
+ });
103
+ const { vertices, edges } = fromExtensions(newExtensions);
104
+ // Only set new vertices
105
+ this.setNodes(vertices, false); // false because we don't want to override already-loaded extensions
106
+ this.setEdges(edges);
107
+
108
+ return this;
109
+ }
110
+
111
+ // :TODO refactor this asap
112
+ getExtension(manifest: ExtensionManifest) {
113
+ const id = getName(manifest);
114
+ const cachedVertex = this.cache.get(id);
115
+ if (cachedVertex) return cachedVertex;
116
+
117
+ const res = this.node(id);
118
+ if (res) {
119
+ this.cache.set(res.name, res);
120
+ return res;
121
+ }
122
+
123
+ return null;
124
+ }
125
+
126
+ get extensions(): ExtensionManifest[] {
127
+ return Array.from(this.nodes.values());
128
+ }
129
+
130
+ get aspects() {
131
+ return this.extensions;
132
+ }
133
+
134
+ get(id: string): any {
135
+ const cachedVertex = this.cache.get(id);
136
+ if (cachedVertex) return cachedVertex;
137
+
138
+ const res = this.node(id);
139
+ if (res) {
140
+ this.cache.set(res.name, res);
141
+ return res;
142
+ }
143
+
144
+ return null;
145
+ }
146
+
147
+ /**
148
+ * build Harmony from a single extension.
149
+ */
150
+ static fromRoot(extension: ExtensionManifest) {
151
+ const { vertices, edges } = fromExtension(extension);
152
+
153
+ return new DependencyGraph(vertices, edges);
154
+ }
155
+
156
+ /**
157
+ * build Harmony from set of extensions
158
+ */
159
+ static from(extensions: ExtensionManifest[], options: DependencyGraphOptions = {}) {
160
+ const { vertices, edges } = fromExtensions(extensions, options);
161
+
162
+ return new DependencyGraph(vertices, edges);
163
+ }
164
+ }
165
+