Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4068b4493e | ||
|
|
0448535ef0 | ||
|
|
0df6aef3a3 | ||
|
|
5ba2989592 | ||
|
|
9240d86ed6 | ||
|
|
27e0dacdaf | ||
|
|
8dc1cd3ca8 | ||
|
|
413bc01676 | ||
|
|
7c025e9bd7 | ||
|
|
24e51c7ae5 | ||
|
|
b2f84f1224 | ||
|
|
8df18f24ad | ||
|
|
d480d84e46 | ||
|
|
f0a9fbeb14 |
@@ -2860,6 +2860,16 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "esemeniuc",
|
||||
"name": "Eric Semeniuc",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3838856?v=4",
|
||||
"profile": "https://semeniuc.ml/",
|
||||
"contributions": [
|
||||
"test",
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,3 +30,4 @@ examples/auth2
|
||||
db.sqlite-journal
|
||||
test/integration/**/db.json
|
||||
test/**/*/out
|
||||
.blitz**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
|
||||
</a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-303-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-304-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
<a aria-label="License" href="https://github.com/blitz-js/blitz/blob/canary/LICENSE">
|
||||
<img alt="" src="https://img.shields.io/npm/l/blitz.svg?style=for-the-badge&labelColor=000000&color=blue">
|
||||
@@ -635,6 +635,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<tr>
|
||||
<td align="center"><a href="http://anolilab.de"><img src="https://avatars.githubusercontent.com/u/2716058?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Bannert</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=prisis" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://benjakugler96.github.io/"><img src="https://avatars.githubusercontent.com/u/53273645?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benja Kugler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=benjakugler96" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://semeniuc.ml/"><img src="https://avatars.githubusercontent.com/u/3838856?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eric Semeniuc</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=esemeniuc" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=esemeniuc" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -12,16 +12,8 @@ import {
|
||||
} from "blitz"
|
||||
import getUser from "app/users/queries/getUser"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
import path from "path"
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({req, res}) => {
|
||||
// Ensure these files are not eliminated by trace-based tree-shaking (like Vercel)
|
||||
// https://github.com/blitz-js/blitz/issues/794
|
||||
path.resolve("next.config.js")
|
||||
path.resolve("blitz.config.js")
|
||||
path.resolve(".next/blitz/db.js")
|
||||
// End anti-tree-shaking
|
||||
|
||||
const session = await getSession(req, res)
|
||||
console.log("Session id:", session.userId)
|
||||
try {
|
||||
|
||||
@@ -29,14 +29,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"passport-auth0": "1.4.0",
|
||||
"passport-github2": "0.1.12",
|
||||
"passport-twitter": "1.0.4",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -48,7 +48,7 @@
|
||||
"@types/passport-github2": "1.2.4",
|
||||
"@types/passport-twitter": "1.0.36",
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2",
|
||||
"secure-password": "4.0.0"
|
||||
},
|
||||
@@ -43,7 +43,7 @@
|
||||
"@cypress/skip-test": "2.6.0",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -28,18 +28,18 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"graphql": "15.5.0",
|
||||
"graphql-request": "3.4.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"babel-eslint": "~10.1.0",
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"knex": "0.21.16",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"sqlite3": "5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"babel-eslint": "~10.1.0",
|
||||
"eslint": "7.21.0",
|
||||
"eslint-config-react-app": "~6.0.0",
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71"
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "~10.1.0",
|
||||
|
||||
@@ -33,16 +33,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"eslint": "7.21.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"cypress": "6.2.1",
|
||||
"start-server-and-test": "1.11.7"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"packages": ["packages/*"],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
|
||||
@@ -116,8 +116,8 @@
|
||||
"prettier": "2.2.1",
|
||||
"pretty-bytes": "5.3.0",
|
||||
"pretty-ms": "7.0.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-ssr-prepass": "1.0.8",
|
||||
"release": "6.3.0",
|
||||
"request-promise-core": "1.1.2",
|
||||
|
||||
@@ -6,6 +6,7 @@ import loadConfig from 'next/dist/compiled/babel/core-lib-config'
|
||||
|
||||
import { NextBabelLoaderOptions, NextJsLoaderContext } from './types'
|
||||
import { consumeIterator } from './util'
|
||||
import { isPageFile as isPageFileFn } from '../../utils'
|
||||
|
||||
const nextDistPath = /(next[\\/]dist[\\/]next-server[\\/]lib)|(next[\\/]dist[\\/]client)|(next[\\/]dist[\\/]pages)/
|
||||
|
||||
@@ -43,8 +44,8 @@ function getCacheCharacteristics(
|
||||
filename: string
|
||||
): CharacteristicsGermaneToCaching {
|
||||
const { isServer, pagesDir } = loaderOptions
|
||||
const isPageFile = filename.startsWith(pagesDir)
|
||||
const isNextDist = nextDistPath.test(filename)
|
||||
const isPageFile = !isNextDist && isPageFileFn(filename.replace(pagesDir, ''))
|
||||
const hasModuleExports = source.indexOf('module.exports') !== -1
|
||||
const fileExt = fileExtensionRegex.exec(filename)?.[1] || 'unknown'
|
||||
|
||||
|
||||
@@ -35,30 +35,39 @@ export default function NoAnonymousDefaultExport({
|
||||
|
||||
switch (def.type) {
|
||||
case 'ArrowFunctionExpression': {
|
||||
warn(
|
||||
[
|
||||
chalk.yellow.bold(
|
||||
'Anonymous arrow functions cause Fast Refresh to not preserve local component state.'
|
||||
),
|
||||
'Please add a name to your function, for example:',
|
||||
'',
|
||||
chalk.bold('Before'),
|
||||
chalk.cyan('export default () => <div />;'),
|
||||
'',
|
||||
chalk.bold('After'),
|
||||
chalk.cyan('const Named = () => <div />;'),
|
||||
chalk.cyan('export default Named;'),
|
||||
'',
|
||||
`A codemod is available to fix the most common cases: ${chalk.cyan(
|
||||
'https://nextjs.link/codemod-ndc'
|
||||
)}`,
|
||||
].join('\n')
|
||||
)
|
||||
if (
|
||||
!process.env.__NEXT_TEST_MODE ||
|
||||
!!process.env.__NEXT_TEST_ANON_EXPORT
|
||||
) {
|
||||
warn(
|
||||
[
|
||||
chalk.yellow.bold(
|
||||
'Anonymous arrow functions cause Fast Refresh to not preserve local component state.'
|
||||
),
|
||||
'Please add a name to your function, for example:',
|
||||
'',
|
||||
chalk.bold('Before'),
|
||||
chalk.cyan('export default () => <div />;'),
|
||||
'',
|
||||
chalk.bold('After'),
|
||||
chalk.cyan('const Named = () => <div />;'),
|
||||
chalk.cyan('export default Named;'),
|
||||
'',
|
||||
`A codemod is available to fix the most common cases: ${chalk.cyan(
|
||||
'https://nextjs.link/codemod-ndc'
|
||||
)}`,
|
||||
].join('\n')
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'FunctionDeclaration': {
|
||||
const isAnonymous = !Boolean(def.id)
|
||||
if (isAnonymous) {
|
||||
if (
|
||||
isAnonymous &&
|
||||
(!process.env.__NEXT_TEST_MODE ||
|
||||
!!process.env.__NEXT_TEST_ANON_EXPORT)
|
||||
) {
|
||||
warn(
|
||||
[
|
||||
chalk.yellow.bold(
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ClientPagesLoaderOptions } from './webpack/loaders/next-client-pages-lo
|
||||
import { ServerlessLoaderQuery } from './webpack/loaders/next-serverless-loader'
|
||||
import { LoadedEnvFiles } from '@next/env'
|
||||
import { NextConfig } from '../next-server/server/config'
|
||||
import { convertPageFilePathToRoutePath } from './utils'
|
||||
|
||||
type PagesMapping = {
|
||||
[page: string]: string
|
||||
@@ -22,19 +23,19 @@ export function createPagesMapping(
|
||||
const previousPages: PagesMapping = {}
|
||||
const pages: PagesMapping = pagePaths.reduce(
|
||||
(result: PagesMapping, pagePath): PagesMapping => {
|
||||
let page = `${pagePath
|
||||
let page = `${convertPageFilePathToRoutePath(pagePath)
|
||||
.replace(new RegExp(`\\.+(${extensions.join('|')})$`), '')
|
||||
.replace(/\\/g, '/')}`.replace(/\/index$/, '')
|
||||
|
||||
const pageKey = page === '' ? '/' : page
|
||||
let pageKey = page === '' ? '/' : page
|
||||
|
||||
if (pageKey in result) {
|
||||
warn(
|
||||
`Duplicate page detected. ${chalk.cyan(
|
||||
join('pages', previousPages[pageKey])
|
||||
)} and ${chalk.cyan(
|
||||
join('pages', pagePath)
|
||||
)} both resolve to ${chalk.cyan(pageKey)}.`
|
||||
previousPages[pageKey]
|
||||
)} and ${chalk.cyan(pagePath)} both resolve to ${chalk.cyan(
|
||||
pageKey
|
||||
)}.`
|
||||
)
|
||||
} else {
|
||||
previousPages[pageKey] = pagePath
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
PUBLIC_DIR_MIDDLEWARE_CONFLICT,
|
||||
} from '../lib/constants'
|
||||
import { fileExists } from '../lib/file-exists'
|
||||
import { findPagesDir } from '../lib/find-pages-dir'
|
||||
import loadCustomRoutes, {
|
||||
CustomRoutes,
|
||||
getRedirectStatus,
|
||||
@@ -125,7 +124,7 @@ export default async function build(
|
||||
const nextBuildSpan = trace('next-build')
|
||||
|
||||
return nextBuildSpan.traceAsyncFn(async () => {
|
||||
// attempt to load global env values so they are available in next.config.js
|
||||
// attempt to load global env values so they are available in blitz.config.js
|
||||
const { loadedEnvFiles } = nextBuildSpan
|
||||
.traceChild('load-dotenv')
|
||||
.traceFn(() => loadEnvConfig(dir, false, Log))
|
||||
@@ -162,7 +161,7 @@ export default async function build(
|
||||
setGlobal('telemetry', telemetry)
|
||||
|
||||
const publicDir = path.join(dir, 'public')
|
||||
const pagesDir = findPagesDir(dir)
|
||||
const pagesDir = dir
|
||||
const hasPublicDir = await fileExists(publicDir)
|
||||
|
||||
telemetry.record(
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
SERVER_PROPS_SSG_CONFLICT,
|
||||
} from '../lib/constants'
|
||||
import prettyBytes from '../lib/pretty-bytes'
|
||||
import { recursiveReadDir } from '../lib/recursive-readdir'
|
||||
import { recursiveFindPages } from '../lib/recursive-readdir'
|
||||
import { getRouteMatcher, getRouteRegex } from '../next-server/lib/router/utils'
|
||||
import { isDynamicRoute } from '../next-server/lib/router/utils/is-dynamic'
|
||||
import escapePathDelimiters from '../next-server/lib/router/utils/escape-path-delimiters'
|
||||
@@ -49,14 +49,35 @@ const fsStat = (file: string) => {
|
||||
return (fileStats[file] = fileSize(file))
|
||||
}
|
||||
|
||||
export const topLevelFoldersThatMayContainPages = [
|
||||
'pages',
|
||||
'src',
|
||||
'app',
|
||||
'integrations',
|
||||
]
|
||||
|
||||
export function convertPageFilePathToRoutePath(filePath: string) {
|
||||
return filePath
|
||||
.replace(/^.*?[\\/]pages[\\/]/, '/')
|
||||
.replace(/^.*?[\\/]api[\\/]/, '/api/')
|
||||
}
|
||||
|
||||
export function isPageFile(filePathFromAppRoot: string) {
|
||||
return (
|
||||
/[\\/]pages[\\/]/.test(filePathFromAppRoot) ||
|
||||
/[\\/]api[\\/]/.test(filePathFromAppRoot)
|
||||
)
|
||||
}
|
||||
|
||||
export function buildPageExtensionRegex(pageExtensions: string[]) {
|
||||
return new RegExp(`(?<!\\.test|\\.spec)\\.(?:${pageExtensions.join('|')})$`)
|
||||
}
|
||||
|
||||
export function collectPages(
|
||||
directory: string,
|
||||
pageExtensions: string[]
|
||||
): Promise<string[]> {
|
||||
return recursiveReadDir(
|
||||
directory,
|
||||
new RegExp(`\\.(?:${pageExtensions.join('|')})$`)
|
||||
)
|
||||
return recursiveFindPages(directory, buildPageExtensionRegex(pageExtensions))
|
||||
}
|
||||
|
||||
export interface PageInfo {
|
||||
|
||||
@@ -52,20 +52,7 @@ import WebpackConformancePlugin, {
|
||||
} from './webpack/plugins/webpack-conformance-plugin'
|
||||
import { WellKnownErrorsPlugin } from './webpack/plugins/wellknown-errors-plugin'
|
||||
import { regexLikeCss } from './webpack/config/blocks/css'
|
||||
|
||||
import fs from 'fs'
|
||||
import { getProjectRoot } from '../server/lib/utils'
|
||||
|
||||
/* ------ Blitz.js ------- */
|
||||
function doesDbModuleExist() {
|
||||
const projectRoot = getProjectRoot()
|
||||
return (
|
||||
fs.existsSync(path.join(projectRoot, 'db/index.js')) ||
|
||||
fs.existsSync(path.join(projectRoot, 'db/index.ts')) ||
|
||||
fs.existsSync(path.join(projectRoot, 'db/index.tsx'))
|
||||
)
|
||||
}
|
||||
/* ------ Blitz.js ------- */
|
||||
import { existsSync } from 'fs'
|
||||
|
||||
type ExcludesFalse = <T>(x: T | false) => x is T
|
||||
|
||||
@@ -279,6 +266,12 @@ export default async function getBaseWebpackConfig(
|
||||
|
||||
const distDir = path.join(dir, config.distDir)
|
||||
|
||||
/* ------ Blitz.js ------- */
|
||||
const hasDbModule =
|
||||
existsSync(path.join(dir, 'db/index.js')) ||
|
||||
existsSync(path.join(dir, 'db/index.ts'))
|
||||
/* ------ Blitz.js ------- */
|
||||
|
||||
// Webpack 5 can use the faster babel loader, webpack 5 has built-in caching for loaders
|
||||
// For webpack 4 the old loader is used as it has external caching
|
||||
const babelLoader = isWebpack5
|
||||
@@ -913,9 +906,7 @@ export default async function getBaseWebpackConfig(
|
||||
entry: async () => {
|
||||
return {
|
||||
...(clientEntries ? clientEntries : {}),
|
||||
...(isServer && doesDbModuleExist()
|
||||
? { 'blitz-db': './db/index' }
|
||||
: {}),
|
||||
...(isServer && hasDbModule ? { 'blitz-db': './db/index' } : {}),
|
||||
...entrypoints,
|
||||
}
|
||||
},
|
||||
@@ -1373,12 +1364,13 @@ export default async function getBaseWebpackConfig(
|
||||
type: 'filesystem',
|
||||
// Includes:
|
||||
// - Next.js version
|
||||
// - next.config.js keys that affect compilation
|
||||
// - blitz.config.js keys that affect compilation
|
||||
version: `${process.env.__NEXT_VERSION}|${configVars}`,
|
||||
cacheDirectory: path.join(distDir, 'cache', 'webpack'),
|
||||
}
|
||||
|
||||
// Adds `next.config.js` as a buildDependency when custom webpack config is provided
|
||||
// TODO - can we remove this?
|
||||
// Adds `blitz.config.js` as a buildDependency when custom webpack config is provided
|
||||
if (config.webpack && config.configFile) {
|
||||
cache.buildDependencies = {
|
||||
config: [config.configFile],
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { join } from 'path'
|
||||
import * as Log from '../../output/log'
|
||||
import babelLoader from './babel-loader/src/index'
|
||||
import { isPageFile as isPageFileFn } from '../../utils'
|
||||
|
||||
// increment 'p' to invalidate cache
|
||||
// eslint-disable-next-line no-useless-concat
|
||||
@@ -81,7 +82,7 @@ const customBabelLoader = babelLoader((babel) => {
|
||||
) {
|
||||
const filename = this.resourcePath
|
||||
const options = Object.assign({}, cfg.options)
|
||||
const isPageFile = filename.startsWith(pagesDir)
|
||||
const isPageFile = isPageFileFn(filename.replace(pagesDir, ''))
|
||||
|
||||
if (cfg.hasFilesystemConfig()) {
|
||||
for (const file of [cfg.babelrc, cfg.config]) {
|
||||
|
||||
@@ -7,7 +7,7 @@ export function removePathTrailingSlash(path: string): string {
|
||||
|
||||
/**
|
||||
* Normalizes the trailing slash of a path according to the `trailingSlash` option
|
||||
* in `next.config.js`.
|
||||
* in `blitz.config.js`.
|
||||
*/
|
||||
export const normalizePathTrailingSlash = process.env.__NEXT_TRAILING_SLASH
|
||||
? (path: string): string => {
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
BUILD_ID_FILE,
|
||||
CLIENT_PUBLIC_FILES_PATH,
|
||||
CLIENT_STATIC_FILES_PATH,
|
||||
CONFIG_FILE,
|
||||
EXPORT_DETAIL,
|
||||
EXPORT_MARKER,
|
||||
PAGES_MANIFEST,
|
||||
@@ -143,7 +142,7 @@ export default async function exportApp(
|
||||
return nextExportSpan.traceAsyncFn(async () => {
|
||||
dir = resolve(dir)
|
||||
|
||||
// attempt to load global env values so they are available in next.config.js
|
||||
// attempt to load global env values so they are available in blitz.config.js
|
||||
nextExportSpan
|
||||
.traceChild('load-dotenv')
|
||||
.traceFn(() => loadEnvConfig(dir, false, Log))
|
||||
@@ -308,7 +307,7 @@ export default async function exportApp(
|
||||
if (typeof nextConfig.exportPathMap !== 'function') {
|
||||
if (!options.silent) {
|
||||
Log.info(
|
||||
`No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`
|
||||
`No "exportPathMap" found in "blitz.config.js". Generating map from "./pages"`
|
||||
)
|
||||
}
|
||||
nextConfig.exportPathMap = async (defaultMap: ExportPathMap) => {
|
||||
|
||||
@@ -85,7 +85,7 @@ async function lint(
|
||||
}
|
||||
}
|
||||
|
||||
const pagesDir = findPagesDir(baseDir)
|
||||
const pagesDir = baseDir
|
||||
|
||||
if (nextEslintPluginIsEnabled) {
|
||||
let updatedPagesDir = false
|
||||
|
||||
@@ -11,7 +11,9 @@ export const existsSync = (f: string): boolean => {
|
||||
}
|
||||
|
||||
export function findPagesDir(dir: string): string {
|
||||
throw new Error('findPagesDir is deprecated in Blitz.js')
|
||||
// prioritize ./pages over ./src/pages
|
||||
// eslint-disable-next-line no-unreachable -- disabled in Blitz.js
|
||||
let curDir = path.join(dir, 'pages')
|
||||
if (existsSync(curDir)) return curDir
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { promises } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { isPageFile, topLevelFoldersThatMayContainPages } from '../build/utils'
|
||||
|
||||
/**
|
||||
* Recursively read directory
|
||||
@@ -40,3 +41,45 @@ export async function recursiveReadDir(
|
||||
|
||||
return arr.sort()
|
||||
}
|
||||
|
||||
export async function recursiveFindPages(
|
||||
dir: string,
|
||||
filter: RegExp,
|
||||
ignore?: RegExp,
|
||||
arr: string[] = [],
|
||||
rootDir: string = dir
|
||||
): Promise<string[]> {
|
||||
let folders = await promises.readdir(dir)
|
||||
|
||||
if (dir === rootDir) {
|
||||
folders = folders.filter((folder) =>
|
||||
topLevelFoldersThatMayContainPages.includes(folder)
|
||||
)
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
folders.map(async (part: string) => {
|
||||
const absolutePath = join(dir, part)
|
||||
if (ignore && ignore.test(part)) return
|
||||
|
||||
const pathStat = await promises.stat(absolutePath)
|
||||
|
||||
if (pathStat.isDirectory()) {
|
||||
await recursiveFindPages(absolutePath, filter, ignore, arr, rootDir)
|
||||
return
|
||||
}
|
||||
|
||||
if (!filter.test(part)) {
|
||||
return
|
||||
}
|
||||
|
||||
const relativeFromRoot = absolutePath.replace(rootDir, '')
|
||||
if (isPageFile(relativeFromRoot)) {
|
||||
arr.push(relativeFromRoot)
|
||||
return
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
return arr.sort()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export const REACT_LOADABLE_MANIFEST = 'react-loadable-manifest.json'
|
||||
export const FONT_MANIFEST = 'font-manifest.json'
|
||||
export const SERVER_DIRECTORY = 'server'
|
||||
export const SERVERLESS_DIRECTORY = 'serverless'
|
||||
export const CONFIG_FILE = 'next.config.js'
|
||||
export const CONFIG_FILE = '.blitz.config.compiled.js'
|
||||
export const BUILD_ID_FILE = 'BUILD_ID'
|
||||
export const BLOCKED_PAGES = ['/_document', '/_app']
|
||||
export const CLIENT_PUBLIC_FILES_PATH = 'public'
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { existsSync, readFileSync } from 'fs'
|
||||
import { build as esbuild } from 'esbuild'
|
||||
import findUp from 'next/dist/compiled/find-up'
|
||||
import os from 'os'
|
||||
import { join } from 'path'
|
||||
import { Header, Redirect, Rewrite } from '../../lib/load-custom-routes'
|
||||
import { imageConfigDefault } from './image-config'
|
||||
import { CONFIG_FILE } from '../lib/constants'
|
||||
import { copy, remove } from 'fs-extra'
|
||||
const debug = require('debug')('blitz:config')
|
||||
|
||||
export type DomainLocales = Array<{
|
||||
http?: true
|
||||
@@ -143,3 +150,116 @@ export function normalizeConfig(phase: string, config: any) {
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
export async function getConfigSrcPath(dir: string | null) {
|
||||
if (!dir) return null
|
||||
|
||||
let tsPath = join(dir, 'blitz.config.ts')
|
||||
let jsPath = join(dir, 'blitz.config.js')
|
||||
let legacyPath = join(dir, 'next.config.js')
|
||||
|
||||
if (existsSync(tsPath)) {
|
||||
return tsPath
|
||||
} else if (existsSync(jsPath)) {
|
||||
return jsPath
|
||||
} else if (existsSync(legacyPath)) {
|
||||
const isInternalDevelopment = __dirname.includes(
|
||||
'packages/next/dist/next-server'
|
||||
)
|
||||
if (isInternalDevelopment || process.env.VERCEL_BUILDER) {
|
||||
// We read from next.config.js that Vercel automatically adds
|
||||
debug(
|
||||
'Using next.config.js because isInternalDevelopment or VERCEL_BUILDER...'
|
||||
)
|
||||
return legacyPath
|
||||
} else {
|
||||
console.log('') // newline
|
||||
throw new Error(
|
||||
'Blitz does not support next.config.js. Please rename it to blitz.config.js'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.__NEXT_TEST_MODE) {
|
||||
let tsPath2 = join(dir, '..', 'blitz.config.ts')
|
||||
let jsPath2 = join(dir, '..', 'blitz.config.js')
|
||||
let legacyPath2 = join(dir, '..', 'next.config.js')
|
||||
if (existsSync(tsPath2)) {
|
||||
return tsPath2
|
||||
} else if (existsSync(jsPath2)) {
|
||||
return jsPath2
|
||||
} else if (existsSync(legacyPath2)) {
|
||||
return legacyPath2
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function getCompiledConfigPath(dir: string) {
|
||||
return join(dir, CONFIG_FILE)
|
||||
}
|
||||
|
||||
export async function compileConfig(dir: string | null) {
|
||||
debug('Starting compileConfig...')
|
||||
|
||||
if (!dir) {
|
||||
debug('compileConfig given empty dir argument')
|
||||
return
|
||||
}
|
||||
|
||||
const srcPath = await getConfigSrcPath(dir)
|
||||
debug('srcPath:', srcPath)
|
||||
const compiledPath = getCompiledConfigPath(dir)
|
||||
debug('compiledPath:', compiledPath)
|
||||
|
||||
// Remove compiled file. This is important for example when user
|
||||
// had a config file but then removed it
|
||||
remove(compiledPath)
|
||||
|
||||
if (!srcPath) {
|
||||
debug('Did not find a config file')
|
||||
return
|
||||
}
|
||||
|
||||
if (readFileSync(srcPath, 'utf8').includes('tsconfig-paths/register')) {
|
||||
// User is manually handling their own typescript stuff
|
||||
debug(
|
||||
"Config contains 'tsconfig-paths/register', so skipping build and just copying the file"
|
||||
)
|
||||
await copy(srcPath, compiledPath)
|
||||
return
|
||||
}
|
||||
|
||||
const pkgJsonPath = await findUp('package.json', { cwd: dir })
|
||||
|
||||
if (!pkgJsonPath) {
|
||||
// This will happen when running blitz no inside a blitz app
|
||||
debug('Unable to find package directory')
|
||||
return
|
||||
}
|
||||
|
||||
debug('Building config...')
|
||||
const pkg = require(pkgJsonPath)
|
||||
|
||||
await esbuild({
|
||||
entryPoints: [srcPath],
|
||||
outfile: compiledPath,
|
||||
format: 'cjs',
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
external: [
|
||||
'*.json',
|
||||
'@blitzjs',
|
||||
'@next',
|
||||
'@zeit',
|
||||
'blitz',
|
||||
'next',
|
||||
'webpack',
|
||||
...Object.keys(require('blitz/package').dependencies),
|
||||
...Object.keys(pkg?.dependencies ?? {}),
|
||||
...Object.keys(pkg?.devDependencies ?? {}),
|
||||
],
|
||||
})
|
||||
debug('Config built.')
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export async function shouldLoadWithWebpack5(
|
||||
}
|
||||
}
|
||||
|
||||
// Use webpack 5 by default in apps that do not have next.config.js
|
||||
// Use webpack 5 by default in apps that do not have blitz.config.js
|
||||
if (!path?.length) {
|
||||
return {
|
||||
enabled: true,
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import chalk from 'chalk'
|
||||
import findUp from 'next/dist/compiled/find-up'
|
||||
import { basename, extname } from 'path'
|
||||
import { basename, extname, join } from 'path'
|
||||
import * as Log from '../../build/output/log'
|
||||
import { hasNextSupport } from '../../telemetry/ci-info'
|
||||
import { CONFIG_FILE, PHASE_DEVELOPMENT_SERVER } from '../lib/constants'
|
||||
import { execOnce } from '../lib/utils'
|
||||
import { defaultConfig, normalizeConfig } from './config-shared'
|
||||
import { compileConfig, defaultConfig, normalizeConfig } from './config-shared'
|
||||
import { loadWebpackHook } from './config-utils'
|
||||
import { ImageConfig, imageConfigDefault, VALID_LOADERS } from './image-config'
|
||||
import { loadEnvConfig } from '@next/env'
|
||||
const debug = require('debug')('blitz:config')
|
||||
|
||||
export { DomainLocales, NextConfig, normalizeConfig } from './config-shared'
|
||||
|
||||
@@ -412,6 +413,10 @@ export default async function loadConfig(
|
||||
customConfig?: object | null
|
||||
) {
|
||||
await loadEnvConfig(dir, phase === PHASE_DEVELOPMENT_SERVER, Log)
|
||||
if (!['start', 's'].includes(process.argv[2])) {
|
||||
// Do not compile config for blitz start because it was already compiled during blitz build
|
||||
await compileConfig(dir)
|
||||
}
|
||||
await loadWebpackHook(phase, dir)
|
||||
|
||||
if (customConfig) {
|
||||
@@ -423,11 +428,20 @@ export default async function loadConfig(
|
||||
// If config file was found
|
||||
if (path?.length) {
|
||||
const userConfigModule = require(path)
|
||||
const userConfig = normalizeConfig(
|
||||
let userConfig = normalizeConfig(
|
||||
phase,
|
||||
userConfigModule.default || userConfigModule
|
||||
)
|
||||
|
||||
if (process.env.VERCEL_BUILDER) {
|
||||
debug("Loading Vercel's next.config.js...")
|
||||
const nextConfig = require(join('dir', 'next.config.js'))
|
||||
debug("Vercel's next.config.js contents:", nextConfig)
|
||||
for (const [key, value] of Object.entries(nextConfig)) {
|
||||
userConfig[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(userConfig).length === 0) {
|
||||
Log.warn(
|
||||
'Detected blitz.config.js, no exported configuration found. https://nextjs.org/docs/messages/empty-configuration'
|
||||
@@ -461,21 +475,23 @@ export default async function loadConfig(
|
||||
...userConfig,
|
||||
})
|
||||
} else {
|
||||
const configBaseName = basename(CONFIG_FILE, extname(CONFIG_FILE))
|
||||
const nonJsPath = findUp.sync(
|
||||
const unsupportedPath = findUp.sync(
|
||||
[
|
||||
`${configBaseName}.jsx`,
|
||||
`${configBaseName}.ts`,
|
||||
`${configBaseName}.tsx`,
|
||||
`${configBaseName}.json`,
|
||||
`blitz.config.jsx`,
|
||||
`blitz.config.tsx`,
|
||||
`blitz.config.json`,
|
||||
`next.config.jsx`,
|
||||
`next.config.ts`,
|
||||
`next.config.tsx`,
|
||||
`next.config.json`,
|
||||
],
|
||||
{ cwd: dir }
|
||||
)
|
||||
if (nonJsPath?.length) {
|
||||
if (unsupportedPath?.length) {
|
||||
throw new Error(
|
||||
`Configuring Blitz.js via '${basename(
|
||||
nonJsPath
|
||||
)}' is not supported. Please replace the file with 'blitz.config.js'.`
|
||||
unsupportedPath
|
||||
)}' is not supported. Please replace the file with 'blitz.config.(js|ts)'`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ export type ServerConstructor = {
|
||||
*/
|
||||
quiet?: boolean
|
||||
/**
|
||||
* Object what you would use in next.config.js - @default {}
|
||||
* Object what you would use in blitz.config.js - @default {}
|
||||
*/
|
||||
conf?: NextConfig | null
|
||||
dev?: boolean
|
||||
@@ -606,7 +606,7 @@ export default class Server {
|
||||
let rewrites: CustomRoutes['rewrites']
|
||||
|
||||
// rewrites can be stored as an array when an array is
|
||||
// returned in next.config.js so massage them into
|
||||
// returned in blitz.config.js so massage them into
|
||||
// the expected object format
|
||||
if (Array.isArray(customRoutes.rewrites)) {
|
||||
rewrites = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"nextjsVersion": "11.0.1",
|
||||
"description": "The React Framework",
|
||||
"main": "./dist/server/next.js",
|
||||
@@ -83,9 +83,12 @@
|
||||
"constants-browserify": "1.0.0",
|
||||
"crypto-browserify": "3.12.0",
|
||||
"cssnano-simple": "2.0.0",
|
||||
"debug": "4.3.1",
|
||||
"domain-browser": "4.19.0",
|
||||
"encoding": "0.1.13",
|
||||
"esbuild": "^0.11.12",
|
||||
"etag": "1.8.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"get-orientation": "1.1.2",
|
||||
"https-browserify": "1.0.0",
|
||||
"image-size": "1.0.0",
|
||||
@@ -110,6 +113,7 @@
|
||||
"stream-http": "3.1.1",
|
||||
"string_decoder": "1.3.0",
|
||||
"styled-jsx": "3.3.2",
|
||||
"superjson": "1.7.2",
|
||||
"timers-browserify": "2.0.12",
|
||||
"tty-browserify": "0.0.1",
|
||||
"use-subscription": "1.5.1",
|
||||
@@ -176,8 +180,8 @@
|
||||
"@types/lru-cache": "5.1.0",
|
||||
"@types/node-fetch": "2.5.8",
|
||||
"@types/path-to-regexp": "1.7.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react-dom": "16.9.4",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/react-dom": "17.0.8",
|
||||
"@types/react-is": "16.7.1",
|
||||
"@types/semver": "7.3.1",
|
||||
"@types/send": "0.14.4",
|
||||
@@ -202,7 +206,6 @@
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.4.1",
|
||||
"css-loader": "4.3.0",
|
||||
"debug": "4.3.1",
|
||||
"devalue": "2.0.1",
|
||||
"escape-string-regexp": "2.0.0",
|
||||
"file-loader": "6.0.0",
|
||||
|
||||
@@ -166,7 +166,7 @@ export default class HotReloader {
|
||||
this.buildId = buildId
|
||||
this.dir = dir
|
||||
this.middlewares = []
|
||||
this.pagesDir = pagesDir
|
||||
this.pagesDir = dir
|
||||
this.webpackHotMiddleware = null
|
||||
this.stats = null
|
||||
this.serverStats = null
|
||||
|
||||
@@ -3,7 +3,9 @@ import chalk from 'chalk'
|
||||
import { warn } from '../../build/output/log'
|
||||
import { promises } from 'fs'
|
||||
import { denormalizePagePath } from '../../next-server/server/normalize-page-path'
|
||||
import { fileExists } from '../../lib/file-exists'
|
||||
// import { fileExists } from '../../lib/file-exists'
|
||||
import { recursiveFindPages } from '../../lib/recursive-readdir'
|
||||
import { buildPageExtensionRegex } from '../../build/utils'
|
||||
|
||||
async function isTrueCasePagePath(pagePath: string, pagesDir: string) {
|
||||
const pageSegments = normalize(pagePath).split(pathSeparator).filter(Boolean)
|
||||
@@ -22,27 +24,60 @@ export async function findPageFile(
|
||||
normalizedPagePath: string,
|
||||
pageExtensions: string[]
|
||||
): Promise<string | null> {
|
||||
const foundPagePaths: string[] = []
|
||||
// console.log('[findPageFile]', { rootDir, normalizedPagePath })
|
||||
|
||||
const page = denormalizePagePath(normalizedPagePath)
|
||||
|
||||
for (const extension of pageExtensions) {
|
||||
if (!normalizedPagePath.endsWith('/index')) {
|
||||
const relativePagePath = `${page}.${extension}`
|
||||
const pagePath = join(rootDir, relativePagePath)
|
||||
const allPages = await recursiveFindPages(
|
||||
rootDir,
|
||||
buildPageExtensionRegex(pageExtensions)
|
||||
)
|
||||
// console.log('allPages', allPages)
|
||||
|
||||
if (await fileExists(pagePath)) {
|
||||
foundPagePaths.push(relativePagePath)
|
||||
}
|
||||
}
|
||||
|
||||
const relativePagePathWithIndex = join(page, `index.${extension}`)
|
||||
const pagePathWithIndex = join(rootDir, relativePagePathWithIndex)
|
||||
if (await fileExists(pagePathWithIndex)) {
|
||||
foundPagePaths.push(relativePagePathWithIndex)
|
||||
}
|
||||
let prefix: string
|
||||
if (normalizedPagePath.startsWith('/api/')) {
|
||||
prefix = ''
|
||||
} else {
|
||||
prefix = '/pages'
|
||||
}
|
||||
|
||||
let nameMatch: string
|
||||
if (page === '/') {
|
||||
nameMatch = normalizedPagePath
|
||||
} else if (page.endsWith('/index')) {
|
||||
nameMatch = `${page}/index`
|
||||
} else {
|
||||
nameMatch = `(${page}|${page}/index)`
|
||||
}
|
||||
|
||||
nameMatch = nameMatch.replace(/[[\]\\]/g, '\\$&')
|
||||
const foundPagePaths = allPages.filter((path) =>
|
||||
path.match(
|
||||
new RegExp(`${prefix}${nameMatch}\\.(?:${pageExtensions.join('|')})$`)
|
||||
)
|
||||
)
|
||||
// console.log(
|
||||
// new RegExp(`${prefix}${nameMatch}\\.(?:${pageExtensions.join('|')})$`)
|
||||
// )
|
||||
// console.log('FOUND', foundPagePaths)
|
||||
|
||||
// for (const extension of pageExtensions) {
|
||||
// if (!normalizedPagePath.endsWith('/index')) {
|
||||
// const relativePagePath = `${page}.${extension}`
|
||||
// const pagePath = join(rootDir, relativePagePath)
|
||||
//
|
||||
// if (await fileExists(pagePath)) {
|
||||
// foundPagePaths.push(relativePagePath)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const relativePagePathWithIndex = join(page, `index.${extension}`)
|
||||
// const pagePathWithIndex = join(rootDir, relativePagePathWithIndex)
|
||||
// if (await fileExists(pagePathWithIndex)) {
|
||||
// foundPagePaths.push(relativePagePathWithIndex)
|
||||
// }
|
||||
// }
|
||||
|
||||
if (foundPagePaths.length < 1) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import findUp from 'next/dist/compiled/find-up'
|
||||
import { dirname } from 'path'
|
||||
|
||||
export function printAndExit(message: string, code = 1) {
|
||||
if (code === 0) {
|
||||
@@ -16,16 +16,14 @@ export function getNodeOptionsWithoutInspect() {
|
||||
return (process.env.NODE_OPTIONS || '').replace(NODE_INSPECT_RE, '')
|
||||
}
|
||||
|
||||
export function getProjectRoot() {
|
||||
return path.dirname(getConfigSrcPath())
|
||||
}
|
||||
export async function getProjectRoot(dir: string) {
|
||||
const pkgJsonPath = await findUp('package.json', { cwd: dir })
|
||||
|
||||
export function getConfigSrcPath() {
|
||||
const tsPath = path.resolve(path.join(process.cwd(), 'blitz.config.ts'))
|
||||
if (fs.existsSync(tsPath)) {
|
||||
return tsPath
|
||||
} else {
|
||||
const jsPath = path.resolve(path.join(process.cwd(), 'blitz.config.js'))
|
||||
return jsPath
|
||||
if (!pkgJsonPath) {
|
||||
throw new Error(
|
||||
'Unable to find project root by looking for your package.json'
|
||||
)
|
||||
}
|
||||
|
||||
return dirname(pkgJsonPath)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import { ampValidation } from '../build/output/index'
|
||||
import * as Log from '../build/output/log'
|
||||
import { PUBLIC_DIR_MIDDLEWARE_CONFLICT } from '../lib/constants'
|
||||
import { fileExists } from '../lib/file-exists'
|
||||
import { findPagesDir } from '../lib/find-pages-dir'
|
||||
import loadCustomRoutes, { CustomRoutes } from '../lib/load-custom-routes'
|
||||
import { verifyTypeScriptSetup } from '../lib/verifyTypeScriptSetup'
|
||||
import {
|
||||
@@ -39,6 +38,12 @@ import { findPageFile } from './lib/find-page-file'
|
||||
import { getNodeOptionsWithoutInspect } from './lib/utils'
|
||||
import { withCoalescedInvoke } from '../lib/coalesced-function'
|
||||
import { NextConfig } from '../next-server/server/config'
|
||||
import {
|
||||
buildPageExtensionRegex,
|
||||
convertPageFilePathToRoutePath,
|
||||
isPageFile,
|
||||
topLevelFoldersThatMayContainPages,
|
||||
} from '../build/utils'
|
||||
|
||||
if (typeof React.Suspense === 'undefined') {
|
||||
throw new Error(
|
||||
@@ -107,7 +112,7 @@ export default class DevServer extends Server {
|
||||
)
|
||||
}
|
||||
this.isCustomServer = !options.isNextDevCommand
|
||||
this.pagesDir = findPagesDir(this.dir)
|
||||
this.pagesDir = this.dir
|
||||
this.staticPathsWorker = new Worker(
|
||||
require.resolve('./static-paths-worker'),
|
||||
{
|
||||
@@ -187,8 +192,8 @@ export default class DevServer extends Server {
|
||||
return
|
||||
}
|
||||
|
||||
const regexPageExtension = new RegExp(
|
||||
`\\.+(?:${this.nextConfig.pageExtensions.join('|')})$`
|
||||
const regexPageExtension = buildPageExtensionRegex(
|
||||
this.nextConfig.pageExtensions
|
||||
)
|
||||
|
||||
let resolved = false
|
||||
@@ -208,18 +213,31 @@ export default class DevServer extends Server {
|
||||
})
|
||||
|
||||
let wp = (this.webpackWatcher = new Watchpack())
|
||||
wp.watch([], [pagesDir!], 0)
|
||||
wp.watch(
|
||||
[],
|
||||
topLevelFoldersThatMayContainPages.map((dir) =>
|
||||
pathJoin(pagesDir!, dir)
|
||||
),
|
||||
0
|
||||
)
|
||||
|
||||
wp.on('aggregated', () => {
|
||||
const routedPages = []
|
||||
const knownFiles = wp.getTimeInfoEntries()
|
||||
for (const [fileName, { accuracy }] of knownFiles) {
|
||||
if (accuracy === undefined || !regexPageExtension.test(fileName)) {
|
||||
for (const [filePath, { accuracy }] of knownFiles) {
|
||||
const relativePath = '/' + relative(pagesDir!, filePath)
|
||||
|
||||
if (
|
||||
accuracy === undefined ||
|
||||
!isPageFile(relativePath) ||
|
||||
!regexPageExtension.test(filePath)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
let pageName =
|
||||
'/' + relative(pagesDir!, fileName).replace(/\\+/g, '/')
|
||||
let pageName = relativePath.replace(/\\+/g, '/')
|
||||
|
||||
pageName = convertPageFilePathToRoutePath(pageName)
|
||||
pageName = pageName.replace(regexPageExtension, '')
|
||||
pageName = pageName.replace(/\/index$/, '') || '/'
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { pageNotFoundError } from '../next-server/server/require'
|
||||
import { findPageFile } from './lib/find-page-file'
|
||||
import getRouteFromEntrypoint from '../next-server/server/get-route-from-entrypoint'
|
||||
import { convertPageFilePathToRoutePath } from '../build/utils'
|
||||
|
||||
export const ADDED = Symbol('added')
|
||||
export const BUILDING = Symbol('building')
|
||||
@@ -158,7 +159,7 @@ export default function onDemandEntryHandler(
|
||||
throw pageNotFoundError(normalizedPagePath)
|
||||
}
|
||||
|
||||
let pageUrl = pagePath.replace(/\\/g, '/')
|
||||
let pageUrl = convertPageFilePathToRoutePath(pagePath.replace(/\\/g, '/'))
|
||||
|
||||
pageUrl = `${pageUrl[0] !== '/' ? '/' : ''}${pageUrl
|
||||
.replace(new RegExp(`\\.+(?:${pageExtensions.join('|')})$`), '')
|
||||
|
||||
@@ -123,8 +123,8 @@ describe('Build Output', () => {
|
||||
)
|
||||
expect(indexSize.endsWith('B')).toBe(true)
|
||||
|
||||
const blitzExtra = 38
|
||||
const blitzExtraGz = 10.2
|
||||
const blitzExtra = 32
|
||||
const blitzExtraGz = 8.7
|
||||
expect(parseFloat(indexFirstLoad)).toBeCloseTo(
|
||||
gz ? 64 + blitzExtraGz : 196 + blitzExtra,
|
||||
0
|
||||
@@ -168,8 +168,8 @@ describe('Build Output', () => {
|
||||
)
|
||||
expect(mainSize.endsWith('kB')).toBe(true)
|
||||
|
||||
const blitzFrameworkExtra = 13
|
||||
const blitzFrameworkExtraGz = 3.2
|
||||
const blitzFrameworkExtra = 7
|
||||
const blitzFrameworkExtraGz = 1.6
|
||||
expect(parseFloat(frameworkSize)).toBeCloseTo(
|
||||
gz ? 42.0 + blitzFrameworkExtraGz : 130 + blitzFrameworkExtra,
|
||||
0
|
||||
|
||||
@@ -74,6 +74,7 @@ describe('Client Navigation accessibility', () => {
|
||||
|
||||
const title = await browser.eval('document.title')
|
||||
|
||||
await waitFor(500)
|
||||
const routeAnnouncerValue = await browser
|
||||
.waitForElementByCss('#__next-route-announcer__')
|
||||
.text()
|
||||
@@ -92,6 +93,7 @@ describe('Client Navigation accessibility', () => {
|
||||
|
||||
const pathname = '/page-without-h1-or-title'
|
||||
|
||||
await waitFor(500)
|
||||
const routeAnnouncerValue = await browser
|
||||
.waitForElementByCss('#__next-route-announcer__')
|
||||
.text()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"url": "https://fonts.googleapis.com/css?family=Voces",
|
||||
"content": "@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v12/-F6_fjJyLyU8d7PGDmk.woff) format('woff')}@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v12/-F6_fjJyLyU8d7PIDm_6pClI_ik.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v12/-F6_fjJyLyU8d7PGDm_6pClI.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}"
|
||||
"content": "@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v15/-F6_fjJyLyU8d7PGDmk.woff) format('woff')}@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v15/-F6_fjJyLyU8d7PIDm_6pClI_ik.woff2) format('woff2');unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:'Voces';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/s/voces/v15/-F6_fjJyLyU8d7PGDm_6pClI.woff2) format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}"
|
||||
},
|
||||
{
|
||||
"url": "https://fonts.googleapis.com/css2?family=Modak",
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
onDemandEntries: {
|
||||
// Make sure entries are not getting disposed.
|
||||
maxInactiveAge: 1000 * 60 * 60,
|
||||
},
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export default function Abc() {
|
||||
return <div />
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/* eslint-env jest */
|
||||
import { nextBuild } from 'next-test-utils'
|
||||
import { join } from 'path'
|
||||
|
||||
jest.setTimeout(1000 * 60 * 2)
|
||||
|
||||
const appDir = join(__dirname, '..')
|
||||
|
||||
describe('Empty JSConfig Support', () => {
|
||||
test('should compile successfully', async () => {
|
||||
const { code, stdout } = await nextBuild(appDir, [], {
|
||||
stdout: true,
|
||||
})
|
||||
expect(code).toBe(0)
|
||||
expect(stdout).toMatch(/Compiled successfully/)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable-next-line */
|
||||
import fs from 'fs'
|
||||
|
||||
export default (_req, res) => {
|
||||
res.send('ok')
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable-next-line */
|
||||
import fs from 'fs'
|
||||
|
||||
export default (_req, res) => {
|
||||
res.send('ok')
|
||||
}
|
||||
2
nextjs/test/integration/multi-pages/app/api/hook.spec.js
Normal file
2
nextjs/test/integration/multi-pages/app/api/hook.spec.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const Page = () => throw new Error('should not be processed as a page')
|
||||
export default Page
|
||||
9
nextjs/test/integration/multi-pages/app/pages/_app.js
Normal file
9
nextjs/test/integration/multi-pages/app/pages/_app.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react'
|
||||
|
||||
export default class App extends React.Component {
|
||||
render() {
|
||||
const { Component, pageProps } = this.props
|
||||
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
}
|
||||
2
nextjs/test/integration/multi-pages/app/pages/home.js
Normal file
2
nextjs/test/integration/multi-pages/app/pages/home.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const Page = () => <div id="page-container">Home page</div>
|
||||
export default Page
|
||||
@@ -0,0 +1,2 @@
|
||||
const Page = () => throw new Error('should not be processed as a page')
|
||||
export default Page
|
||||
@@ -0,0 +1,2 @@
|
||||
const Page = () => <div id="page-container">Some page</div>
|
||||
export default Page
|
||||
@@ -0,0 +1,2 @@
|
||||
const Page = () => <div id="page-container">Some page</div>
|
||||
export default Page
|
||||
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable-next-line */
|
||||
import fs from 'fs'
|
||||
|
||||
export default (_req, res) => {
|
||||
res.send('ok')
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable-next-line */
|
||||
import fs from 'fs'
|
||||
|
||||
export default (_req, res) => {
|
||||
res.send('ok')
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable-next-line */
|
||||
import fs from 'fs'
|
||||
|
||||
export default (_req, res) => {
|
||||
res.send('ok')
|
||||
}
|
||||
2
nextjs/test/integration/multi-pages/pages/index.js
Normal file
2
nextjs/test/integration/multi-pages/pages/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const Page = () => <div id="page-container">Hello World</div>
|
||||
export default Page
|
||||
2
nextjs/test/integration/multi-pages/pages/nested/1.js
Normal file
2
nextjs/test/integration/multi-pages/pages/nested/1.js
Normal file
@@ -0,0 +1,2 @@
|
||||
const Page = () => <div id="page-container">Some page</div>
|
||||
export default Page
|
||||
@@ -0,0 +1,2 @@
|
||||
const Page = () => <div id="page-container">Some page</div>
|
||||
export default Page
|
||||
126
nextjs/test/integration/multi-pages/test/index.test.js
Normal file
126
nextjs/test/integration/multi-pages/test/index.test.js
Normal file
@@ -0,0 +1,126 @@
|
||||
import {
|
||||
nextBuild,
|
||||
findPort,
|
||||
killApp,
|
||||
nextStart,
|
||||
launchApp,
|
||||
renderViaHTTP,
|
||||
} from 'next-test-utils'
|
||||
import fs from 'fs-extra'
|
||||
import webdriver from 'next-webdriver'
|
||||
import { join } from 'path'
|
||||
|
||||
let app
|
||||
let appPort
|
||||
const appDir = join(__dirname, '..')
|
||||
const nextConfig = join(appDir, 'next.config.js')
|
||||
|
||||
const specPage = join(appDir, 'app/pages/home.spec.js')
|
||||
const testPage = join(appDir, 'app/pages/home.test.js')
|
||||
const specApi = join(appDir, 'app/api/hook.spec.js')
|
||||
const testApi = join(appDir, 'app/api/hook.test.js')
|
||||
|
||||
jest.setTimeout(1000 * 60 * 2)
|
||||
|
||||
beforeAll(async () => {
|
||||
await fs.copy(specPage, testPage)
|
||||
await fs.copy(specApi, testApi)
|
||||
})
|
||||
afterAll(async () => {
|
||||
await fs.remove(testPage)
|
||||
await fs.remove(testApi)
|
||||
})
|
||||
|
||||
const runTests = (mode) => {
|
||||
it('should load the pages', async () => {
|
||||
const browser = await webdriver(appPort, '/')
|
||||
let text = await browser.elementByCss('#page-container').text()
|
||||
expect(text).toMatch('Hello World')
|
||||
|
||||
await browser.eval('window.location = "/home"')
|
||||
text = await browser.elementByCss('#page-container').text()
|
||||
expect(text).toMatch('Home page')
|
||||
|
||||
await browser.eval('window.location = "/pages/new"')
|
||||
text = await browser.elementByCss('#page-container').text()
|
||||
expect(text).toMatch('Some page')
|
||||
|
||||
await browser.eval('window.location = "/api/hello-api"')
|
||||
text = await browser.elementByCss('pre').text()
|
||||
expect(text).toMatch('ok')
|
||||
|
||||
await browser.eval('window.location = "/api/api-health"')
|
||||
text = await browser.elementByCss('pre').text()
|
||||
expect(text).toMatch('ok')
|
||||
|
||||
await browser.eval('window.location = "/api/auth/twitter"')
|
||||
text = await browser.elementByCss('pre').text()
|
||||
expect(text).toMatch('ok')
|
||||
})
|
||||
|
||||
it('should not have test or spec pages', async () => {
|
||||
let html = await renderViaHTTP(appPort, '/home.test')
|
||||
expect(html).toContain('This page could not be found')
|
||||
|
||||
html = await renderViaHTTP(appPort, '/home.spec')
|
||||
expect(html).toContain('This page could not be found')
|
||||
})
|
||||
|
||||
if (mode !== 'dev') {
|
||||
it('should build routes', async () => {
|
||||
const pagesManifest = JSON.parse(
|
||||
await fs.readFile(
|
||||
join(appDir, `.next/${mode}/pages-manifest.json`),
|
||||
'utf8'
|
||||
)
|
||||
)
|
||||
const pages = Object.keys(pagesManifest)
|
||||
expect(pages.includes('/home')).toBeTruthy()
|
||||
expect(pages.includes('/pages/new')).toBeTruthy()
|
||||
expect(pages.includes('/api/api-health')).toBeTruthy()
|
||||
expect(pages.includes('/api/v1/api/launch-api')).toBeTruthy()
|
||||
expect(
|
||||
pages.includes('/api/v1/pages/nested-inside-api-pages')
|
||||
).toBeTruthy()
|
||||
|
||||
expect(pages.includes('/home.test')).toBeFalsy()
|
||||
expect(pages.includes('/home.spec')).toBeFalsy()
|
||||
expect(pages.includes('/api/hook.spec')).toBeFalsy()
|
||||
expect(pages.includes('/api/hook.test')).toBeFalsy()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
describe('dev mode', () => {
|
||||
beforeAll(async () => {
|
||||
appPort = await findPort()
|
||||
app = await launchApp(appDir, appPort)
|
||||
})
|
||||
afterAll(() => killApp(app))
|
||||
runTests('dev')
|
||||
})
|
||||
|
||||
describe('production mode', () => {
|
||||
beforeAll(async () => {
|
||||
await nextBuild(appDir)
|
||||
appPort = await findPort()
|
||||
app = await nextStart(appDir, appPort)
|
||||
})
|
||||
afterAll(() => killApp(app))
|
||||
runTests('server')
|
||||
})
|
||||
|
||||
describe('serverless mode', () => {
|
||||
beforeAll(async () => {
|
||||
await fs.writeFile(nextConfig, `module.exports = { target: 'serverless' }`)
|
||||
await nextBuild(appDir)
|
||||
appPort = await findPort()
|
||||
app = await nextStart(appDir, appPort)
|
||||
})
|
||||
afterAll(async () => {
|
||||
await killApp(app)
|
||||
await fs.remove(nextConfig)
|
||||
})
|
||||
|
||||
runTests('serverless')
|
||||
})
|
||||
@@ -17,13 +17,16 @@ describe('no anonymous default export warning', () => {
|
||||
beforeEach(async () => {
|
||||
await fs.remove(join(appDir, '.next'))
|
||||
})
|
||||
afterEach(async () => {
|
||||
await fs.remove(join(appDir, '.next'))
|
||||
})
|
||||
|
||||
it('show correct warnings for page', async () => {
|
||||
let stderr = ''
|
||||
|
||||
const appPort = await findPort()
|
||||
const app = await launchApp(appDir, appPort, {
|
||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||
env: { __NEXT_TEST_WITH_DEVTOOL: true, __NEXT_TEST_ANON_EXPORT: true },
|
||||
onStderr(msg) {
|
||||
stderr += msg || ''
|
||||
},
|
||||
@@ -50,7 +53,7 @@ describe('no anonymous default export warning', () => {
|
||||
|
||||
const appPort = await findPort()
|
||||
const app = await launchApp(appDir, appPort, {
|
||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||
env: { __NEXT_TEST_WITH_DEVTOOL: true, __NEXT_TEST_ANON_EXPORT: true },
|
||||
onStderr(msg) {
|
||||
stderr += msg || ''
|
||||
},
|
||||
@@ -77,7 +80,7 @@ describe('no anonymous default export warning', () => {
|
||||
|
||||
const appPort = await findPort()
|
||||
const app = await launchApp(appDir, appPort, {
|
||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||
env: { __NEXT_TEST_WITH_DEVTOOL: true, __NEXT_TEST_ANON_EXPORT: true },
|
||||
onStderr(msg) {
|
||||
stderr += msg || ''
|
||||
},
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
|
||||
import { join } from 'path'
|
||||
import webdriver from 'next-webdriver'
|
||||
import { killApp, findPort, nextBuild, nextStart } from 'next-test-utils'
|
||||
import {
|
||||
killApp,
|
||||
findPort,
|
||||
nextBuild,
|
||||
nextStart,
|
||||
waitFor,
|
||||
} from 'next-test-utils'
|
||||
|
||||
const appDir = join(__dirname, '../')
|
||||
let appPort
|
||||
@@ -59,6 +65,7 @@ describe('Analytics relayer', () => {
|
||||
expect(largestContentfulPaint).not.toBeNaN()
|
||||
expect(largestContentfulPaint).toBeGreaterThan(0)
|
||||
|
||||
await waitFor(100)
|
||||
const beacons = (await browser.eval('window.__BEACONS')).map(([, value]) =>
|
||||
Object.fromEntries(new URLSearchParams(value))
|
||||
)
|
||||
|
||||
@@ -85,7 +85,7 @@ describe('Production response size', () => {
|
||||
const delta = responseSizesBytes / 1024
|
||||
|
||||
// Expected difference: < 0.5
|
||||
const blitzExtra = 36.08
|
||||
const blitzExtra = 30.24
|
||||
expect(delta).toBeCloseTo(286.8 + blitzExtra, 0)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default () => <h1>PAGES DIR</h1>
|
||||
export default () => <h1>SRC</h1>
|
||||
|
||||
@@ -23,9 +23,11 @@ function runTests(dev) {
|
||||
expect(html).toMatch(/PAGES/)
|
||||
})
|
||||
|
||||
it('should render not render from src/pages', async () => {
|
||||
it('should render from src/pages', async () => {
|
||||
const html = await renderViaHTTP(appPort, '/hello')
|
||||
expect(html).toMatch(/404/)
|
||||
expect(html).toMatch(/SRC/)
|
||||
const html2 = await renderViaHTTP(appPort, '/world')
|
||||
expect(html2).toMatch(/SRC/)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,8 @@ describe('Telemetry CLI', () => {
|
||||
expect(stdout).toMatch(/Status: Disabled/)
|
||||
})
|
||||
|
||||
it('detects isSrcDir dir correctly for `next build`', async () => {
|
||||
it.skip('detects isSrcDir dir correctly for `next build`', async () => {
|
||||
// blitz
|
||||
const { stderr } = await runNextCommand(['build', appDir], {
|
||||
stderr: true,
|
||||
env: {
|
||||
@@ -132,11 +133,9 @@ describe('Telemetry CLI', () => {
|
||||
|
||||
const event1 = /NEXT_BUILD_COMPLETED[\s\S]+?{([\s\S]+?)}/.exec(stderr).pop()
|
||||
expect(event1).toMatch(/hasDunderPages.*?true/)
|
||||
expect(event1).toMatch(/hasTestPages.*?true/)
|
||||
|
||||
const event2 = /NEXT_BUILD_OPTIMIZED[\s\S]+?{([\s\S]+?)}/.exec(stderr).pop()
|
||||
expect(event2).toMatch(/hasDunderPages.*?true/)
|
||||
expect(event2).toMatch(/hasTestPages.*?true/)
|
||||
})
|
||||
|
||||
it('detects correct cli session defaults', async () => {
|
||||
@@ -337,7 +336,8 @@ describe('Telemetry CLI', () => {
|
||||
expect(event1).toMatch(/"totalPageCount": 6/)
|
||||
})
|
||||
|
||||
it('detects isSrcDir dir correctly for `next dev`', async () => {
|
||||
it.skip('detects isSrcDir dir correctly for `next dev`', async () => {
|
||||
// blitz
|
||||
let port = await findPort()
|
||||
let stderr = ''
|
||||
|
||||
|
||||
@@ -89,12 +89,10 @@ describe('config', () => {
|
||||
PHASE_DEVELOPMENT_SERVER,
|
||||
join(__dirname, '_resolvedata', 'typescript-config')
|
||||
)
|
||||
).rejects.toThrow(
|
||||
/Configuring Blitz.js via .+ is not supported. Please replace the file with 'blitz.config.js'/
|
||||
)
|
||||
).rejects.toThrow(/Configuring Blitz.js via .* is not supported/)
|
||||
})
|
||||
|
||||
it('Should not throw an error when two versions of next.config.js are present', async () => {
|
||||
it('Should not throw an error when two versions of blitz.config.js are present', async () => {
|
||||
const config = await loadConfig(
|
||||
PHASE_DEVELOPMENT_SERVER,
|
||||
join(__dirname, '_resolvedata', 'js-ts-config')
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* eslint-env jest */
|
||||
import { Console } from 'console'
|
||||
|
||||
process.env.BLITZ_TEST_ENVIRONMENT = true
|
||||
|
||||
@@ -7,3 +8,6 @@ if (process.env.JEST_RETRY_TIMES) {
|
||||
console.log(`Configuring jest retries: ${retries}`)
|
||||
jest.retryTimes(retries)
|
||||
}
|
||||
|
||||
// Reset to default console instead of the verbose Jest one
|
||||
global.console = new Console({ stdout: process.stdout, stderr: process.stderr })
|
||||
|
||||
@@ -118,15 +118,13 @@ export function runNextCommand(argv, options = {}) {
|
||||
}
|
||||
|
||||
let stderrOutput = ''
|
||||
if (options.stderr) {
|
||||
instance.stderr.on('data', function (chunk) {
|
||||
stderrOutput += chunk
|
||||
instance.stderr.on('data', function (chunk) {
|
||||
stderrOutput += chunk
|
||||
|
||||
if (options.stderr === 'log') {
|
||||
console.log(chunk.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
if (options.stderr === 'log') {
|
||||
console.log(chunk.toString())
|
||||
}
|
||||
})
|
||||
|
||||
let stdoutOutput = ''
|
||||
if (options.stdout) {
|
||||
@@ -146,6 +144,7 @@ export function runNextCommand(argv, options = {}) {
|
||||
!options.ignoreFail &&
|
||||
code !== 0
|
||||
) {
|
||||
console.log(stderrOutput)
|
||||
return reject(new Error(`command failed with code ${code}`))
|
||||
}
|
||||
|
||||
|
||||
@@ -174,10 +174,10 @@ export default async function webdriver(
|
||||
|
||||
const url = `http://${deviceIP}:${appPort}${path}`
|
||||
browser.initUrl = url
|
||||
console.log(`\n> Loading browser with ${url}\n`)
|
||||
console.log(`> Loading browser with ${url}`)
|
||||
|
||||
await browser.get(url)
|
||||
console.log(`\n> Loaded browser with ${url}\n`)
|
||||
console.log(`> Loaded browser with ${url}`)
|
||||
|
||||
// Wait for application to hydrate
|
||||
if (waitHydration) {
|
||||
|
||||
@@ -5,24 +5,24 @@ import { normalizePagePath } from 'next/dist/next-server/server/normalize-page-p
|
||||
import { join } from 'path'
|
||||
|
||||
const resolveDataDir = join(__dirname, '..', 'isolated', '_resolvedata')
|
||||
const dirWithPages = join(resolveDataDir, 'readdir', 'pages')
|
||||
const dirWithPages = join(resolveDataDir, 'readdir')
|
||||
|
||||
describe('findPageFile', () => {
|
||||
it('should work', async () => {
|
||||
const pagePath = normalizePagePath('/nav/about')
|
||||
const result = await findPageFile(dirWithPages, pagePath, ['jsx', 'js'])
|
||||
expect(result).toMatch(/^[\\/]nav[\\/]about\.js/)
|
||||
expect(result).toMatch(/^[\\/]pages[\\/]nav[\\/]about\.js/)
|
||||
})
|
||||
|
||||
it('should work with nested index.js', async () => {
|
||||
const pagePath = normalizePagePath('/nested')
|
||||
const result = await findPageFile(dirWithPages, pagePath, ['jsx', 'js'])
|
||||
expect(result).toMatch(/^[\\/]nested[\\/]index\.js/)
|
||||
expect(result).toMatch(/^[\\/]pages[\\/]nested[\\/]index\.js/)
|
||||
})
|
||||
|
||||
it('should prefer prefered.js before preferred/index.js', async () => {
|
||||
const pagePath = normalizePagePath('/prefered')
|
||||
const result = await findPageFile(dirWithPages, pagePath, ['jsx', 'js'])
|
||||
expect(result).toMatch(/^[\\/]prefered\.js/)
|
||||
expect(result).toMatch(/^[\\/]pages[\\/]prefered\.js/)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('Link rendering', () => {
|
||||
)
|
||||
const html = ReactDOM.renderToString(element)
|
||||
expect(html).toMatchInlineSnapshot(
|
||||
`"<a href=\\"/my-path\\" data-reactroot=\\"\\">to another page</a>"`
|
||||
`"<a href=\\"/my-path\\">to another page</a>"`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -51,9 +51,7 @@ const babel = async (code, queryOpts = {}) => {
|
||||
isServer,
|
||||
distDir: path.resolve(dir, '.next'),
|
||||
pagesDir:
|
||||
'pagesDir' in queryOpts
|
||||
? queryOpts.pagesDir
|
||||
: path.resolve(dir, 'pages'),
|
||||
'pagesDir' in queryOpts ? queryOpts.pagesDir : path.resolve(dir),
|
||||
cache: false,
|
||||
development,
|
||||
hasReactRefresh: Boolean(!isServer && development),
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"dev:nextjs-types": "yarn wait:nextjs && yarn workspace next types && echo 'Finished building nextjs types'",
|
||||
"dev:blitz": "cross-env BLITZ_PROD_BUILD=true preconstruct watch",
|
||||
"dev:tsc": "yarn dev:nextjs-types && tsc --watch --pretty --preserveWatchOutput",
|
||||
"dev:cli": "yarn wait:nextjs && yarn workspace @blitzjs/cli dev",
|
||||
"dev:cli": "yarn wait:nextjs-types && yarn workspace @blitzjs/cli dev",
|
||||
"dev:templates": "yarn workspace @blitzjs/generator dev",
|
||||
"dev": "concurrently --names \"nextjs,blitz,typecheck,cli,templates\" -c \"magenta,cyan,green,yellow,black\" -p \"{name}\" \"npm:dev:nextjs\" \"npm:dev:blitz\" \"npm:dev:tsc\" \"npm:dev:cli\" \"npm:dev:templates\"",
|
||||
"build:nextjs": "yarn workspace next prepublish",
|
||||
@@ -124,8 +124,8 @@
|
||||
"@types/progress": "^2.0.3",
|
||||
"@types/pump": "1.1.0",
|
||||
"@types/pumpify": "1.4.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react-dom": "16.9.4",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/react-dom": "17.0.8",
|
||||
"@types/readable-stream": "2.3.9",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/tar": "4.0.4",
|
||||
@@ -178,6 +178,8 @@
|
||||
"prettier": "2.2.1",
|
||||
"prettier-plugin-prisma": "0.4.0",
|
||||
"prompt": "1.1.0",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-test-renderer": "17.0.1",
|
||||
"release": "6.3.0",
|
||||
"rimraf": "^3.0.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/babel-preset",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
|
||||
@@ -85,17 +85,21 @@ const pagesToSkip = ([] as string[]).concat(
|
||||
);
|
||||
|
||||
function isPage(filePath: string) {
|
||||
if (!filePath.includes('pages' + nodePath.sep)) {
|
||||
if (!filePath.includes(nodePath.sep + 'pages' + nodePath.sep)) {
|
||||
return false;
|
||||
}
|
||||
if (filePath.includes('pages' + nodePath.sep + 'api')) {
|
||||
if (
|
||||
filePath.includes(
|
||||
nodePath.sep + 'pages' + nodePath.sep + 'api' + nodePath.sep
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return !pagesToSkip.some((fileToSkip) => filePath.includes(fileToSkip));
|
||||
}
|
||||
|
||||
function isApiRoute(filePath: string) {
|
||||
if (filePath.includes('pages' + nodePath.sep + 'api')) {
|
||||
if (filePath.includes(nodePath.sep + 'api' + nodePath.sep)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "blitz",
|
||||
"description": "Blitz is a Rails-like framework for monolithic, full-stack React apps — built on Next.js",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
@@ -51,13 +51,13 @@
|
||||
"url": "https://github.com/blitz-js/blitz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/babel-preset": "0.38.2",
|
||||
"@blitzjs/cli": "0.38.2",
|
||||
"@blitzjs/config": "0.38.2",
|
||||
"@blitzjs/core": "0.38.2",
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/generator": "0.38.2",
|
||||
"@blitzjs/server": "0.38.2",
|
||||
"@blitzjs/babel-preset": "0.38.3-canary.1",
|
||||
"@blitzjs/cli": "0.38.3-canary.1",
|
||||
"@blitzjs/config": "0.38.3-canary.1",
|
||||
"@blitzjs/core": "0.38.3-canary.1",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"@blitzjs/generator": "0.38.3-canary.1",
|
||||
"@blitzjs/server": "0.38.3-canary.1",
|
||||
"@testing-library/jest-dom": "5.11.9",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
@@ -66,7 +66,7 @@
|
||||
"cross-spawn": "7.0.3",
|
||||
"debug": "4.3.1",
|
||||
"envinfo": "^7.7.3",
|
||||
"eslint-config-blitz": "0.38.2",
|
||||
"eslint-config-blitz": "0.38.3-canary.1",
|
||||
"jest": "^26.6.3",
|
||||
"jest-watch-typeahead": "^0.6.1",
|
||||
"minimist": "1.2.5",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@blitzjs/cli",
|
||||
"description": "Blitz.js CLI",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"dev": "rimraf lib && tsc --watch --pretty --preserveWatchOutput",
|
||||
@@ -22,8 +22,8 @@
|
||||
"/lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/repl": "0.38.2",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"@blitzjs/repl": "0.38.3-canary.1",
|
||||
"@oclif/command": "1.8.0",
|
||||
"@oclif/config": "1.17.0",
|
||||
"@oclif/plugin-autocomplete": "0.3.0",
|
||||
@@ -56,9 +56,9 @@
|
||||
"v8-compile-cache": "2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/generator": "0.38.2",
|
||||
"@blitzjs/installer": "0.38.2",
|
||||
"@blitzjs/server": "0.38.2",
|
||||
"@blitzjs/generator": "0.38.3-canary.1",
|
||||
"@blitzjs/installer": "0.38.3-canary.1",
|
||||
"@blitzjs/server": "0.38.3-canary.1",
|
||||
"@oclif/dev-cli": "1.26.0",
|
||||
"@oclif/test": "1.2.8",
|
||||
"nock": "13.0.6",
|
||||
|
||||
@@ -2,8 +2,9 @@ require("v8-compile-cache")
|
||||
const cacheFile = require("path").join(__dirname, ".blitzjs-cli-cache")
|
||||
const lazyLoad = require("@salesforce/lazy-require").default.create(cacheFile)
|
||||
lazyLoad.start()
|
||||
import {buildConfig} from "@blitzjs/config"
|
||||
import {getProjectRoot} from "@blitzjs/config"
|
||||
import {run as oclifRun} from "@oclif/command"
|
||||
import {compileConfig} from "next/dist/next-server/server/config-shared"
|
||||
|
||||
// Load the .env environment variable so it's available for all commands
|
||||
require("dotenv-expand")(require("dotenv-flow").config({silent: true}))
|
||||
@@ -13,7 +14,7 @@ function buildConfigIfNeeded() {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
return buildConfig()
|
||||
return compileConfig(getProjectRoot())
|
||||
}
|
||||
|
||||
function runOclif() {
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": false,
|
||||
"noEmit": false,
|
||||
"incremental": true
|
||||
"incremental": false,
|
||||
"tsBuildInfoFile": null
|
||||
},
|
||||
"include": ["src/**/*", "types", "../../types"]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/config",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "Loads the blitz app config",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import * as esbuild from "esbuild"
|
||||
import fs from "fs"
|
||||
import {existsSync, readJSONSync} from "fs-extra"
|
||||
import {NextConfig} from "next/dist/next-server/server/config"
|
||||
import path, {join} from "path"
|
||||
import pkgDir from "pkg-dir"
|
||||
const debug = require("debug")("blitz:config")
|
||||
|
||||
type NextExperimental = NextConfig["experimental"]
|
||||
@@ -45,14 +42,10 @@ export interface BlitzConfigNormalized extends BlitzConfig {
|
||||
}
|
||||
|
||||
export function getProjectRoot() {
|
||||
// TODO consolidate with nextjs/packages/next/server/lib/utils.ts
|
||||
// IF THIS IS UPDATED, so does the one inside nextjs
|
||||
return path.dirname(getConfigSrcPath())
|
||||
}
|
||||
|
||||
export function getConfigSrcPath() {
|
||||
// TODO consolidate with nextjs/packages/next/server/lib/utils.ts
|
||||
// IF THIS IS UPDATED, so does the one inside nextjs
|
||||
const tsPath = path.resolve(path.join(process.cwd(), "blitz.config.ts"))
|
||||
if (existsSync(tsPath)) {
|
||||
return tsPath
|
||||
@@ -61,64 +54,6 @@ export function getConfigSrcPath() {
|
||||
return jsPath
|
||||
}
|
||||
}
|
||||
export function getConfigBuildPath() {
|
||||
return path.join(getProjectRoot(), ".blitz", "blitz.config.js")
|
||||
}
|
||||
|
||||
interface BuildConfigOptions {
|
||||
watch?: boolean
|
||||
}
|
||||
|
||||
export async function buildConfig({watch}: BuildConfigOptions = {}) {
|
||||
debug("Starting buildConfig...")
|
||||
const dir = pkgDir.sync()
|
||||
if (!dir) {
|
||||
// This will happen when running blitz no inside a blitz app
|
||||
debug("Unable to find package directory")
|
||||
return
|
||||
}
|
||||
const pkg = readJSONSync(path.join(dir, "package.json"))
|
||||
const srcPath = getConfigSrcPath()
|
||||
|
||||
if (fs.readFileSync(srcPath, "utf8").includes("tsconfig-paths/register")) {
|
||||
// User is manually handling their own typescript stuff
|
||||
debug("Config contains 'tsconfig-paths/register', so skipping build")
|
||||
return
|
||||
}
|
||||
|
||||
const esbuildOptions: esbuild.BuildOptions = {
|
||||
entryPoints: [srcPath],
|
||||
outfile: getConfigBuildPath(),
|
||||
format: "cjs",
|
||||
bundle: true,
|
||||
platform: "node",
|
||||
external: [
|
||||
"blitz",
|
||||
"next",
|
||||
...Object.keys(require("blitz/package").dependencies),
|
||||
...Object.keys(pkg?.dependencies ?? {}),
|
||||
...Object.keys(pkg?.devDependencies ?? {}),
|
||||
],
|
||||
}
|
||||
|
||||
if (watch) {
|
||||
esbuildOptions.watch = {
|
||||
onRebuild(error) {
|
||||
if (error) {
|
||||
console.error("Failed to re-build blitz config")
|
||||
} else {
|
||||
console.log("\n> Blitz config changed - restart for changes to take effect\n")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
debug("Building config...")
|
||||
debug("Src: ", getConfigSrcPath())
|
||||
debug("Build: ", getConfigBuildPath())
|
||||
await esbuild.build(esbuildOptions)
|
||||
}
|
||||
|
||||
declare global {
|
||||
namespace NodeJS {
|
||||
interface Global {
|
||||
@@ -137,11 +72,13 @@ export const getConfig = (reload?: boolean): BlitzConfigNormalized => {
|
||||
|
||||
const {PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER} = require("next/constants")
|
||||
|
||||
const projectRoot = getProjectRoot()
|
||||
|
||||
let pkgJson: any
|
||||
|
||||
const pkgJsonPath = join(getProjectRoot(), "package.json")
|
||||
if (existsSync(pkgJsonPath)) {
|
||||
pkgJson = readJSONSync(join(getProjectRoot(), "package.json"))
|
||||
pkgJson = readJSONSync(pkgJsonPath)
|
||||
}
|
||||
|
||||
let blitzConfig = {
|
||||
@@ -150,15 +87,8 @@ export const getConfig = (reload?: boolean): BlitzConfigNormalized => {
|
||||
},
|
||||
}
|
||||
|
||||
const projectRoot = getProjectRoot()
|
||||
const nextConfigPath = path.join(projectRoot, "next.config.js")
|
||||
let blitzConfigPath
|
||||
if (existsSync(path.join(projectRoot, ".blitz"))) {
|
||||
blitzConfigPath = path.join(projectRoot, ".blitz", "blitz.config.js")
|
||||
} else {
|
||||
// projectRoot is inside .blitz/build/
|
||||
blitzConfigPath = path.join(projectRoot, "..", "blitz.config.js")
|
||||
}
|
||||
const blitzConfigPath = path.join(projectRoot, ".blitz.config.compiled.js")
|
||||
|
||||
debug("nextConfigPath: " + nextConfigPath)
|
||||
debug("blitzConfigPath: " + blitzConfigPath)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@blitzjs/core",
|
||||
"description": "Blitz.js core functionality",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
@@ -31,8 +31,8 @@
|
||||
"server"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "0.38.2",
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/config": "0.38.3-canary.1",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"b64-lite": "^1.4.0",
|
||||
"bad-behavior": "^1.0.1",
|
||||
@@ -44,7 +44,7 @@
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"lodash.frompairs": "4.0.1",
|
||||
"nanoid": "^3.1.20",
|
||||
"next": "0.38.2",
|
||||
"next": "0.38.3-canary.1",
|
||||
"npm-which": "^3.0.1",
|
||||
"null-loader": "4.0.1",
|
||||
"passport": "0.4.1",
|
||||
@@ -53,7 +53,7 @@
|
||||
"superjson": "1.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"zod": "3.2.0"
|
||||
},
|
||||
"repository": "https://github.com/blitz-js/blitz",
|
||||
|
||||
@@ -61,6 +61,7 @@ export function withBlitzInnerWrapper(Page: BlitzPage) {
|
||||
redirectAuthenticatedTo = formatWithValidation(redirectAuthenticatedTo)
|
||||
}
|
||||
|
||||
clientDebug("[BlitzInnerRoot] redirecting to", redirectAuthenticatedTo)
|
||||
const error = new RedirectError(redirectAuthenticatedTo)
|
||||
error.stack = null!
|
||||
throw error
|
||||
@@ -76,6 +77,7 @@ export function withBlitzInnerWrapper(Page: BlitzPage) {
|
||||
|
||||
const url = new URL(redirectTo, window.location.href)
|
||||
url.searchParams.append("next", window.location.pathname)
|
||||
clientDebug("[BlitzInnerRoot] redirecting to", url.toString())
|
||||
const error = new RedirectError(url.toString())
|
||||
error.stack = null!
|
||||
throw error
|
||||
|
||||
@@ -94,6 +94,7 @@ class ErrorBoundary extends React.Component<
|
||||
if (error instanceof RedirectError) {
|
||||
clientDebug("Redirecting from ErrorBoundary to", error.url)
|
||||
await (this.context as Router)?.push(error.url)
|
||||
return
|
||||
}
|
||||
this.props.onError?.(error, info)
|
||||
}
|
||||
@@ -111,6 +112,7 @@ class ErrorBoundary extends React.Component<
|
||||
|
||||
handleRouteChange = () => {
|
||||
clientDebug("Resetting error boundary on route change")
|
||||
this.props.onReset?.()
|
||||
this.reset()
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,13 @@ export const executeRpcCall = <TInput, TResult>(
|
||||
}
|
||||
if (response.headers.get(HEADER_SESSION_CREATED)) {
|
||||
clientDebug("Session created")
|
||||
await queryClient.invalidateQueries("")
|
||||
// await queryClient.invalidateQueries("")
|
||||
setTimeout(async () => {
|
||||
// Do these in the next tick to prevent various bugs like https://github.com/blitz-js/blitz/issues/2207
|
||||
clientDebug("Invalidating react-query cache...")
|
||||
await queryClient.cancelQueries()
|
||||
await queryClient.resetQueries()
|
||||
})
|
||||
}
|
||||
if (response.headers.get(HEADER_CSRF_ERROR)) {
|
||||
const err = new CSRFTokenMismatchError()
|
||||
|
||||
@@ -99,21 +99,11 @@ export function passportAuth(config: BlitzPassportConfig): BlitzApiHandler {
|
||||
try {
|
||||
let error = err
|
||||
|
||||
if (!error) {
|
||||
if (result === false) {
|
||||
log.warning(
|
||||
`Login via ${strategyName} failed - usually this means the user did not authenticate properly with the provider`,
|
||||
)
|
||||
error = `Login failed`
|
||||
}
|
||||
assert(
|
||||
typeof result === "object" && result !== null,
|
||||
`Your '${strategyName}' passport verify callback returned empty data. Ensure you call 'done(null, {publicData: {userId: 1}})' along with any other publicData fields you need)`,
|
||||
)
|
||||
assert(
|
||||
(result as any).publicData,
|
||||
`'publicData' is missing from your '${strategyName}' passport verify callback. Ensure you call 'done(null, {publicData: {userId: 1}})' along with any other publicData fields you need)`,
|
||||
if (!error && result === false) {
|
||||
log.warning(
|
||||
`Login via ${strategyName} failed - usually this means the user did not authenticate properly with the provider`,
|
||||
)
|
||||
error = `Login failed`
|
||||
}
|
||||
|
||||
const redirectUrlFromVerifyResult =
|
||||
@@ -132,6 +122,14 @@ export function passportAuth(config: BlitzPassportConfig): BlitzApiHandler {
|
||||
return
|
||||
}
|
||||
|
||||
assert(
|
||||
typeof result === "object" && result !== null,
|
||||
`Your '${strategyName}' passport verify callback returned empty data. Ensure you call 'done(null, {publicData: {userId: 1}})' along with any other publicData fields you need)`,
|
||||
)
|
||||
assert(
|
||||
(result as any).publicData,
|
||||
`'publicData' is missing from your '${strategyName}' passport verify callback. Ensure you call 'done(null, {publicData: {userId: 1}})' along with any other publicData fields you need)`,
|
||||
)
|
||||
assert(isVerifyCallbackResult(result), "Passport verify callback is invalid")
|
||||
|
||||
delete (result.publicData as any)[INTERNAL_REDIRECT_URL_KEY]
|
||||
|
||||
@@ -551,6 +551,7 @@ export const setCSRFCookie = (
|
||||
expiresAt: Date,
|
||||
) => {
|
||||
debug("setCSRFCookie", antiCSRFToken)
|
||||
assert(antiCSRFToken !== undefined, "Internal error: antiCSRFToken is being set to undefined")
|
||||
setCookie(
|
||||
res,
|
||||
cookie.serialize(COOKIE_CSRF_TOKEN(), antiCSRFToken, {
|
||||
@@ -726,8 +727,8 @@ export async function getSessionKernel(
|
||||
return {
|
||||
handle: payload.handle,
|
||||
publicData: payload.publicData,
|
||||
antiCSRFToken: payload.antiCSRFToken,
|
||||
jwtPayload: payload,
|
||||
antiCSRFToken,
|
||||
anonymousSessionToken,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,7 @@ export {rpcApiHandler} from "./rpc-server"
|
||||
|
||||
export const fixNodeFileTrace = () => {
|
||||
const path = require("path")
|
||||
path.resolve("next.config.js")
|
||||
path.resolve(".blitz/blitz.config.js")
|
||||
path.resolve(".blitz.config.compiled.js")
|
||||
path.resolve(".next/server/blitz-db.js")
|
||||
path.resolve(".next/serverless/blitz-db.js")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/display",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "Display package for the Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"license": "MIT",
|
||||
@@ -28,8 +28,8 @@
|
||||
"url": "git+https://github.com/blitz-js/blitz.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "0.38.2",
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/config": "0.38.3-canary.1",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"chalk": "^4.1.0",
|
||||
"console-table-printer": "^2.7.5",
|
||||
"ora": "^5.3.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eslint-config-blitz",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "Blitz.js eslint config",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/file-pipeline",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "Display package for the Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"license": "MIT",
|
||||
@@ -28,7 +28,7 @@
|
||||
"url": "git+https://github.com/blitz-js/blitz.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"chalk": "^4.1.0",
|
||||
"chokidar": "3.5.1",
|
||||
"flush-write-stream": "2.0.0",
|
||||
|
||||
@@ -14,9 +14,17 @@ export class RouteCache implements RouteCacheInterface {
|
||||
}
|
||||
|
||||
getUrifromPath(path: string) {
|
||||
const findStr = "/pages"
|
||||
const findStrIdx = path.indexOf(findStr)
|
||||
const uri = path.substring(findStrIdx + findStr.length, path.lastIndexOf("."))
|
||||
let uri = path
|
||||
let findStr = "/pages"
|
||||
let findStrIdx = path.indexOf(findStr)
|
||||
if (findStrIdx >= 0) {
|
||||
uri = path.substring(findStrIdx + findStr.length, path.lastIndexOf("."))
|
||||
} else {
|
||||
findStr = "/api"
|
||||
findStrIdx = path.indexOf(findStr)
|
||||
uri = "/api" + path.substring(findStrIdx + findStr.length, path.lastIndexOf("."))
|
||||
}
|
||||
|
||||
const uriWithoutIndex = uri.replace("/index", "")
|
||||
return uriWithoutIndex.length > 0 ? uriWithoutIndex : "/"
|
||||
}
|
||||
@@ -44,7 +52,7 @@ export class RouteCache implements RouteCacheInterface {
|
||||
private getType(file: File): RouteType | null {
|
||||
const pagesPathRegex = /(pages[\\/][^_.].+(?<!\.test)\.(m?[tj]sx?|mdx))$/
|
||||
const rpcPathRegex = /(api[\\/].+[\\/](queries|mutations).+)$/
|
||||
const apiPathRegex = /(api[\\/].+)$/
|
||||
const apiPathRegex = /(api[\\/].+\.[tj]s)$/
|
||||
|
||||
if (rpcPathRegex.test(file.path)) {
|
||||
return "rpc"
|
||||
@@ -58,7 +66,8 @@ export class RouteCache implements RouteCacheInterface {
|
||||
}
|
||||
|
||||
add(file: File) {
|
||||
if (this.routeCache[file.orginalRelative]) return
|
||||
const srcPath = file.originalRelative ?? file.relative
|
||||
if (this.routeCache[srcPath]) return
|
||||
|
||||
const type = this.getType(file)
|
||||
if (!type) {
|
||||
@@ -68,8 +77,8 @@ export class RouteCache implements RouteCacheInterface {
|
||||
const uri = this.getUrifromPath(this.normalizePath(file.path))
|
||||
const isErrorCode = this.isErrorCode(uri)
|
||||
if (!isErrorCode) {
|
||||
this.routeCache[file.originalRelative] = {
|
||||
path: file.originalRelative,
|
||||
this.routeCache[srcPath] = {
|
||||
path: srcPath,
|
||||
uri,
|
||||
verb: this.getVerb(type),
|
||||
type,
|
||||
@@ -78,7 +87,8 @@ export class RouteCache implements RouteCacheInterface {
|
||||
}
|
||||
|
||||
delete(file: File) {
|
||||
delete this.routeCache[file.originalRelative]
|
||||
const srcPath = file.originalRelative ?? file.relative
|
||||
delete this.routeCache[srcPath]
|
||||
}
|
||||
|
||||
filterByPath(filterFn: (givenPath: string) => boolean) {
|
||||
@@ -96,7 +106,8 @@ export class RouteCache implements RouteCacheInterface {
|
||||
get(file: File): RouteCacheEntry
|
||||
get(key?: string | File) {
|
||||
if (typeof key === "string") return this.routeCache[key]
|
||||
if (key?.originalRelative) return this.routeCache[key.originalRelative]
|
||||
const srcPath = key?.originalRelative ?? key?.relative
|
||||
if (srcPath) return this.routeCache[srcPath]
|
||||
return this.routeCache
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/generator",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "File generation for the Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"license": "MIT",
|
||||
@@ -33,8 +33,8 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.1",
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/server": "0.38.2",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"@blitzjs/server": "0.38.3-canary.1",
|
||||
"@mrleebo/prisma-ast": "^0.2.4",
|
||||
"@types/jscodeshift": "0.7.2",
|
||||
"chalk": "^4.1.0",
|
||||
|
||||
@@ -13,7 +13,7 @@ web_modules/
|
||||
*.sqlite
|
||||
*.sqlite-journal
|
||||
.now
|
||||
.blitz-console-history
|
||||
.blitz**
|
||||
blitz-log.log
|
||||
|
||||
# misc
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/installer",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "Package installation for the Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"license": "MIT",
|
||||
@@ -30,9 +30,9 @@
|
||||
"dependencies": {
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/plugin-transform-typescript": "7.12.1",
|
||||
"@blitzjs/config": "0.38.2",
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/generator": "0.38.2",
|
||||
"@blitzjs/config": "0.38.3-canary.1",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"@blitzjs/generator": "0.38.3-canary.1",
|
||||
"@mrleebo/prisma-ast": "^0.2.4",
|
||||
"@prisma/sdk": "2.19.0",
|
||||
"@types/jscodeshift": "0.7.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/repl",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"description": "Repl package for Blitz CLI",
|
||||
"homepage": "https://github.com/blitz-js/blitz/packages/repl/#readme",
|
||||
"license": "MIT",
|
||||
@@ -28,7 +28,7 @@
|
||||
"url": "git+https://github.com/blitz-js/blitz.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "0.38.2",
|
||||
"@blitzjs/config": "0.38.3-canary.1",
|
||||
"chokidar": "3.5.1",
|
||||
"globby": "11.0.2",
|
||||
"pkg-dir": "^5.0.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@blitzjs/server",
|
||||
"description": "Blitz.js server functionality",
|
||||
"version": "0.38.2",
|
||||
"version": "0.38.3-canary.1",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"next-patched": "./bin/next-patched"
|
||||
@@ -23,10 +23,10 @@
|
||||
"register"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "0.38.2",
|
||||
"@blitzjs/core": "0.38.2",
|
||||
"@blitzjs/display": "0.38.2",
|
||||
"@blitzjs/file-pipeline": "0.38.2",
|
||||
"@blitzjs/config": "0.38.3-canary.1",
|
||||
"@blitzjs/core": "0.38.3-canary.1",
|
||||
"@blitzjs/display": "0.38.3-canary.1",
|
||||
"@blitzjs/file-pipeline": "0.38.3-canary.1",
|
||||
"cross-spawn": "7.0.3",
|
||||
"detect-port": "1.3.0",
|
||||
"esbuild": "^0.11.12",
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import {transform} from "@blitzjs/file-pipeline"
|
||||
import {Stage} from "@blitzjs/file-pipeline"
|
||||
import {pathExistsSync} from "fs-extra"
|
||||
import {resolve} from "path"
|
||||
import File from "vinyl"
|
||||
|
||||
const isNextConfigPath = (p: string) => /next\.config\.(js|ts)/.test(p)
|
||||
const isNowBuild = () => process.env.NOW_BUILDER || process.env.VERCEL_BUILDER
|
||||
/**
|
||||
* Returns a Stage that manages converting from blitz.config.js to next.config.js
|
||||
*/
|
||||
export const createStageConfig: Stage = ({config, processNewFile, processNewChildFile}) => {
|
||||
// Preconditions
|
||||
const hasNextConfig = pathExistsSync(resolve(config.src, "next.config.js"))
|
||||
const hasBlitzConfig =
|
||||
pathExistsSync(resolve(config.src, "blitz.config.js")) ||
|
||||
pathExistsSync(resolve(config.src, "blitz.config.ts"))
|
||||
|
||||
if (hasNextConfig && !isNowBuild()) {
|
||||
// TODO: Pause the stream and ask the user if they wish to have their configuration file renamed
|
||||
const err = new Error(
|
||||
"Blitz does not support next.config.js. Please rename your next.config.js to blitz.config.js",
|
||||
)
|
||||
err.name = "NextConfigSupportError"
|
||||
throw err
|
||||
}
|
||||
|
||||
if (!hasBlitzConfig) {
|
||||
// Assume a bare blitz config
|
||||
processNewFile(
|
||||
new File({
|
||||
cwd: config.src,
|
||||
path: resolve(config.src, "blitz.config.js"),
|
||||
contents: Buffer.from("module.exports = {};"),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
if (!hasNextConfig) {
|
||||
processNewFile(
|
||||
new File({
|
||||
cwd: config.src,
|
||||
path: resolve(config.src, "next.config.js"),
|
||||
contents: Buffer.from(`
|
||||
const config = require('../blitz.config.js');
|
||||
module.exports = config;
|
||||
`),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// No need to filter yet
|
||||
const stream = transform.file((file) => {
|
||||
if (!isNextConfigPath(file.path)) return file
|
||||
|
||||
// File is next.config.js
|
||||
|
||||
// Vercel now adds configuration needed for Now, like serverless target,
|
||||
// so we need to keep and use that
|
||||
if (isNowBuild()) {
|
||||
// Assume we have a next.config.js if NOW_BUILDER is true as the cli creates one
|
||||
|
||||
// Divert next.config to next-vercel.config.js
|
||||
processNewChildFile({
|
||||
parent: file,
|
||||
child: new File({
|
||||
cwd: config.src,
|
||||
path: resolve(config.src, "next-vercel.config.js"),
|
||||
contents: file.contents,
|
||||
}),
|
||||
stageId: "config",
|
||||
subfileId: "vercel-config",
|
||||
})
|
||||
|
||||
file.contents = Buffer.from(`
|
||||
const vercelConfig = require('./next-vercel.config.js');
|
||||
const config = require('../blitz.config.js');
|
||||
module.exports = {...config, ...vercelConfig};
|
||||
`)
|
||||
}
|
||||
|
||||
return file
|
||||
})
|
||||
|
||||
return {stream}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import {ServerEnvironment} from "../config"
|
||||
import {createStageConfig} from "./config"
|
||||
import {createStageManifest} from "./manifest"
|
||||
import {createStagePages} from "./pages"
|
||||
import {createStageRelative} from "./relative"
|
||||
import {createStageRewriteImports} from "./rewrite-imports"
|
||||
import {createStageRouteImportManifest} from "./route-import-manifest/route-import-manifest"
|
||||
@@ -23,23 +21,16 @@ export const configureStages = async (config: StagesConfig) => ({
|
||||
// Order is important
|
||||
createStageRelative,
|
||||
createStageRewriteImports,
|
||||
createStagePages,
|
||||
createStageRpc(config.isTypeScript),
|
||||
createStageRoutes,
|
||||
createStageRouteImportManifest,
|
||||
createStageConfig,
|
||||
await createStageManifest(config.writeManifestFile, config.buildFolder, config.env),
|
||||
],
|
||||
})
|
||||
|
||||
export const configureRouteStages = (config: StagesConfig) => [
|
||||
createStagePages,
|
||||
createStageRpc(config.isTypeScript),
|
||||
createStageRoutes,
|
||||
]
|
||||
|
||||
export const configureGenerateStages = () => [
|
||||
createStagePages,
|
||||
createStageRoutes,
|
||||
createStageRouteImportManifest,
|
||||
]
|
||||
export const configureGenerateStages = () => [createStageRoutes, createStageRouteImportManifest]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user