@fleetbase/ember-core 0.2.12 → 0.2.14

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.
@@ -0,0 +1,25 @@
1
+ import { decoratorWithRequiredParams } from '@ember-decorators/utils/decorator';
2
+ import { computed } from '@ember/object';
3
+ import { assert } from '@ember/debug';
4
+ import injectEngineService from '../utils/inject-engine-service';
5
+ import isObject from '../utils/is-object';
6
+
7
+ export default decoratorWithRequiredParams(function (target, key, descriptor, [engineName, options = {}]) {
8
+ assert('The first argument of the @engineService decorator must be a string', typeof engineName === 'string');
9
+ assert('The second argument of the @engineService decorator must be an object', isObject(options));
10
+
11
+ const { initializer } = descriptor;
12
+ delete descriptor.initializer;
13
+
14
+ const cp = computed(`_engineService_${key}`, function () {
15
+ const service = injectEngineService(this, engineName, key, options);
16
+
17
+ if (initializer) {
18
+ return initializer.call(this);
19
+ }
20
+
21
+ return service;
22
+ });
23
+
24
+ return cp(target, key, descriptor);
25
+ });
@@ -1,55 +1,52 @@
1
1
  import { decoratorWithRequiredParams } from '@ember-decorators/utils/decorator';
2
- import { assert } from '@ember/debug';
3
2
  import { getOwner } from '@ember/application';
4
- import { scheduleOnce } from '@ember/runloop';
3
+ import { assert } from '@ember/debug';
5
4
 
6
- export default function fetchFrom(endpoint, query = {}, options = {}) {
5
+ export default decoratorWithRequiredParams(function (target, key, descriptor, [endpoint, query = {}, options = {}]) {
7
6
  assert('The first argument of the @fetchFrom decorator must be a string', typeof endpoint === 'string');
8
7
  assert('The second argument of the @fetchFrom decorator must be an object', typeof query === 'object');
9
8
  assert('The third argument of the @fetchFrom decorator must be an object', typeof options === 'object');
10
9
 
11
- return decoratorWithRequiredParams(function (target, key) {
12
- const symbol = Symbol(`__${key}_fetchFrom`);
10
+ // Remove value and writable if previously set, use getter instead
11
+ delete descriptor.value;
12
+ delete descriptor.writable;
13
+ delete descriptor.initializer;
14
+
15
+ // Create symbol to track value
16
+ const symbol = Symbol(`__${key}_fetchFrom`);
17
+
18
+ // Setter to get symbol value
19
+ descriptor.set = function (value) {
20
+ this[symbol] = value;
21
+ };
22
+
23
+ // Get or set symbol value
24
+ descriptor.get = async function () {
25
+ if (this[symbol] !== undefined) {
26
+ return this[symbol];
27
+ }
13
28
 
14
- Object.defineProperty(target, symbol, {
29
+ Object.defineProperty(this, symbol, {
15
30
  configurable: true,
16
31
  enumerable: false,
17
32
  writable: true,
18
33
  value: null,
19
34
  });
20
35
 
21
- Object.defineProperty(target, key, {
22
- configurable: true,
23
- enumerable: true,
24
- get() {
25
- return this[symbol];
26
- },
27
- set(value) {
28
- this[symbol] = value;
29
- },
30
- });
31
-
32
- const originalInit = target.init;
33
-
34
- target.init = function () {
35
- if (originalInit) {
36
- originalInit.call(this);
37
- }
38
-
39
- scheduleOnce('afterRender', this, function () {
40
- const owner = getOwner(this);
41
- const fetch = owner.lookup('service:fetch'); // Get the Fleetbase Fetch service
42
-
43
- // Perform the query and set the result to the property
44
- fetch
45
- .get(endpoint, query, options)
46
- .then((result) => {
47
- this.set(key, result);
48
- })
49
- .catch(() => {
50
- this.set(key, []);
51
- });
36
+ const owner = getOwner(this);
37
+ const fetch = owner.lookup('service:fetch');
38
+ return fetch
39
+ .get(endpoint, query, options)
40
+ .then((response) => {
41
+ this.set(key, response);
42
+ if (options && typeof options.onComplete === 'function') {
43
+ options.onComplete(response, this);
44
+ }
45
+ })
46
+ .catch(() => {
47
+ this.set(key, null);
52
48
  });
53
- };
54
- }, 'fetchFrom')(endpoint, query, options);
55
- }
49
+ };
50
+
51
+ return descriptor;
52
+ });
@@ -1,55 +1,52 @@
1
1
  import { decoratorWithRequiredParams } from '@ember-decorators/utils/decorator';
2
- import { assert } from '@ember/debug';
3
2
  import { getOwner } from '@ember/application';
4
- import { scheduleOnce } from '@ember/runloop';
3
+ import { assert } from '@ember/debug';
4
+
5
+ export default decoratorWithRequiredParams(function (target, key, descriptor, [modelName, query = {}, options = {}]) {
6
+ assert('The first argument of the @fetchFrom decorator must be a string', typeof modelName === 'string');
7
+ assert('The second argument of the @fetchFrom decorator must be an object', typeof query === 'object');
8
+ assert('The third argument of the @fetchFrom decorator must be an object', typeof options === 'object');
9
+
10
+ // Remove value and writable if previously set, use getter instead
11
+ delete descriptor.value;
12
+ delete descriptor.writable;
13
+ delete descriptor.initializer;
14
+
15
+ // Create symbol to track value
16
+ const symbol = Symbol(`__${key}_fromStore`);
5
17
 
6
- export default function fromStore(modelName, query = {}, options = {}) {
7
- assert('The first argument of the @fromStore decorator must be a string', typeof modelName === 'string');
8
- assert('The second argument of the @fromStore decorator must be an object', typeof query === 'object');
9
- assert('The third argument of the @fromStore decorator must be an object', typeof options === 'object');
18
+ // Setter to get symbol value
19
+ descriptor.set = function (value) {
20
+ this[symbol] = value;
21
+ };
10
22
 
11
- return decoratorWithRequiredParams(function (target, key) {
12
- const symbol = Symbol(`__${key}_fromStore`);
23
+ // Get or set symbol value
24
+ descriptor.get = function () {
25
+ if (this[symbol] !== undefined) {
26
+ return this[symbol];
27
+ }
13
28
 
14
- Object.defineProperty(target, symbol, {
29
+ Object.defineProperty(this, symbol, {
15
30
  configurable: true,
16
31
  enumerable: false,
17
32
  writable: true,
18
33
  value: null,
19
34
  });
20
35
 
21
- Object.defineProperty(target, key, {
22
- configurable: true,
23
- enumerable: true,
24
- get() {
25
- return this[symbol];
26
- },
27
- set(value) {
28
- this[symbol] = value;
29
- },
30
- });
31
-
32
- const originalInit = target.init;
33
-
34
- target.init = function () {
35
- if (originalInit) {
36
- originalInit.call(this);
37
- }
38
-
39
- scheduleOnce('afterRender', this, function () {
40
- const owner = getOwner(this);
41
- const store = owner.lookup('service:store'); // Get the Ember Data store
42
-
43
- // Perform the query and set the result to the property
44
- store
45
- .query(modelName, query, options)
46
- .then((result) => {
47
- this.set(key, result);
48
- })
49
- .catch(() => {
50
- this.set(key, []);
51
- });
36
+ const owner = getOwner(this);
37
+ const store = owner.lookup('service:store');
38
+ return store
39
+ .query(modelName, query, options)
40
+ .then((response) => {
41
+ this.set(key, response);
42
+ if (options && typeof options.onComplete === 'function') {
43
+ options.onComplete(response, this);
44
+ }
45
+ })
46
+ .catch(() => {
47
+ this.set(key, null);
52
48
  });
53
- };
54
- }, 'fromStore')(modelName, query, options);
55
- }
49
+ };
50
+
51
+ return descriptor;
52
+ });
@@ -8,8 +8,12 @@ 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';
16
+ import config from 'ember-get-config';
13
17
 
14
18
  export default class UniverseService extends Service.extend(Evented) {
15
19
  @service router;
@@ -1055,29 +1059,88 @@ export default class UniverseService extends Service.extend(Evented) {
1055
1059
  }
1056
1060
 
1057
1061
  /**
1058
- * Manually registers a component in a specified engine.
1062
+ * Registers a component class under one or more names within a specified engine instance.
1063
+ * This function provides flexibility in component registration by supporting registration under the component's
1064
+ * full class name, a simplified alias derived from the class name, and an optional custom name provided through the options.
1065
+ * This flexibility facilitates varied referencing styles within different parts of the application, enhancing modularity and reuse.
1059
1066
  *
1060
- * @method registerComponentInEngine
1061
- * @public
1062
- * @memberof UniverseService
1063
- * @param {String} engineName - The name of the engine where the component should be registered.
1064
- * @param {Object} componentClass - The component class to register, which should have a 'name' property.
1067
+ * @param {string} engineName - The name of the engine where the component will be registered.
1068
+ * @param {class} componentClass - The component class to be registered. Must be a class, not an instance.
1069
+ * @param {Object} [options] - Optional parameters for additional configuration.
1070
+ * @param {string} [options.registerAs] - A custom name under which the component can also be registered.
1071
+ *
1072
+ * @example
1073
+ * // Register a component with its default and alias names
1074
+ * registerComponentInEngine('mainEngine', HeaderComponent);
1075
+ *
1076
+ * // Additionally register the component under a custom name
1077
+ * registerComponentInEngine('mainEngine', HeaderComponent, { registerAs: 'header' });
1078
+ *
1079
+ * @remarks
1080
+ * - The function does not return any value.
1081
+ * - Registration only occurs if:
1082
+ * - The specified engine instance exists.
1083
+ * - The component class is properly defined with a non-empty name.
1084
+ * - The custom name, if provided, must be a valid string.
1085
+ * - Allows flexible component referencing by registering under multiple names.
1065
1086
  */
1066
- registerComponentInEngine(engineName, componentClass) {
1087
+ registerComponentInEngine(engineName, componentClass, options = {}) {
1067
1088
  const engineInstance = this.getEngineInstance(engineName);
1068
- if (engineInstance && !isBlank(componentClass) && typeof componentClass.name === 'string') {
1089
+ this.registerComponentToEngineInstance(engineInstance, componentClass, options);
1090
+ }
1091
+
1092
+ /**
1093
+ * Registers a component class under its full class name, a simplified alias, and an optional custom name within a specific engine instance.
1094
+ * This helper function does the actual registration of the component to the engine instance. It registers the component under its
1095
+ * full class name, a dasherized alias of the class name (with 'Component' suffix removed if present), and any custom name provided via options.
1096
+ *
1097
+ * @param {EngineInstance} engineInstance - The engine instance where the component will be registered.
1098
+ * @param {class} componentClass - The component class to be registered. This should be a class reference, not an instance.
1099
+ * @param {Object} [options] - Optional parameters for further configuration.
1100
+ * @param {string} [options.registerAs] - A custom name under which the component can be registered.
1101
+ *
1102
+ * @example
1103
+ * // Typical usage within the system (not usually called directly by users)
1104
+ * registerComponentToEngineInstance(engineInstance, HeaderComponent, { registerAs: 'header' });
1105
+ *
1106
+ * @remarks
1107
+ * - No return value.
1108
+ * - The registration is performed only if:
1109
+ * - The engine instance is valid and not null.
1110
+ * - The component class has a defined and non-empty name.
1111
+ * - The custom name, if provided, is a valid string.
1112
+ * - This function directly manipulates the engine instance's registration map.
1113
+ */
1114
+ registerComponentToEngineInstance(engineInstance, componentClass, options = {}) {
1115
+ if (engineInstance && componentClass && typeof componentClass.name === 'string') {
1069
1116
  engineInstance.register(`component:${componentClass.name}`, componentClass);
1117
+ engineInstance.register(`component:${dasherize(componentClass.name.replace('Component', ''))}`, componentClass);
1118
+ if (options && typeof options.registerAs === 'string') {
1119
+ engineInstance.register(`component:${options.registerAs}`, componentClass);
1120
+ }
1070
1121
  }
1071
1122
  }
1072
1123
 
1073
1124
  /**
1074
- * Manually registers a service in a specified engine.
1125
+ * Registers a service from one engine instance to another within the application.
1126
+ * This method retrieves an instance of a service from the current engine and then registers it
1127
+ * in a target engine, allowing the service to be shared across different parts of the application.
1075
1128
  *
1076
- * @method registerComponentInEngine
1077
- * @public
1078
- * @memberof UniverseService
1079
- * @param {String} engineName - The name of the engine where the component should be registered.
1080
- * @param {Object} serviceClass - The service class to register, which should have a 'name' property.
1129
+ * @param {string} targetEngineName - The name of the engine where the service should be registered.
1130
+ * @param {string} serviceName - The name of the service to be shared and registered.
1131
+ * @param {Object} currentEngineInstance - The engine instance that currently holds the service to be shared.
1132
+ *
1133
+ * @example
1134
+ * // Assuming 'appEngine' and 'componentEngine' are existing engine instances and 'logger' is a service in 'appEngine'
1135
+ * registerServiceInEngine('componentEngine', 'logger', appEngine);
1136
+ *
1137
+ * Note:
1138
+ * - This function does not return any value.
1139
+ * - It only performs registration if all provided parameters are valid:
1140
+ * - Both engine instances must exist.
1141
+ * - The service name must be a string.
1142
+ * - The service must exist in the current engine instance.
1143
+ * - The service is registered without instantiating a new copy in the target engine.
1081
1144
  */
1082
1145
  registerServiceInEngine(targetEngineName, serviceName, currentEngineInstance) {
1083
1146
  // Get the target engine instance
@@ -1108,11 +1171,16 @@ export default class UniverseService extends Service.extend(Evented) {
1108
1171
  * userService.doSomething();
1109
1172
  * }
1110
1173
  */
1111
- getServiceFromEngine(engineName, serviceName) {
1174
+ getServiceFromEngine(engineName, serviceName, options = {}) {
1112
1175
  const engineInstance = this.getEngineInstance(engineName);
1113
1176
 
1114
1177
  if (engineInstance && typeof serviceName === 'string') {
1115
1178
  const serviceInstance = engineInstance.lookup(`service:${serviceName}`);
1179
+ if (options && options.inject) {
1180
+ for (let injectionName in options.inject) {
1181
+ serviceInstance[injectionName] = options.inject[injectionName];
1182
+ }
1183
+ }
1116
1184
  return serviceInstance;
1117
1185
  }
1118
1186
 
@@ -1269,6 +1337,162 @@ export default class UniverseService extends Service.extend(Evented) {
1269
1337
  return null;
1270
1338
  }
1271
1339
 
1340
+ /**
1341
+ * Boot all installed engines, ensuring dependencies are resolved.
1342
+ *
1343
+ * This method attempts to boot all installed engines by first checking if all
1344
+ * their dependencies are already booted. If an engine has dependencies that
1345
+ * are not yet booted, it is deferred and retried after its dependencies are
1346
+ * booted. If some dependencies are never booted, an error is logged.
1347
+ *
1348
+ * @method bootEngines
1349
+ * @param {ApplicationInstance|null} owner - The Ember ApplicationInstance that owns the engines.
1350
+ * @return {void}
1351
+ */
1352
+ bootEngines(owner = null) {
1353
+ const booted = [];
1354
+ const pending = [];
1355
+ const additionalCoreExtensions = config.APP.extensions ?? [];
1356
+
1357
+ // If no owner provided use the owner of this service
1358
+ if (owner === null) {
1359
+ owner = getOwner(this);
1360
+ }
1361
+
1362
+ const tryBootEngine = (extension) => {
1363
+ this.loadEngine(extension.name).then((engineInstance) => {
1364
+ if (engineInstance.base && engineInstance.base.setupExtension) {
1365
+ if (booted.includes(extension.name)) {
1366
+ return;
1367
+ }
1368
+
1369
+ const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
1370
+ const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
1371
+
1372
+ if (!allDependenciesBooted) {
1373
+ pending.push({ extension, engineInstance });
1374
+ return;
1375
+ }
1376
+
1377
+ engineInstance.base.setupExtension(owner, engineInstance, this);
1378
+ booted.push(extension.name);
1379
+ debug(`Booted : ${extension.name}`);
1380
+
1381
+ // Try booting pending engines again
1382
+ tryBootPendingEngines();
1383
+ }
1384
+ });
1385
+ };
1386
+
1387
+ const tryBootPendingEngines = () => {
1388
+ const stillPending = [];
1389
+
1390
+ pending.forEach(({ extension, engineInstance }) => {
1391
+ if (booted.includes(extension.name)) {
1392
+ return;
1393
+ }
1394
+
1395
+ const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
1396
+ const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
1397
+
1398
+ if (allDependenciesBooted) {
1399
+ engineInstance.base.setupExtension(owner, engineInstance, this);
1400
+ booted.push(extension.name);
1401
+ debug(`Booted : ${extension.name}`);
1402
+ } else {
1403
+ stillPending.push({ extension, engineInstance });
1404
+ }
1405
+ });
1406
+
1407
+ // If no progress was made, log an error in debug/development mode
1408
+ assert(`Some engines have unmet dependencies and cannot be booted:`, stillPending.length === 0 && pending.length === 0);
1409
+
1410
+ pending.length = 0;
1411
+ pending.push(...stillPending);
1412
+ };
1413
+
1414
+ loadInstalledExtensions(additionalCoreExtensions).then((extensions) => {
1415
+ extensions.forEach((extension) => {
1416
+ tryBootEngine(extension);
1417
+ });
1418
+ });
1419
+ }
1420
+
1421
+ /**
1422
+ * Boots all installed engines, ensuring dependencies are resolved.
1423
+ *
1424
+ * This method loads all installed extensions and then attempts to boot each engine.
1425
+ * For each extension, it loads the engine and, if the engine has a `setupExtension`
1426
+ * method in its base, it calls this method to complete the setup. This function ensures
1427
+ * that dependencies are resolved before booting the engines. If some dependencies are
1428
+ * never booted, an error is logged.
1429
+ *
1430
+ * @method legacyBootEngines
1431
+ * @param {ApplicationInstance|null} owner - The Ember ApplicationInstance that owns the engines.
1432
+ * @return {void}
1433
+ */
1434
+ legacyBootEngines(owner = null) {
1435
+ const booted = [];
1436
+ const pending = [];
1437
+
1438
+ // If no owner provided use the owner of this service
1439
+ if (owner === null) {
1440
+ owner = getOwner(this);
1441
+ }
1442
+
1443
+ const tryBootEngine = (extension) => {
1444
+ this.loadEngine(extension.name).then((engineInstance) => {
1445
+ if (engineInstance.base && engineInstance.base.setupExtension) {
1446
+ const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
1447
+
1448
+ // Check if all dependency engines are booted
1449
+ const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
1450
+
1451
+ if (!allDependenciesBooted) {
1452
+ pending.push({ extension, engineInstance });
1453
+ return;
1454
+ }
1455
+
1456
+ engineInstance.base.setupExtension(owner, engineInstance, this);
1457
+ booted.push(extension.name);
1458
+ debug(`Booted : ${extension.name}`);
1459
+
1460
+ // Try booting pending engines again
1461
+ tryBootPendingEngines();
1462
+ }
1463
+ });
1464
+ };
1465
+
1466
+ const tryBootPendingEngines = () => {
1467
+ const stillPending = [];
1468
+
1469
+ pending.forEach(({ extension, engineInstance }) => {
1470
+ const engineDependencies = getWithDefault(engineInstance.base, 'engineDependencies', []);
1471
+ const allDependenciesBooted = engineDependencies.every((dep) => booted.includes(dep));
1472
+
1473
+ if (allDependenciesBooted) {
1474
+ engineInstance.base.setupExtension(owner, engineInstance, this);
1475
+ booted.push(extension.name);
1476
+ debug(`Booted : ${extension.name}`);
1477
+ } else {
1478
+ stillPending.push({ extension, engineInstance });
1479
+ }
1480
+ });
1481
+
1482
+ // If no progress was made, log an error in debug/development mode
1483
+ assert('Some engines have unmet dependencies and cannot be booted:', pending.length === stillPending.length);
1484
+
1485
+ pending.length = 0;
1486
+ pending.push(...stillPending);
1487
+ };
1488
+
1489
+ loadExtensions().then((extensions) => {
1490
+ extensions.forEach((extension) => {
1491
+ tryBootEngine(extension);
1492
+ });
1493
+ });
1494
+ }
1495
+
1272
1496
  /**
1273
1497
  * Alias for intl service `t`
1274
1498
  *
@@ -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
+ }
@@ -1,10 +1,49 @@
1
1
  import { getOwner } from '@ember/application';
2
+ import { isArray } from '@ember/array';
3
+ import isObject from './is-object';
2
4
 
3
- export default function injectEngineService(target, engineName, serviceName, key = null) {
5
+ function findService(owner, target, serviceName) {
6
+ let service = target[serviceName];
7
+ if (!service) {
8
+ service = owner.lookup(`service:${serviceName}`);
9
+ }
10
+
11
+ return service;
12
+ }
13
+
14
+ function injectServices(service, target, owner, injections) {
15
+ if (isArray(injections)) {
16
+ for (let i = 0; i < injections.length; i++) {
17
+ const serviceName = injections[i];
18
+ service[serviceName] = findService(owner, target, serviceName);
19
+ }
20
+ } else if (isObject(injections)) {
21
+ for (let serviceName in injections) {
22
+ service[serviceName] = injections[serviceName] ?? findService(owner, target, serviceName);
23
+ }
24
+ }
25
+ }
26
+
27
+ // unresolved services value will be the key as a string
28
+ function automaticServiceResolution(service, target, owner) {
29
+ for (let prop in service) {
30
+ if (typeof prop === 'string' && typeof service[prop] === 'string' && prop === service[prop]) {
31
+ service[prop] = findService(owner, target, prop);
32
+ }
33
+ }
34
+ }
35
+
36
+ export default function injectEngineService(target, engineName, serviceName, options = {}) {
4
37
  const owner = getOwner(target);
5
38
  const universe = owner.lookup('service:universe');
6
39
  const service = universe.getServiceFromEngine(engineName, serviceName);
40
+ const key = options.key || null;
7
41
  const effectiveServiceName = key || serviceName;
42
+ if (options && options.inject) {
43
+ injectServices(service, target, owner, options.inject);
44
+ } else {
45
+ automaticServiceResolution(service, target, owner);
46
+ }
8
47
 
9
48
  Object.defineProperty(target, effectiveServiceName, {
10
49
  value: service,
@@ -12,4 +51,6 @@ export default function injectEngineService(target, engineName, serviceName, key
12
51
  configurable: true,
13
52
  enumerable: true,
14
53
  });
54
+
55
+ return service;
15
56
  }
@@ -0,0 +1,3 @@
1
+ export default function isString(_var) {
2
+ return typeof _var === 'string';
3
+ }
@@ -0,0 +1,23 @@
1
+ import loadExtensions from '../utils/load-extensions';
2
+ import fleetbaseApiFetch from '../utils/fleetbase-api-fetch';
3
+
4
+ export default async function loadInstalledExtensions(additionalCoreEngines = []) {
5
+ const CORE_ENGINES = [
6
+ '@fleetbase/fleetops-engine',
7
+ '@fleetbase/storefront-engine',
8
+ '@fleetbase/registry-bridge-engine',
9
+ '@fleetbase/dev-engine',
10
+ '@fleetbase/iam-engine',
11
+ ...additionalCoreEngines,
12
+ ];
13
+ const INDEXED_ENGINES = await loadExtensions();
14
+ const INSTALLED_ENGINES = await fleetbaseApiFetch('get', 'engines', {}, { namespace: '~registry/v1', fallbackResponse: [] });
15
+
16
+ const isInstalledEngine = (engineName) => {
17
+ return CORE_ENGINES.includes(engineName) || INSTALLED_ENGINES.find((pkg) => pkg.name === engineName);
18
+ };
19
+
20
+ return INDEXED_ENGINES.filter((pkg) => {
21
+ return isInstalledEngine(pkg.name);
22
+ });
23
+ }
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-core/decorators/engine-service';
@@ -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/is-string';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/ember-core/utils/load-installed-extensions';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/ember-core",
3
- "version": "0.2.12",
3
+ "version": "0.2.14",
4
4
  "description": "Provides all the core services, decorators and utilities for building a Fleetbase extension for the Console.",
5
5
  "keywords": [
6
6
  "fleetbase-core",