Compare commits

..

2 Commits

Author SHA1 Message Date
Manus AI
d50d3ab98b fix: Update comments to reflect updating existing environment files
The console/environments directory and .env files already exist in the
repository. The install script overwrites these existing files with
the correct configuration values. Updated comments to say 'Update'
instead of 'Write/Create' and removed unnecessary mkdir -p command.
2026-02-23 01:06:44 -05:00
Manus AI
7d3b6ed18f fix: Update install script to create console environment files
This commit updates the docker-install.sh script to create/update the
console environment files (.env.development and .env.production) before
starting Docker containers.

## Changes

- Added section 6b to create console/environments directory
- Create .env.development with HTTP configuration
- Create .env.production with HTTPS configuration
- Both files include API_HOST, SOCKETCLUSTER settings, and OSRM_HOST
- Production file includes API_SECURE=true flag

## Rationale

Production builds no longer use fleetbase.config.json for runtime
configuration. Instead, they rely on .env.production files that are
baked into the build at compile time. This ensures proper configuration
for both development and production environments.

## Files Created

1. console/environments/.env.development
   - HTTP API endpoint (http://<host>:8000)
   - SOCKETCLUSTER_SECURE=false
   - Uses provided host value

2. console/environments/.env.production
   - HTTPS API endpoint (https://<host>:8000)
   - SOCKETCLUSTER_SECURE=true
   - API_SECURE=true
   - Uses provided host value

## Impact

This ensures that when users run `ember build --environment=production`,
the compiled assets have the correct API endpoints and SocketCluster
configuration embedded, rather than relying on runtime configuration
which is only available in development mode.

## Related

This change mirrors the update made to the CLI install-fleetbase command
in fleetbase/fleetbase-cli PR #3.
2026-02-22 21:00:39 -05:00
5 changed files with 50 additions and 131 deletions

View File

@@ -2,7 +2,6 @@ import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { isArray } from '@ember/array';
import { debug } from '@ember/debug';
import { storageFor } from 'ember-local-storage';
import { add, isPast } from 'date-fns';
import { task } from 'ember-concurrency';

View File

@@ -6,110 +6,20 @@ const KEYS_INDEX = `${CONTEXT_PREFIX}__keys__`;
export default class OnboardingContextService extends Service {
@service appCache;
@service notifications;
@tracked data = {};
@tracked quotaExceeded = false;
@tracked usingMemoryFallback = false;
// In-memory fallback storage for when localStorage is full
_memoryCache = new Map();
/**
* Safe wrapper for appCache.set with quota error handling
*
* @param {string} key - The key to set
* @param {*} value - The value to store
* @returns {Object} Result object with success status and storage type
*/
_safeSet(key, value) {
try {
this.appCache.set(key, value);
return { success: true, storage: 'localStorage' };
} catch (error) {
if (this._isQuotaError(error)) {
console.warn(`[OnboardingContext] localStorage quota exceeded, using memory fallback for key: ${key}`);
// Store in memory as fallback
this._memoryCache.set(key, value);
// Mark that we're using fallback and notify user (only once)
if (!this.quotaExceeded) {
this.quotaExceeded = true;
this.usingMemoryFallback = true;
this._notifyUser();
}
return { success: true, storage: 'memory', warning: 'Using memory fallback' };
}
// Re-throw non-quota errors
throw error;
}
}
/**
* Safe wrapper for appCache.get with memory fallback
*
* @param {string} key - The key to retrieve
* @returns {*} The stored value or undefined
*/
_safeGet(key) {
try {
const value = this.appCache.get(key);
if (value !== undefined) {
return value;
}
} catch (error) {
console.warn(`[OnboardingContext] Error reading from appCache: ${error.message}`);
}
// Fallback to memory cache
return this._memoryCache.get(key);
}
/**
* Check if error is a quota exceeded error
*
* @param {Error} error - The error to check
* @returns {boolean} True if it's a quota error
*/
_isQuotaError(error) {
return (
error instanceof DOMException &&
(error.code === 22 ||
error.code === 1014 ||
error.name === 'QuotaExceededError' ||
error.name === 'NS_ERROR_DOM_QUOTA_REACHED')
);
}
/**
* Notify user about storage issues (only called once)
*/
_notifyUser() {
if (this.notifications) {
this.notifications.warning(
'Your browser storage is full. Your onboarding progress will be saved temporarily but may be lost if you close this tab. Please complete the onboarding process in this session.',
{
timeout: 10000,
clearDuration: 300
}
);
}
}
/**
* Get a value from in-memory state first, then fallback to cache
*/
get(key) {
return this.data[key] ?? this._safeGet(`${CONTEXT_PREFIX}${key}`);
return this.data[key] ?? this.appCache.get(`${CONTEXT_PREFIX}${key}`);
}
/**
* Get a value directly from cache
*/
getFromCache(key) {
return this._safeGet(`${CONTEXT_PREFIX}${key}`);
return this.appCache.get(`${CONTEXT_PREFIX}${key}`);
}
/**
@@ -118,11 +28,11 @@ export default class OnboardingContextService extends Service {
* @returns {Object}
*/
restore() {
const keys = this._safeGet(KEYS_INDEX) ?? [];
const keys = this.appCache.get(KEYS_INDEX) ?? [];
const persisted = {};
for (const key of keys) {
const value = this._safeGet(`${CONTEXT_PREFIX}${key}`);
const value = this.appCache.get(`${CONTEXT_PREFIX}${key}`);
if (value !== undefined) {
persisted[key] = value;
}
@@ -153,14 +63,14 @@ export default class OnboardingContextService extends Service {
this.data = { ...this.data, ...filteredData };
if (options.persist === true) {
const keys = new Set(this._safeGet(KEYS_INDEX) ?? []);
const keys = new Set(this.appCache.get(KEYS_INDEX) ?? []);
for (const key of Object.keys(filteredData)) {
keys.add(key);
this._safeSet(`${CONTEXT_PREFIX}${key}`, this.data[key]);
this.appCache.set(`${CONTEXT_PREFIX}${key}`, this.data[key]);
}
this._safeSet(KEYS_INDEX, [...keys]);
this.appCache.set(KEYS_INDEX, [...keys]);
}
}
@@ -178,11 +88,11 @@ export default class OnboardingContextService extends Service {
this.data = { ...this.data, [key]: value };
if (options.persist === true) {
const keys = new Set(this._safeGet(KEYS_INDEX) ?? []);
const keys = new Set(this.appCache.get(KEYS_INDEX) ?? []);
keys.add(key);
this._safeSet(`${CONTEXT_PREFIX}${key}`, value);
this._safeSet(KEYS_INDEX, [...keys]);
this.appCache.set(`${CONTEXT_PREFIX}${key}`, value);
this.appCache.set(KEYS_INDEX, [...keys]);
}
}
@@ -200,44 +110,24 @@ export default class OnboardingContextService extends Service {
const { [key]: _removed, ...rest } = this.data; // eslint-disable-line no-unused-vars
this.data = rest;
const keys = new Set(this._safeGet(KEYS_INDEX) ?? []);
const keys = new Set(this.appCache.get(KEYS_INDEX) ?? []);
keys.delete(key);
this._safeSet(`${CONTEXT_PREFIX}${key}`, undefined);
this._safeSet(KEYS_INDEX, [...keys]);
// Also remove from memory cache
this._memoryCache.delete(`${CONTEXT_PREFIX}${key}`);
this.appCache.set(`${CONTEXT_PREFIX}${key}`, undefined);
this.appCache.set(KEYS_INDEX, [...keys]);
}
/**
* Fully reset onboarding context (memory + persistence)
*/
reset() {
const keys = this._safeGet(KEYS_INDEX) ?? [];
const keys = this.appCache.get(KEYS_INDEX) ?? [];
for (const key of keys) {
this._safeSet(`${CONTEXT_PREFIX}${key}`, undefined);
this._memoryCache.delete(`${CONTEXT_PREFIX}${key}`);
this.appCache.set(`${CONTEXT_PREFIX}${key}`, undefined);
}
this._safeSet(KEYS_INDEX, []);
this._memoryCache.clear();
this.appCache.set(KEYS_INDEX, []);
this.data = {};
this.quotaExceeded = false;
this.usingMemoryFallback = false;
}
/**
* Get storage status for debugging
*
* @returns {Object} Storage status information
*/
getStorageStatus() {
return {
quotaExceeded: this.quotaExceeded,
usingMemoryFallback: this.usingMemoryFallback,
memoryItemCount: this._memoryCache.size
};
}
}
}

View File

@@ -96,7 +96,7 @@ else
fi
###############################################################################
# 6. Write console/fleetbase.config.json atomically
# 6. Write console/fleetbase.config.json atomically (for development runtime)
###############################################################################
CONFIG_DIR="console"
CONFIG_PATH="$CONFIG_DIR/fleetbase.config.json"
@@ -113,6 +113,36 @@ JSON
mv -f "${CONFIG_PATH}.tmp" "$CONFIG_PATH"
echo "$CONFIG_PATH updated"
###############################################################################
# 6b. Update console environment files (.env.development and .env.production)
###############################################################################
ENV_DIR="$CONFIG_DIR/environments"
# Update .env.development
cat > "$ENV_DIR/.env.development" <<ENV_DEV
API_HOST=http://$HOST:8000
API_NAMESPACE=int/v1
SOCKETCLUSTER_PATH=/socketcluster/
SOCKETCLUSTER_HOST=$HOST
SOCKETCLUSTER_SECURE=false
SOCKETCLUSTER_PORT=38000
OSRM_HOST=https://router.project-osrm.org
ENV_DEV
# Update .env.production
cat > "$ENV_DIR/.env.production" <<ENV_PROD
API_HOST=https://$HOST:8000
API_NAMESPACE=int/v1
API_SECURE=true
SOCKETCLUSTER_PATH=/socketcluster/
SOCKETCLUSTER_HOST=$HOST
SOCKETCLUSTER_SECURE=true
SOCKETCLUSTER_PORT=38000
OSRM_HOST=https://router.project-osrm.org
ENV_PROD
echo "✔ Console environment files updated"
###############################################################################
# 7. Start stack, wait for DB, then run deploy
###############################################################################