feat(smart-app): implement complete mobile app MVP

- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
This commit is contained in:
Eric FELIXINE
2026-06-01 18:00:35 -04:00
parent 08ca495bde
commit e30ae8ed09
35578 changed files with 3703534 additions and 43 deletions

View File

@@ -0,0 +1,15 @@
export type Release = {
stable: string;
candidate?: string;
changelogUrl: string;
diffUrl: string;
};
/**
* Checks via GitHub API if there is a newer stable React Native release and,
* if it exists, returns the release data.
*
* If the latest release is not newer or if it's a prerelease, the function
* will return undefined.
*/
export default function getLatestRelease(name: string, currentVersion: string): Promise<Release | undefined>;
//# sourceMappingURL=getLatestRelease.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getLatestRelease.d.ts","sourceRoot":"","sources":["../../src/releaseChecker/getLatestRelease.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,OAAO,GAAG;IAEpB,MAAM,EAAE,MAAM,CAAC;IAEf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA0BF;;;;;;GAMG;AACH,wBAA8B,gBAAgB,CAC5C,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAwC9B"}

View File

@@ -0,0 +1,126 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = getLatestRelease;
function _semver() {
const data = _interopRequireDefault(require("semver"));
_semver = function () {
return data;
};
return data;
}
var _cacheManager = _interopRequireDefault(require("../cacheManager"));
var _fetch = require("../fetch");
var _logger = _interopRequireDefault(require("../logger"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function isDiffPurgeEntry(data) {
var _data$commit, _data$commit2;
return [data.name, data.zipball_url, data.tarball_url, (_data$commit = data.commit) === null || _data$commit === void 0 ? void 0 : _data$commit.sha, (_data$commit2 = data.commit) === null || _data$commit2 === void 0 ? void 0 : _data$commit2.url, data.node_id].indexOf(false) === -1;
}
/**
* Checks via GitHub API if there is a newer stable React Native release and,
* if it exists, returns the release data.
*
* If the latest release is not newer or if it's a prerelease, the function
* will return undefined.
*/
async function getLatestRelease(name, currentVersion) {
_logger.default.debug('Checking for a newer version of React Native');
try {
_logger.default.debug(`Current version: ${currentVersion}`);
// if the version is a 1000.0.0 version or 0.0.0, we want to bail
// since they are nightlies or unreleased versions
if (currentVersion.includes('1000.0.0') || currentVersion.includes('0.0.0')) {
return;
}
const cachedLatest = _cacheManager.default.get(name, 'latestVersion');
if (cachedLatest) {
_logger.default.debug(`Cached release version: ${cachedLatest}`);
}
_logger.default.debug('Checking for newer releases on GitHub');
const eTag = _cacheManager.default.get(name, 'eTag');
const {
stable,
candidate
} = await getLatestRnDiffPurgeVersion(name, eTag);
_logger.default.debug(`Latest release: ${stable} (${candidate})`);
if (_semver().default.compare(stable, currentVersion) >= 0) {
return {
stable,
candidate,
changelogUrl: buildChangelogUrl(stable),
diffUrl: buildDiffUrl(currentVersion)
};
}
} catch (e) {
_logger.default.debug('Something went wrong with remote version checking, moving on');
_logger.default.debug(e);
}
return undefined;
}
function buildChangelogUrl(version) {
return `https://github.com/facebook/react-native/releases/tag/v${version}`;
}
function buildDiffUrl(version) {
return `https://react-native-community.github.io/upgrade-helper/?from=${version}`;
}
/**
* Returns the most recent React Native version available to upgrade to.
*/
async function getLatestRnDiffPurgeVersion(name, eTag) {
const options = {
// https://developer.github.com/v3/#user-agent-required
headers: {
'User-Agent': 'React-Native-CLI'
}
};
if (eTag) {
options.headers['If-None-Match'] = eTag;
}
const {
data,
status,
headers
} = await (0, _fetch.fetch)('https://api.github.com/repos/react-native-community/rn-diff-purge/tags', options);
const result = {
stable: '0.0.0'
};
// Remote is newer.
if (status === 200) {
const body = data.filter(isDiffPurgeEntry);
const eTagHeader = headers.get('eTag');
for (let {
name: version
} of body) {
if (!result.candidate && version.includes('-rc')) {
result.candidate = version.substring(8);
continue;
}
if (!version.includes('-rc')) {
result.stable = version.substring(8);
if (eTagHeader) {
_logger.default.debug(`Saving ${eTagHeader} to cache`);
_cacheManager.default.set(name, 'eTag', eTagHeader);
_cacheManager.default.set(name, 'latestVersion', result.stable);
}
return result;
}
}
return result;
}
// Cache is still valid.
if (status === 304) {
result.stable = _cacheManager.default.get(name, 'latestVersion') ?? result.stable;
}
// Should be returned only if something went wrong.
return result;
}
//# sourceMappingURL=getLatestRelease.ts.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import { SemVer } from 'semver';
import { Release } from './getLatestRelease';
/**
* Logs out a message if the user's version is behind a stable version of React Native
*/
export declare function logIfUpdateAvailable(projectRoot: string): Promise<void>;
type Update = {
upgrade?: Release;
current: string;
name: string;
};
/**
* Finds the latest stables version of React Native > current version
*/
export declare function latest(projectRoot: string): Promise<Update | undefined>;
/**
* Gets the current project's version parsed as Semver
*/
export declare function current(projectRoot: string): SemVer | undefined;
export {};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/releaseChecker/index.ts"],"names":[],"mappings":"AACA,OAAe,EAAC,MAAM,EAAC,MAAM,QAAQ,CAAC;AAKtC,OAAyB,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAS7D;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E;AAED,KAAK,MAAM,GAAG;IAEZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,OAAO,EAAE,MAAM,CAAC;IAEhB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;GAEG;AACH,wBAAsB,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA0B7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU/D"}

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.current = current;
exports.latest = latest;
exports.logIfUpdateAvailable = logIfUpdateAvailable;
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _semver() {
const data = _interopRequireDefault(require("semver"));
_semver = function () {
return data;
};
return data;
}
var _errors = require("../errors");
var _logger = _interopRequireDefault(require("../logger"));
var _resolveNodeModuleDir = _interopRequireDefault(require("../resolveNodeModuleDir"));
var _getLatestRelease = _interopRequireDefault(require("./getLatestRelease"));
var _printNewRelease = _interopRequireDefault(require("./printNewRelease"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const getReactNativeVersion = projectRoot => {
var _require;
return (_require = require(_path().default.join((0, _resolveNodeModuleDir.default)(projectRoot, 'react-native'), 'package.json'))) === null || _require === void 0 ? void 0 : _require.version;
};
/**
* Logs out a message if the user's version is behind a stable version of React Native
*/
async function logIfUpdateAvailable(projectRoot) {
const versions = await latest(projectRoot);
if (!(versions === null || versions === void 0 ? void 0 : versions.upgrade)) {
return;
}
if (_semver().default.gt(versions.upgrade.stable, versions.current)) {
(0, _printNewRelease.default)(versions.name, versions.upgrade, versions.current);
}
}
/**
* Finds the latest stables version of React Native > current version
*/
async function latest(projectRoot) {
try {
const currentVersion = getReactNativeVersion(projectRoot);
if (!currentVersion) {
return;
}
const {
name
} = require(_path().default.join(projectRoot, 'package.json'));
const upgrade = await (0, _getLatestRelease.default)(name, currentVersion);
if (upgrade) {
return {
name,
current: currentVersion,
upgrade
};
}
} catch (e) {
// We let the flow continue as this component is not vital for the rest of
// the CLI.
_logger.default.debug('Cannot detect current version of React Native, ' + 'skipping check for a newer release');
_logger.default.debug(e);
}
return;
}
/**
* Gets the current project's version parsed as Semver
*/
function current(projectRoot) {
try {
const found = _semver().default.parse(getReactNativeVersion(projectRoot));
if (found) {
return found;
}
} catch {
throw new _errors.UnknownProjectError(projectRoot);
}
return undefined;
}
//# sourceMappingURL=index.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["getReactNativeVersion","projectRoot","require","path","join","resolveNodeModuleDir","version","logIfUpdateAvailable","versions","latest","upgrade","semver","gt","stable","current","printNewRelease","name","currentVersion","getLatestRelease","e","logger","debug","found","parse","UnknownProjectError","undefined"],"sources":["../../src/releaseChecker/index.ts"],"sourcesContent":["import path from 'path';\nimport semver, {SemVer} from 'semver';\n\nimport {UnknownProjectError} from '../errors';\nimport logger from '../logger';\nimport resolveNodeModuleDir from '../resolveNodeModuleDir';\nimport getLatestRelease, {Release} from './getLatestRelease';\nimport printNewRelease from './printNewRelease';\n\nconst getReactNativeVersion = (projectRoot: string): string | undefined =>\n require(path.join(\n resolveNodeModuleDir(projectRoot, 'react-native'),\n 'package.json',\n ))?.version;\n\n/**\n * Logs out a message if the user's version is behind a stable version of React Native\n */\nexport async function logIfUpdateAvailable(projectRoot: string): Promise<void> {\n const versions = await latest(projectRoot);\n if (!versions?.upgrade) {\n return;\n }\n if (semver.gt(versions.upgrade.stable, versions.current)) {\n printNewRelease(versions.name, versions.upgrade, versions.current);\n }\n}\n\ntype Update = {\n // Only populated if an upgrade is available\n upgrade?: Release;\n // The project's package's current version\n current: string;\n // The project's package's name\n name: string;\n};\n\n/**\n * Finds the latest stables version of React Native > current version\n */\nexport async function latest(projectRoot: string): Promise<Update | undefined> {\n try {\n const currentVersion = getReactNativeVersion(projectRoot);\n if (!currentVersion) {\n return;\n }\n const {name} = require(path.join(projectRoot, 'package.json'));\n const upgrade = await getLatestRelease(name, currentVersion);\n\n if (upgrade) {\n return {\n name,\n current: currentVersion,\n upgrade,\n };\n }\n } catch (e) {\n // We let the flow continue as this component is not vital for the rest of\n // the CLI.\n logger.debug(\n 'Cannot detect current version of React Native, ' +\n 'skipping check for a newer release',\n );\n logger.debug(e as any);\n }\n return;\n}\n\n/**\n * Gets the current project's version parsed as Semver\n */\nexport function current(projectRoot: string): SemVer | undefined {\n try {\n const found = semver.parse(getReactNativeVersion(projectRoot));\n if (found) {\n return found;\n }\n } catch {\n throw new UnknownProjectError(projectRoot);\n }\n return undefined;\n}\n"],"mappings":";;;;;;;;AAAA;EAAA;EAAA;IAAA;EAAA;EAAA;AAAA;AACA;EAAA;EAAA;IAAA;EAAA;EAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAAgD;AAEhD,MAAMA,qBAAqB,GAAIC,WAAmB;EAAA;EAAA,mBAChDC,OAAO,CAACC,eAAI,CAACC,IAAI,CACf,IAAAC,6BAAoB,EAACJ,WAAW,EAAE,cAAc,CAAC,EACjD,cAAc,CACf,CAAC,6CAHF,SAGIK,OAAO;AAAA;;AAEb;AACA;AACA;AACO,eAAeC,oBAAoB,CAACN,WAAmB,EAAiB;EAC7E,MAAMO,QAAQ,GAAG,MAAMC,MAAM,CAACR,WAAW,CAAC;EAC1C,IAAI,EAACO,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAEE,OAAO,GAAE;IACtB;EACF;EACA,IAAIC,iBAAM,CAACC,EAAE,CAACJ,QAAQ,CAACE,OAAO,CAACG,MAAM,EAAEL,QAAQ,CAACM,OAAO,CAAC,EAAE;IACxD,IAAAC,wBAAe,EAACP,QAAQ,CAACQ,IAAI,EAAER,QAAQ,CAACE,OAAO,EAAEF,QAAQ,CAACM,OAAO,CAAC;EACpE;AACF;AAWA;AACA;AACA;AACO,eAAeL,MAAM,CAACR,WAAmB,EAA+B;EAC7E,IAAI;IACF,MAAMgB,cAAc,GAAGjB,qBAAqB,CAACC,WAAW,CAAC;IACzD,IAAI,CAACgB,cAAc,EAAE;MACnB;IACF;IACA,MAAM;MAACD;IAAI,CAAC,GAAGd,OAAO,CAACC,eAAI,CAACC,IAAI,CAACH,WAAW,EAAE,cAAc,CAAC,CAAC;IAC9D,MAAMS,OAAO,GAAG,MAAM,IAAAQ,yBAAgB,EAACF,IAAI,EAAEC,cAAc,CAAC;IAE5D,IAAIP,OAAO,EAAE;MACX,OAAO;QACLM,IAAI;QACJF,OAAO,EAAEG,cAAc;QACvBP;MACF,CAAC;IACH;EACF,CAAC,CAAC,OAAOS,CAAC,EAAE;IACV;IACA;IACAC,eAAM,CAACC,KAAK,CACV,iDAAiD,GAC/C,oCAAoC,CACvC;IACDD,eAAM,CAACC,KAAK,CAACF,CAAC,CAAQ;EACxB;EACA;AACF;;AAEA;AACA;AACA;AACO,SAASL,OAAO,CAACb,WAAmB,EAAsB;EAC/D,IAAI;IACF,MAAMqB,KAAK,GAAGX,iBAAM,CAACY,KAAK,CAACvB,qBAAqB,CAACC,WAAW,CAAC,CAAC;IAC9D,IAAIqB,KAAK,EAAE;MACT,OAAOA,KAAK;IACd;EACF,CAAC,CAAC,MAAM;IACN,MAAM,IAAIE,2BAAmB,CAACvB,WAAW,CAAC;EAC5C;EACA,OAAOwB,SAAS;AAClB"}

View File

@@ -0,0 +1,6 @@
import { Release } from './getLatestRelease';
/**
* Notifies the user that a newer version of React Native is available.
*/
export default function printNewRelease(name: string, latestRelease: Release, currentVersion: string): void;
//# sourceMappingURL=printNewRelease.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"printNewRelease.d.ts","sourceRoot":"","sources":["../../src/releaseChecker/printNewRelease.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAG3C;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,eAAe,CACrC,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,OAAO,EACtB,cAAc,EAAE,MAAM,QAcvB"}

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = printNewRelease;
function _chalk() {
const data = _interopRequireDefault(require("chalk"));
_chalk = function () {
return data;
};
return data;
}
var link = _interopRequireWildcard(require("../doclink"));
var _logger = _interopRequireDefault(require("../logger"));
var _cacheManager = _interopRequireDefault(require("../cacheManager"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Notifies the user that a newer version of React Native is available.
*/
function printNewRelease(name, latestRelease, currentVersion) {
_logger.default.info(`React Native v${latestRelease.stable} is now available (your project is running on v${currentVersion}).`);
_logger.default.info(`Changelog: ${_chalk().default.dim.underline(latestRelease.changelogUrl)}`);
_logger.default.info(`Diff: ${_chalk().default.dim.underline(latestRelease.diffUrl)}`);
_logger.default.info(`For more info, check out "${_chalk().default.dim.underline(link.docs('upgrading', 'none'))}".`);
_cacheManager.default.set(name, 'lastChecked', new Date().toISOString());
}
//# sourceMappingURL=printNewRelease.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["printNewRelease","name","latestRelease","currentVersion","logger","info","stable","chalk","dim","underline","changelogUrl","diffUrl","link","docs","cacheManager","set","Date","toISOString"],"sources":["../../src/releaseChecker/printNewRelease.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport * as link from '../doclink';\n\nimport logger from '../logger';\nimport {Release} from './getLatestRelease';\nimport cacheManager from '../cacheManager';\n\n/**\n * Notifies the user that a newer version of React Native is available.\n */\nexport default function printNewRelease(\n name: string,\n latestRelease: Release,\n currentVersion: string,\n) {\n logger.info(\n `React Native v${latestRelease.stable} is now available (your project is running on v${currentVersion}).`,\n );\n logger.info(`Changelog: ${chalk.dim.underline(latestRelease.changelogUrl)}`);\n logger.info(`Diff: ${chalk.dim.underline(latestRelease.diffUrl)}`);\n logger.info(\n `For more info, check out \"${chalk.dim.underline(\n link.docs('upgrading', 'none'),\n )}\".`,\n );\n\n cacheManager.set(name, 'lastChecked', new Date().toISOString());\n}\n"],"mappings":";;;;;;AAAA;EAAA;EAAA;IAAA;EAAA;EAAA;AAAA;AAEA;AAEA;AAEA;AAA2C;AAAA;AAAA;AAE3C;AACA;AACA;AACe,SAASA,eAAe,CACrCC,IAAY,EACZC,aAAsB,EACtBC,cAAsB,EACtB;EACAC,eAAM,CAACC,IAAI,CACR,iBAAgBH,aAAa,CAACI,MAAO,kDAAiDH,cAAe,IAAG,CAC1G;EACDC,eAAM,CAACC,IAAI,CAAE,cAAaE,gBAAK,CAACC,GAAG,CAACC,SAAS,CAACP,aAAa,CAACQ,YAAY,CAAE,EAAC,CAAC;EAC5EN,eAAM,CAACC,IAAI,CAAE,SAAQE,gBAAK,CAACC,GAAG,CAACC,SAAS,CAACP,aAAa,CAACS,OAAO,CAAE,EAAC,CAAC;EAClEP,eAAM,CAACC,IAAI,CACR,6BAA4BE,gBAAK,CAACC,GAAG,CAACC,SAAS,CAC9CG,IAAI,CAACC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAC9B,IAAG,CACN;EAEDC,qBAAY,CAACC,GAAG,CAACd,IAAI,EAAE,aAAa,EAAE,IAAIe,IAAI,EAAE,CAACC,WAAW,EAAE,CAAC;AACjE"}