refactor: 💡 remove usage of ember/runloop & ember-pollster (#2705)

* refactor: 💡 remove usage of ember/runloop & ember-pollster

---------

Co-authored-by: Zhihe Li <zhihe.li@hashicorp.com>
This commit is contained in:
Lisbet AlvarezandZhihe Li authored and GitHub committed 2025-03-06 12:20:48 -08:00
1 parent e29a83ec25
commit 29bde998ed
23 files changed
+225 -197

No files matched your search

@@ -6,7 +6,6 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { run } from '@ember/runloop';
export default class FormAuthenticateDetailsComponent extends Component {
// =properties
@@ -36,7 +35,7 @@ export default class FormAuthenticateDetailsComponent extends Component {
*/
@action
submit(fn, creds) {
run(() => this.resetPassword());
run(() => fn(creds));
this.resetPassword();
fn(creds);
}
}
@@ -6,7 +6,7 @@
<Hds::Button
@text={{t 'actions.refresh'}}
@color='secondary'
@icon={{if this.isLoading 'loading' 'reload'}}
@icon={{if this.toggleRefresh.isRunning 'loading' 'reload'}}
@disabled={{this.isLoading}}
{{on 'click' this.toggleRefresh}}
{{on 'click' this.toggleRefresh.perform}}
/>
@@ -4,22 +4,13 @@
*/
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { later } from '@ember/runloop';
import { dropTask, timeout } from 'ember-concurrency';
export default class LoadingButton extends Component {
// =actions
@tracked isLoading = false;
// =attributes
@action
async toggleRefresh() {
this.isLoading = true;
try {
await this.args.onClick();
} catch (e) {
console.error('Error while loading data', e);
}
later(() => (this.isLoading = false), 1000);
}
toggleRefresh = dropTask(async () => {
await this.args.onClick();
await timeout(1000);
});
}
+2 -2
View File
@@ -19,10 +19,10 @@ export default class extends Helper {
// Parse the expiration time
const expirationTime = new Date(expiration_time);
// Get the curent time
// Get the current time
const currentTime = this.clockTick.now;
// Calculate the difference in milleseconds
// Calculate the difference in milliseconds
const difference = expirationTime - currentTime;
// Calculate the difference in seconds if the difference is positive
+11 -30
View File
@@ -6,7 +6,7 @@
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { getOwner } from '@ember/application';
import { next } from '@ember/runloop';
import { task, timeout } from 'ember-concurrency';
export default class ClockTickService extends Service {
// =attributes
@@ -25,9 +25,15 @@ export default class ClockTickService extends Service {
frequency = 1000;
/**
* The timer interval ID
* Updates the value of `now` every `frequency` milliseconds.
*/
#timer;
_tick = task(async () => {
// eslint-disable-next-line no-constant-condition
while (true) {
await timeout(this.frequency);
this.now = Date.now();
}
});
/**
* This service is enabled only in non-test environments.
@@ -45,7 +51,7 @@ export default class ClockTickService extends Service {
*/
constructor() {
super(...arguments);
if (this.enabled) this._start();
if (this.enabled) this._tick.perform();
}
/**
@@ -53,31 +59,6 @@ export default class ClockTickService extends Service {
*/
willDestroy() {
super.willDestroy(...arguments);
this._stop();
}
/**
* Sets up the timer interval, calling `_tick()` every
* `frequency` milliseconds.
*/
_start() {
const self = this;
this.#timer = setInterval(function () {
self._tick();
}, this.frequency);
}
/**
* Clears the timer interval.
*/
_stop() {
clearInterval(this.#timer);
}
/**
* Updates the value of `now` within the next runloop.
*/
_tick() {
next(() => (this.now = Date.now()));
this._tick.cancelAll();
}
}
+5
View File
@@ -14,6 +14,11 @@ module.exports = function (defaults) {
'ember-simple-auth': {
useSessionSetupMethod: true,
},
babel: {
plugins: [
require.resolve('ember-concurrency/async-arrow-task-transform'),
],
},
});
/*
+8
View File
@@ -10,6 +10,14 @@ var path = require('path');
module.exports = {
name: require('./package').name,
options: {
babel: {
plugins: [
require.resolve('ember-concurrency/async-arrow-task-transform'),
],
},
},
included(app) {
this._super.included.apply(this, arguments);
this.includePublic(app);
+1
View File
@@ -39,6 +39,7 @@
"ember-cli-babel": "^8.2.0",
"ember-cli-htmlbars": "^6.2.0",
"ember-cli-sass": "^11.0.1",
"ember-concurrency": "^4.0.3",
"ember-feature-flags": "^6.0.0",
"ember-intl": "^7.0.7",
"ember-loading": "^2.0.0",
@@ -5,9 +5,7 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { computed } from '@ember/object';
import { action } from '@ember/object';
import { run } from '@ember/runloop';
export default class FormAccountPasswordChangePasswordIndexComponent extends Component {
// =properties
@@ -25,7 +23,6 @@ export default class FormAccountPasswordChangePasswordIndexComponent extends Com
/**
* @type {boolean}
*/
@computed('currentPassword', 'newPassword')
get canSave() {
return this.currentPassword && this.newPassword;
}
@@ -33,7 +30,6 @@ export default class FormAccountPasswordChangePasswordIndexComponent extends Com
/**
* @type {boolean}
*/
@computed('canSave')
get cannotSave() {
return !this.canSave;
}
@@ -41,7 +37,7 @@ export default class FormAccountPasswordChangePasswordIndexComponent extends Com
// =methods
/**
* Unsets the password fields.
* Un-sets the password fields.
*/
resetPasswords() {
this.currentPassword = null;
@@ -52,15 +48,15 @@ export default class FormAccountPasswordChangePasswordIndexComponent extends Com
/**
* Call passed submit function with passwords.
* Unset passwords before callack.
* Unset passwords before callback.
* @param {function} fn
* @param {string} currentPassword
* @param {string} newPassword
*/
@action
submit(fn, currentPassword, newPassword) {
run(() => this.resetPasswords());
run(() => fn(currentPassword, newPassword));
this.resetPasswords();
fn(currentPassword, newPassword);
}
/**
@@ -6,7 +6,6 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { next } from '@ember/runloop';
export default class FormAccountPasswordIndexComponent extends Component {
// =properties
@@ -36,7 +35,7 @@ export default class FormAccountPasswordIndexComponent extends Component {
@action
submit(fn) {
const password = this.password;
next(() => this.resetPassword());
this.resetPassword();
return this.args.model.isNew ? fn(password) : fn();
}
}
@@ -5,9 +5,7 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { computed } from '@ember/object';
import { action } from '@ember/object';
import { run } from '@ember/runloop';
export default class FormAccountPasswordSetPasswordIndexComponent extends Component {
// =properties
@@ -21,7 +19,6 @@ export default class FormAccountPasswordSetPasswordIndexComponent extends Compon
/**
* @type {boolean}
*/
@computed('password')
get cannotSave() {
return !this.password;
}
@@ -45,7 +42,7 @@ export default class FormAccountPasswordSetPasswordIndexComponent extends Compon
*/
@action
submit(fn, password) {
run(() => this.resetPassword());
run(() => fn(password));
this.resetPassword();
fn(password);
}
}
@@ -7,7 +7,7 @@ import Route from '@ember/routing/route';
import { getOwner } from '@ember/application';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import runEvery from 'ember-pollster/decorators/route/run-every';
import { task, timeout } from 'ember-concurrency';
import { notifyError } from 'core/decorators/notify';
import config from '../../../../../config/environment';
@@ -20,6 +20,15 @@ export default class ScopesScopeAuthenticateMethodOidcRoute extends Route {
@service windowManager;
@service router;
// =attributes
poller = task(async () => {
while (!this.session.isAuthenticated) {
await timeout(POLL_TIMEOUT_SECONDS * 1000);
this.refresh();
}
});
// =methods
beforeModel;
@@ -43,9 +52,11 @@ export default class ScopesScopeAuthenticateMethodOidcRoute extends Route {
controller.authMethod = authMethod;
}
@runEvery(POLL_TIMEOUT_SECONDS * 1000)
poller() {
this.refresh();
/**
* When this route is activated (entered), start polling for authentication.
*/
activate() {
this.poller.perform();
}
/**
@@ -53,6 +64,7 @@ export default class ScopesScopeAuthenticateMethodOidcRoute extends Route {
* any windows opened via the window manager service.
*/
deactivate() {
this.poller.cancelAll();
this.windowManager.closeAll();
}
+2 -1
View File
@@ -52,7 +52,6 @@ module.exports = function (environment) {
appName: APP_NAME,
companyName: 'HashiCorp',
sessionPollingTimeoutSeconds: 300,
oidcPollingTimeoutSeconds: 1,
documentation: {
@@ -195,6 +194,8 @@ module.exports = function (environment) {
// Notification timeout should be 0 for fast tests
ENV.flashMessageDefaults.timeout = 0;
// OIDC Authentication timeout should be 0 for fast tests
ENV.oidcPollingTimeoutSeconds = 0;
ENV.enableConfirmService = false;
}
+4 -1
View File
@@ -18,6 +18,9 @@ module.exports = function (defaults) {
},
babel: {
sourceMaps: 'inline',
plugins: [
require.resolve('ember-concurrency/async-arrow-task-transform'),
],
},
sourcemaps: {
enabled: true,
@@ -34,7 +37,7 @@ module.exports = function (defaults) {
},
},
// TODO: Update to 4.12 when deprecations are resolved
// as multiple things break when forcing compatability on > 4.6
// as multiple things break when forcing compatibility on > 4.6
emberData: {
compatWith: '4.6',
},
+1 -1
View File
@@ -71,12 +71,12 @@
"ember-cli-sass": "^11.0.1",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
"ember-concurrency": "^4.0.3",
"ember-exam": "^8.0.0",
"ember-inline-svg": "^1.0.1",
"ember-load-initializers": "^2.1.2",
"ember-modifier": "^4.1.0",
"ember-page-title": "^7.0.0",
"ember-pollster": "https://github.com/hashicorp/ember-pollster.git#605d82e986d829b098667e4a5e221877a4ee4ac8",
"ember-qunit": "^8.1.0",
"ember-resolver": "^10.0.0",
"ember-source": "~4.12.0",
@@ -16,7 +16,6 @@ import { setupApplicationTest } from 'admin/tests/helpers';
import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import { setupIndexedDb } from 'api/test-support/helpers/indexed-db';
import { Response } from 'miragejs';
import { runAllJobs } from 'ember-pollster/test-support';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import {
currentSession,
@@ -86,7 +85,7 @@ module('Acceptance | authentication', function (hooks) {
},
'withChildren',
);
// create an emtpy org with no auth methods
// create an empty org with no auth methods
this.server.create(
'scope',
{
@@ -391,9 +390,6 @@ module('Acceptance | authentication', function (hooks) {
);
await visit(authMethodOIDCAuthenticateURL);
await click('form [type="submit"]');
// explicitly poll multiple times to trigger mock OIDC auth
await runAllJobs();
await runAllJobs();
});
// TODO: test OIDC retry and cancel
@@ -63,6 +63,8 @@ export default class SettingsCardClientAgentComponent extends Component {
} else {
await this.ipc.invoke('resumeClientAgent');
}
await this.router.refresh('scopes.scope.projects.settings');
// Refresh projects page in order to stop or start
// polling when client agent status changes.
await this.router.refresh('scopes.scope.projects');
}
}
@@ -7,7 +7,7 @@ import Route from '@ember/routing/route';
import { getOwner } from '@ember/application';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import runEvery from 'ember-pollster/decorators/route/run-every';
import { task, timeout } from 'ember-concurrency';
import { notifyError } from 'core/decorators/notify';
import config from '../../../../../config/environment';
@@ -19,6 +19,15 @@ export default class ScopesScopeAuthenticateMethodOidcRoute extends Route {
@service session;
@service router;
// =attributes
poller = task(async () => {
while (!this.session.isAuthenticated) {
await timeout(POLL_TIMEOUT_SECONDS * 1000);
this.refresh();
}
});
// =methods
model() {
@@ -41,9 +50,19 @@ export default class ScopesScopeAuthenticateMethodOidcRoute extends Route {
controller.authMethod = authMethod;
}
@runEvery(POLL_TIMEOUT_SECONDS * 1000)
poller() {
this.refresh();
/**
* When this route is activated (entered), start polling for authentication.
*/
activate() {
this.poller.perform();
}
/**
* When this route is deactivated (exited), stop polling for changes and close
* any windows opened via the window manager service.
*/
deactivate() {
this.poller.cancelAll();
}
/**
+77 -77
View File
@@ -5,7 +5,10 @@
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { restartableTask, timeout } from 'ember-concurrency';
import config from '../../../config/environment';
const POLL_TIMEOUT_SECONDS = config.sessionPollingTimeoutSeconds;
const { __electronLog } = globalThis;
/**
@@ -23,10 +26,6 @@ const { __electronLog } = globalThis;
* It no longer makes sense as a dedicated route.
*/
export default class ScopesScopeProjectsRoute extends Route {
// =attributes
job;
// =services
@service session;
@@ -36,7 +35,6 @@ export default class ScopesScopeProjectsRoute extends Route {
@service intl;
@service ipc;
@service clientAgentSessions;
@service pollster;
@service flashMessages;
// =methods
@@ -53,17 +51,13 @@ export default class ScopesScopeProjectsRoute extends Route {
* @return {Promise<ScopeModel>}
*/
async model() {
// Setup the poller job
if (!this.job) {
this.boundPoller = this.poller.bind(this);
this.job = this.pollster.findOrCreateJob(this.boundPoller, 2000);
}
const isClientAgentRunning = await this.ipc.invoke('isClientAgentRunning');
if (isClientAgentRunning) {
this.job.start();
this.poller.perform();
// start polling task
} else {
this.job.stop();
this.poller.cancelAll();
// cancel polling job
}
const { id: scope_id } = this.modelFor('scopes.scope');
@@ -75,42 +69,48 @@ export default class ScopesScopeProjectsRoute extends Route {
return projects;
}
willDestroy() {
this.job?.stop();
super.willDestroy();
/**
* Cancel poller task instances when exiting this route.
*/
deactivate() {
this.poller.cancelAll();
}
/**
* Poll for new sessions with credentials. Sends a notification for each new session that has a credential.
*/
async poller() {
poller = restartableTask(async () => {
let sessions;
try {
sessions = await this.clientAgentSessions.getNewSessionsWithCredentials();
} catch (e) {
// If we're unauthenticated, try and re-authenticate
if (e.statusCode === 401 || e.statusCode === 403) {
const sessionData = this.session.data?.authenticated;
const auth_token_id = sessionData?.id;
const token = sessionData?.token;
// We use a while loop to poll for new sessions from the client agent.
// eslint-disable-next-line no-constant-condition
while (true) {
try {
sessions =
await this.clientAgentSessions.getNewSessionsWithCredentials();
} catch (e) {
// If we're unauthenticated, try and re-authenticate
if (e.statusCode === 401 || e.statusCode === 403) {
const sessionData = this.session.data?.authenticated;
const auth_token_id = sessionData?.id;
const token = sessionData?.token;
try {
await this.ipc.invoke('addTokenToDaemons', {
tokenId: auth_token_id,
token,
});
this.job.start();
__electronLog?.info('Starting polling of new sessions again');
return;
} catch (e) {
__electronLog?.error('Failed to add token to daemons', e.message);
// If it fails again, just let the poller be killed
try {
await this.ipc.invoke('addTokenToDaemons', {
tokenId: auth_token_id,
token,
});
__electronLog?.info('Starting polling of new sessions again');
this.poller.perform();
return;
} catch (e) {
__electronLog?.error('Failed to add token to daemons', e.message);
// If it fails again, just let the poller be killed
}
}
}
__electronLog?.error('Failed to get new Sessions', e.message);
if (this.job) {
__electronLog?.error('Failed to get new Sessions', e.message);
this.flashMessages.danger(
this.intl.t('errors.client-agent-failed.sessions'),
{
@@ -120,46 +120,46 @@ export default class ScopesScopeProjectsRoute extends Route {
},
);
// Kill the poller if we get an error
this.job.stop();
__electronLog?.info('Stopping polling of new sessions');
return;
}
return;
sessions.forEach((session) => {
new window.Notification(
this.intl.t('notifications.connected-to-target.title', {
target: session.alias,
}),
{
body: this.intl.t('notifications.connected-to-target.description'),
// This only has an effect on windows
requireInteraction: true,
},
).onclick = async () => {
let orgScope = 'global';
try {
const aliases = await this.store.query('alias', {
scope_id: 'global',
force_refresh: true,
});
const alias = aliases.find(
(alias) => alias.value === session.alias,
);
const target = await this.store.findRecord(
'target',
alias.destination_id,
);
orgScope = target.scope.parent_scope_id;
} catch (e) {
// Do nothing and default scope to global if an error occurs
}
window.location.href = `serve://boundary/#/scopes/${orgScope}/projects/sessions/${session.session_authorization.session_id}`;
await this.ipc.invoke('focusWindow');
};
});
await timeout(POLL_TIMEOUT_SECONDS * 1000);
}
sessions.forEach((session) => {
new window.Notification(
this.intl.t('notifications.connected-to-target.title', {
target: session.alias,
}),
{
body: this.intl.t('notifications.connected-to-target.description'),
// This only has an effect on windows
requireInteraction: true,
},
).onclick = async () => {
let orgScope = 'global';
try {
const aliases = await this.store.query('alias', {
scope_id: 'global',
force_refresh: true,
});
const alias = aliases.find((alias) => alias.value === session.alias);
const target = await this.store.findRecord(
'target',
alias.destination_id,
);
orgScope = target.scope.parent_scope_id;
} catch (e) {
// Do nothing and default scope to global if an error occurs
}
window.location.href = `serve://boundary/#/scopes/${orgScope}/projects/sessions/${session.session_authorization.session_id}`;
await this.ipc.invoke('focusWindow');
};
});
}
});
}
+5 -1
View File
@@ -43,8 +43,8 @@ module.exports = function (environment) {
appName: APP_NAME,
sessionPollingTimeoutSeconds: 300,
oidcPollingTimeoutSeconds: 1,
sessionPollingTimeoutSeconds: 2,
documentation: {
baseURL: 'https://developer.hashicorp.com/boundary',
@@ -94,6 +94,10 @@ module.exports = function (environment) {
// Notification timeout should be 0 for fast tests
ENV.flashMessageDefaults.timeout = 0;
// OIDC Authentication timeout should be 0 for fast tests
ENV.oidcPollingTimeoutSeconds = 0;
// Sessions polling timeout should be 0 for fast tests
ENV.sessionPollingTimeoutSeconds = 0;
ENV.enableConfirmService = false;
+3
View File
@@ -18,6 +18,9 @@ module.exports = function (defaults) {
},
babel: {
sourceMaps: 'inline',
plugins: [
require.resolve('ember-concurrency/async-arrow-task-transform'),
],
},
sourcemaps: {
enabled: true,
+1 -1
View File
@@ -76,13 +76,13 @@
"ember-cli-sass": "^11.0.1",
"ember-cli-sri": "^2.1.1",
"ember-cli-terser": "^4.0.2",
"ember-concurrency": "^4.0.3",
"ember-electron": "^4.2.2",
"ember-exam": "^8.0.0",
"ember-inline-svg": "^1.0.1",
"ember-load-initializers": "^2.1.2",
"ember-modifier": "^4.1.0",
"ember-page-title": "^7.0.0",
"ember-pollster": "https://github.com/hashicorp/ember-pollster.git#605d82e986d829b098667e4a5e221877a4ee4ac8",
"ember-qunit": "^8.1.0",
"ember-resolver": "^10.0.0",
"ember-source": "~4.12.0",
+45 -34
View File
@@ -812,6 +812,16 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-module-imports@npm:7.25.9"
dependencies:
"@babel/traverse": "npm:^7.25.9"
"@babel/types": "npm:^7.25.9"
checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70
languageName: node
linkType: hard
"@babel/helper-module-imports@npm:^7.22.5":
version: 7.22.5
resolution: "@babel/helper-module-imports@npm:7.22.5"
@@ -831,16 +841,6 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-module-imports@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/helper-module-imports@npm:7.25.9"
dependencies:
"@babel/traverse": "npm:^7.25.9"
"@babel/types": "npm:^7.25.9"
checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70
languageName: node
linkType: hard
"@babel/helper-module-transforms@npm:^7.14.5":
version: 7.15.0
resolution: "@babel/helper-module-transforms@npm:7.15.0"
@@ -4409,6 +4409,16 @@ __metadata:
languageName: node
linkType: hard
"@babel/types@npm:^7.12.13, @babel/types@npm:^7.8.3":
version: 7.26.9
resolution: "@babel/types@npm:7.26.9"
dependencies:
"@babel/helper-string-parser": "npm:^7.25.9"
"@babel/helper-validator-identifier": "npm:^7.25.9"
checksum: 10c0/999c56269ba00e5c57aa711fbe7ff071cd6990bafd1b978341ea7572cc78919986e2aa6ee51dacf4b6a7a6fa63ba4eb3f1a03cf55eee31b896a56d068b895964
languageName: node
linkType: hard
"@babel/types@npm:^7.14.5, @babel/types@npm:^7.14.8, @babel/types@npm:^7.15.0, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.2":
version: 7.15.0
resolution: "@babel/types@npm:7.15.0"
@@ -4472,16 +4482,6 @@ __metadata:
languageName: node
linkType: hard
"@babel/types@npm:^7.8.3":
version: 7.26.9
resolution: "@babel/types@npm:7.26.9"
dependencies:
"@babel/helper-string-parser": "npm:^7.25.9"
"@babel/helper-validator-identifier": "npm:^7.25.9"
checksum: 10c0/999c56269ba00e5c57aa711fbe7ff071cd6990bafd1b978341ea7572cc78919986e2aa6ee51dacf4b6a7a6fa63ba4eb3f1a03cf55eee31b896a56d068b895964
languageName: node
linkType: hard
"@bcoe/v8-coverage@npm:^0.2.3":
version: 0.2.3
resolution: "@bcoe/v8-coverage@npm:0.2.3"
@@ -7187,13 +7187,13 @@ __metadata:
ember-cli-sass: "npm:^11.0.1"
ember-cli-sri: "npm:^2.1.1"
ember-cli-terser: "npm:^4.0.2"
ember-concurrency: "npm:^4.0.3"
ember-exam: "npm:^8.0.0"
ember-inline-svg: "npm:^1.0.1"
ember-load-initializers: "npm:^2.1.2"
ember-modifier: "npm:^4.1.0"
ember-named-blocks-polyfill: "npm:^0.2.5"
ember-page-title: "npm:^7.0.0"
ember-pollster: "https://github.com/hashicorp/ember-pollster.git#605d82e986d829b098667e4a5e221877a4ee4ac8"
ember-qunit: "npm:^8.1.0"
ember-resolver: "npm:^10.0.0"
ember-source: "npm:~4.12.0"
@@ -10090,6 +10090,7 @@ __metadata:
ember-cli-sass: "npm:^11.0.1"
ember-cli-sri: "npm:^2.1.1"
ember-cli-terser: "npm:^4.0.2"
ember-concurrency: "npm:^4.0.3"
ember-feature-flags: "npm:^6.0.0"
ember-inline-svg: "npm:^1.0.1"
ember-intl: "npm:^7.0.7"
@@ -10488,7 +10489,7 @@ __metadata:
languageName: node
linkType: hard
"decorator-transforms@npm:^1.1.0":
"decorator-transforms@npm:^1.0.1, decorator-transforms@npm:^1.1.0":
version: 1.2.1
resolution: "decorator-transforms@npm:1.2.1"
dependencies:
@@ -10649,6 +10650,7 @@ __metadata:
ember-cli-sass: "npm:^11.0.1"
ember-cli-sri: "npm:^2.1.1"
ember-cli-terser: "npm:^4.0.2"
ember-concurrency: "npm:^4.0.3"
ember-electron: "npm:^4.2.2"
ember-exam: "npm:^8.0.0"
ember-inline-svg: "npm:^1.0.1"
@@ -10656,7 +10658,6 @@ __metadata:
ember-modifier: "npm:^4.1.0"
ember-named-blocks-polyfill: "npm:^0.2.5"
ember-page-title: "npm:^7.0.0"
ember-pollster: "https://github.com/hashicorp/ember-pollster.git#605d82e986d829b098667e4a5e221877a4ee4ac8"
ember-qunit: "npm:^8.1.0"
ember-resolver: "npm:^10.0.0"
ember-source: "npm:~4.12.0"
@@ -11167,7 +11168,7 @@ __metadata:
languageName: node
linkType: hard
"ember-cli-babel@npm:^7.10.0, ember-cli-babel@npm:^7.11.1, ember-cli-babel@npm:^7.13.0, ember-cli-babel@npm:^7.19.0, ember-cli-babel@npm:^7.21.0, ember-cli-babel@npm:^7.22.1, ember-cli-babel@npm:^7.23.0, ember-cli-babel@npm:^7.26.11, ember-cli-babel@npm:^7.26.3, ember-cli-babel@npm:^7.26.5, ember-cli-babel@npm:^7.26.6, ember-cli-babel@npm:^7.26.8, ember-cli-babel@npm:^7.7.3":
"ember-cli-babel@npm:^7.10.0, ember-cli-babel@npm:^7.11.1, ember-cli-babel@npm:^7.13.0, ember-cli-babel@npm:^7.19.0, ember-cli-babel@npm:^7.21.0, ember-cli-babel@npm:^7.22.1, ember-cli-babel@npm:^7.23.0, ember-cli-babel@npm:^7.26.11, ember-cli-babel@npm:^7.26.3, ember-cli-babel@npm:^7.26.5, ember-cli-babel@npm:^7.26.6, ember-cli-babel@npm:^7.7.3":
version: 7.26.11
resolution: "ember-cli-babel@npm:7.26.11"
dependencies:
@@ -11933,6 +11934,26 @@ __metadata:
languageName: node
linkType: hard
"ember-concurrency@npm:^4.0.3":
version: 4.0.3
resolution: "ember-concurrency@npm:4.0.3"
dependencies:
"@babel/helper-module-imports": "npm:^7.22.15"
"@babel/helper-plugin-utils": "npm:^7.12.13"
"@babel/types": "npm:^7.12.13"
"@embroider/addon-shim": "npm:^1.8.7"
decorator-transforms: "npm:^1.0.1"
peerDependencies:
"@glimmer/tracking": ^1.1.2
"@glint/template": ">= 1.0.0"
ember-source: ^3.28.0 || ^4.0.0 || >=5.0.0
peerDependenciesMeta:
"@glint/template":
optional: true
checksum: 10c0/01fd3b6b3358f185ee8df7667803044d9a0c13f5e8500c2c8c8b478632a070e03fd7372a2e557ec5fcd605bb34b1f2edea9d3e0968a222a1b1c2d0bce9a9bff3
languageName: node
linkType: hard
"ember-cookies@npm:^1.0.0, ember-cookies@npm:^1.2.0":
version: 1.2.0
resolution: "ember-cookies@npm:1.2.0"
@@ -12304,16 +12325,6 @@ __metadata:
languageName: node
linkType: hard
"ember-pollster@https://github.com/hashicorp/ember-pollster.git#605d82e986d829b098667e4a5e221877a4ee4ac8":
version: 0.0.1-beta.2
resolution: "ember-pollster@https://github.com/hashicorp/ember-pollster.git#commit=605d82e986d829b098667e4a5e221877a4ee4ac8"
dependencies:
ember-cli-babel: "npm:^7.26.8"
ember-cli-htmlbars: "npm:^6.0.1"
checksum: 10c0/0e1b6e8b9ef466d864d01e63a5c58b9ccd81ea5d1e71402a5bd74d010f52a40bd9d257c2c9adf3ccd7f383327e8ffaa1b4ec73980afb6ddd4b1e18676ab099c4
languageName: node
linkType: hard
"ember-power-select@npm:^8.2.0":
version: 8.2.0
resolution: "ember-power-select@npm:8.2.0"