Skip to content

Commit

Permalink
feat(module): add new helper Module
Browse files Browse the repository at this point in the history
  • Loading branch information
jlenon7 committed Jul 6, 2022
1 parent 43365f3 commit 545c356
Show file tree
Hide file tree
Showing 9 changed files with 381 additions and 35 deletions.
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,81 @@ console.log(sortedValue) // a, b or c

---

### Module

> Use Module to resolve modules exports, import modules using hrefs' ensuring compatibility between OS's, creating
> aliases for your modules exports and creating __filename and __dirname properties.
```ts
import { Module } from '@secjs/utils'

const module = await Module.get(import('#src/Helpers/Options'))

console.log(module.name) // Options
```

```ts
import { Module } from '@secjs/utils'

const modules = await Module.getAll([import('#src/Helpers/Number'), import('#src/Helpers/Options')])

console.log(modules[0].name) // Number
console.log(modules[1].name) // Options
```

```ts
import { Module } from '@secjs/utils'

const modules = await Module.getAllWithAlias([
import('#src/Helpers/Number'),
import('#src/Helpers/Options')
], 'App/Helpers')

console.log(modules[0].module.name) // Number
console.log(modules[0].alias) // 'App/Helpers/Number'

console.log(modules[1].module.name) // Options
console.log(modules[1].alias) // 'App/Helpers/Options'
```

```ts
import { Path, Module } from '@secjs/utils'

const module = await Module.getFrom(Path.config('app.js'))

console.log(module.name) // Athenna
console.log(module.description) // Athenna application
console.log(module.environment) // production
```

```ts
import { Path, Module } from '@secjs/utils'

const modules = await Module.getAllFromWithAlias(Path.config(), 'App/Configs')
const appConfigFile = module[0].module
const appConfigAlias = module[0].alias

console.log(appConfigAlias) // App/Configs/App
console.log(appConfigFile.name) // Athenna
console.log(appConfigFile.description) // Athenna application
console.log(appConfigFile.environment) // production
```

```ts
import { Module } from '@secjs/utils'

const setInGlobalTrue = true
const setInGlobalFalse = false

const dirname = Module.createDirname(setInGlobalFalse)
const filename = Module.createFilename(setInGlobalTrue)

console.log(__dirname) // Error! __dirname is not defined in global
console.log(__filename) // '/Users/...'
```

---

### Route

> Use Route to manipulate paths, getParams, getQueryParams, create route matcher RegExp etc.
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@secjs/utils",
"version": "1.9.4",
"version": "1.9.5",
"description": "Utils functions and classes for Node.js",
"license": "MIT",
"author": "João Lenon <lenon@athenna.io>",
Expand Down Expand Up @@ -64,7 +64,7 @@
"@japa/run-failed-tests": "1.0.7",
"@japa/runner": "2.0.7",
"@japa/spec-reporter": "1.1.12",
"@otris/jsdoc-tsd": "^2.0.11",
"@otris/jsdoc-tsd": "2.0.11",
"c8": "7.11.2",
"commitizen": "4.2.4",
"cross-env": "7.0.3",
Expand Down
16 changes: 0 additions & 16 deletions src/Helpers/Exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,20 +146,4 @@ export class Exec {

return { meta, links, data }
}

/**
* Get the module first export match or default.
*
* @param {any,Promise<any>} module
* @return {Promise<any>}
*/
static async getModule(module) {
module = await module

if (module.default) {
return module.default
}

return module[Object.keys(module)[0]]
}
}
188 changes: 188 additions & 0 deletions src/Helpers/Module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { dirname } from 'node:path'
import { fileURLToPath, pathToFileURL } from 'node:url'

import { Folder } from '#src/index'

export class Module {
/**
* Get the module first export match or default.
*
* @param {any|Promise<any>} module
* @return {Promise<any>}
*/
static async get(module) {
module = await module

if (module.default) {
return module.default
}

return module[Object.keys(module)[0]]
}

/**
* Get the module first export match or default with alias.
*
* @param {any|Promise<any>} module
* @param {string} subAlias
* @return {Promise<{ alias: string, module: any }>}
*/
static async getWithAlias(module, subAlias) {
module = await Module.get(module)

if (!subAlias.endsWith('/')) {
subAlias = subAlias.concat('/')
}

const alias = subAlias.concat(module.name)

return { alias, module }
}

/**
* Get all modules first export match or default and return
* as array.
*
* @param {any[]|Promise<any[]>} modules
* @return {Promise<any[]>}
*/
static async getAll(modules) {
const promises = modules.map(m => Module.get(m))

return Promise.all(promises)
}

/**
* Get all modules first export match or default with alias and return
* as array.
*
* @param {any[]|Promise<any[]>} modules
* @param {string} subAlias
* @return {Promise<any[]>}
*/
static async getAllWithAlias(modules, subAlias) {
const promises = modules.map(m => Module.getWithAlias(m, subAlias))

return Promise.all(promises)
}

/**
* Same as get method, but import the path directly.
*
* @param {string} path
* @return {Promise<any>}
*/
static async getFrom(path) {
const module = await Module.import(path)

return Module.get(module)
}

/**
* Same as getWithAlias method, but import the path directly.
*
* @param {string} path
* @param {string} subAlias
* @return {Promise<{ alias: string, module: any }>}
*/
static async getFromWithAlias(path, subAlias) {
const module = await Module.import(path)

return Module.getWithAlias(module, subAlias)
}

/**
* Same as getAll method but import everything in the path directly.
*
* @param {string} path
* @return {Promise<any[]>}
*/
static async getAllFrom(path) {
const files = await Module.getAllJSFilesFrom(path)

const promises = files.map(file => Module.getFrom(file.path))

return Promise.all(promises)
}

/**
* Same as getAllWithAlias method but import everything in the path directly.
*
* @param {string} path
* @param {string} subAlias
* @return {Promise<{ alias: string, module: any }[]>}
*/
static async getAllFromWithAlias(path, subAlias) {
const files = await Module.getAllJSFilesFrom(path)

const promises = files.map(f => Module.getFromWithAlias(f.path, subAlias))

return Promise.all(promises)
}

/**
* Verify if folder exists and get all .js files inside.
*
* @param {string} path
* @return {Promise<File[]>}
*/
static async getAllJSFilesFrom(path) {
if (!(await Folder.exists(path))) {
return []
}

if (!(await Folder.isFolder(path))) {
return []
}

const folder = await new Folder(path).load()

// FIXME Why glob pattern *.js is retrieving .d.ts and .js.map files?
return folder
.getFilesByPattern('*/**/*.js', true)
.filter(file => file.extension.endsWith('.js'))
}

/**
* Import a full path using the path href to ensure compatibility
* between OS's.
*
* @param {string} path
* @return {Promise<any>}
*/
static async import(path) {
return import(pathToFileURL(path).href)
}

/**
* Create the __dirname property. Set in global if necessary.
*
* @param {boolean} setInGlobal
* @return {string}
*/
static createDirname(setInGlobal = false) {
const __dirname = dirname(Module.createFilename(false))

if (setInGlobal) {
global.__dirname = __dirname
}

return __dirname
}

/**
* Create the __filename property. Set in global if necessary.
*
* @param {boolean} setInGlobal
* @return {string}
*/
static createFilename(setInGlobal = false) {
const __filename = fileURLToPath(import.meta.url)

if (setInGlobal) {
global.__filename = __filename
}

return __filename
}
}
31 changes: 28 additions & 3 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,6 @@ export declare class Exec {
total: number,
pagination: PaginationContract,
): PaginatedResponse

static getModule(module: any | Promise<any>): Promise<any>
}

export declare class File {
Expand All @@ -170,7 +168,7 @@ export declare class File {
public base: string

public path: string

public href: string

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

export class Module {
static get(module: any | Promise<any>): Promise<any>

static getWithAlias(module: any | Promise<any>, subAlias: string): Promise<{ alias: string, module: any }>

static getAll(modules: any[] | Promise<any[]>): Promise<any[]>

static getAllWithAlias(modules: any[] | Promise<any[]>, subAlias: string): Promise<{ alias: string, module: any }[]>

static getFrom(path: string): Promise<any>

static getFromWithAlias(path: string, subAlias: string): Promise<{ alias: string, module: any }>

static getAllFrom(path: string): Promise<any>

static getAllFromWithAlias(path: string, subAlias: string): Promise<{ alias: string, module: any }[]>

static getAllJSFilesFrom(path: string): Promise<File[]>

static import(path: string): Promise<any>

static createDirname(setInGlobal?: boolean): string

static createFilename(setInGlobal?: boolean): string
}


export declare class Number {
static getHigher(numbers: number[]): number

Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export * from './Helpers/File.js'
export * from './Helpers/Folder.js'
export * from './Helpers/Is.js'
export * from './Helpers/Json.js'
export * from './Helpers/Module.js'
export * from './Helpers/Number.js'
export * from './Helpers/Options.js'
export * from './Helpers/Parser.js'
Expand Down
Loading

0 comments on commit 545c356

Please sign in to comment.