import path from 'path'
import {
SRC_DIR_NAMES,
TemplateMode,
TemplateType,
} from '../../../../packages/create-next-app/templates'
export type ProjectSettings = {
files: string[]
deps: string[]
devDeps: string[]
}
export type ProjectSpecification = {
global: ProjectSettings
} & {
[key in TemplateType]: {
[key in TemplateMode]: ProjectSettings
}
}
/**
* Required files for a given project template and mode.
*/
export const projectSpecification: ProjectSpecification = {
global: {
files: [
'package.json',
'eslint.config.mjs',
'node_modules/next',
'.gitignore',
],
deps: [
'next',
'react',
'react-dom',
...(process.env.NEXT_RSPACK ? ['next-rspack'] : []),
],
devDeps: ['eslint', 'eslint-config-next'],
},
default: {
js: {
files: [
'pages/index.js',
'pages/_app.js',
'pages/api/hello.js',
'jsconfig.json',
],
deps: [],
devDeps: [],
},
ts: {
files: [
'pages/index.tsx',
'pages/_app.tsx',
'pages/api/hello.ts',
'tsconfig.json',
'next-env.d.ts',
],
deps: [],
devDeps: [
'@types/node',
'@types/react',
'@types/react-dom',
'typescript',
],
},
},
'default-empty': {
js: {
files: ['pages/index.js', 'pages/_app.js', 'jsconfig.json'],
deps: [],
devDeps: [],
},
ts: {
files: [
'pages/index.tsx',
'pages/_app.tsx',
'tsconfig.json',
'next-env.d.ts',
],
deps: [],
devDeps: [
'@types/node',
'@types/react',
'@types/react-dom',
'typescript',
],
},
},
'default-tw': {
js: {
files: [
'jsconfig.json',
'pages/_app.js',
'pages/api/hello.js',
'pages/index.js',
'postcss.config.mjs',
],
deps: [],
devDeps: ['@tailwindcss/postcss', 'tailwindcss'],
},
ts: {
files: [
'next-env.d.ts',
'pages/_app.tsx',
'pages/api/hello.ts',
'pages/index.tsx',
'postcss.config.mjs',
'tsconfig.json',
],
deps: [],
devDeps: [
'@types/node',
'@types/react-dom',
'@types/react',
'@tailwindcss/postcss',
'tailwindcss',
'typescript',
],
},
},
'default-tw-empty': {
js: {
files: [
'jsconfig.json',
'pages/_app.js',
'pages/index.js',
'postcss.config.mjs',
],
deps: [],
devDeps: ['@tailwindcss/postcss', 'tailwindcss'],
},
ts: {
files: [
'next-env.d.ts',
'pages/_app.tsx',
'pages/index.tsx',
'postcss.config.mjs',
'tsconfig.json',
],
deps: [],
devDeps: [
'@types/node',
'@types/react-dom',
'@types/react',
'@tailwindcss/postcss',
'tailwindcss',
'typescript',
],
},
},
app: {
js: {
deps: [],
devDeps: [],
files: ['app/page.js', 'app/layout.js', 'jsconfig.json'],
},
ts: {
deps: [],
devDeps: [
'@types/node',
'@types/react',
'@types/react-dom',
'typescript',
],
files: [
'app/page.tsx',
'app/layout.tsx',
'tsconfig.json',
'next-env.d.ts',
],
},
},
'app-api': {
js: {
deps: ['next', ...(process.env.NEXT_RSPACK ? ['next-rspack'] : [])],
devDeps: [],
files: ['app/route.js', 'app/[slug]/route.js', 'jsconfig.json'],
},
ts: {
deps: ['next', ...(process.env.NEXT_RSPACK ? ['next-rspack'] : [])],
devDeps: ['@types/node', '@types/react', 'typescript'],
files: [
'app/route.ts',
'app/[slug]/route.ts',
'tsconfig.json',
'next-env.d.ts',
],
},
},
'app-empty': {
js: {
deps: [],
devDeps: [],
files: ['app/page.js', 'app/layout.js', 'jsconfig.json'],
},
ts: {
deps: [],
devDeps: [
'@types/node',
'@types/react',
'@types/react-dom',
'typescript',
],
files: [
'app/page.tsx',
'app/layout.tsx',
'tsconfig.json',
'next-env.d.ts',
],
},
},
'app-tw': {
js: {
deps: [],
devDeps: ['@tailwindcss/postcss', 'tailwindcss'],
files: [
'app/layout.js',
'app/page.js',
'jsconfig.json',
'postcss.config.mjs',
],
},
ts: {
deps: [],
devDeps: [
'@types/node',
'@types/react-dom',
'@types/react',
'@tailwindcss/postcss',
'tailwindcss',
'typescript',
],
files: [
'app/layout.tsx',
'app/page.tsx',
'next-env.d.ts',
'postcss.config.mjs',
'tsconfig.json',
],
},
},
'app-tw-empty': {
js: {
deps: [],
devDeps: ['@tailwindcss/postcss', 'tailwindcss'],
files: [
'app/layout.js',
'app/page.js',
'jsconfig.json',
'postcss.config.mjs',
],
},
ts: {
deps: [],
devDeps: [
'@types/node',
'@types/react-dom',
'@types/react',
'@tailwindcss/postcss',
'tailwindcss',
'typescript',
],
files: [
'app/layout.tsx',
'app/page.tsx',
'next-env.d.ts',
'postcss.config.mjs',
'tsconfig.json',
],
},
},
}
export type GetProjectSettingsArgs = {
template: TemplateType
mode: TemplateMode
setting: keyof ProjectSettings
srcDir?: boolean
}
export const mapSrcFiles = (files: string[], srcDir?: boolean) =>
files.map((file) =>
srcDir && SRC_DIR_NAMES.some((name) => file.startsWith(name))
? path.join('src', file)
: file
)
export const getProjectSetting = ({
template,
mode,
setting,
srcDir,
}: GetProjectSettingsArgs) => {
return [
...projectSpecification.global[setting],
...mapSrcFiles(projectSpecification[template][mode][setting], srcDir),
]
}