Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make auto-import pages support .tsx files. #1651

Merged
merged 6 commits into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default () => 'I am a TypeScript page.'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default () => 'I am an page in a subdirectory.'
1 change: 1 addition & 0 deletions packages/internal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"types": "dist/index.d.ts",
"license": "MIT",
"dependencies": {
"glob": "7.1.6",
"deepmerge": "^4.2.2",
"findup-sync": "^4.0.0",
"kill-port": "^1.6.1",
Expand Down
18 changes: 15 additions & 3 deletions packages/internal/src/__tests__/paths.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,26 @@ import { processPagesDir, resolveFile, ensurePosixPath } from '../paths'
describe('paths', () => {
describe('processPagesDir', () => {
it('it accurately finds the pages', () => {
const pagesDir = path.resolve(__dirname, './fixtures/web/src/pages')
const pagesDir = path.resolve(
__dirname,
'../../../../__fixtures__/example-todo-main/web/src/pages'
)
peterp marked this conversation as resolved.
Show resolved Hide resolved

const pages = processPagesDir(pagesDir)
expect(pages[0].importPath).toEqual(
path.join(pagesDir, 'Admin/MargleTheWorld/MargleTheWorld')
path.join(pagesDir, 'admin/EditUserPage/EditUserPage')
)
expect(pages[1].importPath).toEqual(
path.join(pagesDir, 'HelloWorld/HelloWorld')
path.join(pagesDir, 'FatalErrorPage/FatalErrorPage')
)
expect(pages[2].importPath).toEqual(
path.join(pagesDir, 'HomePage/HomePage')
)
expect(pages[3].importPath).toEqual(
path.join(pagesDir, 'NotFoundPage/NotFoundPage')
)
expect(pages[4].importPath).toEqual(
path.join(pagesDir, 'TypeScriptPage/TypeScriptPage')
)
})
})
Expand Down
69 changes: 22 additions & 47 deletions packages/internal/src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'fs'
import path from 'path'

import findUp from 'findup-sync'
import { glob } from 'glob'

import { getConfig } from './config'

Expand Down Expand Up @@ -40,10 +41,15 @@ export interface Paths {
}

export interface PagesDependency {
/** the variable to which the import is assigned */
importName: string
importPath: string
/** @alias importName */
const: string
/** absolute path without extension */
importPath: string
/** absolute path with extension */
path: string
/** const ${importName} = { ...data structure for async imports... } */
importStatement: string
}

Expand Down Expand Up @@ -152,57 +158,26 @@ export const getPaths = (BASE_DIR: string = getBaseDir()): Paths => {
}

/**
* Recursively process the pages directory and return information useful for
* automated imports.
* Process the pages directory and return information useful for automated imports.
*/
export const processPagesDir = (
webPagesDir: string = getPaths().web.pages,
prefix: Array<string> = []
webPagesDir: string = getPaths().web.pages
): Array<PagesDependency> => {
const deps: Array<PagesDependency> = []
const entries = fs.readdirSync(webPagesDir, { withFileTypes: true })

// Iterate over a dir's entries, recursing as necessary into
// subdirectories.
entries.forEach((entry) => {
if (entry.isDirectory()) {
try {
// Actual page js or tsx files reside in a directory of the same
// name (supported by: directory-named-webpack-plugin), so let's
// construct the filename of the actual Page file.
// `require.resolve` will throw if a module cannot be found.
const importPath = path.join(webPagesDir, entry.name, entry.name)
require.resolve(importPath)

// If the Page exists, then construct the dependency object and push it
// onto the deps array.
const basename = path.posix.basename(entry.name)
const importName = prefix.join() + basename
// `src/pages/<PageName>`
const importFile = ['src', 'pages', ...prefix, basename].join('/')
deps.push({
importName,
importPath,
const: importName,
path: path.join(webPagesDir, entry.name),
importStatement: `const ${importName
.split(',')
.join('')} = { name: '${importName
.split(',')
.join('')}', loader: () => import('${importFile}') }`,
})
} catch (e) {
// If the Page doesn't exist then we are in a directory of Page
// directories, so let's recurse into it and do the whole thing over
// again.
const newPrefix = [...prefix, entry.name]
deps.push(
...processPagesDir(path.join(webPagesDir, entry.name), newPrefix)
)
}
const pagePaths = glob.sync('**/**/*Page.{js,jsx,tsx}', { cwd: webPagesDir })
return pagePaths.map((pagePath) => {
const p = path.parse(pagePath)

const importName = p.dir.replace(path.sep, '')
const importPath = path.join(webPagesDir, p.dir, p.name)
const importStatement = `const ${importName} = { name: '${importName}', loader: import('${importPath}') }`
return {
importName,
const: importName,
importPath,
path: path.join(webPagesDir, pagePath),
importStatement,
}
})
return deps
}

/**
Expand Down
9 changes: 2 additions & 7 deletions packages/structure/src/model/RWPage.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { existsSync } from 'fs'
import { dirname } from 'path'

import * as tsm from 'ts-morph'

import { FileNode } from '../ide'
import { lazy } from '../x/decorators'
import { directoryNameResolver } from '../x/path'

import { RWProject } from './RWProject'

Expand All @@ -17,12 +17,7 @@ export class RWPage extends FileNode {
super()
}
@lazy() get filePath() {
const f = directoryNameResolver(this.path)
if (!f)
throw new Error(
`could not resolve index filename for directory '${this.path}' using dirname convention`
)
return f
return this.path
}
@lazy() get route() {
return this.parent.router.routes.find(
Expand Down
8 changes: 7 additions & 1 deletion packages/structure/src/model/__tests__/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ describe('Redwood Project Model', () => {

const pageNames = new Set(project.pages.map((p) => p.basenameNoExt))
expect(pageNames).toEqual(
new Set(['FatalErrorPage', 'HomePage', 'NotFoundPage'])
new Set([
'FatalErrorPage',
'HomePage',
'NotFoundPage',
'TypeScriptPage',
'EditUserPage',
])
)
for (const page of project.pages) {
page.basenameNoExt //?
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10088,7 +10088,7 @@ glob-to-regexp@^0.3.0:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab"
integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=

glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
Expand Down