diff --git a/app.js b/app.js
index 4a421f4e..fa5d483f 100755
--- a/app.js
+++ b/app.js
@@ -1,73 +1,35 @@
-// Core dependencies
-const {
- createReadStream,
- createWriteStream,
- existsSync,
- mkdirSync,
- readdirSync,
- unlinkSync
-} = require('node:fs')
const { join } = require('node:path')
const { format: urlFormat } = require('node:url')
// External dependencies
-const bodyParser = require('body-parser')
-const sessionInCookie = require('client-sessions')
const flash = require('connect-flash')
-const cookieParser = require('cookie-parser')
-const dotenv = require('dotenv')
const express = require('express')
-const sessionInMemory = require('express-session')
const nunjucks = require('nunjucks')
-const sessionInFiles = require('session-file-store')
-// Run before other code to make sure variables from .env are available
-dotenv.config({
- quiet: true
-})
+const NHSPrototypeKit = require('nhsuk-prototype-kit')
// Local dependencies
const config = require('./app/config')
const locals = require('./app/locals')
const routes = require('./app/routes')
-const exampleTemplatesRoutes = require('./lib/example_templates_routes')
-const authentication = require('./lib/middleware/authentication')
-const automaticRouting = require('./lib/middleware/auto-routing')
-const production = require('./lib/middleware/production')
-const prototypeAdminRoutes = require('./lib/middleware/prototype-admin-routes')
-const utils = require('./lib/utils')
-const packageInfo = require('./package.json')
+const sessionDataDefaults = require('./app/data/session-data-defaults')
+const filters = require('./app/filters')
// Set configuration variables
const port = parseInt(process.env.PORT || config.port, 10) || 2000
// Initialise applications
const app = express()
-const exampleTemplatesApp = express()
-
-// Set up configuration variables
-const useAutoStoreData =
- process.env.USE_AUTO_STORE_DATA || config.useAutoStoreData
-const useCookieSessionStore =
- process.env.USE_COOKIE_SESSION_STORE || config.useCookieSessionStore
// Add variables that are available in all views
app.locals.asset_path = '/public/'
-app.locals.useAutoStoreData = useAutoStoreData === 'true'
-app.locals.useCookieSessionStore = useCookieSessionStore === 'true'
app.locals.serviceName = config.serviceName
-// Use cookie middleware to parse cookies
-app.use(cookieParser())
-
// Nunjucks configuration for application
const appViews = [
join(__dirname, 'app/views/'),
join(__dirname, 'app/views/_templates'),
join(__dirname, 'app/views/_includes'),
- join(__dirname, 'lib/example-templates/'),
- join(__dirname, 'lib/prototype-admin/'),
- join(__dirname, 'lib/templates/'),
join(__dirname, 'node_modules/nhsuk-frontend/dist/nhsuk/components'),
join(__dirname, 'node_modules/nhsuk-frontend/dist/nhsuk/macros'),
join(__dirname, 'node_modules/nhsuk-frontend/dist/nhsuk'),
@@ -85,175 +47,12 @@ const nunjucksConfig = {
nunjucksConfig.express = app
let nunjucksAppEnv = nunjucks.configure(appViews, nunjucksConfig)
-nunjucksAppEnv.addGlobal('version', packageInfo.version)
-
-// Add Nunjucks filters
-utils.addNunjucksFilters(nunjucksAppEnv)
-
-// Session uses service name to avoid clashes with other prototypes
-const sessionName = `nhsuk-prototype-kit-${Buffer.from(config.serviceName, 'utf8').toString('hex')}`
-const sessionOptions = {
- secret: sessionName,
- cookie: {
- maxAge: 1000 * 60 * 60 * 4 // 4 hours
- }
-}
-
-if (process.env.NODE_ENV === 'production') {
- app.use(production)
- app.use(authentication)
-}
-
-// Support session data in cookie or memory
-if (useCookieSessionStore === 'true') {
- app.use(
- sessionInCookie({
- ...sessionOptions,
- cookieName: sessionName,
- proxy: true,
- requestKey: 'session'
- })
- )
-} else {
- // app.use(
- // sessionInMemory({
- // ...sessionOptions,
- // name: sessionName,
- // resave: false,
- // saveUninitialized: false
- // })
- // )
-
- // Somewhat similar file store to GOV.UK
- const FileStore = sessionInFiles(sessionInMemory)
- const sessionPath = join(__dirname, '.tmp/sessions')
-
- // Make sure the sessions directory exists
- if (!existsSync(sessionPath)) {
- mkdirSync(sessionPath, { recursive: true })
- } else {
- // Clear existing session files on restart
- readdirSync(sessionPath).forEach((file) => {
- unlinkSync(join(sessionPath, file))
- })
- }
-
- // app.use(
- // sessionInMemory({
- // ...sessionOptions,
- // name: sessionName,
- // resave: false,
- // saveUninitialized: false,
- // store: new FileStore({
- // path: sessionPath,
- // logFn: (message) => {
- // // Suppress all expected session-related messages
- // if (
- // message.endsWith('Deleting expired sessions') ||
- // message.includes('ENOENT')
- // ) {
- // return
- // }
- // // Only log unexpected issues
- // console.log(message)
- // }
- // })
- // })
- // )
- // Support session data in cookie or memory
- if (useCookieSessionStore === 'true') {
- app.use(
- sessionInCookie({
- ...sessionOptions,
- cookieName: sessionName,
- proxy: true,
- requestKey: 'session'
- })
- )
- } else {
- app.use(
- sessionInMemory({
- ...sessionOptions,
- name: sessionName,
- resave: false,
- saveUninitialized: false
- })
- )
- }
-}
-
-// Support for parsing data in POSTs
-app.use(bodyParser.json())
-app.use(
- bodyParser.urlencoded({
- extended: true
- })
-)
-
-// Automatically store all data users enter
-if (useAutoStoreData === 'true') {
- app.use(utils.autoStoreData)
- utils.addCheckedFunction(nunjucksAppEnv)
-}
-
-app.use(utils.setLocals)
// Flash messages
app.use(flash())
-// Warn if node_modules folder doesn't exist
-function checkFiles() {
- const nodeModulesExists = existsSync(join(__dirname, '/node_modules'))
- if (!nodeModulesExists) {
- throw new Error(
- 'ERROR: Node module folder missing. Try running `npm install`'
- )
- }
-
- // Create template .env file if it doesn't exist
- const envExists = existsSync(join(__dirname, '/.env'))
- if (!envExists) {
- createReadStream(join(__dirname, '/lib/template.env')).pipe(
- createWriteStream(join(__dirname, '/.env'))
- )
- }
-}
-
-// initial checks
-checkFiles()
-
-// Create template session data defaults file if it doesn't exist
-const dataDirectory = join(__dirname, '/app/data')
-const sessionDataDefaultsFile = join(dataDirectory, '/session-data-defaults.js')
-const sessionDataDefaultsFileExists = existsSync(sessionDataDefaultsFile)
-
-if (!sessionDataDefaultsFileExists) {
- console.log('Creating session data defaults file')
- if (!existsSync(dataDirectory)) {
- mkdirSync(dataDirectory)
- }
-
- createReadStream(
- join(__dirname, '/lib/template.session-data-defaults.js')
- ).pipe(createWriteStream(sessionDataDefaultsFile))
-}
-
-// Local variables
-app.use(locals(config))
-
-// View engine
-app.set('view engine', 'html')
-exampleTemplatesApp.set('view engine', 'html')
-
-// Support for parsing nested query strings
-// https://github.com/nhsuk/nhsuk-prototype-kit/issues/644
-app.set('query parser', 'extended')
-
-// This setting trusts the X-Forwarded headers set by
-// a proxy and uses them to set the standard header in
-// req. This is needed for hosts like Heroku.
-// See https://expressjs.com/en/guide/behind-proxies.html
-app.set('trust proxy', 1)
+// Serve the images as static assets
+app.use('/images', express.static(join(__dirname, 'app/assets/images')))
// Use public folder for static assets
app.use(express.static(join(__dirname, 'public')))
@@ -264,76 +63,24 @@ app.use(
express.static(join(__dirname, 'node_modules/nhsuk-frontend/dist/nhsuk'))
)
-// Use custom application routes
-app.use('/', routes)
-
-// Automatically route pages
-app.get(/^([^.]+)$/, (req, res, next) => {
- automaticRouting.matchRoutes(req, res, next)
-})
-
-// Example template routes
-app.use('/example-templates', exampleTemplatesApp)
-
-nunjucksAppEnv = nunjucks.configure(appViews, {
- autoescape: true,
- express: exampleTemplatesApp
-})
-nunjucksAppEnv.addGlobal('version', packageInfo.version)
-
// Add Nunjucks filters
-utils.addNunjucksFilters(nunjucksAppEnv)
-
-exampleTemplatesApp.use('/', exampleTemplatesRoutes)
+for (const [name, filter] of Object.entries(filters())) {
+ nunjucksAppEnv.addFilter(name, filter)
-// Automatically route example template pages
-exampleTemplatesApp.get(/^([^.]+)$/, (req, res, next) => {
- automaticRouting.matchRoutes(req, res, next)
-})
-
-app.use('/prototype-admin', prototypeAdminRoutes)
-
-// Redirect all POSTs to GETs - this allows users to use POST for autoStoreData
-app.post(/^\/([^.]+)$/, (req, res) => {
- res.redirect(
- urlFormat({
- pathname: `/${req.params[0]}`,
- query: req.query
- })
- )
-})
-
-// Catch 404 and forward to error handler
-app.use((req, res, next) => {
- const err = new Error(`Page not found: ${req.path}`)
- err.status = 404
- next(err)
-})
-
-// Display error
-app.use((err, req, res) => {
- console.error(err.message)
- res.status(err.status || 500)
- res.send(err.message)
-})
-
-// Run the application
-app.listen(port)
-
-if (
- process.env.WATCH !== 'true' && // If the user isn’t running watch
- process.env.NODE_ENV !== 'production' // and it’s not in production mode
-) {
- console.info(`Running at http://localhost:${port}/`)
- console.info('')
- console.warn(
- 'Warning: It looks like you may have run the command `npm start` locally.'
- )
- console.warn('Press `Ctrl+C` and then run `npm run watch` instead')
+ // Duplicate filter as global function
+ nunjucksAppEnv.addGlobal(name, filter)
}
-module.exports = app
+const prototype = NHSPrototypeKit.init({
+ serviceName: config.serviceName,
+ express: app,
+ nunjucks: nunjucksAppEnv,
+ routes: routes,
+ locals: locals,
+ sessionDataDefaults: sessionDataDefaults,
+ buildOptions: {
+ entryPoints: ['app/assets/sass/main.scss', 'app/assets/javascript/**/*.js']
+ }
+})
-/**
- * @import { ConfigureOptions } from 'nunjucks'
- */
+prototype.start()
diff --git a/app/locals.js b/app/locals.js
index 248b04b4..34469e97 100644
--- a/app/locals.js
+++ b/app/locals.js
@@ -1,8 +1,7 @@
// app/locals.js
-module.exports = (config) => (req, res, next) => {
+module.exports = (req, res, next) => {
const locals = {
- serviceName: config.serviceName,
currentUrl: req.path,
flash: req.flash(),
query: req.query,
diff --git a/app/views/_templates/layout.html b/app/views/_templates/layout.html
index 264306bc..7c7f58a7 100755
--- a/app/views/_templates/layout.html
+++ b/app/views/_templates/layout.html
@@ -24,7 +24,7 @@
{% block head %}
-
+
{% endblock %}
diff --git a/gulpfile.js b/gulpfile.js
deleted file mode 100755
index 8e60b8a7..00000000
--- a/gulpfile.js
+++ /dev/null
@@ -1,163 +0,0 @@
-// External dependencies
-const browserSync = require('browser-sync')
-const gulp = require('gulp')
-const babel = require('gulp-babel')
-const clean = require('gulp-clean')
-const nodemon = require('gulp-nodemon')
-const gulpSass = require('gulp-sass')
-const PluginError = require('plugin-error')
-const dartSass = require('sass-embedded')
-
-// Local dependencies
-const config = require('./app/config')
-const { findAvailablePort } = require('./lib/utils')
-
-// Set configuration variables
-const port = parseInt(process.env.PORT || config.port, 10) || 2000
-
-// Delete all the files in /public build directory
-function cleanPublic() {
- return gulp.src('public', { allowEmpty: true }).pipe(clean())
-}
-
-// Set Sass compiler
-const sass = gulpSass(dartSass)
-
-// Compile SASS to CSS
-function compileStyles() {
- return gulp
- .src(['app/assets/sass/**/*.scss'], {
- sourcemaps: true
- })
- .pipe(
- sass({
- loadPaths: ['node_modules'],
- sourceMap: true,
- sourceMapIncludeSources: true
- }).on('error', (error) => {
- throw new PluginError('compileCSS', error.messageFormatted, {
- showProperties: false
- })
- })
- )
- .pipe(
- gulp.dest('public/css', {
- sourcemaps: '.'
- })
- )
-}
-
-// Compile JavaScript (with ES6 support)
-function compileScripts() {
- return gulp
- .src(['app/assets/javascript/**/*.js'], {
- sourcemaps: true
- })
- .pipe(babel())
- .pipe(
- gulp.dest('public/js', {
- sourcemaps: '.'
- })
- )
-}
-
-// Compile assets
-function compileAssets() {
- return gulp
- .src(
- [
- 'app/assets/**/**/*.*',
- '!**/assets/**/**/*.js', // Don't copy JS files
- '!**/assets/**/**/*.scss' // Don't copy SCSS files
- ],
- { encoding: false }
- )
- .pipe(gulp.dest('public'))
-}
-
-// Start nodemon
-async function startNodemon(done) {
- let availablePort
-
- try {
- availablePort = await findAvailablePort(port)
- if (!availablePort) {
- throw new Error(`Port ${port} in use`)
- }
- } catch (error) {
- done(new PluginError('startNodemon', error))
- return
- }
-
- process.env.PORT = availablePort
- process.env.WATCH = 'true'
-
- const server = nodemon({
- script: 'app.js',
- stdout: true,
- ext: 'js json',
- watch: ['.env', 'app.js', 'app', 'lib'],
- ignore: ['app/assets', 'app/data/generated', '**.test.*'],
- quiet: false
- })
-
- let starting = false
-
- const onReady = () => {
- starting = false
- done()
- }
-
- server.on('start', () => {
- starting = true
- setTimeout(onReady)
- })
-
- server.on('stdout', (stdout) => {
- process.stdout.write(stdout)
- if (starting) {
- onReady()
- }
- })
-}
-
-// Start browsersync
-async function startBrowserSync(done) {
- const proxyPort = parseInt(process.env.PORT, 10)
-
- browserSync.init(
- {
- proxy: `localhost:${proxyPort}`,
- port: proxyPort + 1000,
- ui: false,
- files: ['app/views/**/*.*', 'lib/example-templates/**/*.*'],
- ghostMode: false,
- open: false,
- notify: false,
- logFileChanges: false,
- reloadDebounce: 1000
- },
- done
- )
-
- gulp.watch('public/**/*.*').on('change', browserSync.reload)
-}
-
-// Watch for changes within assets/
-function watch() {
- gulp.watch('app/assets/sass/**/*.scss', compileStyles)
- gulp.watch('app/assets/javascript/**/*.js', compileScripts)
- gulp.watch('app/assets/**/**/*.*', compileAssets)
-}
-
-exports.watch = watch
-exports.compileStyles = compileStyles
-exports.compileScripts = compileScripts
-exports.cleanPublic = cleanPublic
-
-gulp.task(
- 'build',
- gulp.series(cleanPublic, compileStyles, compileScripts, compileAssets)
-)
-
-gulp.task('default', gulp.series(startNodemon, startBrowserSync, watch))
diff --git a/lib/core_filters.js b/lib/core_filters.js
deleted file mode 100644
index af2e8db9..00000000
--- a/lib/core_filters.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @param {Environment} env
- */
-module.exports = function (env) {
- // If you need access to an internal nunjucks filter you can use env
- // see the example below for 'safe' which is used in 'filters.log'
- const nunjucksSafe = env.getFilter('safe')
-
- /**
- * Object used to store the filters
- * filters.foo("input") here, becomes {{ "input" | foo }} in templates
- */
- const filters = {}
-
- /**
- * Logs an object in the template to the console in the browser.
- *
- * @example
- * ```njk
- * {{ "hello world" | log }}
- * ```
- * @example For environments with autoescaping turned on
- * ```njk
- * {{ "hello world" | log | safe }}
- * ```
- * @param {unknown} a - unknown type
- * @returns {string} a script tag with a console.log call.
- */
- filters.log = function log(a) {
- return nunjucksSafe(
- ``
- )
- }
-
- return filters
-}
-
-/**
- * @import { Environment } from 'nunjucks'
- */
diff --git a/lib/example-templates/blank-transactional.html b/lib/example-templates/blank-transactional.html
deleted file mode 100755
index 6626bc13..00000000
--- a/lib/example-templates/blank-transactional.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% extends "layout.html" %}
-
-{% set mainClasses = "nhsuk-main-wrapper--s" %}
-
-{% set pageName = "Blank transactional template" %}
-
-{% block beforeContent %}
- {{ backLink({
- href: "#",
- text: "Back"
- }) }}
-{% endblock %}
-
-{% block content %}
-
-{% endblock %}
diff --git a/lib/example-templates/content-page.html b/lib/example-templates/content-page.html
deleted file mode 100755
index dca0a1d5..00000000
--- a/lib/example-templates/content-page.html
+++ /dev/null
@@ -1,30 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Example content page" %}
-
-{% block beforeContent %}
- {{ breadcrumb({
- href: "#",
- text: "Home"
- }) }}
-{% endblock %}
-
-{% block content %}
-
-{% endblock %}
diff --git a/lib/example-templates/example-templates.html b/lib/example-templates/example-templates.html
deleted file mode 100644
index 368fdd2d..00000000
--- a/lib/example-templates/example-templates.html
+++ /dev/null
@@ -1,38 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Page templates" %}
-
-{% block beforeContent %}
- {{ breadcrumb({
- href: "/",
- text: "Home"
- }) }}
-{% endblock %}
-
-{% block content %}
-
-
-
-
-
{{ pageName }}
-
-
You can find these templates in the /lib/example-templates folder.
-
-
You can copy and paste the templates in any folder within /app/views.
-
-
Content pages
-
-
-
-
Transactional journeys
-
-
-
-
-
-{% endblock %}
diff --git a/lib/example-templates/mini-hub/index.html b/lib/example-templates/mini-hub/index.html
deleted file mode 100644
index 4f99a339..00000000
--- a/lib/example-templates/mini-hub/index.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Mini hub" %}
-
-{% block beforeContent %}
- {{ breadcrumb({
- href: "/",
- text: "Home"
- }) }}
-{% endblock %}
-
-{% block content %}
-
-
-
-
- Main page heading
-
- Section title
-
-
-
- {{ contentsList({
- items: [
- {
- href: "/example-templates/mini-hub/page-1",
- text: "Main page",
- current: "true"
- },
- {
- href: "/example-templates/mini-hub/page-2",
- text: "Page two"
- },
- {
- href: "/example-templates/mini-hub/page-3",
- text: "Page three"
- }
- ]
- }) }}
-
-
- [Page content goes here]
-
-
-
- [Visit the
- NHS digital service manual
- for guidance and examples.]
-
-
- {{ pagination({
- nextUrl: "/example-templates/mini-hub/page-2",
- nextPage: "Page two"
- }) }}
-
-
-
-{% endblock %}
diff --git a/lib/example-templates/mini-hub/page-2.html b/lib/example-templates/mini-hub/page-2.html
deleted file mode 100644
index 078ac3d0..00000000
--- a/lib/example-templates/mini-hub/page-2.html
+++ /dev/null
@@ -1,66 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Mini hub - Page two" %}
-
-{% block beforeContent %}
- {{ breadcrumb({
- items: [
- {
- href: "/",
- text: "Home"
- }
- ],
- href: "/example-templates/mini-hub",
- text: "Main page"
- }) }}
-{% endblock %}
-
-{% block content %}
-
-
-
-
- Page two heading
-
- Section title
-
-
-
- {{ contentsList({
- items: [
- {
- href: "/example-templates/mini-hub",
- text: "Main page"
- },
- {
- href: "/example-templates/mini-hub/page-2",
- text: "Page two",
- current: "true"
- },
- {
- href: "/example-templates/mini-hub/page-3",
- text: "Page three"
- }
- ]
- }) }}
-
-
- [Page content goes here]
-
-
-
- [Visit the
- NHS digital service manual
- for guidance and examples.]
-
-
- {{ pagination({
- previousUrl: "/example-templates/mini-hub",
- previousPage: "Main page",
- nextUrl: "/example-templates/mini-hub/page-3",
- nextPage: "Page two"
- }) }}
-
-
-
-{% endblock %}
diff --git a/lib/example-templates/mini-hub/page-3.html b/lib/example-templates/mini-hub/page-3.html
deleted file mode 100644
index 6a9e5e69..00000000
--- a/lib/example-templates/mini-hub/page-3.html
+++ /dev/null
@@ -1,64 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Mini hub - Page three" %}
-
-{% block beforeContent %}
- {{ breadcrumb({
- items: [
- {
- href: "/",
- text: "Home"
- }
- ],
- href: "/example-templates/mini-hub",
- text: "Main page"
- }) }}
-{% endblock %}
-
-{% block content %}
-
-
-
-
- Page three heading
-
- Section title
-
-
-
- {{ contentsList({
- items: [
- {
- href: "/example-templates/mini-hub",
- text: "Main page"
- },
- {
- href: "/example-templates/mini-hub/page-2",
- text: "Page two"
- },
- {
- href: "/example-templates/mini-hub/page-3",
- text: "Page three",
- current: "true"
- }
- ]
- }) }}
-
-
- [Page content goes here]
-
-
-
- [Visit the
- NHS digital service manual
- for guidance and examples.]
-
-
- {{ pagination({
- previousUrl: "/example-templates/mini-hub/page-2",
- previousPage: "Page two"
- }) }}
-
-
-
-{% endblock %}
diff --git a/lib/example_templates_routes.js b/lib/example_templates_routes.js
deleted file mode 100644
index af49e842..00000000
--- a/lib/example_templates_routes.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// External dependencies
-const express = require('express')
-
-const router = express.Router()
-
-module.exports = router
diff --git a/lib/middleware/authentication.js b/lib/middleware/authentication.js
deleted file mode 100644
index 8e1fcc8a..00000000
--- a/lib/middleware/authentication.js
+++ /dev/null
@@ -1,75 +0,0 @@
-const { format: urlFormat } = require('node:url')
-
-const { encryptPassword } = require('../utils')
-
-const allowedPathsWhenUnauthenticated = [
- '/prototype-admin/password',
- '/css/main.css',
- '/css/main.css.map',
- '/nhsuk-frontend/nhsuk-frontend.min.js',
- '/nhsuk-frontend/nhsuk-frontend.min.js.map',
- '/js/auto-store-data.js',
- '/js/auto-store-data.js.map',
- '/js/main.js',
- '/js/main.js.map'
-]
-
-const encryptedPassword = encryptPassword(process.env.PROTOTYPE_PASSWORD)
-
-/**
- * Redirect the user to the password page, with
- * the current page path set as the returnURL in a query
- * string so the user can be redirected back after successfully
- * entering a password
- *
- * @param {Request} req
- * @param {Response} res
- */
-function sendUserToPasswordPage(req, res) {
- const returnURL = urlFormat({
- pathname: req.path,
- query: req.query
- })
- const passwordPageURL = urlFormat({
- pathname: '/prototype-admin/password',
- query: { returnURL }
- })
- res.redirect(passwordPageURL)
-}
-
-/**
- * Give the user some instructions on how to set a password
- *
- * @param {Response} res
- */
-function showNoPasswordError(res) {
- return res.send(
- 'Error:
Password not set. See guidance for setting a password.
'
- )
-}
-
-/**
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
- */
-function authentication(req, res, next) {
- if (!process.env.PROTOTYPE_PASSWORD) {
- showNoPasswordError(res)
- } else if (
- req.path.startsWith('/nhsuk-frontend/assets/') ||
- allowedPathsWhenUnauthenticated.includes(req.path)
- ) {
- next()
- } else if (req.cookies.authentication === encryptedPassword) {
- next()
- } else {
- sendUserToPasswordPage(req, res)
- }
-}
-
-module.exports = authentication
-
-/**
- * @import { NextFunction, Request, Response } from 'express'
- */
diff --git a/lib/middleware/auto-routing.js b/lib/middleware/auto-routing.js
deleted file mode 100644
index 73f4a0c6..00000000
--- a/lib/middleware/auto-routing.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Automatically route pages
- *
- * Try to match a request to a template, for example a request for /test
- * would look for /app/views/test.html and /app/views/test/index.html
- *
- * 1. Try to render the path
- * 2. if success - send the response
- * 3. if error other than template not found - call next with the error
- * 4. Maybe it's a folder - try to render [path]/index.html
- * 5. We got template not found both times - call next to trigger the 404 page
- * 6. Remove the first slash, render won't work with it
- * 7. If it's blank, render the root index
- *
- * @param {string} path
- * @param {Response} res
- * @param {NextFunction} next
- */
-function renderPath(path, res, next) {
- res.render(path, (error, html) => {
- // [1] //
- if (!error) {
- res.set({ 'Content-type': 'text/html; charset=utf-8' }) // [2] //
- res.end(html)
- return
- }
- if (!error.message.startsWith('template not found')) {
- // [3] //
- next(error)
- return
- }
- if (!path.endsWith('/index')) {
- renderPath(`${path}/index`, res, next) // [4] //
- return
- }
- next() // [5] //
- })
-}
-
-/**
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
- */
-exports.matchRoutes = function (req, res, next) {
- let { path } = req
-
- path = path.substr(1) // [6] //
-
- if (path === '') {
- // [7] //
- path = 'index'
- }
-
- renderPath(path, res, next)
-}
-
-/**
- * @import { NextFunction, Request, Response } from 'express'
- */
diff --git a/lib/middleware/production.js b/lib/middleware/production.js
deleted file mode 100644
index 56be9ea8..00000000
--- a/lib/middleware/production.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * This Express middleware function sets some
- * HTTP headers which should only be set in deployed
- * environments
- *
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
- */
-function production(req, res, next) {
- // Set Strict-Transport-Security header to
- // ensure that browsers only use HTTPS
- res.setHeader(
- 'Strict-Transport-Security',
- 'max-age=31536000; includeSubDomains; preload'
- )
-
- // Set content security policy to upgrade
- // all HTTP requests to HTTPS
- res.setHeader('Content-Security-Policy', 'upgrade-insecure-requests')
-
- // Redirect HTTP requests to HTTPS
- if (req.protocol !== 'https') {
- res.redirect(302, `https://${req.get('Host')}${req.url}`)
- } else {
- next()
- }
-}
-
-module.exports = production
-
-/**
- * @import { NextFunction, Request, Response } from 'express'
- */
diff --git a/lib/middleware/prototype-admin-routes.js b/lib/middleware/prototype-admin-routes.js
deleted file mode 100644
index 3be6d414..00000000
--- a/lib/middleware/prototype-admin-routes.js
+++ /dev/null
@@ -1,89 +0,0 @@
-const { join, resolve } = require('node:path')
-
-const express = require('express')
-
-const router = express.Router()
-
-const password = process.env.PROTOTYPE_PASSWORD
-
-const { encryptPassword } = require('../utils')
-
-router.get('/password', (req, res) => {
- const returnURL = req.query.returnURL || '/'
- const { error } = req.query
- res.render('password', {
- returnURL,
- error
- })
-})
-
-// Check authentication password
-router.post('/password', (req, res) => {
- const submittedPassword = req.body.password
- const { returnURL } = req.body
-
- if (submittedPassword === password) {
- // see lib/middleware/authentication.js for explanation
- res.cookie('authentication', encryptPassword(password), {
- maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
- sameSite: 'None', // Allows GET and POST requests from other domains
- httpOnly: true,
- secure: true
- })
- res.redirect(returnURL)
- } else {
- res.redirect(
- `/prototype-admin/password?error=wrong-password&returnURL=${encodeURIComponent(returnURL)}`
- )
- }
-})
-
-router.get('/reset', (req, res) => {
- let { returnPage } = req.query
-
- // Allow local paths only
- if (!returnPage?.startsWith('/')) {
- returnPage = '/'
- }
-
- res.render('reset', {
- returnPage
- })
-})
-
-router.all('/reset-session-data', (req, res) => {
- let { returnPage } = req.body ?? req.query
-
- // Allow local paths only
- if (!returnPage?.startsWith('/')) {
- returnPage = '/'
- }
-
- console.log('Clearing session data')
-
- const dataDirectory = join(__dirname, '../../app/data')
- const sessionDataPath = resolve(dataDirectory, 'session-data-defaults.js')
- const generatedDataPath = resolve(dataDirectory, 'generated')
-
- // Clear the require cache for session data defaults
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
- delete require.cache[require.resolve(sessionDataPath)]
-
- // Clear cache for the generated JSON files
- Object.keys(require.cache).forEach((key) => {
- if (key.startsWith(generatedDataPath)) {
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
- delete require.cache[key]
- }
- })
-
- // Load fresh session defaults after clearing cache
- req.session.data = require(sessionDataPath)
- req.flash('success', 'Session data cleared')
-
- res.render('reset-done', {
- returnPage
- })
-})
-
-module.exports = router
diff --git a/lib/prototype-admin/password.html b/lib/prototype-admin/password.html
deleted file mode 100644
index d20f77c0..00000000
--- a/lib/prototype-admin/password.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Enter password" %}
-{% set errors = error == "wrong-password" %}
-
-{% block content %}
-
-
-{% endblock %}
diff --git a/lib/prototype-admin/reset-done.html b/lib/prototype-admin/reset-done.html
deleted file mode 100644
index 5356f72f..00000000
--- a/lib/prototype-admin/reset-done.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% extends "layout.html" %}
-
-{% set pageName = "Data reset" %}
-
-{% block content %}
-
-
-
{{ pageName }}
-
-
The session data has been reset.
-
-
Return
-
-
-{% endblock %}
diff --git a/lib/prototype-admin/reset.html b/lib/prototype-admin/reset.html
deleted file mode 100644
index c377882e..00000000
--- a/lib/prototype-admin/reset.html
+++ /dev/null
@@ -1,27 +0,0 @@
-{% extends 'layout.html' %}
-
-{% set pageName = "Reset data" %}
-
-{% block beforeContent %}
- {{ backLink({
- text: "Back",
- href: returnPage
- }) }}
-{% endblock %}
-
-{% block content %}
-
-
-
{{ pageName }}
-
-
This will reset all of the data entered in this session.
-
-
-
-
-{% endblock %}
diff --git a/lib/template.env b/lib/template.env
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/template.session-data-defaults.js b/lib/template.session-data-defaults.js
deleted file mode 100644
index 401ff107..00000000
--- a/lib/template.session-data-defaults.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-
-Provide default values for user session data. These are automatically added
-via the `autoStoreData` middleware. Values will only be added to the
-session if a value doesn't already exist. This may be useful for testing
-journeys where users are returning or logging in to an existing application.
-
-============================================================================
-
-Example usage:
-
-"full-name": "Sarah Philips",
-
-"options-chosen": [ "foo", "bar" ]
-
-============================================================================
-
-*/
-
-module.exports = {
- // Insert values here
-}
diff --git a/lib/templates/prototype-kit-template.njk b/lib/templates/prototype-kit-template.njk
deleted file mode 100644
index f009ece8..00000000
--- a/lib/templates/prototype-kit-template.njk
+++ /dev/null
@@ -1,46 +0,0 @@
-{% extends "template.njk" %}
-
-{%- from 'action-link/macro.njk' import actionLink %}
-{%- from 'back-link/macro.njk' import backLink %}
-{%- from 'breadcrumb/macro.njk' import breadcrumb %}
-{%- from 'button/macro.njk' import button %}
-{%- from 'card/macro.njk' import card %}
-{%- from 'character-count/macro.njk' import characterCount %}
-{%- from 'checkboxes/macro.njk' import checkboxes %}
-{%- from 'contents-list/macro.njk' import contentsList %}
-{%- from 'date-input/macro.njk' import dateInput %}
-{%- from 'details/macro.njk' import details %}
-{%- from 'do-dont-list/macro.njk' import list %}
-{%- from 'error-message/macro.njk' import errorMessage %}
-{%- from 'error-summary/macro.njk' import errorSummary %}
-{%- from 'fieldset/macro.njk' import fieldset %}
-{%- from 'footer/macro.njk' import footer %}
-{%- from 'header/macro.njk' import header %}
-{%- from 'hero/macro.njk' import hero %}
-{%- from 'hint/macro.njk' import hint %}
-{%- from 'images/macro.njk' import image %}
-{%- from 'input/macro.njk' import input %}
-{%- from 'inset-text/macro.njk' import insetText %}
-{%- from 'label/macro.njk' import label %}
-{%- from 'notification-banner/macro.njk' import notificationBanner %}
-{%- from 'pagination/macro.njk' import pagination %}
-{%- from 'panel/macro.njk' import panel with context %}
-{%- from 'radios/macro.njk' import radios %}
-{%- from 'select/macro.njk' import select %}
-{%- from 'skip-link/macro.njk' import skipLink %}
-{# Renamed summary list so we prefer our app one first #}
-{%- from 'summary-list/macro.njk' import summaryList as nativeSummaryList %}
-{%- from 'tables/macro.njk' import table %}
-{%- from 'tabs/macro.njk' import tabs %}
-{%- from 'tag/macro.njk' import tag %}
-{%- from 'task-list/macro.njk' import taskList %}
-{%- from 'textarea/macro.njk' import textarea %}
-{%- from 'warning-callout/macro.njk' import warningCallout %}
-
-{% block pageTitle -%}
- {%- if errors === true or (errors | length) %}Error: {% endif -%}
- {%- if pageName %}{{ pageName }} – {% endif -%}
- {{ serviceName }} – NHS
-{%- endblock %}
-
-{% set assetPath = '/nhsuk-frontend/assets' %}
diff --git a/lib/utils.js b/lib/utils.js
deleted file mode 100644
index b78304fc..00000000
--- a/lib/utils.js
+++ /dev/null
@@ -1,309 +0,0 @@
-// Core dependencies
-const { createHash } = require('node:crypto')
-const { resolve } = require('node:path')
-
-const { get: getKeypath } = require('lodash')
-
-const customFilters = require('../app/filters')
-
-const coreFilters = require('./core_filters')
-const { findAvailablePort } = require('./utils/find-available-port')
-
-/**
- * Merge the core and custom filters into one object
- * and then add the methods to Nunjucks environment
- *
- * @param {Environment} env
- */
-function addNunjucksFilters(env) {
- const filters = {
- ...coreFilters(env),
- ...customFilters(env)
- }
-
- for (const [name, filter] of Object.entries(filters)) {
- env.addFilter(name, filter)
-
- // Duplicate filter as global function
- env.addGlobal(name, filter)
- }
-}
-
-/**
- * Add Nunjucks function called 'checked' to populate radios and checkboxes
- * This function is less useful since NHS Frontend 9.2.0 added an
- * easier way to set checkbox and radio checked items, and may
- * be removed in future.
- *
- * @param {Environment} env
- */
-function addCheckedFunction(env) {
- env.addGlobal('checked', function (name, value) {
- // Check data exists
- if (this.ctx.data === undefined) {
- return ''
- }
-
- // Use string keys or object notation to support:
- // checked("field-name")
- // checked("['field-name']")
- // checked("['parent']['field-name']")
- const matchedName = !name.match(/[.[]/g) ? `['${name}']` : name
- const storedValue = getKeypath(this.ctx.data, matchedName)
-
- // Check the requested data exists
- if (storedValue === undefined) {
- return ''
- }
-
- let checked = ''
-
- // If data is an array, check it exists in the array
- if (Array.isArray(storedValue)) {
- if (storedValue.indexOf(value) !== -1) {
- checked = 'checked'
- }
- } else if (storedValue === value) {
- // The data is just a simple value, check it matches
- checked = 'checked'
- }
- return checked
- })
-}
-
-/*
-// Synchronously get the URL for the latest release on GitHub and cache it
-function getLatestRelease () {
- if (releaseUrl !== null) {
- // Release URL already exists
- console.log('Release url cached:', releaseUrl)
- return releaseUrl
- } else {
- // Release URL doesn't exist
- try {
- console.log('Getting latest release from GitHub')
-
- var res = request(
- 'GET',
- 'https://api.github.com/repos/alphagov/govuk-prototype-kit/releases/latest',
- {
- headers: { 'user-agent': 'node.js' }
- }
- )
- var data = JSON.parse(res.getBody('utf8'))
-
- // Cache releaseUrl before we return it
- releaseUrl = `https://github.com/alphagov/govuk-prototype-kit/archive/${data['name']}.zip`
-
- console.log('Release URL is', releaseUrl)
- return releaseUrl
- } catch (err) {
- console.log("Couldn't retrieve release URL")
- return 'https://github.com/alphagov/govuk-prototype-kit/releases/latest'
- }
- }
-}
-*/
-
-/**
- * Try to match a request to a template, for example a request for /test
- * would look for /app/views/test.html
- * and /app/views/test/index.html
- *
- * @param {string} routePath
- * @param {Response} res
- * @param {NextFunction} next
- */
-function renderPath(routePath, res, next) {
- // Try to render the path
- res.render(routePath, (error, html) => {
- if (!error) {
- // Success - send the response
- res.set({ 'Content-type': 'text/html; charset=utf-8' })
- res.end(html)
- return
- }
- if (!error.message.startsWith('template not found')) {
- // We got an error other than template not found - call next with the error
- next(error)
- return
- }
- if (!routePath.endsWith('/index')) {
- // Maybe it's a folder - try to render [path]/index.html
- renderPath(`${routePath}/index`, res, next)
- return
- }
- // We got template not found both times - call next to trigger the 404 page
- next()
- })
-}
-
-/**
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
- */
-function matchRoutes(req, res, next) {
- let routePath = req.path
-
- // Remove the first slash, render won't work with it
- routePath = routePath.substr(1)
-
- // If it's blank, render the root index
- if (routePath === '') {
- routePath = 'index'
- }
-
- renderPath(routePath, res, next)
-}
-
-/**
- * Store data from POST body or GET query in session
- *
- * @param {{ [key: string]: unknown }} input
- * @param {unknown} data
- */
-function storeData(input, data) {
- for (const i in input) {
- // any input where the name starts with _ is ignored
- if (i.indexOf('_') === 0) {
- continue
- }
-
- let val = input[i]
-
- // Delete values when users unselect checkboxes
- if (val === '_unchecked') {
- // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
- delete data[i]
- continue
- }
-
- // Remove _unchecked from arrays of checkboxes
- if (Array.isArray(val)) {
- val = val.filter((item) => item !== '_unchecked')
- } else if (typeof val === 'object') {
- // Store nested objects that aren't arrays
- if (typeof data[i] !== 'object') {
- data[i] = {}
- }
-
- // Add nested values
- storeData(val, data[i])
- continue
- }
-
- data[i] = val
- }
-}
-
-// Get session default data from file
-let sessionDataDefaults = {}
-
-const sessionDataDefaultsFile = resolve(
- __dirname,
- '../app/data/session-data-defaults.js'
-)
-
-try {
- sessionDataDefaults = require(sessionDataDefaultsFile)
-} catch (error) {
- console.error(
- 'Could not load the session data defaults from app/data/session-data-defaults.js. Might be a syntax error?'
- )
- console.error(error)
-}
-
-/**
- * Middleware - store any data sent in session, and pass it to all views
- *
- * @param {Request['body']} req
- * @param {Response} res
- * @param {NextFunction} next
- */
-function autoStoreData(req, res, next) {
- if (!req.session.data) {
- req.session.data = {}
- }
-
- req.session.data = Object.assign({}, sessionDataDefaults, req.session.data)
-
- storeData(req.body, req.session.data)
- storeData(req.query, req.session.data)
-
- // Send session data to all views
-
- res.locals.data = {}
-
- for (const j in req.session.data) {
- res.locals.data[j] = req.session.data[j]
- }
-
- next()
-}
-
-/**
- * Set any useful local variables
- *
- * @param {Request} req
- * @param {Response} res
- * @param {NextFunction} next
- */
-function setLocals(req, res, next) {
- // Current page used for the Reset data feature
- res.locals.currentPage = req.originalUrl
-
- next()
-}
-
-/*
-function handleCookies (app) {
- return function handleCookies (req, res, next) {
- const COOKIE_NAME = 'seen_cookie_message'
- let cookie = req.cookies[COOKIE_NAME]
-
- if (cookie === 'yes') {
- app.locals.shouldShowCookieMessage = false
- return next()
- }
-
- let maxAgeInDays = 28
- res.cookie(COOKIE_NAME, 'yes', {
- maxAge: maxAgeInDays * 24 * 60 * 60 * 1000,
- httpOnly: true
- })
-
- app.locals.shouldShowCookieMessage = true
-
- next()
- }
-}
-*/
-
-/**
- * @param {string} password
- */
-function encryptPassword(password) {
- if (!password) {
- return undefined
- }
- const hash = createHash('sha256')
- hash.update(password)
- return hash.digest('hex')
-}
-
-module.exports = {
- addCheckedFunction,
- addNunjucksFilters,
- autoStoreData,
- encryptPassword,
- findAvailablePort,
- matchRoutes,
- setLocals,
- storeData
-}
-
-/**
- * @import { NextFunction, Request, Response } from 'express'
- * @import { Environment } from 'nunjucks'
- */
diff --git a/lib/utils/find-available-port.js b/lib/utils/find-available-port.js
deleted file mode 100644
index af75d16c..00000000
--- a/lib/utils/find-available-port.js
+++ /dev/null
@@ -1,39 +0,0 @@
-const inquirer = require('@inquirer/prompts')
-const { checkPortStatus, findAPortNotInUse } = require('portscanner')
-
-/**
- * Find an available port to run a server on. This will check
- * whether the default port is available and if not, will ask
- * the user whether to switch to an available port.
- *
- * @param {number} [startPort] - Find port starting from this port number (optional)
- */
-async function findAvailablePort(startPort = 3000) {
- const host = '127.0.0.1'
-
- // Check default port is free
- if ((await checkPortStatus(startPort, host)) === 'closed') {
- return startPort
- }
-
- console.error(
- `ERROR: Port ${startPort} in use - you may have another prototype running.\n`
- )
-
- const change = inquirer.confirm({
- message: 'Change to an available port?',
- default: false
- })
-
- // Check whether the default port or the default port + 1000
- // is free. (1000 is added because that’s what we use for BrowserSync)
- if (await change.catch(() => false)) {
- return findAPortNotInUse(startPort, startPort + 1000, host)
- }
-
- return undefined
-}
-
-module.exports = {
- findAvailablePort
-}
diff --git a/package-lock.json b/package-lock.json
index a264ede1..ea72213f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,22 +7,14 @@
"": {
"name": "nhsuk-prototype-kit",
"version": "5.0.0",
- "hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"@faker-js/faker": "^10.0.0",
- "@inquirer/prompts": "^7.8.4",
- "body-parser": "^2.2.0",
- "browser-sync": "^3.0.4",
- "client-sessions": "^0.8.0",
"connect-flash": "^0.1.1",
- "cookie-parser": "^1.4.7",
"dayjs": "^1.11.15",
- "dotenv": "^17.2.1",
"express": "^5.1.0",
- "express-session": "^1.18.2",
"gulp": "^5.0.1",
"gulp-babel": "^8.0.0",
"gulp-clean": "^0.4.0",
@@ -30,15 +22,12 @@
"gulp-nodemon": "^2.5.0",
"gulp-rename": "^2.1.0",
"gulp-sass": "^6.0.1",
- "lodash": "^4.17.21",
"nhsuk-frontend": "^10.0.0",
+ "nhsuk-prototype-kit": "8.0.0-internal.4",
"nunjucks": "^3.2.4",
- "path": "^0.12.7",
"plugin-error": "^2.0.1",
"pluralize": "^8.0.0",
- "portscanner": "^2.2.0",
"sass-embedded": "^1.91.0",
- "session-file-store": "^1.5.0",
"weighted": "^1.0.0"
},
"devDependencies": {
@@ -101,6 +90,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz",
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
@@ -1763,36 +1753,452 @@
"dev": true,
"license": "MIT",
"optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz",
+ "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@es-joy/jsdoccomment": {
+ "version": "0.53.0",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.53.0.tgz",
+ "integrity": "sha512-Wyed8Wfn3vMNVwrZrgLMxmqwmlcCE1/RfUAOHFzMJb3QLH03mi9Yv1iOCZjif0yx5EZUeJ+17VD1MHPka9IQjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.8",
+ "@typescript-eslint/types": "^8.39.1",
+ "comment-parser": "1.4.1",
+ "esquery": "^1.6.0",
+ "jsdoc-type-pratt-parser": "~4.8.0"
+ },
+ "engines": {
+ "node": ">=20.11.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz",
+ "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz",
+ "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz",
+ "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz",
+ "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz",
+ "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz",
+ "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz",
+ "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz",
+ "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz",
+ "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz",
+ "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz",
+ "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz",
+ "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz",
+ "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz",
+ "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz",
+ "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz",
+ "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz",
+ "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz",
+ "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz",
+ "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz",
+ "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz",
+ "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz",
+ "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz",
+ "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz",
+ "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz",
- "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==",
- "dev": true,
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz",
+ "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==",
+ "cpu": [
+ "ia32"
+ ],
"license": "MIT",
"optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@es-joy/jsdoccomment": {
- "version": "0.53.0",
- "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.53.0.tgz",
- "integrity": "sha512-Wyed8Wfn3vMNVwrZrgLMxmqwmlcCE1/RfUAOHFzMJb3QLH03mi9Yv1iOCZjif0yx5EZUeJ+17VD1MHPka9IQjQ==",
- "dev": true,
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz",
+ "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==",
+ "cpu": [
+ "x64"
+ ],
"license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.8",
- "@typescript-eslint/types": "^8.39.1",
- "comment-parser": "1.4.1",
- "esquery": "^1.6.0",
- "jsdoc-type-pratt-parser": "~4.8.0"
- },
+ "optional": true,
+ "os": [
+ "win32"
+ ],
"engines": {
- "node": ">=20.11.0"
+ "node": ">=18"
}
},
"node_modules/@eslint-community/eslint-utils": {
@@ -1991,17 +2397,26 @@
"dev": true,
"license": "BSD-3-Clause"
},
+ "node_modules/@inquirer/ansi": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz",
+ "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@inquirer/checkbox": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.2.tgz",
- "integrity": "sha512-E+KExNurKcUJJdxmjglTl141EwxWyAHplvsYJQgSwXf8qiNWkTxTuCCqmhFEmbIXd4zLaGMfQFJ6WrZ7fSeV3g==",
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz",
+ "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/figures": "^1.0.13",
- "@inquirer/type": "^3.0.8",
- "ansi-escapes": "^4.3.2",
- "yoctocolors-cjs": "^2.1.2"
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
},
"engines": {
"node": ">=18"
@@ -2016,13 +2431,13 @@
}
},
"node_modules/@inquirer/confirm": {
- "version": "5.1.16",
- "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.16.tgz",
- "integrity": "sha512-j1a5VstaK5KQy8Mu8cHmuQvN1Zc62TbLhjJxwHvKPPKEoowSF6h/0UdOpA9DNdWZ+9Inq73+puRq1df6OJ8Sag==",
+ "version": "5.1.21",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz",
+ "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/type": "^3.0.8"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
},
"engines": {
"node": ">=18"
@@ -2037,19 +2452,19 @@
}
},
"node_modules/@inquirer/core": {
- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.2.0.tgz",
- "integrity": "sha512-NyDSjPqhSvpZEMZrLCYUquWNl+XC/moEcVFqS55IEYIYsY0a1cUCevSqk7ctOlnm/RaSBU5psFryNlxcmGrjaA==",
+ "version": "10.3.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz",
+ "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==",
"license": "MIT",
"dependencies": {
- "@inquirer/figures": "^1.0.13",
- "@inquirer/type": "^3.0.8",
- "ansi-escapes": "^4.3.2",
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
"cli-width": "^4.1.0",
"mute-stream": "^2.0.0",
"signal-exit": "^4.1.0",
"wrap-ansi": "^6.2.0",
- "yoctocolors-cjs": "^2.1.2"
+ "yoctocolors-cjs": "^2.1.3"
},
"engines": {
"node": ">=18"
@@ -2064,14 +2479,14 @@
}
},
"node_modules/@inquirer/editor": {
- "version": "4.2.18",
- "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.18.tgz",
- "integrity": "sha512-yeQN3AXjCm7+Hmq5L6Dm2wEDeBRdAZuyZ4I7tWSSanbxDzqM0KqzoDbKM7p4ebllAYdoQuPJS6N71/3L281i6w==",
+ "version": "4.2.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz",
+ "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/external-editor": "^1.0.1",
- "@inquirer/type": "^3.0.8"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/external-editor": "^1.0.3",
+ "@inquirer/type": "^3.0.10"
},
"engines": {
"node": ">=18"
@@ -2086,14 +2501,14 @@
}
},
"node_modules/@inquirer/expand": {
- "version": "4.0.18",
- "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.18.tgz",
- "integrity": "sha512-xUjteYtavH7HwDMzq4Cn2X4Qsh5NozoDHCJTdoXg9HfZ4w3R6mxV1B9tL7DGJX2eq/zqtsFjhm0/RJIMGlh3ag==",
+ "version": "4.0.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz",
+ "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/type": "^3.0.8",
- "yoctocolors-cjs": "^2.1.2"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
},
"engines": {
"node": ">=18"
@@ -2108,13 +2523,13 @@
}
},
"node_modules/@inquirer/external-editor": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz",
- "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
+ "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==",
"license": "MIT",
"dependencies": {
- "chardet": "^2.1.0",
- "iconv-lite": "^0.6.3"
+ "chardet": "^2.1.1",
+ "iconv-lite": "^0.7.0"
},
"engines": {
"node": ">=18"
@@ -2128,23 +2543,39 @@
}
}
},
+ "node_modules/@inquirer/external-editor/node_modules/iconv-lite": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz",
+ "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
"node_modules/@inquirer/figures": {
- "version": "1.0.13",
- "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz",
- "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==",
+ "version": "1.0.15",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
+ "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@inquirer/input": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.2.tgz",
- "integrity": "sha512-hqOvBZj/MhQCpHUuD3MVq18SSoDNHy7wEnQ8mtvs71K8OPZVXJinOzcvQna33dNYLYE4LkA9BlhAhK6MJcsVbw==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz",
+ "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/type": "^3.0.8"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
},
"engines": {
"node": ">=18"
@@ -2159,13 +2590,13 @@
}
},
"node_modules/@inquirer/number": {
- "version": "3.0.18",
- "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.18.tgz",
- "integrity": "sha512-7exgBm52WXZRczsydCVftozFTrrwbG5ySE0GqUd2zLNSBXyIucs2Wnm7ZKLe/aUu6NUg9dg7Q80QIHCdZJiY4A==",
+ "version": "3.0.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz",
+ "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/type": "^3.0.8"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
},
"engines": {
"node": ">=18"
@@ -2180,14 +2611,14 @@
}
},
"node_modules/@inquirer/password": {
- "version": "4.0.18",
- "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.18.tgz",
- "integrity": "sha512-zXvzAGxPQTNk/SbT3carAD4Iqi6A2JS2qtcqQjsL22uvD+JfQzUrDEtPjLL7PLn8zlSNyPdY02IiQjzoL9TStA==",
+ "version": "4.0.23",
+ "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz",
+ "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/type": "^3.0.8",
- "ansi-escapes": "^4.3.2"
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10"
},
"engines": {
"node": ">=18"
@@ -2202,21 +2633,21 @@
}
},
"node_modules/@inquirer/prompts": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.8.4.tgz",
- "integrity": "sha512-MuxVZ1en1g5oGamXV3DWP89GEkdD54alcfhHd7InUW5BifAdKQEK9SLFa/5hlWbvuhMPlobF0WAx7Okq988Jxg==",
+ "version": "7.10.1",
+ "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz",
+ "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==",
"license": "MIT",
"dependencies": {
- "@inquirer/checkbox": "^4.2.2",
- "@inquirer/confirm": "^5.1.16",
- "@inquirer/editor": "^4.2.18",
- "@inquirer/expand": "^4.0.18",
- "@inquirer/input": "^4.2.2",
- "@inquirer/number": "^3.0.18",
- "@inquirer/password": "^4.0.18",
- "@inquirer/rawlist": "^4.1.6",
- "@inquirer/search": "^3.1.1",
- "@inquirer/select": "^4.3.2"
+ "@inquirer/checkbox": "^4.3.2",
+ "@inquirer/confirm": "^5.1.21",
+ "@inquirer/editor": "^4.2.23",
+ "@inquirer/expand": "^4.0.23",
+ "@inquirer/input": "^4.3.1",
+ "@inquirer/number": "^3.0.23",
+ "@inquirer/password": "^4.0.23",
+ "@inquirer/rawlist": "^4.1.11",
+ "@inquirer/search": "^3.2.2",
+ "@inquirer/select": "^4.4.2"
},
"engines": {
"node": ">=18"
@@ -2231,14 +2662,14 @@
}
},
"node_modules/@inquirer/rawlist": {
- "version": "4.1.6",
- "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.6.tgz",
- "integrity": "sha512-KOZqa3QNr3f0pMnufzL7K+nweFFCCBs6LCXZzXDrVGTyssjLeudn5ySktZYv1XiSqobyHRYYK0c6QsOxJEhXKA==",
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz",
+ "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/type": "^3.0.8",
- "yoctocolors-cjs": "^2.1.2"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
},
"engines": {
"node": ">=18"
@@ -2253,15 +2684,15 @@
}
},
"node_modules/@inquirer/search": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.1.tgz",
- "integrity": "sha512-TkMUY+A2p2EYVY3GCTItYGvqT6LiLzHBnqsU1rJbrpXUijFfM6zvUx0R4civofVwFCmJZcKqOVwwWAjplKkhxA==",
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz",
+ "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/figures": "^1.0.13",
- "@inquirer/type": "^3.0.8",
- "yoctocolors-cjs": "^2.1.2"
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
},
"engines": {
"node": ">=18"
@@ -2276,16 +2707,16 @@
}
},
"node_modules/@inquirer/select": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.2.tgz",
- "integrity": "sha512-nwous24r31M+WyDEHV+qckXkepvihxhnyIaod2MG7eCE6G0Zm/HUF6jgN8GXgf4U7AU6SLseKdanY195cwvU6w==",
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz",
+ "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==",
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.2.0",
- "@inquirer/figures": "^1.0.13",
- "@inquirer/type": "^3.0.8",
- "ansi-escapes": "^4.3.2",
- "yoctocolors-cjs": "^2.1.2"
+ "@inquirer/ansi": "^1.0.2",
+ "@inquirer/core": "^10.3.2",
+ "@inquirer/figures": "^1.0.15",
+ "@inquirer/type": "^3.0.10",
+ "yoctocolors-cjs": "^2.1.3"
},
"engines": {
"node": ">=18"
@@ -2300,9 +2731,9 @@
}
},
"node_modules/@inquirer/type": {
- "version": "3.0.8",
- "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz",
- "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==",
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz",
+ "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -3396,6 +3827,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/http-proxy": {
+ "version": "1.17.17",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz",
+ "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@@ -3435,6 +3875,7 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
"integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"undici-types": "~7.10.0"
}
@@ -3469,6 +3910,7 @@
"integrity": "sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.41.0",
@@ -3499,6 +3941,7 @@
"integrity": "sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.41.0",
"@typescript-eslint/types": "8.41.0",
@@ -4012,6 +4455,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4074,6 +4518,7 @@
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
"integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"type-fest": "^0.21.3"
@@ -4462,18 +4907,6 @@
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"license": "MIT"
},
- "node_modules/asn1.js": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
- "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
- "license": "MIT",
- "dependencies": {
- "bn.js": "^4.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "safer-buffer": "^2.1.0"
- }
- },
"node_modules/assign-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
@@ -4734,12 +5167,6 @@
"node": ">=10.13.0"
}
},
- "node_modules/bagpipe": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/bagpipe/-/bagpipe-0.3.5.tgz",
- "integrity": "sha512-42sAlmPDKes1nLm/aly+0VdaopSU9br+jkRELedhQxI5uXHgtk47I83Mpmf4zoNTRMASdLFtUkimlu/Z9zQ8+g==",
- "license": "MIT"
- },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -4878,12 +5305,6 @@
"node": ">= 6"
}
},
- "node_modules/bn.js": {
- "version": "4.12.2",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz",
- "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==",
- "license": "MIT"
- },
"node_modules/body-parser": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz",
@@ -5043,6 +5464,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001735",
"electron-to-chromium": "^1.5.204",
@@ -5299,9 +5721,9 @@
}
},
"node_modules/chardet": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz",
- "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz",
+ "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==",
"license": "MIT"
},
"node_modules/chokidar": {
@@ -5387,18 +5809,6 @@
"node": ">= 12"
}
},
- "node_modules/client-sessions": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/client-sessions/-/client-sessions-0.8.0.tgz",
- "integrity": "sha512-XERL6B5cJYGEaAigTADRr8NrUhkGmIUdrlHBzRM62uZEtFben5QYbaOxgWX79wFbCIvABhgZCWch1glw2fcyiQ==",
- "license": "MPL-2.0",
- "dependencies": {
- "cookies": "^0.7.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -5712,19 +6122,6 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
"license": "MIT"
},
- "node_modules/cookies": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.3.tgz",
- "integrity": "sha512-+gixgxYSgQLTaTIilDHAdlNPZDENDQernEMiIcZpYYP14zgHsCt4Ce1FEjFtcp6GefhozebB6orvhAAWx/IS0A==",
- "license": "MIT",
- "dependencies": {
- "depd": "~1.1.2",
- "keygrip": "~1.0.3"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/copy-descriptor": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
@@ -6085,18 +6482,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/dotenv": {
- "version": "17.2.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz",
- "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -6540,6 +6925,63 @@
"es6-symbol": "^3.1.1"
}
},
+ "node_modules/esbuild": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz",
+ "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.27.0",
+ "@esbuild/android-arm": "0.27.0",
+ "@esbuild/android-arm64": "0.27.0",
+ "@esbuild/android-x64": "0.27.0",
+ "@esbuild/darwin-arm64": "0.27.0",
+ "@esbuild/darwin-x64": "0.27.0",
+ "@esbuild/freebsd-arm64": "0.27.0",
+ "@esbuild/freebsd-x64": "0.27.0",
+ "@esbuild/linux-arm": "0.27.0",
+ "@esbuild/linux-arm64": "0.27.0",
+ "@esbuild/linux-ia32": "0.27.0",
+ "@esbuild/linux-loong64": "0.27.0",
+ "@esbuild/linux-mips64el": "0.27.0",
+ "@esbuild/linux-ppc64": "0.27.0",
+ "@esbuild/linux-riscv64": "0.27.0",
+ "@esbuild/linux-s390x": "0.27.0",
+ "@esbuild/linux-x64": "0.27.0",
+ "@esbuild/netbsd-arm64": "0.27.0",
+ "@esbuild/netbsd-x64": "0.27.0",
+ "@esbuild/openbsd-arm64": "0.27.0",
+ "@esbuild/openbsd-x64": "0.27.0",
+ "@esbuild/openharmony-arm64": "0.27.0",
+ "@esbuild/sunos-x64": "0.27.0",
+ "@esbuild/win32-arm64": "0.27.0",
+ "@esbuild/win32-ia32": "0.27.0",
+ "@esbuild/win32-x64": "0.27.0"
+ }
+ },
+ "node_modules/esbuild-sass-plugin": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.3.1.tgz",
+ "integrity": "sha512-SnO1ls+d52n6j8gRRpjexXI8MsHEaumS0IdDHaYM29Y6gakzZYMls6i9ql9+AWMSQk/eryndmUpXEgT34QrX1A==",
+ "license": "MIT",
+ "dependencies": {
+ "resolve": "^1.22.8",
+ "safe-identifier": "^0.4.2",
+ "sass": "^1.71.1"
+ },
+ "peerDependencies": {
+ "esbuild": ">=0.20.1",
+ "sass-embedded": "^1.71.1"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -6575,6 +7017,7 @@
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -6778,6 +7221,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -6979,6 +7423,7 @@
"integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"builtins": "^5.0.1",
@@ -7055,6 +7500,7 @@
"integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==",
"dev": true,
"license": "ISC",
+ "peer": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -10002,6 +10448,23 @@
"node": ">=8.0.0"
}
},
+ "node_modules/http-proxy-middleware": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz",
+ "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-proxy": "^1.17.15",
+ "debug": "^4.3.6",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.3",
+ "is-plain-object": "^5.0.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/human-signals": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
@@ -10110,6 +10573,7 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.19"
@@ -10722,12 +11186,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
- "license": "MIT"
- },
"node_modules/is-unc-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
@@ -10947,6 +11405,7 @@
"integrity": "sha512-yC3JvpP/ZcAZX5rYCtXO/g9k6VTCQz0VFE2v1FpxytWzUqfDtu0XL/pwnNvptzYItvGwomh1ehomRNMOyhCJKw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@jest/core": "30.1.1",
"@jest/types": "30.0.5",
@@ -11642,15 +12101,6 @@
"integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==",
"license": "MIT"
},
- "node_modules/keygrip": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.3.tgz",
- "integrity": "sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -11670,18 +12120,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/kruptein": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/kruptein/-/kruptein-2.2.3.tgz",
- "integrity": "sha512-BTwprBPTzkFT9oTugxKd3WnWrX630MqUDsnmBuoa98eQs12oD4n4TeI0GbpdGcYn/73Xueg2rfnw+oK4dovnJg==",
- "license": "MIT",
- "dependencies": {
- "asn1.js": "^5.4.1"
- },
- "engines": {
- "node": ">6"
- }
- },
"node_modules/last-run": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz",
@@ -12265,12 +12703,6 @@
"node": ">=6"
}
},
- "node_modules/minimalistic-assert": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
- "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
- "license": "ISC"
- },
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -12457,10 +12889,39 @@
"resolved": "https://registry.npmjs.org/nhsuk-frontend/-/nhsuk-frontend-10.0.0.tgz",
"integrity": "sha512-WrvUfYi+FAqcDjQIvtvhx4V6+5nL/K7PvFXp/IwuAQl6F9q+RwxStsr4BBufhSVSfp9vYs7ldegLsO0UtzdJAQ==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": "^20.9.0 || ^22.11.0"
}
},
+ "node_modules/nhsuk-prototype-kit": {
+ "version": "8.0.0-internal.4",
+ "resolved": "https://registry.npmjs.org/nhsuk-prototype-kit/-/nhsuk-prototype-kit-8.0.0-internal.4.tgz",
+ "integrity": "sha512-vQgkuOyvzhLyizcfFHsO/9s8a+FHHjz0ljM2Xj6yqwcdB88KvEoZV5njmhCD8CVIzbsv8WA7LElEaz/RPqlv3w==",
+ "license": "MIT",
+ "workspaces": [
+ ".",
+ "testapp"
+ ],
+ "dependencies": {
+ "@inquirer/prompts": "^7.9.0",
+ "body-parser": "^2.2.0",
+ "browser-sync": "^3.0.4",
+ "cookie-parser": "^1.4.7",
+ "esbuild": "^0.27.0",
+ "esbuild-sass-plugin": "^3.3.1",
+ "express-session": "^1.18.1",
+ "http-proxy-middleware": "^3.0.5",
+ "portscanner": "^2.2.0"
+ },
+ "engines": {
+ "node": "^20.13.0 || ^22.11.0 || ^24.11.0"
+ },
+ "peerDependencies": {
+ "express": "^5.0",
+ "nhsuk-frontend": "^10.0"
+ }
+ },
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
@@ -13116,16 +13577,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/path": {
- "version": "0.12.7",
- "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
- "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
- "license": "MIT",
- "dependencies": {
- "process": "^0.11.1",
- "util": "^0.10.3"
- }
- },
"node_modules/path-dirname": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
@@ -13479,15 +13930,6 @@
"node": ">= 0.8"
}
},
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6.0"
- }
- },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -14115,15 +14557,6 @@
"node": ">=0.12"
}
},
- "node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
@@ -14301,6 +14734,12 @@
],
"license": "MIT"
},
+ "node_modules/safe-identifier": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz",
+ "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==",
+ "license": "ISC"
+ },
"node_modules/safe-push-apply": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
@@ -14356,7 +14795,6 @@
"resolved": "https://registry.npmjs.org/sass/-/sass-1.91.0.tgz",
"integrity": "sha512-aFOZHGf+ur+bp1bCHZ+u8otKGh77ZtmFyXDo4tlYvT7PWql41Kwd8wdkPqhhT+h2879IVblcHFglIMofsFd1EA==",
"license": "MIT",
- "optional": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@@ -14377,6 +14815,7 @@
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.91.0.tgz",
"integrity": "sha512-VTckYcH1AglrZ3VpPETilTo3Ef472XKwP13lrNfbOHSR6Eo5p27XTkIi+6lrCbuhBFFGAmy+4BRoLaeFUgn+eg==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@bufbuild/protobuf": "^2.5.0",
"buffer-builder": "^0.2.0",
@@ -14728,7 +15167,6 @@
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
"integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
"license": "MIT",
- "optional": true,
"dependencies": {
"readdirp": "^4.0.1"
},
@@ -14743,15 +15181,13 @@
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz",
"integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==",
- "license": "MIT",
- "optional": true
+ "license": "MIT"
},
"node_modules/sass/node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
"integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
"license": "MIT",
- "optional": true,
"engines": {
"node": ">= 14.18.0"
},
@@ -15037,64 +15473,6 @@
"integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==",
"license": "ISC"
},
- "node_modules/session-file-store": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/session-file-store/-/session-file-store-1.5.0.tgz",
- "integrity": "sha512-60IZaJNzyu2tIeHutkYE8RiXVx3KRvacOxfLr2Mj92SIsRIroDsH0IlUUR6fJAjoTW4RQISbaOApa2IZpIwFdQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "bagpipe": "^0.3.5",
- "fs-extra": "^8.0.1",
- "kruptein": "^2.0.4",
- "object-assign": "^4.1.1",
- "retry": "^0.12.0",
- "write-file-atomic": "3.0.3"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/session-file-store/node_modules/fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- },
- "engines": {
- "node": ">=6 <7 || >=8"
- }
- },
- "node_modules/session-file-store/node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "license": "MIT",
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/session-file-store/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "license": "ISC"
- },
- "node_modules/session-file-store/node_modules/write-file-atomic": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
- "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
- "license": "ISC",
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "is-typedarray": "^1.0.0",
- "signal-exit": "^3.0.2",
- "typedarray-to-buffer": "^3.1.5"
- }
- },
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
@@ -15649,7 +16027,6 @@
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"license": "BSD-3-Clause",
- "optional": true,
"engines": {
"node": ">=0.10.0"
}
@@ -16468,6 +16845,7 @@
"version": "0.21.3",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=10"
@@ -16574,15 +16952,6 @@
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"license": "MIT"
},
- "node_modules/typedarray-to-buffer": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
- "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
- "license": "MIT",
- "dependencies": {
- "is-typedarray": "^1.0.0"
- }
- },
"node_modules/typescript": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
@@ -16956,27 +17325,12 @@
"node": ">=0.10.0"
}
},
- "node_modules/util": {
- "version": "0.10.4",
- "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
- "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
- "license": "MIT",
- "dependencies": {
- "inherits": "2.0.3"
- }
- },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
- "node_modules/util/node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
- "license": "ISC"
- },
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
diff --git a/package.json b/package.json
index 2a6354c3..8180034e 100644
--- a/package.json
+++ b/package.json
@@ -4,12 +4,8 @@
"description": "Rapidly create HTML prototypes of NHS websites and services.",
"main": "app.js",
"scripts": {
- "build": "gulp build",
- "postinstall": "npm run build",
"start": "node app.js",
"test": "jest --coverage=true",
- "prewatch": "gulp build",
- "watch": "gulp",
"lint": "npm run lint:js && npm run lint:prettier",
"lint:fix": "npm run lint:js:fix && npm run lint:prettier:fix",
"lint:prettier": "prettier --cache --cache-location .cache/prettier --cache-strategy content --check .",
@@ -23,16 +19,9 @@
"@babel/core": "^7.28.3",
"@babel/preset-env": "^7.28.3",
"@faker-js/faker": "^10.0.0",
- "@inquirer/prompts": "^7.8.4",
- "body-parser": "^2.2.0",
- "browser-sync": "^3.0.4",
- "client-sessions": "^0.8.0",
"connect-flash": "^0.1.1",
- "cookie-parser": "^1.4.7",
"dayjs": "^1.11.15",
- "dotenv": "^17.2.1",
"express": "^5.1.0",
- "express-session": "^1.18.2",
"gulp": "^5.0.1",
"gulp-babel": "^8.0.0",
"gulp-clean": "^0.4.0",
@@ -40,15 +29,12 @@
"gulp-nodemon": "^2.5.0",
"gulp-rename": "^2.1.0",
"gulp-sass": "^6.0.1",
- "lodash": "^4.17.21",
"nhsuk-frontend": "^10.0.0",
+ "nhsuk-prototype-kit": "8.0.0-internal.4",
"nunjucks": "^3.2.4",
- "path": "^0.12.7",
"plugin-error": "^2.0.1",
"pluralize": "^8.0.0",
- "portscanner": "^2.2.0",
"sass-embedded": "^1.91.0",
- "session-file-store": "^1.5.0",
"weighted": "^1.0.0"
},
"devDependencies": {