Files
smart-city-digital-twin-mar…/smart-app-city/frontend/node_modules/hermes-parser/dist/transform/astNodeMutationHelpers.js.flow
Eric FELIXINE e30ae8ed09 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
2026-06-01 18:00:35 -04:00

238 lines
5.7 KiB
Plaintext

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
'use strict';
import type {ESNode} from 'hermes-estree';
import type {VisitorKeysType} from '../traverse/getVisitorKeys';
import {
arrayIsEqual,
removeFromArray,
replaceInArray,
} from './astArrayMutationHelpers';
import {getVisitorKeys, isNode} from '../traverse/getVisitorKeys';
import {SimpleTraverser} from '../traverse/SimpleTraverser';
function getParentKey(
target: ESNode,
parent: ESNode,
visitorKeys?: ?VisitorKeysType,
): $ReadOnly<
| {
type: 'single',
node: ESNode,
key: string,
}
| {
type: 'array',
node: ESNode,
key: string,
targetIndex: number,
},
> {
if (parent == null) {
throw new Error(`Expected parent node to be set on "${target.type}"`);
}
for (const key of getVisitorKeys(parent, visitorKeys)) {
if (
isNode(
// $FlowExpectedError[prop-missing]
parent[key],
)
) {
if (parent[key] === target) {
return {type: 'single', node: parent, key};
}
} else if (Array.isArray(parent[key])) {
for (let i = 0; i < parent[key].length; i += 1) {
const current = parent[key][i];
if (current === target) {
return {type: 'array', node: parent, key, targetIndex: i};
}
}
}
}
// this shouldn't happen ever
throw new Error(
`Expected to find the ${target.type} as a direct child of the ${parent.type}.`,
);
}
/**
* Replace a node with a new node within an AST (via the parent pointer).
*/
export function replaceNodeOnParent(
originalNode: ESNode,
originalNodeParent: ESNode,
nodeToReplaceWith: ESNode,
visitorKeys?: ?VisitorKeysType,
): void {
const replacementParent = getParentKey(
originalNode,
originalNodeParent,
visitorKeys,
);
const parent = replacementParent.node;
if (replacementParent.type === 'array') {
// $FlowExpectedError[prop-missing]
parent[replacementParent.key] = replaceInArray(
// $FlowExpectedError[prop-missing]
parent[replacementParent.key],
replacementParent.targetIndex,
[nodeToReplaceWith],
);
} else {
// $FlowExpectedError[prop-missing]
parent[replacementParent.key] = nodeToReplaceWith;
}
}
/**
* Remove a node from the AST its connected to (via the parent pointer).
*/
export function removeNodeOnParent(
originalNode: ESNode,
originalNodeParent: ESNode,
visitorKeys?: ?VisitorKeysType,
): void {
const replacementParent = getParentKey(
originalNode,
originalNodeParent,
visitorKeys,
);
const parent = replacementParent.node;
if (replacementParent.type === 'array') {
// $FlowExpectedError[prop-missing]
parent[replacementParent.key] = removeFromArray(
// $FlowExpectedError[prop-missing]
parent[replacementParent.key],
replacementParent.targetIndex,
);
} else {
// $FlowExpectedError[prop-missing]
parent[replacementParent.key] = null;
}
}
/**
* Corrects the parent pointers in direct children of the given node.
*/
export function setParentPointersInDirectChildren(
node: ESNode,
visitorKeys?: ?VisitorKeysType,
): void {
for (const key: $FlowFixMe of getVisitorKeys(node, visitorKeys)) {
if (isNode(node[key])) {
node[key].parent = node;
} else if (Array.isArray(node[key])) {
for (const child of node[key]) {
child.parent = node;
}
}
}
}
/**
* Traverses the entire subtree to ensure the parent pointers are set correctly.
*/
export function updateAllParentPointers(
node: ESNode,
visitorKeys?: ?VisitorKeysType,
) {
SimpleTraverser.traverse(node, {
enter(node, parent) {
// $FlowExpectedError[cannot-write]
node.parent = parent;
},
leave() {},
visitorKeys,
});
}
/**
* Clone node and add new props.
*
* This will only create a new object if the overrides actually result in a change.
*/
export function nodeWith<T: ESNode>(
node: T,
overrideProps: Partial<T>,
visitorKeys?: ?VisitorKeysType,
): T {
// Check if this will actually result in a change, maintaining referential equality is important.
const willBeUnchanged = Object.entries(overrideProps).every(
([key, value]) => {
if (Array.isArray(value)) {
// $FlowExpectedError[prop-missing]
return Array.isArray(node[key])
? arrayIsEqual(node[key], value)
: false;
}
// $FlowExpectedError[prop-missing]
return node[key] === value;
},
);
if (willBeUnchanged) {
return node;
}
// Create new node.
// $FlowExpectedError[cannot-spread-interface]
const newNode: T = {
...node,
...overrideProps,
};
// Ensure parent pointers are correctly set within this nodes children.
setParentPointersInDirectChildren(newNode, visitorKeys);
return newNode;
}
/**
* Shallow clones node, providing a new reference for an existing node.
*/
export function shallowCloneNode<T: ESNode>(
node: T,
visitorKeys?: ?VisitorKeysType,
): T {
// $FlowExpectedError[cannot-spread-interface]
const newNode: T = {...node};
// Ensure parent pointers are correctly set within this nodes children.
setParentPointersInDirectChildren(newNode, visitorKeys);
return newNode;
}
/**
* Deeply clones node and its entire tree.
*/
export function deepCloneNode<T: ESNode>(
node: T,
visitorKeys?: ?VisitorKeysType,
): T {
const clone: T = JSON.parse(
JSON.stringify(node, (key, value) => {
// null out parent pointers
if (key === 'parent') {
return undefined;
}
return value;
}),
);
updateAllParentPointers(clone, visitorKeys);
return clone;
}