Skip to content

Commit

Permalink
Merge pull request redwoodjs#788 from redwoodjs/pp-support-subdirs-in…
Browse files Browse the repository at this point in the history
…-import-dir

Make sub-directories work in import-dir
  • Loading branch information
peterp authored Jul 2, 2020
2 parents 2798f70 + 687abc2 commit 9826c06
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/* eslint-disable */
import services from '../__fixtures__/*.{js,ts}'
import services from '../__fixtures__/**/*.{js,ts}'
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ import * as services_a from '../__fixtures__/a'
services.a = services_a
import * as services_b from '../__fixtures__/b'
services.b = services_b
import * as services_c from '../__fixtures__/c.sdl'
services.c = services_c
import * as services_c_sdl from '../__fixtures__/c.sdl'
services.c_sdl = services_c_sdl
import * as services_nested_d from '../__fixtures__/nested/d'
services.nested_d = services_nested_d
53 changes: 30 additions & 23 deletions packages/core/src/babel-plugin-redwood-import-dir.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ import glob from 'glob'
import type { PluginObj, types } from '@babel/core'

/**
* This babel plugin will search for import statements that include a star "*",
* the source part of the statement is a glob, the files that are matched are imported,
* This babel plugin will search for import statements that include star `*`
* in the source part of the statement is a glob, the files that are matched are imported,
* and appended to an object.
*
* @example:
* Given a directory "src/services" that contains "a.js" and "b.ts", will produce
* the following results
* ```
* import services from 'src/services/*.{js,ts}'
* Given a directory "src/services" that contains "a.js" and "b.ts", "nested/c.js",
* will produce the following results:
* ```js
* import services from 'src/services/**\/*.{js,ts}'
* console.log(services)
* // services.a = require('src/services/a.js')
* // services.b = require('src/services/b.ts')
* // services.nested_c = require('src/services/nested/c.js')
* ```
*
* @todo We **do not** support nested directories.
* @todo Generate ambient declerations for TypeScript of imported files.
*/
export default function ({ types: t }: { types: typeof types }): PluginObj {
return {
name: 'babel-plugin-redwood-import-dir',
visitor: {
ImportDeclaration(p, state: { file?: any }) {
// This code will only run when we find an import statement that includes a "*".
// This code will only run when we find an import statement that includes a `*`.
if (!p.node.source.value.includes('*')) {
return
}
Expand All @@ -45,42 +45,49 @@ export default function ({ types: t }: { types: typeof types }): PluginObj {
])
)

const importGlob = p.node.source.value
const cwd = path.dirname(state.file.opts.filename)
const dirFiles = glob.sync(p.node.source.value, { cwd })

const sourceFilesOnly = dirFiles.filter(
(dirFile) => !dirFile.includes('.test.')
)
for (const filePath of sourceFilesOnly) {
const fileName = path.basename(filePath).split('.')[0]
// + import * as <importName>_<fileName> from <filePath>
const dirFiles = glob
.sync(importGlob, { cwd })
.filter((n) => !n.includes('.test.')) // ignore `*.test.*` files.

const parsedPath = path.parse(filePath)
const staticGlob = importGlob.split('*')[0]
const filePathToVarName = (filePath: string) => {
return filePath
.replace(staticGlob, '')
.replace(/.(js|ts)/, '')
.replace(/[^a-zA-Z0-9]/g, '_')
}

// Do it this way to allow double dots e.g. service/payment/payment.utils.ts
const filePathWithoutExtension = `${parsedPath.dir}/${parsedPath.name}`
for (const filePath of dirFiles) {
const { dir: fileDir, name: fileName } = path.parse(filePath)
const filePathWithoutExtension = fileDir + '/' + fileName
const fpVarName = filePathToVarName(filePath)

// + import * as <importName>_<fpVarName> from <filePathWithoutExtension>
// import * as a from './services/a.j
nodes.push(
t.importDeclaration(
[
t.importNamespaceSpecifier(
t.identifier(importName + '_' + fileName)
t.identifier(importName + '_' + fpVarName)
),
],
t.stringLiteral(filePathWithoutExtension)
)
)

// + <importName>.<fileName> = <importName_fileName>
// + <importName>.<fpVarName> = <importName_fpVarName>
// services.a = a
nodes.push(
t.expressionStatement(
t.assignmentExpression(
'=',
t.memberExpression(
t.identifier(importName),
t.identifier(fileName)
t.identifier(fpVarName)
),
t.identifier(importName + '_' + fileName)
t.identifier(importName + '_' + fpVarName)
)
)
)
Expand Down

0 comments on commit 9826c06

Please sign in to comment.