1 | import { contains } from './array';
|
2 | import { pickShallow } from './object';
|
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(function (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(function (d) {
|
69 | return containsDependency(factoriesByName[d], dependency);
|
70 | })) {
|
71 | return true;
|
72 | }
|
73 | }
|
74 |
|
75 | return false;
|
76 | }
|
77 |
|
78 | var sorted = [];
|
79 |
|
80 | function addFactory(factory) {
|
81 | var index = 0;
|
82 |
|
83 | while (index < sorted.length && !containsDependency(sorted[index], factory)) {
|
84 | index++;
|
85 | }
|
86 |
|
87 | sorted.splice(index, 0, factory);
|
88 | }
|
89 |
|
90 |
|
91 | factories.filter(isFactory).forEach(addFactory);
|
92 |
|
93 | factories.filter(function (factory) {
|
94 | return !isFactory(factory);
|
95 | }).forEach(addFactory);
|
96 | return sorted;
|
97 | }
|
98 |
|
99 | export function create(factories) {
|
100 | var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
101 | sortFactories(factories).forEach(function (factory) {
|
102 | return factory(scope);
|
103 | });
|
104 | return scope;
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 | export function isFactory(obj) {
|
114 | return typeof obj === 'function' && typeof obj.fn === 'string' && Array.isArray(obj.dependencies);
|
115 | }
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | export function assertDependencies(name, dependencies, scope) {
|
127 | var allDefined = dependencies.filter(function (dependency) {
|
128 | return !isOptionalDependency(dependency);
|
129 | })
|
130 | .every(function (dependency) {
|
131 | return scope[dependency] !== undefined;
|
132 | });
|
133 |
|
134 | if (!allDefined) {
|
135 | var missingDependencies = dependencies.filter(function (dependency) {
|
136 | return scope[dependency] === undefined;
|
137 | });
|
138 |
|
139 | throw new Error("Cannot create function \"".concat(name, "\", ") + "some dependencies are missing: ".concat(missingDependencies.map(function (d) {
|
140 | return "\"".concat(d, "\"");
|
141 | }).join(', '), "."));
|
142 | }
|
143 | }
|
144 | export function isOptionalDependency(dependency) {
|
145 | return dependency && dependency[0] === '?';
|
146 | }
|
147 | export function stripOptionalNotation(dependency) {
|
148 | return dependency && dependency[0] === '?' ? dependency.slice(1) : dependency;
|
149 | } |
\ | No newline at end of file |