UNPKG

fleeta-lib

Version:

A comprehensive library for fleet management applications - API, Auth, Device management

1,105 lines (1,104 loc) โ€ข 36.4 kB
import { create } from "zustand"; import CryptoJS from "crypto-js"; const useApiEndpointStore = create((set) => ({ config: null, isInitialized: false, setConfig: (config) => { console.log("๐Ÿ”ง [ApiEndpointStore] Setting API endpoint configuration:", { apiGateway: config.apiGateway, iotApiGateway: config.iotApiGateway }); set({ config, isInitialized: true }); }, clearConfig: () => { console.log("๐Ÿงน [ApiEndpointStore] Clearing API endpoint configuration"); set({ config: null, isInitialized: false }); } })); function getApiEndpointConfig() { const state = useApiEndpointStore.getState(); if (!state.isInitialized || !state.config) { return null; } return state.config; } function isApiEndpointConfigured() { return getApiEndpointConfig() !== null; } function getApiEndpoint(endpoint) { const config = getApiEndpointConfig(); if (!config) { console.error("โŒ [EndpointUtils] API endpoints not configured. Please initialize in main.tsx"); return null; } return config[endpoint]; } function getApiGateway() { const url = getApiEndpoint("apiGateway"); if (!url) { throw new Error("API Gateway not configured. Please set VITE_API_GATEWAY in .env file."); } return url; } function getIotApiGateway() { const url = getApiEndpoint("iotApiGateway"); if (!url) { throw new Error("IoT API Gateway not configured. Please set VITE_IOT_API_GATEWAY in .env file."); } return url; } function getEndpointErrorMessage() { return "API endpoints not configured. Please check your environment variables."; } function validateApiEndpoints() { const config = getApiEndpointConfig(); if (!config) { return false; } const requiredEndpoints = [ "apiGateway", "iotApiGateway" ]; return requiredEndpoints.every((endpoint) => { const value = config[endpoint]; return value && value.trim().length > 0; }); } const API_MODULE_VERSION = "1.0.0"; const API_MODULE_NAME = "FleetA API Endpoint Manager"; const __vite_import_meta_env__ = {}; function createJSONStorage(getStorage, options) { let storage; try { storage = getStorage(); } catch (_e) { return; } const persistStorage = { getItem: (name) => { var _a; const parse = (str2) => { if (str2 === null) { return null; } return JSON.parse(str2, void 0); }; const str = (_a = storage.getItem(name)) != null ? _a : null; if (str instanceof Promise) { return str.then(parse); } return parse(str); }, setItem: (name, newValue) => storage.setItem( name, JSON.stringify(newValue, void 0) ), removeItem: (name) => storage.removeItem(name) }; return persistStorage; } const toThenable = (fn) => (input) => { try { const result = fn(input); if (result instanceof Promise) { return result; } return { then(onFulfilled) { return toThenable(onFulfilled)(result); }, catch(_onRejected) { return this; } }; } catch (e) { return { then(_onFulfilled) { return this; }, catch(onRejected) { return toThenable(onRejected)(e); } }; } }; const oldImpl = (config, baseOptions) => (set, get, api) => { let options = { getStorage: () => localStorage, serialize: JSON.stringify, deserialize: JSON.parse, partialize: (state) => state, version: 0, merge: (persistedState, currentState) => ({ ...currentState, ...persistedState }), ...baseOptions }; let hasHydrated = false; const hydrationListeners = /* @__PURE__ */ new Set(); const finishHydrationListeners = /* @__PURE__ */ new Set(); let storage; try { storage = options.getStorage(); } catch (_e) { } if (!storage) { return config( (...args) => { console.warn( `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.` ); set(...args); }, get, api ); } const thenableSerialize = toThenable(options.serialize); const setItem = () => { const state = options.partialize({ ...get() }); let errorInSync; const thenable = thenableSerialize({ state, version: options.version }).then( (serializedValue) => storage.setItem(options.name, serializedValue) ).catch((e) => { errorInSync = e; }); if (errorInSync) { throw errorInSync; } return thenable; }; const savedSetState = api.setState; api.setState = (state, replace) => { savedSetState(state, replace); void setItem(); }; const configResult = config( (...args) => { set(...args); void setItem(); }, get, api ); let stateFromStorage; const hydrate = () => { var _a; if (!storage) return; hasHydrated = false; hydrationListeners.forEach((cb) => cb(get())); const postRehydrationCallback = ((_a = options.onRehydrateStorage) == null ? void 0 : _a.call(options, get())) || void 0; return toThenable(storage.getItem.bind(storage))(options.name).then((storageValue) => { if (storageValue) { return options.deserialize(storageValue); } }).then((deserializedStorageValue) => { if (deserializedStorageValue) { if (typeof deserializedStorageValue.version === "number" && deserializedStorageValue.version !== options.version) { if (options.migrate) { return options.migrate( deserializedStorageValue.state, deserializedStorageValue.version ); } console.error( `State loaded from storage couldn't be migrated since no migrate function was provided` ); } else { return deserializedStorageValue.state; } } }).then((migratedState) => { var _a2; stateFromStorage = options.merge( migratedState, (_a2 = get()) != null ? _a2 : configResult ); set(stateFromStorage, true); return setItem(); }).then(() => { postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0); hasHydrated = true; finishHydrationListeners.forEach((cb) => cb(stateFromStorage)); }).catch((e) => { postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e); }); }; api.persist = { setOptions: (newOptions) => { options = { ...options, ...newOptions }; if (newOptions.getStorage) { storage = newOptions.getStorage(); } }, clearStorage: () => { storage == null ? void 0 : storage.removeItem(options.name); }, getOptions: () => options, rehydrate: () => hydrate(), hasHydrated: () => hasHydrated, onHydrate: (cb) => { hydrationListeners.add(cb); return () => { hydrationListeners.delete(cb); }; }, onFinishHydration: (cb) => { finishHydrationListeners.add(cb); return () => { finishHydrationListeners.delete(cb); }; } }; hydrate(); return stateFromStorage || configResult; }; const newImpl = (config, baseOptions) => (set, get, api) => { let options = { storage: createJSONStorage(() => localStorage), partialize: (state) => state, version: 0, merge: (persistedState, currentState) => ({ ...currentState, ...persistedState }), ...baseOptions }; let hasHydrated = false; const hydrationListeners = /* @__PURE__ */ new Set(); const finishHydrationListeners = /* @__PURE__ */ new Set(); let storage = options.storage; if (!storage) { return config( (...args) => { console.warn( `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.` ); set(...args); }, get, api ); } const setItem = () => { const state = options.partialize({ ...get() }); return storage.setItem(options.name, { state, version: options.version }); }; const savedSetState = api.setState; api.setState = (state, replace) => { savedSetState(state, replace); void setItem(); }; const configResult = config( (...args) => { set(...args); void setItem(); }, get, api ); api.getInitialState = () => configResult; let stateFromStorage; const hydrate = () => { var _a, _b; if (!storage) return; hasHydrated = false; hydrationListeners.forEach((cb) => { var _a2; return cb((_a2 = get()) != null ? _a2 : configResult); }); const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? void 0 : _b.call(options, (_a = get()) != null ? _a : configResult)) || void 0; return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => { if (deserializedStorageValue) { if (typeof deserializedStorageValue.version === "number" && deserializedStorageValue.version !== options.version) { if (options.migrate) { return [ true, options.migrate( deserializedStorageValue.state, deserializedStorageValue.version ) ]; } console.error( `State loaded from storage couldn't be migrated since no migrate function was provided` ); } else { return [false, deserializedStorageValue.state]; } } return [false, void 0]; }).then((migrationResult) => { var _a2; const [migrated, migratedState] = migrationResult; stateFromStorage = options.merge( migratedState, (_a2 = get()) != null ? _a2 : configResult ); set(stateFromStorage, true); if (migrated) { return setItem(); } }).then(() => { postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0); stateFromStorage = get(); hasHydrated = true; finishHydrationListeners.forEach((cb) => cb(stateFromStorage)); }).catch((e) => { postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e); }); }; api.persist = { setOptions: (newOptions) => { options = { ...options, ...newOptions }; if (newOptions.storage) { storage = newOptions.storage; } }, clearStorage: () => { storage == null ? void 0 : storage.removeItem(options.name); }, getOptions: () => options, rehydrate: () => hydrate(), hasHydrated: () => hasHydrated, onHydrate: (cb) => { hydrationListeners.add(cb); return () => { hydrationListeners.delete(cb); }; }, onFinishHydration: (cb) => { finishHydrationListeners.add(cb); return () => { finishHydrationListeners.delete(cb); }; } }; if (!options.skipHydration) { hydrate(); } return stateFromStorage || configResult; }; const persistImpl = (config, baseOptions) => { if ("getStorage" in baseOptions || "serialize" in baseOptions || "deserialize" in baseOptions) { if ((__vite_import_meta_env__ ? "production" : void 0) !== "production") { console.warn( "[DEPRECATED] `getStorage`, `serialize` and `deserialize` options are deprecated. Use `storage` option instead." ); } return oldImpl(config, baseOptions); } return newImpl(config, baseOptions); }; const persist = persistImpl; const useAuthStore = create()( persist( (set) => ({ isAuthenticated: false, userToken: null, jwtToken: null, serverConfig: null, userType: null, subscribeInfo: null, latestLoginInfo: null, error: null, setAuth: (data) => { var _a; if (data.resultcode === "BC_ERR_OK") { const responseData = data.response || {}; const duplicateLogins = (_a = responseData["logged in list"]) == null ? void 0 : _a.ids; set({ isAuthenticated: true, userToken: responseData.user_token ?? data.user_token ?? null, jwtToken: responseData.jsonwebtoken ?? data.jsonwebtoken ?? data.jwt_token ?? null, serverConfig: { was_server: responseData.was_server ?? "", was_port: responseData.was_port ?? "", gps_server: responseData.gps_server ?? "", gps_port: responseData.gps_port ?? "", gps_tracking_server: responseData.gps_tracking_server ?? "", gps_tracking_port: responseData.gps_tracking_port ?? "", geo_fence_server: responseData.geo_fence_server ?? "", geo_fence_port: responseData.geo_fence_port ?? "" }, userType: responseData.userType ?? null, subscribeInfo: responseData.subscribeinfo ?? null, latestLoginInfo: { timestamp: responseData.latestlogindt ?? "", mobileOS: responseData.lastMobileOS ?? "", appVersion: responseData.lastAppVer ?? "", webVersion: responseData.lastWebVer ?? "", duplicateLogins }, error: null }); } else { set({ error: data.message ?? "Login failed", isAuthenticated: false }); } }, clearAuth: () => { set({ isAuthenticated: false, userToken: null, jwtToken: null, serverConfig: null, userType: null, subscribeInfo: null, latestLoginInfo: null, error: null }); }, setError: (error) => set({ error }) }), { name: "auth-storage", skipHydration: false } ) ); let isLoggingIn = false; let isLoggingOut = false; const LOGIN_ERROR_MESSAGES = { BC_ERR_AUTHENTICATION: "Authentication failed. Please check your credentials.", BC_ERR_SIGNATURE: "Invalid security signature. Please try again.", BC_ERR_INVALID_DATA: "Something went wrong. Please try again.", BC_ERR_INVALID_PARAMETER: "Invalid login parameters. Please check your input.", BC_ERR_NEED_TO_CONFIRM: "Please verify your email address before logging in.", BC_ERR_BLACK_LIST: "Your account has been blocked for security reasons. Please contact support.", BC_ERR_SERVER: "Server error. Please try again later.", BC_ERR_DUPLICATED: "Account is already logged in on another device.", BC_ERR_GOOGLEAPPLE_ACCOUNT: "This account uses Google or Apple sign-in. Please continue with one of those." }; const RESET_PASSWORD_ERROR_MESSAGES = { BC_ERR_AUTHENTICATION: "Authentication failed. Please try again.", BC_ERR_SIGNATURE: "Security verification failed. Please try again.", BC_ERR_INVALID_DATA: "Invalid data received. Please try again.", BC_ERR_ALREADY_REQUESTED: "Password reset email has already been sent. Please check your inbox.", BC_ERR_INVALID_PARAMETER: "Invalid request parameters. Please try again.", BC_ERR_SERVER: "Internal server error. Please try again later.", BC_ERR_NOT_FOUND: "Email address not found. Please check your email and try again." }; const LOGOUT_ERROR_MESSAGES = { BC_ERR_AUTHENTICATION: "BCS Token not exists", BC_ERR_INVALID_PARAMETER: "Invalid parameter", BC_ERR_SERVER: "Internal server error" }; async function logout() { const { userToken, subscribeInfo, jwtToken } = useAuthStore.getState(); if (isLoggingOut) { return; } if (!userToken || !(subscribeInfo == null ? void 0 : subscribeInfo.userEmail)) { throw new Error("No active session found"); } try { isLoggingOut = true; const API_GATEWAY = getApiGateway(); const params = new URLSearchParams({ email: subscribeInfo.userEmail, user_token: userToken, tokenType: "web" }); let response = await fetch(`${API_GATEWAY}/BCS/userLogout.php?${params.toString()}`, { method: "GET", headers: { "Content-Type": "application/x-www-form-urlencoded", "Authorization": `Bearer ${jwtToken}` } }); const data = await response.json(); if (data.resultcode === "BC_ERR_OK") { useAuthStore.getState().clearAuth(); return; } else { const errorMessage = LOGOUT_ERROR_MESSAGES[data.resultcode] || data.message; useAuthStore.getState().setError(errorMessage); throw new Error(errorMessage); } } catch (error) { console.error("Logout error:", error); useAuthStore.getState().clearAuth(); const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred during logout"; useAuthStore.getState().setError(errorMessage); throw error; } finally { isLoggingOut = false; } } async function login({ email, password }) { if (isLoggingIn) { return; } try { isLoggingIn = true; const API_GATEWAY = getApiGateway(); const formData = new URLSearchParams({ email, passwd: CryptoJS.SHA256(password).toString(), mobile_uuid: "web-" + crypto.randomUUID(), // Web client unique ID mobile_name: navigator.userAgent, mobile_os_type: getOSType(), app_ver: "1.0.0", web_ver: "1.0.0", time_interval: getTimeZoneOffset().toString(), tokenType: "web", loginApp: "fleeta", loginType: "blackvue", companyID: "", mobileLang: navigator.language.split("-")[0] || "eng" }); const response = await fetch(`${API_GATEWAY}/BCS/userLogin.php`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: formData }); const data = await response.json(); console.log("๐Ÿ“ฅ Login API response - FULL DATA:", { resultcode: data.resultcode, message: data.message, userToken: data.user_token || data.userToken, jwtToken: data.jwt_token || data.jwtToken, email: data.email || data.userEmail, fullResponse: data }); if (data.resultcode === "BC_ERR_OK") { console.log("โœ… Login successful, calling setAuth with processed data:", { userToken: data.user_token || data.userToken || "MISSING", jwtToken: data.jwt_token || data.jwtToken || "MISSING", email: data.email || data.userEmail || "MISSING" }); useAuthStore.getState().setAuth(data); } else { const errorMessage = LOGIN_ERROR_MESSAGES[data.resultcode] || data.message; throw new Error(errorMessage); } } catch (error) { console.error("Login error:", error); useAuthStore.getState().setError(error instanceof Error ? error.message : "An error occurred during login"); throw error; } finally { isLoggingIn = false; } } function getOSType() { const platform = navigator.platform.toLowerCase(); if (platform.includes("win")) return "win32"; if (platform.includes("mac")) return "macos"; if (platform.includes("linux")) return "linux"; return "web"; } function getTimeZoneOffset() { return (/* @__PURE__ */ new Date()).getTimezoneOffset() * -1; } async function resetPassword(email) { try { const API_GATEWAY = getApiGateway(); const params = new URLSearchParams({ email, mobileLang: navigator.language.split("-")[0] || "eng", loginApp: "fleeta" }); const response = await fetch(`${API_GATEWAY}/BCS/initPasswd.php?${params.toString()}`, { method: "GET", headers: { "Content-Type": "application/x-www-form-urlencoded" } }); const data = await response.json(); if (!data || typeof data !== "object") { throw new Error("Invalid server response format"); } switch (data.resultcode) { case "BC_ERR_OK": return { success: true, alreadyRequested: false }; case "BC_ERR_ALREADY_REQUESTED": return { success: true, alreadyRequested: true }; case "BC_ERR_NOT_FOUND": return { success: false, alreadyRequested: false }; default: const errorMessage = RESET_PASSWORD_ERROR_MESSAGES[data.resultcode] || data.message || "An unexpected error occurred. Please try again."; throw new Error(errorMessage); } } catch (error) { console.error("Password reset error:", error); throw error; } } function getAuthConfigFromStore() { var _a; const state = useAuthStore.getState(); if (!state.isAuthenticated || !state.userToken || !state.jwtToken || !((_a = state.subscribeInfo) == null ? void 0 : _a.userEmail)) { return null; } return { userToken: state.userToken, userEmail: state.subscribeInfo.userEmail, jwtToken: state.jwtToken }; } function isAuthConfigured() { return getAuthConfigFromStore() !== null; } function isAuthConfigValid() { const authConfig = getAuthConfigFromStore(); if (!authConfig) { return false; } return authConfig.userToken.length > 0 && authConfig.jwtToken.length > 0 && authConfig.userEmail.includes("@"); } function getAuthHeaders() { const authConfig = getAuthConfigFromStore(); if (!authConfig) { throw new Error("Authentication required. Please login first."); } return { "Authorization": `Bearer ${authConfig.jwtToken}`, "Content-Type": "application/json" }; } function getAuthErrorMessage() { return "Authentication required. Please login first."; } const AUTH_MODULE_VERSION = "1.0.0"; const AUTH_MODULE_NAME = "FleetA Authentication Module"; const DEVICE_LIST_ERROR_MESSAGES = { BC_ERR_AUTHENTICATION: "Unauthorized - Authentication failed", BC_ERR_INVALID_PARAMETER: "Invalid parameter provided", BC_ERR_SERVER: "Internal server error occurred" }; const DEVICE_MODE_NAMES = { "0": "Normal Mode", "1": "Parking Mode" }; const COMMUNICATION_TYPE_NAMES = { "Wifi": "Wi-Fi Connection", "Cat4": "LTE Cat-4", "Cat-M1": "LTE Cat-M1" }; const DEVICE_STATUS_NAMES = { "on": "Online", "off": "Offline" }; function processDeviceListData(devices) { const statistics = calculateDeviceStatistics(devices); const groups = groupDevicesByGroup(devices); return { groups, statistics }; } function groupDevicesByGroup(devices) { const groupMap = /* @__PURE__ */ new Map(); devices.forEach((item) => { item.groupName || "Ungrouped"; const groupId = item.groupManagementID || "ungrouped"; if (!groupMap.has(groupId)) { groupMap.set(groupId, []); } groupMap.get(groupId).push(item); }); const groups = []; groupMap.forEach((devices2, groupId) => { const firstDevice = devices2[0]; groups.push({ groupId, groupName: firstDevice.groupName || "Ungrouped", groupRegDate: firstDevice.groupRegDT, devices: devices2, isExpanded: groupId === "ungrouped" // Default expand ungrouped }); }); groups.sort((a, b) => { if (a.groupId === "ungrouped") return -1; if (b.groupId === "ungrouped") return 1; return a.groupName.localeCompare(b.groupName); }); return groups; } function calculateDeviceStatistics(devices) { const total = devices.length; const online = devices.filter((item) => item.device.active === "on").length; const offline = total - online; const grouped = devices.filter((item) => !!item.groupManagementID).length; const ungrouped = total - grouped; const videoSharing = devices.filter((item) => item.device.share_video === "on").length; const normalMode = devices.filter((item) => item.device.mode === "0").length; const parkingMode = devices.filter((item) => item.device.mode === "1").length; const wifiOnly = devices.filter((item) => item.device.reg_category === "wifi").length; const cloudEnabled = devices.filter((item) => item.device.reg_category === "cloud").length; const withBattery = devices.filter((item) => !!item.device.battery).length; return { total, online, offline, grouped, ungrouped, videoSharing, normalMode, parkingMode, wifiOnly, cloudEnabled, withBattery }; } async function getDeviceList$1(params) { var _a, _b, _c, _d; const authConfig = getAuthConfigFromStore(); if (!authConfig) { throw new Error(getAuthErrorMessage()); } try { const API_GATEWAY = getApiGateway(); const requestParams = { email: authConfig.userEmail, userToken: authConfig.userToken, tokenType: "web", ...params }; console.log("๐Ÿ“ฑ [Device API] Requesting device list:", { email: requestParams.email, hasUserToken: !!requestParams.userToken, tokenType: requestParams.tokenType, keyword: requestParams.keyword, startIndex: requestParams.startIndex, endIndex: requestParams.endIndex }); const queryParams = new URLSearchParams(); queryParams.append("email", requestParams.email); queryParams.append("userToken", requestParams.userToken); queryParams.append("tokenType", requestParams.tokenType || "web"); if (requestParams.keyword) { queryParams.append("keyword", requestParams.keyword); } if (requestParams.startIndex && requestParams.startIndex >= 1) { queryParams.append("startIndex", requestParams.startIndex.toString()); } if (requestParams.endIndex && requestParams.endIndex >= 1) { queryParams.append("endIndex", requestParams.endIndex.toString()); } const response = await fetch(`${API_GATEWAY}/DashCam/DeviceList?${queryParams.toString()}`, { method: "GET", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${authConfig.jwtToken}` } }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); console.log("๐Ÿ“ก [Device API] Raw API response:", { resultcode: data.resultcode, message: data.message, hasResponse: !!(data.response || data.deviceListInfo), deviceCount: ((_a = data.response) == null ? void 0 : _a.deviceCount) || data.deviceCount, deviceListInfo: ((_c = (_b = data.response) == null ? void 0 : _b.deviceListInfo) == null ? void 0 : _c.length) || ((_d = data.deviceListInfo) == null ? void 0 : _d.length) || 0, rawResponse: data.response || data }); if (data.resultcode !== "BC_ERR_OK") { const errorMessage = DEVICE_LIST_ERROR_MESSAGES[data.resultcode] || data.message || "Unknown error occurred"; throw new Error(errorMessage); } const responseData = data.response || { deviceCount: data.deviceCount || 0, deviceLimitCount: data.deviceLimitCount || 0, sharedEventMap: data.sharedEventMap || "off", deviceListInfo: data.deviceListInfo || [] }; if (!responseData) { console.warn("โš ๏ธ [Device API] API returned null/undefined response object"); return { resultcode: data.resultcode, message: data.message, deviceCount: 0, deviceLimitCount: 0, sharedEventMap: "off", deviceListInfo: [], groupedData: { groups: [], statistics: { total: 0, online: 0, offline: 0, grouped: 0, ungrouped: 0, videoSharing: 0, normalMode: 0, parkingMode: 0, wifiOnly: 0, cloudEnabled: 0, withBattery: 0 } } }; } if (!responseData.deviceListInfo) { console.warn("โš ๏ธ [Device API] API returned null/undefined deviceListInfo in response, setting to empty array"); responseData.deviceListInfo = []; } const { groups, statistics } = processDeviceListData(responseData.deviceListInfo); console.log("๐Ÿ“ฑ [Device API] Final processed response:", { devices: responseData.deviceListInfo.length, groups: groups.length, statistics: statistics.total, resultcode: data.resultcode, deviceCount: responseData.deviceCount }); return { resultcode: data.resultcode, message: data.message, deviceCount: responseData.deviceCount || 0, deviceLimitCount: responseData.deviceLimitCount || 0, sharedEventMap: responseData.sharedEventMap || "off", deviceListInfo: responseData.deviceListInfo || [], groupedData: { groups, statistics } }; } catch (error) { console.error("โŒ [Device API] Device list request failed:", error); throw error; } } function isDeviceApiReady() { return getAuthConfigFromStore() !== null; } const MOCK_CONFIG = { GROUPS_COUNT: 5, DEVICES_PER_GROUP: 20 }; const MOCK_GROUP_NAMES = [ "Seoul Fleet Alpha", "Busan Transport Beta", "Daegu Logistics Gamma", "Incheon Delivery Delta", "Gwangju Express Epsilon" ]; const MOCK_DEVICE_MODELS = [ "DR970X-2CH", "DR970X-1CH", "DR900X-2CH", "DR900X-1CH", "DR750X-2CH" ]; const COMM_TYPES = [ "Wifi", "Cat4", "Cat-M1" ]; function generatePSN(groupIndex, deviceIndex) { const groupId = (groupIndex + 1).toString().padStart(2, "0"); const deviceId = (deviceIndex + 1).toString().padStart(3, "0"); return `MOCK${groupId}${deviceId}`; } function generateBatteryInfo() { const percentage = Math.floor(Math.random() * 100); const celsius = Math.floor(Math.random() * 60) + 10; return { ssid: `MOCK_BATTERY_${Math.random().toString(36).substr(2, 9)}`, celsius, battery_percent: percentage, createdAt: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1e3).toISOString(), updatedAt: (/* @__PURE__ */ new Date()).toISOString(), state: percentage > 70 ? "latest" : percentage > 30 ? "lateup1" : "lateup2" }; } function generateMockDevice(groupIndex, deviceIndex, groupName) { const psn = generatePSN(groupIndex, deviceIndex); const isOnline = Math.random() > 0.3; const hasVideo = Math.random() > 0.4; const isCloud = Math.random() > 0.5; const isParking = Math.random() > 0.8; const now = /* @__PURE__ */ new Date(); const regDate = new Date(now.getTime() - Math.random() * 365 * 24 * 60 * 60 * 1e3); const loginDate = isOnline ? new Date(now.getTime() - Math.random() * 24 * 60 * 60 * 1e3) : ( // Last 24 hours for online new Date(now.getTime() - Math.random() * 30 * 24 * 60 * 60 * 1e3) ); return { valid: "valid", psn, model: MOCK_DEVICE_MODELS[Math.floor(Math.random() * MOCK_DEVICE_MODELS.length)], active: isOnline ? "on" : "off", dev_name: `${groupName.split(" ")[0]}-${(deviceIndex + 1).toString().padStart(3, "0")}`, battery: Math.random() > 0.2 ? generateBatteryInfo() : void 0, // 80% have battery info lb_server_name: `mock-lb-${Math.floor(Math.random() * 10)}`, lb_http_port: 80, lb_rtmp_port: 1935, share_video: hasVideo ? "on" : "off", share_audio: hasVideo ? Math.random() > 0.5 ? "on" : "off" : "off", share_dev_name: "on", share_gps: isOnline ? "on" : "off", agree_gps: "on", fw_ver: `${Math.floor(Math.random() * 3) + 1}.${Math.floor(Math.random() * 10)}.${Math.floor(Math.random() * 100)}`, upload_server: isCloud ? `cloud-upload-${Math.floor(Math.random() * 5)}.fleeta.io` : void 0, upload_port: isCloud ? 443 : void 0, lang: "eng", mode: isParking ? "1" : "0", communication_identifier: COMM_TYPES[Math.floor(Math.random() * COMM_TYPES.length)], temperature_level: Math.floor(Math.random() * 5) + 1, sensitivity_level: Math.floor(Math.random() * 5) + 1, dms_type: "standard", dms_version: "1.0.0", reg_date: regDate.toISOString(), login_date: loginDate.toISOString(), iot_conn: isOnline ? "on" : "off", reg_category: isCloud ? "cloud" : "wifi", continentCode: "AS", countryCode: "KR", ip: `192.168.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`, liveview_rating: Math.floor(Math.random() * 5) + 1, regInfoUpdateDT: (/* @__PURE__ */ new Date()).toISOString(), countryCodeUpdateDT: (/* @__PURE__ */ new Date()).toISOString(), profile_img: Math.random() > 0.7 ? `https://api.dicebear.com/7.x/identicon/svg?seed=${psn}` : void 0, profile_img_v2: Math.random() > 0.7 ? `https://api.dicebear.com/7.x/avataaars/svg?seed=${psn}` : void 0, cldn: `cldn_${psn.toLowerCase()}`, ap_ssid: isCloud ? void 0 : `MockWiFi_${deviceIndex}`, ap_pw: isCloud ? void 0 : `mock_pass_${deviceIndex}`, require_time_sync: Math.random() > 0.5 ? "on" : "off" }; } function generatePureMockDeviceList() { const mockDevices = []; for (let groupIndex = 0; groupIndex < MOCK_CONFIG.GROUPS_COUNT; groupIndex++) { const groupName = MOCK_GROUP_NAMES[groupIndex]; const groupManagementID = `MOCK_GROUP_${(groupIndex + 1).toString().padStart(3, "0")}`; const groupRegDT = new Date(Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1e3).toISOString(); for (let deviceIndex = 0; deviceIndex < MOCK_CONFIG.DEVICES_PER_GROUP; deviceIndex++) { const device = generateMockDevice(groupIndex, deviceIndex, groupName); const deviceListItem = { groupManagementID, groupName, groupRegDT, device }; mockDevices.push(deviceListItem); } } console.log("๐ŸŽญ [MockAPI] Generated pure mock devices:", { totalDevices: mockDevices.length, groupsCount: MOCK_CONFIG.GROUPS_COUNT, devicesPerGroup: MOCK_CONFIG.DEVICES_PER_GROUP }); return mockDevices; } async function getDeviceList() { console.log("๐Ÿ”€ [MockAPI] Starting combined mock + real device list..."); let mockDevices = []; let realDevices = []; try { mockDevices = generatePureMockDeviceList(); console.log(`๐ŸŽญ [MockAPI] Generated ${mockDevices.length} mock devices`); } catch (error) { console.error("โŒ [MockAPI] Mock data generation failed:", error); } if (isAuthConfigured()) { try { console.log("๐Ÿ“ก [MockAPI] Fetching real devices..."); const realResponse = await getDeviceList$1(); if (realResponse.resultcode === "BC_ERR_OK") { realDevices = realResponse.deviceListInfo || []; console.log(`โœ… [MockAPI] Got ${realDevices.length} real devices`); } else { console.warn("โš ๏ธ [MockAPI] Real API returned error:", realResponse.message); } } catch (error) { console.error("โŒ [MockAPI] Real API failed:", error); } } else { console.log("โš ๏ธ [MockAPI] Authentication not configured, using mock data only"); } const realPsns = new Set(realDevices.map((d) => d.device.psn)); const filteredMock = mockDevices.filter((d) => !realPsns.has(d.device.psn)); const combinedDevices = [...realDevices, ...filteredMock]; console.log("๐Ÿ”€ [MockAPI] Data combination completed:", { mockDevices: mockDevices.length, realDevices: realDevices.length, filteredMock: filteredMock.length, combinedDevices: combinedDevices.length }); const { groups, statistics } = processDeviceListData(combinedDevices); console.log("๐Ÿ“Š [MockAPI] Grouping and statistics completed:", { groups: groups.length, totalStats: statistics.total, onlineStats: statistics.online }); return { resultcode: "BC_ERR_OK", message: "Combined mock and real data with grouping", deviceCount: combinedDevices.length, deviceLimitCount: 1e3, sharedEventMap: "on", deviceListInfo: combinedDevices, groupedData: { groups, statistics } }; } const DEVICE_API_VERSION = "1.0.0"; const DEVICE_API_NAME = "BlackVue Fleeta Device List API"; const LIB_VERSION = "1.0.6"; const LIB_NAME = "FleetA Library"; const index = { version: LIB_VERSION, name: LIB_NAME }; export { API_MODULE_NAME, API_MODULE_VERSION, AUTH_MODULE_NAME, AUTH_MODULE_VERSION, COMMUNICATION_TYPE_NAMES, DEVICE_API_NAME, DEVICE_API_VERSION, DEVICE_LIST_ERROR_MESSAGES, DEVICE_MODE_NAMES, DEVICE_STATUS_NAMES, LIB_NAME, LIB_VERSION, index as default, getApiEndpoint, getApiEndpointConfig, getApiGateway, getAuthConfigFromStore, getAuthErrorMessage, getAuthHeaders, getDeviceList$1 as getDeviceList, getEndpointErrorMessage, getIotApiGateway, getDeviceList as getMockDeviceList, isApiEndpointConfigured, isAuthConfigValid, isAuthConfigured, isDeviceApiReady, login, logout, resetPassword, useApiEndpointStore, useAuthStore, validateApiEndpoints }; //# sourceMappingURL=index.esm.js.map