locter 0.8.2 → 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
  }
@@ -224,30 +230,28 @@ function isTsNodeRuntimeEnvironment() {
224
230
  return !!process[Symbol.for('ts-node.register.instance')];
225
231
  }
226
232
 
227
- class ScriptLoader {
228
- async execute(info) {
229
- const filePath = buildLoaderFilePath(info);
233
+ class ModuleLoader {
234
+ async execute(input) {
230
235
  let output;
231
236
  try {
232
- output = await this.load(info);
237
+ output = await this.load(input);
233
238
  } catch (e) {
234
239
  // jiti + ts-node
235
240
  // issue: https://github.com/nuxt/bridge/issues/228
236
241
  if (isTsNodeRuntimeEnvironment()) {
237
- output = this.loadSync(info);
242
+ output = this.loadSync(input);
238
243
  } else {
239
- output = this.jiti(filePath);
244
+ output = this.jiti(input);
240
245
  }
241
246
  }
242
247
  return output;
243
248
  }
244
- executeSync(info) {
245
- const filePath = buildLoaderFilePath(info);
249
+ executeSync(input) {
246
250
  let output;
247
251
  try {
248
- output = this.loadSync(info);
252
+ output = this.loadSync(input);
249
253
  } catch (e) {
250
- output = this.jiti(filePath);
254
+ output = this.jiti(input);
251
255
  }
252
256
  return output;
253
257
  }
@@ -325,17 +329,17 @@ class ScriptLoader {
325
329
  }
326
330
  }
327
331
  constructor(){
328
- /*
329
- const loaderMap : Record<string, ESLoader> = {
330
- '.mjs': 'js',
331
- '.js': 'js',
332
- '.jsx': 'jsx',
333
- '.ts': 'ts',
334
- '.tsx': 'tsx',
335
- };
336
- */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
332
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
337
333
  // @ts-ignore
338
334
  this.jiti = createJITI(undefined, {
335
+ extensions: [
336
+ '.js',
337
+ '.mjs',
338
+ '.mts',
339
+ '.cjs',
340
+ '.cts',
341
+ '.ts'
342
+ ],
339
343
  esmResolve: true
340
344
  });
341
345
  }
@@ -362,35 +366,59 @@ class JSONLoader {
362
366
  }
363
367
  }
364
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
+
365
380
  class LoaderManager {
366
- register(rule) {
367
- 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);
368
390
  }
369
- async execute(info) {
370
- const rule = this.findRule(info);
371
- if (!rule) {
391
+ async execute(input) {
392
+ const id = this.findLoader(input);
393
+ if (!id) {
394
+ const info = pathToLocatorInfo(input);
372
395
  throw new Error(`No loader registered for extension: "${info.extension}"`);
373
396
  }
374
- const loader = this.resolve(rule.loader);
375
- return loader.execute(info);
397
+ const loader = this.resolve(id);
398
+ return loader.execute(input);
376
399
  }
377
- executeSync(info) {
378
- const rule = this.findRule(info);
379
- if (!rule) {
400
+ executeSync(input) {
401
+ const id = this.findLoader(input);
402
+ if (!id) {
403
+ const info = pathToLocatorInfo(input);
380
404
  throw new Error(`No loader registered for extension: ${info.extension || 'unknown'}`);
381
405
  }
382
- const loader = this.resolve(rule.loader);
383
- return loader.executeSync(info);
406
+ const loader = this.resolve(id);
407
+ return loader.executeSync(input);
384
408
  }
385
- findRule(info) {
409
+ findLoader(input) {
410
+ if (!isFilePath(input)) {
411
+ return LoaderId.MODULE;
412
+ }
413
+ const info = pathToLocatorInfo(input);
386
414
  for(let i = 0; i < this.rules.length; i++){
387
415
  const { test } = this.rules[i];
388
416
  if (Array.isArray(test)) {
389
417
  if (test.indexOf(info.extension) !== -1) {
390
- return this.rules[i];
418
+ return this.rules[i].loader;
391
419
  }
392
420
  } else if (test.test(buildLoaderFilePath(info))) {
393
- return this.rules[i];
421
+ return this.rules[i].loader;
394
422
  }
395
423
  }
396
424
  return undefined;
@@ -403,27 +431,48 @@ class LoaderManager {
403
431
  if (typeof id !== 'string') {
404
432
  return id;
405
433
  }
406
- if (this.loaders[id]) {
434
+ if (Object.prototype.hasOwnProperty.call(this.loaders, id)) {
407
435
  return this.loaders[id];
408
436
  }
409
437
  let loader;
438
+ // built-in
410
439
  switch(id){
411
- case 'script':
440
+ case LoaderId.MODULE:
412
441
  {
413
- loader = new ScriptLoader();
442
+ loader = new ModuleLoader();
414
443
  break;
415
444
  }
416
- case 'json':
445
+ case LoaderId.JSON:
417
446
  {
418
447
  loader = new JSONLoader();
419
448
  break;
420
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
+ }
421
457
  }
422
458
  if (typeof loader !== 'undefined') {
459
+ this.loaders[id] = loader;
423
460
  return loader;
424
461
  }
425
462
  throw new Error(`The loader ${id} could not be resolved.`);
426
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
+ }
427
476
  constructor(){
428
477
  this.loaders = {};
429
478
  this.rules = [
@@ -431,23 +480,25 @@ class LoaderManager {
431
480
  test: [
432
481
  '.js',
433
482
  '.mjs',
483
+ '.mts',
434
484
  '.cjs',
485
+ '.cts',
435
486
  '.ts'
436
487
  ],
437
- loader: 'script'
488
+ loader: LoaderId.MODULE
438
489
  },
439
490
  {
440
491
  test: [
441
492
  '.json'
442
493
  ],
443
- loader: 'json'
494
+ loader: LoaderId.JSON
444
495
  }
445
496
  ];
446
497
  }
447
498
  }
448
499
 
449
500
  let instance;
450
- function useLoaderManager() {
501
+ function useLoader() {
451
502
  if (typeof instance !== 'undefined') {
452
503
  return instance;
453
504
  }
@@ -455,45 +506,50 @@ function useLoaderManager() {
455
506
  return instance;
456
507
  }
457
508
 
458
- async function loadFile(input) {
459
- 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();
460
519
  if (typeof input === 'string') {
461
- info = pathToLocatorInfo(input);
462
- } else {
463
- info = input;
520
+ return manager.execute(input);
464
521
  }
465
- const manager = useLoaderManager();
466
- return manager.execute(info);
522
+ return manager.execute(buildLoaderFilePath(input));
467
523
  }
468
- function loadFileSync(input) {
469
- let info;
524
+ function loadSync(input) {
525
+ const manager = useLoader();
470
526
  if (typeof input === 'string') {
471
- info = pathToLocatorInfo(input);
472
- } else {
473
- info = input;
527
+ return manager.executeSync(input);
474
528
  }
475
- const manager = useLoaderManager();
476
- return manager.executeSync(info);
529
+ return manager.executeSync(buildLoaderFilePath(input));
477
530
  }
478
531
 
479
532
  exports.JSONLoader = JSONLoader;
480
- exports.ScriptLoader = ScriptLoader;
533
+ exports.LoaderManager = LoaderManager;
534
+ exports.ModuleLoader = ModuleLoader;
481
535
  exports.buildLoaderFilePath = buildLoaderFilePath;
482
536
  exports.buildLocatorOptions = buildLocatorOptions;
483
537
  exports.getExportItem = getExportItem;
484
538
  exports.handleFileLoadError = handleFileLoadError;
485
539
  exports.hasOwnProperty = hasOwnProperty;
486
540
  exports.hasStringProperty = hasStringProperty;
541
+ exports.isFilePath = isFilePath;
487
542
  exports.isJestRuntimeEnvironment = isJestRuntimeEnvironment;
488
543
  exports.isObject = isObject;
489
544
  exports.isTsNodeRuntimeEnvironment = isTsNodeRuntimeEnvironment;
490
- exports.loadFile = loadFile;
491
- exports.loadFileSync = loadFileSync;
492
- exports.locateFile = locateFile;
493
- exports.locateFileSync = locateFileSync;
494
- exports.locateFiles = locateFiles;
495
- exports.locateFilesSync = locateFilesSync;
545
+ exports.load = load;
546
+ exports.loadSync = loadSync;
547
+ exports.locate = locate;
548
+ exports.locateMany = locateMany;
549
+ exports.locateManySync = locateManySync;
550
+ exports.locateSync = locateSync;
496
551
  exports.pathToLocatorInfo = pathToLocatorInfo;
552
+ exports.registerLoader = registerLoader;
497
553
  exports.removeFileNameExtension = removeFileNameExtension;
498
554
  exports.toArray = toArray;
499
555
  //# sourceMappingURL=index.cjs.map