From d74dab7e8ba4ae664876e272ddbd5e6964767a98 Mon Sep 17 00:00:00 2001 From: Daniel Choudhury Date: Wed, 7 Jun 2023 13:06:06 +0700 Subject: [PATCH 01/26] Pull in changes from experimental render modes branch into Suspense Router --- packages/cli/src/commands/buildHandler.js | 49 +-- packages/cli/src/commands/devHandler.js | 47 +-- .../generate/page/templates/page.tsx.template | 3 - packages/cli/src/commands/serve.js | 149 ++------- packages/core/package.json | 3 + packages/core/src/bins/rw-dev-fe.ts | 10 + packages/core/src/bins/rw-serve-api.ts | 10 + packages/core/src/bins/rw-serve-fe.ts | 10 + packages/internal/src/build/babel/api.ts | 24 ++ packages/internal/src/build/babel/common.ts | 43 ++- packages/internal/src/build/babel/web.ts | 1 + packages/internal/src/files.ts | 7 + .../templates/api-globImports.d.ts.template | 6 +- packages/internal/src/routes.ts | 50 ++- packages/project-config/src/paths.ts | 38 +++ packages/router/src/active-route-loader.tsx | 18 +- packages/structure/src/model/RWRoute.ts | 8 + packages/vite/.babelrc.js | 5 +- packages/vite/ambient.d.ts | 15 + packages/vite/inject/reactRefresh.js | 7 + packages/vite/package.json | 11 +- packages/vite/src/buildFeServer.ts | 142 +++++++++ packages/vite/src/devFeServer.ts | 207 +++++++++++++ packages/vite/src/runFeServer.ts | 291 ++++++++++++++++++ packages/vite/src/triggerRouteHooks.ts | 59 ++++ packages/vite/src/types.ts | 14 + packages/vite/src/utils.ts | 3 + packages/vite/tsconfig.json | 1 + packages/web/src/apollo/index.tsx | 3 +- .../web/src/components/RedwoodProvider.tsx | 23 +- packages/web/src/components/htmlTags.tsx | 116 +++++++ packages/web/src/index.ts | 3 + packages/web/src/routeHooks.types.ts | 18 ++ packages/web/src/serverContext.tsx | 12 + tasks/framework-tools/lib/project.mjs | 26 +- yarn.lock | 26 +- 36 files changed, 1223 insertions(+), 235 deletions(-) create mode 100644 packages/core/src/bins/rw-dev-fe.ts create mode 100644 packages/core/src/bins/rw-serve-api.ts create mode 100644 packages/core/src/bins/rw-serve-fe.ts create mode 100644 packages/vite/ambient.d.ts create mode 100644 packages/vite/inject/reactRefresh.js create mode 100644 packages/vite/src/buildFeServer.ts create mode 100644 packages/vite/src/devFeServer.ts create mode 100644 packages/vite/src/runFeServer.ts create mode 100644 packages/vite/src/triggerRouteHooks.ts create mode 100644 packages/vite/src/types.ts create mode 100644 packages/vite/src/utils.ts create mode 100644 packages/web/src/components/htmlTags.tsx create mode 100644 packages/web/src/routeHooks.types.ts create mode 100644 packages/web/src/serverContext.tsx diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index e889e62f25b0..91210dcf88f8 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -3,15 +3,15 @@ import path from 'path' import execa from 'execa' import { Listr } from 'listr2' -import { rimraf } from 'rimraf' -import terminalLink from 'terminal-link' +import rimraf from 'rimraf' import { buildApi } from '@redwoodjs/internal/dist/build/api' import { loadAndValidateSdls } from '@redwoodjs/internal/dist/validateSchema' import { detectPrerenderRoutes } from '@redwoodjs/prerender/detection' -import { timedTelemetry, errorTelemetry } from '@redwoodjs/telemetry' +import { errorTelemetry, timedTelemetry } from '@redwoodjs/telemetry' +import { buildFeServer } from '@redwoodjs/vite' -import { getPaths, getConfig } from '../lib' +import { getConfig, getPaths } from '../lib' import c from '../lib/colors' import { generatePrismaCommand } from '../lib/generatePrismaClient' @@ -72,8 +72,8 @@ export const handler = async ({ }, side.includes('api') && { title: 'Building API...', - task: () => { - const { errors, warnings } = buildApi() + task: async () => { + const { errors, warnings } = await buildApi() if (errors.length) { console.error(errors) @@ -96,13 +96,8 @@ export const handler = async ({ title: 'Building Web...', task: async () => { if (getConfig().web.bundler === 'vite') { - // @NOTE: we're using the vite build command here, instead of the buildWeb function - // because we want the process.cwd to be the web directory, not the root of the project - // This is important for postcss/tailwind to work correctly - await execa(`yarn rw-vite-build`, { - stdio: verbose ? 'inherit' : 'pipe', - shell: true, - cwd: rwjsPaths.web.base, // <-- important for postcss/tailwind + await buildFeServer({ + verbose, }) } else { await execa( @@ -129,25 +124,6 @@ export const handler = async ({ }, ].filter(Boolean) - const triggerPrerender = async () => { - console.log('Starting prerendering...') - if (prerenderRoutes.length === 0) { - console.log( - `You have not marked any routes to "prerender" in your ${terminalLink( - 'Routes', - 'file://' + rwjsPaths.web.routes - )}.` - ) - } - // Running a separate process here, otherwise it wouldn't pick up the - // generated Prisma Client due to require module caching - await execa('yarn rw prerender', { - stdio: 'inherit', - shell: true, - cwd: rwjsPaths.web.base, - }) - } - const jobs = new Listr(tasks, { renderer: verbose && 'verbose', }) @@ -156,10 +132,11 @@ export const handler = async ({ await timedTelemetry(process.argv, { type: 'build' }, async () => { await jobs.run() - if (side.includes('web') && prerender) { - // This step is outside Listr so that it prints clearer, complete messages - await triggerPrerender() - } + // Removing prerender for streaming setup + // if (side.includes('web') && prerender) { + // // This step is outside Listr so that it prints clearer, complete messages + // await triggerPrerender() + // } }) } catch (e) { console.log(c.error(e.message)) diff --git a/packages/cli/src/commands/devHandler.js b/packages/cli/src/commands/devHandler.js index 11c422061835..8c13bcc0a0c1 100644 --- a/packages/cli/src/commands/devHandler.js +++ b/packages/cli/src/commands/devHandler.js @@ -21,12 +21,11 @@ export const handler = async ({ watchNodeModules = process.env.RWJS_WATCH_NODE_MODULES === '1', apiDebugPort, }) => { - const redwoodProjectPaths = getPaths() - const redwoodProjectConfig = getConfig() + const rwjsPaths = getPaths() // Starting values of ports from config (redwood.toml) - let apiPreferredPort = parseInt(redwoodProjectConfig.api.port) - let webPreferredPort = parseInt(redwoodProjectConfig.web.port) + let apiPreferredPort = parseInt(getConfig().api.port) + let webPreferredPort = parseInt(getConfig().web.port) // Assume we can have the ports we want let apiAvailablePort = apiPreferredPort @@ -51,8 +50,9 @@ export const handler = async ({ ...forward.matchAll(/\-\-port(\=|\s)(?[^\s]*)/g), ] if (forwardedPortMatches.length) { - webPreferredPort = parseInt(forwardedPortMatches.pop().groups.port) + webPreferredPort = forwardedPortMatches.pop().groups.port } + webAvailablePort = await getFreePort(webPreferredPort, [ apiPreferredPort, apiAvailablePort, @@ -85,7 +85,7 @@ export const handler = async ({ await generatePrismaClient({ verbose: false, force: false, - schema: redwoodProjectPaths.api.dbSchema, + schema: rwjsPaths.api.dbSchema, }) } catch (e) { errorTelemetry( @@ -128,7 +128,7 @@ export const handler = async ({ return `--debug-port ${defaultApiDebugPort}` } - const apiDebugPortInToml = redwoodProjectConfig.api.debugPort + const apiDebugPortInToml = getConfig().api.debugPort if (apiDebugPortInToml) { return `--debug-port ${apiDebugPortInToml}` } @@ -140,47 +140,26 @@ export const handler = async ({ const redwoodConfigPath = getConfigPath() const webCommand = - redwoodProjectConfig.web.bundler === 'vite' // @NOTE: can't use enums, not TS - ? `yarn cross-env NODE_ENV=development rw-vite-dev ${forward}` + getConfig().web.bundler === 'vite' // @NOTE: can't use enums, not TS + ? `yarn cross-env NODE_ENV=development rw-dev-fe` : `yarn cross-env NODE_ENV=development RWJS_WATCH_NODE_MODULES=${ watchNodeModules ? '1' : '' } webpack serve --config "${webpackDevConfig}" ${forward}` - const apiCommand = [ - 'yarn', - 'cross-env', - 'NODE_ENV=development', - 'NODE_OPTIONS=--enable-source-maps', - 'yarn', - 'nodemon', - '--quiet', - `--watch "${redwoodConfigPath}"`, - '--exec', - `"${[ - 'yarn', - 'rw-api-server-watch', - `--port ${apiAvailablePort}`, - `--host '::'`, - getApiDebugFlag(), - '|', - 'rw-log-formatter', - ].join(' ')}"`, - ].join(' ') - /** @type {Record} */ const jobs = { api: { name: 'api', - command: apiCommand, + command: `yarn cross-env NODE_ENV=development NODE_OPTIONS=--enable-source-maps yarn nodemon --quiet --watch "${redwoodConfigPath}" --exec "yarn rw-api-server-watch --port ${apiAvailablePort} ${getApiDebugFlag()} | rw-log-formatter"`, prefixColor: 'cyan', - runWhen: () => fs.existsSync(redwoodProjectPaths.api.src), + runWhen: () => fs.existsSync(rwjsPaths.api.src), }, web: { name: 'web', command: webCommand, prefixColor: 'blue', - cwd: redwoodProjectPaths.web.base, - runWhen: () => fs.existsSync(redwoodProjectPaths.web.src), + cwd: rwjsPaths.web.base, + runWhen: () => fs.existsSync(rwjsPaths.web.src), }, gen: { name: 'gen', diff --git a/packages/cli/src/commands/generate/page/templates/page.tsx.template b/packages/cli/src/commands/generate/page/templates/page.tsx.template index fc16315a0a96..1b1b3ff61177 100644 --- a/packages/cli/src/commands/generate/page/templates/page.tsx.template +++ b/packages/cli/src/commands/generate/page/templates/page.tsx.template @@ -1,5 +1,4 @@ import { Link, routes } from '@redwoodjs/router' -import { MetaTags } from '@redwoodjs/web' <% if (paramName !== '') { %> type ${pascalName}PageProps = { ${paramName}: ${paramType} @@ -8,8 +7,6 @@ type ${pascalName}PageProps = { const ${pascalName}Page = (<%- paramName === '' ? '' : `${propParam}: ${pascalName}PageProps` %>) => { return ( <> - -

${pascalName}Page

Find me in ${outputPath} diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index 6dc843f392b3..1d045bd99375 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -1,121 +1,53 @@ import fs from 'fs' import path from 'path' -import chalk from 'chalk' -import execa from 'execa' import terminalLink from 'terminal-link' -import { getPaths, getConfig } from '../lib' +import { getPaths } from '../lib' import c from '../lib/colors' export const command = 'serve [side]' export const description = 'Run server for api or web in production' -export async function builder(yargs) { - const redwoodProjectPaths = getPaths() - const redwoodProjectConfig = getConfig() +const streamServerErrorHandler = () => { + console.error('โš ๏ธ Experimental Render Mode ~ Cannot serve the web side โš ๏ธ') + console.log('~'.repeat(50)) + console.log() + console.log() + console.log('You can run the new frontend server with: `yarn rw-serve-fe`') + console.log('You can run the api server with: yarn rw serve api') + console.log() + console.log() + console.log('~'.repeat(50)) + + throw new Error( + 'You will need to run the FE server and API server separately.' + ) +} + +export const builder = async (yargs) => { + const { apiCliOptions, webCliOptions, commonOptions, apiServerHandler } = + await import('@redwoodjs/api-server') yargs .usage('usage: $0 ') .command({ command: '$0', - description: 'Run both api and web servers. Uses the web port and host', - builder: (yargs) => - yargs.options({ - port: { - default: redwoodProjectConfig.web.port, - type: 'number', - alias: 'p', - }, - host: { - default: redwoodProjectConfig.web.host, - type: 'string', - }, - socket: { type: 'string' }, - }), - handler: async (argv) => { - const serverFilePath = path.join( - redwoodProjectPaths.api.dist, - 'server.js' - ) - - if (fs.existsSync(serverFilePath)) { - console.log( - [ - separator, - `๐Ÿงช ${chalk.green('Experimental Feature')} ๐Ÿงช`, - separator, - 'Using the experimental API server file at api/dist/server.js', - separator, - ].join('\n') - ) - - await execa('yarn', ['node', path.join('dist', 'server.js')], { - cwd: redwoodProjectPaths.api.base, - stdio: 'inherit', - shell: true, - }) - - return - } - - const { bothServerHandler } = await import('./serveHandler.js') - await bothServerHandler(argv) - }, + descriptions: 'Run both api and web servers', + handler: streamServerErrorHandler, + builder: (yargs) => yargs.options(commonOptions), }) .command({ command: 'api', - description: 'Start server for serving only the api', - builder: (yargs) => - yargs.options({ - port: { - default: redwoodProjectConfig.api.port, - type: 'number', - alias: 'p', - }, - host: { - default: redwoodProjectConfig.api.host, - type: 'string', - }, - socket: { type: 'string' }, - apiRootPath: { - alias: ['api-root-path', 'rootPath', 'root-path'], - default: '/', - type: 'string', - desc: 'Root path where your api functions are served', - coerce: coerceRootPath, - }, - }), - handler: async (argv) => { - const { apiServerHandler } = await import('./serveHandler.js') - await apiServerHandler(argv) - }, + description: 'start server for serving only the api', + handler: apiServerHandler, + builder: (yargs) => yargs.options(apiCliOptions), }) .command({ command: 'web', - description: 'Start server for serving only the web side', - builder: (yargs) => - yargs.options({ - port: { - default: redwoodProjectConfig.web.port, - type: 'number', - alias: 'p', - }, - host: { - default: redwoodProjectConfig.web.host, - type: 'string', - }, - socket: { type: 'string' }, - apiHost: { - alias: 'api-host', - type: 'string', - desc: 'Forward requests from the apiUrl, defined in redwood.toml to this host', - }, - }), - handler: async (argv) => { - const { webServerHandler } = await import('./serveHandler.js') - await webServerHandler(argv) - }, + description: 'start server for serving only the web side', + handler: streamServerErrorHandler, + builder: (yargs) => yargs.options(webCliOptions), }) .middleware((argv) => { // Make sure the relevant side has been built, before serving @@ -123,7 +55,7 @@ export async function builder(yargs) { if ( positionalArgs.includes('web') && - !fs.existsSync(path.join(redwoodProjectPaths.web.dist), 'index.html') + !fs.existsSync(path.join(getPaths().web.dist), 'index.html') ) { console.error( c.error( @@ -135,7 +67,7 @@ export async function builder(yargs) { if ( positionalArgs.includes('api') && - !fs.existsSync(path.join(redwoodProjectPaths.api.dist)) + !fs.existsSync(path.join(getPaths().api.dist)) ) { console.error( c.error( @@ -148,8 +80,8 @@ export async function builder(yargs) { if ( // serve both positionalArgs.length === 1 && - (!fs.existsSync(path.join(redwoodProjectPaths.api.dist)) || - !fs.existsSync(path.join(redwoodProjectPaths.web.dist), 'index.html')) + (!fs.existsSync(path.join(getPaths().api.dist)) || + !fs.existsSync(path.join(getPaths().web.dist), 'index.html')) ) { console.error( c.error( @@ -171,18 +103,3 @@ export async function builder(yargs) { )}` ) } - -const separator = chalk.hex('#ff845e')( - '------------------------------------------------------------------' -) - -// We'll clean this up later, but for now note that this function is -// duplicated between this package and @redwoodjs/fastify -// to avoid importing @redwoodjs/fastify when the CLI starts. -export function coerceRootPath(path) { - // Make sure that we create a root path that starts and ends with a slash (/) - const prefix = path.charAt(0) !== '/' ? '/' : '' - const suffix = path.charAt(path.length - 1) !== '/' ? '/' : '' - - return `${prefix}${path}${suffix}` -} diff --git a/packages/core/package.json b/packages/core/package.json index 6754b626ba66..205e201ed5a2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -17,9 +17,12 @@ "rimraf": "./dist/bins/rimraf.js", "rw": "./dist/bins/redwood.js", "rw-api-server-watch": "./dist/bins/rw-api-server-watch.js", + "rw-dev-fe": "./dist/bins/rw-dev-fe.js", "rw-gen": "./dist/bins/rw-gen.js", "rw-gen-watch": "./dist/bins/rw-gen-watch.js", "rw-log-formatter": "./dist/bins/rw-log-formatter.js", + "rw-serve-api": "./dist/bins/rw-serve-api.js", + "rw-serve-fe": "./dist/bins/rw-serve-fe.js", "rwfw": "./dist/bins/rwfw.js" }, "files": [ diff --git a/packages/core/src/bins/rw-dev-fe.ts b/packages/core/src/bins/rw-dev-fe.ts new file mode 100644 index 000000000000..e25b584ad397 --- /dev/null +++ b/packages/core/src/bins/rw-dev-fe.ts @@ -0,0 +1,10 @@ +#!/usr/bin/env node +import { createRequire } from 'module' + +const requireFromRwVite = createRequire( + require.resolve('@redwoodjs/vite/package.json') +) + +const bins = requireFromRwVite('./package.json')['bin'] + +requireFromRwVite(bins['rw-dev-fe']) diff --git a/packages/core/src/bins/rw-serve-api.ts b/packages/core/src/bins/rw-serve-api.ts new file mode 100644 index 000000000000..4156ecaa86f7 --- /dev/null +++ b/packages/core/src/bins/rw-serve-api.ts @@ -0,0 +1,10 @@ +#!/usr/bin/env node +import { createRequire } from 'module' + +const requireFromApiServer = createRequire( + require.resolve('@redwoodjs/api-server/package.json') +) + +const bins = requireFromApiServer('./package.json')['bin'] + +requireFromApiServer(bins['rw-serve-api']) diff --git a/packages/core/src/bins/rw-serve-fe.ts b/packages/core/src/bins/rw-serve-fe.ts new file mode 100644 index 000000000000..a31988ae98bf --- /dev/null +++ b/packages/core/src/bins/rw-serve-fe.ts @@ -0,0 +1,10 @@ +#!/usr/bin/env node +import { createRequire } from 'module' + +const requireFromRwVite = createRequire( + require.resolve('@redwoodjs/vite/package.json') +) + +const bins = requireFromRwVite('./package.json')['bin'] + +requireFromRwVite(bins['rw-serve-fe']) diff --git a/packages/internal/src/build/babel/api.ts b/packages/internal/src/build/babel/api.ts index 6e1ff3900929..2a9a8aca648e 100644 --- a/packages/internal/src/build/babel/api.ts +++ b/packages/internal/src/build/babel/api.ts @@ -228,3 +228,27 @@ export const prebuildApiFile = ( }) return result } + +// @TODO: I changed the prebuildApiFile function in https://github.com/redwoodjs/redwood/pull/7672/files +// but we had to revert. For this branch temporarily, I'm going to add a new function +// This is used in building routeHooks +export const transformWithBabel = ( + srcPath: string, + plugins: TransformOptions['plugins'] +) => { + const code = fs.readFileSync(srcPath, 'utf-8') + const defaultOptions = getApiSideDefaultBabelConfig() + + const result = transform(code, { + ...defaultOptions, + cwd: getPaths().api.base, + filename: srcPath, + // we need inline sourcemaps at this level + // because this file will eventually be fed to esbuild + // when esbuild finds an inline sourcemap, it tries to "combine" it + // so the final sourcemap (the one that esbuild generates) combines both mappings + sourceMaps: 'inline', + plugins, + }) + return result +} diff --git a/packages/internal/src/build/babel/common.ts b/packages/internal/src/build/babel/common.ts index 7c6d50f65c76..b8322e7e7f22 100644 --- a/packages/internal/src/build/babel/common.ts +++ b/packages/internal/src/build/babel/common.ts @@ -6,6 +6,10 @@ import { parseConfigFileTextToJson } from 'typescript' import { getPaths } from '@redwoodjs/project-config' +import { getPaths } from '@redwoodjs/project-config' + +import { getWebSideBabelPlugins } from './web' + const pkgJson = require('../../../package.json') export interface RegisterHookOptions { @@ -60,12 +64,45 @@ if (!RUNTIME_CORE_JS_VERSION) { export const getCommonPlugins = () => { return [ - ['@babel/plugin-proposal-class-properties', { loose: true }], + [ + '@babel/plugin-proposal-class-properties', + { loose: true }, + 'rw-class-properties', + ], // Note: The private method loose mode configuration setting must be the // same as @babel/plugin-proposal class-properties. // (https://babeljs.io/docs/en/babel-plugin-proposal-private-methods#loose) - ['@babel/plugin-proposal-private-methods', { loose: true }], - ['@babel/plugin-proposal-private-property-in-object', { loose: true }], + [ + '@babel/plugin-proposal-private-methods', + { loose: true }, + 'rw-private-methods', + ], + [ + '@babel/plugin-proposal-private-property-in-object', + { loose: true }, + 'rw-private-prop-in-object', + ], + ] +} + +// @TODO double check this, think about it more carefully please! +export const getRouteHookBabelPlugins = () => { + return [ + ...getWebSideBabelPlugins({ + forVite: true, + }), + [ + 'babel-plugin-module-resolver', + { + alias: { + 'api/src': './src', + }, + root: [getPaths().api.base], + cwd: 'packagejson', + loglevel: 'silent', // to silence the unnecessary warnings + }, + 'rwjs-api-module-resolver', + ], ] } diff --git a/packages/internal/src/build/babel/web.ts b/packages/internal/src/build/babel/web.ts index 6bafbee3457e..511f5a847526 100644 --- a/packages/internal/src/build/babel/web.ts +++ b/packages/internal/src/build/babel/web.ts @@ -37,6 +37,7 @@ export const getWebSideBabelPlugins = ( forJest ? rwjsPaths.web.src : './src', // adds the paths from [ts|js]config.json to the module resolver ...getPathsFromConfig(tsConfigs.web), + $api: rwjsPaths.api.base, }, root: [rwjsPaths.web.base], cwd: 'packagejson', diff --git a/packages/internal/src/files.ts b/packages/internal/src/files.ts index e88a136a157d..8a7a0c1ecb94 100644 --- a/packages/internal/src/files.ts +++ b/packages/internal/src/files.ts @@ -96,6 +96,13 @@ export const findApiDistFunctions = (cwd: string = getPaths().api.base) => { }) } +export const findRouteHooksSrc = (cwd: string = getPaths().web.src) => { + return fg.sync('**/*.routeHooks.{js,ts,tsx,jsx}', { + absolute: true, + cwd, + }) +} + export const findPrerenderedHtml = (cwd = getPaths().web.dist) => fg.sync('**/*.html', { cwd, ignore: ['200.html', '404.html'] }) diff --git a/packages/internal/src/generate/templates/api-globImports.d.ts.template b/packages/internal/src/generate/templates/api-globImports.d.ts.template index 51e248fd5f82..a843cb4cff47 100644 --- a/packages/internal/src/generate/templates/api-globImports.d.ts.template +++ b/packages/internal/src/generate/templates/api-globImports.d.ts.template @@ -1,4 +1,8 @@ declare module 'src/services/**/*.{js,ts}' declare module 'src/directives/**/*.{js,ts}' declare module 'src/graphql/**/*.sdl.{js,ts}' -declare module 'src/subscriptions/**/*.{js,ts}' + + +declare module 'api/src/services/**/*.{js,ts}' +declare module 'api/src/directives/**/*.{js,ts}' +declare module 'api/src/graphql/**/*.sdl.{js,ts}' diff --git a/packages/internal/src/routes.ts b/packages/internal/src/routes.ts index 8fd37f6df17c..363680d11916 100644 --- a/packages/internal/src/routes.ts +++ b/packages/internal/src/routes.ts @@ -1,6 +1,9 @@ +import path from 'path' + import chalk from 'chalk' -import { getPaths } from '@redwoodjs/project-config' +import { getPaths, getRouteHookForPage } from '@redwoodjs/project-config' +import { getRouteRegexAndParams } from '@redwoodjs/router' // Circular dependency when trying to use the standard import const { getProject } = require('@redwoodjs/structure/dist/index') @@ -63,3 +66,48 @@ export function warningForDuplicateRoutes() { } return message.trimEnd() } + +export interface RouteSpec { + name: string + path: string + hasParams: boolean + id: string + isNotFound: boolean + filePath: string | undefined + relativeFilePath: string | undefined + routeHooks: string | undefined | null + matchRegexString: string | null + redirect: { to: string; permanent: boolean } | null + renderMode: 'stream' | 'html' +} + +export const getProjectRoutes = (): RouteSpec[] => { + const rwProject = getProject(getPaths().base) + const routes = rwProject.getRouter().routes + + return routes.map((route: any) => { + const { matchRegexString, routeParams } = route.isNotFound + ? { matchRegexString: null, routeParams: null } + : getRouteRegexAndParams(route.path) + + return { + name: route.isNotFound ? 'NotFoundPage' : route.name, + path: route.isNotFound ? 'notfound' : route.path, + hasParams: route.hasParameters, + id: route.id, + isNotFound: route.isNotFound, + filePath: route.page?.filePath, + relativeFilePath: route.page?.filePath + ? path.relative(getPaths().web.src, route.page?.filePath) + : undefined, + routeHooks: getRouteHookForPage(route.page?.filePath), + renderMode: route.renderMode, + matchRegexString: matchRegexString, + paramNames: routeParams, + // @TODO deal with permanent/temp later + redirect: route.redirect + ? { to: route.redirect, permanent: false } + : null, + } + }) +} diff --git a/packages/project-config/src/paths.ts b/packages/project-config/src/paths.ts index a3a571ed85d6..82ca7cc25173 100644 --- a/packages/project-config/src/paths.ts +++ b/packages/project-config/src/paths.ts @@ -39,11 +39,15 @@ export interface WebPaths { webpack: string viteConfig: string | null // because vite is opt-in only entryClient: string | null + entryServer: string | null postcss: string storybookConfig: string storybookPreviewConfig: string storybookManagerConfig: string dist: string + distServer: string + distRouteHooks: string + routeManifest: string types: string } @@ -100,6 +104,7 @@ const PATH_WEB_DIR_CONFIG = 'web/config' const PATH_WEB_DIR_CONFIG_WEBPACK = 'web/config/webpack.config.js' const PATH_WEB_DIR_CONFIG_VITE = 'web/vite.config' // .js,.ts const PATH_WEB_DIR_ENTRY_CLIENT = 'web/src/entry-client' // .jsx,.tsx +const PATH_WEB_DIR_ENTRY_SERVER = 'web/src/entry-server' // .jsx,.tsx const PATH_WEB_DIR_CONFIG_POSTCSS = 'web/config/postcss.config.js' const PATH_WEB_DIR_CONFIG_STORYBOOK_CONFIG = 'web/config/storybook.config.js' @@ -107,6 +112,9 @@ const PATH_WEB_DIR_CONFIG_STORYBOOK_PREVIEW = 'web/config/storybook.preview.js' const PATH_WEB_DIR_CONFIG_STORYBOOK_MANAGER = 'web/config/storybook.manager.js' const PATH_WEB_DIR_DIST = 'web/dist' +const PATH_WEB_DIR_DIST_SERVER = 'web/dist/server' +const PATH_WEB_DIR_DIST_SERVER_ROUTEHOOKS = 'web/dist/server/routeHooks' +const PATH_WEB_DIR_ROUTE_MANIFEST = 'web/dist/server/route-manifest.json' /** * The Redwood config file is used as an anchor for the base directory of a project. @@ -206,8 +214,12 @@ export const getPaths = (BASE_DIR: string = getBaseDir()): Paths => { PATH_WEB_DIR_CONFIG_STORYBOOK_MANAGER ), dist: path.join(BASE_DIR, PATH_WEB_DIR_DIST), + distServer: path.join(BASE_DIR, PATH_WEB_DIR_DIST_SERVER), + distRouteHooks: path.join(BASE_DIR, PATH_WEB_DIR_DIST_SERVER_ROUTEHOOKS), + routeManifest: path.join(BASE_DIR, PATH_WEB_DIR_ROUTE_MANIFEST), types: path.join(BASE_DIR, 'web/types'), entryClient: resolveFile(path.join(BASE_DIR, PATH_WEB_DIR_ENTRY_CLIENT)), // new vite/stream entry point for client + entryServer: resolveFile(path.join(BASE_DIR, PATH_WEB_DIR_ENTRY_SERVER)), }, } @@ -217,6 +229,32 @@ export const getPaths = (BASE_DIR: string = getBaseDir()): Paths => { return paths } +/** + * Returns the route hook for the supplied page path. + * Note that the page name doesn't have to match + * + * @param pagePath + * @returns string + */ +export const getRouteHookForPage = (pagePath: string | undefined | null) => { + if (!pagePath) { + return null + } + + // We just use fg, so if they make typos in the routeHook file name, + // it's all good, we'll still find it + return fg + .sync('*.routeHooks.{js,ts,tsx,jsx}', { + absolute: true, + cwd: path.dirname(pagePath), // the page's folder + }) + .at(0) +} + +export const getAppRouteHook = () => { + return resolveFile(path.join(getPaths().web.src, 'App.routeHooks')) +} + /** * Process the pages directory and return information useful for automated imports. * diff --git a/packages/router/src/active-route-loader.tsx b/packages/router/src/active-route-loader.tsx index ae3e59dc4851..c8ab61607ad6 100644 --- a/packages/router/src/active-route-loader.tsx +++ b/packages/router/src/active-route-loader.tsx @@ -12,15 +12,19 @@ interface Props { children?: React.ReactNode } -let isPrerendered = false +const isPrerendered = false -if (typeof window !== 'undefined') { - const redwoodAppElement = document.getElementById('redwood-app') +// @MARK @TODO +// SSR and streaming changes how we mount the React app (we render the whole page, including head and body) +// This logic is no longer valid and needs to be rethought - if (redwoodAppElement && redwoodAppElement.children.length > 0) { - isPrerendered = true - } -} +// if (typeof window !== 'undefined') { +// const redwoodAppElement = document.getElementById('redwood-app') + +// if (redwoodAppElement && redwoodAppElement.children.length > 0) { +// isPrerendered = true +// } +// } let firstLoad = true diff --git a/packages/structure/src/model/RWRoute.ts b/packages/structure/src/model/RWRoute.ts index 289cf5bf8535..f7e684fbe466 100644 --- a/packages/structure/src/model/RWRoute.ts +++ b/packages/structure/src/model/RWRoute.ts @@ -144,6 +144,10 @@ export class RWRoute extends BaseNode { return this.getBoolAttr('prerender') } + @lazy() get renderMode(): string | undefined { + return this.getStringAttr('renderMode') || 'stream' + } + @lazy() get path_literal_node() { const a = this.jsxNode.getAttribute('path') if (!a) { @@ -162,6 +166,10 @@ export class RWRoute extends BaseNode { return typeof this.jsxNode.getAttribute('notfound') !== 'undefined' } + @lazy() get redirect() { + return this.getStringAttr('redirect') + } + *diagnostics() { if (this.page_identifier && !this.page) { // normally this would be caught by TypeScript diff --git a/packages/vite/.babelrc.js b/packages/vite/.babelrc.js index 3b2c815712d9..ecc3f819986d 100644 --- a/packages/vite/.babelrc.js +++ b/packages/vite/.babelrc.js @@ -1 +1,4 @@ -module.exports = { extends: '../../babel.config.js' } +module.exports = { + extends: '../../babel.config.js', + plugins: ['@babel/plugin-syntax-import-assertions'], +} diff --git a/packages/vite/ambient.d.ts b/packages/vite/ambient.d.ts new file mode 100644 index 000000000000..3814acb97c3d --- /dev/null +++ b/packages/vite/ambient.d.ts @@ -0,0 +1,15 @@ +/* eslint-disable no-var */ + +declare global { + var RWJS_ENV: { + RWJS_API_GRAPHQL_URL?: string + /** URL or absolute path to serverless functions */ + RWJS_API_URL?: string + + __REDWOOD__APP_TITLE?: string + } + + var __REDWOOD__PRERENDER_PAGES: any +} + +export {} diff --git a/packages/vite/inject/reactRefresh.js b/packages/vite/inject/reactRefresh.js new file mode 100644 index 000000000000..b411150d2f00 --- /dev/null +++ b/packages/vite/inject/reactRefresh.js @@ -0,0 +1,7 @@ +/* eslint-disable no-undef */ + +import RefreshRuntime from '/@react-refresh' +RefreshRuntime.injectIntoGlobalHook(window) +window.$RefreshReg$ = () => {} +window.$RefreshSig$ = () => (type) => type +window.__vite_plugin_react_preamble_installed__ = true diff --git a/packages/vite/package.json b/packages/vite/package.json index a488869af15f..739769ecd9d0 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -9,10 +9,13 @@ }, "license": "MIT", "files": [ - "dist" + "dist", + "inject" ], "main": "dist/index.js", "bin": { + "rw-dev-fe": "./dist/devFeServer.js", + "rw-serve-fe": "./dist/runFeServer.js", "rw-vite-build": "./bins/rw-vite-build.mjs", "rw-vite-dev": "./bins/rw-vite-dev.mjs", "vite": "./bins/vite.mjs" @@ -32,12 +35,18 @@ "@vitejs/plugin-react": "4.0.0", "buffer": "6.0.3", "core-js": "3.30.2", + "dotenv-defaults": "5.0.2", + "express": "4.18.2", + "http-proxy-middleware": "2.0.6", + "isbot": "3.6.8", "vite": "4.3.9", "vite-plugin-commonjs": "0.6.2", "vite-plugin-environment": "1.1.3" }, "devDependencies": { "@babel/cli": "7.21.5", + "@babel/plugin-syntax-import-assertions": "7.20.0", + "@types/express": "4", "glob": "10.2.7", "jest": "29.5.0", "typescript": "5.1.3" diff --git a/packages/vite/src/buildFeServer.ts b/packages/vite/src/buildFeServer.ts new file mode 100644 index 000000000000..9193e5bf9c76 --- /dev/null +++ b/packages/vite/src/buildFeServer.ts @@ -0,0 +1,142 @@ +import fs from 'fs/promises' +import path from 'path' + +import { build as esbuildBuild, PluginBuild } from 'esbuild' +import type { ViteManifest } from 'vite' + +import { getRouteHookBabelPlugins } from '@redwoodjs/internal' +import { transformWithBabel } from '@redwoodjs/internal/dist/build/babel/api' +import { buildWeb } from '@redwoodjs/internal/dist/build/web' +import { findRouteHooksSrc } from '@redwoodjs/internal/dist/files' +import { getProjectRoutes } from '@redwoodjs/internal/dist/routes' +import { getAppRouteHook, getPaths } from '@redwoodjs/project-config' + +import { RWRouteManifest } from './types' + +interface BuildOptions { + verbose?: boolean +} + +export const buildFeServer = async ({ verbose }: BuildOptions) => { + const rwPaths = getPaths() + const viteConfig = rwPaths.web.viteConfig + + if (!viteConfig) { + throw new Error( + 'Vite config not found. You need to setup your project with Vite using `yarn rw setup vite`' + ) + } + + if (!rwPaths.web.entryServer || !rwPaths.web.entryClient) { + throw new Error( + 'Vite entry points not found. Please check that your project has an entry-client.{jsx,tsx} and entry-server.{jsx,tsx} file in the web/src directory.' + ) + } + + // Step 1A: Generate the client bundle + await buildWeb({ verbose }) + + // @NOTE: Using dynamic import, because vite is still opt-in + const { build } = await import('vite') + + // Step 1B: Generate the server output + await build({ + configFile: viteConfig, + build: { + // Because we configure the root to be web/src, we need to go up one level + outDir: rwPaths.web.distServer, + ssr: rwPaths.web.entryServer, + }, + envFile: false, + logLevel: verbose ? 'info' : 'warn', + }) + + const allRouteHooks = findRouteHooksSrc() + + const runRwBabelTransformsPlugin = { + name: 'rw-esbuild-babel-transform', + setup(build: PluginBuild) { + build.onLoad({ filter: /\.(js|ts|tsx|jsx)$/ }, async (args) => { + // Remove RedwoodJS "magic" from a user's code leaving JavaScript behind. + // @TODO: We need the new transformWithBabel function in https://github.com/redwoodjs/redwood/pull/7672/files + const transformedCode = transformWithBabel(args.path, [ + ...getRouteHookBabelPlugins(), + ]) + + if (transformedCode?.code) { + return { + contents: transformedCode.code, + loader: 'js', + } + } + + throw new Error(`Could not transform file: ${args.path}`) + }) + }, + } + + await esbuildBuild({ + absWorkingDir: getPaths().web.base, + entryPoints: allRouteHooks, + platform: 'node', + target: 'node16', + // @MARK Disable splitting and esm, because Redwood web modules dont support esm yet + // outExtension: { '.js': '.mjs' }, + // format: 'esm', + // splitting: true, + bundle: true, + plugins: [runRwBabelTransformsPlugin], + packages: 'external', + logLevel: verbose ? 'info' : 'error', + outdir: rwPaths.web.distRouteHooks, + }) + + // Step 3: Generate route-manifest.json + const clientBuildManifest: ViteManifest = await import( + path.join(getPaths().web.dist, 'build-manifest.json') + ) + + const routesList = getProjectRoutes() + + const routeManifest = routesList.reduce((acc, route) => { + acc[route.path] = { + name: route.name, + bundle: route.relativeFilePath + ? clientBuildManifest[route.relativeFilePath].file + : null, + matchRegexString: route.matchRegexString, + // @NOTE this is the path definition, not the actual path + pathDefinition: route.path, + hasParams: route.hasParams, + routeHooks: FIXME_constructRouteHookPath(route.routeHooks), + redirect: route.redirect + ? { + to: route.redirect?.to, + permanent: false, + } + : null, + renderMode: route.renderMode, + } + return acc + }, {}) + + await fs.writeFile(rwPaths.web.routeManifest, JSON.stringify(routeManifest)) +} + +// @TODO @MARK Hacky work around because when you don't have a App.routeHook, esbuild doesn't create +// the pages folder in the dist/server/routeHooks directory. +// @MARK need to change to .mjs here if we use esm +const FIXME_constructRouteHookPath = (rhSrcPath: string | null | undefined) => { + const rwPaths = getPaths() + if (!rhSrcPath) { + return null + } + + if (getAppRouteHook()) { + return path.relative(rwPaths.web.src, rhSrcPath).replace('.ts', '.js') + } else { + return path + .relative(path.join(rwPaths.web.src, 'pages'), rhSrcPath) + .replace('.ts', '.js') + } +} diff --git a/packages/vite/src/devFeServer.ts b/packages/vite/src/devFeServer.ts new file mode 100644 index 000000000000..9ff03d97e391 --- /dev/null +++ b/packages/vite/src/devFeServer.ts @@ -0,0 +1,207 @@ +import path from 'path' + +import express from 'express' +import { renderToPipeableStream } from 'react-dom/server' +import { createServer as createViteServer } from 'vite' + +import { getProjectRoutes } from '@redwoodjs/internal/dist/routes' +import { getAppRouteHook, getConfig, getPaths } from '@redwoodjs/project-config' +import { matchPath } from '@redwoodjs/router' +import type { TagDescriptor } from '@redwoodjs/web' + +import { triggerRouteHooks } from './triggerRouteHooks' +import { stripQueryStringAndHashFromPath } from './utils' + +// These values are defined in the vite.config.ts +globalThis.RWJS_ENV = {} + +// @MARK, @TODO Just so it doesn't error out. Not sure how to handle this. +globalThis.__REDWOOD__PRERENDER_PAGES = {} + +async function createServer() { + const app = express() + const rwPaths = getPaths() + + // @MARK: Vite is still experimental, and opt-in + if (!rwPaths.web.viteConfig) { + throw new Error( + 'Vite config not found. You need to setup your project with Vite using `yarn rw setup vite`' + ) + } + + // Create Vite server in middleware mode and configure the app type as + // 'custom', disabling Vite's own HTML serving logic so parent server + // can take control + const vite = await createViteServer({ + configFile: rwPaths.web.viteConfig, + server: { middlewareMode: true }, + logLevel: 'info', + clearScreen: false, + appType: 'custom', + }) + + // use vite's connect instance as middleware + // if you use your own express router (express.Router()), you should use router.use + app.use(vite.middlewares) + + app.use('*', async (req, res, next) => { + const currentPathName = stripQueryStringAndHashFromPath(req.originalUrl) + + try { + const routes = getProjectRoutes() + + // Do a simple match with regex, don't bother parsing params yet + const currentRoute = routes.find((route) => { + if (!route.matchRegexString) { + // This is the 404/NotFoundPage case + return false + } + + const matches = [ + ...currentPathName.matchAll(new RegExp(route.matchRegexString, 'g')), + ] + + return matches.length > 0 + }) + + let serverData = {} + let metaTags: TagDescriptor[] = [] + + if (currentRoute?.redirect) { + return res.redirect(currentRoute.redirect.to) + } + + if (currentRoute) { + // A. Trigger app route hook + const rootRouteHookOutput = await runDevRouteHooks(getAppRouteHook()) + + // B. Trigger current route RH + const currentRouteHookOutput = await runDevRouteHooks( + currentRoute.routeHooks, + currentRoute.hasParams + ? matchPath(currentRoute.path, currentPathName).params + : undefined, + rootRouteHookOutput + ) + + // Compose the appRH output and RH output + serverData = { + ...rootRouteHookOutput.serverData, + ...currentRouteHookOutput.serverData, + } + + metaTags = [...rootRouteHookOutput.meta, ...currentRouteHookOutput.meta] + } + + if (!currentRoute) { + // @TODO do something + } + + if (!rwPaths.web.entryServer || !rwPaths.web.entryClient) { + throw new Error( + 'Vite entry points not found. Please check that your project has an entry-client.{jsx,tsx} and entry-server.{jsx,tsx} file in the web/src directory.' + ) + } + + // 3. Load the server entry. vite.ssrLoadModule automatically transforms + // your ESM source code to be usable in Node.js! There is no bundling + // required, and provides efficient invalidation similar to HMR. + const { serverEntry } = await vite.ssrLoadModule(rwPaths.web.entryServer) + + // Serialize route context so it can be passed to the client entry + const serialisedRouteContext = JSON.stringify(serverData) + + // @TODO CSS is handled by Vite in dev mode, we don't need to worry about it in dev + // but..... it causes a flash of unstyled content. For now I'm just injecting index css here + const FIXME_HardcodedIndexCss = ['index.css'] + + const bootstrapModules = [ + path.join(__dirname, '../inject', 'reactRefresh.js'), + ] + + const pageWithJs = currentRoute?.renderMode !== 'html' + + if (pageWithJs) { + bootstrapModules.push(rwPaths.web.entryClient) + } + + const { pipe } = renderToPipeableStream( + serverEntry({ + url: currentPathName, + routeContext: serverData, + css: FIXME_HardcodedIndexCss, + meta: metaTags, + }), + { + bootstrapScriptContent: pageWithJs + ? `window.__loadServerData = function() { return ${serialisedRouteContext} }; window.__assetMap = function() { return ${JSON.stringify( + { + css: FIXME_HardcodedIndexCss, + meta: metaTags, + } + )} }` + : undefined, + bootstrapModules, + onShellReady() { + res.setHeader('content-type', 'text/html; charset=utf-8') + pipe(res) + }, + } + ) + } catch (e) { + // send back a SPA page + // res.status(200).set({ 'Content-Type': 'text/html' }).end(template) + + // If an error is caught, let Vite fix the stack trace so it maps back to + // your actual source code. + vite.ssrFixStacktrace(e as any) + next(e) + } + + // @TODO Refactor this + // WE are repeating code a lot between runFeServer and devFeServer + async function runDevRouteHooks( + routeHookPath: string | null | undefined, + parsedParams?: Record, + appRouteHookOutput?: { meta: TagDescriptor[]; serverData: any } + ) { + if (routeHookPath) { + try { + const routeHooks = await vite.ssrLoadModule(routeHookPath) + + const output = await triggerRouteHooks({ + routeHooks, + req, + parsedParams, + appRouteHookOutput, + }) + + return { + serverData: output.serverData, + meta: output.meta, + } + } catch (e) { + console.error(`Error running route hooks in ${routeHookPath}}`) + console.error(e) + } + } + + // Empty values if error, or no routeHookPath + return { serverData: {}, meta: [] } + } + }) + + const port = getConfig().web.port + console.log(`Started server on http://localhost:${port}`) + return await app.listen(port) +} + +let devApp = createServer() + +process.stdin.on('data', async (data) => { + const str = data.toString().trim().toLowerCase() + if (str === 'rs' || str === 'restart') { + ;(await devApp).close() + devApp = createServer() + } +}) diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts new file mode 100644 index 000000000000..93b9c9c7f75b --- /dev/null +++ b/packages/vite/src/runFeServer.ts @@ -0,0 +1,291 @@ +import path from 'path' + +// @ts-expect-error We will remove dotenv-defaults from this package anyway +import { config as loadDotEnv } from 'dotenv-defaults' +import express from 'express' +import { createProxyMiddleware } from 'http-proxy-middleware' +import isbot from 'isbot' +import { renderToPipeableStream } from 'react-dom/server' +import type { ViteManifest } from 'vite' + +import { getConfig, getPaths } from '@redwoodjs/project-config' +import { matchPath } from '@redwoodjs/router' +import type { TagDescriptor } from '@redwoodjs/web' + +import { triggerRouteHooks } from './triggerRouteHooks' +import { RWRouteManifest } from './types' +import { stripQueryStringAndHashFromPath } from './utils' + +globalThis.RWJS_ENV = {} + +/** + * @MARK @TODO + * We have this server in the vite package only temporarily. + * We will need to decide where to put it, so that rwjs/internal and other heavy dependencies + * can be removed from the final docker image + */ + +// --- @MARK This should be removed once we have re-architected the rw serve command --- +// We need the dotenv, so that prisma knows the DATABASE env var +// Normally the RW cli loads this for us, but we expect this file to be run directly +// without using the CLI. Remember to remove dotenv-defaults dependency from this package +loadDotEnv({ + path: path.join(getPaths().base, '.env'), + defaults: path.join(getPaths().base, '.env.defaults'), + multiline: true, +}) +//------------------------------------------------ + +const checkUaForSeoCrawler = isbot.spawn() +checkUaForSeoCrawler.exclude(['chrome-lighthouse']) + +export async function runFeServer() { + const app = express() + const rwPaths = getPaths() + const rwConfig = getConfig() + + const routeManifest: RWRouteManifest = await import( + rwPaths.web.dist + '/server/route-manifest.json', + { assert: { type: 'json' } } + ) + + const buildManifest: ViteManifest = await import( + rwPaths.web.dist + '/build-manifest.json', + { assert: { type: 'json' } } + ) + + const indexEntry = Object.values(buildManifest).find((manifestItem) => { + return manifestItem.isEntry + }) + + if (!indexEntry) { + throw new Error('Could not find index.html in build manifest') + } + + // ๐Ÿ‘‰ 1. Use static handler for assets + // For CF workers, we'd need an equivalent of this + app.use('/assets', express.static(rwPaths.web.dist + '/assets')) + + // ๐Ÿ‘‰ 2. Proxy the api server + // @TODO we need to be able to specify whether proxying is required or not + // e.g. deploying to Netlify, we don't need to proxy but configure it in Netlify + // Also be careful of differences between v2 and v3 of the server + app.use( + rwConfig.web.apiUrl, + // @WARN! Be careful, between v2 and v3 of http-proxy-middleware + // the syntax has changed https://github.com/chimurai/http-proxy-middleware + createProxyMiddleware({ + changeOrigin: true, + pathRewrite: { + [`^${rwConfig.web.apiUrl}`]: '', // remove base path + }, + // Using 127.0.0.1 to force ipv4. With `localhost` you don't really know + // if it's going to be ipv4 or ipv6 + target: `http://127.0.0.1:${rwConfig.api.port}`, + }) + ) + + // ๐Ÿ‘‰ 3. Handle all other requests with the server entry + // This is where we match the url to the correct route, and render it + // We also call the relevant routeHooks here + app.use('*', async (req, res) => { + const currentPathName = stripQueryStringAndHashFromPath(req.originalUrl) + + try { + const { serverEntry } = await import( + path.join(rwPaths.web.distServer, '/entry-server.js') + ) + + // @MARK should we generate individual express Routes for each Route? + // This would make handling 404s and favicons / public assets etc. easier + const currentRoute = Object.values(routeManifest).find((route) => { + if (!route.matchRegexString) { + // This is the 404/NotFoundPage case + return false + } + + const matches = [ + ...currentPathName.matchAll(new RegExp(route.matchRegexString, 'g')), + ] + return matches.length > 0 + }) + + // Doesn't match any of the defined Routes + // Render 404 page, and send back 404 status + if (!currentRoute) { + // @MARK should we CONST it? + const fourOhFourRoute = routeManifest['notfound'] + + if (!fourOhFourRoute) { + return res.sendStatus(404) + } + + const { pipe } = renderToPipeableStream( + serverEntry({ + url: currentPathName, + routeContext: null, + css: indexEntry.css, + }), + { + bootstrapScriptContent: `window.__assetMap = function() { return ${JSON.stringify( + { css: indexEntry.css } + )} }`, + // @NOTE have to add slash so subpaths still pick up the right file + // Vite is currently producing modules not scripts: https://vitejs.dev/config/build-options.html#build-target + bootstrapModules: [ + '/' + indexEntry.file, + '/' + fourOhFourRoute.bundle, + ], + onShellReady() { + res.setHeader('content-type', 'text/html') + res.status(404) + pipe(res) + }, + } + ) + + return + } + + let serverData = {} + let metaTags: TagDescriptor[] = [] + + if (currentRoute?.redirect) { + // @TODO deal with permanent/temp + // Short-circuit, and return a 301 or 302 + return res.redirect(currentRoute.redirect.to) + } + + if (currentRoute) { + // @TODO hardcoded JS file, watchout if we switch to ESM! + const prodAppRouteHookPath = path.join( + rwPaths.web.distRouteHooks, + 'App.routeHooks.js' + ) + + // A. Trigger app route hook + const rootRouteHookOutput = await runProdRouteHooks( + prodAppRouteHookPath + ) + + const routeHookPath = currentRoute.routeHooks + ? path.join(rwPaths.web.distRouteHooks, currentRoute.routeHooks || '') + : undefined + + // B. Trigger current route RH + const currentRouteHookOutput = await runProdRouteHooks( + routeHookPath, + currentRoute.hasParams + ? matchPath(currentRoute.pathDefinition, currentPathName).params + : undefined, + rootRouteHookOutput + ) + + // Compose the appRH output and RH output + serverData = { + ...rootRouteHookOutput.serverData, + ...currentRouteHookOutput.serverData, + } + + metaTags = [...rootRouteHookOutput.meta, ...currentRouteHookOutput.meta] + } + + // Serialize route context so it can be passed to the client entry + const serializedRouteContext = JSON.stringify(serverData) + + const pageWithJs = currentRoute.renderMode !== 'html' + // @NOTE have to add slash so subpaths still pick up the right file + // Vite is currently producing modules not scripts: https://vitejs.dev/config/build-options.html#build-target + const bootstrapModules = pageWithJs + ? ['/' + indexEntry.file, '/' + currentRoute.bundle] + : undefined + + const isSeoCrawler = checkUaForSeoCrawler(req.get('user-agent')) + + const { pipe, abort } = renderToPipeableStream( + // we should use the same shape as Remix or Next for the meta object + serverEntry({ + url: currentPathName, + routeContext: serverData, + css: indexEntry.css, + meta: metaTags, + }), + { + bootstrapScriptContent: pageWithJs + ? `window.__loadServerData = function() { return ${serializedRouteContext} }; window.__assetMap = function() { return ${JSON.stringify( + { css: indexEntry.css, meta: metaTags } + )} }` + : undefined, + bootstrapModules, + onShellReady() { + if (!isSeoCrawler) { + res.setHeader('content-type', 'text/html; charset=utf-8') + pipe(res) + } + }, + onAllReady() { + if (isSeoCrawler) { + res.setHeader('content-type', 'text/html; charset=utf-8') + pipe(res) + } + }, + onError(error) { + console.error(error) + }, + } + ) + + // @TODO make the timeout configurable + setTimeout(() => { + abort() + }, 10_000) + } catch (e) { + console.error(e) + + // streaming no longer requires us to send back a blank page + // React will automatically switch to client rendering on error + return res.sendStatus(500) + } + + // @TODO Refactor this + // WE are repeating code a lot between runFeServer and devFeServer + async function runProdRouteHooks( + routeHookPath: string | null | undefined, + parsedParams?: Record, + appRouteHookOutput?: { meta: TagDescriptor[]; serverData: any } + ) { + if (routeHookPath) { + try { + const routeHooks = await import(routeHookPath) + + const output = await triggerRouteHooks({ + routeHooks, + req, + parsedParams, + appRouteHookOutput, + }) + + return { + serverData: output.serverData, + meta: output.meta, + } + } catch (e) { + console.error(`Error running route hooks in ${routeHookPath}}`) + console.error(e) + } + } + + // Empty values if error, or no routeHookPath + return { serverData: {}, meta: [] } + } + + return + }) + + app.listen(rwConfig.web.port) + console.log( + `Started production FE server on http://localhost:${rwConfig.web.port}` + ) +} + +runFeServer() diff --git a/packages/vite/src/triggerRouteHooks.ts b/packages/vite/src/triggerRouteHooks.ts new file mode 100644 index 000000000000..689c5ed696aa --- /dev/null +++ b/packages/vite/src/triggerRouteHooks.ts @@ -0,0 +1,59 @@ +/// + +import { Request } from 'express' + +import { MetaHook, ServerDataHook, TagDescriptor } from '@redwoodjs/web' +import type { RouteHookEvent, RouteHookOutput } from '@redwoodjs/web' + +interface RouteHooks { + serverData?: ServerDataHook + meta?: MetaHook +} + +interface TriggerRouteHooksParam { + routeHooks: RouteHooks + req: Request + parsedParams?: Record + appRouteHookOutput?: RouteHookOutput +} + +export const triggerRouteHooks = async ({ + routeHooks, + req, + parsedParams = {}, + appRouteHookOutput, +}: TriggerRouteHooksParam) => { + const event: RouteHookEvent = { + params: parsedParams, + headers: req.headers || {}, + query: req.query as any, // @TODO we should parse query parameters the same way as RW router + // cookies: req.cookies || {}, // @TODO we probably need some sort of cookie parser + appRouteHook: appRouteHookOutput, + } + + let serverData = {} + let meta: TagDescriptor[] = [] + + try { + serverData = (await routeHooks?.serverData?.(event)) || {} + } catch (e: any) { + throw new Error(`Error in serverData hook: ${e.message}`) + } + + try { + const metaRouteHookOutput = + (await routeHooks?.meta?.({ ...event, serverData })) || [] + + // Convert it to an array, if it's not already + meta = Array.isArray(metaRouteHookOutput) + ? metaRouteHookOutput + : [metaRouteHookOutput] + } catch (e: any) { + throw new Error(`Error in meta hook: ${e.message}`) + } + + return { + serverData, + meta, + } +} diff --git a/packages/vite/src/types.ts b/packages/vite/src/types.ts new file mode 100644 index 000000000000..c8c397c73848 --- /dev/null +++ b/packages/vite/src/types.ts @@ -0,0 +1,14 @@ +export interface RWRouteManifestItem { + matchRegexString: string | null + routeHooks: string | null + bundle: string | null + pathDefinition: PathDefinition + hasParams: boolean + name: string + redirect: { to: string; permanent: boolean } | null + renderMode: 'html' | 'stream' +} + +export type RWRouteManifest = Record + +type PathDefinition = string diff --git a/packages/vite/src/utils.ts b/packages/vite/src/utils.ts new file mode 100644 index 000000000000..fcf22a750f11 --- /dev/null +++ b/packages/vite/src/utils.ts @@ -0,0 +1,3 @@ +export function stripQueryStringAndHashFromPath(url: string) { + return url.split('?')[0].split('#')[0]; +} diff --git a/packages/vite/tsconfig.json b/packages/vite/tsconfig.json index be6bc71ed0ae..17a371aa267b 100644 --- a/packages/vite/tsconfig.json +++ b/packages/vite/tsconfig.json @@ -9,5 +9,6 @@ "include": ["src/**/*", "./ambient.d.ts", "./vite-plugin-commonjs.d.ts"], "references": [ { "path": "../internal" }, + { "path": "../web" }, ] } diff --git a/packages/web/src/apollo/index.tsx b/packages/web/src/apollo/index.tsx index 445b6f4bbb82..2df9bb638e05 100644 --- a/packages/web/src/apollo/index.tsx +++ b/packages/web/src/apollo/index.tsx @@ -5,6 +5,7 @@ import type { } from '@apollo/client' import * as apolloClient from '@apollo/client' import { setContext } from '@apollo/client/link/context' +import { fetch as crossFetch } from '@whatwg-node/fetch' import { print } from 'graphql/language/printer' // Note: Importing directly from `apollo/client` does not work properly in Storybook. @@ -176,7 +177,7 @@ const ApolloProviderWithFetchConfig: React.FunctionComponent<{ */ const { httpLinkConfig, link: userLink, ...rest } = config ?? {} - const httpLink = new HttpLink({ uri, ...httpLinkConfig }) + const httpLink = new HttpLink({ uri, fetch: crossFetch, ...httpLinkConfig }) /** * The order here is important. The last link *must* be a terminating link like HttpLink. diff --git a/packages/web/src/components/RedwoodProvider.tsx b/packages/web/src/components/RedwoodProvider.tsx index dd331c92461c..d5944919a462 100644 --- a/packages/web/src/components/RedwoodProvider.tsx +++ b/packages/web/src/components/RedwoodProvider.tsx @@ -1,28 +1,19 @@ -import { Helmet, HelmetProvider } from 'react-helmet-async' +import { HelmetProvider } from 'react-helmet-async' interface RedwoodProviderProps { children: React.ReactNode titleTemplate?: string } -export const RedwoodProvider = ({ - children, - titleTemplate, -}: RedwoodProviderProps) => { - const appTitle = globalThis.__REDWOOD__APP_TITLE - const template = () => { - if (titleTemplate) { - let template = titleTemplate.replace(/%AppTitle/g, appTitle) - template = template.replace(/%PageTitle/g, '%s') - return template - } - return '' - } +export const RedwoodProvider = ({ children }: RedwoodProviderProps) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + // @TODO disabling helmet here, because it clashes with meta routeHooks + // but still leaving helmet provider to make it easy to migrate to new setup return ( - + {/* {appTitle} - + */} {children} ) diff --git a/packages/web/src/components/htmlTags.tsx b/packages/web/src/components/htmlTags.tsx new file mode 100644 index 000000000000..1f29b4de52d2 --- /dev/null +++ b/packages/web/src/components/htmlTags.tsx @@ -0,0 +1,116 @@ +import { Fragment } from 'react' +/** CSS is a specialised metatag */ +export const Css = ({ css = [] }: { css: string[] }) => { + return ( + <> + {css.map((cssLinks, index) => { + return ( + + ) + })} + + ) +} + +/** + * My Page + */ +interface Title { + title: string +} + +/** + * + */ +interface NameContent { + name: string + content: string +} + +/** + * + */ +interface OpenGraph { + property: string + content: string +} + +/** + * + */ +interface HttpEquiv { + httpEquiv: string + content: string +} + +/*** + * + */ +interface Custom { + [name: string]: unknown +} + +/** + * + */ +interface Other extends Custom { + tagType: string // link, script, etc +} + +// @MARK Maintaining the similar format to Remix's V2_MetaDescriptor +// 1. because I like it +// 2. because it'll feel consistent to people who are familiar with Remix +// I've modified it a little bit, but we need to decide wether we want the +// remix style DIY meta tags, or the more opinionated approach in MetaTags.tsx +export type TagDescriptor = + | Title + // Not sure why we need these, maybe just for ease of use + | NameContent + | OpenGraph + | HttpEquiv + // ------------------------ + | Custom + | Other + +interface MetaProps { + tags: TagDescriptor[] | undefined +} + +export const Meta = ({ tags = [] }: MetaProps) => { + return ( + <> + {tags.map((tag, index) => { + if (!tag) { + return null + } + + if (isTitleTag(tag)) { + return ( + + {tag.title} + + + ) + } + + // @TODO add validate tag function + if (otherTag(tag)) { + const { tagType: TagName, ...rest } = tag + return + } + + return + })} + + ) +} + +const isTitleTag = (tag: TagDescriptor): tag is Title => { + return 'title' in tag +} + +// Not a "" tag +const otherTag = (tag: TagDescriptor): tag is Other => { + return 'tagType' in tag +} diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts index 7774301aab5b..baa1196cb448 100644 --- a/packages/web/src/index.ts +++ b/packages/web/src/index.ts @@ -31,3 +31,6 @@ export * from './components/RedwoodProvider' export * from './components/MetaTags' export { Helmet as Head, Helmet } from 'react-helmet-async' + +export * from './components/htmlTags' +export * from './routeHooks.types' diff --git a/packages/web/src/routeHooks.types.ts b/packages/web/src/routeHooks.types.ts new file mode 100644 index 000000000000..29484f642576 --- /dev/null +++ b/packages/web/src/routeHooks.types.ts @@ -0,0 +1,18 @@ +import { TagDescriptor } from './components/htmlTags' + +export type RouteHookOutput = { + meta: TagDescriptor[] + serverData: any +} +export interface RouteHookEvent { + params: Record // this has to be provided from RW router + headers: Record + query: Record + // cookies: Record @TODO pass in parsed cookies + appRouteHook?: RouteHookOutput +} + +export type ServerDataHook = (event: RouteHookEvent) => any +export type MetaHook = ( + event: RouteHookEvent & { serverData: T } +) => Promise | TagDescriptor[] | TagDescriptor diff --git a/packages/web/src/serverContext.tsx b/packages/web/src/serverContext.tsx new file mode 100644 index 000000000000..3fc8a38d3d28 --- /dev/null +++ b/packages/web/src/serverContext.tsx @@ -0,0 +1,12 @@ +import React from 'react' + +const ServerContext = React.createContext({}) + +export const { + Provider: ServerContextProvider, + Consumer: ServerContextConsumer, +} = ServerContext + +export const useServerData = () => { + return React.useContext(ServerContext) as T +} diff --git a/tasks/framework-tools/lib/project.mjs b/tasks/framework-tools/lib/project.mjs index ad10d6fc41de..6951ca7361bc 100644 --- a/tasks/framework-tools/lib/project.mjs +++ b/tasks/framework-tools/lib/project.mjs @@ -22,18 +22,22 @@ import { export function fixProjectBinaries(projectPath) { const bins = frameworkPackagesBins() for (let [binName, binPath] of Object.entries(bins)) { - // if the binPath doesn't exist, create it. - const binSymlink = path.join(projectPath, 'node_modules/.bin', binName) - binPath = path.join(projectPath, 'node_modules', binPath) - if (!fs.existsSync(binSymlink)) { - fs.mkdirSync(path.dirname(binSymlink), { - recursive: true, - }) - fs.symlinkSync(binPath, binSymlink) + try { + // if the binPath doesn't exist, create it. + const binSymlink = path.join(projectPath, 'node_modules/.bin', binName) + binPath = path.join(projectPath, 'node_modules', binPath) + if (!fs.existsSync(binSymlink)) { + fs.mkdirSync(path.dirname(binSymlink), { + recursive: true, + }) + fs.symlinkSync(binPath, binSymlink) + } + console.log('chmod +x', terminalLink(binName, binPath)) + fs.chmodSync(binSymlink, '755') + fs.chmodSync(binPath, '755') + } catch (e) { + console.error(e) } - console.log('chmod +x', terminalLink(binName, binPath)) - fs.chmodSync(binSymlink, '755') - fs.chmodSync(binPath, '755') } } diff --git a/yarn.lock b/yarn.lock index ff7bdf694d19..cfc19ba37a0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1303,7 +1303,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-assertions@npm:^7.20.0": +"@babel/plugin-syntax-import-assertions@npm:7.20.0, @babel/plugin-syntax-import-assertions@npm:^7.20.0": version: 7.20.0 resolution: "@babel/plugin-syntax-import-assertions@npm:7.20.0" dependencies: @@ -7614,9 +7614,12 @@ __metadata: rimraf: ./dist/bins/rimraf.js rw: ./dist/bins/redwood.js rw-api-server-watch: ./dist/bins/rw-api-server-watch.js + rw-dev-fe: ./dist/bins/rw-dev-fe.js rw-gen: ./dist/bins/rw-gen.js rw-gen-watch: ./dist/bins/rw-gen-watch.js rw-log-formatter: ./dist/bins/rw-log-formatter.js + rw-serve-api: ./dist/bins/rw-serve-api.js + rw-serve-fe: ./dist/bins/rw-serve-fe.js rwfw: ./dist/bins/rwfw.js languageName: unknown linkType: soft @@ -8046,19 +8049,27 @@ __metadata: resolution: "@redwoodjs/vite@workspace:packages/vite" dependencies: "@babel/cli": 7.21.5 + "@babel/plugin-syntax-import-assertions": 7.20.0 "@babel/runtime-corejs3": 7.22.3 "@redwoodjs/internal": 5.0.0 "@redwoodjs/project-config": 5.0.0 + "@types/express": 4 "@vitejs/plugin-react": 4.0.0 buffer: 6.0.3 core-js: 3.30.2 + dotenv-defaults: 5.0.2 + express: 4.18.2 glob: 10.2.7 + http-proxy-middleware: 2.0.6 + isbot: 3.6.8 jest: 29.5.0 typescript: 5.1.3 vite: 4.3.9 vite-plugin-commonjs: 0.6.2 vite-plugin-environment: 1.1.3 bin: + rw-dev-fe: ./dist/devFeServer.js + rw-serve-fe: ./dist/runFeServer.js rw-vite-build: ./bins/rw-vite-build.mjs rw-vite-dev: ./bins/rw-vite-dev.mjs vite: ./bins/vite.mjs @@ -9792,7 +9803,7 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.14, @types/express@npm:^4.7.0": +"@types/express@npm:*, @types/express@npm:4, @types/express@npm:^4.17.13, @types/express@npm:^4.17.14, @types/express@npm:^4.7.0": version: 4.17.17 resolution: "@types/express@npm:4.17.17" dependencies: @@ -17025,7 +17036,7 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.1, express@npm:^4.17.3": +"express@npm:4.18.2, express@npm:^4.17.1, express@npm:^4.17.3": version: 4.18.2 resolution: "express@npm:4.18.2" dependencies: @@ -19355,7 +19366,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-middleware@npm:^2.0.3": +"http-proxy-middleware@npm:2.0.6, http-proxy-middleware@npm:^2.0.3": version: 2.0.6 resolution: "http-proxy-middleware@npm:2.0.6" dependencies: @@ -20488,6 +20499,13 @@ __metadata: languageName: node linkType: hard +"isbot@npm:3.6.8": + version: 3.6.8 + resolution: "isbot@npm:3.6.8" + checksum: fbc067d6567fc006026f24527fd09ff655f5eb7e3672070ceb7e62afae9973aeb88f37dd29b88318ee25404818bb294bcc0cab93fb447c798294f0fd36b4b436 + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" From 137f7808ed540bcdde18dac34b35a02871a03059 Mon Sep 17 00:00:00 2001 From: Daniel Choudhury Date: Thu, 8 Jun 2023 15:58:11 +0700 Subject: [PATCH 02/26] Fix bad merge --- packages/internal/src/build/babel/common.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/internal/src/build/babel/common.ts b/packages/internal/src/build/babel/common.ts index b8322e7e7f22..ddb4d1d4d5e7 100644 --- a/packages/internal/src/build/babel/common.ts +++ b/packages/internal/src/build/babel/common.ts @@ -6,8 +6,6 @@ import { parseConfigFileTextToJson } from 'typescript' import { getPaths } from '@redwoodjs/project-config' -import { getPaths } from '@redwoodjs/project-config' - import { getWebSideBabelPlugins } from './web' const pkgJson = require('../../../package.json') From e4bc979c02f2142b4681b50df825066eae54a0c0 Mon Sep 17 00:00:00 2001 From: Daniel Choudhury Date: Tue, 13 Jun 2023 13:57:17 +0700 Subject: [PATCH 03/26] Recursively trigger routeHooks --- packages/cli/src/commands/buildHandler.js | 10 +++ packages/vite/src/buildFeServer.ts | 10 ++- packages/vite/src/devFeServer.ts | 64 +++----------- packages/vite/src/index.ts | 2 + packages/vite/src/runFeServer.ts | 100 +++++++--------------- packages/vite/src/triggerRouteHooks.ts | 83 ++++++++++++++++-- packages/vite/src/types.ts | 27 ++++-- packages/web/src/routeHooks.types.ts | 3 +- 8 files changed, 163 insertions(+), 136 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index 91210dcf88f8..5f3e69ab8bf7 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -96,6 +96,16 @@ export const handler = async ({ title: 'Building Web...', task: async () => { if (getConfig().web.bundler === 'vite') { + // @WARN DO NOT MERGE TEMPORARY HACK + // @WARN DO NOT MERGE TEMPORARY HACK + // @WARN DO NOT MERGE TEMPORARY HACK + // @WARN DO NOT MERGE TEMPORARY HACK + // @WARN DO NOT MERGE TEMPORARY HACK + // @WARN DO NOT MERGE TEMPORARY HACK + // @WARN DO NOT MERGE TEMPORARY HACK + process.chdir(rwjsPaths.web.base) + + // @TODO: we need to use a binary here, so the the cwd is correct await buildFeServer({ verbose, }) diff --git a/packages/vite/src/buildFeServer.ts b/packages/vite/src/buildFeServer.ts index 9193e5bf9c76..eaf8eae2daaa 100644 --- a/packages/vite/src/buildFeServer.ts +++ b/packages/vite/src/buildFeServer.ts @@ -92,9 +92,13 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { }) // Step 3: Generate route-manifest.json - const clientBuildManifest: ViteManifest = await import( - path.join(getPaths().web.dist, 'build-manifest.json') - ) + // @TODO double check why we need to do .default here + // Its related to the babel import assertion plugin most likely + const clientBuildManifest: ViteManifest = ( + await import(path.join(getPaths().web.dist, 'build-manifest.json'), { + assert: { type: 'json' }, + }) + ).default const routesList = getProjectRoutes() diff --git a/packages/vite/src/devFeServer.ts b/packages/vite/src/devFeServer.ts index 9ff03d97e391..678944873065 100644 --- a/packages/vite/src/devFeServer.ts +++ b/packages/vite/src/devFeServer.ts @@ -9,7 +9,7 @@ import { getAppRouteHook, getConfig, getPaths } from '@redwoodjs/project-config' import { matchPath } from '@redwoodjs/router' import type { TagDescriptor } from '@redwoodjs/web' -import { triggerRouteHooks } from './triggerRouteHooks' +import { loadAndRunRouteHooks } from './triggerRouteHooks' import { stripQueryStringAndHashFromPath } from './utils' // These values are defined in the vite.config.ts @@ -72,25 +72,21 @@ async function createServer() { } if (currentRoute) { - // A. Trigger app route hook - const rootRouteHookOutput = await runDevRouteHooks(getAppRouteHook()) - - // B. Trigger current route RH - const currentRouteHookOutput = await runDevRouteHooks( - currentRoute.routeHooks, - currentRoute.hasParams - ? matchPath(currentRoute.path, currentPathName).params - : undefined, - rootRouteHookOutput - ) + const parsedParams = currentRoute.hasParams + ? matchPath(currentRoute.path, currentPathName).params + : undefined - // Compose the appRH output and RH output - serverData = { - ...rootRouteHookOutput.serverData, - ...currentRouteHookOutput.serverData, - } + const routeHookOutput = await loadAndRunRouteHooks({ + paths: [getAppRouteHook(), currentRoute.routeHooks], + reqMeta: { + req, + parsedParams, + }, + viteDevServer: vite, // because its dev + }) - metaTags = [...rootRouteHookOutput.meta, ...currentRouteHookOutput.meta] + serverData = routeHookOutput.serverData + metaTags = routeHookOutput.meta } if (!currentRoute) { @@ -157,38 +153,6 @@ async function createServer() { vite.ssrFixStacktrace(e as any) next(e) } - - // @TODO Refactor this - // WE are repeating code a lot between runFeServer and devFeServer - async function runDevRouteHooks( - routeHookPath: string | null | undefined, - parsedParams?: Record, - appRouteHookOutput?: { meta: TagDescriptor[]; serverData: any } - ) { - if (routeHookPath) { - try { - const routeHooks = await vite.ssrLoadModule(routeHookPath) - - const output = await triggerRouteHooks({ - routeHooks, - req, - parsedParams, - appRouteHookOutput, - }) - - return { - serverData: output.serverData, - meta: output.meta, - } - } catch (e) { - console.error(`Error running route hooks in ${routeHookPath}}`) - console.error(e) - } - } - - // Empty values if error, or no routeHookPath - return { serverData: {}, meta: [] } - } }) const port = getConfig().web.port diff --git a/packages/vite/src/index.ts b/packages/vite/src/index.ts index 83d9959438a1..be122a20670a 100644 --- a/packages/vite/src/index.ts +++ b/packages/vite/src/index.ts @@ -188,3 +188,5 @@ export default function redwoodPluginVite(): PluginOption[] { }), ] } + +export { buildFeServer } from './buildFeServer' diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index 93b9c9c7f75b..9f31c31c9806 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -12,7 +12,7 @@ import { getConfig, getPaths } from '@redwoodjs/project-config' import { matchPath } from '@redwoodjs/router' import type { TagDescriptor } from '@redwoodjs/web' -import { triggerRouteHooks } from './triggerRouteHooks' +import { loadAndRunRouteHooks } from './triggerRouteHooks' import { RWRouteManifest } from './types' import { stripQueryStringAndHashFromPath } from './utils' @@ -44,15 +44,19 @@ export async function runFeServer() { const rwPaths = getPaths() const rwConfig = getConfig() - const routeManifest: RWRouteManifest = await import( - rwPaths.web.dist + '/server/route-manifest.json', - { assert: { type: 'json' } } - ) + // @TODO @MARK figure out why we're having to do default here + const routeManifest: RWRouteManifest = ( + await import(rwPaths.web.dist + '/server/route-manifest.json', { + assert: { type: 'json' }, + }) + ).default - const buildManifest: ViteManifest = await import( - rwPaths.web.dist + '/build-manifest.json', - { assert: { type: 'json' } } - ) + // @TODO @MARK figure out why we're having to do default here + const buildManifest: ViteManifest = ( + await import(rwPaths.web.dist + '/build-manifest.json', { + assert: { type: 'json' }, + }) + ).default const indexEntry = Object.values(buildManifest).find((manifestItem) => { return manifestItem.isEntry @@ -157,37 +161,29 @@ export async function runFeServer() { } if (currentRoute) { - // @TODO hardcoded JS file, watchout if we switch to ESM! - const prodAppRouteHookPath = path.join( - rwPaths.web.distRouteHooks, - 'App.routeHooks.js' - ) - - // A. Trigger app route hook - const rootRouteHookOutput = await runProdRouteHooks( - prodAppRouteHookPath - ) + // Make sure we access the dist routeHooks! + const routeHookPaths = [ + // @TODO hardcoded JS file, watchout if we switch to ESM! + path.join(rwPaths.web.distRouteHooks, 'App.routeHooks.js'), + currentRoute.routeHooks + ? path.join(rwPaths.web.distRouteHooks, currentRoute.routeHooks) + : null, + ] - const routeHookPath = currentRoute.routeHooks - ? path.join(rwPaths.web.distRouteHooks, currentRoute.routeHooks || '') + const parsedParams = currentRoute.hasParams + ? matchPath(currentRoute.pathDefinition, currentPathName).params : undefined - // B. Trigger current route RH - const currentRouteHookOutput = await runProdRouteHooks( - routeHookPath, - currentRoute.hasParams - ? matchPath(currentRoute.pathDefinition, currentPathName).params - : undefined, - rootRouteHookOutput - ) - - // Compose the appRH output and RH output - serverData = { - ...rootRouteHookOutput.serverData, - ...currentRouteHookOutput.serverData, - } + const routeHookOutput = await loadAndRunRouteHooks({ + paths: routeHookPaths, + reqMeta: { + req, + parsedParams, + }, + }) - metaTags = [...rootRouteHookOutput.meta, ...currentRouteHookOutput.meta] + serverData = routeHookOutput.serverData + metaTags = routeHookOutput.meta } // Serialize route context so it can be passed to the client entry @@ -247,38 +243,6 @@ export async function runFeServer() { return res.sendStatus(500) } - // @TODO Refactor this - // WE are repeating code a lot between runFeServer and devFeServer - async function runProdRouteHooks( - routeHookPath: string | null | undefined, - parsedParams?: Record, - appRouteHookOutput?: { meta: TagDescriptor[]; serverData: any } - ) { - if (routeHookPath) { - try { - const routeHooks = await import(routeHookPath) - - const output = await triggerRouteHooks({ - routeHooks, - req, - parsedParams, - appRouteHookOutput, - }) - - return { - serverData: output.serverData, - meta: output.meta, - } - } catch (e) { - console.error(`Error running route hooks in ${routeHookPath}}`) - console.error(e) - } - } - - // Empty values if error, or no routeHookPath - return { serverData: {}, meta: [] } - } - return }) diff --git a/packages/vite/src/triggerRouteHooks.ts b/packages/vite/src/triggerRouteHooks.ts index 689c5ed696aa..9e3dbf134578 100644 --- a/packages/vite/src/triggerRouteHooks.ts +++ b/packages/vite/src/triggerRouteHooks.ts @@ -1,6 +1,7 @@ /// import { Request } from 'express' +import { ViteDevServer } from 'vite' import { MetaHook, ServerDataHook, TagDescriptor } from '@redwoodjs/web' import type { RouteHookEvent, RouteHookOutput } from '@redwoodjs/web' @@ -14,28 +15,32 @@ interface TriggerRouteHooksParam { routeHooks: RouteHooks req: Request parsedParams?: Record - appRouteHookOutput?: RouteHookOutput + previousOutput?: RouteHookOutput } export const triggerRouteHooks = async ({ routeHooks, req, parsedParams = {}, - appRouteHookOutput, + previousOutput, }: TriggerRouteHooksParam) => { const event: RouteHookEvent = { params: parsedParams, headers: req.headers || {}, query: req.query as any, // @TODO we should parse query parameters the same way as RW router // cookies: req.cookies || {}, // @TODO we probably need some sort of cookie parser - appRouteHook: appRouteHookOutput, + // @TODO called app routeHook, but its just the previous output + appRouteHook: previousOutput, } let serverData = {} - let meta: TagDescriptor[] = [] + let meta: TagDescriptor[] = previousOutput?.meta || [] try { - serverData = (await routeHooks?.serverData?.(event)) || {} + serverData = { + ...previousOutput?.serverData, + ...((await routeHooks?.serverData?.(event)) || {}), + } } catch (e: any) { throw new Error(`Error in serverData hook: ${e.message}`) } @@ -45,9 +50,11 @@ export const triggerRouteHooks = async ({ (await routeHooks?.meta?.({ ...event, serverData })) || [] // Convert it to an array, if it's not already - meta = Array.isArray(metaRouteHookOutput) + const currentMeta = Array.isArray(metaRouteHookOutput) ? metaRouteHookOutput : [metaRouteHookOutput] + + meta = [...meta, ...currentMeta] } catch (e: any) { throw new Error(`Error in meta hook: ${e.message}`) } @@ -57,3 +64,67 @@ export const triggerRouteHooks = async ({ meta, } } + +interface LoadAndRunRouteHooks { + paths: Array // will run in order of the array + reqMeta: { + req: Request + parsedParams?: Record + } + viteDevServer?: ViteDevServer + previousOutput?: RouteHookOutput +} + +const defaultRouteHookOutput = { + meta: [], + serverData: {}, +} + +export const loadAndRunRouteHooks = async ({ + paths = [], + reqMeta, + viteDevServer, + previousOutput = defaultRouteHookOutput, +}: LoadAndRunRouteHooks): Promise => { + // Step 1, load the route hooks + const loadModule = async (path: string) => { + return viteDevServer ? viteDevServer.ssrLoadModule(path) : import(path) + } + + let currentRouteHooks: RouteHooks + + // Pull out the first path + // Remember shift will mutate the array + const routeHookPath = paths.shift() + + if (!routeHookPath) { + return defaultRouteHookOutput + } else { + try { + currentRouteHooks = await loadModule(routeHookPath) + + // Step 2, run the route hooks + const rhOutput = await triggerRouteHooks({ + routeHooks: currentRouteHooks, + req: reqMeta.req, + parsedParams: reqMeta.parsedParams, + previousOutput, + }) + + if (paths.length > 0) { + // Step 3, recursively call this function + return loadAndRunRouteHooks({ + paths, + reqMeta, + previousOutput: rhOutput, + viteDevServer, + }) + } else { + return rhOutput + } + } catch (e) { + console.error(`Error loading route hooks in ${routeHookPath}}`) + throw new Error(e as any) + } + } +} diff --git a/packages/vite/src/types.ts b/packages/vite/src/types.ts index c8c397c73848..445f3226a572 100644 --- a/packages/vite/src/types.ts +++ b/packages/vite/src/types.ts @@ -1,12 +1,23 @@ +/** + * + * Sub+Superset of RouteSpec returned by getProjectRoutes() + * in packages/internal/src/routes.ts + * + * Differences: + * - has path to routeHook (which is not available until after build) + * - bundle doesn't exist before build, comes from vite build manifest. Used in script injection + * + * **All** of these properties are used by the prod FE server + */ export interface RWRouteManifestItem { - matchRegexString: string | null - routeHooks: string | null - bundle: string | null - pathDefinition: PathDefinition - hasParams: boolean - name: string - redirect: { to: string; permanent: boolean } | null - renderMode: 'html' | 'stream' + matchRegexString: string | null // xAR, RouteSpec.matchRegexString + routeHooks: string | null // xAR, RouteSpec.routeHooks BUT in RouteSpec its the src path, here its the dist path + bundle: string | null // xAR, xRS + pathDefinition: PathDefinition // <-- AnalyzedRoute.path, RouteSpec.path + hasParams: boolean // xAR, RouteSpec.hasParams + name: string // <-- AnalyzedRoute.name, RouteSpec.name + redirect: { to: string; permanent: boolean } | null // xAR (not same type), RouteSpec.redirect + renderMode: 'html' | 'stream' // x, RouteSpec.renderMode } export type RWRouteManifest = Record diff --git a/packages/web/src/routeHooks.types.ts b/packages/web/src/routeHooks.types.ts index 29484f642576..934062923b74 100644 --- a/packages/web/src/routeHooks.types.ts +++ b/packages/web/src/routeHooks.types.ts @@ -2,13 +2,14 @@ import { TagDescriptor } from './components/htmlTags' export type RouteHookOutput = { meta: TagDescriptor[] - serverData: any + serverData: Record } export interface RouteHookEvent { params: Record // this has to be provided from RW router headers: Record query: Record // cookies: Record @TODO pass in parsed cookies + // @MARK @TODO: this is the previous output, but we call it appRouteHook, we should rename it appRouteHook?: RouteHookOutput } From 29499b8d4baa01df63cf2c20de9ed363974768c3 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Sun, 25 Jun 2023 17:21:48 +0200 Subject: [PATCH 04/26] Make it build --- packages/cli/src/commands/buildHandler.js | 4 ++-- packages/internal/package.json | 1 + packages/internal/tsconfig.json | 1 + packages/vite/package.json | 1 + packages/vite/src/buildFeServer.ts | 2 +- packages/vite/src/runFeServer.ts | 2 +- packages/vite/tsconfig.json | 1 + 7 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index 5f3e69ab8bf7..fbd2b38dc14f 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -72,8 +72,8 @@ export const handler = async ({ }, side.includes('api') && { title: 'Building API...', - task: async () => { - const { errors, warnings } = await buildApi() + task: () => { + const { errors, warnings } = buildApi() if (errors.length) { console.error(errors) diff --git a/packages/internal/package.json b/packages/internal/package.json index 35bc627eac0c..8ab2965479ac 100644 --- a/packages/internal/package.json +++ b/packages/internal/package.json @@ -43,6 +43,7 @@ "@graphql-codegen/typescript-resolvers": "3.2.1", "@redwoodjs/graphql-server": "5.0.0", "@redwoodjs/project-config": "5.0.0", + "@redwoodjs/router": "5.0.0", "@sdl-codegen/node": "0.0.10", "babel-plugin-graphql-tag": "3.3.0", "babel-plugin-polyfill-corejs3": "0.8.1", diff --git a/packages/internal/tsconfig.json b/packages/internal/tsconfig.json index d7c3724e5c43..dc8605264e3a 100644 --- a/packages/internal/tsconfig.json +++ b/packages/internal/tsconfig.json @@ -10,5 +10,6 @@ "references": [ { "path": "../graphql-server" }, // ODD, but we do this so we dont have to have internal as a runtime dependency { "path": "../project-config" }, + { "path": "../router" }, ] } diff --git a/packages/vite/package.json b/packages/vite/package.json index 739769ecd9d0..72d8dc6f9430 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -32,6 +32,7 @@ "@babel/runtime-corejs3": "7.22.3", "@redwoodjs/internal": "5.0.0", "@redwoodjs/project-config": "5.0.0", + "@redwoodjs/web": "5.0.0", "@vitejs/plugin-react": "4.0.0", "buffer": "6.0.3", "core-js": "3.30.2", diff --git a/packages/vite/src/buildFeServer.ts b/packages/vite/src/buildFeServer.ts index eaf8eae2daaa..72469f6c76d7 100644 --- a/packages/vite/src/buildFeServer.ts +++ b/packages/vite/src/buildFeServer.ts @@ -2,7 +2,7 @@ import fs from 'fs/promises' import path from 'path' import { build as esbuildBuild, PluginBuild } from 'esbuild' -import type { ViteManifest } from 'vite' +import type { Manifest as ViteManifest } from 'vite' import { getRouteHookBabelPlugins } from '@redwoodjs/internal' import { transformWithBabel } from '@redwoodjs/internal/dist/build/babel/api' diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index 9f31c31c9806..3b5dbd178257 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -6,7 +6,7 @@ import express from 'express' import { createProxyMiddleware } from 'http-proxy-middleware' import isbot from 'isbot' import { renderToPipeableStream } from 'react-dom/server' -import type { ViteManifest } from 'vite' +import type { Manifest as ViteManifest } from 'vite' import { getConfig, getPaths } from '@redwoodjs/project-config' import { matchPath } from '@redwoodjs/router' diff --git a/packages/vite/tsconfig.json b/packages/vite/tsconfig.json index 17a371aa267b..552bfa0056b0 100644 --- a/packages/vite/tsconfig.json +++ b/packages/vite/tsconfig.json @@ -9,6 +9,7 @@ "include": ["src/**/*", "./ambient.d.ts", "./vite-plugin-commonjs.d.ts"], "references": [ { "path": "../internal" }, + { "path": "../project-config" }, { "path": "../web" }, ] } From a1774244ab77368f329cfccd7b9d4fd1b781805f Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Sun, 25 Jun 2023 19:22:09 +0200 Subject: [PATCH 05/26] extract assetMap --- packages/vite/src/devFeServer.ts | 14 +++++++------- packages/vite/src/runFeServer.ts | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/vite/src/devFeServer.ts b/packages/vite/src/devFeServer.ts index 678944873065..04b79feb4bcf 100644 --- a/packages/vite/src/devFeServer.ts +++ b/packages/vite/src/devFeServer.ts @@ -105,12 +105,17 @@ async function createServer() { const { serverEntry } = await vite.ssrLoadModule(rwPaths.web.entryServer) // Serialize route context so it can be passed to the client entry - const serialisedRouteContext = JSON.stringify(serverData) + const serializedRouteContext = JSON.stringify(serverData) // @TODO CSS is handled by Vite in dev mode, we don't need to worry about it in dev // but..... it causes a flash of unstyled content. For now I'm just injecting index css here const FIXME_HardcodedIndexCss = ['index.css'] + const assetMap = JSON.stringify({ + css: FIXME_HardcodedIndexCss, + meta: metaTags, + }) + const bootstrapModules = [ path.join(__dirname, '../inject', 'reactRefresh.js'), ] @@ -130,12 +135,7 @@ async function createServer() { }), { bootstrapScriptContent: pageWithJs - ? `window.__loadServerData = function() { return ${serialisedRouteContext} }; window.__assetMap = function() { return ${JSON.stringify( - { - css: FIXME_HardcodedIndexCss, - meta: metaTags, - } - )} }` + ? `window.__loadServerData = function() { return ${serializedRouteContext} }; window.__assetMap = function() { return ${assetMap} }` : undefined, bootstrapModules, onShellReady() { diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index 3b5dbd178257..facb146d2ab3 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -124,6 +124,8 @@ export async function runFeServer() { return res.sendStatus(404) } + const assetMap = JSON.stringify({ css: indexEntry.css }) + const { pipe } = renderToPipeableStream( serverEntry({ url: currentPathName, @@ -131,9 +133,7 @@ export async function runFeServer() { css: indexEntry.css, }), { - bootstrapScriptContent: `window.__assetMap = function() { return ${JSON.stringify( - { css: indexEntry.css } - )} }`, + bootstrapScriptContent: `window.__assetMap = function() { return ${assetMap} }`, // @NOTE have to add slash so subpaths still pick up the right file // Vite is currently producing modules not scripts: https://vitejs.dev/config/build-options.html#build-target bootstrapModules: [ From 01df1fc51bc42ef35e68c5cda23a0241e879c90c Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Sun, 25 Jun 2023 20:16:12 +0200 Subject: [PATCH 06/26] Limit code churn --- packages/cli/src/commands/buildHandler.js | 5 +++-- packages/cli/src/commands/devHandler.js | 1 - .../commands/generate/page/templates/page.tsx.template | 3 +++ packages/cli/src/commands/serve.js | 8 ++++---- .../src/generate/templates/api-globImports.d.ts.template | 1 + 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index 30f63498a7c6..50bb17240469 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -3,7 +3,8 @@ import path from 'path' import execa from 'execa' import { Listr } from 'listr2' -import rimraf from 'rimraf' +import { rimraf } from 'rimraf' +import terminalLink from 'terminal-link' import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers' import { buildApi } from '@redwoodjs/internal/dist/build/api' @@ -12,7 +13,7 @@ import { detectPrerenderRoutes } from '@redwoodjs/prerender/detection' import { timedTelemetry } from '@redwoodjs/telemetry' import { buildFeServer } from '@redwoodjs/vite' -import { getConfig, getPaths } from '../lib' +import { getPaths, getConfig } from '../lib' import { generatePrismaCommand } from '../lib/generatePrismaClient' export const handler = async ({ diff --git a/packages/cli/src/commands/devHandler.js b/packages/cli/src/commands/devHandler.js index bfe1c40e34d6..3e356e73688d 100644 --- a/packages/cli/src/commands/devHandler.js +++ b/packages/cli/src/commands/devHandler.js @@ -63,7 +63,6 @@ export const handler = async ({ if (forwardedPortMatches.length) { webPreferredPort = parseInt(forwardedPortMatches.pop().groups.port) } - webAvailablePort = await getFreePort(webPreferredPort, [ apiPreferredPort, apiAvailablePort, diff --git a/packages/cli/src/commands/generate/page/templates/page.tsx.template b/packages/cli/src/commands/generate/page/templates/page.tsx.template index 1b1b3ff61177..fc16315a0a96 100644 --- a/packages/cli/src/commands/generate/page/templates/page.tsx.template +++ b/packages/cli/src/commands/generate/page/templates/page.tsx.template @@ -1,4 +1,5 @@ import { Link, routes } from '@redwoodjs/router' +import { MetaTags } from '@redwoodjs/web' <% if (paramName !== '') { %> type ${pascalName}PageProps = { ${paramName}: ${paramType} @@ -7,6 +8,8 @@ type ${pascalName}PageProps = { const ${pascalName}Page = (<%- paramName === '' ? '' : `${propParam}: ${pascalName}PageProps` %>) => { return ( <> + +

${pascalName}Page

Find me in ${outputPath} diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index 5111c4df9bb2..9d7a82d2ccca 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -118,7 +118,7 @@ export const builder = async (yargs) => { if ( positionalArgs.includes('web') && - !fs.existsSync(path.join(getPaths().web.dist), 'index.html') + !fs.existsSync(path.join(redwoodProjectPaths.web.dist), 'index.html') ) { console.error( c.error( @@ -130,7 +130,7 @@ export const builder = async (yargs) => { if ( positionalArgs.includes('api') && - !fs.existsSync(path.join(getPaths().api.dist)) + !fs.existsSync(path.join(redwoodProjectPaths.api.dist)) ) { console.error( c.error( @@ -143,8 +143,8 @@ export const builder = async (yargs) => { if ( // serve both positionalArgs.length === 1 && - (!fs.existsSync(path.join(getPaths().api.dist)) || - !fs.existsSync(path.join(getPaths().web.dist), 'index.html')) + (!fs.existsSync(path.join(redwoodProjectPaths.api.dist)) || + !fs.existsSync(path.join(redwoodProjectPaths.web.dist), 'index.html')) ) { console.error( c.error( diff --git a/packages/internal/src/generate/templates/api-globImports.d.ts.template b/packages/internal/src/generate/templates/api-globImports.d.ts.template index a843cb4cff47..ada756867205 100644 --- a/packages/internal/src/generate/templates/api-globImports.d.ts.template +++ b/packages/internal/src/generate/templates/api-globImports.d.ts.template @@ -1,6 +1,7 @@ declare module 'src/services/**/*.{js,ts}' declare module 'src/directives/**/*.{js,ts}' declare module 'src/graphql/**/*.sdl.{js,ts}' +declare module 'src/subscriptions/**/*.{js,ts}' declare module 'api/src/services/**/*.{js,ts}' From 0268f2fe550f5d52252af382e680c81c61027036 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Sun, 25 Jun 2023 20:39:25 +0200 Subject: [PATCH 07/26] Limit code churn project.mjs --- tasks/framework-tools/lib/project.mjs | 28 ++++++++++++--------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/tasks/framework-tools/lib/project.mjs b/tasks/framework-tools/lib/project.mjs index d9efe9f348e8..4a93e0194604 100644 --- a/tasks/framework-tools/lib/project.mjs +++ b/tasks/framework-tools/lib/project.mjs @@ -23,15 +23,14 @@ export function fixProjectBinaries(projectPath) { const bins = getFrameworkPackagesBins() for (let [binName, binPath] of Object.entries(bins)) { - try { - // if the binPath doesn't exist, create it. - const binSymlink = path.join(projectPath, 'node_modules/.bin', binName) - binPath = path.join(projectPath, 'node_modules', binPath) + // if the binPath doesn't exist, create it. + const binSymlink = path.join(projectPath, 'node_modules/.bin', binName) + binPath = path.join(projectPath, 'node_modules', binPath) - if (!fs.existsSync(binSymlink)) { - fs.mkdirSync(path.dirname(binSymlink), { - recursive: true, - }) + if (!fs.existsSync(binSymlink)) { + fs.mkdirSync(path.dirname(binSymlink), { + recursive: true, + }) // `fs.existsSync` checks if the target of the symlink exists, not the symlink. If the symlink exists, // we have to remove it before we can fix it. As far as I can tell, there's no way to check if a symlink exists but not its target, @@ -44,15 +43,12 @@ export function fixProjectBinaries(projectPath) { } } - fs.symlinkSync(binPath, binSymlink) - } - - console.log('chmod +x', terminalLink(binName, binPath)) - fs.chmodSync(binSymlink, '755') - fs.chmodSync(binPath, '755') - } catch (e) { - console.error(e) + fs.symlinkSync(binPath, binSymlink) } + + console.log('chmod +x', terminalLink(binName, binPath)) + fs.chmodSync(binSymlink, '755') + fs.chmodSync(binPath, '755') } } From fbbfdeb30684a91f73d3320bb1343a75609e81d6 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Sun, 25 Jun 2023 21:01:53 +0200 Subject: [PATCH 08/26] Merge serve.js with latest on main --- packages/cli/src/commands/serve.js | 121 +++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 13 deletions(-) diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index 9d7a82d2ccca..61a417c34a6b 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -34,20 +34,39 @@ const streamServerErrorHandler = () => { ) } -export const builder = async (yargs) => { +export async function builder(yargs) { const redwoodProjectPaths = getPaths() const redwoodProjectConfig = getConfig() - const { apiCliOptions, webCliOptions, commonOptions, apiServerHandler } = - await import('@redwoodjs/api-server') - yargs .usage('usage: $0 ') .command({ command: '$0', - descriptions: 'Run both api and web servers', - handler: streamServerErrorHandler, - builder: (yargs) => yargs.options(commonOptions), + descriptions: 'Run both api and web servers. Uses the web port and host', + handler: (argv) => { + recordTelemetryAttributes({ + command, + port: argv.port, + host: argv.host, + socket: argv.socket, + apiHost: argv.apiHost, + }) + + streamServerErrorHandler() + }, + builder: (yargs) => + yargs.options({ + port: { + default: redwoodProjectConfig.web.port, + type: 'number', + alias: 'p', + }, + host: { + default: redwoodProjectConfig.web.host, + type: 'string', + }, + socket: { type: 'string' }, + }), }) .command({ command: 'both', @@ -102,15 +121,91 @@ export const builder = async (yargs) => { }) .command({ command: 'api', - description: 'start server for serving only the api', - handler: apiServerHandler, - builder: (yargs) => yargs.options(apiCliOptions), + description: 'Start server for serving only the api', + builder: (yargs) => + yargs.options({ + port: { + default: redwoodProjectConfig.api.port, + type: 'number', + alias: 'p', + }, + host: { + default: redwoodProjectConfig.api.host, + type: 'string', + }, + socket: { type: 'string' }, + apiRootPath: { + alias: ['api-root-path', 'rootPath', 'root-path'], + default: '/', + type: 'string', + desc: 'Root path where your api functions are served', + coerce: coerceRootPath, + }, + }), + handler: async (argv) => { + recordTelemetryAttributes({ + command, + port: argv.port, + host: argv.host, + socket: argv.socket, + apiRootPath: argv.apiRootPath, + }) + + // Run the experimental server file, if it exists, api side only + if (hasExperimentalServerFile()) { + console.log( + [ + separator, + `๐Ÿงช ${chalk.green('Experimental Feature')} ๐Ÿงช`, + separator, + 'Using the experimental API server file at api/dist/server.js', + separator, + ].join('\n') + ) + await execa('yarn', ['node', path.join('dist', 'server.js')], { + cwd: redwoodProjectPaths.api.base, + stdio: 'inherit', + shell: true, + }) + return + } + + const { apiServerHandler } = await import('./serveHandler.js') + await apiServerHandler(argv) + }, }) .command({ command: 'web', - description: 'start server for serving only the web side', - handler: streamServerErrorHandler, - builder: (yargs) => yargs.options(webCliOptions), + description: 'Start server for serving only the web side', + builder: (yargs) => + yargs.options({ + port: { + default: redwoodProjectConfig.web.port, + type: 'number', + alias: 'p', + }, + host: { + default: redwoodProjectConfig.web.host, + type: 'string', + }, + socket: { type: 'string' }, + apiHost: { + alias: 'api-host', + type: 'string', + desc: 'Forward requests from the apiUrl, defined in redwood.toml to this host', + }, + }), + handler: async (argv) => { + recordTelemetryAttributes({ + command, + port: argv.port, + host: argv.host, + socket: argv.socket, + apiHost: argv.apiHost, + }) + + streamServerErrorHandler() + }, }) .middleware((argv) => { // Make sure the relevant side has been built, before serving From f29f9dd2af9e677302a3af6735928bd28b5232ab Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Mon, 26 Jun 2023 18:46:59 +0200 Subject: [PATCH 09/26] babel common.ts: Undo custom plugin names to reduce churn --- packages/internal/src/build/babel/common.ts | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/packages/internal/src/build/babel/common.ts b/packages/internal/src/build/babel/common.ts index ddb4d1d4d5e7..3b3ab67f4853 100644 --- a/packages/internal/src/build/babel/common.ts +++ b/packages/internal/src/build/babel/common.ts @@ -62,24 +62,12 @@ if (!RUNTIME_CORE_JS_VERSION) { export const getCommonPlugins = () => { return [ - [ - '@babel/plugin-proposal-class-properties', - { loose: true }, - 'rw-class-properties', - ], + ['@babel/plugin-proposal-class-properties', { loose: true }], // Note: The private method loose mode configuration setting must be the // same as @babel/plugin-proposal class-properties. // (https://babeljs.io/docs/en/babel-plugin-proposal-private-methods#loose) - [ - '@babel/plugin-proposal-private-methods', - { loose: true }, - 'rw-private-methods', - ], - [ - '@babel/plugin-proposal-private-property-in-object', - { loose: true }, - 'rw-private-prop-in-object', - ], + ['@babel/plugin-proposal-private-methods', { loose: true }], + ['@babel/plugin-proposal-private-property-in-object', { loose: true }], ] } From 12bf302b0c833b6871766ab364c27efe70c38c56 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Tue, 27 Jun 2023 15:14:09 +0200 Subject: [PATCH 10/26] Resolve getRouteHookBabelPlugins comment --- packages/internal/src/build/babel/common.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/internal/src/build/babel/common.ts b/packages/internal/src/build/babel/common.ts index 3b3ab67f4853..777612b3fc9d 100644 --- a/packages/internal/src/build/babel/common.ts +++ b/packages/internal/src/build/babel/common.ts @@ -71,7 +71,8 @@ export const getCommonPlugins = () => { ] } -// @TODO double check this, think about it more carefully please! +// TODO (STREAMING) double check this, think about it more carefully please! +// It's related to yarn workspaces to be or not to be export const getRouteHookBabelPlugins = () => { return [ ...getWebSideBabelPlugins({ From 86710c3e650d1f275a73908159de43b5d3f2504c Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Tue, 27 Jun 2023 15:15:19 +0200 Subject: [PATCH 11/26] Use @TODO for GitHub highlighting to work --- packages/internal/src/build/babel/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/internal/src/build/babel/common.ts b/packages/internal/src/build/babel/common.ts index 777612b3fc9d..d87c66e1c7df 100644 --- a/packages/internal/src/build/babel/common.ts +++ b/packages/internal/src/build/babel/common.ts @@ -71,7 +71,7 @@ export const getCommonPlugins = () => { ] } -// TODO (STREAMING) double check this, think about it more carefully please! +// @TODO STREAMING double check this, think about it more carefully please! // It's related to yarn workspaces to be or not to be export const getRouteHookBabelPlugins = () => { return [ From 94aa4e5708e865d0eb59cbc1d7b1ece438ec7054 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Tue, 27 Jun 2023 15:43:19 +0200 Subject: [PATCH 12/26] TODO (STREAMING) everywhere --- packages/internal/src/build/babel/api.ts | 2 +- packages/internal/src/build/babel/common.ts | 2 +- packages/internal/src/routes.ts | 2 +- packages/router/src/active-route-loader.tsx | 2 +- packages/structure/src/model/RWRoute.ts | 1 + packages/vite/src/buildFeServer.ts | 11 +++++++---- packages/vite/src/devFeServer.ts | 11 ++++++++--- packages/vite/src/runFeServer.ts | 18 +++++++++--------- packages/vite/src/triggerRouteHooks.ts | 6 +++--- .../web/src/components/RedwoodProvider.tsx | 4 +++- packages/web/src/components/htmlTags.tsx | 6 +++--- packages/web/src/routeHooks.types.ts | 4 ++-- 12 files changed, 40 insertions(+), 29 deletions(-) diff --git a/packages/internal/src/build/babel/api.ts b/packages/internal/src/build/babel/api.ts index 2a9a8aca648e..ea0ddb8c7119 100644 --- a/packages/internal/src/build/babel/api.ts +++ b/packages/internal/src/build/babel/api.ts @@ -229,7 +229,7 @@ export const prebuildApiFile = ( return result } -// @TODO: I changed the prebuildApiFile function in https://github.com/redwoodjs/redwood/pull/7672/files +// TODO (STREAMING) I changed the prebuildApiFile function in https://github.com/redwoodjs/redwood/pull/7672/files // but we had to revert. For this branch temporarily, I'm going to add a new function // This is used in building routeHooks export const transformWithBabel = ( diff --git a/packages/internal/src/build/babel/common.ts b/packages/internal/src/build/babel/common.ts index d87c66e1c7df..777612b3fc9d 100644 --- a/packages/internal/src/build/babel/common.ts +++ b/packages/internal/src/build/babel/common.ts @@ -71,7 +71,7 @@ export const getCommonPlugins = () => { ] } -// @TODO STREAMING double check this, think about it more carefully please! +// TODO (STREAMING) double check this, think about it more carefully please! // It's related to yarn workspaces to be or not to be export const getRouteHookBabelPlugins = () => { return [ diff --git a/packages/internal/src/routes.ts b/packages/internal/src/routes.ts index 363680d11916..21e460cd8fa6 100644 --- a/packages/internal/src/routes.ts +++ b/packages/internal/src/routes.ts @@ -104,7 +104,7 @@ export const getProjectRoutes = (): RouteSpec[] => { renderMode: route.renderMode, matchRegexString: matchRegexString, paramNames: routeParams, - // @TODO deal with permanent/temp later + // TODO (STREAMING) deal with permanent/temp later redirect: route.redirect ? { to: route.redirect, permanent: false } : null, diff --git a/packages/router/src/active-route-loader.tsx b/packages/router/src/active-route-loader.tsx index c8ab61607ad6..1d3c1e5a7cb7 100644 --- a/packages/router/src/active-route-loader.tsx +++ b/packages/router/src/active-route-loader.tsx @@ -14,7 +14,7 @@ interface Props { const isPrerendered = false -// @MARK @TODO +// TODO (STREAMING) // SSR and streaming changes how we mount the React app (we render the whole page, including head and body) // This logic is no longer valid and needs to be rethought diff --git a/packages/structure/src/model/RWRoute.ts b/packages/structure/src/model/RWRoute.ts index f7e684fbe466..fbe67fbd5f9a 100644 --- a/packages/structure/src/model/RWRoute.ts +++ b/packages/structure/src/model/RWRoute.ts @@ -144,6 +144,7 @@ export class RWRoute extends BaseNode { return this.getBoolAttr('prerender') } + // TODO (STREAMING) Remove this once we're sure we don't want to do Render Modes @lazy() get renderMode(): string | undefined { return this.getStringAttr('renderMode') || 'stream' } diff --git a/packages/vite/src/buildFeServer.ts b/packages/vite/src/buildFeServer.ts index 72469f6c76d7..10a64e9f2ff4 100644 --- a/packages/vite/src/buildFeServer.ts +++ b/packages/vite/src/buildFeServer.ts @@ -36,6 +36,8 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { // Step 1A: Generate the client bundle await buildWeb({ verbose }) + // TODO (STREAMING) When Streaming is released Vite will be the only bundler, + // so we can switch to a regular import // @NOTE: Using dynamic import, because vite is still opt-in const { build } = await import('vite') @@ -58,7 +60,7 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { setup(build: PluginBuild) { build.onLoad({ filter: /\.(js|ts|tsx|jsx)$/ }, async (args) => { // Remove RedwoodJS "magic" from a user's code leaving JavaScript behind. - // @TODO: We need the new transformWithBabel function in https://github.com/redwoodjs/redwood/pull/7672/files + // TODO (STREAMING) We need the new transformWithBabel function in https://github.com/redwoodjs/redwood/pull/7672/files const transformedCode = transformWithBabel(args.path, [ ...getRouteHookBabelPlugins(), ]) @@ -80,7 +82,7 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { entryPoints: allRouteHooks, platform: 'node', target: 'node16', - // @MARK Disable splitting and esm, because Redwood web modules dont support esm yet + // @MARK Disable splitting and esm, because Redwood web modules don't support esm yet // outExtension: { '.js': '.mjs' }, // format: 'esm', // splitting: true, @@ -92,7 +94,7 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { }) // Step 3: Generate route-manifest.json - // @TODO double check why we need to do .default here + // TODO (STREAMING) double check why we need to do .default here // Its related to the babel import assertion plugin most likely const clientBuildManifest: ViteManifest = ( await import(path.join(getPaths().web.dist, 'build-manifest.json'), { @@ -110,6 +112,7 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { : null, matchRegexString: route.matchRegexString, // @NOTE this is the path definition, not the actual path + // E.g. /blog/post/{id:Int} pathDefinition: route.path, hasParams: route.hasParams, routeHooks: FIXME_constructRouteHookPath(route.routeHooks), @@ -127,7 +130,7 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { await fs.writeFile(rwPaths.web.routeManifest, JSON.stringify(routeManifest)) } -// @TODO @MARK Hacky work around because when you don't have a App.routeHook, esbuild doesn't create +// TODO (STREAMING) Hacky work around because when you don't have a App.routeHook, esbuild doesn't create // the pages folder in the dist/server/routeHooks directory. // @MARK need to change to .mjs here if we use esm const FIXME_constructRouteHookPath = (rhSrcPath: string | null | undefined) => { diff --git a/packages/vite/src/devFeServer.ts b/packages/vite/src/devFeServer.ts index 04b79feb4bcf..7dcfc7d3603f 100644 --- a/packages/vite/src/devFeServer.ts +++ b/packages/vite/src/devFeServer.ts @@ -1,3 +1,4 @@ +// TODO (STREAMING) Merge with runFeServer so we only have one file import path from 'path' import express from 'express' @@ -15,13 +16,16 @@ import { stripQueryStringAndHashFromPath } from './utils' // These values are defined in the vite.config.ts globalThis.RWJS_ENV = {} -// @MARK, @TODO Just so it doesn't error out. Not sure how to handle this. +// TODO (STREAMING) Just so it doesn't error out. Not sure how to handle this. globalThis.__REDWOOD__PRERENDER_PAGES = {} async function createServer() { const app = express() const rwPaths = getPaths() + // TODO (STREAMING) When Streaming is released Vite will be the only bundler, + // and this file should always exist. So the error message needs to change + // (or be removed perhaps) // @MARK: Vite is still experimental, and opt-in if (!rwPaths.web.viteConfig) { throw new Error( @@ -90,7 +94,7 @@ async function createServer() { } if (!currentRoute) { - // @TODO do something + // TODO (STREAMING) do something } if (!rwPaths.web.entryServer || !rwPaths.web.entryClient) { @@ -107,7 +111,7 @@ async function createServer() { // Serialize route context so it can be passed to the client entry const serializedRouteContext = JSON.stringify(serverData) - // @TODO CSS is handled by Vite in dev mode, we don't need to worry about it in dev + // TODO (STREAMING) CSS is handled by Vite in dev mode, we don't need to worry about it in dev // but..... it causes a flash of unstyled content. For now I'm just injecting index css here const FIXME_HardcodedIndexCss = ['index.css'] @@ -145,6 +149,7 @@ async function createServer() { } ) } catch (e) { + // TODO (STREAMING) Is this what we want to do? // send back a SPA page // res.status(200).set({ 'Content-Type': 'text/html' }).end(template) diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index facb146d2ab3..bf54a1896262 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -19,7 +19,7 @@ import { stripQueryStringAndHashFromPath } from './utils' globalThis.RWJS_ENV = {} /** - * @MARK @TODO + * TODO (STREAMING) * We have this server in the vite package only temporarily. * We will need to decide where to put it, so that rwjs/internal and other heavy dependencies * can be removed from the final docker image @@ -44,14 +44,14 @@ export async function runFeServer() { const rwPaths = getPaths() const rwConfig = getConfig() - // @TODO @MARK figure out why we're having to do default here + // TODO (STREAMING) figure out why we're having to do default here const routeManifest: RWRouteManifest = ( await import(rwPaths.web.dist + '/server/route-manifest.json', { assert: { type: 'json' }, }) ).default - // @TODO @MARK figure out why we're having to do default here + // TODO (STREAMING) figure out why we're having to do default here const buildManifest: ViteManifest = ( await import(rwPaths.web.dist + '/build-manifest.json', { assert: { type: 'json' }, @@ -71,7 +71,7 @@ export async function runFeServer() { app.use('/assets', express.static(rwPaths.web.dist + '/assets')) // ๐Ÿ‘‰ 2. Proxy the api server - // @TODO we need to be able to specify whether proxying is required or not + // TODO (STREAMING) we need to be able to specify whether proxying is required or not // e.g. deploying to Netlify, we don't need to proxy but configure it in Netlify // Also be careful of differences between v2 and v3 of the server app.use( @@ -100,7 +100,7 @@ export async function runFeServer() { path.join(rwPaths.web.distServer, '/entry-server.js') ) - // @MARK should we generate individual express Routes for each Route? + // TODO (STREAMING) should we generate individual express Routes for each Route? // This would make handling 404s and favicons / public assets etc. easier const currentRoute = Object.values(routeManifest).find((route) => { if (!route.matchRegexString) { @@ -117,7 +117,7 @@ export async function runFeServer() { // Doesn't match any of the defined Routes // Render 404 page, and send back 404 status if (!currentRoute) { - // @MARK should we CONST it? + // TODO (STREAMING) should we CONST it? const fourOhFourRoute = routeManifest['notfound'] if (!fourOhFourRoute) { @@ -155,7 +155,7 @@ export async function runFeServer() { let metaTags: TagDescriptor[] = [] if (currentRoute?.redirect) { - // @TODO deal with permanent/temp + // TODO (STREAMING) deal with permanent/temp // Short-circuit, and return a 301 or 302 return res.redirect(currentRoute.redirect.to) } @@ -163,7 +163,7 @@ export async function runFeServer() { if (currentRoute) { // Make sure we access the dist routeHooks! const routeHookPaths = [ - // @TODO hardcoded JS file, watchout if we switch to ESM! + // TODO (STREAMING) hardcoded JS file, watchout if we switch to ESM! path.join(rwPaths.web.distRouteHooks, 'App.routeHooks.js'), currentRoute.routeHooks ? path.join(rwPaths.web.distRouteHooks, currentRoute.routeHooks) @@ -231,7 +231,7 @@ export async function runFeServer() { } ) - // @TODO make the timeout configurable + // TODO (STREAMING) make the timeout configurable setTimeout(() => { abort() }, 10_000) diff --git a/packages/vite/src/triggerRouteHooks.ts b/packages/vite/src/triggerRouteHooks.ts index 9e3dbf134578..551bde93ed7b 100644 --- a/packages/vite/src/triggerRouteHooks.ts +++ b/packages/vite/src/triggerRouteHooks.ts @@ -27,9 +27,9 @@ export const triggerRouteHooks = async ({ const event: RouteHookEvent = { params: parsedParams, headers: req.headers || {}, - query: req.query as any, // @TODO we should parse query parameters the same way as RW router - // cookies: req.cookies || {}, // @TODO we probably need some sort of cookie parser - // @TODO called app routeHook, but its just the previous output + query: req.query as any, // TODO (STREAMING) we should parse query parameters the same way as RW router + // cookies: req.cookies || {}, // TODO (STREAMING) we probably need some sort of cookie parser + // TODO (STREAMING) called app routeHook, but its just the previous output appRouteHook: previousOutput, } diff --git a/packages/web/src/components/RedwoodProvider.tsx b/packages/web/src/components/RedwoodProvider.tsx index d5944919a462..c46aa4ab3b1e 100644 --- a/packages/web/src/components/RedwoodProvider.tsx +++ b/packages/web/src/components/RedwoodProvider.tsx @@ -7,8 +7,10 @@ interface RedwoodProviderProps { export const RedwoodProvider = ({ children }: RedwoodProviderProps) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars - // @TODO disabling helmet here, because it clashes with meta routeHooks + // TODO (STREAMING) disabling helmet here, because it clashes with meta routeHooks // but still leaving helmet provider to make it easy to migrate to new setup + // TODO (STREAMING) Figure out how the Helmet stuff can live along side + // streaming while streaming is still experimental return ( {/* diff --git a/packages/web/src/components/htmlTags.tsx b/packages/web/src/components/htmlTags.tsx index 1f29b4de52d2..738a185f7b5d 100644 --- a/packages/web/src/components/htmlTags.tsx +++ b/packages/web/src/components/htmlTags.tsx @@ -58,8 +58,8 @@ interface Other extends Custom { tagType: string // link, script, etc } -// @MARK Maintaining the similar format to Remix's V2_MetaDescriptor -// 1. because I like it +// @MARK Maintaining a similar format to Remix's V2_MetaDescriptor +// 1. because I (Danny) like it // 2. because it'll feel consistent to people who are familiar with Remix // I've modified it a little bit, but we need to decide wether we want the // remix style DIY meta tags, or the more opinionated approach in MetaTags.tsx @@ -94,7 +94,7 @@ export const Meta = ({ tags = [] }: MetaProps) => { ) } - // @TODO add validate tag function + // TODO (STREAMING) add validate tag function if (otherTag(tag)) { const { tagType: TagName, ...rest } = tag return diff --git a/packages/web/src/routeHooks.types.ts b/packages/web/src/routeHooks.types.ts index 934062923b74..74f1baa0ed4e 100644 --- a/packages/web/src/routeHooks.types.ts +++ b/packages/web/src/routeHooks.types.ts @@ -8,8 +8,8 @@ export interface RouteHookEvent { params: Record // this has to be provided from RW router headers: Record query: Record - // cookies: Record @TODO pass in parsed cookies - // @MARK @TODO: this is the previous output, but we call it appRouteHook, we should rename it + // cookies: Record TODO (STREAMING) pass in parsed cookies + // TODO (STREAMING) this is the previous output, but we call it appRouteHook, we should rename it appRouteHook?: RouteHookOutput } From d48d7561d6eb22fc42801a3430dd17896d21fe5f Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Wed, 28 Jun 2023 16:32:50 +0200 Subject: [PATCH 13/26] after yarn install --- packages/vite/package.json | 2 +- yarn.lock | 954 +++++++++++++++++++------------------ 2 files changed, 502 insertions(+), 454 deletions(-) diff --git a/packages/vite/package.json b/packages/vite/package.json index 6ded0bd0bb1a..1400bb20a78f 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -47,8 +47,8 @@ "devDependencies": { "@babel/cli": "7.22.5", "@babel/plugin-syntax-import-assertions": "7.20.0", - "@types/yargs-parser": "21.0.0", "@types/express": "4", + "@types/yargs-parser": "21.0.0", "glob": "10.3.0", "jest": "29.5.0", "typescript": "5.1.3" diff --git a/yarn.lock b/yarn.lock index 878c04babb2c..c78779fc0987 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5,6 +5,13 @@ __metadata: version: 6 cacheKey: 8c0 +"@aashutoshrathi/word-wrap@npm:^1.2.3": + version: 1.2.6 + resolution: "@aashutoshrathi/word-wrap@npm:1.2.6" + checksum: 53c2b231a61a46792b39a0d43bc4f4f776bb4542aa57ee04930676802e5501282c2fc8aac14e4cd1f1120ff8b52616b6ff5ab539ad30aa2277d726444b71619f + languageName: node + linkType: hard + "@actions/cache@npm:3.2.1": version: 3.2.1 resolution: "@actions/cache@npm:3.2.1" @@ -110,12 +117,12 @@ __metadata: languageName: node linkType: hard -"@apollo/cache-control-types@npm:^1.0.2": - version: 1.0.2 - resolution: "@apollo/cache-control-types@npm:1.0.2" +"@apollo/cache-control-types@npm:^1.0.3": + version: 1.0.3 + resolution: "@apollo/cache-control-types@npm:1.0.3" peerDependencies: graphql: 14.x || 15.x || 16.x - checksum: 685b29a3f68d4690fd6e7fd277a5dc4b26f4b65843a67e66b9c012981db9b979e690169acd04eb5196770cebc0c0ac7f987aee25f0b73f9e527b47bf6455fcea + checksum: b49a9e99c7d5af6dfe12b775eb6374c8a54894e17ffa882b3d85f4501ca19ee413bdcc1a787a4b44dcc2903ce2c28f19b69116f338f88670c4f6f2e10a0bc498 languageName: node linkType: hard @@ -178,33 +185,33 @@ __metadata: languageName: node linkType: hard -"@apollo/server-gateway-interface@npm:^1.1.0": - version: 1.1.0 - resolution: "@apollo/server-gateway-interface@npm:1.1.0" +"@apollo/server-gateway-interface@npm:^1.1.1": + version: 1.1.1 + resolution: "@apollo/server-gateway-interface@npm:1.1.1" dependencies: - "@apollo/usage-reporting-protobuf": ^4.0.0 + "@apollo/usage-reporting-protobuf": ^4.1.1 "@apollo/utils.fetcher": ^2.0.0 "@apollo/utils.keyvaluecache": ^2.1.0 "@apollo/utils.logger": ^2.0.0 peerDependencies: graphql: 14.x || 15.x || 16.x - checksum: 27745253bed0b65e532eec95b184c1b10df0238c51b4975f98d18de1365e1e55003a37d544bc58a1807653710c030a1b98a99fb7cf55a6529151136b3ce7ef90 + checksum: 2787b2954028f5aff55846df98b3967f38f40df4c5e4c9df0da56ac16d4323ba0aeabd76d4b134fedc9f6fe7d63e6fd9e9a133eb5d209408eac34c0e25cbe7dd languageName: node linkType: hard "@apollo/server@npm:^4.0.0": - version: 4.7.1 - resolution: "@apollo/server@npm:4.7.1" + version: 4.7.5 + resolution: "@apollo/server@npm:4.7.5" dependencies: - "@apollo/cache-control-types": ^1.0.2 - "@apollo/server-gateway-interface": ^1.1.0 - "@apollo/usage-reporting-protobuf": ^4.1.0 + "@apollo/cache-control-types": ^1.0.3 + "@apollo/server-gateway-interface": ^1.1.1 + "@apollo/usage-reporting-protobuf": ^4.1.1 "@apollo/utils.createhash": ^2.0.0 "@apollo/utils.fetcher": ^2.0.0 "@apollo/utils.isnodelike": ^2.0.0 "@apollo/utils.keyvaluecache": ^2.1.0 "@apollo/utils.logger": ^2.0.0 - "@apollo/utils.usagereporting": ^2.0.0 + "@apollo/utils.usagereporting": ^2.1.0 "@apollo/utils.withrequired": ^2.0.0 "@graphql-tools/schema": ^9.0.0 "@josephg/resolvable": ^1.0.0 @@ -224,16 +231,16 @@ __metadata: whatwg-mimetype: ^3.0.0 peerDependencies: graphql: ^16.6.0 - checksum: 804087b462bf4b00f8e5b51b4450197e12621da5b96a7507634632e4fa591eeffc49f12125d331c67824cc27bcf5fd72187dcd67350abf4ae78af752b4d68d11 + checksum: 6a260d000866945b83ddccf5eed4bd64a77514a2fab73c4bff6935608083824fa2e140b13fd83edd74f34f7351ecd6bad92c8c853f82acc298f3d8e3eeaf351f languageName: node linkType: hard -"@apollo/usage-reporting-protobuf@npm:^4.0.0, @apollo/usage-reporting-protobuf@npm:^4.1.0": - version: 4.1.0 - resolution: "@apollo/usage-reporting-protobuf@npm:4.1.0" +"@apollo/usage-reporting-protobuf@npm:^4.1.0, @apollo/usage-reporting-protobuf@npm:^4.1.1": + version: 4.1.1 + resolution: "@apollo/usage-reporting-protobuf@npm:4.1.1" dependencies: "@apollo/protobufjs": 1.2.7 - checksum: 58772a2d679130ca0cb2b4700ed6a3175dbc501ca1af08b2907afd90ca6cf758981619cc0bc85ffc2e686647c56edd4a80d9ef394318a196c50c04e66fb822c8 + checksum: 45f0167a87d4ae8a12124831ebb29905122d28afdbfa23a4f25f4570189d5ddaa6f2829ef97923f5909b9753e39dbd28f810ca2a93ad9fcd60b2baf5669f5223 languageName: node linkType: hard @@ -325,11 +332,11 @@ __metadata: languageName: node linkType: hard -"@apollo/utils.usagereporting@npm:^2.0.0": - version: 2.0.1 - resolution: "@apollo/utils.usagereporting@npm:2.0.1" +"@apollo/utils.usagereporting@npm:^2.1.0": + version: 2.1.0 + resolution: "@apollo/utils.usagereporting@npm:2.1.0" dependencies: - "@apollo/usage-reporting-protobuf": ^4.0.0 + "@apollo/usage-reporting-protobuf": ^4.1.0 "@apollo/utils.dropunuseddefinitions": ^2.0.1 "@apollo/utils.printwithreducedwhitespace": ^2.0.1 "@apollo/utils.removealiases": 2.0.1 @@ -337,7 +344,7 @@ __metadata: "@apollo/utils.stripsensitiveliterals": ^2.0.1 peerDependencies: graphql: 14.x || 15.x || 16.x - checksum: eac3ce29a29fcd109a588f2ce1d367ec0b13d138087835f2d054a06683fff13270ddfcc903fa614abc7f3c0e2ce5fd7a4c8eec5413412762074274d29d8959d2 + checksum: 5c2b06a14c5094d0ee8eab7ff78449da1efff3bb4c82ef311b2bb90190437c6c59f2783702a428775f394f12455a53a9723e625e53e18e47b423df8cb9eb26d8 languageName: node linkType: hard @@ -424,8 +431,8 @@ __metadata: linkType: hard "@azure/core-http@npm:^3.0.0": - version: 3.0.1 - resolution: "@azure/core-http@npm:3.0.1" + version: 3.0.2 + resolution: "@azure/core-http@npm:3.0.2" dependencies: "@azure/abort-controller": ^1.0.0 "@azure/core-auth": ^1.3.0 @@ -441,7 +448,7 @@ __metadata: tunnel: ^0.0.6 uuid: ^8.3.0 xml2js: ^0.5.0 - checksum: 3e74fa4f7aab2b5f3fe2256b0e922f331c21f1367f3e1e069802126d3e3ef3235f9df07180919acd82b9ea5869d42ea55cd73ee31cf0fcf9db4a2c5fa3607b6a + checksum: 2dacb199bb77b07bc3cf8d3e9426e0ddec0de4a105f1f38a85d13c3e438bf34c29c1bd9a7e54d36483162ec9ddb6d0081caeb924445c0689868f432f5ccdc6cc languageName: node linkType: hard @@ -849,7 +856,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.16.7, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.21.5, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.16.7, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.18.9, @babel/helper-plugin-utils@npm:^7.19.0, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.21.5, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": version: 7.22.5 resolution: "@babel/helper-plugin-utils@npm:7.22.5" checksum: d2c4bfe2fa91058bcdee4f4e57a3f4933aed7af843acfd169cd6179fab8d13c1d636474ecabb2af107dc77462c7e893199aa26632bac1c6d7e025a17cbb9d20d @@ -1316,14 +1323,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.18.6": - version: 7.21.4 - resolution: "@babel/plugin-syntax-flow@npm:7.21.4" +"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-syntax-flow@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 07afc7df02141597968532bfbfa3f6c0ad21a2bdd885d0e5e035dcf60fdf35f0995631c9750b464e1a6f2feea14160a82787f914e88e8f7115dc99f09853e43e + languageName: node + linkType: hard + +"@babel/plugin-syntax-import-assertions@npm:7.20.0": + version: 7.20.0 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.20.0" + dependencies: + "@babel/helper-plugin-utils": ^7.19.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ff6bd5e5b6064276fd18b8a2e9bafb4d8cdf95b7a06b34bc93cd4fa3b5dfcc482f830c1174cbb245c160c32beed2d4ac6b402be9b3b6962d40a032fda3f61c80 + checksum: 0ac0176984ad799b39264070007737c514ea95e4b3c3c515ecddef958629abcd3c8e8810fd60fb63de5a8f3f7022dd2c7af7580b819a9207acc372c8b8ec878e languageName: node linkType: hard @@ -1679,15 +1697,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-flow-strip-types@npm:^7.0.0, @babel/plugin-transform-flow-strip-types@npm:^7.21.0": - version: 7.21.0 - resolution: "@babel/plugin-transform-flow-strip-types@npm:7.21.0" +"@babel/plugin-transform-flow-strip-types@npm:^7.0.0, @babel/plugin-transform-flow-strip-types@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/plugin-syntax-flow": ^7.18.6 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/plugin-syntax-flow": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7d6c6a4de53c4106ed30cd32c769f340d048d7c4d01391eebd3ad71eabbd6910bd1d483bc23eebcfd9bb45d40cb9b743d916c0746cdedd952791a1222620b48c + checksum: 5949a8e5214e3fc65d31dab0551423cea9d9eef35faa5d0004707ba7347baf96166aa400907ce7498f754db4e1e9d039ca434a508546b0dc9fdae9a42e814c1a languageName: node linkType: hard @@ -2363,15 +2381,15 @@ __metadata: linkType: hard "@babel/preset-flow@npm:^7.13.13, @babel/preset-flow@npm:^7.18.6": - version: 7.21.4 - resolution: "@babel/preset-flow@npm:7.21.4" + version: 7.22.5 + resolution: "@babel/preset-flow@npm:7.22.5" dependencies: - "@babel/helper-plugin-utils": ^7.20.2 - "@babel/helper-validator-option": ^7.21.0 - "@babel/plugin-transform-flow-strip-types": ^7.21.0 + "@babel/helper-plugin-utils": ^7.22.5 + "@babel/helper-validator-option": ^7.22.5 + "@babel/plugin-transform-flow-strip-types": ^7.22.5 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 50ec8dc9a30ef7ba668e9872f2142bad4ecf7a9a37dfe323a28b7f1de3b2db861e4cf7737e9dfa1a433bd65c3a26d4da93d2efce4f83c39bb8114fcc010ec39f + checksum: d3a54fbaa6da304bedc08847876f23c4bd6f9b13eb8b675ae48c45c678066f7610437b16a8972209c5250bdb205bde8800b8055a844922488b899fdbfe295f31 languageName: node linkType: hard @@ -2454,11 +2472,11 @@ __metadata: linkType: hard "@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.9.2": - version: 7.22.3 - resolution: "@babel/runtime@npm:7.22.3" + version: 7.22.5 + resolution: "@babel/runtime@npm:7.22.5" dependencies: regenerator-runtime: ^0.13.11 - checksum: 097d0d6aaab0dea782d14f720a7383ea50fa87cba6c070495aea691739ea11459d80b4acd086a38d52894a2b15d4748dc8040dba3706aa18a8d5c8d896dec9b0 + checksum: 11dcaeecd2246857ccf22f939fcae28a58d29e410607bfa28b95d9b03e298a3e3df8a530e22637d5bfccfc1661fb39cc50c06b404b5d53454bd93889c7dd3eb8 languageName: node linkType: hard @@ -2623,17 +2641,17 @@ __metadata: linkType: hard "@clerk/backend@npm:^0.23.5": - version: 0.23.5 - resolution: "@clerk/backend@npm:0.23.5" + version: 0.23.6 + resolution: "@clerk/backend@npm:0.23.6" dependencies: - "@clerk/types": ^3.46.0 + "@clerk/types": ^3.46.1 "@peculiar/webcrypto": 1.4.1 "@types/node": 16.18.6 deepmerge: 4.2.2 node-fetch-native: 1.0.1 snakecase-keys: 5.4.4 tslib: 2.4.1 - checksum: dfddb681fc898d48a778e51958265fe6ee64aee3b15dc70e9e3a952f1a6cf1fa3705f8304c8b3f1939239e5fdd2d67187e393aeb5c4752d2c0bf3853c61168d3 + checksum: f0b2082c74e9360bca65e3b29153391eb932b9e93b11dd2e6fb80d5a3d925b3e0793600ef548fbe76b63d525440d08716c91ee8323072f88b7fa3c041b90fcec languageName: node linkType: hard @@ -2681,7 +2699,7 @@ __metadata: languageName: node linkType: hard -"@clerk/types@npm:3.46.0, @clerk/types@npm:^3.46.0": +"@clerk/types@npm:3.46.0": version: 3.46.0 resolution: "@clerk/types@npm:3.46.0" dependencies: @@ -2690,6 +2708,15 @@ __metadata: languageName: node linkType: hard +"@clerk/types@npm:^3.46.0, @clerk/types@npm:^3.46.1": + version: 3.46.1 + resolution: "@clerk/types@npm:3.46.1" + dependencies: + csstype: 3.1.1 + checksum: ed1c784b78517ca0cf770c12892ba26d61f551696497bba29a945b370a76b801a7f74e3ba2f93c72f28cc23ff5eb8504b9e317865637f8b0108659774fee68e0 + languageName: node + linkType: hard + "@colors/colors@npm:1.5.0": version: 1.5.0 resolution: "@colors/colors@npm:1.5.0" @@ -3443,9 +3470,9 @@ __metadata: linkType: hard "@fastify/error@npm:^3.0.0, @fastify/error@npm:^3.2.0": - version: 3.2.1 - resolution: "@fastify/error@npm:3.2.1" - checksum: d6626cbefa9caf42cda5347323031a5bb5e8ca9a2952f99d44e395f8e85f18a16593c60dcf0788cb936902f29e93c702c3999b29daa23ad3b25e2d04fb3cb5ea + version: 3.3.0 + resolution: "@fastify/error@npm:3.3.0" + checksum: b9651ad1b25781880343514bd4dfcbdb55e2459830a78ada73c0ac3dbf217161ee80af7245c7c7bfa370775d0beb146845c7314da13f478ff67520c8128ec3f0 languageName: node linkType: hard @@ -3470,8 +3497,8 @@ __metadata: linkType: hard "@fastify/reply-from@npm:^9.0.0": - version: 9.1.0 - resolution: "@fastify/reply-from@npm:9.1.0" + version: 9.4.0 + resolution: "@fastify/reply-from@npm:9.4.0" dependencies: "@fastify/error": ^3.0.0 end-of-stream: ^1.4.4 @@ -3480,7 +3507,7 @@ __metadata: pump: ^3.0.0 tiny-lru: ^11.0.0 undici: ^5.19.1 - checksum: 5a7c343d90393d8a545cf43c14f66c17c4533d903a9a0aded84428abaff9140dbd4e9d22bb3c18e184bdc4ddc0dd2a6807ace7ff233a8b2ac82e09a0fa97bdb8 + checksum: 2090866e5d381685cf553918921fb27cd229aa3aa9d03353f91facf2f0637ee66a56391704a0bcb88344d7f10ff0360c4159e7f31eca5fa181271474da8a0d31 languageName: node linkType: hard @@ -4029,7 +4056,7 @@ __metadata: languageName: node linkType: hard -"@gar/promisify@npm:^1.0.1, @gar/promisify@npm:^1.1.3": +"@gar/promisify@npm:^1.0.1": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" checksum: 0b3c9958d3cd17f4add3574975e3115ae05dc7f1298a60810414b16f6f558c137b5fb3cd3905df380bacfd955ec13f67c1e6710cbb5c246a7e8d65a8289b2bff @@ -4679,14 +4706,14 @@ __metadata: linkType: hard "@graphql-tools/utils@npm:^10.0.0": - version: 10.0.0 - resolution: "@graphql-tools/utils@npm:10.0.0" + version: 10.0.1 + resolution: "@graphql-tools/utils@npm:10.0.1" dependencies: "@graphql-typed-document-node/core": ^3.1.1 tslib: ^2.4.0 peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: b1666ade8fc289df6072a1725ebb4e7b925a1a85ca6832d53a4ada6d273248cc08bf035c35478cb8fd377d7e6ea1ad5b9060c98b380b5f37ce6d1ad3dff460b6 + checksum: c3562240f99543428fa960c1c9836225b33492e16a1ce0622ca71a3abbc3ef4e4f8e453cdb5cc32227e1866f1cdd9e20e09518f8354fa50c87164b2f793f03ae languageName: node linkType: hard @@ -4767,12 +4794,12 @@ __metadata: linkType: hard "@grpc/grpc-js@npm:~1.8.0": - version: 1.8.16 - resolution: "@grpc/grpc-js@npm:1.8.16" + version: 1.8.17 + resolution: "@grpc/grpc-js@npm:1.8.17" dependencies: "@grpc/proto-loader": ^0.7.0 "@types/node": ">=12.12.47" - checksum: d69b286d444535ae06f42845fcda9e807e296d0f1446ab0db319787f7ea9e520ef29c8484411ce1c0b12e65d66bd44c0f5497f3e7c1bc9ff0473d06e3cec9eea + checksum: 08e15d8795310dc45facf6af17708d92623380866cc0586cca766b3692abf6816a0cf7b9a9b4c3e6f1188c697df996244f64fd102c039271db5c63ff2d5981a8 languageName: node linkType: hard @@ -5162,7 +5189,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/source-map@npm:^0.3.2": +"@jridgewell/source-map@npm:^0.3.3": version: 0.3.3 resolution: "@jridgewell/source-map@npm:0.3.3" dependencies: @@ -5474,16 +5501,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/fs@npm:^2.1.0": - version: 2.1.2 - resolution: "@npmcli/fs@npm:2.1.2" - dependencies: - "@gar/promisify": ^1.1.3 - semver: ^7.3.5 - checksum: c50d087733d0d8df23be24f700f104b19922a28677aa66fdbe06ff6af6431cc4a5bb1e27683cbc661a5dafa9bafdc603e6a0378121506dfcd394b2b6dd76a187 - languageName: node - linkType: hard - "@npmcli/fs@npm:^3.1.0": version: 3.1.0 resolution: "@npmcli/fs@npm:3.1.0" @@ -5493,9 +5510,9 @@ __metadata: languageName: node linkType: hard -"@npmcli/git@npm:^4.0.0": - version: 4.0.4 - resolution: "@npmcli/git@npm:4.0.4" +"@npmcli/git@npm:^4.0.0, @npmcli/git@npm:^4.1.0": + version: 4.1.0 + resolution: "@npmcli/git@npm:4.1.0" dependencies: "@npmcli/promise-spawn": ^6.0.0 lru-cache: ^7.4.4 @@ -5505,7 +5522,7 @@ __metadata: promise-retry: ^2.0.1 semver: ^7.3.5 which: ^3.0.0 - checksum: 42a2a600c380adf141b6fe01a41ebbaab4c0f5541af58a79e66d7c62acca08ec1f5a9f0a636e3c63dad47000c4a80496b912f18a3af58f1a40624f283ef3fd00 + checksum: 78591ba8f03de3954a5b5b83533455696635a8f8140c74038685fec4ee28674783a5b34a3d43840b2c5f9aa37fd0dce57eaf4ef136b52a8ec2ee183af2e40724 languageName: node linkType: hard @@ -5555,16 +5572,6 @@ __metadata: languageName: node linkType: hard -"@npmcli/move-file@npm:^2.0.0": - version: 2.0.1 - resolution: "@npmcli/move-file@npm:2.0.1" - dependencies: - mkdirp: ^1.0.4 - rimraf: ^3.0.2 - checksum: 11b2151e6d1de6f6eb23128de5aa8a429fd9097d839a5190cb77aa47a6b627022c42d50fa7c47a00f1c9f8f0c1560092b09b061855d293fa0741a2a94cfb174d - languageName: node - linkType: hard - "@npmcli/name-from-folder@npm:^2.0.0": version: 2.0.0 resolution: "@npmcli/name-from-folder@npm:2.0.0" @@ -5580,14 +5587,16 @@ __metadata: linkType: hard "@npmcli/package-json@npm:^3.0.0": - version: 3.1.0 - resolution: "@npmcli/package-json@npm:3.1.0" + version: 3.1.1 + resolution: "@npmcli/package-json@npm:3.1.1" dependencies: + "@npmcli/git": ^4.1.0 glob: ^10.2.2 json-parse-even-better-errors: ^3.0.0 normalize-package-data: ^5.0.0 npm-normalize-package-bin: ^3.0.1 - checksum: e2d054a3c012fd180864d60afb2e66f2e8b0c5bb4ecad97371d288ff23fc668765be3c55e60c8b9cfb0231904536f639fdc5e9e37dd0e329ce8cf41bc87733a7 + proc-log: ^3.0.0 + checksum: fc3052a36cb65c011da75dfdb051b631557e5ccc7b25b64be87cb363e8f2e99d78fcf94495f456406ada2c75afaff8177a2a06a46594f15eb0b4e667110a415e languageName: node linkType: hard @@ -5622,12 +5631,12 @@ __metadata: languageName: node linkType: hard -"@nrwl/devkit@npm:16.3.2": - version: 16.3.2 - resolution: "@nrwl/devkit@npm:16.3.2" +"@nrwl/devkit@npm:16.4.0": + version: 16.4.0 + resolution: "@nrwl/devkit@npm:16.4.0" dependencies: - "@nx/devkit": 16.3.2 - checksum: b53edcbd65e24aa2232cae29389540ccd1db9d7a571cf8620b754ba7063a72bdb7c929a30627527f663bbef9c3d267b0bc2a3069609631e49136e60b6829668f + "@nx/devkit": 16.4.0 + checksum: 6828896c9a3d8ffb76c9e2cb1a0fe04ed69272ee88f59df987fff321685f5b5410016dfe302abf6afd300aab0057b9e94457224c7ca2bbaa3643fb57f7d27a22 languageName: node linkType: hard @@ -5651,19 +5660,19 @@ __metadata: languageName: node linkType: hard -"@nx/devkit@npm:16.3.2, @nx/devkit@npm:>=16.1.3 < 17": - version: 16.3.2 - resolution: "@nx/devkit@npm:16.3.2" +"@nx/devkit@npm:16.4.0, @nx/devkit@npm:>=16.1.3 < 17": + version: 16.4.0 + resolution: "@nx/devkit@npm:16.4.0" dependencies: - "@nrwl/devkit": 16.3.2 + "@nrwl/devkit": 16.4.0 ejs: ^3.1.7 ignore: ^5.0.4 - semver: 7.3.4 + semver: 7.5.3 tmp: ~0.2.1 tslib: ^2.3.0 peerDependencies: nx: ">= 15 <= 17" - checksum: ec6b4f7dca3449aabf2b7f9aab61ca6278185b6c1596d1bc555dc870104c10e408eb7a1e65b2dae4f2987ace4d9ff07ba5ba36ef6ad3f0da4b4115e6ed13d13d + checksum: edf2d3ae34eff7e78279c77e295ddfa00837f145dd107f136ab017f9075d8c05e7d83712fe075d6d4e6783ff62bf46cbe5b5f035b47e25c8e3d68407db2ceec3 languageName: node linkType: hard @@ -5738,8 +5747,8 @@ __metadata: linkType: hard "@octokit/app@npm:^13.1.5": - version: 13.1.5 - resolution: "@octokit/app@npm:13.1.5" + version: 13.1.8 + resolution: "@octokit/app@npm:13.1.8" dependencies: "@octokit/auth-app": ^4.0.13 "@octokit/auth-unauthenticated": ^3.0.0 @@ -5748,7 +5757,7 @@ __metadata: "@octokit/plugin-paginate-rest": ^6.0.0 "@octokit/types": ^9.0.0 "@octokit/webhooks": ^10.0.0 - checksum: deb79bbf29e1704e4981a8fe2344510a2e65a3f647331f03bd1d575803362dc33d78aee4b195c68bcee1787053de2a9b74b6cb75d69fc95eee5af9326fefbcbd + checksum: baf0382ff9e51d7e081745826e9b1b722ae4e3b27f7d6badafcc92e3daeb5eae7e368c6acf980d4a6f3c85ce17afe1a19c06abc8416ea48f0ac926f566054690 languageName: node linkType: hard @@ -5770,8 +5779,8 @@ __metadata: linkType: hard "@octokit/auth-oauth-app@npm:^5.0.0": - version: 5.0.5 - resolution: "@octokit/auth-oauth-app@npm:5.0.5" + version: 5.0.6 + resolution: "@octokit/auth-oauth-app@npm:5.0.6" dependencies: "@octokit/auth-oauth-device": ^4.0.0 "@octokit/auth-oauth-user": ^2.0.0 @@ -5780,25 +5789,25 @@ __metadata: "@types/btoa-lite": ^1.0.0 btoa-lite: ^1.0.0 universal-user-agent: ^6.0.0 - checksum: 6d74dfb63c2fa91d3f77aed7f929779364fb182b3f251302b77517946abff0bdd0f420cf15fd366a83a6fd8f553bbd6eed0040e37bc92ab9bbe8ee725e8b2aa6 + checksum: 94760dc9799c8a5b3f723892272b8852f8f15f5a1ff0d2eb4d145b984cb305622a625ffcc332f18f9359c6cc43ceb5fe07e31d4079e7b2a436ecbaed093ae986 languageName: node linkType: hard "@octokit/auth-oauth-device@npm:^4.0.0": - version: 4.0.4 - resolution: "@octokit/auth-oauth-device@npm:4.0.4" + version: 4.0.5 + resolution: "@octokit/auth-oauth-device@npm:4.0.5" dependencies: "@octokit/oauth-methods": ^2.0.0 "@octokit/request": ^6.0.0 "@octokit/types": ^9.0.0 universal-user-agent: ^6.0.0 - checksum: d114204e6dbbedad197e07fa99528138312d99207af1e8a266c700356c336b4e60e379af29e6e19e5d878d14330972108b7a62232b03d8421ea5d684561f10ad + checksum: e962835dcbb2138aa75077284968eb8e2d244859ed8c72dd0ecf2e55724c1bdedbe32e94bcd4f0a44c3e2fc382433ac10026ec0808b9b8bccece1741160227a1 languageName: node linkType: hard "@octokit/auth-oauth-user@npm:^2.0.0": - version: 2.1.1 - resolution: "@octokit/auth-oauth-user@npm:2.1.1" + version: 2.1.2 + resolution: "@octokit/auth-oauth-user@npm:2.1.2" dependencies: "@octokit/auth-oauth-device": ^4.0.0 "@octokit/oauth-methods": ^2.0.0 @@ -5806,16 +5815,14 @@ __metadata: "@octokit/types": ^9.0.0 btoa-lite: ^1.0.0 universal-user-agent: ^6.0.0 - checksum: b5ded133df1b6ea0759301272b10b6d3de1ce83cf185cec894ba2197538d32c3f131a3b5cf83d3522450a0d6a2ac2ec360ef19415f1b358fe0ed4c65a13cc261 + checksum: 3adc7aa7cf277d50572120be22832a4ef2f88103371d888be6ad3a9d58b4b40f3c2e3b3dca4df583dd4c48f45ed0c4825c426fc1ff8a4570e9cba2857004452e languageName: node linkType: hard "@octokit/auth-token@npm:^3.0.0": - version: 3.0.3 - resolution: "@octokit/auth-token@npm:3.0.3" - dependencies: - "@octokit/types": ^9.0.0 - checksum: ff33a5bbfcef8f9303d5fb7fd4757828490efe893ebe894f4ae5faa7bd37cc8d732408ce5f565bb6ad476f0d601ac3205b2256077530caebc7bac80dab8e4770 + version: 3.0.4 + resolution: "@octokit/auth-token@npm:3.0.4" + checksum: abdf5e2da36344de9727c70ba782d58004f5ae1da0f65fa9bc9216af596ef23c0e4675f386df2f6886806612558091d603564051b693b0ad1986aa6160b7a231 languageName: node linkType: hard @@ -5830,8 +5837,8 @@ __metadata: linkType: hard "@octokit/core@npm:^4.0.0, @octokit/core@npm:^4.2.1": - version: 4.2.1 - resolution: "@octokit/core@npm:4.2.1" + version: 4.2.4 + resolution: "@octokit/core@npm:4.2.4" dependencies: "@octokit/auth-token": ^3.0.0 "@octokit/graphql": ^5.0.0 @@ -5840,18 +5847,18 @@ __metadata: "@octokit/types": ^9.0.0 before-after-hook: ^2.2.0 universal-user-agent: ^6.0.0 - checksum: b21f60d1ceb8a1aa8cc1573718de2941aad1d2ca5c46ed4b6a2feec4830463efd32434e9452655455f6e6ea0a9fe030d4a09c1b7e0be7cd194afb51dade405e9 + checksum: e54081a56884e628d1804837fddcd48c10d516117bb891551c8dc9d8e3dad449aeb9b4677ca71e8f0e76268c2b7656c953099506679aaa4666765228474a3ce6 languageName: node linkType: hard "@octokit/endpoint@npm:^7.0.0": - version: 7.0.5 - resolution: "@octokit/endpoint@npm:7.0.5" + version: 7.0.6 + resolution: "@octokit/endpoint@npm:7.0.6" dependencies: "@octokit/types": ^9.0.0 is-plain-object: ^5.0.0 universal-user-agent: ^6.0.0 - checksum: 68de3e40b4d2b4d3decfc3e23480d5a781275ebf86d084a38ba70c5d46a6cad051b63332da1768a64d58b0b810c5b57401a3892dff4dd0060d8b6b31d78fc2f5 + checksum: fd147a55010b54af7567bf90791359f7096a1c9916a2b7c72f8afd0c53141338b3d78da3a4ab3e3bdfeb26218a1b73735432d8987ccc04996b1019219299f115 languageName: node linkType: hard @@ -5867,8 +5874,8 @@ __metadata: linkType: hard "@octokit/oauth-app@npm:^4.0.7, @octokit/oauth-app@npm:^4.2.1": - version: 4.2.2 - resolution: "@octokit/oauth-app@npm:4.2.2" + version: 4.2.4 + resolution: "@octokit/oauth-app@npm:4.2.4" dependencies: "@octokit/auth-oauth-app": ^5.0.0 "@octokit/auth-oauth-user": ^2.0.0 @@ -5879,7 +5886,7 @@ __metadata: "@types/aws-lambda": ^8.10.83 fromentries: ^1.3.1 universal-user-agent: ^6.0.0 - checksum: d6caa25fc3188afdcf06aa883df88d89d9668ba3a4525162486113b7c98ab5a46e2640d05b4cefd929db7c4d62e967f737d287bb97be4f12632c152da68f9085 + checksum: a39e7627790594797e64ef337fe82fcca239eb3f01957154ce4a558edb24e868526003007608ace80b72dfe03fdd3e3d7ba123681be22cf5b4cbb1c2acfbb97d languageName: node linkType: hard @@ -5891,22 +5898,15 @@ __metadata: linkType: hard "@octokit/oauth-methods@npm:^2.0.0": - version: 2.0.5 - resolution: "@octokit/oauth-methods@npm:2.0.5" + version: 2.0.6 + resolution: "@octokit/oauth-methods@npm:2.0.6" dependencies: "@octokit/oauth-authorization-url": ^5.0.0 "@octokit/request": ^6.2.3 "@octokit/request-error": ^3.0.3 "@octokit/types": ^9.0.0 btoa-lite: ^1.0.0 - checksum: 4a51cc8580f4246f95a0c5c6c5d31ab4846cf1757b7da2776263bd93f2f3ba940fb4367bdc9a3ae59a5e6a71fc9642fdc57e3f04e69c5f78cfd18c4e18da40a6 - languageName: node - linkType: hard - -"@octokit/openapi-types@npm:^17.2.0": - version: 17.2.0 - resolution: "@octokit/openapi-types@npm:17.2.0" - checksum: baec94b9c300171245d8b0592867ef96d3aa9cbb3261e961c5138e91894e165fffc421288d98f51031af12ab4149efb7ba597d79dee2e5b5a38962348528b1e5 + checksum: eeaaa772de3dbce954b6fea7aeaa77e87aafcae831618321e128ab65e8009aec518a0417db1a856cf55522bd0f5ff9916cba3fe9ed2287ca4c18a589ee8df05a languageName: node linkType: hard @@ -5946,25 +5946,25 @@ __metadata: linkType: hard "@octokit/plugin-rest-endpoint-methods@npm:^7.1.1, @octokit/plugin-rest-endpoint-methods@npm:^7.1.2": - version: 7.2.2 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:7.2.2" + version: 7.2.3 + resolution: "@octokit/plugin-rest-endpoint-methods@npm:7.2.3" dependencies: "@octokit/types": ^10.0.0 peerDependencies: "@octokit/core": ">=3" - checksum: c62de2dd1202d5050dc5d8a799d0a6f52954858e9294af7a904257b883c8471c04ee9b93a4828e960e71963238776eff37aec7123de1423bb7397c07978c75d0 + checksum: 8bffbc5852695dd08d65cc64b6ab7d2871ed9df1e791608f48b488a3908b5b655e3686b5dd72fc37c824e82bdd4dfc9d24e2e50205bbc324667def1d705bc9da languageName: node linkType: hard "@octokit/plugin-retry@npm:^4.1.3": - version: 4.1.3 - resolution: "@octokit/plugin-retry@npm:4.1.3" + version: 4.1.6 + resolution: "@octokit/plugin-retry@npm:4.1.6" dependencies: "@octokit/types": ^9.0.0 bottleneck: ^2.15.3 peerDependencies: "@octokit/core": ">=3" - checksum: 375a31c5e52effb1cabdfb47bcf83b418d3555344eda682e9ccca619d8a0d741bf530845fe433405d852bbc9574e4e763d1161b1fa3d3af1e63a18ba77ec4c64 + checksum: becda71309b8fde99b2daa6c5ab7c9774adfabc2c950da53741bb911c6cd4db1b4d9cc878498580f8b8e881f491450a57bfaa50b6ad749aea421766675dbebdb languageName: node linkType: hard @@ -5992,8 +5992,8 @@ __metadata: linkType: hard "@octokit/request@npm:^6.0.0, @octokit/request@npm:^6.2.3": - version: 6.2.5 - resolution: "@octokit/request@npm:6.2.5" + version: 6.2.8 + resolution: "@octokit/request@npm:6.2.8" dependencies: "@octokit/endpoint": ^7.0.0 "@octokit/request-error": ^3.0.0 @@ -6001,7 +6001,7 @@ __metadata: is-plain-object: ^5.0.0 node-fetch: ^2.6.7 universal-user-agent: ^6.0.0 - checksum: 1f9feaedd75156ffc5b05294974e18b1798a3350ed99acb6d7f9d7b76fc338a47cb9d88b927e7d506894edf49e3a1ef1e18d877403a0aa386d0037b734ab59e4 + checksum: 6b6079ed45bac44c4579b40990bfd1905b03d4bc4e5255f3d5a10cf5182171578ebe19abeab32ebb11a806f1131947f2a06b7a077bd7e77ade7b15fe2882174b languageName: node linkType: hard @@ -6034,18 +6034,18 @@ __metadata: linkType: hard "@octokit/types@npm:^9.0.0, @octokit/types@npm:^9.2.2, @octokit/types@npm:^9.2.3": - version: 9.2.3 - resolution: "@octokit/types@npm:9.2.3" + version: 9.3.2 + resolution: "@octokit/types@npm:9.3.2" dependencies: - "@octokit/openapi-types": ^17.2.0 - checksum: 9604939ed79be2298827e832177bb8e871d44170144a7504adb0c399966e45361fb909ccffacbd7151f08b94d2e739c6a2d1c0b9a2f9a4bde09c968d27060514 + "@octokit/openapi-types": ^18.0.0 + checksum: 2925479aa378a4491762b4fcf381bdc7daca39b4e0b2dd7062bce5d74a32ed7d79d20d3c65ceaca6d105cf4b1f7417fea634219bf90f79a57d03e2dac629ec45 languageName: node linkType: hard "@octokit/webhooks-methods@npm:^3.0.0": - version: 3.0.2 - resolution: "@octokit/webhooks-methods@npm:3.0.2" - checksum: 553626b5c55ac4b7fef0ca2aadbfedbbb22b96f8a3311212fbf62e667b0dbaf8a8620b89cb9adb08302b063e4373b62f247c95b9a0ee1ec6b138c76b012924f4 + version: 3.0.3 + resolution: "@octokit/webhooks-methods@npm:3.0.3" + checksum: f000d7b3cb2523bc352a0f2cb9d6f6f19c499704f9273a7564cbb0a69545fe92fc35f8f18ddc45026d54275ecef5ea6c127a7a058a6af2852abd5055a838fc9f languageName: node linkType: hard @@ -7499,9 +7499,12 @@ __metadata: redwood: ./dist/bins/redwood.js rw: ./dist/bins/redwood.js rw-api-server-watch: ./dist/bins/rw-api-server-watch.js + rw-dev-fe: ./dist/bins/rw-dev-fe.js rw-gen: ./dist/bins/rw-gen.js rw-gen-watch: ./dist/bins/rw-gen-watch.js rw-log-formatter: ./dist/bins/rw-log-formatter.js + rw-serve-api: ./dist/bins/rw-serve-api.js + rw-serve-fe: ./dist/bins/rw-serve-fe.js rwfw: ./dist/bins/rwfw.js languageName: unknown linkType: soft @@ -7666,6 +7669,7 @@ __metadata: "@graphql-codegen/typescript-resolvers": 3.2.1 "@redwoodjs/graphql-server": 5.0.0 "@redwoodjs/project-config": 5.0.0 + "@redwoodjs/router": 5.0.0 "@sdl-codegen/node": 0.0.10 "@types/babel-plugin-tester": 9.0.5 "@types/babel__core": 7.20.1 @@ -7944,20 +7948,29 @@ __metadata: resolution: "@redwoodjs/vite@workspace:packages/vite" dependencies: "@babel/cli": 7.22.5 + "@babel/plugin-syntax-import-assertions": 7.20.0 "@babel/runtime-corejs3": 7.22.5 "@redwoodjs/internal": 5.0.0 "@redwoodjs/project-config": 5.0.0 + "@redwoodjs/web": 5.0.0 + "@types/express": 4 "@types/yargs-parser": 21.0.0 "@vitejs/plugin-react": 4.0.1 buffer: 6.0.3 core-js: 3.31.0 + dotenv-defaults: 5.0.2 + express: 4.18.2 glob: 10.3.0 + http-proxy-middleware: 2.0.6 + isbot: 3.6.8 jest: 29.5.0 typescript: 5.1.3 vite: 4.3.9 vite-plugin-environment: 1.1.3 yargs-parser: 21.1.1 bin: + rw-dev-fe: ./dist/devFeServer.js + rw-serve-fe: ./dist/runFeServer.js rw-vite-build: ./bins/rw-vite-build.mjs rw-vite-dev: ./bins/rw-vite-dev.mjs vite: ./bins/vite.mjs @@ -8040,6 +8053,17 @@ __metadata: languageName: node linkType: hard +"@sigstore/tuf@npm:^1.0.0": + version: 1.0.0 + resolution: "@sigstore/tuf@npm:1.0.0" + dependencies: + "@sigstore/protobuf-specs": ^0.1.0 + make-fetch-happen: ^11.0.1 + tuf-js: ^1.1.3 + checksum: 95251d95b42875907863f67637238c4cafe7c24d816ab01f71dc6ac07e275d8fef33c65d49a4165368c208e427119bd57737e4913dd7053cee0021195bc5655f + languageName: node + linkType: hard + "@simplewebauthn/browser@npm:7.2.0": version: 7.2.0 resolution: "@simplewebauthn/browser@npm:7.2.0" @@ -8111,11 +8135,11 @@ __metadata: linkType: hard "@sinonjs/fake-timers@npm:^10.0.2": - version: 10.2.0 - resolution: "@sinonjs/fake-timers@npm:10.2.0" + version: 10.3.0 + resolution: "@sinonjs/fake-timers@npm:10.3.0" dependencies: "@sinonjs/commons": ^3.0.0 - checksum: 9f4726e7799a409d51d6760af3b65dac061b4f5c0b69b3af4caf79ecc3012dacae1f40078d915f9cec1ecd81d84a41619a98d4878bb2ef9f3ed66c16c2f5f833 + checksum: 2e2fb6cc57f227912814085b7b01fede050cd4746ea8d49a1e44d5a0e56a804663b0340ae2f11af7559ea9bf4d087a11f2f646197a660ea3cb04e19efc04aa63 languageName: node linkType: hard @@ -8817,11 +8841,11 @@ __metadata: linkType: hard "@storybook/csf@npm:^0.1.0": - version: 0.1.0 - resolution: "@storybook/csf@npm:0.1.0" + version: 0.1.1 + resolution: "@storybook/csf@npm:0.1.1" dependencies: type-fest: ^2.19.0 - checksum: 76e284884eacb54bb2130448c45204d64e9ca436d73614d3369d72049b1e786e31e55c0bbb922b8e1069fecbc97a3d68796d401f8e3d93d7ffba0df59b6d8cbe + checksum: 999bb87fbbe047a559bbaa5baf2ed84872fcd5cdcae3c1169f8e4c641eefe8759d09a09034a78ed114032c0e5cf6301b7fa89e5e3ce60d75cf0bd5e33ec0a6e7 languageName: node linkType: hard @@ -9129,29 +9153,29 @@ __metadata: linkType: hard "@supabase/functions-js@npm:^2.1.0": - version: 2.1.1 - resolution: "@supabase/functions-js@npm:2.1.1" + version: 2.1.2 + resolution: "@supabase/functions-js@npm:2.1.2" dependencies: cross-fetch: ^3.1.5 - checksum: 1cb1b2fdfc845f472527eef285cb6fba7e06045dfd13b869815b5956a38a423926d1c9484839c30eab611bbf0999bb7d74f0d4d126ea129dd385d35578129af0 + checksum: fe35d1a145570c83d33c3f09148b0d7448b0d78e8a55da38b7d7ba3d22d6373303cf23a5c19d8a8dcc98f53f4247de2cb831923e6aff6bdc9cf2aa2e58ce7335 languageName: node linkType: hard "@supabase/gotrue-js@npm:^2.31.0": - version: 2.31.0 - resolution: "@supabase/gotrue-js@npm:2.31.0" + version: 2.34.0 + resolution: "@supabase/gotrue-js@npm:2.34.0" dependencies: cross-fetch: ^3.1.5 - checksum: b04c29c965e8b90779baed425d356d6132772aff602cd4980fe80df08ab2d9b25312c197b1150f7cee9450047a5c26225b02565af5d3881314f50b6d406b15f6 + checksum: 54362b113fdb955028bed87c8f9cc161b857ab2cd40a2d796a17d4249e4dc59b5ae7263955a7c73dfea5dd482a79b7cd52449bd16e88373ae7709c83dbc6f354 languageName: node linkType: hard "@supabase/postgrest-js@npm:^1.7.0": - version: 1.7.0 - resolution: "@supabase/postgrest-js@npm:1.7.0" + version: 1.7.1 + resolution: "@supabase/postgrest-js@npm:1.7.1" dependencies: cross-fetch: ^3.1.5 - checksum: dff68d516f4c54d7425941fa41579f4cfc0f95b490f299ab9a0fe96a01946c7e6a3622f174c0013770e5de2066f8d5c09e54fe8977d74b19687511fe4fc3f663 + checksum: d781c403209b1394e575b47ccb21044e6c8123518311a9ff7f6f5be30f5a02fb285cbcfd178993f814250e5d2daf13f47fb2e6404878a6f3e49a39e3ef801846 languageName: node linkType: hard @@ -9342,18 +9366,18 @@ __metadata: linkType: hard "@testing-library/dom@npm:^8.11.1": - version: 8.20.0 - resolution: "@testing-library/dom@npm:8.20.0" + version: 8.20.1 + resolution: "@testing-library/dom@npm:8.20.1" dependencies: "@babel/code-frame": ^7.10.4 "@babel/runtime": ^7.12.5 "@types/aria-query": ^5.0.1 - aria-query: ^5.0.0 + aria-query: 5.1.3 chalk: ^4.1.0 dom-accessibility-api: ^0.5.9 - lz-string: ^1.4.4 + lz-string: ^1.5.0 pretty-format: ^27.0.2 - checksum: 454c71f65708d1504256ae055f060adf8ed9eadcc7ddbf6d07a528045beceb842783c1253871759f5c137eca58e5e32700dc64b130cbb37e10e7a52ab08d7b44 + checksum: 614013756706467f2a7f3f693c18377048c210ec809884f0f9be866f7d865d075805ad15f5d100e8a699467fdde09085bf79e23a00ea0a6ab001d9583ef15e5d languageName: node linkType: hard @@ -9599,11 +9623,11 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.20.0 - resolution: "@types/babel__traverse@npm:7.20.0" + version: 7.20.1 + resolution: "@types/babel__traverse@npm:7.20.1" dependencies: "@babel/types": ^7.20.7 - checksum: 9a4cfe345fc681f6009f11de705d19c6546fc681b9c7408f2ddd3eb18e8cbfbae80b63e153ac62afdd5a4e9beb57987b377dc2f84d50c477e5470abce9648e74 + checksum: 5a6a3a26be090573309527184a31f1b82ef55f3d73d811c15f181d323e471305f2390651a04d49d4cd4ca41bbeabb53c9f7862a8e09eab5a0f8910a6aec6e867 languageName: node linkType: hard @@ -9786,7 +9810,7 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.14, @types/express@npm:^4.7.0": +"@types/express@npm:*, @types/express@npm:4, @types/express@npm:^4.17.13, @types/express@npm:^4.17.14, @types/express@npm:^4.7.0": version: 4.17.17 resolution: "@types/express@npm:4.17.17" dependencies: @@ -9853,6 +9877,13 @@ __metadata: languageName: node linkType: hard +"@types/http-errors@npm:*": + version: 2.0.1 + resolution: "@types/http-errors@npm:2.0.1" + checksum: 3bbc8c84fb02b381737e2eec563b434121384b1aef4e070edec4479a1bc74f27373edc09162680cd3ea1035ef8e5ab6d606bd7c99e3855c424045fb74376cb66 + languageName: node + linkType: hard + "@types/http-proxy@npm:^1.17.8": version: 1.17.11 resolution: "@types/http-proxy@npm:1.17.11" @@ -10148,9 +10179,9 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0": - version: 20.2.5 - resolution: "@types/node@npm:20.2.5" - checksum: 1c3db8a4ceb5e5d12e7cb140e37c14a16ce013084c6d65579b91cefbe0ecaca57d85093d968172b11c3d1d95bcbc5d972b08aa3dc3935206fb39bc6c10751102 + version: 20.3.2 + resolution: "@types/node@npm:20.3.2" + checksum: d857cbe388d11fefd6c598144db42a32e1c15c09624b9e0669ec65e9d72e080093db3ec6b536037e6575574e33413479d4b3762140c2544ff30eb0c2111b5596 languageName: node linkType: hard @@ -10169,16 +10200,16 @@ __metadata: linkType: hard "@types/node@npm:^14.14.31": - version: 14.18.48 - resolution: "@types/node@npm:14.18.48" - checksum: 83c43539d579665588ad4eeafb7b2f112dda2b4fb35eb8b0f2bb53270ba99022c85d312a992332cca393e03bb9300c43ca78b835130139ba4413204734d5a09e + version: 14.18.52 + resolution: "@types/node@npm:14.18.52" + checksum: 25b34334c109fae745ad7d52d2eebbc20e2feee5967594008992338f05f1d235d3f56929d3213b15dbb35681b2722dd106c603170606f2ec89e1215ba490e080 languageName: node linkType: hard "@types/node@npm:^16.0.0": - version: 16.18.34 - resolution: "@types/node@npm:16.18.34" - checksum: d6572e12b2200a813b2e0944add0abb8ac59d51a0cf28651dd1dde9de4d43e9d4c2c41fd7cf910d0c3bd8e13d10047f58211a53e76780279fc6d284137d3b001 + version: 16.18.37 + resolution: "@types/node@npm:16.18.37" + checksum: b0bc60bb9045ab13af31d4de14a53a0e2617296bb3c686849150d579043691164833b844ca0db1fea16d91d8e8d8fc6fc91ebf38f8615044bd131198de38ac90 languageName: node linkType: hard @@ -10356,12 +10387,13 @@ __metadata: linkType: hard "@types/serve-static@npm:*, @types/serve-static@npm:^1.13.10": - version: 1.15.1 - resolution: "@types/serve-static@npm:1.15.1" + version: 1.15.2 + resolution: "@types/serve-static@npm:1.15.2" dependencies: + "@types/http-errors": "*" "@types/mime": "*" "@types/node": "*" - checksum: dc934e2adce730480af5af6081b99f50be4dfb7f44537893444bcf1dc97f5d5ffb16b38350ecd89dd114184d751ba3271500631fa56cf1faa35be56f8e45971b + checksum: 5e7b3e17b376f8910d5c9a0b1def38d7841c8939713940098f1b80a330d5caa9cfe9b632c122252cd70165052439e18fafa46635dc55b1d6058343901eec22eb languageName: node linkType: hard @@ -11200,12 +11232,12 @@ __metadata: linkType: hard "@yarnpkg/parsers@npm:^3.0.0-rc.18": - version: 3.0.0-rc.44 - resolution: "@yarnpkg/parsers@npm:3.0.0-rc.44" + version: 3.0.0-rc.46 + resolution: "@yarnpkg/parsers@npm:3.0.0-rc.46" dependencies: js-yaml: ^3.10.0 tslib: ^2.4.0 - checksum: b4f6ccec3a4e91332c4f5ae76c8949b25a427062ba0e1e1358591f4de839458af8dd471481be4086de960aa83a781ea7b70bcf4f38b1738dcf8b4309fd2ef2a7 + checksum: c7f421c6885142f351459031c093fb2e79abcce6f4a89765a10e600bb7ab122949c54bcea2b23de9572a2b34ba29f822b17831c1c43ba50373ceb8cb5b336667 languageName: node linkType: hard @@ -11344,7 +11376,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:8.9.0, acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.1": +"acorn@npm:8.9.0, acorn@npm:^8.0.4, acorn@npm:^8.1.0, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.7.1, acorn@npm:^8.8.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2": version: 8.9.0 resolution: "acorn@npm:8.9.0" bin: @@ -11788,7 +11820,7 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:5.1.3, aria-query@npm:^5.0.0, aria-query@npm:^5.1.3": +"aria-query@npm:5.1.3": version: 5.1.3 resolution: "aria-query@npm:5.1.3" dependencies: @@ -11797,6 +11829,15 @@ __metadata: languageName: node linkType: hard +"aria-query@npm:^5.0.0, aria-query@npm:^5.1.3": + version: 5.3.0 + resolution: "aria-query@npm:5.3.0" + dependencies: + dequal: ^2.0.3 + checksum: 2bff0d4eba5852a9dd578ecf47eaef0e82cc52569b48469b0aac2db5145db0b17b7a58d9e01237706d1e14b7a1b0ac9b78e9c97027ad97679dd8f91b85da1469 + languageName: node + linkType: hard + "arr-diff@npm:^4.0.0": version: 4.0.0 resolution: "arr-diff@npm:4.0.0" @@ -12181,8 +12222,8 @@ __metadata: linkType: hard "aws-sdk@npm:^2.814.0": - version: 2.1387.0 - resolution: "aws-sdk@npm:2.1387.0" + version: 2.1406.0 + resolution: "aws-sdk@npm:2.1406.0" dependencies: buffer: 4.9.2 events: 1.1.1 @@ -12194,7 +12235,7 @@ __metadata: util: ^0.12.4 uuid: 8.0.0 xml2js: 0.5.0 - checksum: 7a4ca0fe6059b320f13e1a6419db64d61bc082a769779d1eb834eceb0ec55be03835eecbc3d7111ba9ed19df741ee28ca5fa0ed5d15d96190c7ec70664b9062d + checksum: bc271a2df5fa957ec127845b944b48599a3d2a6ee5a85fbdcd373bafac04f7c9d13dd4bd539a009402490a88fd684c812e75bebc9a91e8a40e6ca927fea9a826 languageName: node linkType: hard @@ -12242,11 +12283,11 @@ __metadata: linkType: hard "axobject-query@npm:^3.1.1": - version: 3.1.1 - resolution: "axobject-query@npm:3.1.1" + version: 3.2.1 + resolution: "axobject-query@npm:3.2.1" dependencies: - deep-equal: ^2.0.5 - checksum: fff3175a22fd1f41fceb7ae0cd25f6594a0d7fba28c2335dd904538b80eb4e1040432564a3c643025cd2bb748f68d35aaabffb780b794da97ecfc748810b25ad + dequal: ^2.0.3 + checksum: f7debc2012e456139b57d888c223f6d3cb4b61eb104164a85e3d346273dd6ef0bc9a04b6660ca9407704a14a8e05fa6b6eb9d55f44f348c7210de7ffb350c3a7 languageName: node linkType: hard @@ -13007,16 +13048,16 @@ __metadata: linkType: hard "browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.21.3, browserslist@npm:^4.21.4, browserslist@npm:^4.21.5": - version: 4.21.7 - resolution: "browserslist@npm:4.21.7" + version: 4.21.9 + resolution: "browserslist@npm:4.21.9" dependencies: - caniuse-lite: ^1.0.30001489 - electron-to-chromium: ^1.4.411 + caniuse-lite: ^1.0.30001503 + electron-to-chromium: ^1.4.431 node-releases: ^2.0.12 update-browserslist-db: ^1.0.11 bin: browserslist: cli.js - checksum: c523a982ef5d4141907795bbb72d7e2c5df79b2c6e495ef8ff6405b6734a2f16529a7f54c86b113085cad8a3359ac2fc6a478e86ae715084ba7384b9344b2ef5 + checksum: 903189787141f645f47ec46ec482dc85985d1297948062690dc2ea8480eb98fd6213507234eb17177825acaae49c53888445910f1af984abce5373fb65c270b8 languageName: node linkType: hard @@ -13229,32 +13270,6 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^16.1.0": - version: 16.1.3 - resolution: "cacache@npm:16.1.3" - dependencies: - "@npmcli/fs": ^2.1.0 - "@npmcli/move-file": ^2.0.0 - chownr: ^2.0.0 - fs-minipass: ^2.1.0 - glob: ^8.0.1 - infer-owner: ^1.0.4 - lru-cache: ^7.7.1 - minipass: ^3.1.6 - minipass-collect: ^1.0.2 - minipass-flush: ^1.0.5 - minipass-pipeline: ^1.2.4 - mkdirp: ^1.0.4 - p-map: ^4.0.0 - promise-inflight: ^1.0.1 - rimraf: ^3.0.2 - ssri: ^9.0.0 - tar: ^6.1.11 - unique-filename: ^2.0.0 - checksum: cdf6836e1c457d2a5616abcaf5d8240c0346b1f5bd6fdb8866b9d84b6dff0b54e973226dc11e0d099f35394213d24860d1989c8358d2a41b39eb912b3000e749 - languageName: node - linkType: hard - "cacache@npm:^17.0.0, cacache@npm:^17.0.4": version: 17.1.3 resolution: "cacache@npm:17.1.3" @@ -13390,10 +13405,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001489": - version: 1.0.30001492 - resolution: "caniuse-lite@npm:1.0.30001492" - checksum: df7ad55d2475ff6561e84e2f21c8da45fe02ba539d493d5a77214aeaf264632cf74084a8eb13bfd2cb0c9fbde0ff6af4acbd923b8590eb6b2920ba44fcac9b2d +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001503": + version: 1.0.30001509 + resolution: "caniuse-lite@npm:1.0.30001509" + checksum: 631e61b8de50174ffe0baeb0b87d52f0b873bae6c13b4b4eb7eb9e2dbd7d48fb05c8426cc9eccc21e4e4156d2d2bdfe7f7d9677a6f9484c2f24404e737020700 languageName: node linkType: hard @@ -13778,9 +13793,9 @@ __metadata: linkType: hard "cjs-module-lexer@npm:^1.0.0": - version: 1.2.2 - resolution: "cjs-module-lexer@npm:1.2.2" - checksum: 83330e1feda2e3699b8c305bfa8f841b41822049393f5eefeb574e60bde556e2a251ee9b7971cde0cb47ac4f7823bf4ab4a6005b8471f86ad9f5509eefb66cbd + version: 1.2.3 + resolution: "cjs-module-lexer@npm:1.2.3" + checksum: 0de9a9c3fad03a46804c0d38e7b712fb282584a9c7ef1ed44cae22fb71d9bb600309d66a9711ac36a596fd03422f5bb03e021e8f369c12a39fa1786ae531baab languageName: node linkType: hard @@ -14507,18 +14522,18 @@ __metadata: linkType: hard "core-js-compat@npm:^3.25.1, core-js-compat@npm:^3.30.1, core-js-compat@npm:^3.30.2": - version: 3.30.2 - resolution: "core-js-compat@npm:3.30.2" + version: 3.31.0 + resolution: "core-js-compat@npm:3.31.0" dependencies: browserslist: ^4.21.5 - checksum: 7cb984fc6bcdd2f28c2f2f19fc8fc874a303adf7f835720b9937f0b1d40793819ed744dc14dff28ddb7735404b02a43f08493c3e2f227b27090cd6d64d28c5f9 + checksum: 09cca4c2565ddea1fb65324ef17c2dcc61e6c3ec089d8b343e6cbea2b42a9c3ae5e76a42c6faff3759a321c5e7165201db93b7b47912c4c2d1c3d6afad44f7fc languageName: node linkType: hard "core-js-pure@npm:^3.23.3, core-js-pure@npm:^3.30.2": - version: 3.30.2 - resolution: "core-js-pure@npm:3.30.2" - checksum: 4035947addee484227e99281fc594837387f4c4e209a5996c9d6c1609cbbe11e1a583133414c6685974ebcf228e620011ad4edcad8991882f69ff1663cbbfd82 + version: 3.31.0 + resolution: "core-js-pure@npm:3.31.0" + checksum: fd3f003391bf13722ab40de30c1e0bad9284a2289303ce34db119906eb0f26df677d1f755d07628a1d595d7728c51cea9d41f5dc8fe1b5d4e4214817c557a01a languageName: node linkType: hard @@ -15164,9 +15179,9 @@ __metadata: linkType: hard "dayjs@npm:^1.10.4": - version: 1.11.7 - resolution: "dayjs@npm:1.11.7" - checksum: 41a54853c8b8bf0fa94a5559eec98b3e4d11b31af81a9558a159d40adeaafb1f3414e8c41a4e3277281d97687d8252f400015e1f715b47f8c24d88a9ebd43626 + version: 1.11.8 + resolution: "dayjs@npm:1.11.8" + checksum: 66833f3eb88ac06c8dd9b163986faab9b03f46df9e16a7d1a95aa3fca86eee334234e873e322977c8a458d721dee8f730a43ddda2c383e70d306454088eca8bb languageName: node linkType: hard @@ -15518,7 +15533,7 @@ __metadata: languageName: node linkType: hard -"dequal@npm:^2.0.2": +"dequal@npm:^2.0.2, dequal@npm:^2.0.3": version: 2.0.3 resolution: "dequal@npm:2.0.3" checksum: f98860cdf58b64991ae10205137c0e97d384c3a4edc7f807603887b7c4b850af1224a33d88012009f150861cbee4fa2d322c4cc04b9313bee312e47f6ecaa888 @@ -15963,10 +15978,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.411": - version: 1.4.414 - resolution: "electron-to-chromium@npm:1.4.414" - checksum: bb8397bfbcf369d8a5dc307346b5b721720d8355c03cb312673a0fc283396eac1998db4fbb95c7eac74da22aff5c4f62324509036a23feda7904aa955afba636 +"electron-to-chromium@npm:^1.4.431": + version: 1.4.442 + resolution: "electron-to-chromium@npm:1.4.442" + checksum: 3a4d756a1c3fa72b9715ca9f945e410ee949abd398bfe6210459b6bedec86ca09b518b7dabc363983098b60454edc3b3328483173c02b663ca66fe488b7b16f9 languageName: node linkType: hard @@ -16123,7 +16138,7 @@ __metadata: languageName: node linkType: hard -"envinfo@npm:7.9.0, envinfo@npm:^7.7.3": +"envinfo@npm:7.9.0": version: 7.9.0 resolution: "envinfo@npm:7.9.0" bin: @@ -16132,6 +16147,15 @@ __metadata: languageName: node linkType: hard +"envinfo@npm:^7.7.3": + version: 7.10.0 + resolution: "envinfo@npm:7.10.0" + bin: + envinfo: dist/cli.js + checksum: ebc7792fbedca72bc829913abe0c2a3384b883903012f97b56085afd4e83d26f7dd0652403fedd99cd3e1c93d4fb0706f5d2c3dc06ac6a1eda348280a06a9dcf + languageName: node + linkType: hard + "err-code@npm:^2.0.2": version: 2.0.3 resolution: "err-code@npm:2.0.3" @@ -16235,9 +16259,9 @@ __metadata: linkType: hard "es-module-lexer@npm:^1.2.1": - version: 1.2.1 - resolution: "es-module-lexer@npm:1.2.1" - checksum: 6e0a9095e0abe38f480e0f366cdeca19db64d85a533da9332739a64d70e97a61e68c1f98a2396468ae6229245b8e5edcb1e48c4d3615ae4da9052a1bdc2367e2 + version: 1.3.0 + resolution: "es-module-lexer@npm:1.3.0" + checksum: cbd9bdc65458d4c4bd0d22a1c792926bfdf7bb6a96a9ed04da7d31f317159bd4945d2dbeb318717f9214f9695ee85a8fae64a5d25bf360baa82b58079032fc7a languageName: node linkType: hard @@ -17075,7 +17099,14 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.1, express@npm:^4.17.3": +"exponential-backoff@npm:^3.1.1": + version: 3.1.1 + resolution: "exponential-backoff@npm:3.1.1" + checksum: 160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 + languageName: node + linkType: hard + +"express@npm:4.18.2, express@npm:^4.17.1, express@npm:^4.17.3": version: 4.18.2 resolution: "express@npm:4.18.2" dependencies: @@ -17318,11 +17349,11 @@ __metadata: linkType: hard "fast-querystring@npm:^1.0.0, fast-querystring@npm:^1.1.1": - version: 1.1.1 - resolution: "fast-querystring@npm:1.1.1" + version: 1.1.2 + resolution: "fast-querystring@npm:1.1.2" dependencies: fast-decode-uri-component: ^1.0.1 - checksum: bfc14761201796ef2ad9b4c645512701c474c8ed2bd503f7dd4b966894f29ef67e38ef4d3cfb4c633fa6e9118d512b610356b1eae9d89a710f773f585d56d391 + checksum: e8223273a9b199722f760f5a047a77ad049a14bd444b821502cb8218f5925e3a5fffb56b64389bca73ab2ac6f1aa7aebbe4e203e5f6e53ff5978de97c0fde4e3 languageName: node linkType: hard @@ -17447,8 +17478,8 @@ __metadata: linkType: hard "fbjs@npm:^3.0.0": - version: 3.0.4 - resolution: "fbjs@npm:3.0.4" + version: 3.0.5 + resolution: "fbjs@npm:3.0.5" dependencies: cross-fetch: ^3.1.5 fbjs-css-vars: ^1.0.0 @@ -17456,8 +17487,8 @@ __metadata: object-assign: ^4.1.0 promise: ^7.1.1 setimmediate: ^1.0.5 - ua-parser-js: ^0.7.30 - checksum: 6c605d038d6852f0199a333e0b7f1f3e2602eebd0b815fba505f641912610007a0a8419222909e17ad0e07365d3b8a0bf45cacf9b43366dde0e95e5ced251632 + ua-parser-js: ^1.0.35 + checksum: 66d0a2fc9a774f9066e35ac2ac4bf1245931d27f3ac287c7d47e6aa1fc152b243c2109743eb8f65341e025621fb51a12038fadb9fd8fda2e3ddae04ebab06f91 languageName: node linkType: hard @@ -17781,9 +17812,9 @@ __metadata: linkType: hard "flow-parser@npm:0.*": - version: 0.207.0 - resolution: "flow-parser@npm:0.207.0" - checksum: a6d6c64bf6f5818e325d0ad0e3529220817be88488481933ee498fd093b0d3031e59ddc5d8d3e661c05801cc0820ae36aa1af4e855aa239f92c7fe48095a866a + version: 0.210.1 + resolution: "flow-parser@npm:0.210.1" + checksum: 749d1941879b5db3487e77d86dd01e56f1a18df0e394be932f050caeb2c2bd5ad9181bb60b7b2265a30d78f7359be765be50162db0250285990804262571907a languageName: node linkType: hard @@ -18034,7 +18065,7 @@ __metadata: languageName: node linkType: hard -"fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": +"fs-minipass@npm:^2.0.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" dependencies: @@ -18052,10 +18083,10 @@ __metadata: languageName: node linkType: hard -"fs-monkey@npm:^1.0.3": - version: 1.0.3 - resolution: "fs-monkey@npm:1.0.3" - checksum: 197fd276d224d54a27c6267c69887ec29ccd4bedd83d72b5050abf3b6c6ef83d7b86a85a87f615c24a4e6f9a4888fd151c9f16a37ffb23e37c4c2d14c1da6275 +"fs-monkey@npm:^1.0.4": + version: 1.0.4 + resolution: "fs-monkey@npm:1.0.4" + checksum: eeb2457ec50f7202c44273de2a42b50868c8e6b2ab4825d517947143d4e727c028e24f6d0f46e6f3e7a149a1c9e7d8b3ca28243c3b10366d280a08016483e829 languageName: node linkType: hard @@ -18366,11 +18397,11 @@ __metadata: linkType: hard "get-tsconfig@npm:^4.4.0": - version: 4.6.0 - resolution: "get-tsconfig@npm:4.6.0" + version: 4.6.2 + resolution: "get-tsconfig@npm:4.6.2" dependencies: resolve-pkg-maps: ^1.0.0 - checksum: 6480197512fc97e4bc049fc23943d78ef5f034e6a3c7c7dbc1d16d8a2091aa08b72122ebf29c2dc815842266f966cf0c12000dc9151e632296feb9e1a285b854 + checksum: 352c7313720b0f1172de5b6697da55c02744bacd8587f4cd989bfa25d8bb1af702128c2869121e6e4eef06c5c2f013406d2840905a8e898fd35351a305298ee1 languageName: node linkType: hard @@ -18515,13 +18546,13 @@ __metadata: linkType: hard "glob-promise@npm:^6.0.2": - version: 6.0.2 - resolution: "glob-promise@npm:6.0.2" + version: 6.0.3 + resolution: "glob-promise@npm:6.0.3" dependencies: "@types/glob": ^8.0.0 peerDependencies: glob: ^8.0.3 - checksum: fa08c8beb32b87d9313d7f24d17b2eebeed6e77fcfe0e4b743f94e9621663292cf5e665f671502dcf925683aea1086d3a756032bef08c87d7dc05014aef71c5a + checksum: f6b4f318449a2ed4c4a511921d5ec311b78c1f6e75e8c1479791b7576bf4c0ad72ed5d2ee95e60cafc037633c9295603191fb1987b529055a116bc051f30d43a languageName: node linkType: hard @@ -18547,7 +18578,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.0, glob@npm:^10.2.2, glob@npm:^10.2.5": +"glob@npm:10.3.0": version: 10.3.0 resolution: "glob@npm:10.3.0" dependencies: @@ -18576,6 +18607,21 @@ __metadata: languageName: node linkType: hard +"glob@npm:^10.2.2, glob@npm:^10.2.5": + version: 10.3.1 + resolution: "glob@npm:10.3.1" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.0.3 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 + path-scurry: ^1.10.0 + bin: + glob: dist/cjs/src/bin.js + checksum: b39d24c093ce2ffa992dc5b412dbc871af0ccd38a6b2356f67dc906857f0c4c811039a4a4665d19443e1bb484ce2d97855cc7fcfb9a7d0b7e0dadfef4dad5b82 + languageName: node + linkType: hard + "glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0": version: 7.2.3 resolution: "glob@npm:7.2.3" @@ -18664,15 +18710,15 @@ __metadata: linkType: hard "globby@npm:^13.1.1, globby@npm:^13.1.4": - version: 13.1.4 - resolution: "globby@npm:13.1.4" + version: 13.2.0 + resolution: "globby@npm:13.2.0" dependencies: dir-glob: ^3.0.1 fast-glob: ^3.2.11 ignore: ^5.2.0 merge2: ^1.4.1 slash: ^4.0.0 - checksum: cbf4ce32ea7fba37be8c4749a2f69c2803b70a57e40a968b57343cc74daced8c87a7cdea038f69eda95fe17df8ebf75346d18e188c2bc4948f081bbbc655c323 + checksum: d1ea2b09dbb24961d16413cdb45764cb63280a2a7066739df5e5b33292ce4980d9da1d168a6a135c332ea1856f921e28d8ffcc2c6c24b82d4f4208477bfe62b4 languageName: node linkType: hard @@ -18889,13 +18935,20 @@ __metadata: languageName: node linkType: hard -"graphql@npm:16.6.0, graphql@npm:^15.0.0 || ^16.0.0, graphql@npm:^16.0.0": +"graphql@npm:16.6.0": version: 16.6.0 resolution: "graphql@npm:16.6.0" checksum: 3a2c15ff58b69d017618d2b224fa6f3c4a7937e1f711c3a5e0948db536b4931e6e649560b53de7cc26735e027ceea6e2d0a6bb7c29fc4639b290313e3aa71618 languageName: node linkType: hard +"graphql@npm:^15.0.0 || ^16.0.0, graphql@npm:^16.0.0": + version: 16.7.1 + resolution: "graphql@npm:16.7.1" + checksum: 0b4e83382bf3cb9c82ddf61a51aab382c4de50c34025173285c580135fe8646aa281c264fcf0c2214ae92ea925742d86999fe5e2ad842b6f3b54a9ffb0b299d2 + languageName: node + linkType: hard + "gtoken@npm:^6.1.0": version: 6.1.2 resolution: "gtoken@npm:6.1.2" @@ -19221,9 +19274,9 @@ __metadata: linkType: hard "html-entities@npm:^2.1.0, html-entities@npm:^2.3.2": - version: 2.3.3 - resolution: "html-entities@npm:2.3.3" - checksum: a76cbdbb276d9499dc7ef800d23f3964254e659f04db51c8d1ff6abfe21992c69b7217ecfd6e3c16ff0aa027ba4261d77f0dba71f55639c16a325bbdf69c535d + version: 2.4.0 + resolution: "html-entities@npm:2.4.0" + checksum: 42bbd5d91f451625d7e35aaed41c8cd110054c0d0970764cb58df467b3f27f20199e8cf7b4aebc8d4eeaf17a27c0d1fb165f2852db85de200995d0f009c9011d languageName: node linkType: hard @@ -19385,7 +19438,7 @@ __metadata: languageName: node linkType: hard -"http-proxy-middleware@npm:^2.0.3": +"http-proxy-middleware@npm:2.0.6, http-proxy-middleware@npm:^2.0.3": version: 2.0.6 resolution: "http-proxy-middleware@npm:2.0.6" dependencies: @@ -20487,6 +20540,13 @@ __metadata: languageName: node linkType: hard +"isbot@npm:3.6.8": + version: 3.6.8 + resolution: "isbot@npm:3.6.8" + checksum: fbc067d6567fc006026f24527fd09ff655f5eb7e3672070ceb7e62afae9973aeb88f37dd29b88318ee25404818bb294bcc0cab93fb447c798294f0fd36b4b436 + languageName: node + linkType: hard + "isexe@npm:^2.0.0": version: 2.0.0 resolution: "isexe@npm:2.0.0" @@ -22404,10 +22464,17 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^9.0.0, lru-cache@npm:^9.1.1": - version: 9.1.1 - resolution: "lru-cache@npm:9.1.1" - checksum: a70630bccc94e6d6bf5523de8103302407a3b0090f4e245d126569ba96f85b4fa10ad537fb5d9435c58ba3762c0880361f8f5a92d7c9d10b59c8fcc8a0c615e5 +"lru-cache@npm:^9.0.0": + version: 9.1.2 + resolution: "lru-cache@npm:9.1.2" + checksum: 886811ab451332c899c230274e7e51507c15e5b3b18f0b39fb55f558978d58799a0b1a50e04d60a448d8c970ff4e6ee718bb119083ca88abb78930284f1e0900 + languageName: node + linkType: hard + +"lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.0.0 + resolution: "lru-cache@npm:10.0.0" + checksum: 347b7b391091e9f91182b6f683ce04329932a542376a2d7d300637213b99f06c222a3bb0f0db59adf246dac6cef1bb509cab352451a96621d07c41b10a20495f languageName: node linkType: hard @@ -22431,7 +22498,7 @@ __metadata: languageName: node linkType: hard -"lz-string@npm:^1.4.4, lz-string@npm:^1.5.0": +"lz-string@npm:^1.5.0": version: 1.5.0 resolution: "lz-string@npm:1.5.0" bin: @@ -22487,31 +22554,7 @@ __metadata: languageName: node linkType: hard -"make-fetch-happen@npm:^10.0.3": - version: 10.2.1 - resolution: "make-fetch-happen@npm:10.2.1" - dependencies: - agentkeepalive: ^4.2.1 - cacache: ^16.1.0 - http-cache-semantics: ^4.1.0 - http-proxy-agent: ^5.0.0 - https-proxy-agent: ^5.0.0 - is-lambda: ^1.0.1 - lru-cache: ^7.7.1 - minipass: ^3.1.6 - minipass-collect: ^1.0.2 - minipass-fetch: ^2.0.3 - minipass-flush: ^1.0.5 - minipass-pipeline: ^1.2.4 - negotiator: ^0.6.3 - promise-retry: ^2.0.1 - socks-proxy-agent: ^7.0.0 - ssri: ^9.0.0 - checksum: 28ec392f63ab93511f400839dcee83107eeecfaad737d1e8487ea08b4332cd89a8f3319584222edd9f6f1d0833cf516691469496d46491863f9e88c658013949 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^11.0.0, make-fetch-happen@npm:^11.0.1, make-fetch-happen@npm:^11.1.0": +"make-fetch-happen@npm:^11.0.0, make-fetch-happen@npm:^11.0.1, make-fetch-happen@npm:^11.0.3, make-fetch-happen@npm:^11.1.1": version: 11.1.1 resolution: "make-fetch-happen@npm:11.1.1" dependencies: @@ -22644,11 +22687,11 @@ __metadata: linkType: hard "markdown-to-jsx@npm:^7.1.8": - version: 7.2.0 - resolution: "markdown-to-jsx@npm:7.2.0" + version: 7.2.1 + resolution: "markdown-to-jsx@npm:7.2.1" peerDependencies: react: ">= 0.14.0" - checksum: 43056a49a222efddb0d5a055bc0ad61e038ac299d1008db4c4bebb270b4efc9872dc51dad2f6078d58bf178f8f15df6677f6e67295095284d8b61cfb8e9876f3 + checksum: 002ba7c723853c456a4902976d5f5a15d9585bd75dc6ab3add783b4a346e3372327c4fffd7843f30fd5b6550c5fd97e7142330521a5886f8b770db4c61558d61 languageName: node linkType: hard @@ -22728,11 +22771,11 @@ __metadata: linkType: hard "memfs@npm:^3.4.1, memfs@npm:^3.4.3": - version: 3.5.1 - resolution: "memfs@npm:3.5.1" + version: 3.5.3 + resolution: "memfs@npm:3.5.3" dependencies: - fs-monkey: ^1.0.3 - checksum: c0365330bd861b900284c5b50056dddc841ab64196cc8eb164214104031559130ab129c20de67c91314bc7b2b4f20d521d43b0e389080ac2bf6bf77813601b2c + fs-monkey: ^1.0.4 + checksum: 038fc81bce17ea92dde15aaa68fa0fdaf4960c721ce3ffc7c2cb87a259333f5159784ea48b3b72bf9e054254d9d0d0d5209d0fdc3d07d08653a09933b168fbd7 languageName: node linkType: hard @@ -23038,11 +23081,11 @@ __metadata: linkType: hard "minimatch@npm:^9.0.0, minimatch@npm:^9.0.1": - version: 9.0.1 - resolution: "minimatch@npm:9.0.1" + version: 9.0.2 + resolution: "minimatch@npm:9.0.2" dependencies: brace-expansion: ^2.0.1 - checksum: aa043eb8822210b39888a5d0d28df0017b365af5add9bd522f180d2a6962de1cbbf1bdeacdb1b17f410dc3336bc8d76fb1d3e814cdc65d00c2f68e01f0010096 + checksum: 39157d5fd831a7981f7c0c5b22a0e0c2ae8a987ec4a4aeaacc21d3e85da24ce812808cbf7c07cde0d63ad1cf307f73be581131a7a84eeda65f00be1f51972471 languageName: node linkType: hard @@ -23088,21 +23131,6 @@ __metadata: languageName: node linkType: hard -"minipass-fetch@npm:^2.0.3": - version: 2.1.2 - resolution: "minipass-fetch@npm:2.1.2" - dependencies: - encoding: ^0.1.13 - minipass: ^3.1.6 - minipass-sized: ^1.0.3 - minizlib: ^2.1.2 - dependenciesMeta: - encoding: - optional: true - checksum: 33ab2c5bdb3d91b9cb8bc6ae42d7418f4f00f7f7beae14b3bb21ea18f9224e792f560a6e17b6f1be12bbeb70dbe99a269f4204c60e5d99130a0777b153505c43 - languageName: node - linkType: hard - "minipass-fetch@npm:^3.0.0": version: 3.0.3 resolution: "minipass-fetch@npm:3.0.3" @@ -23155,7 +23183,7 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^3.0.0, minipass@npm:^3.1.0, minipass@npm:^3.1.1, minipass@npm:^3.1.3, minipass@npm:^3.1.6": +"minipass@npm:^3.0.0, minipass@npm:^3.1.0, minipass@npm:^3.1.1, minipass@npm:^3.1.3": version: 3.3.6 resolution: "minipass@npm:3.3.6" dependencies: @@ -23572,9 +23600,9 @@ __metadata: linkType: hard "node-fetch-native@npm:^1.0.2": - version: 1.1.1 - resolution: "node-fetch-native@npm:1.1.1" - checksum: 4b12e42c7bd80688acbfd8cceaa246aa00c532d00193e049d9ccce7038b135932a7f1d8a12107e790b827f295d1fd9e76706b634bce7c7e375e6a2f96e233e0f + version: 1.2.0 + resolution: "node-fetch-native@npm:1.2.0" + checksum: 85faa0b7af6884fd615ddc05ec70f05d3818bef8ece43952c49dd849885b21fe7cef54f62cf17b9c0faadfe13498f667a996070d386918ab7017b46c725c5ff6 languageName: node linkType: hard @@ -23667,13 +23695,14 @@ __metadata: linkType: hard "node-gyp@npm:^9.0.0, node-gyp@npm:latest": - version: 9.3.1 - resolution: "node-gyp@npm:9.3.1" + version: 9.4.0 + resolution: "node-gyp@npm:9.4.0" dependencies: env-paths: ^2.2.0 + exponential-backoff: ^3.1.1 glob: ^7.1.4 graceful-fs: ^4.2.6 - make-fetch-happen: ^10.0.3 + make-fetch-happen: ^11.0.3 nopt: ^6.0.0 npmlog: ^6.0.0 rimraf: ^3.0.2 @@ -23682,7 +23711,7 @@ __metadata: which: ^2.0.2 bin: node-gyp: bin/node-gyp.js - checksum: 3285c110768eb65aadd9aa1d056f917e594ea22611d21fd535ab3677ea433d0a281e7f09bc73d53e64b02214f4379dbca476dc33faffe455b0ac1d5ba92802f4 + checksum: e8dfbe2b02f23d056f69e01c409381963e92c71cafba6c9cfbf63b038f65ca19ab8183bb6891d080e59c4eb2cc425fc736f42e90afc0f0030ecd97bfc64fb7ad languageName: node linkType: hard @@ -23781,13 +23810,13 @@ __metadata: linkType: hard "nopt@npm:^7.0.0": - version: 7.1.0 - resolution: "nopt@npm:7.1.0" + version: 7.2.0 + resolution: "nopt@npm:7.2.0" dependencies: abbrev: ^2.0.0 bin: nopt: bin/nopt.js - checksum: f6dc14b7ae956d561798ed98e40ab5354ace6b6b23a74c7fd5f60036b5d734a6a99e4873c7a76dccda1b0326f0e3cdd432536fe8d1eab4d96fe525b53830f674 + checksum: 9bd7198df6f16eb29ff16892c77bcf7f0cc41f9fb5c26280ac0def2cf8cf319f3b821b3af83eba0e74c85807cc430a16efe0db58fe6ae1f41e69519f585b6aff languageName: node linkType: hard @@ -24457,16 +24486,16 @@ __metadata: linkType: hard "optionator@npm:^0.9.1": - version: 0.9.1 - resolution: "optionator@npm:0.9.1" + version: 0.9.3 + resolution: "optionator@npm:0.9.3" dependencies: + "@aashutoshrathi/word-wrap": ^1.2.3 deep-is: ^0.1.3 fast-levenshtein: ^2.0.6 levn: ^0.4.1 prelude-ls: ^1.2.1 type-check: ^0.4.0 - word-wrap: ^1.2.3 - checksum: 8b574d50b032f34713dc09bfacdc351824f713c3c80773ead3a05ab977364de88f2f3962a6f15437747b93a5e0636928253949970daea3aaeeefbd3a525da6a4 + checksum: 66fba794d425b5be51353035cf3167ce6cfa049059cbb93229b819167687e0f48d2bc4603fcb21b091c99acb516aae1083624675b15c4765b2e4693a085e959c languageName: node linkType: hard @@ -24995,13 +25024,13 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.6.1, path-scurry@npm:^1.7.0": - version: 1.9.2 - resolution: "path-scurry@npm:1.9.2" +"path-scurry@npm:^1.10.0, path-scurry@npm:^1.6.1, path-scurry@npm:^1.7.0": + version: 1.10.0 + resolution: "path-scurry@npm:1.10.0" dependencies: - lru-cache: ^9.1.1 + lru-cache: ^9.1.1 || ^10.0.0 minipass: ^5.0.0 || ^6.0.2 - checksum: 99a3461a1ebc5269165170a744367a900802dc1ecc8a17a8c9700cca9b00b0938c8a06d57ec9bc9a485e430fd37c647f4029ccaf31b5f9dacedaf685cef3e69a + checksum: dcc4109928c9a0991f0e1719c73b0a184eb7f313fe3eb2242f25274b1e761f53041989fb6b069541b88f58ee6dfbbecf94922225e0c5a3fba8112c9c60abb391 languageName: node linkType: hard @@ -25036,9 +25065,9 @@ __metadata: linkType: hard "pathe@npm:^1.1.0": - version: 1.1.0 - resolution: "pathe@npm:1.1.0" - checksum: 1c5d07378475bcdf4f435684566190d35d06be2db8b8e61cf9e866ae649941fdb093d732fa01b0f51d86e3f94140543c2571b0bf65a87ca7b5d1f52152aabe03 + version: 1.1.1 + resolution: "pathe@npm:1.1.1" + checksum: 3ae5a0529c3415d91c3ac9133f52cffea54a0dd46892fe059f4b80faf36fd207957d4594bdc87043b65d0761b1e5728f81f46bafff3b5302da4e2e48889b8c0e languageName: node linkType: hard @@ -25151,9 +25180,9 @@ __metadata: linkType: hard "pino-std-serializers@npm:^6.0.0": - version: 6.2.1 - resolution: "pino-std-serializers@npm:6.2.1" - checksum: 6f5e7525edc515160a2edb414b327096f7a305ffdf93cafdec692b660b11abec98dc79da57c5084ea59ff5413af03f75ec6d1d34a6d48cb8e9505babcc2f866e + version: 6.2.2 + resolution: "pino-std-serializers@npm:6.2.2" + checksum: 8f1c7f0f0d8f91e6c6b5b2a6bfb48f06441abeb85f1c2288319f736f9c6d814fbeebe928d2314efc2ba6018fa7db9357a105eca9fc99fc1f28945a8a8b28d3d5 languageName: node linkType: hard @@ -25179,9 +25208,9 @@ __metadata: linkType: hard "pirates@npm:^4.0.4, pirates@npm:^4.0.5": - version: 4.0.5 - resolution: "pirates@npm:4.0.5" - checksum: 58b6ff0f137a3d70ff34ac4802fd19819cdc19b53e9c95adecae6c7cfc77719a11f561ad85d46e79e520ef57c31145a564c8bc3bee8cfee75d441fab2928a51d + version: 4.0.6 + resolution: "pirates@npm:4.0.6" + checksum: 00d5fa51f8dded94d7429700fb91a0c1ead00ae2c7fd27089f0c5b63e6eca36197fe46384631872690a66f390c5e27198e99006ab77ae472692ab9c2ca903f36 languageName: node linkType: hard @@ -25890,7 +25919,7 @@ __metadata: languageName: node linkType: hard -"protobufjs@npm:7.2.3, protobufjs@npm:^7.0.0": +"protobufjs@npm:7.2.3": version: 7.2.3 resolution: "protobufjs@npm:7.2.3" dependencies: @@ -25934,6 +25963,26 @@ __metadata: languageName: node linkType: hard +"protobufjs@npm:^7.0.0": + version: 7.2.4 + resolution: "protobufjs@npm:7.2.4" + dependencies: + "@protobufjs/aspromise": ^1.1.2 + "@protobufjs/base64": ^1.1.2 + "@protobufjs/codegen": ^2.0.4 + "@protobufjs/eventemitter": ^1.1.0 + "@protobufjs/fetch": ^1.1.0 + "@protobufjs/float": ^1.0.2 + "@protobufjs/inquire": ^1.1.0 + "@protobufjs/path": ^1.1.2 + "@protobufjs/pool": ^1.1.0 + "@protobufjs/utf8": ^1.1.0 + "@types/node": ">=13.7.0" + long: ^5.0.0 + checksum: 7610b4e3b961e7637e8f61099931161af7f47f8b88b4a0d55124158f9b7fbe6e8fdfe551803b0c65fefad9d58d49332f0b5b4aa5826d8dcd8b062c351cbe2ebb + languageName: node + linkType: hard + "protocols@npm:^2.0.0, protocols@npm:^2.0.1": version: 2.0.1 resolution: "protocols@npm:2.0.1" @@ -26067,7 +26116,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^1.2.4, punycode@npm:^1.3.2": +"punycode@npm:^1.2.4, punycode@npm:^1.3.2, punycode@npm:^1.4.1": version: 1.4.1 resolution: "punycode@npm:1.4.1" checksum: 354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 @@ -26131,7 +26180,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.11.2, qs@npm:^6.10.0": +"qs@npm:6.11.2, qs@npm:^6.10.0, qs@npm:^6.11.0": version: 6.11.2 resolution: "qs@npm:6.11.2" dependencies: @@ -26379,11 +26428,11 @@ __metadata: linkType: hard "react-inspector@npm:^6.0.0": - version: 6.0.1 - resolution: "react-inspector@npm:6.0.1" + version: 6.0.2 + resolution: "react-inspector@npm:6.0.2" peerDependencies: react: ^16.8.4 || ^17.0.0 || ^18.0.0 - checksum: 34b0ba6e8c718aa0bbde3bc325531bc94b1e536eb226579e57cb912065693ff70611308c8e567c8e5703b0513655eb5258e5c3ac447e6a5003a44559abc84fa7 + checksum: 8f9b23c21b4d95722e28c9455c2bf00fd9437347714382594461f98e5b9954d60864d0f4e74e881639b065e752a97ba52a65e39930c234072e5bff291bb02b5e languageName: node linkType: hard @@ -27263,8 +27312,8 @@ __metadata: linkType: hard "rollup@npm:^3.21.0": - version: 3.23.0 - resolution: "rollup@npm:3.23.0" + version: 3.25.3 + resolution: "rollup@npm:3.25.3" dependencies: fsevents: ~2.3.2 dependenciesMeta: @@ -27272,7 +27321,7 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: e0cdd5c188272e33d12c7f411f1a5727dbe97bdc58e178b14d4dccf679152c14abaae5130d5de7bc69ba5be5de829c367dc5c29ba93725756a15a241b80de4ab + checksum: 571f2a365a694fd83af585d1df4bf7617d45a77cef58891deb8bf7670ab8f3ed7f74db6ac983a3a7d648db4ce0e66a25636d70ca828c67b80ad8256cabeeac04 languageName: node linkType: hard @@ -27615,17 +27664,6 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.3.4": - version: 7.3.4 - resolution: "semver@npm:7.3.4" - dependencies: - lru-cache: ^6.0.0 - bin: - semver: bin/semver.js - checksum: 16b77752071597135b934bb33258badbac6c1cebbabe507ce31f68db3229acae7afa9602265c375c34df092339caa738b105e0c62240536ea1efd4767c36e674 - languageName: node - linkType: hard - "semver@npm:7.5.3, semver@npm:^7.0.0, semver@npm:^7.1.1, semver@npm:^7.1.2, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.0, semver@npm:^7.5.2": version: 7.5.3 resolution: "semver@npm:7.5.3" @@ -27896,15 +27934,16 @@ __metadata: linkType: hard "sigstore@npm:^1.3.0, sigstore@npm:^1.4.0": - version: 1.5.2 - resolution: "sigstore@npm:1.5.2" + version: 1.6.0 + resolution: "sigstore@npm:1.6.0" dependencies: "@sigstore/protobuf-specs": ^0.1.0 + "@sigstore/tuf": ^1.0.0 make-fetch-happen: ^11.0.1 tuf-js: ^1.1.3 bin: sigstore: bin/sigstore.js - checksum: dfe6426c7fc9631883280655f54bd264d2a4f2fa95815ada678cafef5b9d8b02468ea1c560a95a1e7538017f4fa77f7f06840117b1c61289cad8e547bca47f50 + checksum: d0dd051774765ded57d19652a115ddebd2bd3253b1db11ce6cb83f32ab86c3f200bfe83138c577ea179236e148d93d3480430561081eef7cb0d8deab1b466f75 languageName: node linkType: hard @@ -28414,7 +28453,7 @@ __metadata: languageName: node linkType: hard -"ssri@npm:^9.0.0, ssri@npm:^9.0.1": +"ssri@npm:^9.0.1": version: 9.0.1 resolution: "ssri@npm:9.0.1" dependencies: @@ -29179,16 +29218,16 @@ __metadata: linkType: hard "terser@npm:^5.10.0, terser@npm:^5.16.8": - version: 5.17.6 - resolution: "terser@npm:5.17.6" + version: 5.18.2 + resolution: "terser@npm:5.18.2" dependencies: - "@jridgewell/source-map": ^0.3.2 - acorn: ^8.5.0 + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 commander: ^2.20.0 source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 4c175f35af332320189db20e2b37b0671c51164d55a3fc44ed5b74b023858fd670cb987de7b2e8e3704b0d863f95ea9a0ecff37c8c01a48906fb7f81b512a5c8 + checksum: 7a7203eceef379c6381f5b43aaed509d12381c7453baee28b320fcd968523347f1bf4ba297cd3155ec860e9604279a1c9bc7060b35d9c34fae94c80cfa2738c2 languageName: node linkType: hard @@ -29437,14 +29476,14 @@ __metadata: linkType: hard "tough-cookie@npm:^4.1.2": - version: 4.1.2 - resolution: "tough-cookie@npm:4.1.2" + version: 4.1.3 + resolution: "tough-cookie@npm:4.1.3" dependencies: psl: ^1.1.33 punycode: ^2.1.1 universalify: ^0.2.0 url-parse: ^1.5.3 - checksum: 1f9d97bc9ff22b41e107eca4a146064f916e567b5557795dbfe742f098557ba1101b8f7c4e02ac785236663f7f086c37dc595a5b9813ef8fb27f8d800dc9eb9b + checksum: 4fc0433a0cba370d57c4b240f30440c848906dee3180bb6e85033143c2726d322e7e4614abb51d42d111ebec119c4876ed8d7247d4113563033eebbc1739c831 languageName: node linkType: hard @@ -29656,10 +29695,17 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.5.0, tslib@npm:~2.5.0": - version: 2.5.2 - resolution: "tslib@npm:2.5.2" - checksum: 34fa100454708fa8acb7afc2b07d80e0332081e2075ddd912ba959af3b24f969663dac6d602961e57371dc05683badb83b3186ada92c4631ec777e02e3aab608 +"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.2.0, tslib@npm:^2.3.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.4.1, tslib@npm:^2.5.0": + version: 2.6.0 + resolution: "tslib@npm:2.6.0" + checksum: 8d18020a8b9e70ecc529a744c883c095f177805efdbc9786bd50bd82a46c17547923133c5444fbcaf1f7f1c44e0e29c89f73ecf6d8fd1039668024a073a81dc6 + languageName: node + linkType: hard + +"tslib@npm:~2.5.0": + version: 2.5.3 + resolution: "tslib@npm:2.5.3" + checksum: 4cb1817d34fae5b27d146e6c4a468d4155097d95c1335d0bc9690f11f33e63844806bf4ed6d97c30c72b8d85261b66cbbe16d871d9c594ac05701ec83e62a607 languageName: node linkType: hard @@ -29699,13 +29745,13 @@ __metadata: linkType: hard "tuf-js@npm:^1.1.3": - version: 1.1.6 - resolution: "tuf-js@npm:1.1.6" + version: 1.1.7 + resolution: "tuf-js@npm:1.1.7" dependencies: "@tufjs/models": 1.0.4 debug: ^4.3.4 - make-fetch-happen: ^11.1.0 - checksum: bb34127ba88d842a8c186e297bebeb75e2cd27cb4a39b51996294da34f9e6b72b3aa052ab2dbeb87f2ad061076bddca879ca9f8250cc94c382204fffce536c27 + make-fetch-happen: ^11.1.1 + checksum: 7c4980ada7a55f2670b895e8d9345ef2eec4a471c47f6127543964a12a8b9b69f16002990e01a138cd775aa954880b461186a6eaf7b86633d090425b4273375b languageName: node linkType: hard @@ -29821,9 +29867,9 @@ __metadata: linkType: hard "type-fest@npm:^3.0.0": - version: 3.11.1 - resolution: "type-fest@npm:3.11.1" - checksum: 55c0ba11e8b494684bf63f76e762ac44a95a9243a873cfc03c97f909477938d4a80f0c6265bfae92074072305447428748726385bbf2be4484b8451d73c84881 + version: 3.12.0 + resolution: "type-fest@npm:3.12.0" + checksum: c51abb6bcb7f92601a9b143d0fa44cacc1d1c19041300168303476c36f05e561610b8c2457e321a107c715160a33f63f507552034d2fd49a7bc1dbb4c1de565f languageName: node linkType: hard @@ -29878,7 +29924,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:5.1.3, typescript@npm:>=3 < 6": +"typescript@npm:5.1.3": version: 5.1.3 resolution: "typescript@npm:5.1.3" bin: @@ -29888,7 +29934,17 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@5.1.3#~builtin, typescript@patch:typescript@>=3 < 6#~builtin": +"typescript@npm:>=3 < 6": + version: 5.1.5 + resolution: "typescript@npm:5.1.5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 952b29830b1dbc6183fc9d305ac4f2969a612429ddfbc5273a547faea81ec5c67ca5d9c41e3cfcb20be10bfe5c65b3e5c3eac5acb8c3dfb2b0a3676209221de0 + languageName: node + linkType: hard + +"typescript@patch:typescript@5.1.3#~builtin": version: 5.1.3 resolution: "typescript@patch:typescript@npm%3A5.1.3#~builtin::version=5.1.3&hash=5da071" bin: @@ -29898,10 +29954,20 @@ __metadata: languageName: node linkType: hard -"ua-parser-js@npm:^0.7.30": - version: 0.7.35 - resolution: "ua-parser-js@npm:0.7.35" - checksum: 53091de47669f042a7644b6f8b8f21cf901f94b58a4658249db47c47569295aadf1c3ae11c92cb8cafa57b483ab75cb206b9476480a698adc68158f8476bb8f8 +"typescript@patch:typescript@>=3 < 6#~builtin": + version: 5.1.5 + resolution: "typescript@patch:typescript@npm%3A5.1.5#~builtin::version=5.1.5&hash=5da071" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 4a90551fd363da5e7ef61e5ec3a68532c769041d67ad1f629700c7db36d9bd64593bbb5162ab0d5e8fd136a295713955bbd099180b20da61def9c57ccfa6f933 + languageName: node + linkType: hard + +"ua-parser-js@npm:^1.0.35": + version: 1.0.35 + resolution: "ua-parser-js@npm:1.0.35" + checksum: 4641332fdf163ecdec4810cc2335932754f1b71527097f06005a658de256e22f5836a4a7860619c9e611d578e0451ff39dbff1a9b83c6615e3b0b3dd29588c30 languageName: node linkType: hard @@ -30022,15 +30088,6 @@ __metadata: languageName: node linkType: hard -"unique-filename@npm:^2.0.0": - version: 2.0.1 - resolution: "unique-filename@npm:2.0.1" - dependencies: - unique-slug: ^3.0.0 - checksum: 55d95cd670c4a86117ebc34d394936d712d43b56db6bc511f9ca00f666373818bf9f075fb0ab76bcbfaf134592ef26bb75aad20786c1ff1ceba4457eaba90fb8 - languageName: node - linkType: hard - "unique-filename@npm:^3.0.0": version: 3.0.0 resolution: "unique-filename@npm:3.0.0" @@ -30049,15 +30106,6 @@ __metadata: languageName: node linkType: hard -"unique-slug@npm:^3.0.0": - version: 3.0.0 - resolution: "unique-slug@npm:3.0.0" - dependencies: - imurmurhash: ^0.1.4 - checksum: 617240eb921af803b47d322d75a71a363dacf2e56c29ae5d1404fad85f64f4ec81ef10ee4fd79215d0202cbe1e5a653edb0558d59c9c81d3bd538c2d58e4c026 - languageName: node - linkType: hard - "unique-slug@npm:^4.0.0": version: 4.0.0 resolution: "unique-slug@npm:4.0.0" @@ -30298,12 +30346,12 @@ __metadata: linkType: hard "url@npm:^0.11.0": - version: 0.11.0 - resolution: "url@npm:0.11.0" + version: 0.11.1 + resolution: "url@npm:0.11.1" dependencies: - punycode: 1.3.2 - querystring: 0.2.0 - checksum: bbe05f9f570ec5c06421c50ca63f287e61279092eed0891db69a9619323703ccd3987e6eed234c468794cf25680c599680d5c1f58d26090f1956c8e9ed8346a2 + punycode: ^1.4.1 + qs: ^6.11.0 + checksum: 9e18c57b854d6a8e0288c4ddf21f9e30273a0ef2efb28a7e3e3d6eac392637dbdecce0d8f616586d58ff43154997150ecc2c9873e6c845d1e742e24c940b6e12 languageName: node linkType: hard @@ -30870,13 +30918,13 @@ __metadata: linkType: hard "webpack-hot-middleware@npm:^2.25.1": - version: 2.25.3 - resolution: "webpack-hot-middleware@npm:2.25.3" + version: 2.25.4 + resolution: "webpack-hot-middleware@npm:2.25.4" dependencies: ansi-html-community: 0.0.8 html-entities: ^2.1.0 strip-ansi: ^6.0.0 - checksum: dca26d6d32eb684469830b4074dcd11c298036fe3ec8276ea5a69bc14bc8a53aab2494e02871ada146ec0881965d7018d559683cbcc73bcafcfa4da1184e92b5 + checksum: c0702d308a39bdbc9277d66df50272e8c358c2238cecb0881df57136f54cb7a3d8291320b13075325b58f7a3cbf7a1ef10829554a5bc2ddfa3effbf416dc8e8c languageName: node linkType: hard @@ -31199,7 +31247,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:^1.2.3, word-wrap@npm:~1.2.3": +"word-wrap@npm:~1.2.3": version: 1.2.3 resolution: "word-wrap@npm:1.2.3" checksum: 1cb6558996deb22c909330db1f01d672feee41d7f0664492912de3de282da3f28ba2d49e87b723024e99d56ba2dac2f3ab28f8db07ac199f5e5d5e2e437833de From 85f1f760e4bec2e99cb5e7089bb6dd4399773827 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Wed, 28 Jun 2023 16:35:44 +0200 Subject: [PATCH 14/26] Fix merge conflict --- packages/cli/src/commands/buildHandler.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index 372708456020..e7af67fcafba 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -116,6 +116,9 @@ export const handler = async ({ // We don't have any parallel tasks right now, but someone might add // one in the future as a performance optimization. await execa(`yarn rw-vite-build --webDir="${rwjsPaths.web.base}"`, { + stdio: verbose ? 'inherit' : 'pipe', + shell: true, + }) // @WARN DO NOT MERGE TEMPORARY HACK // @WARN DO NOT MERGE TEMPORARY HACK @@ -126,7 +129,7 @@ export const handler = async ({ // @WARN DO NOT MERGE TEMPORARY HACK process.chdir(rwjsPaths.web.base) - // @TODO: we need to use a binary here, so the the cwd is correct + // TODO (STREAMING) we need to use a binary here, so the the cwd is correct await buildFeServer({ verbose, }) From eacfff0f272edbdeb057824d0542c442e78b2e3c Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Thu, 29 Jun 2023 19:53:00 +0200 Subject: [PATCH 15/26] Fix serve.js merge --- packages/cli/src/commands/serve.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index 3fa15e679f66..89a6023ec55b 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -35,14 +35,13 @@ const streamServerErrorHandler = () => { } export async function builder(yargs) { - const redwoodProjectPaths = getPaths() const redwoodProjectConfig = getConfig() yargs .usage('usage: $0 ') .command({ command: '$0', - description: 'Run both api and web servers. Uses the web port and host', + description: 'Run both api and web servers', handler: (argv) => { recordTelemetryAttributes({ command: 'serve', @@ -57,15 +56,10 @@ export async function builder(yargs) { builder: (yargs) => yargs.options({ port: { - default: redwoodProjectConfig.web.port, + default: getConfig().web?.port || 8910, type: 'number', alias: 'p', }, - host: { - default: redwoodProjectConfig.web.host, - type: 'string', - }, - socket: { type: 'string' }, }), }) .command({ From 14a1c63adf8b78deb91fb4199643a9958b9d5f6f Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Thu, 29 Jun 2023 19:58:22 +0200 Subject: [PATCH 16/26] More serve.js fixes --- packages/cli/src/commands/serve.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index 89a6023ec55b..22f9dc43f22b 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -34,9 +34,7 @@ const streamServerErrorHandler = () => { ) } -export async function builder(yargs) { - const redwoodProjectConfig = getConfig() - +export const builder = async (yargs) => { yargs .usage('usage: $0 ') .command({ @@ -68,12 +66,12 @@ export async function builder(yargs) { builder: (yargs) => yargs.options({ port: { - default: redwoodProjectConfig.web.port, + default: getConfig().web.port, type: 'number', alias: 'p', }, host: { - default: redwoodProjectConfig.web.host, + default: getConfig().web.host, type: 'string', }, socket: { type: 'string' }, From f2f191db65e0661edc5b156645e4a5115627b903 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Thu, 29 Jun 2023 19:59:41 +0200 Subject: [PATCH 17/26] serve.js keep trying --- packages/cli/src/commands/serve.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index 22f9dc43f22b..d94414bb5c3f 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -40,6 +40,14 @@ export const builder = async (yargs) => { .command({ command: '$0', description: 'Run both api and web servers', + builder: (yargs) => + yargs.options({ + port: { + default: getConfig().web?.port || 8910, + type: 'number', + alias: 'p', + }, + }), handler: (argv) => { recordTelemetryAttributes({ command: 'serve', @@ -51,14 +59,6 @@ export const builder = async (yargs) => { streamServerErrorHandler() }, - builder: (yargs) => - yargs.options({ - port: { - default: getConfig().web?.port || 8910, - type: 'number', - alias: 'p', - }, - }), }) .command({ command: 'both', From eac929605cc0b113dc140b78cc940f351c7cb8c9 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Thu, 29 Jun 2023 23:35:11 +0200 Subject: [PATCH 18/26] Revert prerender changes to make current CI pass --- packages/router/src/active-route-loader.tsx | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/router/src/active-route-loader.tsx b/packages/router/src/active-route-loader.tsx index 1d3c1e5a7cb7..ae3e59dc4851 100644 --- a/packages/router/src/active-route-loader.tsx +++ b/packages/router/src/active-route-loader.tsx @@ -12,19 +12,15 @@ interface Props { children?: React.ReactNode } -const isPrerendered = false +let isPrerendered = false -// TODO (STREAMING) -// SSR and streaming changes how we mount the React app (we render the whole page, including head and body) -// This logic is no longer valid and needs to be rethought +if (typeof window !== 'undefined') { + const redwoodAppElement = document.getElementById('redwood-app') -// if (typeof window !== 'undefined') { -// const redwoodAppElement = document.getElementById('redwood-app') - -// if (redwoodAppElement && redwoodAppElement.children.length > 0) { -// isPrerendered = true -// } -// } + if (redwoodAppElement && redwoodAppElement.children.length > 0) { + isPrerendered = true + } +} let firstLoad = true From 142cbe604b65b99808a70a9689566bae91f65a2e Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Thu, 29 Jun 2023 23:42:01 +0200 Subject: [PATCH 19/26] buildHandler: Wrap in feature flag check --- packages/cli/src/commands/buildHandler.js | 56 ++++++++++++----------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index e7af67fcafba..9e3d555e51c7 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -3,6 +3,7 @@ import path from 'path' import execa from 'execa' import { Listr } from 'listr2' +import { get } from 'lodash' import { rimraf } from 'rimraf' import terminalLink from 'terminal-link' @@ -105,34 +106,35 @@ export const handler = async ({ side.includes('web') && { title: 'Building Web...', task: async () => { + const streamingSsrEnabled = + getConfig().experimental?.streamingSsr && + getConfig().experimental?.streamingSsr.enabled + if (getConfig().web.bundler !== 'webpack') { - // @NOTE: we're using the vite build command here, instead of the - // buildWeb function directly because we want the process.cwd to be - // the web directory, not the root of the project. - // This is important for postcss/tailwind to work correctly - // Having a separate binary lets us contain the change of cwd to that - // process only. If we changed cwd here, or in the buildWeb function, - // it could affect other things that run in parallel while building. - // We don't have any parallel tasks right now, but someone might add - // one in the future as a performance optimization. - await execa(`yarn rw-vite-build --webDir="${rwjsPaths.web.base}"`, { - stdio: verbose ? 'inherit' : 'pipe', - shell: true, - }) - - // @WARN DO NOT MERGE TEMPORARY HACK - // @WARN DO NOT MERGE TEMPORARY HACK - // @WARN DO NOT MERGE TEMPORARY HACK - // @WARN DO NOT MERGE TEMPORARY HACK - // @WARN DO NOT MERGE TEMPORARY HACK - // @WARN DO NOT MERGE TEMPORARY HACK - // @WARN DO NOT MERGE TEMPORARY HACK - process.chdir(rwjsPaths.web.base) - - // TODO (STREAMING) we need to use a binary here, so the the cwd is correct - await buildFeServer({ - verbose, - }) + if (!streamingSsrEnabled) { + // @NOTE: we're using the vite build command here, instead of the + // buildWeb function directly because we want the process.cwd to be + // the web directory, not the root of the project. + // This is important for postcss/tailwind to work correctly + // Having a separate binary lets us contain the change of cwd to that + // process only. If we changed cwd here, or in the buildWeb function, + // it could affect other things that run in parallel while building. + // We don't have any parallel tasks right now, but someone might add + // one in the future as a performance optimization. + await execa(`yarn rw-vite-build --webDir="${rwjsPaths.web.base}"`, { + stdio: verbose ? 'inherit' : 'pipe', + shell: true, + }) + } else { + // TODO (STREAMING) we need to contain this in a separate binary + process.chdir(rwjsPaths.web.base) + + // TODO (STREAMING) we need to use a binary here, so the the cwd is correct + // Should merge this with the existing rw-vite-build binary + await buildFeServer({ + verbose, + }) + } } else { await execa( `yarn cross-env NODE_ENV=production webpack --config ${require.resolve( From 1791deedd6878a8b0f9f3dba21145263ecb1d1f7 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Thu, 29 Jun 2023 23:50:22 +0200 Subject: [PATCH 20/26] serve.js: streamingSsr feature flag --- packages/cli/src/commands/buildHandler.js | 4 +-- packages/cli/src/commands/serve.js | 41 +++++++---------------- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index 9e3d555e51c7..def5cc8809bb 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -3,7 +3,6 @@ import path from 'path' import execa from 'execa' import { Listr } from 'listr2' -import { get } from 'lodash' import { rimraf } from 'rimraf' import terminalLink from 'terminal-link' @@ -107,8 +106,7 @@ export const handler = async ({ title: 'Building Web...', task: async () => { const streamingSsrEnabled = - getConfig().experimental?.streamingSsr && - getConfig().experimental?.streamingSsr.enabled + !!getConfig().experimental?.streamingSsr?.enabled if (getConfig().web.bundler !== 'webpack') { if (!streamingSsrEnabled) { diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index d94414bb5c3f..e1aa6f47b7b3 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -48,34 +48,6 @@ export const builder = async (yargs) => { alias: 'p', }, }), - handler: (argv) => { - recordTelemetryAttributes({ - command: 'serve', - port: argv.port, - host: argv.host, - socket: argv.socket, - apiHost: argv.apiHost, - }) - - streamServerErrorHandler() - }, - }) - .command({ - command: 'both', - description: 'Run both api and web servers. Uses the web port and host', - builder: (yargs) => - yargs.options({ - port: { - default: getConfig().web.port, - type: 'number', - alias: 'p', - }, - host: { - default: getConfig().web.host, - type: 'string', - }, - socket: { type: 'string' }, - }), handler: async (argv) => { recordTelemetryAttributes({ command: 'serve', @@ -84,6 +56,11 @@ export const builder = async (yargs) => { socket: argv.socket, }) + if (getConfig().experimental?.streamingSsr?.enabled) { + streamServerErrorHandler() + return + } + // Run the experimental server file, if it exists, with web side also if (hasExperimentalServerFile()) { console.log( @@ -188,7 +165,13 @@ export const builder = async (yargs) => { apiHost: argv.apiHost, }) - streamServerErrorHandler() + if (getConfig().experimental?.streamingSsr?.enabled) { + streamServerErrorHandler() + return + } else { + const { webServerHandler } = await import('./serveHandler.js') + await webServerHandler(argv) + } }, }) .middleware((argv) => { From 7389399a059801c99ac69773c2d9dc72509a0e53 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Fri, 30 Jun 2023 00:52:25 +0200 Subject: [PATCH 21/26] Work on getting this mergable by getting behavior closer to what's in main --- packages/cli/src/commands/buildHandler.js | 5 +--- packages/cli/src/commands/serve.js | 7 +++--- packages/vite/src/devFeServer.ts | 2 ++ .../web/src/components/RedwoodProvider.tsx | 25 ++++++++++++++----- packages/web/src/components/htmlTags.tsx | 2 +- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index def5cc8809bb..add07a73eb59 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -105,11 +105,8 @@ export const handler = async ({ side.includes('web') && { title: 'Building Web...', task: async () => { - const streamingSsrEnabled = - !!getConfig().experimental?.streamingSsr?.enabled - if (getConfig().web.bundler !== 'webpack') { - if (!streamingSsrEnabled) { + if (!getConfig().experimental?.streamingSsr?.enabled) { // @NOTE: we're using the vite build command here, instead of the // buildWeb function directly because we want the process.cwd to be // the web directory, not the root of the project. diff --git a/packages/cli/src/commands/serve.js b/packages/cli/src/commands/serve.js index e1aa6f47b7b3..57f1518d24be 100644 --- a/packages/cli/src/commands/serve.js +++ b/packages/cli/src/commands/serve.js @@ -47,6 +47,7 @@ export const builder = async (yargs) => { type: 'number', alias: 'p', }, + socket: { type: 'string' }, }), handler: async (argv) => { recordTelemetryAttributes({ @@ -168,10 +169,10 @@ export const builder = async (yargs) => { if (getConfig().experimental?.streamingSsr?.enabled) { streamServerErrorHandler() return - } else { - const { webServerHandler } = await import('./serveHandler.js') - await webServerHandler(argv) } + + const { webServerHandler } = await import('./serveHandler.js') + await webServerHandler(argv) }, }) .middleware((argv) => { diff --git a/packages/vite/src/devFeServer.ts b/packages/vite/src/devFeServer.ts index 7dcfc7d3603f..61064150b929 100644 --- a/packages/vite/src/devFeServer.ts +++ b/packages/vite/src/devFeServer.ts @@ -113,6 +113,8 @@ async function createServer() { // TODO (STREAMING) CSS is handled by Vite in dev mode, we don't need to worry about it in dev // but..... it causes a flash of unstyled content. For now I'm just injecting index css here + // We believe we saw a fix for this somewhere in the Waku sources. And + // also in the Vite issues. const FIXME_HardcodedIndexCss = ['index.css'] const assetMap = JSON.stringify({ diff --git a/packages/web/src/components/RedwoodProvider.tsx b/packages/web/src/components/RedwoodProvider.tsx index c46aa4ab3b1e..bc84deeb17af 100644 --- a/packages/web/src/components/RedwoodProvider.tsx +++ b/packages/web/src/components/RedwoodProvider.tsx @@ -1,21 +1,34 @@ -import { HelmetProvider } from 'react-helmet-async' +import { Helmet, HelmetProvider } from 'react-helmet-async' interface RedwoodProviderProps { children: React.ReactNode titleTemplate?: string } -export const RedwoodProvider = ({ children }: RedwoodProviderProps) => { +export const RedwoodProvider = ({ + children, + titleTemplate, +}: RedwoodProviderProps) => { + const appTitle = globalThis.__REDWOOD__APP_TITLE + const template = () => { + if (titleTemplate) { + let template = titleTemplate.replace(/%AppTitle/g, appTitle) + template = template.replace(/%PageTitle/g, '%s') + return template + } + return '' + } // eslint-disable-next-line @typescript-eslint/no-unused-vars - // TODO (STREAMING) disabling helmet here, because it clashes with meta routeHooks - // but still leaving helmet provider to make it easy to migrate to new setup + // TODO (STREAMING) need to disable helmet here, because it clashes with meta + // routeHooks but can still leave helmet provider to make it easy to migrate + // to new setup // TODO (STREAMING) Figure out how the Helmet stuff can live along side // streaming while streaming is still experimental return ( - {/* + {appTitle} - */} + {children} ) diff --git a/packages/web/src/components/htmlTags.tsx b/packages/web/src/components/htmlTags.tsx index 738a185f7b5d..57482830ece8 100644 --- a/packages/web/src/components/htmlTags.tsx +++ b/packages/web/src/components/htmlTags.tsx @@ -65,7 +65,7 @@ interface Other extends Custom { // remix style DIY meta tags, or the more opinionated approach in MetaTags.tsx export type TagDescriptor = | Title - // Not sure why we need these, maybe just for ease of use + // TODO (STREAMING) Not sure why we need these, maybe just for ease of use | NameContent | OpenGraph | HttpEquiv From 58870fe0fd59e988b789f8269fdcb28660cf0a9b Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Fri, 30 Jun 2023 01:06:18 +0200 Subject: [PATCH 22/26] Remove serverData --- packages/vite/src/devFeServer.ts | 18 +++++++----------- packages/vite/src/runFeServer.ts | 13 ++++--------- packages/vite/src/triggerRouteHooks.ts | 22 +++------------------- packages/web/src/routeHooks.types.ts | 6 ++---- packages/web/src/serverContext.tsx | 5 +---- 5 files changed, 17 insertions(+), 47 deletions(-) diff --git a/packages/vite/src/devFeServer.ts b/packages/vite/src/devFeServer.ts index 61064150b929..7f0a95194655 100644 --- a/packages/vite/src/devFeServer.ts +++ b/packages/vite/src/devFeServer.ts @@ -68,7 +68,6 @@ async function createServer() { return matches.length > 0 }) - let serverData = {} let metaTags: TagDescriptor[] = [] if (currentRoute?.redirect) { @@ -89,7 +88,6 @@ async function createServer() { viteDevServer: vite, // because its dev }) - serverData = routeHookOutput.serverData metaTags = routeHookOutput.meta } @@ -108,13 +106,12 @@ async function createServer() { // required, and provides efficient invalidation similar to HMR. const { serverEntry } = await vite.ssrLoadModule(rwPaths.web.entryServer) - // Serialize route context so it can be passed to the client entry - const serializedRouteContext = JSON.stringify(serverData) - - // TODO (STREAMING) CSS is handled by Vite in dev mode, we don't need to worry about it in dev - // but..... it causes a flash of unstyled content. For now I'm just injecting index css here - // We believe we saw a fix for this somewhere in the Waku sources. And - // also in the Vite issues. + // TODO (STREAMING) CSS is handled by Vite in dev mode, we don't need to + // worry about it in dev but..... it causes a flash of unstyled content. + // For now I'm just injecting index css here + // We believe we saw a fix for this somewhere in the Waku sources. Maybe + // it was called something like "Capture Css". And it's also mentioned + // in the Vite issues on GitHub const FIXME_HardcodedIndexCss = ['index.css'] const assetMap = JSON.stringify({ @@ -135,13 +132,12 @@ async function createServer() { const { pipe } = renderToPipeableStream( serverEntry({ url: currentPathName, - routeContext: serverData, css: FIXME_HardcodedIndexCss, meta: metaTags, }), { bootstrapScriptContent: pageWithJs - ? `window.__loadServerData = function() { return ${serializedRouteContext} }; window.__assetMap = function() { return ${assetMap} }` + ? `window.__assetMap = function() { return ${assetMap} }` : undefined, bootstrapModules, onShellReady() { diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index bf54a1896262..2cfc2216b99f 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -151,7 +151,6 @@ export async function runFeServer() { return } - let serverData = {} let metaTags: TagDescriptor[] = [] if (currentRoute?.redirect) { @@ -182,13 +181,9 @@ export async function runFeServer() { }, }) - serverData = routeHookOutput.serverData metaTags = routeHookOutput.meta } - // Serialize route context so it can be passed to the client entry - const serializedRouteContext = JSON.stringify(serverData) - const pageWithJs = currentRoute.renderMode !== 'html' // @NOTE have to add slash so subpaths still pick up the right file // Vite is currently producing modules not scripts: https://vitejs.dev/config/build-options.html#build-target @@ -202,15 +197,15 @@ export async function runFeServer() { // we should use the same shape as Remix or Next for the meta object serverEntry({ url: currentPathName, - routeContext: serverData, css: indexEntry.css, meta: metaTags, }), { bootstrapScriptContent: pageWithJs - ? `window.__loadServerData = function() { return ${serializedRouteContext} }; window.__assetMap = function() { return ${JSON.stringify( - { css: indexEntry.css, meta: metaTags } - )} }` + ? `window.__assetMap = function() { return ${JSON.stringify({ + css: indexEntry.css, + meta: metaTags, + })} }` : undefined, bootstrapModules, onShellReady() { diff --git a/packages/vite/src/triggerRouteHooks.ts b/packages/vite/src/triggerRouteHooks.ts index 551bde93ed7b..9f118a11429c 100644 --- a/packages/vite/src/triggerRouteHooks.ts +++ b/packages/vite/src/triggerRouteHooks.ts @@ -1,14 +1,11 @@ -/// - import { Request } from 'express' import { ViteDevServer } from 'vite' -import { MetaHook, ServerDataHook, TagDescriptor } from '@redwoodjs/web' +import { MetaHook, TagDescriptor } from '@redwoodjs/web' import type { RouteHookEvent, RouteHookOutput } from '@redwoodjs/web' interface RouteHooks { - serverData?: ServerDataHook - meta?: MetaHook + meta?: MetaHook } interface TriggerRouteHooksParam { @@ -33,21 +30,10 @@ export const triggerRouteHooks = async ({ appRouteHook: previousOutput, } - let serverData = {} let meta: TagDescriptor[] = previousOutput?.meta || [] try { - serverData = { - ...previousOutput?.serverData, - ...((await routeHooks?.serverData?.(event)) || {}), - } - } catch (e: any) { - throw new Error(`Error in serverData hook: ${e.message}`) - } - - try { - const metaRouteHookOutput = - (await routeHooks?.meta?.({ ...event, serverData })) || [] + const metaRouteHookOutput = (await routeHooks?.meta?.(event)) || [] // Convert it to an array, if it's not already const currentMeta = Array.isArray(metaRouteHookOutput) @@ -60,7 +46,6 @@ export const triggerRouteHooks = async ({ } return { - serverData, meta, } } @@ -77,7 +62,6 @@ interface LoadAndRunRouteHooks { const defaultRouteHookOutput = { meta: [], - serverData: {}, } export const loadAndRunRouteHooks = async ({ diff --git a/packages/web/src/routeHooks.types.ts b/packages/web/src/routeHooks.types.ts index 74f1baa0ed4e..b282ec3db667 100644 --- a/packages/web/src/routeHooks.types.ts +++ b/packages/web/src/routeHooks.types.ts @@ -2,7 +2,6 @@ import { TagDescriptor } from './components/htmlTags' export type RouteHookOutput = { meta: TagDescriptor[] - serverData: Record } export interface RouteHookEvent { params: Record // this has to be provided from RW router @@ -13,7 +12,6 @@ export interface RouteHookEvent { appRouteHook?: RouteHookOutput } -export type ServerDataHook = (event: RouteHookEvent) => any -export type MetaHook = ( - event: RouteHookEvent & { serverData: T } +export type MetaHook = ( + event: RouteHookEvent ) => Promise | TagDescriptor[] | TagDescriptor diff --git a/packages/web/src/serverContext.tsx b/packages/web/src/serverContext.tsx index 3fc8a38d3d28..f2ac6ac7a698 100644 --- a/packages/web/src/serverContext.tsx +++ b/packages/web/src/serverContext.tsx @@ -1,3 +1,4 @@ +// TODO (STREAMING) is this even used anymore? import React from 'react' const ServerContext = React.createContext({}) @@ -6,7 +7,3 @@ export const { Provider: ServerContextProvider, Consumer: ServerContextConsumer, } = ServerContext - -export const useServerData = () => { - return React.useContext(ServerContext) as T -} From fdf7d644afdeebcf53e7c6c2d97305399887f26a Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Fri, 30 Jun 2023 01:08:49 +0200 Subject: [PATCH 23/26] runFeServer: Add comment about new package --- packages/vite/src/runFeServer.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index 2cfc2216b99f..018eed581cd0 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -1,3 +1,8 @@ +// TODO (STREAMING) Move this to a new package called @redwoodjs/fe-server (goes +// well in naming with with @redwoodjs/api-server) +// Only things used during dev can be in @redwoodjs/vite. Everything else has +// to go in fe-server + import path from 'path' // @ts-expect-error We will remove dotenv-defaults from this package anyway From 8a3925d2aaeb9a4232336ecc634ff7e948bc2cd5 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Fri, 30 Jun 2023 01:13:12 +0200 Subject: [PATCH 24/26] apollo: streamingSsr feature flag --- packages/web/src/apollo/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/web/src/apollo/index.tsx b/packages/web/src/apollo/index.tsx index 24b0d03de540..f7b0827ced72 100644 --- a/packages/web/src/apollo/index.tsx +++ b/packages/web/src/apollo/index.tsx @@ -183,7 +183,10 @@ const ApolloProviderWithFetchConfig: React.FunctionComponent<{ // A terminating link. Apollo Client uses this to send GraphQL operations to a server over HTTP. // See https://www.apollographql.com/docs/react/api/link/introduction/#the-terminating-link. - const httpLink = new HttpLink({ uri, fetch: crossFetch, ...httpLinkConfig }) + let httpLink = new HttpLink({ uri, ...httpLinkConfig }) + if (globalThis.RWJS_EXP_STREAMING_SSR) { + httpLink = new HttpLink({ uri, fetch: crossFetch, ...httpLinkConfig }) + } // The order here is important. The last link *must* be a terminating link like HttpLink. const redwoodApolloLinks: RedwoodApolloLinks = [ From 9841fd27c5c5ae7527b5cdbe994e05508244e0e4 Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Fri, 30 Jun 2023 02:18:49 +0200 Subject: [PATCH 25/26] Update paths tests --- .../src/__tests__/paths.test.ts | 66 ++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/packages/project-config/src/__tests__/paths.test.ts b/packages/project-config/src/__tests__/paths.test.ts index a7bb4bda9549..df64ffd2eb0f 100644 --- a/packages/project-config/src/__tests__/paths.test.ts +++ b/packages/project-config/src/__tests__/paths.test.ts @@ -94,6 +94,13 @@ describe('paths', () => { }, web: { routes: path.join(FIXTURE_BASEDIR, 'web', 'src', 'Routes.tsx'), + routeManifest: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'route-manifest.json' + ), base: path.join(FIXTURE_BASEDIR, 'web'), pages: path.join(FIXTURE_BASEDIR, 'web', 'src', 'pages/'), components: path.join(FIXTURE_BASEDIR, 'web', 'src', 'components'), @@ -135,10 +142,19 @@ describe('paths', () => { 'storybook.manager.js' ), dist: path.join(FIXTURE_BASEDIR, 'web', 'dist'), + distRouteHooks: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'routeHooks' + ), + distServer: path.join(FIXTURE_BASEDIR, 'web', 'dist', 'server'), types: path.join(FIXTURE_BASEDIR, 'web', 'types'), // Vite paths ~ not configured in empty-project viteConfig: null, entryClient: null, + entryServer: null, }, } @@ -332,6 +348,13 @@ describe('paths', () => { }, web: { routes: path.join(FIXTURE_BASEDIR, 'web', 'src', 'Routes.js'), + routeManifest: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'route-manifest.json' + ), base: path.join(FIXTURE_BASEDIR, 'web'), pages: path.join(FIXTURE_BASEDIR, 'web', 'src', 'pages/'), components: path.join(FIXTURE_BASEDIR, 'web', 'src', 'components'), @@ -374,10 +397,19 @@ describe('paths', () => { 'storybook.manager.js' ), dist: path.join(FIXTURE_BASEDIR, 'web', 'dist'), + distRouteHooks: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'routeHooks' + ), + distServer: path.join(FIXTURE_BASEDIR, 'web', 'dist', 'server'), types: path.join(FIXTURE_BASEDIR, 'web', 'types'), // New Vite paths viteConfig: path.join(FIXTURE_BASEDIR, 'web', 'vite.config.ts'), - entryClient: null, // doesnt exist in example-todo-main + entryClient: null, // doesn't exist in example-todo-main + entryServer: null, // doesn't exist in example-todo-main }, } @@ -617,6 +649,13 @@ describe('paths', () => { }, web: { routes: path.join(FIXTURE_BASEDIR, 'web', 'src', 'Routes.js'), + routeManifest: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'route-manifest.json' + ), base: path.join(FIXTURE_BASEDIR, 'web'), pages: path.join(FIXTURE_BASEDIR, 'web', 'src', 'pages/'), components: path.join(FIXTURE_BASEDIR, 'web', 'src', 'components'), @@ -659,7 +698,16 @@ describe('paths', () => { 'storybook.manager.js' ), entryClient: null, + entryServer: null, dist: path.join(FIXTURE_BASEDIR, 'web', 'dist'), + distRouteHooks: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'routeHooks' + ), + distServer: path.join(FIXTURE_BASEDIR, 'web', 'dist', 'server'), types: path.join(FIXTURE_BASEDIR, 'web', 'types'), }, } @@ -860,6 +908,13 @@ describe('paths', () => { }, web: { routes: path.join(FIXTURE_BASEDIR, 'web', 'src', 'Routes.tsx'), + routeManifest: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'route-manifest.json' + ), base: path.join(FIXTURE_BASEDIR, 'web'), pages: path.join(FIXTURE_BASEDIR, 'web', 'src', 'pages/'), components: path.join(FIXTURE_BASEDIR, 'web', 'src', 'components'), @@ -901,10 +956,19 @@ describe('paths', () => { 'storybook.manager.js' ), dist: path.join(FIXTURE_BASEDIR, 'web', 'dist'), + distRouteHooks: path.join( + FIXTURE_BASEDIR, + 'web', + 'dist', + 'server', + 'routeHooks' + ), + distServer: path.join(FIXTURE_BASEDIR, 'web', 'dist', 'server'), types: path.join(FIXTURE_BASEDIR, 'web', 'types'), // Vite paths viteConfig: path.join(FIXTURE_BASEDIR, 'web', 'vite.config.ts'), entryClient: path.join(FIXTURE_BASEDIR, 'web/src/entry.client.tsx'), + entryServer: null, }, } From 3b56964d7e32fec967e072f41232b8c90e22973a Mon Sep 17 00:00:00 2001 From: Tobbe Lundberg Date: Fri, 30 Jun 2023 11:48:34 +0200 Subject: [PATCH 26/26] No unsupported import assertions --- packages/cli/src/commands/buildHandler.js | 4 +--- packages/vite/.babelrc.js | 5 +---- packages/vite/package.json | 1 - packages/vite/src/buildFeServer.ts | 10 +++------- packages/vite/src/runFeServer.ts | 18 ++++++------------ 5 files changed, 11 insertions(+), 27 deletions(-) diff --git a/packages/cli/src/commands/buildHandler.js b/packages/cli/src/commands/buildHandler.js index add07a73eb59..026879b41fae 100644 --- a/packages/cli/src/commands/buildHandler.js +++ b/packages/cli/src/commands/buildHandler.js @@ -126,9 +126,7 @@ export const handler = async ({ // TODO (STREAMING) we need to use a binary here, so the the cwd is correct // Should merge this with the existing rw-vite-build binary - await buildFeServer({ - verbose, - }) + await buildFeServer({ verbose }) } } else { await execa( diff --git a/packages/vite/.babelrc.js b/packages/vite/.babelrc.js index ecc3f819986d..3b2c815712d9 100644 --- a/packages/vite/.babelrc.js +++ b/packages/vite/.babelrc.js @@ -1,4 +1 @@ -module.exports = { - extends: '../../babel.config.js', - plugins: ['@babel/plugin-syntax-import-assertions'], -} +module.exports = { extends: '../../babel.config.js' } diff --git a/packages/vite/package.json b/packages/vite/package.json index 1400bb20a78f..cb57708538e3 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -46,7 +46,6 @@ }, "devDependencies": { "@babel/cli": "7.22.5", - "@babel/plugin-syntax-import-assertions": "7.20.0", "@types/express": "4", "@types/yargs-parser": "21.0.0", "glob": "10.3.0", diff --git a/packages/vite/src/buildFeServer.ts b/packages/vite/src/buildFeServer.ts index 10a64e9f2ff4..7eb123f411e4 100644 --- a/packages/vite/src/buildFeServer.ts +++ b/packages/vite/src/buildFeServer.ts @@ -94,13 +94,9 @@ export const buildFeServer = async ({ verbose }: BuildOptions) => { }) // Step 3: Generate route-manifest.json - // TODO (STREAMING) double check why we need to do .default here - // Its related to the babel import assertion plugin most likely - const clientBuildManifest: ViteManifest = ( - await import(path.join(getPaths().web.dist, 'build-manifest.json'), { - assert: { type: 'json' }, - }) - ).default + const manifestPath = path.join(getPaths().web.dist, 'build-manifest.json') + const buildManifestStr = await fs.readFile(manifestPath, 'utf-8') + const clientBuildManifest: ViteManifest = JSON.parse(buildManifestStr) const routesList = getProjectRoutes() diff --git a/packages/vite/src/runFeServer.ts b/packages/vite/src/runFeServer.ts index 018eed581cd0..9aefa342c38a 100644 --- a/packages/vite/src/runFeServer.ts +++ b/packages/vite/src/runFeServer.ts @@ -3,6 +3,7 @@ // Only things used during dev can be in @redwoodjs/vite. Everything else has // to go in fe-server +import fs from 'fs/promises' import path from 'path' // @ts-expect-error We will remove dotenv-defaults from this package anyway @@ -49,19 +50,12 @@ export async function runFeServer() { const rwPaths = getPaths() const rwConfig = getConfig() - // TODO (STREAMING) figure out why we're having to do default here - const routeManifest: RWRouteManifest = ( - await import(rwPaths.web.dist + '/server/route-manifest.json', { - assert: { type: 'json' }, - }) - ).default + const routeManifestStr = await fs.readFile(rwPaths.web.routeManifest, 'utf-8') + const routeManifest: RWRouteManifest = JSON.parse(routeManifestStr) - // TODO (STREAMING) figure out why we're having to do default here - const buildManifest: ViteManifest = ( - await import(rwPaths.web.dist + '/build-manifest.json', { - assert: { type: 'json' }, - }) - ).default + const manifestPath = path.join(getPaths().web.dist, 'build-manifest.json') + const buildManifestStr = await fs.readFile(manifestPath, 'utf-8') + const buildManifest: ViteManifest = JSON.parse(buildManifestStr) const indexEntry = Object.values(buildManifest).find((manifestItem) => { return manifestItem.isEntry