diff --git a/.environment b/.environment new file mode 100644 index 000000000..e5518e807 --- /dev/null +++ b/.environment @@ -0,0 +1,4 @@ +# Platform.sh env vars. Used for all apps. +# The file is a script which is executed in Dash. + +export PREVIEW_URL=$(echo $PLATFORM_ROUTES | base64 --decode | jq -r 'to_entries[] | select (.value.id == "preview") | .key') diff --git a/.platform/applications.yaml b/.platform/applications.yaml new file mode 100644 index 000000000..6e4d7a9b8 --- /dev/null +++ b/.platform/applications.yaml @@ -0,0 +1,158 @@ +cms: + type: 'php:8.2' + + dependencies: + php: + composer/composer: '^2.1' + + runtime: + extensions: + - sodium + + relationships: + database: 'db:mysql' + + disk: 2048 + + mounts: + '/apps/cms/web/sites/default/files': + source: local + source_path: 'files' + '/.drush': + source: local + source_path: 'drush' + + variables: + env: + NVM_VERSION: v0.39.3 + NODE_VERSION: v18.20.2 + + build: + flavor: none + + hooks: + build: | + set -ex + + # Install NVM and switch to node version defined in env vars. Script from + # https://docs.platform.sh/languages/nodejs/node-version.html#use-nvm + set +x + unset NPM_CONFIG_PREFIX + export NVM_DIR="$PLATFORM_APP_DIR/.nvm" + if [ ! -d "$PLATFORM_CACHE_DIR/.nvm" ]; then + mkdir -p $PLATFORM_CACHE_DIR/.nvm + fi + ln -s $PLATFORM_CACHE_DIR/.nvm $NVM_DIR + if [ ! -d "$PLATFORM_CACHE_DIR/.nvm/versions/node/$NODE_VERSION" ]; then + export NVM_INSTALL_FILE="${PLATFORM_CACHE_DIR}/nvm_${NVM_VERSION}_install.sh" + if [ ! -f "$NVM_INSTALL_FILE" ]; then + wget -nc -O "$NVM_INSTALL_FILE" "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh" + fi + bash $NVM_INSTALL_FILE + fi + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm use "$NODE_VERSION" + set -x + + npm install -g pnpm@8.6.12 + pnpm i + pnpm turbo:prep:cms + + deploy: | + set -ex + cd apps/cms + php ./drush/platformsh_generate_drush_yml.php + cd web + ../vendor/bin/drush -y deploy + + web: + locations: + '/': + root: 'apps/cms/web' + expires: 5m + passthru: '/index.php' + # Deny access to all static files, except those specifically allowed below. + allow: false + rules: + '\.(avif|webp|jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': + allow: true + '^/robots\.txt$': + allow: true + '^/sitemap\.xml$': + allow: true + # Deny direct access to configuration files. + '^/sites/sites\.php$': + scripts: false + '^/sites/[^/]+/settings.*?\.php$': + scripts: false + + '/sites/default/files': + allow: true + expires: 5m + passthru: '/index.php' + root: 'apps/cms/web/sites/default/files' + scripts: false + rules: + '^/sites/default/files/(css|js)': + expires: 2w + # Ensure that private files are not accessible. + '^/sites/default/files/private/.*': + allow: false + + crons: + drupal: + spec: '*/15 * * * *' + cmd: 'cd apps/cms/web && ../vendor/bin/drush cron' + +################################################################################ + +preview: + type: 'nodejs:18' + + # AXXX check + # relationships: + # cms: 'cms:http' + + disk: 1024 + + web: + commands: + start: cd apps/preview && pnpm start + + build: + flavor: none + + hooks: + build: | + set -ex + + npm install -g pnpm@8.6.12 + pnpm i + pnpm turbo:prep:preview + +################################################################################ + +publisher: + type: 'nodejs:18' + + disk: 1024 + + mounts: + '/apps/website/.cache': + source: local + source_path: 'cache' + + web: + commands: + start: cd apps/website && pnpm start + + build: + flavor: none + + hooks: + build: | + set -ex + + npm install -g pnpm@8.6.12 + pnpm i + pnpm turbo:prep:website diff --git a/.platform/routes.yaml b/.platform/routes.yaml new file mode 100644 index 000000000..0796477d5 --- /dev/null +++ b/.platform/routes.yaml @@ -0,0 +1,17 @@ +'https://cms.{default}/': + id: cms + type: upstream + upstream: 'cms:http' + cache: + enabled: true + cookies: ['/^SS?ESS/', '/^Drupal.visitor/'] + +'https://preview.{default}/': + id: preview + type: upstream + upstream: 'preview:http' + +'https://build.{default}/': + id: publisher + type: upstream + upstream: 'publisher:http' diff --git a/.platform/services.yaml b/.platform/services.yaml new file mode 100644 index 000000000..59349f89b --- /dev/null +++ b/.platform/services.yaml @@ -0,0 +1,3 @@ +db: + type: mariadb:10.11 + disk: 2048 diff --git a/apps/cms/.gitignore b/apps/cms/.gitignore index 9f48ed0ec..4b8f42c52 100644 --- a/apps/cms/.gitignore +++ b/apps/cms/.gitignore @@ -13,7 +13,8 @@ !/web/themes/custom # Lagoon integrations -/drush +/drush/sites +/drush/Commands /.drush-lock-update # Silverback diff --git a/apps/cms/composer.json b/apps/cms/composer.json index 50427ad02..30a49d13a 100644 --- a/apps/cms/composer.json +++ b/apps/cms/composer.json @@ -75,7 +75,8 @@ "drupal/userprotect": "^1.2", "drupal/webform": "^6.1.5", "drush/drush": "^12.5", - "enyo/dropzone": "^5.7.1" + "enyo/dropzone": "^5.7.1", + "platformsh/config-reader": "^2.4" }, "conflict": { "drupal/drupal": "*" @@ -118,6 +119,7 @@ }, "[web-root]/sites/default/all.services.yml": "scaffold/all.services.yml", "[web-root]/sites/default/production.settings.php": "scaffold/production.settings.php", + "[web-root]/sites/default/settings.platformsh.php": "scaffold/settings.platformsh.php", "[web-root]/robots.txt": "scaffold/robots.txt" }, "allowed-packages": [ diff --git a/apps/cms/composer.lock b/apps/cms/composer.lock index 6aa58607b..761d4ce8b 100644 --- a/apps/cms/composer.lock +++ b/apps/cms/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f2375207790855cc777235f699c7c2b9", + "content-hash": "eeddb318a084b7dcf824f6a6244c2770", "packages": [ { "name": "amazeeio/drupal_integrations", @@ -6625,6 +6625,49 @@ }, "time": "2021-09-22T16:57:06+00:00" }, + { + "name": "platformsh/config-reader", + "version": "2.4.1", + "source": { + "type": "git", + "url": "https://github.com/platformsh/config-reader-php.git", + "reference": "dc08f50f5a40a767457668ad154116c8ea89cfc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/platformsh/config-reader-php/zipball/dc08f50f5a40a767457668ad154116c8ea89cfc6", + "reference": "dc08f50f5a40a767457668ad154116c8ea89cfc6", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Platformsh\\ConfigReader\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Larry Garfield", + "email": "larry@platform.sh" + } + ], + "description": "Small helper to access Platform.sh environment variables", + "support": { + "issues": "https://github.com/platformsh/config-reader-php/issues", + "source": "https://github.com/platformsh/config-reader-php/tree/2.4.1" + }, + "time": "2023-09-14T17:07:00+00:00" + }, { "name": "psr/cache", "version": "3.0.0", @@ -15815,8 +15858,5 @@ "php": "^8.2 <8.3" }, "platform-dev": [], - "platform-overrides": { - "php": "8.2" - }, "plugin-api-version": "2.6.0" } diff --git a/apps/cms/drush/platformsh_generate_drush_yml.php b/apps/cms/drush/platformsh_generate_drush_yml.php new file mode 100644 index 000000000..f8f83b425 --- /dev/null +++ b/apps/cms/drush/platformsh_generate_drush_yml.php @@ -0,0 +1,82 @@ +inRuntime()) { + return; + } + + $routes = $platformsh->getUpstreamRoutes($platformsh->applicationName); + + // Sort URLs, with the primary route first, then by HTTPS before HTTP, then by length. + usort($routes, function (array $a, array $b) { + // false sorts before true, normally, so negate the comparison. + return + [!$a['primary'], strpos($a['url'], 'https://') !== 0, strlen($a['url'])] + <=> + [!$b['primary'], strpos($b['url'], 'https://') !== 0, strlen($b['url'])]; + }); + + // Return the url of the first one. + return reset($routes)['url'] ?: NULL; +} + +$appRoot = dirname(__DIR__); +$filename = $appRoot . '/../../.drush/drush.yml'; + +$siteUrl = _platformsh_drush_site_url(); + +if (empty($siteUrl)) { + echo "Failed to find a site URL\n"; + + if (file_exists($filename)) { + echo "The file exists but may be invalid: $filename\n"; + } + + exit(1); +} + +$siteUrlYamlEscaped = json_encode($siteUrl, JSON_UNESCAPED_SLASHES); +$scriptPath = __FILE__; + +$success = file_put_contents($filename, <</dev/null) && ([ -z "$PLATFORM_PROJECT" ] || [ "$PLATFORM_APPLICATION_NAME" = "cms" ]); then + composer install +else + echo 'Skipping composer install.' +fi diff --git a/apps/cms/prep-database.sh b/apps/cms/prep-database.sh index 242782f3c..65488569e 100755 --- a/apps/cms/prep-database.sh +++ b/apps/cms/prep-database.sh @@ -1,10 +1,12 @@ -if [ ! -z $LAGOON ]; then - # Do not touch database on Lagoon - exit 0 -fi +#!/bin/sh set -e +if [ ! -z "$LAGOON" ] || [ ! -z "$PLATFORM_PROJECT" ]; then + # Do not touch database on Lagoon or Platform.sh + exit 0 +fi + if ! test -f web/sites/default/files/.sqlite; then pnpm drupal-install pnpm export-webforms diff --git a/apps/cms/scaffold/settings.php.append.txt b/apps/cms/scaffold/settings.php.append.txt index 00575f853..eefda7a5c 100644 --- a/apps/cms/scaffold/settings.php.append.txt +++ b/apps/cms/scaffold/settings.php.append.txt @@ -65,3 +65,7 @@ if (getenv('LAGOON_ENVIRONMENT') !== 'prod') { // Disable key permissions check for Simple OAuth. // https://www.drupal.org/project/simple_oauth/issues/3021054 $settings['simple_oauth.key_permissions_check'] = FALSE; + +if (getenv('PLATFORM_PROJECT') && file_exists($app_root . '/' . $site_path . '/settings.platformsh.php')) { + include $app_root . '/' . $site_path . '/settings.platformsh.php'; +} diff --git a/apps/cms/scaffold/settings.platformsh.php b/apps/cms/scaffold/settings.platformsh.php new file mode 100644 index 000000000..b8e6b70d7 --- /dev/null +++ b/apps/cms/scaffold/settings.platformsh.php @@ -0,0 +1,134 @@ +hasRelationship('database')) { + $creds = $platformsh->credentials('database'); + $databases['default']['default'] = [ + 'driver' => $creds['scheme'], + 'database' => $creds['path'], + 'username' => $creds['username'], + 'password' => $creds['password'], + 'host' => $creds['host'], + 'port' => $creds['port'], + 'pdo' => [PDO::MYSQL_ATTR_COMPRESS => !empty($creds['query']['compression'])], + 'init_commands' => [ + 'isolation_level' => 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', + ], + ]; +} + +// Enable Redis caching. +if ($platformsh->hasRelationship('redis') && !InstallerKernel::installationAttempted() && extension_loaded('redis') && class_exists('Drupal\redis\ClientFactory')) { + $redis = $platformsh->credentials('redis'); + + // Set Redis as the default backend for any cache bin not otherwise specified. + $settings['cache']['default'] = 'cache.backend.redis'; + $settings['redis.connection']['host'] = $redis['host']; + $settings['redis.connection']['port'] = $redis['port']; + + // Apply changes to the container configuration to better leverage Redis. + // This includes using Redis for the lock and flood control systems, as well + // as the cache tag checksum. Alternatively, copy the contents of that file + // to your project-specific services.yml file, modify as appropriate, and + // remove this line. + $settings['container_yamls'][] = 'modules/contrib/redis/example.services.yml'; + + // Allow the services to work before the Redis module itself is enabled. + $settings['container_yamls'][] = 'modules/contrib/redis/redis.services.yml'; + + // Manually add the classloader path, this is required for the container cache bin definition below + // and allows to use it without the redis module being enabled. + $class_loader->addPsr4('Drupal\\redis\\', 'modules/contrib/redis/src'); + + // Use redis for container cache. + // The container cache is used to load the container definition itself, and + // thus any configuration stored in the container itself is not available + // yet. These lines force the container cache to use Redis rather than the + // default SQL cache. + $settings['bootstrap_container_definition'] = [ + 'parameters' => [], + 'services' => [ + 'redis.factory' => [ + 'class' => 'Drupal\redis\ClientFactory', + ], + 'cache.backend.redis' => [ + 'class' => 'Drupal\redis\Cache\CacheBackendFactory', + 'arguments' => ['@redis.factory', '@cache_tags_provider.container', '@serialization.phpserialize'], + ], + 'cache.container' => [ + 'class' => '\Drupal\redis\Cache\PhpRedis', + 'factory' => ['@cache.backend.redis', 'get'], + 'arguments' => ['container'], + ], + 'cache_tags_provider.container' => [ + 'class' => 'Drupal\redis\Cache\RedisCacheTagsChecksum', + 'arguments' => ['@redis.factory'], + ], + 'serialization.phpserialize' => [ + 'class' => 'Drupal\Component\Serialization\PhpSerialize', + ], + ], + ]; +} + +if ($platformsh->inRuntime()) { + // Set the deployment identifier, which is used by some Drupal cache systems. + $settings['deployment_identifier'] = $settings['deployment_identifier'] ?? $platformsh->treeId; +} + +// The 'trusted_hosts_pattern' setting allows an admin to restrict the Host header values +// that are considered trusted. If an attacker sends a request with a custom-crafted Host +// header then it can be an injection vector, depending on how the Host header is used. +// However, Platform.sh already replaces the Host header with the route that was used to reach +// Platform.sh, so it is guaranteed to be safe. The following line explicitly allows all +// Host headers, as the only possible Host header is already guaranteed safe. +$settings['trusted_host_patterns'] = ['.*']; + +// Import variables prefixed with 'drupalsettings:' into $settings +// and 'drupalconfig:' into $config. +foreach ($platformsh->variables() as $name => $value) { + $parts = explode(':', $name); + list($prefix, $key) = array_pad($parts, 3, null); + switch ($prefix) { + // Variables that begin with `drupalsettings` or `drupal` get mapped + // to the $settings array verbatim, even if the value is an array. + // For example, a variable named drupalsettings:example-setting' with + // value 'foo' becomes $settings['example-setting'] = 'foo'; + case 'drupalsettings': + case 'drupal': + $settings[$key] = $value; + break; + // Variables that begin with `drupalconfig` get mapped to the $config + // array. Deeply nested variable names, with colon delimiters, + // get mapped to deeply nested array elements. Array values + // get added to the end just like a scalar. Variables without + // both a config object name and property are skipped. + // Example: Variable `drupalconfig:conf_file:prop` with value `foo` becomes + // $config['conf_file']['prop'] = 'foo'; + // Example: Variable `drupalconfig:conf_file:prop:subprop` with value `foo` becomes + // $config['conf_file']['prop']['subprop'] = 'foo'; + // Example: Variable `drupalconfig:conf_file:prop:subprop` with value ['foo' => 'bar'] becomes + // $config['conf_file']['prop']['subprop']['foo'] = 'bar'; + // Example: Variable `drupalconfig:prop` is ignored. + case 'drupalconfig': + if (count($parts) > 2) { + $temp = &$config[$key]; + foreach (array_slice($parts, 2) as $n) { + $prev = &$temp; + $temp = &$temp[$n]; + } + $prev[$n] = $value; + } + break; + } +} diff --git a/apps/cms/turbo.json b/apps/cms/turbo.json index 36ad2b625..f1cf8cb57 100644 --- a/apps/cms/turbo.json +++ b/apps/cms/turbo.json @@ -20,7 +20,7 @@ "web/sites/default/files/**", "../../packages/ui/static/stories/webforms/**" ], - "env": ["CI", "LAGOON"] + "env": ["CI", "LAGOON", "PLATFORM_PROJECT"] }, "prep:composer": { "inputs": ["composer.json", "composer.lock", "scaffold/**", "patches/**"], @@ -32,7 +32,8 @@ "!web/modules/custom/**", "!web/themes/custom/**", "!web/sites/default/files/**" - ] + ], + "env": ["PLATFORM_PROJECT", "PLATFORM_APPLICATION_NAME"] }, "test:integration": { "dependsOn": [ diff --git a/apps/preview/package.json b/apps/preview/package.json index e5ec902c5..31fc1648d 100644 --- a/apps/preview/package.json +++ b/apps/preview/package.json @@ -16,6 +16,7 @@ "@custom/ui": "workspace:*", "express": "^4.19.2", "express-ws": "^5.0.2", + "platformsh-config": "^2.4.1", "react": "^18.2.0", "react-dom": "^18.2.0", "rxjs": "^7.8.1" diff --git a/apps/preview/server/index.ts b/apps/preview/server/index.ts index 333df04a0..1041e1467 100644 --- a/apps/preview/server/index.ts +++ b/apps/preview/server/index.ts @@ -1,7 +1,14 @@ import express from 'express'; import expressWs from 'express-ws'; +import platformsh from 'platformsh-config'; import { Subject } from 'rxjs'; +const platformshConfig = platformsh.config(); +const isPlatform = platformshConfig.isValidPlatform(); +if (platformshConfig.isValidPlatform() && !platformshConfig.inBuild()) { + process.env.DRUPAL_URL = platformshConfig.getRoute('cms').url; +} + const expressServer = express(); const expressWsInstance = expressWs(expressServer); const { app } = expressWsInstance; @@ -39,7 +46,7 @@ app.get('/__preview/*', (req, _, next) => { app.use(express.static('./dist')); const isLagoon = !!process.env.LAGOON; -const port = isLagoon ? 3000 : 8001; +const port = isLagoon ? 3000 : isPlatform ? platformshConfig.port : 8001; console.log(`Server is running on port ${port}`); app.listen({ port, host: '0.0.0.0' }); diff --git a/apps/website/package.json b/apps/website/package.json index 8ba4d3ae7..27dd63f3d 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -28,6 +28,7 @@ "image-size": "^1.1.1", "mime-types": "^2.1.35", "netlify-cli": "^17.21.1", + "platformsh-config": "^2.4.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -43,7 +44,7 @@ "vitest": "^1.1.1" }, "scripts": { - "test:static": "tsc --noEmit && eslint '**/*.{ts,tsx,js,jsx}' --ignore-path='./.gitignore'", + "test:static": "tsc --noEmit && eslint '**/*.{ts,tsx,js,jsx}' --ignore-path='./.gitignore' --config ../../.eslintrc.json", "full-rebuild": "pnpm clean && pnpm build:gatsby", "start:drupal": "pnpm run --filter @custom/cms start", "build:drupal": "CLOUDINARY_CLOUDNAME=test pnpm start-test start:drupal 8888 build:gatsby", diff --git a/apps/website/publisher.config.ts b/apps/website/publisher.config.ts index 6c5d95797..07c5845cd 100644 --- a/apps/website/publisher.config.ts +++ b/apps/website/publisher.config.ts @@ -1,10 +1,14 @@ import { defineConfig } from '@amazeelabs/publisher'; +import * as platformsh from 'platformsh-config'; + +const platformshConfig = platformsh.config(); +const isPlatform = platformshConfig.isValidPlatform(); const isNetlifyEnabled = !!process.env.NETLIFY_SITE_ID && !!process.env.NETLIFY_AUTH_TOKEN; const isLagoon = !!process.env.LAGOON; -export default defineConfig({ +const defaultConfig = defineConfig({ commands: { build: { command: isNetlifyEnabled @@ -52,3 +56,25 @@ export default defineConfig({ } : undefined, }); + +export default isPlatform + ? defineConfig({ + commands: { + build: { + command: + 'echo "Starting fake build" && sleep 5 && echo "Fake build done"', + outputTimeout: 1000 * 60 * 10, + }, + clean: 'pnpm clean', + serve: { + command: 'exit 0', + readyPattern: 'Server now ready', + readyTimeout: 1000 * 60, + port: 7999, + }, + deploy: 'echo "Fake deployment done"', + }, + databaseUrl: '/tmp/publisher.sqlite', + publisherPort: platformshConfig.port, + }) + : defaultConfig; diff --git a/apps/website/src/types/platformsh.d.ts b/apps/website/src/types/platformsh.d.ts new file mode 100644 index 000000000..2d71437e8 --- /dev/null +++ b/apps/website/src/types/platformsh.d.ts @@ -0,0 +1,6 @@ +declare module 'platformsh-config' { + export const config: () => { + isValidPlatform: () => boolean; + get port(): number; + }; +} diff --git a/package.json b/package.json index c86941856..baf3f2d9a 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,9 @@ "turbo:test:quick": "pnpm turbo:local && pnpm tb test:unit --no-daemon --go-fallback --output-logs=new-only", "turbo:prep": "pnpm turbo:local && pnpm tb prep --no-daemon --go-fallback --output-logs=new-only", "turbo:prep:force": "rm -f apps/cms/web/sites/default/files/.sqlite && pnpm tb prep --no-daemon --go-fallback --force", + "turbo:prep:cms": "pnpm turbo prep --filter @custom/cms --no-daemon --go-fallback --output-logs=new-only", + "turbo:prep:preview": "pnpm turbo prep --filter @custom/preview --no-daemon --go-fallback --output-logs=new-only", + "turbo:prep:website": "pnpm turbo prep --filter @custom/website --no-daemon --go-fallback --output-logs=new-only", "gutenberg:generate": "pnpm run --filter \"@custom/gutenberg_blocks\" gutenberg:generate" }, "private": true, diff --git a/packages/drupal/gutenberg_blocks/package.json b/packages/drupal/gutenberg_blocks/package.json index e5a3cc019..a75f88fff 100644 --- a/packages/drupal/gutenberg_blocks/package.json +++ b/packages/drupal/gutenberg_blocks/package.json @@ -5,7 +5,7 @@ "scripts": { "dev": "vite build --watch", "prep": "vite build", - "test:static": "tsc --noEmit && eslint \"**/*.{ts,tsx,js,jsx}\" --ignore-path=\"./.eslintignore\"", + "test:static": "tsc --noEmit && eslint \"**/*.{ts,tsx,js,jsx}\" --ignore-path=\"./.eslintignore\" --config ../../../.eslintrc.json", "test:fix": "tsc --noEmit && eslint \"**/*.{ts,tsx,js,jsx}\" --ignore-path=\"./.eslintignore\" --fix", "gutenberg:generate": "node ./scripts/generate-gutenberg-block.js" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2ca78a0bb..39b5d39eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: devDependencies: '@commitlint/cli': specifier: ^18.4.3 - version: 18.4.3(@types/node@18.19.31)(typescript@5.3.3) + version: 18.4.3(@types/node@20.11.17)(typescript@5.3.3) '@commitlint/config-conventional': specifier: ^18.4.3 version: 18.4.3 @@ -64,7 +64,7 @@ importers: version: 5.3.3 vitest: specifier: ^1.1.1 - version: 1.1.1(@types/node@18.19.31) + version: 1.1.1(@types/node@20.11.17) apps/cms: dependencies: @@ -201,6 +201,9 @@ importers: express-ws: specifier: ^5.0.2 version: 5.0.2(express@4.19.2) + platformsh-config: + specifier: ^2.4.1 + version: 2.4.1 react: specifier: ^18.2.0 version: 18.2.0 @@ -340,6 +343,9 @@ importers: netlify-cli: specifier: ^17.21.1 version: 17.21.1(@types/node@20.11.17) + platformsh-config: + specifier: ^2.4.1 + version: 2.4.1 react: specifier: ^18.2.0 version: 18.2.0 @@ -565,7 +571,7 @@ importers: devDependencies: '@amazeelabs/bridge-storybook': specifier: ^1.2.8 - version: 1.2.8(@storybook/addon-actions@8.1.6)(happy-dom@12.10.3)(playwright@1.43.1)(react@18.2.0) + version: 1.2.8(@storybook/addon-actions@8.1.6)(happy-dom@12.10.3)(playwright@1.44.1)(react@18.2.0) '@amazeelabs/cloudinary-responsive-image': specifier: ^1.6.15 version: 1.6.15 @@ -637,7 +643,7 @@ importers: version: 10.4.16(postcss@8.4.32) axe-playwright: specifier: ^2.0.1 - version: 2.0.1(playwright@1.43.1) + version: 2.0.1(playwright@1.44.1) cssnano: specifier: ^6.0.3 version: 6.0.3(postcss@8.4.32) @@ -779,7 +785,7 @@ packages: - webdriverio dev: false - /@amazeelabs/bridge-storybook@1.2.8(@storybook/addon-actions@8.1.6)(happy-dom@12.10.3)(playwright@1.43.1)(react@18.2.0): + /@amazeelabs/bridge-storybook@1.2.8(@storybook/addon-actions@8.1.6)(happy-dom@12.10.3)(playwright@1.44.1)(react@18.2.0): resolution: {integrity: sha512-cM0IS1pZayNDPIc//8qKglo09RgTC0gCqCRKP5i3AuFAKZiLNZxGOWwwhS4aB2q81nBnzrAVj22rnyaaqEUpdw==} peerDependencies: '@storybook/addon-actions': '>=7.6.7' @@ -790,7 +796,7 @@ packages: optionalDependencies: '@types/react': 18.2.46 typescript: 5.4.4 - vitest: 0.34.6(happy-dom@12.10.3)(playwright@1.43.1) + vitest: 0.34.6(happy-dom@12.10.3)(playwright@1.44.1) transitivePeerDependencies: - '@edge-runtime/vm' - '@vitest/browser' @@ -2678,14 +2684,14 @@ packages: resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} - /@commitlint/cli@18.4.3(@types/node@18.19.31)(typescript@5.3.3): + /@commitlint/cli@18.4.3(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==} engines: {node: '>=v18'} hasBin: true dependencies: '@commitlint/format': 18.6.1 '@commitlint/lint': 18.6.1 - '@commitlint/load': 18.6.1(@types/node@18.19.31)(typescript@5.3.3) + '@commitlint/load': 18.6.1(@types/node@20.11.17)(typescript@5.3.3) '@commitlint/read': 18.6.1 '@commitlint/types': 18.6.1 execa: 5.1.1 @@ -2756,7 +2762,7 @@ packages: '@commitlint/types': 18.6.1 dev: true - /@commitlint/load@18.6.1(@types/node@18.19.31)(typescript@5.3.3): + /@commitlint/load@18.6.1(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==} engines: {node: '>=v18'} dependencies: @@ -2766,7 +2772,7 @@ packages: '@commitlint/types': 18.6.1 chalk: 4.1.2 cosmiconfig: 8.3.6(typescript@5.3.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@18.19.31)(cosmiconfig@8.3.6)(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.11.17)(cosmiconfig@8.3.6)(typescript@5.3.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -10767,7 +10773,7 @@ packages: vite: ^4 || ^5 dependencies: '@swc/core': 1.4.13 - vite: 5.0.10(@types/node@20.11.17) + vite: 5.0.10(@types/node@18.0.0) transitivePeerDependencies: - '@swc/helpers' dev: true @@ -12434,7 +12440,7 @@ packages: rimraf: 3.0.2 dev: true - /axe-playwright@2.0.1(playwright@1.43.1): + /axe-playwright@2.0.1(playwright@1.44.1): resolution: {integrity: sha512-MHjNjGARulF9XzqSfspmNjw+tpBz4x9o1VlTuLWEUW9fqzhn+xWa1qEpuOIQPbsRWQiLfooDjQAunLeE0PM5AQ==} peerDependencies: playwright: '>1.0.0' @@ -12444,7 +12450,7 @@ packages: axe-html-reporter: 2.2.3(axe-core@4.7.0) junit-report-builder: 3.2.1 picocolors: 1.0.0 - playwright: 1.43.1 + playwright: 1.44.1 dev: true /axios@0.21.4(debug@4.3.4): @@ -14178,7 +14184,7 @@ packages: object-assign: 4.1.1 vary: 1.1.2 - /cosmiconfig-typescript-loader@5.0.0(@types/node@18.19.31)(cosmiconfig@8.3.6)(typescript@5.3.3): + /cosmiconfig-typescript-loader@5.0.0(@types/node@20.11.17)(cosmiconfig@8.3.6)(typescript@5.3.3): resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} peerDependencies: @@ -14186,7 +14192,7 @@ packages: cosmiconfig: '>=8.2' typescript: '>=4' dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 cosmiconfig: 8.3.6(typescript@5.3.3) jiti: 1.21.0 typescript: 5.3.3 @@ -26123,6 +26129,10 @@ packages: /platform@1.3.6: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + /platformsh-config@2.4.1: + resolution: {integrity: sha512-7uiWcjhP0Q7/MDBpdcaZG5X4lCMXcU1va9h4yJZyAAtMpHZoogd/C/+5ucc94z3W40FJwf07MO5p15ZrGzDfQA==} + dev: false + /playwright-core@1.43.1: resolution: {integrity: sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==} engines: {node: '>=16'} @@ -32320,6 +32330,7 @@ packages: - sugarss - supports-color - terser + dev: true optional: true /vite-node@1.1.1(@types/node@18.0.0): @@ -32343,27 +32354,6 @@ packages: - terser dev: true - /vite-node@1.1.1(@types/node@18.19.31): - resolution: {integrity: sha512-2bGE5w4jvym5v8llF6Gu1oBrmImoNSs4WmRVcavnG2me6+8UQntTqLiAMFyiAobp+ZXhj5ZFhI7SmLiFr/jrow==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4 - pathe: 1.1.2 - picocolors: 1.0.0 - vite: 5.2.8(@types/node@18.19.31) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vite-node@1.1.1(@types/node@20.11.17): resolution: {integrity: sha512-2bGE5w4jvym5v8llF6Gu1oBrmImoNSs4WmRVcavnG2me6+8UQntTqLiAMFyiAobp+ZXhj5ZFhI7SmLiFr/jrow==} engines: {node: ^18.0.0 || >=20.0.0} @@ -32538,6 +32528,8 @@ packages: rollup: 4.14.1 optionalDependencies: fsevents: 2.3.3 + dev: false + optional: true /vite@5.2.8(@types/node@20.11.17): resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} @@ -32573,6 +32565,7 @@ packages: rollup: 4.14.1 optionalDependencies: fsevents: 2.3.3 + dev: true /vitest@0.34.6: resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} @@ -32675,7 +32668,7 @@ packages: dependencies: '@types/chai': 4.3.14 '@types/chai-subset': 1.3.5 - '@types/node': 20.11.17 + '@types/node': 18.19.31 '@vitest/expect': 0.34.6 '@vitest/runner': 0.34.6 '@vitest/snapshot': 0.34.6 @@ -32688,15 +32681,15 @@ packages: debug: 4.3.4 happy-dom: 12.10.3 local-pkg: 0.4.3 - magic-string: 0.30.10 + magic-string: 0.30.9 pathe: 1.1.2 picocolors: 1.0.0 std-env: 3.7.0 strip-literal: 1.3.0 tinybench: 2.6.0 tinypool: 0.7.0 - vite: 5.2.8(@types/node@20.11.17) - vite-node: 0.34.6(@types/node@20.11.17) + vite: 5.2.8(@types/node@18.19.31) + vite-node: 0.34.6(@types/node@18.19.31) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -32709,7 +32702,7 @@ packages: dev: false optional: true - /vitest@0.34.6(happy-dom@12.10.3)(playwright@1.43.1): + /vitest@0.34.6(happy-dom@12.10.3)(playwright@1.44.1): resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} hasBin: true @@ -32759,7 +32752,7 @@ packages: magic-string: 0.30.10 pathe: 1.1.2 picocolors: 1.0.0 - playwright: 1.43.1 + playwright: 1.44.1 std-env: 3.7.0 strip-literal: 1.3.0 tinybench: 2.6.0 @@ -32836,7 +32829,7 @@ packages: - terser dev: true - /vitest@1.1.1(@types/node@18.19.31): + /vitest@1.1.1(@types/node@20.11.17): resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -32861,7 +32854,7 @@ packages: jsdom: optional: true dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 '@vitest/expect': 1.1.1 '@vitest/runner': 1.1.1 '@vitest/snapshot': 1.1.1 @@ -32880,8 +32873,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.6.0 tinypool: 0.8.3 - vite: 5.2.8(@types/node@18.19.31) - vite-node: 1.1.1(@types/node@18.19.31) + vite: 5.2.8(@types/node@20.11.17) + vite-node: 1.1.1(@types/node@20.11.17) why-is-node-running: 2.2.2 transitivePeerDependencies: - less