@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,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,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,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
|
+
|