@fleetbase/ember-core 0.2.12 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -8,8 +8,11 @@ import { A, isArray } from '@ember/array';
|
|
|
8
8
|
import { later } from '@ember/runloop';
|
|
9
9
|
import { dasherize, camelize } from '@ember/string';
|
|
10
10
|
import { getOwner } from '@ember/application';
|
|
11
|
-
import { assert } from '@ember/debug';
|
|
11
|
+
import { assert, debug } from '@ember/debug';
|
|
12
12
|
import RSVP from 'rsvp';
|
|
13
|
+
import loadInstalledExtensions from '../utils/load-installed-extensions';
|
|
14
|
+
import loadExtensions from '../utils/load-extensions';
|
|
15
|
+
import getWithDefault from '../utils/get-with-default';
|
|
13
16
|
|
|
14
17
|
export default class UniverseService extends Service.extend(Evented) {
|
|
15
18
|
@service router;
|
|
@@ -1269,6 +1272,155 @@ export default class UniverseService extends Service.extend(Evented) {
|
|
|
1269
1272
|
return null;
|
|
1270
1273
|
}
|
|
1271
1274
|
|
|
1275
|
+
/**
|
|
1276
|
+
* Boot all installed engines, ensuring dependencies are resolved.
|
|
1277
|
+
*
|
|
1278
|
+
* This method attempts to boot all installed engines by first checking if all
|
|
1279
|
+
* their dependencies are already booted. If an engine has dependencies that
|
|
1280
|
+
* are not yet booted, it is deferred and retried after its dependencies are
|
|
1281
|
+
* booted. If some dependencies are never booted, an error is logged.
|
|
1282
|
+
*
|
|
1283
|
+
* @method bootEngines
|
|
1284
|
+
* @param {ApplicationInstance|null} owner - The Ember ApplicationInstance that owns the engines.
|
|
1285
|
+
* @return {void}
|
|
1286
|
+
*/
|
|
1287
|
+
bootEngines(owner = null) {
|
|
1288
|
+
const booted = [];
|
|
1289
|
+
const pending = [];
|
|
1290
|
+
|
|
1291
|
+
// If no owner provided use the owner of this service
|
|
1292
|
+
if (owner === null) {
|
|
1293
|
+
owner = getOwner(this);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
const tryBootEngine = (extension) => {
|
|
1297
|
+
this.loadEngine(extension.name).then((engineInstance) => {
|
|
1298
|
+
if (engineInstance.base && engineInstance.base.setupExtension) {
|
|
1299
|
+
const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
|
|
1300
|
+
|
|
1301
|
+
// Check if all dependency engines are booted
|
|
1302
|
+
const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
|
|
1303
|
+
|
|
1304
|
+
if (!allDependenciesBooted) {
|
|
1305
|
+
pending.push({ extension, engineInstance });
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
engineInstance.base.setupExtension(owner, engineInstance, this);
|
|
1310
|
+
booted.push(extension.name);
|
|
1311
|
+
debug(`Booted : ${extension.name}`);
|
|
1312
|
+
|
|
1313
|
+
// Try booting pending engines again
|
|
1314
|
+
tryBootPendingEngines();
|
|
1315
|
+
}
|
|
1316
|
+
});
|
|
1317
|
+
};
|
|
1318
|
+
|
|
1319
|
+
const tryBootPendingEngines = () => {
|
|
1320
|
+
const stillPending = [];
|
|
1321
|
+
|
|
1322
|
+
pending.forEach(({ extension, engineInstance }) => {
|
|
1323
|
+
const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
|
|
1324
|
+
const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
|
|
1325
|
+
|
|
1326
|
+
if (allDependenciesBooted) {
|
|
1327
|
+
engineInstance.base.setupExtension(owner, engineInstance, this);
|
|
1328
|
+
booted.push(extension.name);
|
|
1329
|
+
debug(`Booted : ${extension.name}`);
|
|
1330
|
+
} else {
|
|
1331
|
+
stillPending.push({ extension, engineInstance });
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
// If no progress was made, log an error in debug/development mode
|
|
1336
|
+
assert('Some engines have unmet dependencies and cannot be booted:', pending.length === stillPending.length);
|
|
1337
|
+
|
|
1338
|
+
pending.length = 0;
|
|
1339
|
+
pending.push(...stillPending);
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1342
|
+
loadInstalledExtensions().then((extensions) => {
|
|
1343
|
+
extensions.forEach((extension) => {
|
|
1344
|
+
tryBootEngine(extension);
|
|
1345
|
+
});
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
/**
|
|
1350
|
+
* Boots all installed engines, ensuring dependencies are resolved.
|
|
1351
|
+
*
|
|
1352
|
+
* This method loads all installed extensions and then attempts to boot each engine.
|
|
1353
|
+
* For each extension, it loads the engine and, if the engine has a `setupExtension`
|
|
1354
|
+
* method in its base, it calls this method to complete the setup. This function ensures
|
|
1355
|
+
* that dependencies are resolved before booting the engines. If some dependencies are
|
|
1356
|
+
* never booted, an error is logged.
|
|
1357
|
+
*
|
|
1358
|
+
* @method legacyBootEngines
|
|
1359
|
+
* @param {ApplicationInstance|null} owner - The Ember ApplicationInstance that owns the engines.
|
|
1360
|
+
* @return {void}
|
|
1361
|
+
*/
|
|
1362
|
+
legacyBootEngines(owner = null) {
|
|
1363
|
+
const booted = [];
|
|
1364
|
+
const pending = [];
|
|
1365
|
+
|
|
1366
|
+
// If no owner provided use the owner of this service
|
|
1367
|
+
if (owner === null) {
|
|
1368
|
+
owner = getOwner(this);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
const tryBootEngine = (extension) => {
|
|
1372
|
+
this.loadEngine(extension.name).then((engineInstance) => {
|
|
1373
|
+
if (engineInstance.base && engineInstance.base.setupExtension) {
|
|
1374
|
+
const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
|
|
1375
|
+
|
|
1376
|
+
// Check if all dependency engines are booted
|
|
1377
|
+
const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
|
|
1378
|
+
|
|
1379
|
+
if (!allDependenciesBooted) {
|
|
1380
|
+
pending.push({ extension, engineInstance });
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
engineInstance.base.setupExtension(owner, engineInstance, this);
|
|
1385
|
+
booted.push(extension.name);
|
|
1386
|
+
debug(`Booted : ${extension.name}`);
|
|
1387
|
+
|
|
1388
|
+
// Try booting pending engines again
|
|
1389
|
+
tryBootPendingEngines();
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
const tryBootPendingEngines = () => {
|
|
1395
|
+
const stillPending = [];
|
|
1396
|
+
|
|
1397
|
+
pending.forEach(({ extension, engineInstance }) => {
|
|
1398
|
+
const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
|
|
1399
|
+
const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
|
|
1400
|
+
|
|
1401
|
+
if (allDependenciesBooted) {
|
|
1402
|
+
engineInstance.base.setupExtension(owner, engineInstance, this);
|
|
1403
|
+
booted.push(extension.name);
|
|
1404
|
+
debug(`Booted : ${extension.name}`);
|
|
1405
|
+
} else {
|
|
1406
|
+
stillPending.push({ extension, engineInstance });
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1409
|
+
|
|
1410
|
+
// If no progress was made, log an error in debug/development mode
|
|
1411
|
+
assert('Some engines have unmet dependencies and cannot be booted:', pending.length === stillPending.length);
|
|
1412
|
+
|
|
1413
|
+
pending.length = 0;
|
|
1414
|
+
pending.push(...stillPending);
|
|
1415
|
+
};
|
|
1416
|
+
|
|
1417
|
+
loadExtensions().then((extensions) => {
|
|
1418
|
+
extensions.forEach((extension) => {
|
|
1419
|
+
tryBootEngine(extension);
|
|
1420
|
+
});
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1272
1424
|
/**
|
|
1273
1425
|
* Alias for intl service `t`
|
|
1274
1426
|
*
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import config from 'ember-get-config';
|
|
2
|
+
|
|
3
|
+
export default async function fleetbaseApiFetch(method, uri, params = {}, fetchOptions = {}) {
|
|
4
|
+
// Prepare base URL
|
|
5
|
+
const baseUrl = `${config.API.host}/${fetchOptions.namespace ?? config.API.namespace}`;
|
|
6
|
+
|
|
7
|
+
// Initialize headers
|
|
8
|
+
const headers = {
|
|
9
|
+
'Content-Type': 'application/json',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// Check localStorage for the session data
|
|
13
|
+
const localStorageSession = JSON.parse(window.localStorage.getItem('ember_simple_auth-session'));
|
|
14
|
+
let token;
|
|
15
|
+
if (localStorageSession) {
|
|
16
|
+
const { authenticated } = localStorageSession;
|
|
17
|
+
if (authenticated) {
|
|
18
|
+
token = authenticated.token;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Set Authorization header if token is available
|
|
23
|
+
if (token) {
|
|
24
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Configure request options
|
|
28
|
+
const options = {
|
|
29
|
+
method,
|
|
30
|
+
headers,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Handle params based on method
|
|
34
|
+
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method) && params) {
|
|
35
|
+
options.body = JSON.stringify(params);
|
|
36
|
+
} else if (method === 'GET' && params) {
|
|
37
|
+
// Add params to URL for GET requests
|
|
38
|
+
const urlParams = new URLSearchParams(params).toString();
|
|
39
|
+
uri += `?${urlParams}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// Make the fetch request
|
|
44
|
+
const response = await fetch(`${baseUrl}/${uri}`, options);
|
|
45
|
+
|
|
46
|
+
// Check if the response is OK (status in the range 200-299)
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Parse and return the JSON response
|
|
52
|
+
return await response.json();
|
|
53
|
+
} catch (error) {
|
|
54
|
+
// If a fallback response is provided use it instead
|
|
55
|
+
if (fetchOptions && fetchOptions.fallbackResponse !== undefined) {
|
|
56
|
+
return fetchOptions.fallbackResponse;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Handle errors (network errors, JSON parsing errors, etc.)
|
|
60
|
+
console.error('Error making request:', error);
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import loadExtensions from '../utils/load-extensions';
|
|
2
|
+
import fleetbaseApiFetch from '../utils/fleetbase-api-fetch';
|
|
3
|
+
|
|
4
|
+
export default async function loadInstalledExtensions() {
|
|
5
|
+
const CORE_ENGINES = ['@fleetbase/fleetops-engine', '@fleetbase/storefront-engine', '@fleetbase/registry-bridge-engine', '@fleetbase/dev-engine', '@fleetbase/iam-engine'];
|
|
6
|
+
const INDEXED_ENGINES = await loadExtensions();
|
|
7
|
+
const INSTALLED_ENGINES = await fleetbaseApiFetch('get', 'engines', {}, { namespace: '~registry/v1', fallbackResponse: [] });
|
|
8
|
+
|
|
9
|
+
const isInstalledEngine = (engineName) => {
|
|
10
|
+
return CORE_ENGINES.includes(engineName) || INSTALLED_ENGINES.find((pkg) => pkg.name === engineName);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return INDEXED_ENGINES.filter((pkg) => {
|
|
14
|
+
return isInstalledEngine(pkg.name);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/fleetbase-api-fetch';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/ember-core/utils/load-installed-extensions';
|
package/package.json
CHANGED