@eggjs/core 6.4.0 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +22 -22
  2. package/dist/commonjs/egg.d.ts +17 -18
  3. package/dist/commonjs/egg.js +11 -11
  4. package/dist/commonjs/lifecycle.d.ts +2 -2
  5. package/dist/commonjs/lifecycle.js +16 -13
  6. package/dist/commonjs/loader/context_loader.js +2 -2
  7. package/dist/commonjs/loader/egg_loader.d.ts +13 -13
  8. package/dist/commonjs/loader/egg_loader.js +77 -62
  9. package/dist/commonjs/loader/file_loader.d.ts +3 -3
  10. package/dist/commonjs/loader/file_loader.js +22 -24
  11. package/dist/commonjs/singleton.d.ts +2 -2
  12. package/dist/commonjs/singleton.js +6 -7
  13. package/dist/commonjs/utils/index.d.ts +2 -2
  14. package/dist/commonjs/utils/index.js +4 -4
  15. package/dist/commonjs/utils/sequencify.d.ts +1 -1
  16. package/dist/commonjs/utils/sequencify.js +18 -13
  17. package/dist/commonjs/utils/timing.js +14 -8
  18. package/dist/esm/egg.d.ts +17 -18
  19. package/dist/esm/egg.js +13 -13
  20. package/dist/esm/lifecycle.d.ts +2 -2
  21. package/dist/esm/lifecycle.js +16 -13
  22. package/dist/esm/loader/context_loader.js +2 -2
  23. package/dist/esm/loader/egg_loader.d.ts +13 -13
  24. package/dist/esm/loader/egg_loader.js +80 -65
  25. package/dist/esm/loader/file_loader.d.ts +3 -3
  26. package/dist/esm/loader/file_loader.js +23 -25
  27. package/dist/esm/singleton.d.ts +2 -2
  28. package/dist/esm/singleton.js +6 -7
  29. package/dist/esm/utils/index.d.ts +2 -2
  30. package/dist/esm/utils/index.js +4 -4
  31. package/dist/esm/utils/sequencify.d.ts +1 -1
  32. package/dist/esm/utils/sequencify.js +18 -13
  33. package/dist/esm/utils/timing.js +14 -8
  34. package/dist/package.json +1 -1
  35. package/package.json +16 -6
  36. package/src/egg.ts +161 -61
  37. package/src/lifecycle.ts +72 -33
  38. package/src/loader/context_loader.ts +9 -7
  39. package/src/loader/egg_loader.ts +445 -183
  40. package/src/loader/file_loader.ts +78 -37
  41. package/src/singleton.ts +64 -26
  42. package/src/utils/index.ts +20 -13
  43. package/src/utils/sequencify.ts +50 -15
  44. package/src/utils/timing.ts +27 -13
@@ -2,10 +2,17 @@ import assert from 'node:assert';
2
2
  import fs from 'node:fs';
3
3
  import { debuglog } from 'node:util';
4
4
  import path from 'node:path';
5
+
5
6
  import globby from 'globby';
6
- import { isClass, isGeneratorFunction, isAsyncFunction, isPrimitive } from 'is-type-of';
7
+ import {
8
+ isClass,
9
+ isGeneratorFunction,
10
+ isAsyncFunction,
11
+ isPrimitive,
12
+ } from 'is-type-of';
7
13
  import { isSupportTypeScript } from '@eggjs/utils';
8
- import utils, { Fun } from '../utils/index.js';
14
+
15
+ import utils, { type Fun } from '../utils/index.js';
9
16
 
10
17
  const debug = debuglog('@eggjs/core/file_loader');
11
18
 
@@ -19,13 +26,17 @@ export enum CaseStyle {
19
26
  }
20
27
 
21
28
  export type CaseStyleFunction = (filepath: string) => string[];
22
- export type FileLoaderInitializer = (exports: unknown, options: { path: string; pathName: string }) => unknown;
29
+ export type FileLoaderInitializer = (
30
+ exports: unknown,
31
+ options: { path: string; pathName: string }
32
+ ) => unknown;
23
33
  export type FileLoaderFilter = (exports: unknown) => boolean;
24
34
 
25
35
  export interface FileLoaderOptions {
26
36
  /** directories to be loaded */
27
37
  directory: string | string[];
28
38
  /** attach the target object from loaded files */
39
+
29
40
  target: Record<string, any>;
30
41
  /** match the files when load, support glob, default to all js files */
31
42
  match?: string | string[];
@@ -38,6 +49,7 @@ export interface FileLoaderOptions {
38
49
  /** determine whether override the property when get the same name */
39
50
  override?: boolean;
40
51
  /** an object that be the argument when invoke the function */
52
+
41
53
  inject?: Record<string, any>;
42
54
  /** a function that filter the exports which can be loaded */
43
55
  filter?: FileLoaderFilter;
@@ -65,7 +77,8 @@ export class FileLoader {
65
77
  return EXPORTS;
66
78
  }
67
79
 
68
- readonly options: FileLoaderOptions & Required<Pick<FileLoaderOptions, 'caseStyle'>>;
80
+ readonly options: FileLoaderOptions &
81
+ Required<Pick<FileLoaderOptions, 'caseStyle'>>;
69
82
 
70
83
  /**
71
84
  * @class
@@ -101,7 +114,7 @@ export class FileLoader {
101
114
  /**
102
115
  * attach items to target object. Mapping the directory to properties.
103
116
  * `app/controller/group/repository.js` => `target.group.repository`
104
- * @return {Object} target
117
+ * @returns {Object} target
105
118
  * @since 1.0.0
106
119
  */
107
120
  async load(): Promise<object> {
@@ -111,12 +124,15 @@ export class FileLoader {
111
124
  debug('loading item: %o', item);
112
125
  // item { properties: [ 'a', 'b', 'c'], exports }
113
126
  // => target.a.b.c = exports
127
+ // oxlint-disable-next-line unicorn/no-array-reduce
114
128
  item.properties.reduce((target, property, index) => {
115
129
  let obj;
116
130
  const properties = item.properties.slice(0, index + 1).join('.');
117
131
  if (index === item.properties.length - 1) {
118
- if (property in target) {
119
- if (!this.options.override) throw new Error(`can't overwrite property '${properties}' from ${target[property][FULLPATH]} by ${item.fullpath}`);
132
+ if (property in target && !this.options.override) {
133
+ throw new Error(
134
+ `can't overwrite property '${properties}' from ${target[property][FULLPATH]} by ${item.fullpath}`
135
+ );
120
136
  }
121
137
  obj = item.exports;
122
138
  if (obj && !isPrimitive(obj)) {
@@ -157,37 +173,43 @@ export class FileLoader {
157
173
  * `Properties` is an array that contains the directory of a filepath.
158
174
  *
159
175
  * `Exports` depends on type, if exports is a function, it will be called. if initializer is specified, it will be called with exports for customizing.
160
- * @return {Array} items
176
+ * @returns {Array} items
161
177
  * @since 1.0.0
162
178
  */
163
179
  protected async parse(): Promise<FileLoaderParseItem[]> {
164
180
  let files = this.options.match;
165
- if (!files) {
166
- files = isSupportTypeScript()
167
- ? [ '**/*.(js|ts)', '!**/*.d.ts' ]
168
- : [ '**/*.js' ];
181
+ if (files) {
182
+ files = Array.isArray(files) ? files : [files];
169
183
  } else {
170
- files = Array.isArray(files) ? files : [ files ];
184
+ files = isSupportTypeScript()
185
+ ? ['**/*.(js|ts)', '!**/*.d.ts']
186
+ : ['**/*.js'];
171
187
  }
172
188
 
173
189
  let ignore = this.options.ignore;
174
190
  if (ignore) {
175
- ignore = Array.isArray(ignore) ? ignore : [ ignore ];
191
+ ignore = Array.isArray(ignore) ? ignore : [ignore];
176
192
  ignore = ignore.filter(f => !!f).map(f => '!' + f);
177
193
  files = files.concat(ignore);
178
194
  }
179
195
 
180
196
  let directories = this.options.directory;
181
197
  if (!Array.isArray(directories)) {
182
- directories = [ directories ];
198
+ directories = [directories];
183
199
  }
184
200
 
185
- const filter = typeof this.options.filter === 'function' ? this.options.filter : null;
201
+ const filter =
202
+ typeof this.options.filter === 'function' ? this.options.filter : null;
186
203
  const items: FileLoaderParseItem[] = [];
187
204
  debug('[parse] parsing directories: %j', directories);
188
205
  for (const directory of directories) {
189
206
  const filepaths = globby.sync(files, { cwd: directory });
190
- debug('[parse] globby files: %o, cwd: %o => %o', files, directory, filepaths);
207
+ debug(
208
+ '[parse] globby files: %o, cwd: %o => %o',
209
+ files,
210
+ directory,
211
+ filepaths
212
+ );
191
213
  for (const filepath of filepaths) {
192
214
  const fullpath = path.join(directory, filepath);
193
215
  if (!fs.statSync(fullpath).isFile()) continue;
@@ -202,12 +224,17 @@ export class FileLoader {
202
224
  // app/service/foo/bar.js => [ 'foo', 'bar' ]
203
225
  const properties = getProperties(filepath, this.options.caseStyle);
204
226
  // app/service/foo/bar.js => service.foo.bar
205
- const pathName = directory.split(/[/\\]/).slice(-1) + '.' + properties.join('.');
227
+ const pathName =
228
+ directory.split(/[/\\]/).slice(-1) + '.' + properties.join('.');
206
229
  // get exports from the file
207
230
  const exports = await getExports(fullpath, this.options, pathName);
208
231
 
209
232
  // ignore exports when it's null or false returned by filter function
210
- if (exports == null || (filter && filter(exports) === false)) {
233
+ if (
234
+ exports === null ||
235
+ exports === undefined ||
236
+ (filter && filter(exports) === false)
237
+ ) {
211
238
  continue;
212
239
  }
213
240
 
@@ -218,7 +245,12 @@ export class FileLoader {
218
245
  }
219
246
 
220
247
  items.push({ fullpath, properties, exports });
221
- debug('[parse] parse %s, properties %j, exports %o', fullpath, properties, exports);
248
+ debug(
249
+ '[parse] parse %s, properties %j, exports %o',
250
+ fullpath,
251
+ properties,
252
+ exports
253
+ );
222
254
  }
223
255
  }
224
256
 
@@ -228,11 +260,17 @@ export class FileLoader {
228
260
 
229
261
  // convert file path to an array of properties
230
262
  // a/b/c.js => ['a', 'b', 'c']
231
- function getProperties(filepath: string, caseStyle: CaseStyle | CaseStyleFunction) {
263
+ function getProperties(
264
+ filepath: string,
265
+ caseStyle: CaseStyle | CaseStyleFunction
266
+ ) {
232
267
  // if caseStyle is function, return the result of function
233
268
  if (typeof caseStyle === 'function') {
234
269
  const result = caseStyle(filepath);
235
- assert(Array.isArray(result), `caseStyle expect an array, but got ${JSON.stringify(result)}`);
270
+ assert(
271
+ Array.isArray(result),
272
+ `caseStyle expect an array, but got ${JSON.stringify(result)}`
273
+ );
236
274
  return result;
237
275
  }
238
276
  // use default camelize
@@ -241,7 +279,11 @@ function getProperties(filepath: string, caseStyle: CaseStyle | CaseStyleFunctio
241
279
 
242
280
  // Get exports from filepath
243
281
  // If exports is null/undefined, it will be ignored
244
- async function getExports(fullpath: string, options: FileLoaderOptions, pathName: string) {
282
+ async function getExports(
283
+ fullpath: string,
284
+ options: FileLoaderOptions,
285
+ pathName: string
286
+ ) {
245
287
  let exports = await utils.loadFile(fullpath);
246
288
  // process exports as you like
247
289
  if (options.initializer) {
@@ -250,7 +292,9 @@ async function getExports(fullpath: string, options: FileLoaderOptions, pathName
250
292
  }
251
293
 
252
294
  if (isGeneratorFunction(exports)) {
253
- throw new TypeError(`Support for generators was removed, fullpath: ${fullpath}`);
295
+ throw new TypeError(
296
+ `Support for generators was removed, fullpath: ${fullpath}`
297
+ );
254
298
  }
255
299
 
256
300
  // return exports when it's a class or async function
@@ -269,7 +313,7 @@ async function getExports(fullpath: string, options: FileLoaderOptions, pathName
269
313
  // }
270
314
  if (options.call && typeof exports === 'function') {
271
315
  exports = exports(options.inject);
272
- if (exports != null) {
316
+ if (exports !== null && exports !== undefined) {
273
317
  return exports;
274
318
  }
275
319
  }
@@ -279,7 +323,7 @@ async function getExports(fullpath: string, options: FileLoaderOptions, pathName
279
323
  }
280
324
 
281
325
  function defaultCamelize(filepath: string, caseStyle: CaseStyle) {
282
- const properties = filepath.substring(0, filepath.lastIndexOf('.')).split('/');
326
+ const properties = filepath.slice(0, filepath.lastIndexOf('.')).split('/');
283
327
  return properties.map(property => {
284
328
  if (!/^[a-z][a-z0-9_-]*$/i.test(property)) {
285
329
  throw new Error(`${property} is not match 'a-z0-9_-' in ${filepath}`);
@@ -291,18 +335,15 @@ function defaultCamelize(filepath: string, caseStyle: CaseStyle) {
291
335
  // FooBar.js > FooBar
292
336
  // FooBar.js > FooBar
293
337
  // FooBar.js > fooBar (if lowercaseFirst is true)
294
- property = property.replace(/[_-][a-z]/ig, s => s.substring(1).toUpperCase());
338
+ property = property.replaceAll(/[_-][a-z]/gi, s =>
339
+ s.slice(1).toUpperCase()
340
+ );
295
341
  let first = property[0];
296
- switch (caseStyle) {
297
- case 'lower':
298
- first = first.toLowerCase();
299
- break;
300
- case 'upper':
301
- first = first.toUpperCase();
302
- break;
303
- case 'camel':
304
- default:
342
+ if (caseStyle === CaseStyle.lower) {
343
+ first = first.toLowerCase();
344
+ } else if (caseStyle === CaseStyle.upper) {
345
+ first = first.toUpperCase();
305
346
  }
306
- return first + property.substring(1);
347
+ return first + property.slice(1);
307
348
  });
308
349
  }
package/src/singleton.ts CHANGED
@@ -2,8 +2,11 @@ import assert from 'node:assert';
2
2
  import { isAsyncFunction } from 'is-type-of';
3
3
  import type { EggCore } from './egg.js';
4
4
 
5
- export type SingletonCreateMethod =
6
- (config: Record<string, any>, app: EggCore, clientName: string) => unknown | Promise<unknown>;
5
+ export type SingletonCreateMethod = (
6
+ config: Record<string, any>,
7
+ app: EggCore,
8
+ clientName: string
9
+ ) => unknown | Promise<unknown>;
7
10
 
8
11
  export interface SingletonOptions {
9
12
  name: string;
@@ -19,10 +22,22 @@ export class Singleton<T = any> {
19
22
  readonly options: Record<string, any>;
20
23
 
21
24
  constructor(options: SingletonOptions) {
22
- assert(options.name, '[@eggjs/core/singleton] Singleton#constructor options.name is required');
23
- assert(options.app, '[@eggjs/core/singleton] Singleton#constructor options.app is required');
24
- assert(options.create, '[@eggjs/core/singleton] Singleton#constructor options.create is required');
25
- assert(!(options.name in options.app), `[@eggjs/core/singleton] ${options.name} is already exists in app`);
25
+ assert(
26
+ options.name,
27
+ '[@eggjs/core/singleton] Singleton#constructor options.name is required'
28
+ );
29
+ assert(
30
+ options.app,
31
+ '[@eggjs/core/singleton] Singleton#constructor options.app is required'
32
+ );
33
+ assert(
34
+ options.create,
35
+ '[@eggjs/core/singleton] Singleton#constructor options.create is required'
36
+ );
37
+ assert(
38
+ !(options.name in options.app),
39
+ `[@eggjs/core/singleton] ${options.name} is already exists in app`
40
+ );
26
41
  this.app = options.app;
27
42
  this.name = options.name;
28
43
  this.create = options.create;
@@ -35,8 +50,10 @@ export class Singleton<T = any> {
35
50
 
36
51
  initSync() {
37
52
  const options = this.options;
38
- assert(!(options.client && options.clients),
39
- `[@eggjs/core/singleton] ${this.name} can not set options.client and options.clients both`);
53
+ assert(
54
+ !(options.client && options.clients),
55
+ `[@eggjs/core/singleton] ${this.name} can not set options.client and options.clients both`
56
+ );
40
57
 
41
58
  // alias app[name] as client, but still support createInstance method
42
59
  if (options.client) {
@@ -48,10 +65,10 @@ export class Singleton<T = any> {
48
65
 
49
66
  // multi client, use app[name].getSingletonInstance(id)
50
67
  if (options.clients) {
51
- Object.keys(options.clients).forEach(id => {
68
+ for (const id of Object.keys(options.clients)) {
52
69
  const client = this.createInstance(options.clients[id], id);
53
70
  this.clients.set(id, client);
54
- });
71
+ }
55
72
  this.#setClientToApp(this);
56
73
  return;
57
74
  }
@@ -62,12 +79,17 @@ export class Singleton<T = any> {
62
79
 
63
80
  async initAsync() {
64
81
  const options = this.options;
65
- assert(!(options.client && options.clients),
66
- `[@eggjs/core/singleton] ${this.name} can not set options.client and options.clients both`);
82
+ assert(
83
+ !(options.client && options.clients),
84
+ `[@eggjs/core/singleton] ${this.name} can not set options.client and options.clients both`
85
+ );
67
86
 
68
87
  // alias app[name] as client, but still support createInstance method
69
88
  if (options.client) {
70
- const client = await this.createInstanceAsync(options.client, options.name);
89
+ const client = await this.createInstanceAsync(
90
+ options.client,
91
+ options.name
92
+ );
71
93
  this.#setClientToApp(client);
72
94
  this.#extendDynamicMethods(client);
73
95
  return;
@@ -75,10 +97,13 @@ export class Singleton<T = any> {
75
97
 
76
98
  // multi client, use app[name].getInstance(id)
77
99
  if (options.clients) {
78
- await Promise.all(Object.keys(options.clients).map((id: string) => {
79
- return this.createInstanceAsync(options.clients[id], id)
80
- .then(client => this.clients.set(id, client));
81
- }));
100
+ await Promise.all(
101
+ Object.keys(options.clients).map((id: string) => {
102
+ return this.createInstanceAsync(options.clients[id], id).then(
103
+ client => this.clients.set(id, client)
104
+ );
105
+ })
106
+ );
82
107
  this.#setClientToApp(this);
83
108
  return;
84
109
  }
@@ -95,26 +120,32 @@ export class Singleton<T = any> {
95
120
  * @deprecated please use `getSingletonInstance(id)` instead
96
121
  */
97
122
  get(id: string) {
98
- return this.clients.get(id)!;
123
+ return this.clients.get(id) as T;
99
124
  }
100
125
 
101
126
  /**
102
127
  * Get singleton instance by id
103
128
  */
104
129
  getSingletonInstance(id: string) {
105
- return this.clients.get(id)!;
130
+ return this.clients.get(id) as T;
106
131
  }
107
132
 
108
133
  createInstance(config: Record<string, any>, clientName: string) {
109
134
  // async creator only support createInstanceAsync
110
- assert(!isAsyncFunction(this.create),
111
- `[@eggjs/core/singleton] ${this.name} only support synchronous creation, please use createInstanceAsync`);
135
+ assert(
136
+ !isAsyncFunction(this.create),
137
+ `[@eggjs/core/singleton] ${this.name} only support asynchronous creation, please use createInstanceAsync`
138
+ );
112
139
  // options.default will be merge in to options.clients[id]
113
140
  config = {
114
141
  ...this.options.default,
115
142
  ...config,
116
143
  };
117
- return (this.create as SingletonCreateMethod)(config, this.app, clientName) as T;
144
+ return (this.create as SingletonCreateMethod)(
145
+ config,
146
+ this.app,
147
+ clientName
148
+ ) as T;
118
149
  }
119
150
 
120
151
  async createInstanceAsync(config: Record<string, any>, clientName: string) {
@@ -123,12 +154,18 @@ export class Singleton<T = any> {
123
154
  ...this.options.default,
124
155
  ...config,
125
156
  };
126
- return await this.create(config, this.app, clientName) as T;
157
+ return (await this.create(config, this.app, clientName)) as T;
127
158
  }
128
159
 
129
160
  #extendDynamicMethods(client: any) {
130
- assert(!client.createInstance, '[@eggjs/core/singleton] singleton instance should not have createInstance method');
131
- assert(!client.createInstanceAsync, '[@eggjs/core/singleton] singleton instance should not have createInstanceAsync method');
161
+ assert(
162
+ !client.createInstance,
163
+ '[@eggjs/core/singleton] singleton instance should not have createInstance method'
164
+ );
165
+ assert(
166
+ !client.createInstanceAsync,
167
+ '[@eggjs/core/singleton] singleton instance should not have createInstanceAsync method'
168
+ );
132
169
 
133
170
  try {
134
171
  let extendable = client;
@@ -142,7 +179,8 @@ export class Singleton<T = any> {
142
179
  } catch (err) {
143
180
  this.app.coreLogger.warn(
144
181
  '[@eggjs/core/singleton] %s dynamic create is disabled because of client is un-extendable',
145
- this.name);
182
+ this.name
183
+ );
146
184
  this.app.coreLogger.warn(err);
147
185
  }
148
186
  }
@@ -3,20 +3,22 @@ import path from 'node:path';
3
3
  import fs from 'node:fs';
4
4
  import { stat } from 'node:fs/promises';
5
5
  import BuiltinModule from 'node:module';
6
+
6
7
  import { importResolve, importModule } from '@eggjs/utils';
7
8
 
8
9
  const debug = debuglog('@eggjs/core/utils');
9
10
 
10
- export type Fun = (...args: any[]) => any;
11
+ export type Fun = (...args: unknown[]) => unknown;
11
12
 
12
13
  // Guard against poorly mocked module constructors.
13
- const Module = typeof module !== 'undefined' && module.constructor.length > 1
14
- ? module.constructor
15
- /* istanbul ignore next */
16
- : BuiltinModule;
14
+ const Module =
15
+ typeof module !== 'undefined' && module.constructor.length > 1
16
+ ? module.constructor
17
+ : /* istanbul ignore next */
18
+ BuiltinModule;
17
19
 
18
20
  const extensions = (Module as any)._extensions;
19
- const extensionNames = Object.keys(extensions).concat([ '.cjs', '.mjs' ]);
21
+ const extensionNames = Object.keys(extensions).concat(['.cjs', '.mjs']);
20
22
  debug('Module extensions: %j', extensionNames);
21
23
 
22
24
  function getCalleeFromStack(withLine?: boolean, stackIndex?: number) {
@@ -28,6 +30,7 @@ function getCalleeFromStack(withLine?: boolean, stackIndex?: number) {
28
30
  Error.stackTraceLimit = 5;
29
31
 
30
32
  // capture the stack
33
+
31
34
  const obj: any = {};
32
35
  Error.captureStackTrace(obj);
33
36
  let callSite = obj.stack[stackIndex];
@@ -58,7 +61,9 @@ export default {
58
61
  console.trace('[@eggjs/core/deprecated] %s', message);
59
62
  } else {
60
63
  console.log('[@eggjs/core/deprecated] %s', message);
61
- console.log('[@eggjs/core/deprecated] set NODE_DEBUG=@eggjs/core/utils can show call stack');
64
+ console.log(
65
+ '[@eggjs/core/deprecated] set NODE_DEBUG=@eggjs/core/utils can show call stack'
66
+ );
62
67
  }
63
68
  },
64
69
 
@@ -83,13 +88,15 @@ export default {
83
88
  }
84
89
  const obj = await importModule(filepath, { importDefaultOnly: true });
85
90
  return obj;
86
- } catch (e: any) {
87
- if (!e.message && typeof e !== 'string') {
91
+ } catch (e) {
92
+ if (!(e instanceof Error)) {
88
93
  // ts error: test/fixtures/apps/app-ts/app/extend/context.ts(5,17): error TS2339: Property 'url' does not exist on type 'Context'
89
94
  console.trace(e);
90
95
  throw e;
91
96
  }
92
- const err = new Error(`[@eggjs/core] load file: ${filepath}, error: ${e.message}`);
97
+ const err = new Error(
98
+ `[@eggjs/core] load file: ${filepath}, error: ${e.message}`
99
+ );
93
100
  err.cause = e;
94
101
  debug('[loadFile] handle %s error: %s', filepath, e);
95
102
  throw err;
@@ -100,9 +107,9 @@ export default {
100
107
  return importResolve(filepath, options);
101
108
  },
102
109
 
103
- methods: [ 'head', 'options', 'get', 'put', 'patch', 'post', 'delete' ],
110
+ methods: ['head', 'options', 'get', 'put', 'patch', 'post', 'delete'],
104
111
 
105
- async callFn(fn: Fun, args?: any[], ctx?: any) {
112
+ async callFn(fn: Fun, args?: unknown[], ctx?: unknown) {
106
113
  args = args || [];
107
114
  if (typeof fn !== 'function') return;
108
115
  return ctx ? fn.call(ctx, ...args) : fn(...args);
@@ -120,6 +127,6 @@ export default {
120
127
  * Capture call site stack from v8.
121
128
  * https://github.com/v8/v8/wiki/Stack-Trace-API
122
129
  */
123
- function prepareObjectStackTrace(_obj: any, stack: any) {
130
+ function prepareObjectStackTrace(_obj: unknown, stack: unknown) {
124
131
  return stack;
125
132
  }
@@ -12,27 +12,59 @@ export interface SequencifyTask {
12
12
  optionalDependencies: string[];
13
13
  }
14
14
 
15
- function sequence(tasks: Record<string, SequencifyTask>, names: string[], result: SequencifyResult,
16
- missing: string[], recursive: string[],
17
- nest: string[], optional: boolean, parent: string) {
18
- names.forEach(function(name) {
19
- if (result.requires[name]) return;
20
-
15
+ function sequence(
16
+ // oxlint-disable-next-line max-params
17
+ tasks: Record<string, SequencifyTask>,
18
+ names: string[],
19
+ result: SequencifyResult,
20
+ missing: string[],
21
+ recursive: string[],
22
+ nest: string[],
23
+ optional: boolean,
24
+ parent: string
25
+ ) {
26
+ for (const name of names) {
27
+ if (result.requires[name]) {
28
+ continue;
29
+ }
21
30
  const node = tasks[name];
22
31
  if (!node) {
23
- if (optional === true) return;
32
+ if (optional === true) {
33
+ continue;
34
+ }
24
35
  missing.push(name);
25
36
  } else if (nest.includes(name)) {
26
37
  nest.push(name);
27
38
  recursive.push(...nest.slice(0));
28
39
  nest.pop();
29
- } else if (node.dependencies.length || node.optionalDependencies.length) {
40
+ } else if (
41
+ node.dependencies.length > 0 ||
42
+ node.optionalDependencies.length > 0
43
+ ) {
30
44
  nest.push(name);
31
- if (node.dependencies.length) {
32
- sequence(tasks, node.dependencies, result, missing, recursive, nest, optional, name);
45
+ if (node.dependencies.length > 0) {
46
+ sequence(
47
+ tasks,
48
+ node.dependencies,
49
+ result,
50
+ missing,
51
+ recursive,
52
+ nest,
53
+ optional,
54
+ name
55
+ );
33
56
  }
34
- if (node.optionalDependencies.length) {
35
- sequence(tasks, node.optionalDependencies, result, missing, recursive, nest, true, name);
57
+ if (node.optionalDependencies.length > 0) {
58
+ sequence(
59
+ tasks,
60
+ node.optionalDependencies,
61
+ result,
62
+ missing,
63
+ recursive,
64
+ nest,
65
+ true,
66
+ name
67
+ );
36
68
  }
37
69
  nest.pop();
38
70
  }
@@ -43,12 +75,15 @@ function sequence(tasks: Record<string, SequencifyTask>, names: string[], result
43
75
  if (!result.sequence.includes(name)) {
44
76
  result.sequence.push(name);
45
77
  }
46
- });
78
+ }
47
79
  }
48
80
 
49
81
  // tasks: object with keys as task names
50
82
  // names: array of task names
51
- export default function sequencify(tasks: Record<string, SequencifyTask>, names: string[]) {
83
+ export function sequencify(
84
+ tasks: Record<string, SequencifyTask>,
85
+ names: string[]
86
+ ) {
52
87
  const result: SequencifyResult = {
53
88
  sequence: [],
54
89
  requires: {},
@@ -58,7 +93,7 @@ export default function sequencify(tasks: Record<string, SequencifyTask>, names:
58
93
 
59
94
  sequence(tasks, names, result, missing, recursive, [], false, 'app');
60
95
 
61
- if (missing.length || recursive.length) {
96
+ if (missing.length > 0 || recursive.length > 0) {
62
97
  result.sequence = []; // results are incomplete at best, completely wrong at worst, remove them to avoid confusion
63
98
  }
64
99