Skip to content

Commit

Permalink
[glob-modules] Add support for resolving parent and nested modules
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronccasanova committed Jan 16, 2023
1 parent 9607735 commit 273d76a
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/pretty-cups-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'glob-modules': patch
---

Added support for resolving parent and nested modules
65 changes: 65 additions & 0 deletions packages/glob-modules/playground/nested/playground.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as path from 'node:path'
import * as url from 'node:url'
import { globModules as globModulesRaw } from '../../dist/esm/index.mjs'

/** @type {import('../../dist/types/index.js').globModules} */
// @ts-ignore
const globModules = globModulesRaw

const __dirname = path.dirname(url.fileURLToPath(import.meta.url))

const modules = await globModules('../modules/*.mjs', {
importMeta: import.meta,
})
console.log('modules:', modules)
/* {
modules: {
one: { default: 1, one: 'one' },
two: { default: 2 },
four: { default: 4 },
},
} */

const nestedModules = await globModules('../modules/nested-modules/*.mjs', {
importMeta: import.meta,
})
console.log('nestedModules:', nestedModules)
/* {
modules: {
'nested-modules': {
five: 5,
six: 6,
eight: 8,
},
},
} */

const allModules = await globModules('../modules/**/*.mjs', {
cwd: __dirname,
})
console.log('allModules:', allModules)
/* {
modules: {
one: { default: 1 },
two: { default: 2 },
four: { default: 4 },
'nested-modules': {
five: 5,
six: 6,
eight: 8,
},
},
} */

const cjsModules = await globModules('../modules/**/*.js', {
cwd: __dirname,
})
console.log('cjsModules:', cjsModules)
/* {
modules: {
three: { default: 3 },
'nested-modules': {
seven: 8,
},
},
} */
6 changes: 4 additions & 2 deletions packages/glob-modules/playground/playground.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
const modules = await globModules('./modules/*.mjs', {
importMeta: import.meta,
})
console.log('modules:', modules)
/* {
modules: {
one: { default: 1, one: 'one' },
Expand All @@ -22,6 +23,7 @@ const modules = await globModules('./modules/*.mjs', {
const nestedModules = await globModules('./modules/nested-modules/*.mjs', {
importMeta: import.meta,
})
console.log('nestedModules:', nestedModules)
/* {
modules: {
'nested-modules': {
Expand All @@ -35,6 +37,7 @@ const nestedModules = await globModules('./modules/nested-modules/*.mjs', {
const allModules = await globModules('./modules/**/*.mjs', {
cwd: __dirname,
})
console.log('allModules:', allModules)
/* {
modules: {
one: { default: 1 },
Expand All @@ -51,6 +54,7 @@ const allModules = await globModules('./modules/**/*.mjs', {
const cjsModules = await globModules('./modules/**/*.js', {
cwd: __dirname,
})
console.log('cjsModules:', cjsModules)
/* {
modules: {
three: { default: 3 },
Expand All @@ -59,5 +63,3 @@ const cjsModules = await globModules('./modules/**/*.js', {
},
},
} */

console.log('allModules:', JSON.stringify(allModules, null, 2))
54 changes: 39 additions & 15 deletions packages/glob-modules/src/glob-modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function getCWD(options: GlobModulesCWDOptions) {
return path.dirname(url.fileURLToPath(options.importMeta.url))
}

throw new Error('globModules: cwd or importMeta must be specified')
throw new Error('`options.cwd` or `options.importMeta` must be specified')
}

type GlobbyParameters = Parameters<typeof globby>
Expand Down Expand Up @@ -43,29 +43,53 @@ export async function globModules<T extends GlobModulesResult>(

const modules: GlobModulesResult = {}

const modulePaths = await globby(patterns, { cwd })
const modulePaths = await globby(patterns, {
absolute: true,
cwd,
})

for (const modulePath of modulePaths) {
const moduleSpecifier = path.join(cwd, modulePath)
if (!modulePaths.length) {
throw new Error(`Cannot find modules for patterns: ${patterns.toString()}`)
}

const moduleName = path.parse(moduleSpecifier).name
const commonParentModuleDir = getCommonParentModuleDir(cwd, modulePaths)

const moduleSegments = moduleSpecifier
.replace(`${cwd}${path.sep}`, '')
.split(path.sep)
.filter(Boolean)
for (const modulePath of modulePaths) {
// TODO: Investigate a Promise.all() implementation.
// eslint-disable-next-line no-await-in-loop
const mod = (await import(modulePath)) as { [modName: string]: any }

// NOTE: This POC assumes only one extension type was
// used in the glob pattern.
moduleSegments[moduleSegments.length - 1] = moduleName
const moduleSegments = modulePath
.slice(1)
.replace(`${commonParentModuleDir}${path.sep}`, '')
.split(path.sep)

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, no-await-in-loop
const mod: { [modName: string]: any } = await import(moduleSpecifier)
// NOTE: This POC assumes only one extension type was used in the glob pattern.
moduleSegments[moduleSegments.length - 1] = path.parse(modulePath).name

for (const modName of Object.keys(mod)) {
safeSet(modules, [...moduleSegments, modName], mod[modName])
safeSet(modules, moduleSegments.concat(modName), mod[modName])
}
}

return modules as T
}

function getCommonParentModuleDir(cwd: string, modulePaths: string[]) {
// NOTE: All paths are assumed to be absolute.
const commonParentModuleSegments = cwd.slice(1).split(path.sep)

for (const modulePath of modulePaths) {
const moduleSegments = modulePath.slice(1).split(path.sep)

for (const [i, moduleSegment] of moduleSegments.entries()) {
if (moduleSegment !== commonParentModuleSegments[i]) {
commonParentModuleSegments.splice(i, Infinity) // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice#deletecount

break
}
}
}

return commonParentModuleSegments.join(path.sep)
}

3 comments on commit 273d76a

@vercel
Copy link

@vercel vercel bot commented on 273d76a Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

aacc-next-ts – ./recipes/next-ts

aacc-next-ts-aaronccasanova.vercel.app
aacc-next-ts-git-main-aaronccasanova.vercel.app
aacc-next-ts.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 273d76a Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

aacc-scales – ./apps/scales

aacc-scales-git-main-aaronccasanova.vercel.app
aacc-scales.vercel.app
aacc-scales-aaronccasanova.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 273d76a Jan 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

aacc-next-ts-styled-comps – ./recipes/next-ts-styled-comps

aacc-next-ts-styled-comps-git-main-aaronccasanova.vercel.app
aacc-next-ts-styled-comps-aaronccasanova.vercel.app
aacc-next-ts-styled-comps.vercel.app

Please sign in to comment.