UNPKG

10.4 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 });
6exports.OperationLoader = void 0;
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 // do nothing
84 }
85 return {
86 // @ts-expect-error
87 Processor,
88 // @ts-expect-error
89 Schema,
90 API,
91 };
92 }
93 loadReader(name, assetIds) {
94 const codePath = this.findOrThrow(name, assetIds);
95 if (this.isLegacyReader(codePath)) {
96 return this.shimLegacyReader(name, codePath);
97 }
98 let Fetcher;
99 let Slicer;
100 let Schema;
101 let API;
102 try {
103 Slicer = this.require(codePath, 'slicer');
104 }
105 catch (err) {
106 throw new Error(`Failure loading slicer from module: ${name}, error: ${utils_1.parseError(err, true)}`);
107 }
108 try {
109 Fetcher = this.require(codePath, 'fetcher');
110 }
111 catch (err) {
112 throw new Error(`Failure loading fetcher from module: ${name}, error: ${utils_1.parseError(err, true)}`);
113 }
114 try {
115 Schema = this.require(codePath, 'schema');
116 }
117 catch (err) {
118 throw new Error(`Failure loading schema from module: ${name}, error: ${utils_1.parseError(err, true)}`);
119 }
120 try {
121 API = this.require(codePath, 'api');
122 }
123 catch (err) {
124 // do nothing
125 }
126 return {
127 // @ts-expect-error
128 Slicer,
129 // @ts-expect-error
130 Fetcher,
131 // @ts-expect-error
132 Schema,
133 API,
134 };
135 }
136 loadAPI(name, assetIds) {
137 const [apiName] = name.split(':');
138 const codePath = this.findOrThrow(apiName, assetIds);
139 let API;
140 try {
141 API = this.require(codePath, 'api');
142 }
143 catch (err) {
144 // do nothing
145 }
146 let Observer;
147 try {
148 Observer = this.require(codePath, 'observer');
149 }
150 catch (err) {
151 // do nothing
152 }
153 let Schema;
154 try {
155 Schema = this.require(codePath, 'schema');
156 }
157 catch (err) {
158 throw new Error(`Failure loading schema from module: ${apiName}, error: ${utils_1.parseError(err, true)}`);
159 }
160 if (Observer == null && API == null) {
161 throw new Error(`Failure to load api module: ${apiName}, requires at least an api.js or observer.js`);
162 }
163 else if (Observer != null && API != null) {
164 throw new Error(`Failure to load api module: ${apiName}, required only one api.js or observer.js`);
165 }
166 const type = API != null ? 'api' : 'observer';
167 return {
168 // @ts-expect-error
169 API: API || Observer,
170 // @ts-expect-error
171 Schema,
172 type,
173 };
174 }
175 findOrThrow(name, assetIds) {
176 this.verifyOpName(name);
177 const codePath = this.find(name, assetIds);
178 if (!codePath) {
179 throw new Error(`Unable to find module for operation: ${name}`);
180 }
181 return codePath;
182 }
183 isLegacyReader(codePath) {
184 return !this.fileExists(codePath, 'fetcher') && !this.fileExists(codePath, 'slicer');
185 }
186 shimLegacyReader(name, codePath) {
187 try {
188 return shims_1.readerShim(this.require(codePath));
189 }
190 catch (err) {
191 throw new Error(`Failure loading reader: ${name}, error: ${utils_1.parseError(err, true)}`);
192 }
193 }
194 isLegacyProcessor(codePath) {
195 return !this.fileExists(codePath, 'processor');
196 }
197 shimLegacyProcessor(name, codePath) {
198 try {
199 return shims_1.processorShim(this.require(codePath));
200 }
201 catch (err) {
202 throw new Error(`Failure loading processor: ${name}, error: ${utils_1.parseError(err, true)}`);
203 }
204 }
205 fileExists(dir, name) {
206 const filePaths = this.availableExtensions.map((ext) => path_1.default.format({
207 dir,
208 name,
209 ext,
210 }));
211 return filePaths.some((filePath) => fs_1.default.existsSync(filePath));
212 }
213 require(dir, name) {
214 const filePaths = name
215 ? this.availableExtensions.map((ext) => path_1.default.format({
216 dir,
217 name,
218 ext,
219 }))
220 : [dir];
221 let err;
222 for (const filePath of filePaths) {
223 try {
224 const mod = require(filePath);
225 return mod.default || mod;
226 }
227 catch (_err) {
228 err = _err;
229 }
230 }
231 if (err) {
232 throw err;
233 }
234 else {
235 throw new Error(`Unable to find module at paths: ${filePaths.join(', ')}`);
236 }
237 }
238 resolvePath(filePath) {
239 if (!filePath)
240 return null;
241 if (fs_1.default.existsSync(filePath))
242 return filePath;
243 try {
244 return require.resolve(filePath);
245 }
246 catch (err) {
247 for (const ext of this.availableExtensions) {
248 try {
249 return path_1.default.dirname(require.resolve(path_1.default.format({
250 dir: filePath,
251 name: 'schema',
252 ext,
253 })));
254 }
255 catch (_err) {
256 // do nothing
257 }
258 }
259 return null;
260 }
261 }
262 verifyOpName(name) {
263 if (!utils_1.isString(name)) {
264 throw new TypeError('Please verify that the "_op" name exists for each operation');
265 }
266 }
267 findCode(name) {
268 let filePath = null;
269 const codeNames = this.availableExtensions.map((ext) => path_1.default.format({
270 name,
271 ext,
272 }));
273 const allowedNames = utils_1.uniq([name, ...codeNames]);
274 const invalid = ['node_modules', ...ignoreDirectories()];
275 const findCode = (rootDir) => {
276 const fileNames = fs_1.default.readdirSync(rootDir)
277 .filter((fileName) => !invalid.includes(fileName));
278 for (const fileName of fileNames) {
279 if (filePath)
280 break;
281 const nextPath = path_1.default.join(rootDir, fileName);
282 // if name is same as fileName/dir then we found it
283 if (allowedNames.includes(fileName)) {
284 filePath = this.resolvePath(nextPath);
285 }
286 if (!filePath && this.isDir(nextPath)) {
287 filePath = findCode(nextPath);
288 }
289 }
290 return filePath;
291 };
292 return findCode;
293 }
294 isDir(filePath) {
295 return fs_1.default.statSync(filePath).isDirectory();
296 }
297 getBuiltinDir() {
298 if (this.availableExtensions.includes('.ts')) {
299 return path_1.default.join(__dirname, 'builtin');
300 }
301 return path_1.default.join(__dirname, '..', '..', 'dist', 'src', 'builtin');
302 }
303}
304exports.OperationLoader = OperationLoader;
305function availableExtensions() {
306 // populated by teraslice Jest configuration
307 // @ts-expect-error
308 return global.availableExtensions ? global.availableExtensions : ['.js'];
309}
310function ignoreDirectories() {
311 // populated by teraslice Jest configuration
312 // @ts-expect-error
313 return global.ignoreDirectories || [];
314}
315//# sourceMappingURL=operation-loader.js.map
\No newline at end of file