Compare commits

..

1 Commits

Author SHA1 Message Date
Ronald A. Richardson
0bcd9ec165 fix: always generate extension loader files even when no extensions are installed
When no extensions are installed, generateExtensionFiles() previously
returned early after cleaning up the app/extensions directory. This left
the directory absent, causing a fatal module resolution error at runtime:

  Error: Could not find module `@fleetbase/console/extensions`
  imported from `@fleetbase/ember-core/services/universe/extension-manager`

The extension-manager service in @fleetbase/ember-core has a hard static
import:

  import { getExtensionLoader } from '@fleetbase/console/extensions';

Ember's module resolver maps this to app/extensions/index.js. Because
that file was never created in the zero-extension scenario, the entire
application failed to boot.

Changes:
- Remove the early return when extensions.length === 0.
- Restructure generateExtensionFiles() so that generateExtensionLoaders(),
  generateRouter(), and generateExtensionsManifest() are always called,
  regardless of whether any extensions are discovered.
- generateExtensionShims() is still only called when extensions > 0, as
  there are no shim files to write in the empty case.
- When no extensions are found, generateExtensionLoaders() writes an
  app/extensions/index.js with an empty EXTENSION_LOADERS = {} object,
  satisfying the module dependency without registering any loaders.
- generateExtensionsManifest() writes public/extensions.json with an
  empty array [], which is the correct state for zero extensions.

Additionally, add null-guards to the recast AST visitor inside
generateRouter() to prevent a potential TypeError when traversing call
expressions whose callee is not a MemberExpression (e.g. bare require()
or import() calls that have no .property).
2026-02-28 03:44:37 -05:00
18 changed files with 526 additions and 2811 deletions

View File

@@ -240,6 +240,10 @@ jobs:
set -u
DEPLOY_BUCKET=${STATIC_DEPLOY_BUCKET:-${{ env.PROJECT }}-${{ env.STACK }}}
NEW_BUCKET="${PROJECT}-${STACK}-console"
if aws s3api head-bucket --bucket "$NEW_BUCKET" 2>/dev/null; then
DEPLOY_BUCKET="$NEW_BUCKET"
fi
# this value will come from the dotenv above
echo "Deploying to $DEPLOY_BUCKET"

View File

@@ -24,15 +24,6 @@
"fleetbase/fleetops-api": "^0.6.37",
"fleetbase/registry-bridge": "^0.1.7",
"fleetbase/storefront-api": "^0.4.13",
"fleetbase/aws-marketplace": "^0.0.8",
"fleetbase/billing-api": "^0.1.20",
"fleetbase/customer-portal-api": "^0.0.10",
"fleetbase/flespi-integration": "^0.1.16",
"fleetbase/internals-api": "^0.0.28",
"fleetbase/samsara-api": "^0.0.3",
"fleetbase/solid-api": "^0.0.7",
"fleetbase/valhalla-api": "^0.0.3",
"fleetbase/vroom-api": "^0.0.3",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^10.0",
"laravel/octane": "^2.3",
@@ -61,14 +52,6 @@
{
"type": "composer",
"url": "https://registry.fleetbase.io"
},
{
"type": "vcs",
"url": "https://github.com/fleetbase/aws-marketplace"
},
{
"type": "vcs",
"url": "https://github.com/fleetbase/internals"
}
],
"autoload": {

1483
api/composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,8 @@
API_HOST=https://api.fleetbase.io
API_HOST=
API_NAMESPACE=int/v1
API_SECURE=true
SOCKETCLUSTER_PATH=/socketcluster/
SOCKETCLUSTER_HOST=socket.fleetbase.io
SOCKETCLUSTER_HOST=
SOCKETCLUSTER_SECURE=true
SOCKETCLUSTER_PORT=8000
OSRM_HOST=https://router.project-osrm.org
DISABLE_RUNTIME_CONFIG=true
SOCKETCLUSTER_PORT=38000
OSRM_HOST=https://router.project-osrm.org

View File

@@ -1,9 +0,0 @@
API_HOST=https://api.qa.fleetbase.io
API_NAMESPACE=int/v1
API_SECURE=true
SOCKETCLUSTER_PATH=/socketcluster/
SOCKETCLUSTER_HOST=socket.qa.fleetbase.io
SOCKETCLUSTER_SECURE=true
SOCKETCLUSTER_PORT=8000
OSRM_HOST=https://router.project-osrm.org
DISABLE_RUNTIME_CONFIG=true

View File

@@ -59,27 +59,24 @@ module.exports = {
const extensions = await this.getExtensions();
if (extensions.length === 0) {
console.log('[Fleetbase] No extensions found');
return;
if (extensions.length > 0) {
console.log(`[Fleetbase] Discovered ${extensions.length} extension(s)`);
extensions.forEach((ext) => {
console.log(`[Fleetbase] - ${ext.name} (v${ext.version})`);
});
console.log('');
// Generate extension shims (only needed when extensions are present)
this.generateExtensionShims(extensions);
} else {
console.log('[Fleetbase] No extensions found — generating empty extension loader to satisfy module dependencies.');
}
console.log(`[Fleetbase] Discovered ${extensions.length} extension(s)`);
extensions.forEach((ext) => {
console.log(`[Fleetbase] - ${ext.name} (v${ext.version})`);
});
console.log('');
// Generate extension shims
this.generateExtensionShims(extensions);
// Generate extension loaders
// Always generate loaders, router, and manifest so that
// @fleetbase/console/extensions (app/extensions/index.js) always exists
// and the build does not fail when zero extensions are installed.
this.generateExtensionLoaders(extensions);
// Generate router
this.generateRouter(extensions);
// Generate manifest
this.generateExtensionsManifest(extensions);
},
@@ -227,7 +224,7 @@ export default getExtensionLoader;
recast.visit(ast, {
visitCallExpression(path) {
if (path.value.type === 'CallExpression' && path.value.callee.property.name === 'route' && path.value.arguments[0].value === 'console') {
if (path.value.type === 'CallExpression' && path.value.callee.property && path.value.callee.property.name === 'route' && path.value.arguments[0] && path.value.arguments[0].value === 'console') {
let functionExpression;
// Find the function expression
@@ -270,7 +267,7 @@ export default getExtensionLoader;
}
}
if (path.value.type === 'CallExpression' && path.value.callee.property.name === 'map') {
if (path.value.type === 'CallExpression' && path.value.callee.property && path.value.callee.property.name === 'map') {
let functionExpression;
path.value.arguments.forEach((arg) => {

View File

@@ -33,24 +33,15 @@
},
"dependencies": {
"@ember/legacy-built-in-components": "^0.4.2",
"@fleetbase/aws-marketplace": "^0.0.8",
"@fleetbase/billing-engine": "^0.1.20",
"@fleetbase/customer-portal-engine": "^0.0.10",
"@fleetbase/dev-engine": "^0.2.12",
"@fleetbase/ember-core": "^0.3.12",
"@fleetbase/ember-ui": "^0.3.21",
"@fleetbase/fleetops-data": "^0.1.25",
"@fleetbase/fleetops-engine": "^0.6.37",
"@fleetbase/iam-engine": "^0.1.7",
"@fleetbase/flespi-engine": "^0.1.16",
"@fleetbase/internals-engine": "^0.0.28",
"@fleetbase/leaflet-routing-machine": "^3.2.17",
"@fleetbase/registry-bridge-engine": "^0.1.7",
"@fleetbase/samsara-engine": "^0.0.3",
"@fleetbase/solid-engine": "^0.0.7",
"@fleetbase/storefront-engine": "^0.4.13",
"@fleetbase/valhalla-engine": "^0.0.3",
"@fleetbase/vroom-engine": "^0.0.3",
"@formatjs/intl-datetimeformat": "^6.18.2",
"@formatjs/intl-numberformat": "^8.15.6",
"@formatjs/intl-pluralrules": "^5.4.6",

1751
console/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff