1 | import { contains } from './array.js';
|
2 | import { pickShallow } from './object.js';
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 | export function factory(name, dependencies, create, meta) {
|
29 | function assertAndCreate(scope) {
|
30 |
|
31 |
|
32 |
|
33 | var deps = pickShallow(scope, dependencies.map(stripOptionalNotation));
|
34 | assertDependencies(name, dependencies, scope);
|
35 | return create(deps);
|
36 | }
|
37 |
|
38 | assertAndCreate.isFactory = true;
|
39 | assertAndCreate.fn = name;
|
40 | assertAndCreate.dependencies = dependencies.slice().sort();
|
41 |
|
42 | if (meta) {
|
43 | assertAndCreate.meta = meta;
|
44 | }
|
45 |
|
46 | return assertAndCreate;
|
47 | }
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 | export function sortFactories(factories) {
|
56 | var factoriesByName = {};
|
57 | factories.forEach(factory => {
|
58 | factoriesByName[factory.fn] = factory;
|
59 | });
|
60 |
|
61 | function containsDependency(factory, dependency) {
|
62 |
|
63 | if (isFactory(factory)) {
|
64 | if (contains(factory.dependencies, dependency.fn || dependency.name)) {
|
65 | return true;
|
66 | }
|
67 |
|
68 | if (factory.dependencies.some(d => containsDependency(factoriesByName[d], dependency))) {
|
69 | return true;
|
70 | }
|
71 | }
|
72 |
|
73 | return false;
|
74 | }
|
75 |
|
76 | var sorted = [];
|
77 |
|
78 | function addFactory(factory) {
|
79 | var index = 0;
|
80 |
|
81 | while (index < sorted.length && !containsDependency(sorted[index], factory)) {
|
82 | index++;
|
83 | }
|
84 |
|
85 | sorted.splice(index, 0, factory);
|
86 | }
|
87 |
|
88 |
|
89 | factories.filter(isFactory).forEach(addFactory);
|
90 |
|
91 | factories.filter(factory => !isFactory(factory)).forEach(addFactory);
|
92 | return sorted;
|
93 | }
|
94 |
|
95 | export function create(factories) {
|
96 | var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
97 | sortFactories(factories).forEach(factory => factory(scope));
|
98 | return scope;
|
99 | }
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | export function isFactory(obj) {
|
108 | return typeof obj === 'function' && typeof obj.fn === 'string' && Array.isArray(obj.dependencies);
|
109 | }
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 | export function assertDependencies(name, dependencies, scope) {
|
121 | var allDefined = dependencies.filter(dependency => !isOptionalDependency(dependency))
|
122 | .every(dependency => scope[dependency] !== undefined);
|
123 |
|
124 | if (!allDefined) {
|
125 | var missingDependencies = dependencies.filter(dependency => scope[dependency] === undefined);
|
126 |
|
127 | throw new Error("Cannot create function \"".concat(name, "\", ") + "some dependencies are missing: ".concat(missingDependencies.map(d => "\"".concat(d, "\"")).join(', '), "."));
|
128 | }
|
129 | }
|
130 | export function isOptionalDependency(dependency) {
|
131 | return dependency && dependency[0] === '?';
|
132 | }
|
133 | export function stripOptionalNotation(dependency) {
|
134 | return dependency && dependency[0] === '?' ? dependency.slice(1) : dependency;
|
135 | } |
\ | No newline at end of file |