UNPKG

20.9 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6/* tslint:disable:variable-name */
7const fs_1 = __importDefault(require("fs"));
8const path_1 = __importDefault(require("path"));
9const utils_1 = require("@terascope/utils");
10const shims_1 = require("./operations/shims");
11class OperationLoader {
12 constructor(options = {}) {
13 this.options = utils_1.cloneDeep(options);
14 this.availableExtensions = availableExtensions();
15 }
16 find(name, assetIds) {
17 let filePath = null;
18 const findCodeFn = this.findCode(name);
19 const findCodeByConvention = (basePath, subfolders) => {
20 if (!basePath)
21 return;
22 if (!fs_1.default.existsSync(basePath))
23 return;
24 if (!subfolders || !subfolders.length)
25 return;
26 subfolders.forEach((folder) => {
27 const folderPath = path_1.default.join(basePath, folder);
28 if (!filePath && fs_1.default.existsSync(folderPath)) {
29 filePath = findCodeFn(folderPath);
30 }
31 });
32 };
33 findCodeByConvention(this.options.assetPath, assetIds);
34 if (!filePath) {
35 findCodeByConvention(this.getBuiltinDir(), ['.']);
36 }
37 if (!filePath) {
38 findCodeByConvention(this.options.terasliceOpPath, ['readers', 'processors']);
39 }
40 if (!filePath) {
41 filePath = this.resolvePath(name);
42 }
43 return filePath;
44 }
45 /**
46 * Load any LegacyOperation
47 * DEPRECATED to accommadate for new Job APIs,
48 * use loadReader, or loadProcessor
49 */
50 load(name, assetIds) {
51 const codePath = this.findOrThrow(name, assetIds);
52 try {
53 return this.require(codePath);
54 }
55 catch (err) {
56 throw new Error(`Failure loading module: ${name}, error: ${utils_1.parseError(err, true)}`);
57 }
58 }
59 loadProcessor(name, assetIds) {
60 const codePath = this.findOrThrow(name, assetIds);
61 if (this.isLegacyProcessor(codePath)) {
62 return this.shimLegacyProcessor(name, codePath);
63 }
64 let Processor;
65 let Schema;
66 let API;
67 try {
68 Processor = this.require(codePath, 'processor');
69 }
70 catch (err) {
71 throw new Error(`Failure loading processor from module: ${name}, error: ${utils_1.parseError(err, true)}`);
72 }
73 try {
74 Schema = this.require(codePath, 'schema');
75 }
76 catch (err) {
77 throw new Error(`Failure loading schema from module: ${name}, error: ${utils_1.parseError(err, true)}`);
78 }
79 try {
80 API = this.require(codePath, 'api');
81 }
82 catch (err) {
83 }
84 return {
85 // @ts-ignore
86 Processor,
87 // @ts-ignore
88 Schema,
89 API,
90 };
91 }
92 loadReader(name, assetIds) {
93 const codePath = this.findOrThrow(name, assetIds);
94 if (this.isLegacyReader(codePath)) {
95 return this.shimLegacyReader(name, codePath);
96 }
97 let Fetcher;
98 let Slicer;
99 let Schema;
100 let API;
101 try {
102 Slicer = this.require(codePath, 'slicer');
103 }
104 catch (err) {
105 throw new Error(`Failure loading slicer from module: ${name}, error: ${utils_1.parseError(err, true)}`);
106 }
107 try {
108 Fetcher = this.require(codePath, 'fetcher');
109 }
110 catch (err) {
111 throw new Error(`Failure loading fetcher from module: ${name}, error: ${utils_1.parseError(err, true)}`);
112 }
113 try {
114 Schema = this.require(codePath, 'schema');
115 }
116 catch (err) {
117 throw new Error(`Failure loading schema from module: ${name}, error: ${utils_1.parseError(err, true)}`);
118 }
119 try {
120 API = this.require(codePath, 'api');
121 }
122 catch (err) {
123 }
124 return {
125 // @ts-ignore
126 Slicer,
127 // @ts-ignore
128 Fetcher,
129 // @ts-ignore
130 Schema,
131 API,
132 };
133 }
134 loadAPI(name, assetIds) {
135 const [apiName] = name.split(':');
136 const codePath = this.findOrThrow(apiName, assetIds);
137 let API;
138 try {
139 API = this.require(codePath, 'api');
140 }
141 catch (err) {
142 }
143 let Observer;
144 try {
145 Observer = this.require(codePath, 'observer');
146 }
147 catch (err) {
148 }
149 let Schema;
150 try {
151 Schema = this.require(codePath, 'schema');
152 }
153 catch (err) {
154 throw new Error(`Failure loading schema from module: ${apiName}, error: ${utils_1.parseError(err, true)}`);
155 }
156 if (Observer == null && API == null) {
157 throw new Error(`Failure to load api module: ${apiName}, requires at least an api.js or observer.js`);
158 }
159 else if (Observer != null && API != null) {
160 throw new Error(`Failure to load api module: ${apiName}, required only one api.js or observer.js`);
161 }
162 const type = API != null ? 'api' : 'observer';
163 return {
164 // @ts-ignore
165 API: API || Observer,
166 // @ts-ignore
167 Schema,
168 type,
169 };
170 }
171 findOrThrow(name, assetIds) {
172 this.verifyOpName(name);
173 const codePath = this.find(name, assetIds);
174 if (!codePath) {
175 throw new Error(`Unable to find module for operation: ${name}`);
176 }
177 return codePath;
178 }
179 isLegacyReader(codePath) {
180 return !this.fileExists(codePath, 'fetcher') && !this.fileExists(codePath, 'slicer');
181 }
182 shimLegacyReader(name, codePath) {
183 try {
184 return shims_1.readerShim(this.require(codePath));
185 }
186 catch (err) {
187 throw new Error(`Failure loading reader: ${name}, error: ${utils_1.parseError(err, true)}`);
188 }
189 }
190 isLegacyProcessor(codePath) {
191 return !this.fileExists(codePath, 'processor');
192 }
193 shimLegacyProcessor(name, codePath) {
194 try {
195 return shims_1.processorShim(this.require(codePath));
196 }
197 catch (err) {
198 throw new Error(`Failure loading processor: ${name}, error: ${utils_1.parseError(err, true)}`);
199 }
200 }
201 fileExists(dir, name) {
202 const filePaths = this.availableExtensions.map((ext) => {
203 return path_1.default.format({
204 dir,
205 name,
206 ext,
207 });
208 });
209 return filePaths.some((filePath) => fs_1.default.existsSync(filePath));
210 }
211 require(dir, name) {
212 const filePaths = name ? this.availableExtensions.map((ext) => {
213 return path_1.default.format({
214 dir,
215 name,
216 ext,
217 });
218 }) : [dir];
219 let err;
220 for (const filePath of filePaths) {
221 try {
222 const mod = require(filePath);
223 return mod.default || mod;
224 }
225 catch (_err) {
226 err = _err;
227 }
228 }
229 if (err) {
230 throw err;
231 }
232 else {
233 throw new Error(`Unable to find module at paths: ${filePaths.join(', ')}`);
234 }
235 }
236 resolvePath(filePath) {
237 if (fs_1.default.existsSync(filePath))
238 return filePath;
239 try {
240 return require.resolve(filePath);
241 }
242 catch (err) {
243 return null;
244 }
245 }
246 verifyOpName(name) {
247 if (!utils_1.isString(name)) {
248 throw new TypeError('Please verify that the "_op" name exists for each operation');
249 }
250 }
251 findCode(name) {
252 let filePath = null;
253 const codeNames = this.availableExtensions.map((ext) => {
254 return path_1.default.format({
255 name,
256 ext,
257 });
258 });
259 const allowedNames = utils_1.uniq([name, ...codeNames]);
260 const invalid = [
261 'node_modules',
262 ...ignoreDirectories(),
263 ];
264 const findCode = (rootDir) => {
265 const fileNames = fs_1.default.readdirSync(rootDir)
266 .filter((fileName) => !invalid.includes(fileName));
267 for (const fileName of fileNames) {
268 if (filePath)
269 break;
270 const nextPath = path_1.default.join(rootDir, fileName);
271 // if name is same as fileName/dir then we found it
272 if (allowedNames.includes(fileName)) {
273 filePath = this.resolvePath(nextPath);
274 }
275 if (!filePath && this.isDir(nextPath)) {
276 filePath = findCode(nextPath);
277 }
278 }
279 return filePath;
280 };
281 return findCode;
282 }
283 isDir(filePath) {
284 return fs_1.default.statSync(filePath).isDirectory();
285 }
286 getBuiltinDir() {
287 if (this.availableExtensions.includes('.ts')) {
288 return path_1.default.join(__dirname, 'builtin');
289 }
290 return path_1.default.join(__dirname, '..', 'dist', 'builtin');
291 }
292}
293exports.OperationLoader = OperationLoader;
294function availableExtensions() {
295 // populated by teraslice Jest configuration
296 // @ts-ignore
297 return global.availableExtensions ? global.availableExtensions : ['.js'];
298}
299function ignoreDirectories() {
300 // populated by teraslice Jest configuration
301 // @ts-ignore
302 return global.ignoreDirectories || [];
303}
304//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9uLWxvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9vcGVyYXRpb24tbG9hZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsa0NBQWtDO0FBQ2xDLDRDQUFvQjtBQUNwQixnREFBd0I7QUFDeEIsNENBQXlFO0FBYXpFLDhDQUErRDtBQVMvRCxNQUFhLGVBQWU7SUFJeEIsWUFBWSxVQUF5QixFQUFFO1FBQ25DLElBQUksQ0FBQyxPQUFPLEdBQUcsaUJBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsbUJBQW1CLEdBQUcsbUJBQW1CLEVBQUUsQ0FBQztJQUNyRCxDQUFDO0lBRUQsSUFBSSxDQUFDLElBQVksRUFBRSxRQUFtQjtRQUNsQyxJQUFJLFFBQVEsR0FBa0IsSUFBSSxDQUFDO1FBQ25DLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFdkMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLFFBQWlCLEVBQUUsVUFBcUIsRUFBRSxFQUFFO1lBQ3RFLElBQUksQ0FBQyxRQUFRO2dCQUFFLE9BQU87WUFDdEIsSUFBSSxDQUFDLFlBQUUsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDO2dCQUFFLE9BQU87WUFDckMsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNO2dCQUFFLE9BQU87WUFFOUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQWMsRUFBRSxFQUFFO2dCQUNsQyxNQUFNLFVBQVUsR0FBRyxjQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDL0MsSUFBSSxDQUFDLFFBQVEsSUFBSSxZQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxFQUFFO29CQUN4QyxRQUFRLEdBQUcsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2lCQUNyQztZQUNMLENBQUMsQ0FBQyxDQUFD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
\No newline at end of file