refactor: more reliable import map generation, supporting turbopack and tsconfig basePath (#11618)
This simplifies and cleans up import map generation and adds support for turbopack, as well as the tsconfig `compilerOptions.basePath` property.
Previously, relative import paths looked like this:
```ts
import { TestComponent as ___ } from 'test/admin/components/TestComponent.js'
```
Paths like these will be resolved based on the `compilerOptions.baseUrl` path of your tsconfig.
This had 2 problems:
### baseUrl support
If your tsconfig baseUrl was not `"."`, this did not work, as the import map generator does not respect it
### Turbopack support
If Turbopack was used, certain import paths were not able to be resolved.
For example, if your component is outside the `baseDir`, the generated path looked like this:
```ts
import { TestComponent as ___ } from '/../test/admin/components/TestComponent.js'
```
This works fine in webpack, but breaks in turbopack.
## Solution
This PR ensures all import paths are relative, making them more predictable and reliable.
The same component will now generate the following import path which works in Turbopack and if a different `compilerOptions.basePath` property is set:
```ts
import { TestComponent as ___ } from '../../../test/admin/components/TestComponent.js'
```
It also adds unit tests
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
import type { PayloadComponent } from '../../index.js'
|
||||
import { addPayloadComponentToImportMap } from './utilities/addPayloadComponentToImportMap.js'
|
||||
import { getImportMapToBaseDirPath } from './utilities/getImportMapToBaseDirPath.js'
|
||||
|
||||
describe('addPayloadComponentToImportMap', () => {
|
||||
let importMap: Record<string, string>
|
||||
let imports: Record<
|
||||
string,
|
||||
{
|
||||
path: string
|
||||
specifier: string
|
||||
}
|
||||
>
|
||||
|
||||
beforeEach(() => {
|
||||
importMap = {}
|
||||
imports = {}
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
function componentPathTest({
|
||||
baseDir,
|
||||
importMapFilePath,
|
||||
payloadComponent,
|
||||
expectedPath,
|
||||
expectedSpecifier,
|
||||
expectedImportMapToBaseDirPath,
|
||||
}: {
|
||||
baseDir: string
|
||||
importMapFilePath: string
|
||||
payloadComponent: PayloadComponent
|
||||
expectedPath: string
|
||||
expectedImportMapToBaseDirPath: string
|
||||
expectedSpecifier: string
|
||||
}) {
|
||||
const importMapToBaseDirPath = getImportMapToBaseDirPath({
|
||||
baseDir,
|
||||
importMapPath: importMapFilePath,
|
||||
})
|
||||
|
||||
expect(importMapToBaseDirPath).toBe(expectedImportMapToBaseDirPath)
|
||||
|
||||
const { path, specifier } =
|
||||
addPayloadComponentToImportMap({
|
||||
importMapToBaseDirPath,
|
||||
importMap,
|
||||
imports,
|
||||
payloadComponent,
|
||||
}) ?? {}
|
||||
|
||||
expect(path).toBe(expectedPath)
|
||||
expect(specifier).toBe(expectedSpecifier)
|
||||
}
|
||||
|
||||
it('relative path with import map partially in base dir', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/myPackage/test/myTest',
|
||||
importMapFilePath: '/myPackage/app/(payload)/importMap.js',
|
||||
payloadComponent: './MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../test/myTest/',
|
||||
expectedPath: '../../test/myTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map partially in base dir 2', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/myPackage/test/myTest',
|
||||
importMapFilePath: '/myPackage/test/prod/app/(payload)/importMap.js',
|
||||
payloadComponent: {
|
||||
path: './MyComponent.js#MyExport',
|
||||
},
|
||||
expectedImportMapToBaseDirPath: '../../../myTest/',
|
||||
expectedPath: '../../../myTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map partially in base dir 3', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/myPackage/test/myTest',
|
||||
importMapFilePath: '/myPackage/test/prod/app/(payload)/importMap.js',
|
||||
payloadComponent: {
|
||||
path: '../otherTest/MyComponent.js',
|
||||
exportName: 'MyExport',
|
||||
},
|
||||
expectedImportMapToBaseDirPath: '../../../myTest/',
|
||||
expectedPath: '../../../otherTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map within base dir', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/myPackage/test/myTest',
|
||||
importMapFilePath: '/myPackage/test/myTest/prod/app/(payload)/importMap.js',
|
||||
payloadComponent: './MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../../',
|
||||
expectedPath: '../../../MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map not in base dir', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/app/(payload)/importMap.js',
|
||||
payloadComponent: './MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../test/myTest/',
|
||||
expectedPath: '../../test/myTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map not in base dir 2', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/app/(payload)/importMap.js',
|
||||
payloadComponent: '../myOtherTest/MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../test/myTest/',
|
||||
expectedPath: '../../test/myOtherTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map not in base dir, baseDir ending with slash', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest/',
|
||||
importMapFilePath: '/app/(payload)/importMap.js',
|
||||
payloadComponent: './MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../test/myTest/',
|
||||
expectedPath: '../../test/myTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path with import map not in base dir, component starting with slash', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/app/(payload)/importMap.js',
|
||||
payloadComponent: '/MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../test/myTest/',
|
||||
expectedPath: '../../test/myTest/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('aliased path', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/app/(payload)/importMap.js',
|
||||
payloadComponent: '@components/MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../../test/myTest/',
|
||||
expectedPath: '@components/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
it('aliased path in PayloadComponent object', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/',
|
||||
importMapFilePath: '/app/(payload)/importMap.js',
|
||||
payloadComponent: {
|
||||
path: '@components/MyComponent.js',
|
||||
},
|
||||
expectedImportMapToBaseDirPath: '../../test/',
|
||||
expectedPath: '@components/MyComponent.js',
|
||||
expectedSpecifier: 'default',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path import starting with slash, going up', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/test/myTest/app/importMap.js',
|
||||
payloadComponent: '/../MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../',
|
||||
expectedPath: '../../MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('relative path import starting with dot-slash, going up', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/test/myTest/app/importMap.js',
|
||||
payloadComponent: './../MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: '../',
|
||||
expectedPath: '../../MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('importMap and baseDir in same directory', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest',
|
||||
importMapFilePath: '/test/myTest/importMap.js',
|
||||
payloadComponent: './MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: './',
|
||||
expectedPath: './MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
|
||||
it('baseDir within importMap dir', () => {
|
||||
componentPathTest({
|
||||
baseDir: '/test/myTest/components',
|
||||
importMapFilePath: '/test/myTest/importMap.js',
|
||||
payloadComponent: './MyComponent.js#MyExport',
|
||||
expectedImportMapToBaseDirPath: './components/',
|
||||
expectedPath: './components/MyComponent.js',
|
||||
expectedSpecifier: 'MyExport',
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,12 +1,13 @@
|
||||
import crypto from 'crypto'
|
||||
/* eslint-disable no-console */
|
||||
import fs from 'fs'
|
||||
import process from 'node:process'
|
||||
import path from 'path'
|
||||
|
||||
import type { PayloadComponent, SanitizedConfig } from '../../config/types.js'
|
||||
|
||||
import { iterateConfig } from './iterateConfig.js'
|
||||
import { parsePayloadComponent } from './parsePayloadComponent.js'
|
||||
import { addPayloadComponentToImportMap } from './utilities/addPayloadComponentToImportMap.js'
|
||||
import { getImportMapToBaseDirPath } from './utilities/getImportMapToBaseDirPath.js'
|
||||
import { resolveImportMapFilePath } from './utilities/resolveImportMapFilePath.js'
|
||||
|
||||
type ImportIdentifier = string
|
||||
type ImportSpecifier = string
|
||||
@@ -37,54 +38,6 @@ export type ImportMap = {
|
||||
[path: UserImportPath]: any
|
||||
}
|
||||
|
||||
export function addPayloadComponentToImportMap({
|
||||
baseDir,
|
||||
importMap,
|
||||
imports,
|
||||
payloadComponent,
|
||||
}: {
|
||||
baseDir: string
|
||||
importMap: InternalImportMap
|
||||
imports: Imports
|
||||
payloadComponent: PayloadComponent
|
||||
}) {
|
||||
if (!payloadComponent) {
|
||||
return
|
||||
}
|
||||
const { exportName, path: componentPath } = parsePayloadComponent(payloadComponent)
|
||||
|
||||
if (importMap[componentPath + '#' + exportName]) {
|
||||
return
|
||||
}
|
||||
|
||||
const importIdentifier =
|
||||
exportName + '_' + crypto.createHash('md5').update(componentPath).digest('hex')
|
||||
|
||||
// e.g. if baseDir is /test/fields and componentPath is /components/Field.tsx
|
||||
// then path needs to be /test/fields/components/Field.tsx NOT /users/username/project/test/fields/components/Field.tsx
|
||||
// so we need to append baseDir to componentPath
|
||||
|
||||
if (componentPath.startsWith('.') || componentPath.startsWith('/')) {
|
||||
const normalizedBaseDir = baseDir.replace(/\\/g, '/')
|
||||
|
||||
const finalPath = normalizedBaseDir.startsWith('/../')
|
||||
? `${normalizedBaseDir}${componentPath.slice(1)}`
|
||||
: path.posix.join(normalizedBaseDir, componentPath.slice(1))
|
||||
|
||||
imports[importIdentifier] = {
|
||||
path:
|
||||
componentPath.startsWith('.') || componentPath.startsWith('/') ? finalPath : componentPath,
|
||||
specifier: exportName,
|
||||
}
|
||||
} else {
|
||||
imports[importIdentifier] = {
|
||||
path: componentPath,
|
||||
specifier: exportName,
|
||||
}
|
||||
}
|
||||
importMap[componentPath + '#' + exportName] = importIdentifier
|
||||
}
|
||||
|
||||
export type AddToImportMap = (payloadComponent: PayloadComponent | PayloadComponent[]) => void
|
||||
|
||||
export async function generateImportMap(
|
||||
@@ -100,49 +53,21 @@ export async function generateImportMap(
|
||||
const importMap: InternalImportMap = {}
|
||||
const imports: Imports = {}
|
||||
|
||||
// Determine the root directory of the project - usually the directory where the src or app folder is located
|
||||
const rootDir = process.env.ROOT_DIR ?? process.cwd()
|
||||
|
||||
// get componentsBaseDir.
|
||||
// E.g.:
|
||||
// config.admin.importMap.baseDir = /test/fields/
|
||||
// rootDir: /
|
||||
// componentsBaseDir = /test/fields/
|
||||
const baseDir = config.admin.importMap.baseDir ?? process.cwd()
|
||||
|
||||
// or
|
||||
const importMapFilePath = resolveImportMapFilePath({
|
||||
adminRoute: config.routes.admin,
|
||||
importMapFile: config?.admin?.importMap?.importMapFile,
|
||||
rootDir,
|
||||
})
|
||||
|
||||
// E.g.:
|
||||
// config.admin.importMap.baseDir = /test/fields/
|
||||
// rootDir: /test
|
||||
// componentsBaseDir = /fields/
|
||||
|
||||
// or
|
||||
// config.admin.importMap.baseDir = /
|
||||
// rootDir: /
|
||||
// componentsBaseDir = /
|
||||
|
||||
// E.g.:
|
||||
// config.admin.importMap.baseDir = /test/fields/
|
||||
// rootDir: /test/fields/prod
|
||||
// componentsBaseDir = ../
|
||||
|
||||
// Check if rootDir is a subdirectory of baseDir
|
||||
const baseDir = config.admin.importMap.baseDir
|
||||
const isSubdirectory = path.relative(baseDir, rootDir).startsWith('..')
|
||||
|
||||
let componentsBaseDir
|
||||
|
||||
if (isSubdirectory) {
|
||||
// Get the relative path from rootDir to baseDir
|
||||
componentsBaseDir = path.relative(rootDir, baseDir)
|
||||
} else {
|
||||
// If rootDir is not a subdirectory, just return baseDir relative to rootDir
|
||||
componentsBaseDir = `/${path.relative(rootDir, baseDir)}`
|
||||
}
|
||||
|
||||
// Ensure result has a trailing slash
|
||||
if (!componentsBaseDir.endsWith('/')) {
|
||||
componentsBaseDir += '/'
|
||||
}
|
||||
const importMapToBaseDirPath = getImportMapToBaseDirPath({
|
||||
baseDir,
|
||||
importMapPath: importMapFilePath,
|
||||
})
|
||||
|
||||
const addToImportMap: AddToImportMap = (payloadComponent) => {
|
||||
if (!payloadComponent) {
|
||||
@@ -157,16 +82,16 @@ export async function generateImportMap(
|
||||
if (Array.isArray(payloadComponent)) {
|
||||
for (const component of payloadComponent) {
|
||||
addPayloadComponentToImportMap({
|
||||
baseDir: componentsBaseDir,
|
||||
importMap,
|
||||
importMapToBaseDirPath,
|
||||
imports,
|
||||
payloadComponent: component,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
addPayloadComponentToImportMap({
|
||||
baseDir: componentsBaseDir,
|
||||
importMap,
|
||||
importMapToBaseDirPath,
|
||||
imports,
|
||||
payloadComponent,
|
||||
})
|
||||
@@ -183,56 +108,26 @@ export async function generateImportMap(
|
||||
|
||||
await writeImportMap({
|
||||
componentMap: importMap,
|
||||
config,
|
||||
fileName: 'importMap.js',
|
||||
force: options?.force,
|
||||
importMap: imports,
|
||||
importMapFilePath,
|
||||
log: shouldLog,
|
||||
rootDir,
|
||||
})
|
||||
}
|
||||
|
||||
export async function writeImportMap({
|
||||
componentMap,
|
||||
config,
|
||||
fileName,
|
||||
force,
|
||||
importMap,
|
||||
importMapFilePath,
|
||||
log,
|
||||
rootDir,
|
||||
}: {
|
||||
componentMap: InternalImportMap
|
||||
config: SanitizedConfig
|
||||
fileName: string
|
||||
force?: boolean
|
||||
importMap: Imports
|
||||
importMapFilePath: string
|
||||
log?: boolean
|
||||
rootDir: string
|
||||
}) {
|
||||
let importMapFilePath: string | undefined = undefined
|
||||
|
||||
if (config?.admin?.importMap?.importMapFile?.length) {
|
||||
if (!fs.existsSync(config.admin.importMap.importMapFile)) {
|
||||
throw new Error(
|
||||
`Could not find the import map file at ${config.admin.importMap.importMapFile}`,
|
||||
)
|
||||
}
|
||||
importMapFilePath = config.admin.importMap.importMapFile
|
||||
} else {
|
||||
const appLocation = path.resolve(rootDir, `app/(payload)${config.routes.admin}/`)
|
||||
const srcAppLocation = path.resolve(rootDir, `src/app/(payload)${config.routes.admin}/`)
|
||||
|
||||
if (fs.existsSync(appLocation)) {
|
||||
importMapFilePath = path.resolve(appLocation, fileName)
|
||||
} else if (fs.existsSync(srcAppLocation)) {
|
||||
importMapFilePath = path.resolve(srcAppLocation, fileName)
|
||||
} else {
|
||||
throw new Error(
|
||||
`Could not find Payload import map folder. Looked in ${appLocation} and ${srcAppLocation}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const imports: string[] = []
|
||||
for (const [identifier, { path, specifier }] of Object.entries(importMap)) {
|
||||
imports.push(`import { ${specifier} as ${identifier} } from '${path}'`)
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import crypto from 'crypto'
|
||||
import path from 'path'
|
||||
|
||||
import type { PayloadComponent } from '../../../config/types.js'
|
||||
import type { Imports, InternalImportMap } from '../index.js'
|
||||
|
||||
import { parsePayloadComponent } from './parsePayloadComponent.js'
|
||||
|
||||
/**
|
||||
* Normalizes the component path based on the import map's base directory path.
|
||||
*/
|
||||
function getAdjustedComponentPath(importMapToBaseDirPath: string, componentPath: string): string {
|
||||
// Normalize input paths to use forward slashes
|
||||
const normalizedBasePath = importMapToBaseDirPath.replace(/\\/g, '/')
|
||||
const normalizedComponentPath = componentPath.replace(/\\/g, '/')
|
||||
|
||||
// Base path starts with './' - preserve the './' prefix
|
||||
// => import map is in a subdirectory of the base directory, or in the same directory as the base directory
|
||||
if (normalizedBasePath.startsWith('./')) {
|
||||
// Remove './' from component path if it exists
|
||||
const cleanComponentPath = normalizedComponentPath.startsWith('./')
|
||||
? normalizedComponentPath.substring(2)
|
||||
: normalizedComponentPath
|
||||
|
||||
// Join the paths to preserve the './' prefix
|
||||
return `${normalizedBasePath}${cleanComponentPath}`
|
||||
}
|
||||
|
||||
return path.posix.join(normalizedBasePath, normalizedComponentPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a payload component to the import map.
|
||||
*/
|
||||
export function addPayloadComponentToImportMap({
|
||||
importMap,
|
||||
importMapToBaseDirPath,
|
||||
imports,
|
||||
payloadComponent,
|
||||
}: {
|
||||
importMap: InternalImportMap
|
||||
importMapToBaseDirPath: string
|
||||
imports: Imports
|
||||
payloadComponent: PayloadComponent
|
||||
}): {
|
||||
path: string
|
||||
specifier: string
|
||||
} | null {
|
||||
if (!payloadComponent) {
|
||||
return null
|
||||
}
|
||||
const { exportName, path: componentPath } = parsePayloadComponent(payloadComponent)
|
||||
|
||||
if (importMap[componentPath + '#' + exportName]) {
|
||||
return null
|
||||
}
|
||||
|
||||
const importIdentifier =
|
||||
exportName + '_' + crypto.createHash('md5').update(componentPath).digest('hex')
|
||||
|
||||
importMap[componentPath + '#' + exportName] = importIdentifier
|
||||
|
||||
const isRelativePath = componentPath.startsWith('.') || componentPath.startsWith('/')
|
||||
|
||||
if (isRelativePath) {
|
||||
const adjustedComponentPath = getAdjustedComponentPath(importMapToBaseDirPath, componentPath)
|
||||
|
||||
imports[importIdentifier] = {
|
||||
path: adjustedComponentPath,
|
||||
specifier: exportName,
|
||||
}
|
||||
return {
|
||||
path: adjustedComponentPath,
|
||||
specifier: exportName,
|
||||
}
|
||||
} else {
|
||||
// Tsconfig alias or package import, e.g. '@payloadcms/ui' or '@/components/MyComponent'
|
||||
imports[importIdentifier] = {
|
||||
path: componentPath,
|
||||
specifier: exportName,
|
||||
}
|
||||
return {
|
||||
path: componentPath,
|
||||
specifier: exportName,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { PayloadComponent } from '../../config/types.js'
|
||||
import type { ImportMap } from './index.js'
|
||||
|
||||
import type { PayloadComponent } from '../../../config/types.js'
|
||||
import type { ImportMap } from '../index.js'
|
||||
import { parsePayloadComponent } from './parsePayloadComponent.js'
|
||||
|
||||
export const getFromImportMap = <TOutput>(args: {
|
||||
@@ -0,0 +1,39 @@
|
||||
import path from 'path'
|
||||
|
||||
/**
|
||||
* Returns the path that navigates from the import map file to the base directory.
|
||||
* This can then be prepended to relative paths in the import map to get the full, absolute path.
|
||||
*/
|
||||
export function getImportMapToBaseDirPath({
|
||||
baseDir,
|
||||
importMapPath,
|
||||
}: {
|
||||
/**
|
||||
* Absolute path to the base directory
|
||||
*/
|
||||
baseDir: string
|
||||
/**
|
||||
* Absolute path to the import map file
|
||||
*/
|
||||
importMapPath: string
|
||||
}): string {
|
||||
const importMapDir = path.dirname(importMapPath)
|
||||
|
||||
// 1. Direct relative path from `importMapDir` -> `baseDir`
|
||||
let relativePath = path.relative(importMapDir, baseDir).replace(/\\/g, '/')
|
||||
|
||||
// 2. If they're the same directory, path.relative will be "", so use "./"
|
||||
if (!relativePath) {
|
||||
relativePath = './'
|
||||
} // Add ./ prefix for subdirectories of the current directory
|
||||
else if (!relativePath.startsWith('.') && !relativePath.startsWith('/')) {
|
||||
relativePath = `./${relativePath}`
|
||||
}
|
||||
|
||||
// 3. For consistency ensure a trailing slash
|
||||
if (!relativePath.endsWith('/')) {
|
||||
relativePath += '/'
|
||||
}
|
||||
|
||||
return relativePath
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-strict-ignore
|
||||
import type { PayloadComponent } from '../../config/types.js'
|
||||
import type { PayloadComponent } from '../../../config/types.js'
|
||||
|
||||
export function parsePayloadComponent(PayloadComponent: PayloadComponent): {
|
||||
exportName: string
|
||||
@@ -0,0 +1,38 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
/**
|
||||
* Returns the path to the import map file. If the import map file is not found, it throws an error.
|
||||
*/
|
||||
export function resolveImportMapFilePath({
|
||||
adminRoute = '/admin',
|
||||
importMapFile,
|
||||
rootDir,
|
||||
}: {
|
||||
adminRoute?: string
|
||||
importMapFile?: string
|
||||
rootDir: string
|
||||
}) {
|
||||
let importMapFilePath: string | undefined = undefined
|
||||
|
||||
if (importMapFile?.length) {
|
||||
if (!fs.existsSync(importMapFile)) {
|
||||
throw new Error(`Could not find the import map file at ${importMapFile}`)
|
||||
}
|
||||
importMapFilePath = importMapFile
|
||||
} else {
|
||||
const appLocation = path.resolve(rootDir, `app/(payload)${adminRoute}/`)
|
||||
const srcAppLocation = path.resolve(rootDir, `src/app/(payload)${adminRoute}/`)
|
||||
|
||||
if (fs.existsSync(appLocation)) {
|
||||
importMapFilePath = path.resolve(appLocation, 'importMap.js')
|
||||
} else if (fs.existsSync(srcAppLocation)) {
|
||||
importMapFilePath = path.resolve(srcAppLocation, 'importMap.js')
|
||||
} else {
|
||||
throw new Error(
|
||||
`Could not find Payload import map folder. Looked in ${appLocation} and ${srcAppLocation}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return importMapFilePath
|
||||
}
|
||||
@@ -6,8 +6,8 @@ export {
|
||||
parseCookies,
|
||||
} from '../auth/cookies.js'
|
||||
export { getLoginOptions } from '../auth/getLoginOptions.js'
|
||||
export { getFromImportMap } from '../bin/generateImportMap/getFromImportMap.js'
|
||||
export { parsePayloadComponent } from '../bin/generateImportMap/parsePayloadComponent.js'
|
||||
export { getFromImportMap } from '../bin/generateImportMap/utilities/getFromImportMap.js'
|
||||
export { parsePayloadComponent } from '../bin/generateImportMap/utilities/parsePayloadComponent.js'
|
||||
export { defaults as collectionDefaults } from '../collections/config/defaults.js'
|
||||
|
||||
export { serverProps } from '../config/types.js'
|
||||
|
||||
@@ -22,7 +22,7 @@ import type {
|
||||
} from '../../fields/config/types.js'
|
||||
import type { Payload } from '../../types/index.js'
|
||||
|
||||
import { getFromImportMap } from '../../bin/generateImportMap/getFromImportMap.js'
|
||||
import { getFromImportMap } from '../../bin/generateImportMap/utilities/getFromImportMap.js'
|
||||
import { MissingEditorProp } from '../../errors/MissingEditorProp.js'
|
||||
import { fieldAffectsData } from '../../fields/config/types.js'
|
||||
import { flattenTopLevelFields, type ImportMap } from '../../index.js'
|
||||
|
||||
Reference in New Issue
Block a user