Skip to content

Commit 0ba90e1

Browse files
authored
Merge pull request #53 from SecJS/feat/len-create-module-helper
feat(module): add new helper Module
2 parents 3bc443c + 545c356 commit 0ba90e1

File tree

9 files changed

+381
-35
lines changed

9 files changed

+381
-35
lines changed

README.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,81 @@ console.log(sortedValue) // a, b or c
481481

482482
---
483483

484+
### Module
485+
486+
> Use Module to resolve modules exports, import modules using hrefs' ensuring compatibility between OS's, creating
487+
> aliases for your modules exports and creating __filename and __dirname properties.
488+
489+
```ts
490+
import { Module } from '@secjs/utils'
491+
492+
const module = await Module.get(import('#src/Helpers/Options'))
493+
494+
console.log(module.name) // Options
495+
```
496+
497+
```ts
498+
import { Module } from '@secjs/utils'
499+
500+
const modules = await Module.getAll([import('#src/Helpers/Number'), import('#src/Helpers/Options')])
501+
502+
console.log(modules[0].name) // Number
503+
console.log(modules[1].name) // Options
504+
```
505+
506+
```ts
507+
import { Module } from '@secjs/utils'
508+
509+
const modules = await Module.getAllWithAlias([
510+
import('#src/Helpers/Number'),
511+
import('#src/Helpers/Options')
512+
], 'App/Helpers')
513+
514+
console.log(modules[0].module.name) // Number
515+
console.log(modules[0].alias) // 'App/Helpers/Number'
516+
517+
console.log(modules[1].module.name) // Options
518+
console.log(modules[1].alias) // 'App/Helpers/Options'
519+
```
520+
521+
```ts
522+
import { Path, Module } from '@secjs/utils'
523+
524+
const module = await Module.getFrom(Path.config('app.js'))
525+
526+
console.log(module.name) // Athenna
527+
console.log(module.description) // Athenna application
528+
console.log(module.environment) // production
529+
```
530+
531+
```ts
532+
import { Path, Module } from '@secjs/utils'
533+
534+
const modules = await Module.getAllFromWithAlias(Path.config(), 'App/Configs')
535+
const appConfigFile = module[0].module
536+
const appConfigAlias = module[0].alias
537+
538+
console.log(appConfigAlias) // App/Configs/App
539+
console.log(appConfigFile.name) // Athenna
540+
console.log(appConfigFile.description) // Athenna application
541+
console.log(appConfigFile.environment) // production
542+
```
543+
544+
```ts
545+
import { Module } from '@secjs/utils'
546+
547+
const setInGlobalTrue = true
548+
const setInGlobalFalse = false
549+
550+
const dirname = Module.createDirname(setInGlobalFalse)
551+
const filename = Module.createFilename(setInGlobalTrue)
552+
553+
console.log(__dirname) // Error! __dirname is not defined in global
554+
console.log(__filename) // '/Users/...'
555+
```
556+
557+
---
558+
484559
### Route
485560

486561
> Use Route to manipulate paths, getParams, getQueryParams, create route matcher RegExp etc.

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@secjs/utils",
3-
"version": "1.9.4",
3+
"version": "1.9.5",
44
"description": "Utils functions and classes for Node.js",
55
"license": "MIT",
66
"author": "João Lenon <lenon@athenna.io>",
@@ -64,7 +64,7 @@
6464
"@japa/run-failed-tests": "1.0.7",
6565
"@japa/runner": "2.0.7",
6666
"@japa/spec-reporter": "1.1.12",
67-
"@otris/jsdoc-tsd": "^2.0.11",
67+
"@otris/jsdoc-tsd": "2.0.11",
6868
"c8": "7.11.2",
6969
"commitizen": "4.2.4",
7070
"cross-env": "7.0.3",

src/Helpers/Exec.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -146,20 +146,4 @@ export class Exec {
146146

147147
return { meta, links, data }
148148
}
149-
150-
/**
151-
* Get the module first export match or default.
152-
*
153-
* @param {any,Promise<any>} module
154-
* @return {Promise<any>}
155-
*/
156-
static async getModule(module) {
157-
module = await module
158-
159-
if (module.default) {
160-
return module.default
161-
}
162-
163-
return module[Object.keys(module)[0]]
164-
}
165149
}

src/Helpers/Module.js

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import { dirname } from 'node:path'
2+
import { fileURLToPath, pathToFileURL } from 'node:url'
3+
4+
import { Folder } from '#src/index'
5+
6+
export class Module {
7+
/**
8+
* Get the module first export match or default.
9+
*
10+
* @param {any|Promise<any>} module
11+
* @return {Promise<any>}
12+
*/
13+
static async get(module) {
14+
module = await module
15+
16+
if (module.default) {
17+
return module.default
18+
}
19+
20+
return module[Object.keys(module)[0]]
21+
}
22+
23+
/**
24+
* Get the module first export match or default with alias.
25+
*
26+
* @param {any|Promise<any>} module
27+
* @param {string} subAlias
28+
* @return {Promise<{ alias: string, module: any }>}
29+
*/
30+
static async getWithAlias(module, subAlias) {
31+
module = await Module.get(module)
32+
33+
if (!subAlias.endsWith('/')) {
34+
subAlias = subAlias.concat('/')
35+
}
36+
37+
const alias = subAlias.concat(module.name)
38+
39+
return { alias, module }
40+
}
41+
42+
/**
43+
* Get all modules first export match or default and return
44+
* as array.
45+
*
46+
* @param {any[]|Promise<any[]>} modules
47+
* @return {Promise<any[]>}
48+
*/
49+
static async getAll(modules) {
50+
const promises = modules.map(m => Module.get(m))
51+
52+
return Promise.all(promises)
53+
}
54+
55+
/**
56+
* Get all modules first export match or default with alias and return
57+
* as array.
58+
*
59+
* @param {any[]|Promise<any[]>} modules
60+
* @param {string} subAlias
61+
* @return {Promise<any[]>}
62+
*/
63+
static async getAllWithAlias(modules, subAlias) {
64+
const promises = modules.map(m => Module.getWithAlias(m, subAlias))
65+
66+
return Promise.all(promises)
67+
}
68+
69+
/**
70+
* Same as get method, but import the path directly.
71+
*
72+
* @param {string} path
73+
* @return {Promise<any>}
74+
*/
75+
static async getFrom(path) {
76+
const module = await Module.import(path)
77+
78+
return Module.get(module)
79+
}
80+
81+
/**
82+
* Same as getWithAlias method, but import the path directly.
83+
*
84+
* @param {string} path
85+
* @param {string} subAlias
86+
* @return {Promise<{ alias: string, module: any }>}
87+
*/
88+
static async getFromWithAlias(path, subAlias) {
89+
const module = await Module.import(path)
90+
91+
return Module.getWithAlias(module, subAlias)
92+
}
93+
94+
/**
95+
* Same as getAll method but import everything in the path directly.
96+
*
97+
* @param {string} path
98+
* @return {Promise<any[]>}
99+
*/
100+
static async getAllFrom(path) {
101+
const files = await Module.getAllJSFilesFrom(path)
102+
103+
const promises = files.map(file => Module.getFrom(file.path))
104+
105+
return Promise.all(promises)
106+
}
107+
108+
/**
109+
* Same as getAllWithAlias method but import everything in the path directly.
110+
*
111+
* @param {string} path
112+
* @param {string} subAlias
113+
* @return {Promise<{ alias: string, module: any }[]>}
114+
*/
115+
static async getAllFromWithAlias(path, subAlias) {
116+
const files = await Module.getAllJSFilesFrom(path)
117+
118+
const promises = files.map(f => Module.getFromWithAlias(f.path, subAlias))
119+
120+
return Promise.all(promises)
121+
}
122+
123+
/**
124+
* Verify if folder exists and get all .js files inside.
125+
*
126+
* @param {string} path
127+
* @return {Promise<File[]>}
128+
*/
129+
static async getAllJSFilesFrom(path) {
130+
if (!(await Folder.exists(path))) {
131+
return []
132+
}
133+
134+
if (!(await Folder.isFolder(path))) {
135+
return []
136+
}
137+
138+
const folder = await new Folder(path).load()
139+
140+
// FIXME Why glob pattern *.js is retrieving .d.ts and .js.map files?
141+
return folder
142+
.getFilesByPattern('*/**/*.js', true)
143+
.filter(file => file.extension.endsWith('.js'))
144+
}
145+
146+
/**
147+
* Import a full path using the path href to ensure compatibility
148+
* between OS's.
149+
*
150+
* @param {string} path
151+
* @return {Promise<any>}
152+
*/
153+
static async import(path) {
154+
return import(pathToFileURL(path).href)
155+
}
156+
157+
/**
158+
* Create the __dirname property. Set in global if necessary.
159+
*
160+
* @param {boolean} setInGlobal
161+
* @return {string}
162+
*/
163+
static createDirname(setInGlobal = false) {
164+
const __dirname = dirname(Module.createFilename(false))
165+
166+
if (setInGlobal) {
167+
global.__dirname = __dirname
168+
}
169+
170+
return __dirname
171+
}
172+
173+
/**
174+
* Create the __filename property. Set in global if necessary.
175+
*
176+
* @param {boolean} setInGlobal
177+
* @return {string}
178+
*/
179+
static createFilename(setInGlobal = false) {
180+
const __filename = fileURLToPath(import.meta.url)
181+
182+
if (setInGlobal) {
183+
global.__filename = __filename
184+
}
185+
186+
return __filename
187+
}
188+
}

src/index.d.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,6 @@ export declare class Exec {
150150
total: number,
151151
pagination: PaginationContract,
152152
): PaginatedResponse
153-
154-
static getModule(module: any | Promise<any>): Promise<any>
155153
}
156154

157155
export declare class File {
@@ -170,7 +168,7 @@ export declare class File {
170168
public base: string
171169

172170
public path: string
173-
171+
174172
public href: string
175173

176174
public isCopy: boolean
@@ -416,6 +414,33 @@ export declare class Json {
416414
static get(object: any, key: string, defaultValue?: any): any | undefined
417415
}
418416

417+
export class Module {
418+
static get(module: any | Promise<any>): Promise<any>
419+
420+
static getWithAlias(module: any | Promise<any>, subAlias: string): Promise<{ alias: string, module: any }>
421+
422+
static getAll(modules: any[] | Promise<any[]>): Promise<any[]>
423+
424+
static getAllWithAlias(modules: any[] | Promise<any[]>, subAlias: string): Promise<{ alias: string, module: any }[]>
425+
426+
static getFrom(path: string): Promise<any>
427+
428+
static getFromWithAlias(path: string, subAlias: string): Promise<{ alias: string, module: any }>
429+
430+
static getAllFrom(path: string): Promise<any>
431+
432+
static getAllFromWithAlias(path: string, subAlias: string): Promise<{ alias: string, module: any }[]>
433+
434+
static getAllJSFilesFrom(path: string): Promise<File[]>
435+
436+
static import(path: string): Promise<any>
437+
438+
static createDirname(setInGlobal?: boolean): string
439+
440+
static createFilename(setInGlobal?: boolean): string
441+
}
442+
443+
419444
export declare class Number {
420445
static getHigher(numbers: number[]): number
421446

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export * from './Helpers/File.js'
1717
export * from './Helpers/Folder.js'
1818
export * from './Helpers/Is.js'
1919
export * from './Helpers/Json.js'
20+
export * from './Helpers/Module.js'
2021
export * from './Helpers/Number.js'
2122
export * from './Helpers/Options.js'
2223
export * from './Helpers/Parser.js'

0 commit comments

Comments
 (0)