fleeta-lib
Version:
A comprehensive library for fleet management applications - API, Auth, Device management
1,105 lines (1,104 loc) โข 36.4 kB
JavaScript
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