UNPKG

4.11 kBJavaScriptView Raw
1'use strict';
2
3const debug = require('debug')('tarima:compile');
4
5const path = require('path');
6
7const _worker = require('./_worker');
8const support = require('../../lib/support');
9
10module.exports = (context, files, cb) => {
11 const tasks = [];
12
13 const dispatch = context.dispatch;
14 const copy = context.copy;
15 const cache = context.cache;
16 const match = context.match;
17 const options = context.opts;
18
19 if (!_worker.shared) {
20 _worker.shared = _worker.init(options);
21 }
22
23 const onDelete = context.emit.bind(null, 'delete');
24
25 const seen = {};
26 const unknown = [];
27
28 const watchers = !Array.isArray(options.watching)
29 ? [options.watching]
30 : options.watching;
31
32 const watching = file => {
33 for (let i = 0, c = watchers.length; i < c; i += 1) {
34 if (file.indexOf(watchers[i]) === 0) {
35 return true;
36 }
37 }
38 };
39
40 debug('Processing %s files', files.length);
41
42 function append(src, next) {
43 const entry = cache.get(src);
44
45 if (entry.dirty === false) {
46 delete entry.dirty;
47 }
48
49 if (entry.dirty) {
50 next(src);
51 }
52 }
53
54 function compile(src) {
55 const entry = cache.get(src) || {};
56
57 // override
58 entry.main = true;
59
60 if (entry.deleted) {
61 context.dist({
62 src,
63 type: 'delete',
64 dest: entry.dest,
65 });
66
67 cache.rm(src);
68 onDelete(src, entry);
69 } else {
70 tasks.push({ src });
71 }
72 }
73
74 function dest(id, ext) {
75 return path.relative(options.cwd, path.join(options.output, ext
76 ? id.replace(/\.[\w.]+$/, `.${ext}`)
77 : id));
78 }
79
80 files.forEach(src => {
81 // skip early
82 if (watching(src) || copy(src)) {
83 debug('WATCH %s', src);
84 return;
85 }
86
87 const entry = cache.get(src);
88
89 if (!entry) {
90 // required reference
91 cache.set(src, { dirty: true });
92 }
93
94 if (!support.isSupported(src)) {
95 return append(src, id => {
96 if (match(src)) {
97 debug('OK %s', id);
98
99 seen[id] = 1;
100 unknown.push(id);
101 } else {
102 debug('SKIP %s', id);
103 }
104 });
105 }
106
107 if (!seen[src]) {
108 seen[src] = true;
109
110 if (match(src)) {
111 debug('ADD %s', src);
112 append(src, compile);
113 } else {
114 debug('SKIP %s', src);
115 }
116 } else {
117 debug('SEEN %s', src);
118 }
119 });
120
121 const _subtasks = [];
122 const _files = [];
123
124 if (unknown.length) {
125 dispatch(options, unknown.map(file => {
126 const _target = {
127 src: file,
128 dest: dest(file),
129 };
130
131 return _target;
132 }), (result, next) => {
133 Array.prototype.push.apply(tasks, result.map(x => {
134 if (typeof options.rename === 'function') {
135 options.rename(x);
136 }
137 return x;
138 }));
139
140 _subtasks.push(next((err, _result) => {
141 if (!err) {
142 Array.prototype.push.apply(_files, _result.map(x => x.dest));
143 }
144 }));
145 });
146 }
147
148 function _end(err, output) {
149 cb(err, {
150 files,
151 output,
152 cache: cache.all(),
153 input: Object.keys(seen),
154 });
155 }
156
157 Promise.all(_subtasks)
158 .then(() => {
159 return tasks.map(task => () => new Promise((resolve, reject) => {
160 _worker.run(task, options, (err, result, caching) => {
161 if (err) {
162 reject(err);
163 } else {
164 cache.set(task.src, caching);
165 cache.set(task.src, 'dirty', false);
166
167 (caching.deps || []).forEach(dep => {
168 const parent = cache.get(dep) || {};
169 const deps = parent.deps || [];
170
171 cache.set(dep, 'dirty', false);
172
173 if (deps.indexOf(task.src) === -1) {
174 deps.push(task.src);
175 cache.set(dep, 'deps', deps);
176 }
177 });
178
179 result.forEach(x => {
180 if (_files.indexOf(x) === -1) {
181 _files.push(x);
182 }
183 });
184
185 resolve();
186 }
187 });
188 }))
189 .reduce((prev, cur) => prev.then(() => cur()), Promise.resolve());
190 })
191 .then(() => _end(null, _files)).catch(e => _end(e, _files));
192};