diff --git a/.gitignore b/.gitignore
index 9160f5a27..945354821 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,6 @@ local.log
# ember-api-docs-data checkout
/ember-api-docs-data/
/ember-api-docs-data
+
+# prerendered output tmp dir
+/prerender
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e757f4973..1eef41118 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -80,22 +80,22 @@ cd to the cloned ember-api-docs directory
ensure Node.js and npm are installed
follow these commands to build ember.js
- - npm install
- - npm build
+ - pnpm install
+ - pnpm build
```
## Development steps
1. Follow the setup steps listed above under [Building Ember.js API](#building-emberjs-api-docs).
-2. To start the development server, run `npm start`.
+2. To start the development server, run `pnpm start`.
-3. To run all tests run `npm test`
+3. To run all tests run `pnpm test`
-4. To run the app with fastboot cli like our server deployment run the following commands,
+4. To run prerender and run the site as it would be for a production deploy,
```
-- ember deploy production
-- ./bin/ember-fastboot tmp/deploy-dist
+- pnpm build
+- cd dist && npx http-server
```
diff --git a/Procfile b/Procfile
deleted file mode 100644
index 9fab527f7..000000000
--- a/Procfile
+++ /dev/null
@@ -1,2 +0,0 @@
-web: ./bin/ember-fastboot tmp/deploy-dist --port $PORT
-release: npm i -g fastly-cli && fastly purge-all -k $FASTLY_PURGE_KEY -s $FASTLY_SERVICE_ID
\ No newline at end of file
diff --git a/app/adapters/application.js b/app/adapters/application.js
index fda8232e6..fdfe7d082 100644
--- a/app/adapters/application.js
+++ b/app/adapters/application.js
@@ -2,7 +2,6 @@ import { service } from '@ember/service';
import { JSONAPIAdapter } from '@warp-drive/legacy/adapter/json-api';
import { pluralize } from 'ember-inflector';
import { isBlank } from '@ember/utils';
-import config from 'ember-api-docs/config/environment';
export default class Application extends JSONAPIAdapter {
currentProject = '';
@@ -80,9 +79,7 @@ export default class Application extends JSONAPIAdapter {
throw new Error('Unexpected model lookup');
}
- const base = this.fastboot.isFastBoot
- ? config.APP.domain
- : window.location.origin;
+ const base = window.location.origin;
url = `${base}/${url}.json`;
try {
diff --git a/app/components/in-head.gjs b/app/components/in-head.gjs
new file mode 100644
index 000000000..396a979c7
--- /dev/null
+++ b/app/components/in-head.gjs
@@ -0,0 +1,9 @@
+function getHead() {
+ return document.head;
+}
+
+
+ {{#in-element (getHead) insertBefore=null}}
+ {{yield}}
+ {{/in-element}}
+
diff --git a/app/controllers/project-version.js b/app/controllers/project-version.js
index a192dd711..fc8e34672 100644
--- a/app/controllers/project-version.js
+++ b/app/controllers/project-version.js
@@ -17,7 +17,7 @@ export default class ProjectVersionController extends Controller {
project;
@service
- fastboot;
+ prerender;
@service router;
@service('project') projectService;
diff --git a/app/instance-initializers/clear-double-boot.js b/app/instance-initializers/clear-double-boot.js
new file mode 100644
index 000000000..2eb2a1117
--- /dev/null
+++ b/app/instance-initializers/clear-double-boot.js
@@ -0,0 +1,41 @@
+// This removes any pre-rendered elements, so that the booting
+// application will replace the pre-rendered output
+export function clearHtml() {
+ let current = document.getElementById('prerender-body-start');
+ let endMarker = document.getElementById('prerender-body-end');
+
+ if (current && endMarker) {
+ let shoeboxNodes = document.querySelectorAll('[type="prerender/shoebox"]');
+ let shoeboxNodesArray = []; // Note that IE11 doesn't support more concise options like Array.from, so we have to do something like this
+ for (let i = 0; i < shoeboxNodes.length; i++) {
+ shoeboxNodesArray.push(shoeboxNodes[i]);
+ }
+ let parent = current.parentElement;
+ let nextNode;
+ do {
+ nextNode = current.nextSibling;
+ parent.removeChild(current);
+ current = nextNode;
+ } while (
+ nextNode &&
+ nextNode !== endMarker &&
+ shoeboxNodesArray.indexOf(nextNode) < 0
+ );
+ endMarker.parentElement.removeChild(endMarker);
+ }
+}
+export default {
+ name: 'clear-double-boot',
+
+ initialize(instance) {
+ const prerender = instance.lookup('service:prerender');
+ if (!prerender.isPrerendering) {
+ const originalDidCreateRootView = instance.didCreateRootView;
+
+ instance.didCreateRootView = function () {
+ clearHtml();
+ originalDidCreateRootView.apply(instance, arguments);
+ };
+ }
+ },
+};
diff --git a/app/instance-initializers/ember-data-prerender.js b/app/instance-initializers/ember-data-prerender.js
new file mode 100644
index 000000000..295d49400
--- /dev/null
+++ b/app/instance-initializers/ember-data-prerender.js
@@ -0,0 +1,69 @@
+import { dasherize } from '@ember/string';
+
+export function initialize(applicationInstance) {
+ window.__emberApiDocs = window.__emberApiDocs ?? applicationInstance;
+
+ let store = applicationInstance.lookup('service:store');
+ let shoebox = applicationInstance.lookup('service:shoebox');
+ const isPrerendering =
+ applicationInstance.lookup('service:prerender').isPrerendering;
+
+ if (!isPrerendering) {
+ if (!shoebox) {
+ return;
+ }
+ let dump = shoebox.retrieve('ember-data-store');
+ if (!dump) {
+ return;
+ }
+ store.pushPayload(dump.records);
+ return;
+ }
+
+ shoebox?.put('ember-data-store', {
+ get records() {
+ const modelNames = Object.keys(
+ store.cacheKeyManager._cache.resourcesByType,
+ );
+ return modelNames
+ .map((name) => {
+ return store.peekAll(name);
+ })
+ .reduce((a, b) => a.concat(b), [])
+ .filter((record) => record.get('isLoaded') && !record.get('isNew'))
+ .map((record) => {
+ const serializedRecord = record.serialize({ includeId: true });
+
+ record.eachRelationship((name, meta) => {
+ const link = record[meta.kind](name).link();
+
+ if (link) {
+ const dashName = dasherize(name);
+
+ serializedRecord.data.relationships =
+ serializedRecord.data.relationships || {};
+ serializedRecord.data.relationships[dashName] =
+ serializedRecord.data.relationships[dashName] || {};
+ serializedRecord.data.relationships[dashName].links = {
+ related: link,
+ };
+ }
+ });
+
+ return serializedRecord;
+ })
+ .reduce(
+ (a, b) => {
+ a.data.push(b.data);
+ return a;
+ },
+ { data: [] },
+ );
+ },
+ });
+}
+
+export default {
+ name: 'ember-data-prerender',
+ initialize,
+};
diff --git a/app/instance-initializers/ember-meta-store.js b/app/instance-initializers/ember-meta-store.js
index 9c5fa7d3d..06534b26e 100644
--- a/app/instance-initializers/ember-meta-store.js
+++ b/app/instance-initializers/ember-meta-store.js
@@ -2,11 +2,10 @@ import { isPresent } from '@ember/utils';
export function initialize(appInstance) {
const metaStore = appInstance.lookup('service:meta-store');
- const fastBootService = appInstance.lookup('service:fastboot');
+ const shoebox = appInstance.lookup('service:shoebox');
+ const isPrerendering = appInstance.lookup('service:prerender').isPrerendering;
- const shoebox = fastBootService.get('shoebox');
-
- if (typeof FastBoot !== 'undefined') {
+ if (isPrerendering) {
shoebox.put(
'meta-store',
metaStore.getProperties('availableProjectVersions', 'projectRevMap'),
diff --git a/app/router.js b/app/router.js
index 4e91dd14b..ac01d4a3e 100644
--- a/app/router.js
+++ b/app/router.js
@@ -2,7 +2,7 @@ import EmberRouter from '@ember/routing/router';
import config from 'ember-api-docs/config/environment';
import { withHashSupport } from 'ember-api-docs/utils/url-hash-polyfill';
-// The following adds support for URL hash routing for those URLs not rendered with fastboot
+// The following adds support for URL hash routing for those URLs not prerendered
@withHashSupport
class AppRouter extends EmberRouter {
location = config.locationType;
diff --git a/app/routes/application.js b/app/routes/application.js
index b1bda91d6..2f9c5dcdc 100644
--- a/app/routes/application.js
+++ b/app/routes/application.js
@@ -14,7 +14,7 @@ export default class ApplicationRoute extends Route {
router;
@service
- fastboot;
+ prerender;
@service
metrics;
@@ -22,14 +22,17 @@ export default class ApplicationRoute extends Route {
@service
routerScroll;
+ @service
+ shoebox;
+
constructor() {
super(...arguments);
- if (!this.fastboot.isFastBoot) {
+ if (!this.prerender.isPrerendering) {
this.router.on('routeDidChange', this.trackPage);
/* Hax from https://github.com/DockYard/ember-router-scroll/issues/263
to handle router scroll behavior when the page was initially served
- with fastboot
+ pre-rendered
*/
this.routerScroll.set('preserveScrollPosition', true);
@@ -39,8 +42,16 @@ export default class ApplicationRoute extends Route {
}
}, 1000);
}
+
+ if (this.prerender.isPrerendering) {
+ this.router.on('routeDidChange', this.storeShoebox);
+ }
}
+ storeShoebox = () => {
+ this.shoebox.store();
+ };
+
trackPage = () => {
// this is constant for this app and is only used to identify page views in the GA dashboard
const hostname = ENV.APP.domain.replace(/(http|https)?:?\/\//g, '');
diff --git a/app/routes/not-found.js b/app/routes/not-found.js
index c91695fa5..b7c9290a5 100644
--- a/app/routes/not-found.js
+++ b/app/routes/not-found.js
@@ -1,17 +1,6 @@
import Route from '@ember/routing/route';
-import { service } from '@ember/service';
export default class NotFoundRoute extends Route {
- @service fastboot;
-
- beforeModel() {
- if (!this.fastboot.isFastBoot) {
- return;
- }
-
- this.fastboot.response.statusCode = 404;
- }
-
redirect() {
if (typeof window === 'undefined' || !window.location) {
return;
diff --git a/app/routes/project-version.js b/app/routes/project-version.js
index 61e68b046..95ab08b8f 100644
--- a/app/routes/project-version.js
+++ b/app/routes/project-version.js
@@ -4,12 +4,7 @@ import semverCompare from 'semver-compare';
import getFullVersion from 'ember-api-docs/utils/get-full-version';
import getLastVersion from 'ember-api-docs/utils/get-last-version';
-import config from 'ember-api-docs/config/environment';
-
export default class ProjectVersionRoute extends Route {
- @service
- fastboot;
-
@service
headData;
@@ -115,16 +110,6 @@ export default class ProjectVersionRoute extends Route {
_gatherHeadDataFromVersion(model, projectVersion) {
this.headData.isRelease = projectVersion === 'release';
this.headData.compactVersion = model.get('compactVersion');
- this.headData.urlVersion = projectVersion;
- if (!this.headData.isRelease) {
- let request = this.fastboot.request;
- let href = this.fastboot.isFastBoot
- ? `${config.APP.domain}/${request.path}`
- : window.location.href;
- let version = new RegExp(model.get('compactVersion'), 'g');
- let canonicalUrl = href.replace(version, 'release');
- this.headData.canonicalUrl = canonicalUrl;
- }
}
serialize(model) {
diff --git a/app/routes/project.js b/app/routes/project.js
index 063076b35..9d6f10ecd 100644
--- a/app/routes/project.js
+++ b/app/routes/project.js
@@ -25,7 +25,7 @@ export default class ProjectRoute extends Route {
});
}
- // Using redirect instead of afterModel so transition succeeds and returns 307 in fastboot
+ // Using redirect instead of afterModel so transition succeeds
redirect(project /*, transition */) {
return this.router.transitionTo(
'project-version',
diff --git a/app/services/head-data.js b/app/services/head-data.js
index f45fe55b3..cacfaaf44 100644
--- a/app/services/head-data.js
+++ b/app/services/head-data.js
@@ -5,7 +5,6 @@ export default class HeadDataService extends Service {
@tracked title;
@tracked isRelease;
@tracked compactVersion;
- @tracked urlVersion;
@tracked canonicalUrl;
@tracked description;
}
diff --git a/app/services/prerender.js b/app/services/prerender.js
new file mode 100644
index 000000000..97164eea2
--- /dev/null
+++ b/app/services/prerender.js
@@ -0,0 +1,7 @@
+import Service from '@ember/service';
+
+export default class PrerenderService extends Service {
+ get isPrerendering() {
+ return window.__isPrerendering;
+ }
+}
diff --git a/app/services/shoebox.js b/app/services/shoebox.js
new file mode 100644
index 000000000..e26935c03
--- /dev/null
+++ b/app/services/shoebox.js
@@ -0,0 +1,86 @@
+import Service, { service } from '@ember/service';
+import { assert } from '@ember/debug';
+
+export default class ShoeboxService extends Service {
+ @service prerender;
+
+ shoebox = {};
+
+ retrieve(key) {
+ if (this.prerender.isPrerendering) {
+ return this.shoebox?.[key];
+ }
+
+ let shoeboxItem = this.shoebox?.[key];
+ if (shoeboxItem) {
+ return shoeboxItem;
+ }
+
+ let el = document.querySelector(`#shoebox-${key}`);
+ if (!el) {
+ return;
+ }
+ let valueString = el.textContent;
+ if (!valueString) {
+ return;
+ }
+
+ shoeboxItem = JSON.parse(valueString);
+ this.shoebox[key] = shoeboxItem;
+
+ return shoeboxItem;
+ }
+
+ put(key, value) {
+ assert(
+ 'shoebox.put is only invoked from the pre-rendered application',
+ this.prerender.isPrerendering,
+ );
+ assert('the provided key is a string', typeof key === 'string');
+
+ this.shoebox[key] = value;
+ }
+
+ store() {
+ const shoebox = this.shoebox;
+ const doc = window.document;
+
+ // Clear any existing prerender/shoebox script tags
+ const existingShoeboxes = doc.querySelectorAll(
+ 'script[type="prerender/shoebox"]',
+ );
+ existingShoeboxes.forEach((el) => el.remove());
+
+ for (let key in shoebox) {
+ if (!hasOwnProperty.call(shoebox, key)) {
+ continue;
+ }
+ let value = shoebox[key];
+ let textValue = JSON.stringify(value);
+ textValue = escapeJSONString(textValue);
+
+ let scriptEl = doc.createElement('script');
+
+ scriptEl.setAttribute('type', 'prerender/shoebox');
+ scriptEl.setAttribute('id', `shoebox-${key}`);
+ scriptEl.textContent = textValue;
+ doc.body.appendChild(scriptEl);
+ }
+ }
+}
+
+const JSON_ESCAPE = {
+ '&': '\\u0026',
+ '>': '\\u003e',
+ '<': '\\u003c',
+ '\u2028': '\\u2028',
+ '\u2029': '\\u2029',
+};
+
+const JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/g;
+
+function escapeJSONString(string) {
+ return string.replace(JSON_ESCAPE_REGEXP, function (match) {
+ return JSON_ESCAPE[match];
+ });
+}
diff --git a/app/templates/application.gjs b/app/templates/application.gjs
index e22bd3c43..dff1ea7a2 100644
--- a/app/templates/application.gjs
+++ b/app/templates/application.gjs
@@ -1,22 +1,60 @@
import pageTitle from 'ember-page-title/helpers/page-title';
-import HeadLayout from 'ember-cli-head/components/head-layout';
+import InHead from 'ember-api-docs/components/in-head';
import EsHeader from 'ember-styleguide/components/es-header';
import ApiSearch from 'ember-api-docs/components/api-search';
import EsFooter from 'ember-styleguide/components/es-footer';
+import Component from '@glimmer/component';
+import { service } from '@ember/service';
import BasicDropdownWormhole from 'ember-basic-dropdown/components/basic-dropdown-wormhole';
-
- {{pageTitle "Ember API Documentation"}}
+import config from 'ember-api-docs/config/environment';
-
+export default class Application extends Component {
+ @service headData;
+ @service router;
+ @service prerender;
-
-
-
+ get canonicalUrl() {
+ let path = this.router.currentURL;
+ let version = new RegExp(this.headData.compactVersion, 'g');
+ return `${config.APP.domain}${path.replace(version, 'release')}`;
+ }
-
- {{outlet}}
-
+
+ {{pageTitle "Ember API Documentation"}}
-
-
-
+ {{#if this.prerender.isPrerendering}}
+ {{! template-lint-disable no-forbidden-elements}}
+
+ {{/if}}
+
+
+ {{! template-lint-disable no-forbidden-elements}}
+
+
+ {{#if this.headData.description}}
+
+
+ {{/if}}
+
+ {{#unless this.headData.isRelease}}
+
+ {{/unless}}
+
+
+
+
+
+
+
+ {{outlet}}
+
+
+
+
+
+ {{#if this.prerender.isPrerendering}}
+ {{! template-lint-disable no-forbidden-elements}}
+
+ {{/if}}
+
+}
diff --git a/app/templates/head.hbs b/app/templates/head.hbs
index e697fb315..e69de29bb 100644
--- a/app/templates/head.hbs
+++ b/app/templates/head.hbs
@@ -1,8 +0,0 @@
-{{#if this.model.description}}
-
-
-{{/if}}
-
-{{#unless this.model.isRelease}}
-
-{{/unless}}
diff --git a/app/templates/project-version.gjs b/app/templates/project-version.gjs
index edae47fe1..108246211 100644
--- a/app/templates/project-version.gjs
+++ b/app/templates/project-version.gjs
@@ -44,7 +44,7 @@ import ScrollToTopButton from 'ember-api-docs/components/scroll-to-top-button';
{{outlet}}
- {{#unless @controller.fastboot.isFastBoot}}
+ {{#unless @controller.prerender.isPrerendering}}
{{/unless}}
diff --git a/app/utils/url-hash-polyfill.js b/app/utils/url-hash-polyfill.js
index 7e7c1b7c8..56c659738 100644
--- a/app/utils/url-hash-polyfill.js
+++ b/app/utils/url-hash-polyfill.js
@@ -9,7 +9,7 @@ import { schedule } from '@ember/runloop';
import { waitForPromise } from '@ember/test-waiters';
/* Taken from ember-url-hash-polyfill (https://github.com/CrowdStrike/ember-url-hash-polyfill/)
- and modified to not run in Fastboot. The original addon is not maintained.
+ and modified to not run when pre-rendered. The original addon is not maintained.
There is a PR to add it to ember-primitives https://github.com/universal-ember/ember-primitives/pull/529
*/
@@ -73,7 +73,7 @@ async function setupHashSupport(router) {
let initialURL;
let owner = getOwner(router);
- if (owner.lookup('service:fastboot').isFastBoot) {
+ if (owner.lookup('service:prerender').isPrerendering) {
return;
}
diff --git a/bin/build.mjs b/bin/build.mjs
new file mode 100755
index 000000000..e9c81c86a
--- /dev/null
+++ b/bin/build.mjs
@@ -0,0 +1,37 @@
+import { execSync, spawn } from 'child_process';
+import { cpSync, rmSync } from 'fs';
+import { join } from 'path';
+
+const PORT = 8080;
+
+console.log('Installing playwright browsers...');
+execSync('pnpm exec playwright install', { stdio: 'inherit' });
+
+console.log('\nBuilding production app...');
+execSync('ember build --environment=production', { stdio: 'inherit' });
+
+console.log(`\nStarting http-server on port ${PORT}...`);
+const server = spawn('http-server', ['-p', String(PORT), '--silent'], {
+ cwd: join(process.cwd(), 'dist'),
+ stdio: 'ignore',
+});
+
+// Wait for server to be ready
+await new Promise((resolve) => setTimeout(resolve, 2000));
+
+try {
+ console.log('\nRunning prerender...');
+ execSync('pnpm prerender', { stdio: 'inherit' });
+
+ console.log('\nMoving prerendered content to dist...');
+ const prerenderDir = join(process.cwd(), 'prerender');
+ const distDir = join(process.cwd(), 'dist');
+
+ cpSync(prerenderDir, distDir, { recursive: true });
+ rmSync(prerenderDir, { recursive: true, force: true });
+
+ console.log('\nBuild complete!');
+} finally {
+ console.log('\nShutting down server...');
+ server.kill();
+}
diff --git a/bin/ember-fastboot b/bin/ember-fastboot
deleted file mode 100755
index 18bda8ee2..000000000
--- a/bin/ember-fastboot
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env node
-"use strict";
-
-/* eslint-env node */
-const FastBootAppServer = require("fastboot-app-server");
-const ExpressHTTPServer = require("fastboot-app-server/src/express-http-server");
-const parseArgs = require("minimist");
-const express = require("express");
-const { URL } = require("url");
-const enforce = require("express-sslify");
-
-// Provide a title to the process in `ps`
-process.title = "ember-fastboot-server";
-
-let argOptions = {
- default: { port: 3000, host: "::" },
-};
-
-let options = parseArgs(process.argv.slice(2), argOptions);
-let distPath = options._[0];
-
-if (!distPath) {
- console.error(
- `You must call ember-fastboot with the path of a fastboot-dist directory:
- ember-fastboot fastboot-dist`,
- );
- process.exit(1);
-}
-
-const serverOptions = {
- port: options.port,
- distPath,
- gzip: false, // Let Fastly take care of compression, reducing load on the fastboot
-};
-
-const httpServer = new ExpressHTTPServer(serverOptions);
-
-const app = httpServer.app;
-
-app.use(
- enforce.HTTPS({
- trustProtoHeader: true,
- trustXForwardedHostHeader: true,
- }),
-);
-
-app.use(
- express.static(distPath, {
- setHeaders(res, path) {
- if (!path.endsWith("index.html")) {
- res.setHeader("Cache-Control", "public, max-age=365000000, immutable");
- }
- res.removeHeader("X-Powered-By");
- },
- }),
-);
-
-/** We rewrite the 307 location header into a relativeURL so that our special setup is handled */
-app.use(function (req, res, next) {
- const originalSendFn = res.send;
-
- res.send = function () {
- if (res.hasHeader("location")) {
- let originalLocation = res.getHeader("location");
-
- // FastBoot broke us once by removing the protocol so adding a check for safety
- if (originalLocation.startsWith("//")) {
- originalLocation = `http:${originalLocation}`;
- }
-
- let relativeURL = "/ember/2.14/namespaces/Ember";
-
- try {
- relativeURL = new URL(originalLocation).pathname;
- } catch (e) {
- console.log(`Original location value: ${originalLocation}`);
- console.log(e);
- }
-
- res.setHeader("location", relativeURL);
- arguments[0] = arguments[0].replace(
- new RegExp(originalLocation, "g"),
- relativeURL,
- );
- }
- originalSendFn.apply(res, arguments);
- };
-
- res.removeHeader("X-Powered-By");
- next();
-});
-
-let server = new FastBootAppServer(
- Object.assign({ httpServer }, serverOptions),
-);
-
-server.start();
diff --git a/config/environment.js b/config/environment.js
index 66c42edc6..90d4a2338 100644
--- a/config/environment.js
+++ b/config/environment.js
@@ -28,15 +28,6 @@ module.exports = function (environment) {
domain: 'http://localhost:4200',
},
- fastboot: {
- hostWhitelist: [
- /^[\w-]+\.herokuapp\.com$/,
- /^localhost:\d+$/,
- /^127\.0\.0\.1:\d+$/,
- /^[\w-]+\.fastly\.net$/,
- /^[\w-]+\.emberjs\.com$/,
- ],
- },
algolia: {
algoliaId: ALGOLIA_APP_ID,
algoliaKey: ALGOLIA_API_KEY,
diff --git a/ember-cli-build.js b/ember-cli-build.js
index a6348ca04..c3185d75e 100644
--- a/ember-cli-build.js
+++ b/ember-cli-build.js
@@ -2,14 +2,10 @@
const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const envIsProduction = process.env.EMBER_ENV === 'production';
-const premberUrls = require('./prember-urls');
const { setConfig } = require('@warp-drive/core/build-config');
module.exports = function (defaults) {
const app = new EmberApp(defaults, {
- prember: {
- urls: premberUrls(),
- },
fingerprint: {
extensions: ['js', 'css', 'jpg', 'png', 'gif', 'map', 'webmanifest'],
generateAssetMap: true,
@@ -56,13 +52,11 @@ module.exports = function (defaults) {
});
const { Webpack } = require('@embroider/webpack');
- const appTree = require('@embroider/compat').compatBuild(app, Webpack, {
+ return require('@embroider/compat').compatBuild(app, Webpack, {
staticAddonTrees: true,
staticAddonTestSupportTrees: true,
staticHelpers: true,
staticModifiers: true,
staticComponents: true,
});
-
- return require('prember').prerender(app, appTree);
};
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 7b6e0b5f1..61cd1d362 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -95,6 +95,7 @@ export default [
'ember-cli-build.js',
'prember-urls.js',
'lib/api-docs-data/**/*.js',
+ 'prerender.js',
],
...n.configs['flat/recommended-script'],
plugins: {
diff --git a/fastboot/initializers/ajax.js b/fastboot/initializers/ajax.js
deleted file mode 100644
index bd5675300..000000000
--- a/fastboot/initializers/ajax.js
+++ /dev/null
@@ -1,8 +0,0 @@
-export default {
- name: 'ajax-service',
- initialize() {
- // noop
- // This is to override Fastboot's initializer which prevents ember-fetch from working
- // https://github.com/ember-fastboot/ember-cli-fastboot/blob/master/fastboot/initializers/ajax.js
- },
-};
diff --git a/package.json b/package.json
index dbaa60125..c126992ea 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
},
"scripts": {
"clone": "rm -rf ember-api-docs-data && git clone --depth=1 https://github.com/ember-learn/ember-api-docs-data.git",
- "build": "ember build --environment=production",
+ "build": "node bin/build.mjs",
"format": "prettier . --cache --write",
"lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto",
"lint:css": "stylelint \"**/*.css\"",
@@ -25,6 +25,7 @@
"lint:hbs:fix": "ember-template-lint . --fix",
"lint:js": "eslint . --cache",
"lint:js:fix": "eslint . --fix",
+ "prerender": "node prerender.js",
"start": "ember serve",
"test:ember": "ember test"
},
@@ -68,14 +69,11 @@
"ember-cli-deploy-build": "^3.0.0",
"ember-cli-deploy-gzip": "^3.0.0",
"ember-cli-deprecation-workflow": "^3.4.0",
- "ember-cli-fastboot": "^4.1.5",
- "ember-cli-head": "^2.0.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-cli-inject-live-reload": "^2.1.0",
"ember-cli-showdown": "^9.0.1",
"ember-cli-terser": "^4.0.2",
"ember-concurrency": "^4.0.6",
- "ember-data-fastboot": "https://github.com/kategengler/ember-data-fastboot#v0.0.1",
"ember-decorators": "^6.1.1",
"ember-eslint-parser": "^0.5.11",
"ember-inflector": "^6.0.0",
@@ -102,8 +100,8 @@
"eslint-plugin-n": "^17.21.3",
"eslint-plugin-qunit": "^8.2.5",
"express-sslify": "^1.2.0",
- "fastboot-app-server": "^4.1.4",
"globals": "^15.15.0",
+ "http-server": "^14.1.1",
"lint-to-the-future": "^2.6.3",
"lint-to-the-future-ember-template": "^4.1.0",
"lint-to-the-future-eslint": "^3.1.0",
@@ -117,6 +115,7 @@
"lodash.values": "^4.3.0",
"minimist": "^1.2.6",
"normalize.css": "^8.0.1",
+ "playwright": "^1.58.2",
"prember": "^2.1.0",
"prettier": "^3.6.2",
"prettier-plugin-ember-template-tag": "^2.1.0",
@@ -132,7 +131,7 @@
"webpack": "^5.101.3"
},
"engines": {
- "node": ">= 20.11",
+ "node": ">= 22.22",
"pnpm": "10"
},
"packageManager": "pnpm@10.34.1",
@@ -142,13 +141,6 @@
"ember": {
"edition": "octane"
},
- "fastbootDependencies": [
- "crypto",
- "algoliasearch",
- "node-fetch",
- "abortcontroller-polyfill",
- "abortcontroller-polyfill/dist/cjs-ponyfill"
- ],
"ember-addon": {
"paths": [
"lib/api-docs-data"
diff --git a/patches/ember-data-fastboot@0.1.2.patch b/patches/ember-data-fastboot@0.1.2.patch
deleted file mode 100644
index ffb056789..000000000
--- a/patches/ember-data-fastboot@0.1.2.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/fastboot/instance-initializers/ember-data-fastboot.js b/fastboot/instance-initializers/ember-data-fastboot.js
-index b6db25d90653b5a6b742cb02f2dbba0fd66fefca..9cbafde3d3281f45344b2152dccef4e55ba5984a 100644
---- a/fastboot/instance-initializers/ember-data-fastboot.js
-+++ b/fastboot/instance-initializers/ember-data-fastboot.js
-@@ -6,9 +6,9 @@ export function initialize(applicationInstance) {
-
- shoebox.put('ember-data-store', {
- get records() {
-- const modelNames = Object.keys(store._modelFactoryCache);
-+ const modelNames = Object.keys(store.cacheKeyManager._cache.resourcesByType);
- return modelNames.map(name => {
-- return store.peekAll(name).toArray();
-+ return store.peekAll(name);
- }).reduce((a,b) => a.concat(b), [])
- .filter(record => record.get('isLoaded') && !record.get('isNew'))
- .map(record => {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5e457b6db..5998decbb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4,11 +4,6 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
-patchedDependencies:
- ember-data-fastboot@0.1.2:
- hash: d43942b2da6f05a2962db8c115fdee0f38acfaa0b61d16b183cee3282897973c
- path: patches/ember-data-fastboot@0.1.2.patch
-
importers:
.:
@@ -130,12 +125,6 @@ importers:
ember-cli-deprecation-workflow:
specifier: ^3.4.0
version: 3.4.0(ember-source@6.7.0(@glimmer/component@2.0.0)(rsvp@4.8.5))
- ember-cli-fastboot:
- specifier: ^4.1.5
- version: 4.1.5(ember-source@6.7.0(@glimmer/component@2.0.0)(rsvp@4.8.5))
- ember-cli-head:
- specifier: ^2.0.0
- version: 2.0.0
ember-cli-htmlbars:
specifier: ^6.3.0
version: 6.3.0
@@ -151,9 +140,6 @@ importers:
ember-concurrency:
specifier: ^4.0.6
version: 4.0.6(@babel/core@7.29.0)
- ember-data-fastboot:
- specifier: https://github.com/kategengler/ember-data-fastboot#v0.0.1
- version: https://codeload.github.com/kategengler/ember-data-fastboot/tar.gz/fd24e8b4043e3b911ef7ce0b438f6e149d7fb51c(patch_hash=d43942b2da6f05a2962db8c115fdee0f38acfaa0b61d16b183cee3282897973c)(@babel/core@7.29.0)
ember-decorators:
specifier: ^6.1.1
version: 6.1.1
@@ -232,12 +218,12 @@ importers:
express-sslify:
specifier: ^1.2.0
version: 1.2.0
- fastboot-app-server:
- specifier: ^4.1.4
- version: 4.1.4
globals:
specifier: ^15.15.0
version: 15.15.0
+ http-server:
+ specifier: ^14.1.1
+ version: 14.1.1
lint-to-the-future:
specifier: ^2.6.3
version: 2.6.4(encoding@0.1.13)
@@ -277,6 +263,9 @@ importers:
normalize.css:
specifier: ^8.0.1
version: 8.0.1
+ playwright:
+ specifier: ^1.58.2
+ version: 1.58.2
prember:
specifier: ^2.1.0
version: 2.1.0
@@ -2939,12 +2928,6 @@ packages:
array-flatten@1.1.1:
resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==}
- array-to-error@1.1.1:
- resolution: {integrity: sha512-kqcQ8s7uQfg3UViYON3kCMcck3A9exxgq+riVuKy08Mx00VN4EJhK30L2VpjE58LQHKhcE/GRpvbVUhqTvqzGQ==}
-
- array-to-sentence@1.1.0:
- resolution: {integrity: sha512-YkwkMmPA2+GSGvXj1s9NZ6cc2LBtR+uSeWTy2IGi5MR1Wag4DdrcjTxA/YV/Fw+qKlBeXomneZgThEbm/wvZbw==}
-
array-union@2.1.0:
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
engines: {node: '>=8'}
@@ -3401,9 +3384,6 @@ packages:
bluebird@3.7.2:
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
- blueimp-md5@2.19.0:
- resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
-
body-parser@1.20.2:
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -3474,13 +3454,6 @@ packages:
broccoli-caching-writer@3.1.0:
resolution: {integrity: sha512-3TWi92ogzUhLmCF5V4DjhN7v4t6OjXYO21p9GkuOZQ1SiVmM1sYio364y64dREHUzjFEcH8mdVCiRDdrwUGVTw==}
- broccoli-clean-css@1.1.0:
- resolution: {integrity: sha512-S7/RWWX+lL42aGc5+fXVLnwDdMtS0QEWUFalDp03gJ9Na7zj1rWa351N2HZ687E2crM9g+eDWXKzD17cbcTepg==}
-
- broccoli-concat@4.2.5:
- resolution: {integrity: sha512-dFB5ATPwOyV8S2I7a07HxCoutoq23oY//LhM6Mou86cWUTB174rND5aQLR7Fu8FjFFLxoTbkk7y0VPITJ1IQrw==}
- engines: {node: 10.* || >= 12.*}
-
broccoli-concat@4.2.7:
resolution: {integrity: sha512-JePfBFwHtZ2FR33PBZQA99/hQ4idIbZ205rH84Jw6vgkuKDRVXWVzZP2gvR2WXugXaQ1fj3+yO04b0QsstNHzQ==}
engines: {node: 10.* || >= 12.*}
@@ -3515,9 +3488,6 @@ packages:
broccoli-kitchen-sink-helpers@0.3.1:
resolution: {integrity: sha512-gqYnKSJxBSjj/uJqeuRAzYVbmjWhG0mOZ8jrp6+fnUIOgLN6MvI7XxBECDHkYMIFPJ8Smf4xaI066Q2FqQDnXg==}
- broccoli-merge-trees@2.0.1:
- resolution: {integrity: sha512-WjaexJ+I8BxP5V5RNn6um/qDRSmKoiBC/QkRi79FT9ClHfldxRyCDs9mcV7mmoaPlsshmmPaUz5jdtcKA6DClQ==}
-
broccoli-merge-trees@3.0.2:
resolution: {integrity: sha512-ZyPAwrOdlCddduFbsMyyFzJUrvW6b04pMvDiAQZrCwghlvgowJDY+EfoXn+eR1RRA5nmGHJ+B68T63VnpRiT1A==}
engines: {node: '>=6.0.0'}
@@ -3590,10 +3560,6 @@ packages:
resolution: {integrity: sha512-ZbGVQjivWi0k220fEeIUioN6Y68xjMy0xiLAc0LdieHI99gw+tafU8w0CggBDYVNsJMKUr006AZaM7gNEwCxEg==}
engines: {node: 8.* || 10.* || >= 12.*}
- broccoli-stew@1.6.0:
- resolution: {integrity: sha512-sUwCJNnYH4Na690By5xcEMAZqKgquUQnMAEuIiL3Z2k63mSw9Xg+7Ew4wCrFrMmXMcLpWjZDOm6Yqnq268N+ZQ==}
- engines: {node: ^4.5 || 6.* || >= 7.*}
-
broccoli-stew@3.0.0:
resolution: {integrity: sha512-NXfi+Vas24n3Ivo21GvENTI55qxKu7OwKRnCLWXld8MiLiQKQlWIq28eoARaFj0lTUFwUa4jKZeA7fW9PiWQeg==}
engines: {node: 8.* || >= 10.*}
@@ -3742,14 +3708,6 @@ packages:
clean-base-url@1.0.0:
resolution: {integrity: sha512-9q6ZvUAhbKOSRFY7A/irCQ/rF0KIpa3uXpx6izm8+fp7b2H4hLeUJ+F1YYk9+gDQ/X8Q0MEyYs+tG3cht//HTg==}
- clean-css-promise@0.1.1:
- resolution: {integrity: sha512-tzWkANXMD70ETa/wAu2TXAAxYWS0ZjVUFM2dVik8RQBoAbGMFJv4iVluz3RpcoEbo++fX4RV/BXfgGoOjp8o3Q==}
-
- clean-css@3.4.28:
- resolution: {integrity: sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw==}
- engines: {node: '>=0.10.0'}
- hasBin: true
-
clean-css@5.3.3:
resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==}
engines: {node: '>= 10.0'}
@@ -3852,10 +3810,6 @@ packages:
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
- commander@2.8.1:
- resolution: {integrity: sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ==}
- engines: {node: '>= 0.6.x'}
-
commander@4.1.1:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
@@ -4166,6 +4120,10 @@ packages:
resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==}
engines: {node: '>= 0.10'}
+ corser@2.0.1:
+ resolution: {integrity: sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==}
+ engines: {node: '>= 0.4.0'}
+
cosmiconfig@8.3.6:
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
engines: {node: '>=14'}
@@ -4617,19 +4575,9 @@ packages:
peerDependencies:
ember-source: '>= 3.28.0'
- ember-cli-fastboot@4.1.5:
- resolution: {integrity: sha512-XVigHzn+xXMqvovdrPNQHXRCzVOkU78ij6adU8Qt7PAaF3stR9oPh/35f30aJ2vcL6jwR72glnuCyXpm3EL22A==}
- engines: {node: 14.* || 16.* || >= 18}
- peerDependencies:
- ember-source: '>=3.16'
-
ember-cli-get-component-path-option@1.0.0:
resolution: {integrity: sha512-k47TDwcJ2zPideBCZE8sCiShSxQSpebY2BHcX2DdipMmBox5gsfyVrbKJWIHeSTTKyEUgmBIvQkqTOozEziCZA==}
- ember-cli-head@2.0.0:
- resolution: {integrity: sha512-i9qwljBlpzU/ei0xN+FiCHUvU1ZdjVXk0OzRKoeMZJK3m4p29CvB095klT0q+PigvYFYHIyTaeSWmbgjP8CZiw==}
- engines: {node: 12.* || >= 14}
-
ember-cli-htmlbars@5.7.2:
resolution: {integrity: sha512-Uj6R+3TtBV5RZoJY14oZn/sNPnc+UgmC8nb5rI4P3fR/gYoyTFIZSXiIM7zl++IpMoIrocxOrgt+mhonKphgGg==}
engines: {node: 10.* || >= 12.*}
@@ -4645,10 +4593,6 @@ packages:
ember-cli-is-package-missing@1.0.0:
resolution: {integrity: sha512-9hEoZj6Au5onlSDdcoBqYEPT8ehlYntZPxH8pBKV0GO7LNel88otSAQsCfXvbi2eKE+MaSeLG/gNaCI5UdWm9g==}
- ember-cli-lodash-subset@2.0.1:
- resolution: {integrity: sha512-QkLGcYv1WRK35g4MWu/uIeJ5Suk2eJXKtZ+8s+qE7C9INmpCPyPxzaqZABquYzcWNzIdw6kYwz3NWAFdKYFxwg==}
- engines: {node: ^4.5 || 6.* || >= 7.*}
-
ember-cli-normalize-entity-name@1.0.0:
resolution: {integrity: sha512-rF4P1rW2P1gVX1ynZYPmuIf7TnAFDiJmIUFI1Xz16VYykUAyiOCme0Y22LeZq8rTzwBMiwBwoE3RO4GYWehXZA==}
@@ -4659,9 +4603,6 @@ packages:
resolution: {integrity: sha512-S2HQqmNtcezmLSt/OPZKCXg+aRV7yFoZp+tn1HCLSbR/eU95xl7MWxTjbj/wOIGMfhggy/hBT2+STDh8mGuVpw==}
engines: {node: '>= 14'}
- ember-cli-preprocess-registry@3.3.0:
- resolution: {integrity: sha512-60GYpw7VPeB7TvzTLZTuLTlHdOXvayxjAQ+IxM2T04Xkfyu75O2ItbWlftQW7NZVGkaCsXSRAmn22PG03VpLMA==}
-
ember-cli-preprocess-registry@5.0.1:
resolution: {integrity: sha512-Jb2zbE5Kfe56Nf4IpdaQ10zZ72p/RyLdgE5j5/lKG3I94QHlq+7AkAd18nPpb5OUeRUT13yQTAYpU+MbjpKTtg==}
engines: {node: 16.* || >= 18}
@@ -4735,11 +4676,6 @@ packages:
'@glint/template':
optional: true
- ember-data-fastboot@https://codeload.github.com/kategengler/ember-data-fastboot/tar.gz/fd24e8b4043e3b911ef7ce0b438f6e149d7fb51c:
- resolution: {gitHosted: true, tarball: https://codeload.github.com/kategengler/ember-data-fastboot/tar.gz/fd24e8b4043e3b911ef7ce0b438f6e149d7fb51c}
- version: 0.1.2
- engines: {node: ^4.5 || 6.* || >= 7.*}
-
ember-decorators@6.1.1:
resolution: {integrity: sha512-63vZPntPn1aqMyeNRLoYjJD+8A8obd+c2iZkJflswpDRNVIsp2m7aQdSCtPt4G0U/TEq2251g+N10maHX3rnJQ==}
engines: {node: '>= 8.*'}
@@ -4762,10 +4698,6 @@ packages:
'@typescript-eslint/parser':
optional: true
- ember-in-element-polyfill@1.0.1:
- resolution: {integrity: sha512-eHs+7D7PuQr8a1DPqsJTsEyo3FZ1XuH6WEZaEBPDa9s0xLlwByCNKl8hi1EbXOgvgEZNHHi9Rh0vjxyfakrlgg==}
- engines: {node: 10.* || >= 12}
-
ember-inflector@6.0.0:
resolution: {integrity: sha512-g6trqBhQHRwlq9bBmoyxhAl0tD0/CaTKK0xWPUgi3BfxFOgGG1bbiwAx+tjyiAkLzDqU+ihyjtT+sd41y6K1hA==}
@@ -5229,21 +5161,6 @@ packages:
fast-uri@3.1.0:
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
- fastboot-app-server@4.1.4:
- resolution: {integrity: sha512-1XEP0vnZ8GPqWqo7YNMzfNRtH+x/l2OcRpPjuP/07vL8qozHxakb79DU2lcnDqOAmqz5aCYAHCXRrYF7SLCw0g==}
- engines: {node: 12.* || 14.* || >=16}
-
- fastboot-express-middleware@4.1.2:
- resolution: {integrity: sha512-vnzEBV7gZ3lSoGiqG/7+006nHNA3z+ZnU/5u9jPHtKpjH28yEbvZq6PnAeTu24UR98jZVR0pnFbfX0co+O9PeA==}
- engines: {node: 12.* || 14.* || >=16}
-
- fastboot-transform@0.1.3:
- resolution: {integrity: sha512-6otygPIJw1ARp1jJb+6KVO56iKBjhO+5x59RSC9qiZTbZRrv+HZAuP00KD3s+nWMvcFDemtdkugki9DNFTTwCQ==}
-
- fastboot@4.1.2:
- resolution: {integrity: sha512-VJLmF0xdCNwIIuA7DQtN1KTAKfEGsbZGJ0cfKh64h6DeMh3Fhr2FCCxkPh8zYqGoqzjXFdFbtk60WS3f6HKqBg==}
- engines: {node: 12.* || 14.* || >=16}
-
fastboot@4.1.5:
resolution: {integrity: sha512-2FkJWrpxgJjy5kLb3KrYp0pKdB4WgT/6qxtQO7ozYtQqMBOAARMnp59xp/Hdosa1cE2jslZgwDAv3v11OlQfAw==}
engines: {node: 12.* || 14.* || >=16}
@@ -5491,6 +5408,11 @@ packages:
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ fsevents@2.3.2:
+ resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
@@ -5534,10 +5456,6 @@ packages:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
- get-stdin@4.0.1:
- resolution: {integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==}
- engines: {node: '>=0.10.0'}
-
get-stdin@9.0.0:
resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==}
engines: {node: '>=12'}
@@ -5670,9 +5588,6 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- graceful-readlink@1.0.1:
- resolution: {integrity: sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==}
-
grapheme-splitter@1.0.4:
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
@@ -5765,6 +5680,10 @@ packages:
resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
engines: {node: '>= 0.4'}
+ he@1.2.0:
+ resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+ hasBin: true
+
heimdalljs-fs-monitor@1.1.2:
resolution: {integrity: sha512-M7OPf3Tu+ybhAXdiC07O1vUYFyhCgfew4L3vaG2nn4Be05xzNvtBcU6IKMTfHJ9AxWFa3w9rrmiJovkxHhpopw==}
@@ -5846,6 +5765,11 @@ packages:
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
+ http-server@14.1.1:
+ resolution: {integrity: sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==}
+ engines: {node: '>=12'}
+ hasBin: true
+
https-proxy-agent@5.0.1:
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
@@ -5942,10 +5866,6 @@ packages:
ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
- inline-source-map-comment@1.0.5:
- resolution: {integrity: sha512-a3/m6XgooVCXkZCduOb7pkuvUtNKt4DaqaggKKJrMQHQsqt6JcJXEreExeZiiK4vWL/cM/uF6+chH05pz2/TdQ==}
- hasBin: true
-
inquirer@6.5.2:
resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==}
engines: {node: '>=6.0.0'}
@@ -6507,10 +6427,6 @@ packages:
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
- lodash.omit@4.5.0:
- resolution: {integrity: sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==}
- deprecated: This package is deprecated. Use destructuring assignment syntax instead.
-
lodash.sortby@4.7.0:
resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
@@ -6605,10 +6521,6 @@ packages:
mathml-tag-names@2.1.3:
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
- md5-hex@3.0.1:
- resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
- engines: {node: '>=8'}
-
mdn-data@1.1.4:
resolution: {integrity: sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==}
@@ -6652,9 +6564,6 @@ packages:
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
- merge-trees@1.0.1:
- resolution: {integrity: sha512-O7TWwipLHhc9tErjq3WBvNP7I1g7Wgudl1ZkLqpT7F2MZy1yEdgnI9cpZZxBaqk+wJZu+2b9FE7D3ubUmGFHFA==}
-
merge-trees@2.0.0:
resolution: {integrity: sha512-5xBbmqYBalWqmhYm51XlohhkmVOua3VAUrrWh8t9iOkaLpS6ifqm/UVuUjQCeDVJ9Vx3g2l6ihfkbLSTeKsHbw==}
@@ -6861,9 +6770,6 @@ packages:
node-int64@0.4.0:
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
- node-modules-path@1.0.2:
- resolution: {integrity: sha512-6Gbjq+d7uhkO7epaKi5DNgUJn7H0gEyA4Jg0Mo1uQOi3Rk50G83LtmhhFyw0LxnAFhtlspkiiw52ISP13qzcBg==}
-
node-notifier@10.0.1:
resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==}
@@ -6945,9 +6851,6 @@ packages:
resolution: {integrity: sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==}
engines: {node: '>= 0.10.0'}
- object-inspect@1.13.1:
- resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
-
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -7003,6 +6906,10 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
+ opener@1.5.2:
+ resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
+ hasBin: true
+
optional-require@1.1.10:
resolution: {integrity: sha512-0r3OB9EIQsP+a5HVATHq2ExIy2q/Vaffoo4IAikW1spCYswhLxqWQS0i3GwS3AdY/OIP4SWZHLGz8CMU558PGw==}
engines: {node: '>=4'}
@@ -7235,14 +7142,6 @@ packages:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'}
- pinkie-promise@2.0.1:
- resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==}
- engines: {node: '>=0.10.0'}
-
- pinkie@2.0.4:
- resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==}
- engines: {node: '>=0.10.0'}
-
pirates@4.0.7:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
engines: {node: '>= 6'}
@@ -7270,6 +7169,16 @@ packages:
resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==}
engines: {node: '>=8'}
+ playwright-core@1.58.2:
+ resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ playwright@1.58.2:
+ resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==}
+ engines: {node: '>=18'}
+ hasBin: true
+
portfinder@1.0.32:
resolution: {integrity: sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==}
engines: {node: '>= 0.12.0'}
@@ -7502,9 +7411,6 @@ packages:
resolution: {integrity: sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==}
engines: {node: ^18.17.0 || >=20.5.0}
- process-relative-require@1.0.0:
- resolution: {integrity: sha512-r8G5WJPozMJAiv8sDdVWKgJ4In/zBXqwJdMCGAXQt2Kd3HdbAuJVzWYM4JW150hWoaI9DjhtbjcsCCHIMxm8RA==}
-
promise-map-series@0.2.3:
resolution: {integrity: sha512-wx9Chrutvqu1N/NHzTayZjE1BgIwt6SJykQoCOic4IZ9yUDjKyVYrpLa/4YCNsV61eRENfs29hrEquVuB13Zlw==}
@@ -7542,7 +7448,6 @@ packages:
engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
deprecated: |-
You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.
-
(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)
qified@0.6.0:
@@ -7614,10 +7519,6 @@ packages:
resolution: {integrity: sha512-XNvYvkfdAN9QewbrxeTOjgINkdY/odTgTS56ZNEWL9Ml0weT4T3sFtvnTuF+Gxyu46ANcRm1ntrF6F5LAJPAaQ==}
engines: {node: '>= 4'}
- recast@0.19.1:
- resolution: {integrity: sha512-8FCjrBxjeEU2O6I+2hyHyBFH1siJbMBLwIRvVr1T3FD2cL754sOaJDsJ/8h3xYltasbJ8jqWRIhMuDGBSiSbjw==}
- engines: {node: '>= 4'}
-
recast@0.23.11:
resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==}
engines: {node: '>= 4'}
@@ -7939,6 +7840,9 @@ packages:
resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==}
engines: {node: '>= 10.13.0'}
+ secure-compare@3.0.1:
+ resolution: {integrity: sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==}
+
semver-compare@1.0.0:
resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
@@ -8042,10 +7946,6 @@ packages:
resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
engines: {node: '>= 0.4'}
- side-channel@1.0.6:
- resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
- engines: {node: '>= 0.4'}
-
side-channel@1.1.0:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
@@ -8311,9 +8211,6 @@ packages:
engines: {node: '>=18.12.0'}
hasBin: true
- sum-up@1.0.3:
- resolution: {integrity: sha512-zw5P8gnhiqokJUWRdR6F4kIIIke0+ubQSGyYUY506GCbJWtV7F6Xuy0j6S125eSX2oF+a8KdivsZ8PlVEH0Mcw==}
-
supports-color@2.0.0:
resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==}
engines: {node: '>=0.8.0'}
@@ -8666,6 +8563,10 @@ packages:
resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==}
engines: {node: '>=0.10.0'}
+ union@0.5.0:
+ resolution: {integrity: sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==}
+ engines: {node: '>= 0.8.0'}
+
uniq@1.0.1:
resolution: {integrity: sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==}
@@ -8713,6 +8614,9 @@ packages:
resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
deprecated: Please see https://github.com/lydell/urix#deprecated
+ url-join@4.0.1:
+ resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==}
+
url-parse@1.5.10:
resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==}
@@ -9010,10 +8914,6 @@ packages:
xmlchars@2.2.0:
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
- xtend@4.0.2:
- resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
- engines: {node: '>=0.4'}
-
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -12705,12 +12605,6 @@ snapshots:
array-flatten@1.1.1: {}
- array-to-error@1.1.1:
- dependencies:
- array-to-sentence: 1.1.0
-
- array-to-sentence@1.1.0: {}
-
array-union@2.1.0: {}
array-unique@0.3.2: {}
@@ -13466,8 +13360,6 @@ snapshots:
bluebird@3.7.2: {}
- blueimp-md5@2.19.0: {}
-
body-parser@1.20.2:
dependencies:
bytes: 3.1.2
@@ -13643,31 +13535,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- broccoli-clean-css@1.1.0:
- dependencies:
- broccoli-persistent-filter: 1.4.6
- clean-css-promise: 0.1.1
- inline-source-map-comment: 1.0.5
- json-stable-stringify: 1.1.1
- transitivePeerDependencies:
- - supports-color
-
- broccoli-concat@4.2.5:
- dependencies:
- broccoli-debug: 0.6.5
- broccoli-kitchen-sink-helpers: 0.3.1
- broccoli-plugin: 4.0.7
- ensure-posix-path: 1.1.1
- fast-sourcemap-concat: 2.1.1
- find-index: 1.1.1
- fs-extra: 8.1.0
- fs-tree-diff: 2.0.1
- lodash.merge: 4.6.2
- lodash.omit: 4.5.0
- lodash.uniq: 4.5.0
- transitivePeerDependencies:
- - supports-color
-
broccoli-concat@4.2.7:
dependencies:
broccoli-debug: 0.6.5
@@ -13763,13 +13630,6 @@ snapshots:
glob: 5.0.15
mkdirp: 0.5.6
- broccoli-merge-trees@2.0.1:
- dependencies:
- broccoli-plugin: 1.3.1
- merge-trees: 1.0.1
- transitivePeerDependencies:
- - supports-color
-
broccoli-merge-trees@3.0.2:
dependencies:
broccoli-plugin: 1.3.1
@@ -13931,25 +13791,6 @@ snapshots:
dependencies:
broccoli-node-api: 1.7.0
- broccoli-stew@1.6.0:
- dependencies:
- broccoli-debug: 0.6.5
- broccoli-funnel: 2.0.2
- broccoli-merge-trees: 2.0.1
- broccoli-persistent-filter: 1.4.6
- broccoli-plugin: 1.3.1
- chalk: 2.4.2
- debug: 3.2.7
- ensure-posix-path: 1.1.1
- fs-extra: 5.0.0
- minimatch: 3.1.5
- resolve: 1.22.12
- rsvp: 4.8.5
- symlink-or-copy: 1.3.1
- walk-sync: 0.3.4
- transitivePeerDependencies:
- - supports-color
-
broccoli-stew@3.0.0:
dependencies:
broccoli-debug: 0.6.5
@@ -14199,17 +14040,6 @@ snapshots:
clean-base-url@1.0.0: {}
- clean-css-promise@0.1.1:
- dependencies:
- array-to-error: 1.1.1
- clean-css: 3.4.28
- pinkie-promise: 2.0.1
-
- clean-css@3.4.28:
- dependencies:
- commander: 2.8.1
- source-map: 0.4.4
-
clean-css@5.3.3:
dependencies:
source-map: 0.6.1
@@ -14294,10 +14124,6 @@ snapshots:
commander@2.20.3: {}
- commander@2.8.1:
- dependencies:
- graceful-readlink: 1.0.1
-
commander@4.1.1: {}
commander@7.2.0: {}
@@ -14401,7 +14227,8 @@ snapshots:
continuable-cache@0.3.1: {}
- convert-source-map@1.9.0: {}
+ convert-source-map@1.9.0:
+ optional: true
convert-source-map@2.0.0: {}
@@ -14452,6 +14279,8 @@ snapshots:
object-assign: 4.1.1
vary: 1.1.2
+ corser@2.0.1: {}
+
cosmiconfig@8.3.6(typescript@4.9.5):
dependencies:
import-fresh: 3.3.0
@@ -15088,43 +14917,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
- ember-cli-fastboot@4.1.5(ember-source@6.7.0(@glimmer/component@2.0.0)(rsvp@4.8.5)):
- dependencies:
- broccoli-concat: 4.2.5
- broccoli-file-creator: 2.1.1
- broccoli-funnel: 3.0.8
- broccoli-merge-trees: 4.2.0
- broccoli-plugin: 4.0.7
- chalk: 4.1.2
- ember-cli-babel: 7.26.11
- ember-cli-lodash-subset: 2.0.1
- ember-cli-preprocess-registry: 3.3.0
- ember-cli-version-checker: 5.1.2
- ember-source: 6.7.0(@glimmer/component@2.0.0)(rsvp@4.8.5)
- fastboot: 4.1.5
- fastboot-express-middleware: 4.1.2
- fastboot-transform: 0.1.3
- fs-extra: 10.1.0
- json-stable-stringify: 1.1.1
- md5-hex: 3.0.1
- recast: 0.19.1
- silent-error: 1.1.1
- transitivePeerDependencies:
- - bufferutil
- - canvas
- - supports-color
- - utf-8-validate
-
ember-cli-get-component-path-option@1.0.0: {}
- ember-cli-head@2.0.0:
- dependencies:
- ember-cli-babel: 7.26.11
- ember-cli-htmlbars: 5.7.2
- ember-in-element-polyfill: 1.0.1
- transitivePeerDependencies:
- - supports-color
-
ember-cli-htmlbars@5.7.2:
dependencies:
'@ember/edition-utils': 1.2.0
@@ -15172,8 +14966,6 @@ snapshots:
ember-cli-is-package-missing@1.0.0: {}
- ember-cli-lodash-subset@2.0.1: {}
-
ember-cli-normalize-entity-name@1.0.0:
dependencies:
silent-error: 1.1.1
@@ -15192,15 +14984,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- ember-cli-preprocess-registry@3.3.0:
- dependencies:
- broccoli-clean-css: 1.1.0
- broccoli-funnel: 2.0.2
- debug: 3.2.7
- process-relative-require: 1.0.0
- transitivePeerDependencies:
- - supports-color
-
ember-cli-preprocess-registry@5.0.1:
dependencies:
broccoli-funnel: 3.0.8
@@ -15500,13 +15283,6 @@ snapshots:
- '@babel/core'
- supports-color
- ember-data-fastboot@https://codeload.github.com/kategengler/ember-data-fastboot/tar.gz/fd24e8b4043e3b911ef7ce0b438f6e149d7fb51c(patch_hash=d43942b2da6f05a2962db8c115fdee0f38acfaa0b61d16b183cee3282897973c)(@babel/core@7.29.0):
- dependencies:
- ember-cli-babel: 8.3.1(@babel/core@7.29.0)
- transitivePeerDependencies:
- - '@babel/core'
- - supports-color
-
ember-decorators@6.1.1:
dependencies:
'@ember-decorators/component': 6.1.1
@@ -15547,15 +15323,6 @@ snapshots:
- eslint
- typescript
- ember-in-element-polyfill@1.0.1:
- dependencies:
- debug: 4.4.3(supports-color@8.1.1)
- ember-cli-babel: 7.26.11
- ember-cli-htmlbars: 5.7.2
- ember-cli-version-checker: 5.1.2
- transitivePeerDependencies:
- - supports-color
-
ember-inflector@6.0.0(@babel/core@7.29.0):
dependencies:
'@embroider/addon-shim': 1.10.2
@@ -15967,7 +15734,7 @@ snapshots:
es-define-property@1.0.0:
dependencies:
- get-intrinsic: 1.2.4
+ get-intrinsic: 1.3.0
es-define-property@1.0.1: {}
@@ -16390,52 +16157,6 @@ snapshots:
fast-uri@3.1.0: {}
- fastboot-app-server@4.1.4:
- dependencies:
- basic-auth: 2.0.1
- chalk: 4.1.2
- compression: 1.8.1
- express: 4.22.1
- fastboot: 4.1.5
- fastboot-express-middleware: 4.1.2
- transitivePeerDependencies:
- - bufferutil
- - canvas
- - supports-color
- - utf-8-validate
-
- fastboot-express-middleware@4.1.2:
- dependencies:
- chalk: 4.1.2
- fastboot: 4.1.2
- transitivePeerDependencies:
- - bufferutil
- - canvas
- - supports-color
- - utf-8-validate
-
- fastboot-transform@0.1.3:
- dependencies:
- broccoli-stew: 1.6.0
- convert-source-map: 1.9.0
- transitivePeerDependencies:
- - supports-color
-
- fastboot@4.1.2:
- dependencies:
- chalk: 4.1.2
- cookie: 0.4.2
- debug: 4.4.3(supports-color@8.1.1)
- jsdom: 19.0.0
- resolve: 1.22.12
- simple-dom: 1.4.0
- source-map-support: 0.5.21
- transitivePeerDependencies:
- - bufferutil
- - canvas
- - supports-color
- - utf-8-validate
-
fastboot@4.1.5:
dependencies:
chalk: 4.1.2
@@ -16782,6 +16503,9 @@ snapshots:
fs.realpath@1.0.0: {}
+ fsevents@2.3.2:
+ optional: true
+
function-bind@1.1.2: {}
function.prototype.name@1.1.8:
@@ -16840,8 +16564,6 @@ snapshots:
dunder-proto: 1.0.1
es-object-atoms: 1.1.2
- get-stdin@4.0.1: {}
-
get-stdin@9.0.0: {}
get-stream@4.1.0:
@@ -16994,8 +16716,6 @@ snapshots:
graceful-fs@4.2.11: {}
- graceful-readlink@1.0.1: {}
-
grapheme-splitter@1.0.4: {}
growly@1.3.0: {}
@@ -17101,6 +16821,8 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ he@1.2.0: {}
+
heimdalljs-fs-monitor@1.1.2:
dependencies:
callsites: 3.1.0
@@ -17224,6 +16946,25 @@ snapshots:
transitivePeerDependencies:
- debug
+ http-server@14.1.1:
+ dependencies:
+ basic-auth: 2.0.1
+ chalk: 4.1.2
+ corser: 2.0.1
+ he: 1.2.0
+ html-encoding-sniffer: 3.0.0
+ http-proxy: 1.18.1
+ mime: 1.6.0
+ minimist: 1.2.8
+ opener: 1.5.2
+ portfinder: 1.0.32
+ secure-compare: 3.0.1
+ union: 0.5.0
+ url-join: 4.0.1
+ transitivePeerDependencies:
+ - debug
+ - supports-color
+
https-proxy-agent@5.0.1(supports-color@8.1.1):
dependencies:
agent-base: 6.0.2(supports-color@8.1.1)
@@ -17304,14 +17045,6 @@ snapshots:
ini@1.3.8: {}
- inline-source-map-comment@1.0.5:
- dependencies:
- chalk: 1.1.3
- get-stdin: 4.0.1
- minimist: 1.2.8
- sum-up: 1.0.3
- xtend: 4.0.2
-
inquirer@6.5.2:
dependencies:
ansi-escapes: 3.2.0
@@ -17973,8 +17706,6 @@ snapshots:
lodash.merge@4.6.2: {}
- lodash.omit@4.5.0: {}
-
lodash.sortby@4.7.0: {}
lodash.truncate@4.4.2: {}
@@ -18071,10 +17802,6 @@ snapshots:
mathml-tag-names@2.1.3: {}
- md5-hex@3.0.1:
- dependencies:
- blueimp-md5: 2.19.0
-
mdn-data@1.1.4: {}
mdn-data@2.0.14: {}
@@ -18110,17 +17837,6 @@ snapshots:
merge-stream@2.0.0: {}
- merge-trees@1.0.1:
- dependencies:
- can-symlink: 1.0.0
- fs-tree-diff: 0.5.9
- heimdalljs: 0.2.6
- heimdalljs-logger: 0.1.10
- rimraf: 2.7.1
- symlink-or-copy: 1.3.1
- transitivePeerDependencies:
- - supports-color
-
merge-trees@2.0.0:
dependencies:
fs-updater: 1.0.4
@@ -18310,8 +18026,6 @@ snapshots:
node-int64@0.4.0: {}
- node-modules-path@1.0.2: {}
-
node-notifier@10.0.1:
dependencies:
growly: 1.3.0
@@ -18391,8 +18105,6 @@ snapshots:
object-hash@1.3.1: {}
- object-inspect@1.13.1: {}
-
object-inspect@1.13.4: {}
object-keys@1.1.1: {}
@@ -18455,6 +18167,8 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
+ opener@1.5.2: {}
+
optional-require@1.1.10:
dependencies:
require-at: 1.0.6
@@ -18665,12 +18379,6 @@ snapshots:
pify@4.0.1: {}
- pinkie-promise@2.0.1:
- dependencies:
- pinkie: 2.0.4
-
- pinkie@2.0.4: {}
-
pirates@4.0.7: {}
pkg-dir@3.0.0:
@@ -18695,6 +18403,14 @@ snapshots:
dependencies:
find-up: 3.0.0
+ playwright-core@1.58.2: {}
+
+ playwright@1.58.2:
+ dependencies:
+ playwright-core: 1.58.2
+ optionalDependencies:
+ fsevents: 2.3.2
+
portfinder@1.0.32:
dependencies:
async: 2.6.4
@@ -18996,10 +18712,6 @@ snapshots:
proc-log@5.0.0: {}
- process-relative-require@1.0.0:
- dependencies:
- node-modules-path: 1.0.2
-
promise-map-series@0.2.3:
dependencies:
rsvp: 3.6.2
@@ -19038,7 +18750,7 @@ snapshots:
qs@6.11.0:
dependencies:
- side-channel: 1.0.6
+ side-channel: 1.1.0
qs@6.14.2:
dependencies:
@@ -19121,13 +18833,6 @@ snapshots:
private: 0.1.8
source-map: 0.6.1
- recast@0.19.1:
- dependencies:
- ast-types: 0.13.3
- esprima: 4.0.1
- private: 0.1.8
- source-map: 0.6.1
-
recast@0.23.11:
dependencies:
ast-types: 0.16.1
@@ -19480,6 +19185,8 @@ snapshots:
ajv-formats: 2.1.1(ajv@8.18.0)
ajv-keywords: 5.1.0(ajv@8.18.0)
+ secure-compare@3.0.1: {}
+
semver-compare@1.0.0: {}
semver@5.7.2: {}
@@ -19549,7 +19256,7 @@ snapshots:
define-data-property: 1.1.4
es-errors: 1.3.0
function-bind: 1.1.2
- get-intrinsic: 1.2.4
+ get-intrinsic: 1.3.0
gopd: 1.2.0
has-property-descriptors: 1.0.2
@@ -19625,13 +19332,6 @@ snapshots:
object-inspect: 1.13.4
side-channel-map: 1.0.1
- side-channel@1.0.6:
- dependencies:
- call-bind: 1.0.9
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- object-inspect: 1.13.1
-
side-channel@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -19993,10 +19693,6 @@ snapshots:
- supports-color
- typescript
- sum-up@1.0.3:
- dependencies:
- chalk: 1.1.3
-
supports-color@2.0.0: {}
supports-color@5.5.0:
@@ -20461,6 +20157,10 @@ snapshots:
is-extendable: 0.1.1
set-value: 2.0.1
+ union@0.5.0:
+ dependencies:
+ qs: 6.14.2
+
uniq@1.0.1: {}
unique-string@2.0.0:
@@ -20502,6 +20202,8 @@ snapshots:
urix@0.1.0: {}
+ url-join@4.0.1: {}
+
url-parse@1.5.10:
dependencies:
querystringify: 2.2.0
@@ -20684,7 +20386,7 @@ snapshots:
whatwg-url@8.7.0:
dependencies:
- lodash: 4.17.21
+ lodash: 4.17.23
tr46: 2.1.0
webidl-conversions: 6.1.0
@@ -20809,8 +20511,6 @@ snapshots:
xmlchars@2.2.0: {}
- xtend@4.0.2: {}
-
y18n@5.0.8: {}
yallist@3.1.1: {}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
deleted file mode 100644
index 3ca0d27be..000000000
--- a/pnpm-workspace.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-patchedDependencies:
- ember-data-fastboot@0.1.2: patches/ember-data-fastboot@0.1.2.patch
diff --git a/prember-urls.js b/prember-urls.js
index f2690dd63..58b56c1ad 100644
--- a/prember-urls.js
+++ b/prember-urls.js
@@ -15,11 +15,18 @@ const singularData = {
module.exports = function () {
const projects = readdirSync('ember-api-docs-data/json-docs');
- const urls = [];
+ const urlsByVersion = new Map();
+
+ const addUrlToVersion = (versionKey, url) => {
+ if (!urlsByVersion.has(versionKey)) {
+ urlsByVersion.set(versionKey, []);
+ }
+ urlsByVersion.get(versionKey).push(url);
+ };
projects.forEach((p) => {
// add release index for each of the projects
- urls.push(`/${p}/release`);
+ addUrlToVersion(`${p}/release`, `/${p}/release`);
const fullProjectVersions = readdirSync(
`ember-api-docs-data/json-docs/${p}`,
@@ -44,9 +51,9 @@ module.exports = function () {
const addUrl = (p, uniqVersion, suffix) => {
// If it's the latest release version, also create release URLs
if (projectVersions[projectVersions.length - 1] === uniqVersion) {
- urls.push(`/${p}/release/${suffix}`);
+ addUrlToVersion(`${p}/release`, `/${p}/release/${suffix}`);
}
- urls.push(`/${p}/${uniqVersion}/${suffix}`);
+ addUrlToVersion(`${p}/${uniqVersion}`, `/${p}/${uniqVersion}/${suffix}`);
};
const oldVersions = ['1.13', '2.18', '3.28', '4.12', '5.12'];
@@ -68,7 +75,7 @@ module.exports = function () {
return;
}
- urls.push(`/${p}/${uniqVersion}`);
+ addUrlToVersion(`${p}/${uniqVersion}`, `/${p}/${uniqVersion}`);
const sortedPatchVersions = fullProjectVersions
.filter((projectVersion) => {
@@ -144,7 +151,7 @@ module.exports = function () {
});
});
- return urls;
+ return urlsByVersion;
};
// this is useful to debug why a url isn't being prembered
diff --git a/prerender.js b/prerender.js
new file mode 100644
index 000000000..ba9085df6
--- /dev/null
+++ b/prerender.js
@@ -0,0 +1,140 @@
+const { chromium } = require('playwright');
+const { mkdirSync, writeFileSync } = require('fs');
+const { dirname, join } = require('path');
+const getPremberUrls = require('./prember-urls');
+
+const BASE_URL = 'http://127.0.0.1:8080';
+const PRERENDER_DIR = 'prerender';
+
+async function prerenderPage(page, url) {
+ try {
+ // Use router transition
+ await page.evaluate((path) => {
+ window.__router?.transitionTo(path);
+ }, url);
+
+ await page.waitForFunction(() => {
+ return (
+ window.__router &&
+ !window.__router.currentRouteName?.includes('loading')
+ );
+ });
+
+ // Check if we got a 404 by looking for common error indicators
+ const is404 = await page.evaluate(() => {
+ return document.title.includes('Page Not Found');
+ });
+
+ if (is404) {
+ return { url, status: 'not-found' };
+ }
+
+ // Get the HTML content
+ const html = await page.content();
+
+ // Convert URL to file path
+ // e.g., /ember/release/classes/ApplicationInstance -> prerender/ember/release/classes/ApplicationInstance/index.html
+ const filePath = join(PRERENDER_DIR, url, 'index.html');
+ const dir = dirname(filePath);
+
+ // Create directory structure
+ mkdirSync(dir, { recursive: true });
+
+ // Write HTML file
+ writeFileSync(filePath, html, 'utf-8');
+
+ return { url, status: 'success' };
+ } catch (error) {
+ return { url, status: 'error', error: error.message };
+ }
+}
+
+async function initializePage(browser) {
+ const page = await browser.newPage();
+
+ await page.addInitScript(() => {
+ window.__isPrerendering = true;
+ });
+
+ // First navigation: full page load
+ await page.goto(BASE_URL, { waitUntil: 'networkidle' });
+
+ await page.waitForFunction(() => {
+ const app = window.__emberApiDocs;
+ if (!app) return false;
+ // Check that the router is in a stable state (no active transitions)
+ const router = app.lookup('service:router');
+ window.__router = router;
+ return router && !router.currentRouteName?.includes('loading');
+ });
+
+ return page;
+}
+
+async function prerenderVersion(urls) {
+ const browser = await chromium.launch();
+ const CONCURRENCY = 5; // Number of parallel pages
+
+ // Initialize multiple pages
+ const pages = await Promise.all(
+ Array.from({ length: CONCURRENCY }, () => initializePage(browser)),
+ );
+
+ let successCount = 0;
+ let notFoundCount = 0;
+ let errorCount = 0;
+ let urlIndex = 0;
+
+ // Process URLs in parallel using a worker pool pattern
+ const workers = pages.map(async (page) => {
+ while (urlIndex < urls.length) {
+ const currentIndex = urlIndex++;
+ const url = urls[currentIndex];
+
+ const result = await prerenderPage(page, url);
+
+ if (result.status === 'success') {
+ successCount++;
+ } else if (result.status === 'not-found') {
+ console.log(`Not Found: ${url}`);
+ notFoundCount++;
+ } else {
+ console.error(`Error processing ${url}:`, result.error);
+ errorCount++;
+ }
+
+ if ((currentIndex + 1) % 100 === 0) {
+ console.log(
+ `Progress: ${currentIndex + 1}/${urls.length} (${successCount} saved, ${notFoundCount} not found, ${errorCount} errors)`,
+ );
+ }
+ }
+ });
+
+ await Promise.all(workers);
+ await browser.close();
+}
+async function prerender() {
+ const urlsByVersion = getPremberUrls();
+ const totalUrls = Array.from(urlsByVersion.values()).reduce(
+ (sum, urls) => sum + urls.length,
+ 0,
+ );
+
+ console.log(
+ `Prerendering ${totalUrls} URLs across ${urlsByVersion.size} versions...`,
+ );
+
+ for (const [, urls] of urlsByVersion.entries()) {
+ await prerenderVersion(urls);
+ }
+
+ console.log('\nPrerendering complete!');
+ console.log(`Total URLs: ${totalUrls}`);
+}
+
+prerender().catch((error) => {
+ console.error('Prerendering failed:', error);
+ // eslint-disable-next-line n/no-process-exit
+ process.exit(1);
+});