locter 0.8.1 → 1.0.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.
package/README.MD CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Known Vulnerabilities](https://snyk.io/test/github/Tada5hi/locter/badge.svg?targetFile=package.json)](https://snyk.io/test/github/Tada5hi/locter?targetFile=package.json)
7
7
  [![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
8
8
 
9
- Locter is a library to locate and load a file regarding specific criteria.
9
+ Locter is a library to locate and load a file/modules regarding specific criteria.
10
10
 
11
11
  **Table of Contents**
12
12
 
@@ -40,10 +40,10 @@ The following examples are based on some shared assumptions:
40
40
  Locating multiple files will return information about all files matching the pattern.
41
41
 
42
42
  ```typescript
43
- import { locateFiles } from 'locter';
43
+ import { locateMany } from 'locter';
44
44
 
45
45
  (async () => {
46
- let files = await locateFiles(
46
+ let files = await locateMany(
47
47
  'files/example.{js,.ts}',
48
48
  {
49
49
  path: process.cwd()
@@ -58,7 +58,7 @@ import { locateFiles } from 'locter';
58
58
  ]
59
59
  */
60
60
 
61
- files = await locateFiles(
61
+ files = await locateMany(
62
62
  'files/*.{js,ts}',
63
63
  {
64
64
  path: process.cwd()
@@ -76,17 +76,17 @@ import { locateFiles } from 'locter';
76
76
  })
77
77
  ```
78
78
 
79
- A synchronous variant is also available: `locateFilesSync`
79
+ A synchronous variant is also available: `locateManySync`
80
80
 
81
81
  **Single**
82
82
 
83
83
  Locating a single file will return information about the first file matching the pattern.
84
84
 
85
85
  ```typescript
86
- import { locateFile } from 'locter';
86
+ import { locate } from 'locter';
87
87
 
88
88
  (async () => {
89
- let file = await locateFile(
89
+ let file = await locate(
90
90
  'files/example.{js,.ts}',
91
91
  {
92
92
  path: process.cwd()
@@ -100,32 +100,77 @@ import { locateFile } from 'locter';
100
100
  })
101
101
  ```
102
102
 
103
- A synchronous variant is also available: `locateFileSync`
103
+ A synchronous variant is also available: `locateSync`
104
104
 
105
105
  ### Loader
106
106
 
107
- The method will load the located file.
107
+ The `load` method can be used to load a file/module in an asynchronous fashion.
108
+ Either a string or the output of the locate/locateSync method can be passed as argument.
108
109
 
109
110
  ```typescript
110
- import { loadFile, locateFile } from 'locter';
111
+ import { load, locate } from 'locter';
111
112
 
112
113
  (async () => {
113
- const file = await locateFile(
114
+ const file = await locate(
114
115
  'files/example.{js,.ts}',
115
116
  {
116
117
  path: process.cwd()
117
118
  }
118
119
  );
119
120
 
120
- const content = loadFile(file);
121
+ let content = await load(file);
122
+ console.log(content);
123
+ // ...
124
+
125
+ content = await load('...');
126
+ console.log(content);
127
+ // ...
128
+ })
129
+ ```
130
+
131
+ There is also a synchronous method called `loadSync` to load files.
132
+
133
+ ```typescript
134
+ import { loadSync, locateSync } from 'locter';
135
+
136
+ (async () => {
137
+ const file = await locateSync(
138
+ 'files/example.{js,.ts}',
139
+ {
140
+ path: process.cwd()
141
+ }
142
+ );
121
143
 
144
+ let content = await loadSync(file);
122
145
  console.log(content);
146
+ // ...
123
147
 
148
+ content = await loadSync('...');
149
+ console.log(content);
124
150
  // ...
125
151
  })
126
152
  ```
127
153
 
128
- A synchronous variant is also available: `loadFileSync`
154
+ Two loaders are predefined from scratch and already registered:
155
+ - **JsonLoader**: This loader allows to load `.json` files.
156
+ - **ModuleLoader**: This loader allows to load modules with
157
+ `.js`, `.mjs`, `.mts`, `.cjs`, `.cts`, `.ts` file extensions independent of the environment (cjs or esm).
158
+
159
+ To register loader for other file types, the function `registerLoader` can be used.
160
+
161
+ ```typescript
162
+ import { LocatorInfo, registerLoader } from 'locter';
163
+
164
+ registerLoader(['.ext'], {
165
+ execute(info: LocatorInfo) {
166
+
167
+ },
168
+ executeSync(info: LocatorInfo) {
169
+
170
+ }
171
+ })
172
+ ```
173
+
129
174
 
130
175
  ## License
131
176
 
package/dist/index.cjs CHANGED
@@ -71,7 +71,7 @@ function hasStringProperty(obj, prop) {
71
71
  * Author Peter Placzek (tada5hi)
72
72
  * For the full copyright and license information,
73
73
  * view the LICENSE file that was distributed with this source code.
74
- */ var _options, _options1;
74
+ */ var _options;
75
75
  function buildLocatorOptions(options) {
76
76
  options = options || {};
77
77
  options.path = options.path || [];
@@ -79,10 +79,13 @@ function buildLocatorOptions(options) {
79
79
  if (options.path.length === 0) {
80
80
  options.path.push(process.cwd());
81
81
  }
82
- (_options = options).soft ?? (_options.soft = true);
83
- (_options1 = options).ignore ?? (_options1.ignore = []);
82
+ (_options = options).ignore ?? (_options.ignore = []);
84
83
  return options;
85
84
  }
85
+ function isFilePath(input) {
86
+ const info = path.parse(input);
87
+ return info.ext !== '';
88
+ }
86
89
  function pathToLocatorInfo(input, skipResolve) {
87
90
  if (!skipResolve && !path.isAbsolute(input)) {
88
91
  input = path.resolve(process.cwd(), input);
@@ -96,7 +99,7 @@ function pathToLocatorInfo(input, skipResolve) {
96
99
  }
97
100
 
98
101
  const globAsync = node_util.promisify(glob);
99
- async function locateFiles(pattern, options) {
102
+ async function locateMany(pattern, options) {
100
103
  options = buildLocatorOptions(options);
101
104
  const patterns = Array.isArray(pattern) ? pattern : [
102
105
  pattern
@@ -117,7 +120,7 @@ async function locateFiles(pattern, options) {
117
120
  }
118
121
  return items;
119
122
  }
120
- async function locateFile(pattern, options) {
123
+ async function locate(pattern, options) {
121
124
  options = buildLocatorOptions(options);
122
125
  const patterns = Array.isArray(pattern) ? pattern : [
123
126
  pattern
@@ -136,13 +139,10 @@ async function locateFile(pattern, options) {
136
139
  }
137
140
  }
138
141
  }
139
- if (!options.soft) {
140
- throw new Error('The file could not be located.');
141
- }
142
142
  return undefined;
143
143
  }
144
144
 
145
- function locateFilesSync(pattern, options) {
145
+ function locateManySync(pattern, options) {
146
146
  options = buildLocatorOptions(options);
147
147
  const patterns = Array.isArray(pattern) ? pattern : [
148
148
  pattern
@@ -163,7 +163,7 @@ function locateFilesSync(pattern, options) {
163
163
  }
164
164
  return items;
165
165
  }
166
- function locateFileSync(pattern, options) {
166
+ function locateSync(pattern, options) {
167
167
  options = buildLocatorOptions(options);
168
168
  const patterns = Array.isArray(pattern) ? pattern : [
169
169
  pattern
@@ -185,7 +185,13 @@ function locateFileSync(pattern, options) {
185
185
  return undefined;
186
186
  }
187
187
 
188
- function buildLoaderFilePath(info, withExtension) {
188
+ function buildLoaderFilePath(input, withExtension) {
189
+ let info;
190
+ if (typeof input === 'string') {
191
+ info = pathToLocatorInfo(input);
192
+ } else {
193
+ info = input;
194
+ }
189
195
  if (withExtension) {
190
196
  return path.join(info.path, info.name) + info.extension;
191
197
  }
@@ -215,28 +221,37 @@ function getExportItem(data, filterFn) {
215
221
  * Author Peter Placzek (tada5hi)
216
222
  * For the full copyright and license information,
217
223
  * view the LICENSE file that was distributed with this source code.
218
- */ function isJestEnvironment() {
224
+ */ function isJestRuntimeEnvironment() {
219
225
  return process.env && process.env.JEST_WORKER_ID !== undefined;
220
226
  }
227
+ function isTsNodeRuntimeEnvironment() {
228
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
229
+ // @ts-ignore
230
+ return !!process[Symbol.for('ts-node.register.instance')];
231
+ }
221
232
 
222
- class ScriptLoader {
223
- async execute(info) {
224
- const filePath = buildLoaderFilePath(info);
233
+ class ModuleLoader {
234
+ async execute(input) {
225
235
  let output;
226
236
  try {
227
- output = await this.load(info);
237
+ output = await this.load(input);
228
238
  } catch (e) {
229
- output = this.jiti(filePath);
239
+ // jiti + ts-node
240
+ // issue: https://github.com/nuxt/bridge/issues/228
241
+ if (isTsNodeRuntimeEnvironment()) {
242
+ output = this.loadSync(input);
243
+ } else {
244
+ output = this.jiti(input);
245
+ }
230
246
  }
231
247
  return output;
232
248
  }
233
- executeSync(info) {
234
- const filePath = buildLoaderFilePath(info);
249
+ executeSync(input) {
235
250
  let output;
236
251
  try {
237
- output = this.loadSync(info);
252
+ output = this.loadSync(input);
238
253
  } catch (e) {
239
- output = this.jiti(filePath);
254
+ output = this.jiti(input);
240
255
  }
241
256
  return output;
242
257
  }
@@ -256,7 +271,7 @@ class ScriptLoader {
256
271
  try {
257
272
  // segmentation fault
258
273
  // issue: https://github.com/nodejs/node/issues/35889
259
- if (isJestEnvironment()) {
274
+ if (isJestRuntimeEnvironment()) {
260
275
  // eslint-disable-next-line global-require,import/no-dynamic-require
261
276
  return require(filePath);
262
277
  }
@@ -314,17 +329,17 @@ class ScriptLoader {
314
329
  }
315
330
  }
316
331
  constructor(){
317
- /*
318
- const loaderMap : Record<string, ESLoader> = {
319
- '.mjs': 'js',
320
- '.js': 'js',
321
- '.jsx': 'jsx',
322
- '.ts': 'ts',
323
- '.tsx': 'tsx',
324
- };
325
- */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
332
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
326
333
  // @ts-ignore
327
334
  this.jiti = createJITI(undefined, {
335
+ extensions: [
336
+ '.js',
337
+ '.mjs',
338
+ '.mts',
339
+ '.cjs',
340
+ '.cts',
341
+ '.ts'
342
+ ],
328
343
  esmResolve: true
329
344
  });
330
345
  }
@@ -351,35 +366,59 @@ class JSONLoader {
351
366
  }
352
367
  }
353
368
 
369
+ /*
370
+ * Copyright (c) 2023.
371
+ * Author Peter Placzek (tada5hi)
372
+ * For the full copyright and license information,
373
+ * view the LICENSE file that was distributed with this source code.
374
+ */ var LoaderId;
375
+ (function(LoaderId) {
376
+ LoaderId["MODULE"] = 'module';
377
+ LoaderId["JSON"] = 'json';
378
+ })(LoaderId || (LoaderId = {}));
379
+
354
380
  class LoaderManager {
355
- register(rule) {
356
- this.rules.push(rule);
381
+ register(test, loader) {
382
+ if (typeof loader !== 'undefined') {
383
+ this.rules.push({
384
+ test,
385
+ loader
386
+ });
387
+ return;
388
+ }
389
+ this.rules.push(test);
357
390
  }
358
- async execute(info) {
359
- const rule = this.findRule(info);
360
- if (!rule) {
391
+ async execute(input) {
392
+ const id = this.findLoader(input);
393
+ if (!id) {
394
+ const info = pathToLocatorInfo(input);
361
395
  throw new Error(`No loader registered for extension: "${info.extension}"`);
362
396
  }
363
- const loader = this.resolve(rule.loader);
364
- return loader.execute(info);
397
+ const loader = this.resolve(id);
398
+ return loader.execute(input);
365
399
  }
366
- executeSync(info) {
367
- const rule = this.findRule(info);
368
- if (!rule) {
400
+ executeSync(input) {
401
+ const id = this.findLoader(input);
402
+ if (!id) {
403
+ const info = pathToLocatorInfo(input);
369
404
  throw new Error(`No loader registered for extension: ${info.extension || 'unknown'}`);
370
405
  }
371
- const loader = this.resolve(rule.loader);
372
- return loader.executeSync(info);
406
+ const loader = this.resolve(id);
407
+ return loader.executeSync(input);
373
408
  }
374
- findRule(info) {
409
+ findLoader(input) {
410
+ if (!isFilePath(input)) {
411
+ return LoaderId.MODULE;
412
+ }
413
+ const info = pathToLocatorInfo(input);
375
414
  for(let i = 0; i < this.rules.length; i++){
376
415
  const { test } = this.rules[i];
377
416
  if (Array.isArray(test)) {
378
417
  if (test.indexOf(info.extension) !== -1) {
379
- return this.rules[i];
418
+ return this.rules[i].loader;
380
419
  }
381
420
  } else if (test.test(buildLoaderFilePath(info))) {
382
- return this.rules[i];
421
+ return this.rules[i].loader;
383
422
  }
384
423
  }
385
424
  return undefined;
@@ -392,27 +431,48 @@ class LoaderManager {
392
431
  if (typeof id !== 'string') {
393
432
  return id;
394
433
  }
395
- if (this.loaders[id]) {
434
+ if (Object.prototype.hasOwnProperty.call(this.loaders, id)) {
396
435
  return this.loaders[id];
397
436
  }
398
437
  let loader;
438
+ // built-in
399
439
  switch(id){
400
- case 'script':
440
+ case LoaderId.MODULE:
401
441
  {
402
- loader = new ScriptLoader();
442
+ loader = new ModuleLoader();
403
443
  break;
404
444
  }
405
- case 'json':
445
+ case LoaderId.JSON:
406
446
  {
407
447
  loader = new JSONLoader();
408
448
  break;
409
449
  }
450
+ default:
451
+ {
452
+ const pluginPath = this.normalizePath(id);
453
+ const moduleLoader = this.resolve(LoaderId.MODULE);
454
+ loader = moduleLoader.executeSync(pluginPath);
455
+ break;
456
+ }
410
457
  }
411
458
  if (typeof loader !== 'undefined') {
459
+ this.loaders[id] = loader;
412
460
  return loader;
413
461
  }
414
462
  throw new Error(`The loader ${id} could not be resolved.`);
415
463
  }
464
+ normalizePath(input) {
465
+ if (path.isAbsolute(input) || input.startsWith('./')) {
466
+ return input;
467
+ }
468
+ if (input.startsWith('module:')) {
469
+ return input.substring(0, 'module:'.length);
470
+ }
471
+ if (!input.startsWith('@')) {
472
+ return `@locter/${input}`;
473
+ }
474
+ return input;
475
+ }
416
476
  constructor(){
417
477
  this.loaders = {};
418
478
  this.rules = [
@@ -420,23 +480,25 @@ class LoaderManager {
420
480
  test: [
421
481
  '.js',
422
482
  '.mjs',
483
+ '.mts',
423
484
  '.cjs',
485
+ '.cts',
424
486
  '.ts'
425
487
  ],
426
- loader: 'script'
488
+ loader: LoaderId.MODULE
427
489
  },
428
490
  {
429
491
  test: [
430
492
  '.json'
431
493
  ],
432
- loader: 'json'
494
+ loader: LoaderId.JSON
433
495
  }
434
496
  ];
435
497
  }
436
498
  }
437
499
 
438
500
  let instance;
439
- function useLoaderManager() {
501
+ function useLoader() {
440
502
  if (typeof instance !== 'undefined') {
441
503
  return instance;
442
504
  }
@@ -444,44 +506,50 @@ function useLoaderManager() {
444
506
  return instance;
445
507
  }
446
508
 
447
- async function loadFile(input) {
448
- let info;
509
+ function registerLoader(test, loader) {
510
+ const manager = useLoader();
511
+ if (typeof loader !== 'undefined') {
512
+ manager.register(test, loader);
513
+ return;
514
+ }
515
+ manager.register(test);
516
+ }
517
+ async function load(input) {
518
+ const manager = useLoader();
449
519
  if (typeof input === 'string') {
450
- info = pathToLocatorInfo(input);
451
- } else {
452
- info = input;
520
+ return manager.execute(input);
453
521
  }
454
- const manager = useLoaderManager();
455
- return manager.execute(info);
522
+ return manager.execute(buildLoaderFilePath(input));
456
523
  }
457
- function loadFileSync(input) {
458
- let info;
524
+ function loadSync(input) {
525
+ const manager = useLoader();
459
526
  if (typeof input === 'string') {
460
- info = pathToLocatorInfo(input);
461
- } else {
462
- info = input;
527
+ return manager.executeSync(input);
463
528
  }
464
- const manager = useLoaderManager();
465
- return manager.executeSync(info);
529
+ return manager.executeSync(buildLoaderFilePath(input));
466
530
  }
467
531
 
468
532
  exports.JSONLoader = JSONLoader;
469
- exports.ScriptLoader = ScriptLoader;
533
+ exports.LoaderManager = LoaderManager;
534
+ exports.ModuleLoader = ModuleLoader;
470
535
  exports.buildLoaderFilePath = buildLoaderFilePath;
471
536
  exports.buildLocatorOptions = buildLocatorOptions;
472
537
  exports.getExportItem = getExportItem;
473
538
  exports.handleFileLoadError = handleFileLoadError;
474
539
  exports.hasOwnProperty = hasOwnProperty;
475
540
  exports.hasStringProperty = hasStringProperty;
476
- exports.isJestEnvironment = isJestEnvironment;
541
+ exports.isFilePath = isFilePath;
542
+ exports.isJestRuntimeEnvironment = isJestRuntimeEnvironment;
477
543
  exports.isObject = isObject;
478
- exports.loadFile = loadFile;
479
- exports.loadFileSync = loadFileSync;
480
- exports.locateFile = locateFile;
481
- exports.locateFileSync = locateFileSync;
482
- exports.locateFiles = locateFiles;
483
- exports.locateFilesSync = locateFilesSync;
544
+ exports.isTsNodeRuntimeEnvironment = isTsNodeRuntimeEnvironment;
545
+ exports.load = load;
546
+ exports.loadSync = loadSync;
547
+ exports.locate = locate;
548
+ exports.locateMany = locateMany;
549
+ exports.locateManySync = locateManySync;
550
+ exports.locateSync = locateSync;
484
551
  exports.pathToLocatorInfo = pathToLocatorInfo;
552
+ exports.registerLoader = registerLoader;
485
553
  exports.removeFileNameExtension = removeFileNameExtension;
486
554
  exports.toArray = toArray;
487
555
  //# sourceMappingURL=index.cjs.map