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,31 @@
"use strict";
const { GENERATED_ORDER, iterationOrderToString } = require("./constants");
const invariant = require("invariant");
class AbstractConsumer {
constructor(sourceMap) {
this._sourceMap = sourceMap;
}
originalPositionFor(generatedPosition) {
invariant(false, "Not implemented");
}
generatedMappings() {
invariant(false, "Not implemented");
}
eachMapping(callback, context = null, order = GENERATED_ORDER) {
invariant(
order === GENERATED_ORDER,
`Iteration order not implemented: ${iterationOrderToString(order)}`
);
for (const mapping of this.generatedMappings()) {
callback.call(context, mapping);
}
}
get file() {
return this._sourceMap.file;
}
sourceContentFor(source, nullOnMissing) {
invariant(false, "Not implemented");
}
}
module.exports = AbstractConsumer;

View File

@@ -0,0 +1,67 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {
GeneratedPositionLookup,
IConsumer,
IterationOrder,
Mapping,
SourcePosition,
} from './types.flow';
const {GENERATED_ORDER, iterationOrderToString} = require('./constants');
const invariant = require('invariant');
// Implementation details shared between MappingsConsumer and SectionsConsumer
class AbstractConsumer implements IConsumer {
_sourceMap: {+file?: string, ...};
constructor(sourceMap: {+file?: string, ...}) {
this._sourceMap = sourceMap;
}
originalPositionFor(
generatedPosition: GeneratedPositionLookup,
): SourcePosition {
invariant(false, 'Not implemented');
}
generatedMappings(): Iterable<Mapping> {
invariant(false, 'Not implemented');
}
eachMapping(
callback: (mapping: Mapping) => mixed,
context?: mixed = null,
order?: IterationOrder = GENERATED_ORDER,
): void {
invariant(
order === GENERATED_ORDER,
`Iteration order not implemented: ${iterationOrderToString(order)}`,
);
for (const mapping of this.generatedMappings()) {
callback.call(context, mapping);
}
}
// flowlint-next-line unsafe-getters-setters:off
get file(): ?string {
return this._sourceMap.file;
}
sourceContentFor(source: string, nullOnMissing: true): ?string {
invariant(false, 'Not implemented');
}
}
module.exports = AbstractConsumer;

View File

@@ -0,0 +1,35 @@
"use strict";
const {
GENERATED_ORDER,
GREATEST_LOWER_BOUND,
LEAST_UPPER_BOUND,
ORIGINAL_ORDER,
} = require("./constants");
const createConsumer = require("./createConsumer");
class DelegatingConsumer {
static GENERATED_ORDER = GENERATED_ORDER;
static ORIGINAL_ORDER = ORIGINAL_ORDER;
static GREATEST_LOWER_BOUND = GREATEST_LOWER_BOUND;
static LEAST_UPPER_BOUND = LEAST_UPPER_BOUND;
constructor(sourceMap) {
this._rootConsumer = createConsumer(sourceMap);
return this._rootConsumer;
}
originalPositionFor(generatedPosition) {
return this._rootConsumer.originalPositionFor(generatedPosition);
}
generatedMappings() {
return this._rootConsumer.generatedMappings();
}
eachMapping(callback, context, order) {
return this._rootConsumer.eachMapping(callback, context, order);
}
get file() {
return this._rootConsumer.file;
}
sourceContentFor(source, nullOnMissing) {
return this._rootConsumer.sourceContentFor(source, nullOnMissing);
}
}
module.exports = DelegatingConsumer;

View File

@@ -0,0 +1,78 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {MixedSourceMap} from '../source-map';
import type {LookupBias} from './constants.js';
import type {
GeneratedPositionLookup,
IConsumer,
IterationOrder,
Mapping,
SourcePosition,
} from './types.flow';
const {
GENERATED_ORDER,
GREATEST_LOWER_BOUND,
LEAST_UPPER_BOUND,
ORIGINAL_ORDER,
} = require('./constants');
const createConsumer = require('./createConsumer');
/**
* A source map consumer that supports both "basic" and "indexed" source maps.
* Uses `MappingsConsumer` and `SectionsConsumer` under the hood (via
* `createConsumer`).
*/
class DelegatingConsumer implements IConsumer {
static +GENERATED_ORDER: IterationOrder = GENERATED_ORDER;
static +ORIGINAL_ORDER: IterationOrder = ORIGINAL_ORDER;
static +GREATEST_LOWER_BOUND: LookupBias = GREATEST_LOWER_BOUND;
static +LEAST_UPPER_BOUND: LookupBias = LEAST_UPPER_BOUND;
_rootConsumer: IConsumer;
// $FlowFixMe[incompatible-return]
constructor(sourceMap: MixedSourceMap): IConsumer {
this._rootConsumer = createConsumer(sourceMap);
return this._rootConsumer;
}
originalPositionFor(
generatedPosition: GeneratedPositionLookup,
): SourcePosition {
return this._rootConsumer.originalPositionFor(generatedPosition);
}
generatedMappings(): Iterable<Mapping> {
return this._rootConsumer.generatedMappings();
}
eachMapping(
callback: (mapping: Mapping) => mixed,
context?: mixed,
order?: IterationOrder,
): void {
return this._rootConsumer.eachMapping(callback, context, order);
}
// flowlint-next-line unsafe-getters-setters:off
get file(): ?string {
return this._rootConsumer.file;
}
sourceContentFor(source: string, nullOnMissing: true): ?string {
return this._rootConsumer.sourceContentFor(source, nullOnMissing);
}
}
module.exports = DelegatingConsumer;

View File

@@ -0,0 +1,177 @@
"use strict";
const AbstractConsumer = require("./AbstractConsumer");
const {
EMPTY_POSITION,
FIRST_COLUMN,
FIRST_LINE,
GREATEST_LOWER_BOUND,
lookupBiasToString,
} = require("./constants");
const normalizeSourcePath = require("./normalizeSourcePath");
const { greatestLowerBound } = require("./search");
const invariant = require("invariant");
const { add, add0, get0, inc, sub } = require("ob1");
const { decode: decodeVlq } = require("vlq");
class MappingsConsumer extends AbstractConsumer {
constructor(sourceMap) {
super(sourceMap);
this._sourceMap = sourceMap;
this._decodedMappings = null;
this._normalizedSources = null;
}
originalPositionFor(generatedPosition) {
const { line, column } = generatedPosition;
if (line == null || column == null) {
return {
...EMPTY_POSITION,
};
}
if (generatedPosition.bias != null) {
invariant(
generatedPosition.bias === GREATEST_LOWER_BOUND,
`Unimplemented lookup bias: ${lookupBiasToString(
generatedPosition.bias
)}`
);
}
const mappings = this._decodeAndCacheMappings();
const index = greatestLowerBound(
mappings,
{
line,
column,
},
(position, mapping) => {
if (position.line === mapping.generatedLine) {
return get0(sub(position.column, mapping.generatedColumn));
}
return get0(sub(position.line, mapping.generatedLine));
}
);
if (
index != null &&
mappings[index].generatedLine === generatedPosition.line
) {
const mapping = mappings[index];
return {
source: mapping.source,
name: mapping.name,
line: mapping.originalLine,
column: mapping.originalColumn,
};
}
return {
...EMPTY_POSITION,
};
}
*_decodeMappings() {
let generatedLine = FIRST_LINE;
let generatedColumn = FIRST_COLUMN;
let originalLine = FIRST_LINE;
let originalColumn = FIRST_COLUMN;
let nameIndex = add0(0);
let sourceIndex = add0(0);
const normalizedSources = this._normalizeAndCacheSources();
const { mappings: mappingsRaw, names } = this._sourceMap;
let next;
const vlqCache = new Map();
for (let i = 0; i < mappingsRaw.length; i = next) {
switch (mappingsRaw[i]) {
case ";":
generatedLine = inc(generatedLine);
generatedColumn = FIRST_COLUMN;
case ",":
next = i + 1;
continue;
}
findNext: for (next = i + 1; next < mappingsRaw.length; ++next) {
switch (mappingsRaw[next]) {
case ";":
case ",":
break findNext;
}
}
const mappingRaw = mappingsRaw.slice(i, next);
let decodedVlqValues;
if (vlqCache.has(mappingRaw)) {
decodedVlqValues = vlqCache.get(mappingRaw);
} else {
decodedVlqValues = decodeVlq(mappingRaw);
vlqCache.set(mappingRaw, decodedVlqValues);
}
invariant(Array.isArray(decodedVlqValues), "Decoding VLQ tuple failed");
const [
generatedColumnDelta,
sourceIndexDelta,
originalLineDelta,
originalColumnDelta,
nameIndexDelta,
] = decodedVlqValues;
decodeVlq(mappingRaw);
invariant(generatedColumnDelta != null, "Invalid generated column delta");
generatedColumn = add(generatedColumn, generatedColumnDelta);
const mapping = {
generatedLine,
generatedColumn,
source: null,
name: null,
originalLine: null,
originalColumn: null,
};
if (sourceIndexDelta != null) {
sourceIndex = add(sourceIndex, sourceIndexDelta);
mapping.source = normalizedSources[get0(sourceIndex)];
invariant(originalLineDelta != null, "Invalid original line delta");
invariant(originalColumnDelta != null, "Invalid original column delta");
originalLine = add(originalLine, originalLineDelta);
originalColumn = add(originalColumn, originalColumnDelta);
mapping.originalLine = originalLine;
mapping.originalColumn = originalColumn;
if (nameIndexDelta != null) {
nameIndex = add(nameIndex, nameIndexDelta);
mapping.name = names[get0(nameIndex)];
}
}
yield mapping;
}
}
_normalizeAndCacheSources() {
if (!this._normalizedSources) {
this._normalizedSources = this._sourceMap.sources.map((source) =>
normalizeSourcePath(source, this._sourceMap)
);
}
return this._normalizedSources;
}
_decodeAndCacheMappings() {
if (!this._decodedMappings) {
this._decodedMappings = [...this._decodeMappings()];
}
return this._decodedMappings;
}
generatedMappings() {
return this._decodeAndCacheMappings();
}
_indexOfSource(source) {
const idx = this._normalizeAndCacheSources().indexOf(
normalizeSourcePath(source, this._sourceMap)
);
if (idx === -1) {
return null;
}
return add0(idx);
}
sourceContentFor(source, nullOnMissing) {
const { sourcesContent } = this._sourceMap;
if (!sourcesContent) {
return null;
}
const idx = this._indexOfSource(source);
if (idx == null) {
return null;
}
return sourcesContent[get0(idx)] ?? null;
}
}
module.exports = MappingsConsumer;

View File

@@ -0,0 +1,220 @@
/**
* 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
* @format
* @oncall react_native
*/
'use strict';
import type {BasicSourceMap} from '../source-map';
import type {
GeneratedPositionLookup,
IConsumer,
Mapping,
SourcePosition,
} from './types.flow';
import type {Number0} from 'ob1';
const AbstractConsumer = require('./AbstractConsumer');
const {
EMPTY_POSITION,
FIRST_COLUMN,
FIRST_LINE,
GREATEST_LOWER_BOUND,
lookupBiasToString,
} = require('./constants');
const normalizeSourcePath = require('./normalizeSourcePath');
const {greatestLowerBound} = require('./search');
const invariant = require('invariant');
const {add, add0, get0, inc, sub} = require('ob1');
const {decode: decodeVlq} = require('vlq');
/**
* A source map consumer that supports "basic" source maps (that have a
* `mappings` field and no sections).
*/
class MappingsConsumer extends AbstractConsumer implements IConsumer {
_sourceMap: BasicSourceMap;
_decodedMappings: ?$ReadOnlyArray<Mapping>;
_normalizedSources: ?$ReadOnlyArray<string>;
constructor(sourceMap: BasicSourceMap) {
super(sourceMap);
this._sourceMap = sourceMap;
this._decodedMappings = null;
this._normalizedSources = null;
}
originalPositionFor(
generatedPosition: GeneratedPositionLookup,
): SourcePosition {
const {line, column} = generatedPosition;
if (line == null || column == null) {
return {...EMPTY_POSITION};
}
if (generatedPosition.bias != null) {
invariant(
generatedPosition.bias === GREATEST_LOWER_BOUND,
`Unimplemented lookup bias: ${lookupBiasToString(
// $FlowFixMe[incompatible-call]
generatedPosition.bias,
)}`,
);
}
const mappings = this._decodeAndCacheMappings();
const index = greatestLowerBound(
mappings,
{line, column},
(position, mapping) => {
if (position.line === mapping.generatedLine) {
return get0(sub(position.column, mapping.generatedColumn));
}
return get0(sub(position.line, mapping.generatedLine));
},
);
if (
index != null &&
mappings[index].generatedLine === generatedPosition.line
) {
const mapping = mappings[index];
return {
source: mapping.source,
name: mapping.name,
line: mapping.originalLine,
column: mapping.originalColumn,
};
}
return {...EMPTY_POSITION};
}
*_decodeMappings(): Generator<Mapping, void, void> {
let generatedLine = FIRST_LINE;
let generatedColumn = FIRST_COLUMN;
let originalLine = FIRST_LINE;
let originalColumn = FIRST_COLUMN;
let nameIndex = add0(0);
let sourceIndex = add0(0);
const normalizedSources = this._normalizeAndCacheSources();
const {mappings: mappingsRaw, names} = this._sourceMap;
let next;
const vlqCache = new Map<string, any>();
for (let i = 0; i < mappingsRaw.length; i = next) {
switch (mappingsRaw[i]) {
case ';':
generatedLine = inc(generatedLine);
generatedColumn = FIRST_COLUMN;
/* falls through */
case ',':
next = i + 1;
continue;
}
findNext: for (next = i + 1; next < mappingsRaw.length; ++next) {
switch (mappingsRaw[next]) {
case ';':
/* falls through */
case ',':
break findNext;
}
}
const mappingRaw = mappingsRaw.slice(i, next);
let decodedVlqValues;
if (vlqCache.has(mappingRaw)) {
decodedVlqValues = vlqCache.get(mappingRaw);
} else {
decodedVlqValues = decodeVlq(mappingRaw);
vlqCache.set(mappingRaw, decodedVlqValues);
}
invariant(Array.isArray(decodedVlqValues), 'Decoding VLQ tuple failed');
const [
generatedColumnDelta,
sourceIndexDelta,
originalLineDelta,
originalColumnDelta,
nameIndexDelta,
] = decodedVlqValues;
decodeVlq(mappingRaw);
invariant(generatedColumnDelta != null, 'Invalid generated column delta');
generatedColumn = add(generatedColumn, generatedColumnDelta);
const mapping: Mapping = {
generatedLine,
generatedColumn,
source: null,
name: null,
originalLine: null,
originalColumn: null,
};
if (sourceIndexDelta != null) {
sourceIndex = add(sourceIndex, sourceIndexDelta);
mapping.source = normalizedSources[get0(sourceIndex)];
invariant(originalLineDelta != null, 'Invalid original line delta');
invariant(originalColumnDelta != null, 'Invalid original column delta');
originalLine = add(originalLine, originalLineDelta);
originalColumn = add(originalColumn, originalColumnDelta);
mapping.originalLine = originalLine;
mapping.originalColumn = originalColumn;
if (nameIndexDelta != null) {
nameIndex = add(nameIndex, nameIndexDelta);
mapping.name = names[get0(nameIndex)];
}
}
yield mapping;
}
}
_normalizeAndCacheSources(): $ReadOnlyArray<string> {
if (!this._normalizedSources) {
this._normalizedSources = this._sourceMap.sources.map(source =>
normalizeSourcePath(source, this._sourceMap),
);
}
return this._normalizedSources;
}
_decodeAndCacheMappings(): $ReadOnlyArray<Mapping> {
if (!this._decodedMappings) {
this._decodedMappings = [...this._decodeMappings()];
}
return this._decodedMappings;
}
generatedMappings(): Iterable<Mapping> {
return this._decodeAndCacheMappings();
}
_indexOfSource(source: string): ?Number0 {
const idx = this._normalizeAndCacheSources().indexOf(
normalizeSourcePath(source, this._sourceMap),
);
if (idx === -1) {
return null;
}
return add0(idx);
}
sourceContentFor(source: string, nullOnMissing: true): ?string {
const {sourcesContent} = this._sourceMap;
if (!sourcesContent) {
return null;
}
const idx = this._indexOfSource(source);
if (idx == null) {
return null;
}
return sourcesContent[get0(idx)] ?? null;
}
}
module.exports = MappingsConsumer;

View File

@@ -0,0 +1,91 @@
"use strict";
const AbstractConsumer = require("./AbstractConsumer");
const { EMPTY_POSITION, FIRST_COLUMN, FIRST_LINE } = require("./constants");
const createConsumer = require("./createConsumer");
const { subtractOffsetFromPosition } = require("./positionMath");
const { greatestLowerBound } = require("./search");
const { add, add0, get0, get1, sub, sub1 } = require("ob1");
class SectionsConsumer extends AbstractConsumer {
constructor(sourceMap) {
super(sourceMap);
this._consumers = sourceMap.sections.map((section, index) => {
const generatedOffset = {
lines: add0(section.offset.line),
columns: add0(section.offset.column),
};
const consumer = createConsumer(section.map);
return [generatedOffset, consumer];
});
}
originalPositionFor(generatedPosition) {
const [generatedOffset, consumer] =
this._consumerForPosition(generatedPosition) || [];
if (!consumer) {
return {
...EMPTY_POSITION,
};
}
return consumer.originalPositionFor(
subtractOffsetFromPosition(generatedPosition, generatedOffset)
);
}
*generatedMappings() {
for (const [generatedOffset, consumer] of this._consumers) {
let first = true;
for (const mapping of consumer.generatedMappings()) {
if (
first &&
(get1(mapping.generatedLine) > 1 || get0(mapping.generatedColumn) > 0)
) {
yield {
generatedLine: FIRST_LINE,
generatedColumn: FIRST_COLUMN,
source: null,
name: null,
originalLine: null,
originalColumn: null,
};
}
first = false;
yield {
...mapping,
generatedLine: add(mapping.generatedLine, generatedOffset.lines),
generatedColumn: add(
mapping.generatedColumn,
generatedOffset.columns
),
};
}
}
}
_consumerForPosition(generatedPosition) {
const { line, column } = generatedPosition;
if (line == null || column == null) {
return null;
}
const index = greatestLowerBound(
this._consumers,
generatedPosition,
(position, [offset]) => {
const line0 = sub1(line);
const column0 = column;
if (line0 === offset.lines) {
return get0(sub(column0, offset.columns));
}
return get0(sub(line0, offset.lines));
}
);
return index != null ? this._consumers[index] : null;
}
sourceContentFor(source, nullOnMissing) {
for (const [_, consumer] of this._consumers) {
const content = consumer.sourceContentFor(source, nullOnMissing);
if (content != null) {
return content;
}
}
return null;
}
}
module.exports = SectionsConsumer;

View File

@@ -0,0 +1,125 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {IndexMap} from '../source-map';
import type {
GeneratedOffset,
GeneratedPositionLookup,
IConsumer,
Mapping,
SourcePosition,
} from './types.flow';
const AbstractConsumer = require('./AbstractConsumer');
const {EMPTY_POSITION, FIRST_COLUMN, FIRST_LINE} = require('./constants');
const createConsumer = require('./createConsumer');
const {subtractOffsetFromPosition} = require('./positionMath');
const {greatestLowerBound} = require('./search');
const {add, add0, get0, get1, sub, sub1} = require('ob1');
/**
* A source map consumer that supports "indexed" source maps (that have a
* `sections` field and no top-level mappings).
*/
class SectionsConsumer extends AbstractConsumer implements IConsumer {
_consumers: $ReadOnlyArray<[GeneratedOffset, IConsumer]>;
constructor(sourceMap: IndexMap) {
super(sourceMap);
this._consumers = sourceMap.sections.map((section, index) => {
const generatedOffset = {
lines: add0(section.offset.line),
columns: add0(section.offset.column),
};
const consumer = createConsumer(section.map);
return [generatedOffset, consumer];
});
}
originalPositionFor(
generatedPosition: GeneratedPositionLookup,
): SourcePosition {
const [generatedOffset, consumer] =
this._consumerForPosition(generatedPosition) || [];
if (!consumer) {
return {...EMPTY_POSITION};
}
return consumer.originalPositionFor(
subtractOffsetFromPosition(generatedPosition, generatedOffset),
);
}
*generatedMappings(): Iterable<Mapping> {
for (const [generatedOffset, consumer] of this._consumers) {
let first = true;
for (const mapping of consumer.generatedMappings()) {
if (
first &&
(get1(mapping.generatedLine) > 1 || get0(mapping.generatedColumn) > 0)
) {
yield {
generatedLine: FIRST_LINE,
generatedColumn: FIRST_COLUMN,
source: null,
name: null,
originalLine: null,
originalColumn: null,
};
}
first = false;
yield {
...mapping,
generatedLine: add(mapping.generatedLine, generatedOffset.lines),
generatedColumn: add(
mapping.generatedColumn,
generatedOffset.columns,
),
};
}
}
}
_consumerForPosition(
generatedPosition: GeneratedPositionLookup,
): ?[GeneratedOffset, IConsumer] {
const {line, column} = generatedPosition;
if (line == null || column == null) {
return null;
}
const index = greatestLowerBound(
this._consumers,
generatedPosition,
(position, [offset]) => {
const line0 = sub1(line);
const column0 = column;
if (line0 === offset.lines) {
return get0(sub(column0, offset.columns));
}
return get0(sub(line0, offset.lines));
},
);
return index != null ? this._consumers[index] : null;
}
sourceContentFor(source: string, nullOnMissing: true): ?string {
for (const [_, consumer] of this._consumers) {
const content = consumer.sourceContentFor(source, nullOnMissing);
if (content != null) {
return content;
}
}
return null;
}
}
module.exports = SectionsConsumer;

View File

@@ -0,0 +1,32 @@
"use strict";
const { add0, add1 } = require("ob1");
const FIRST_COLUMN = add0(0);
const FIRST_LINE = add1(0);
const GENERATED_ORDER = "GENERATED_ORDER";
const ORIGINAL_ORDER = "ORIGINAL_ORDER";
const GREATEST_LOWER_BOUND = "GREATEST_LOWER_BOUND";
const LEAST_UPPER_BOUND = "LEAST_UPPER_BOUND";
const EMPTY_POSITION = Object.freeze({
source: null,
name: null,
line: null,
column: null,
});
function iterationOrderToString(x) {
return x;
}
function lookupBiasToString(x) {
return x;
}
module.exports = {
FIRST_COLUMN,
FIRST_LINE,
GENERATED_ORDER,
ORIGINAL_ORDER,
GREATEST_LOWER_BOUND,
LEAST_UPPER_BOUND,
EMPTY_POSITION,
iterationOrderToString,
lookupBiasToString,
};

View File

@@ -0,0 +1,53 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {Number0, Number1} from 'ob1';
const {add0, add1} = require('ob1');
const FIRST_COLUMN: Number0 = add0(0);
const FIRST_LINE: Number1 = add1(0);
export opaque type IterationOrder = 'GENERATED_ORDER' | 'ORIGINAL_ORDER';
const GENERATED_ORDER: IterationOrder = 'GENERATED_ORDER';
const ORIGINAL_ORDER: IterationOrder = 'ORIGINAL_ORDER';
export opaque type LookupBias = 'GREATEST_LOWER_BOUND' | 'LEAST_UPPER_BOUND';
const GREATEST_LOWER_BOUND: LookupBias = 'GREATEST_LOWER_BOUND';
const LEAST_UPPER_BOUND: LookupBias = 'LEAST_UPPER_BOUND';
const EMPTY_POSITION = Object.freeze({
source: null,
name: null,
line: null,
column: null,
});
function iterationOrderToString(x: IterationOrder): string {
return x;
}
function lookupBiasToString(x: LookupBias): string {
return x;
}
module.exports = {
FIRST_COLUMN,
FIRST_LINE,
GENERATED_ORDER,
ORIGINAL_ORDER,
GREATEST_LOWER_BOUND,
LEAST_UPPER_BOUND,
EMPTY_POSITION,
iterationOrderToString,
lookupBiasToString,
};

View File

@@ -0,0 +1,16 @@
"use strict";
const invariant = require("invariant");
function createConsumer(sourceMap) {
invariant(
sourceMap.version === "3" || sourceMap.version === 3,
`Unrecognized source map format version: ${sourceMap.version}`
);
const MappingsConsumer = require("./MappingsConsumer");
const SectionsConsumer = require("./SectionsConsumer");
if (sourceMap.mappings === undefined) {
return new SectionsConsumer(sourceMap);
}
return new MappingsConsumer(sourceMap);
}
module.exports = createConsumer;

View File

@@ -0,0 +1,34 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {MixedSourceMap} from '../source-map';
import type {IConsumer} from './types.flow';
const invariant = require('invariant');
function createConsumer(sourceMap: MixedSourceMap): IConsumer {
invariant(
(sourceMap.version: mixed) === '3' || sourceMap.version === 3,
`Unrecognized source map format version: ${sourceMap.version}`,
);
const MappingsConsumer = require('./MappingsConsumer');
const SectionsConsumer = require('./SectionsConsumer');
// eslint-disable-next-line lint/strictly-null
if (sourceMap.mappings === undefined) {
return new SectionsConsumer(sourceMap);
}
return new MappingsConsumer(sourceMap);
}
module.exports = createConsumer;

View File

@@ -0,0 +1,4 @@
"use strict";
const DelegatingConsumer = require("./DelegatingConsumer");
module.exports = DelegatingConsumer;

View File

@@ -0,0 +1,17 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
// Implements an API-compatible subset of source-map's `SourceMapConsumer`.
const DelegatingConsumer = require('./DelegatingConsumer');
module.exports = DelegatingConsumer;

View File

@@ -0,0 +1,15 @@
"use strict";
const util = require("source-map/lib/util");
function normalizeSourcePath(sourceInput, map) {
const { sourceRoot } = map;
let source = sourceInput;
source = String(source);
source = util.normalize(source);
source =
sourceRoot != null && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
? util.relative(sourceRoot, source)
: source;
return source;
}
module.exports = normalizeSourcePath;

View File

@@ -0,0 +1,42 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
// flowlint-next-line untyped-import:off
const util = require('source-map/lib/util');
// Extracted from source-map@0.5.6's SourceMapConsumer
function normalizeSourcePath(
sourceInput: string,
map: {+sourceRoot?: ?string, ...},
): string {
const {sourceRoot} = map;
let source = sourceInput;
source = String(source);
// Some source maps produce relative source paths like "./foo.js" instead of
// "foo.js". Normalize these first so that future comparisons will succeed.
// See bugzil.la/1090768.
source = util.normalize(source);
// Always ensure that absolute sources are internally stored relative to
// the source root, if the source root is absolute. Not doing this would
// be particularly problematic when the source root is a prefix of the
// source (valid, but why??). See github issue #199 and bugzil.la/1188982.
source =
sourceRoot != null && util.isAbsolute(sourceRoot) && util.isAbsolute(source)
? util.relative(sourceRoot, source)
: source;
return source;
}
module.exports = normalizeSourcePath;

View File

@@ -0,0 +1,26 @@
"use strict";
const { add, add0, add1, neg } = require("ob1");
function shiftPositionByOffset(pos, offset) {
return {
...pos,
line: pos.line != null ? add(pos.line, offset.lines) : null,
column: pos.column != null ? add(pos.column, offset.columns) : null,
};
}
function subtractOffsetFromPosition(pos, offset) {
if (pos.line === add1(offset.lines)) {
return shiftPositionByOffset(pos, {
lines: neg(offset.lines),
columns: neg(offset.columns),
});
}
return shiftPositionByOffset(pos, {
lines: neg(offset.lines),
columns: add0(0),
});
}
module.exports = {
shiftPositionByOffset,
subtractOffsetFromPosition,
};

View File

@@ -0,0 +1,52 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {GeneratedOffset} from './types.flow';
import type {Number0, Number1} from 'ob1';
const {add, add0, add1, neg} = require('ob1');
function shiftPositionByOffset<
T: {
+line: ?Number1,
+column: ?Number0,
...
},
>(pos: T, offset: GeneratedOffset): T {
return {
...pos,
line: pos.line != null ? add(pos.line, offset.lines) : null,
column: pos.column != null ? add(pos.column, offset.columns) : null,
};
}
function subtractOffsetFromPosition<
T: {
+line: ?Number1,
+column: ?Number0,
...
},
>(pos: T, offset: GeneratedOffset): T {
if (pos.line === add1(offset.lines)) {
return shiftPositionByOffset(pos, {
lines: neg(offset.lines),
columns: neg(offset.columns),
});
}
return shiftPositionByOffset(pos, {
lines: neg(offset.lines),
columns: add0(0),
});
}
module.exports = {shiftPositionByOffset, subtractOffsetFromPosition};

View File

@@ -0,0 +1,23 @@
"use strict";
function greatestLowerBound(elements, target, comparator) {
let first = 0;
let it = 0;
let count = elements.length;
let step;
while (count > 0) {
it = first;
step = Math.floor(count / 2);
it = it + step;
if (comparator(target, elements[it]) >= 0) {
first = ++it;
count = count - (step + 1);
} else {
count = step;
}
}
return first ? first - 1 : null;
}
module.exports = {
greatestLowerBound,
};

View File

@@ -0,0 +1,37 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
function greatestLowerBound<T, U>(
elements: $ReadOnlyArray<T>,
target: U,
comparator: (U, T) => number,
): ?number {
let first = 0;
let it = 0;
let count = elements.length;
let step;
while (count > 0) {
it = first;
step = Math.floor(count / 2);
it = it + step;
if (comparator(target, elements[it]) >= 0) {
first = ++it;
count = count - (step + 1);
} else {
count = step;
}
}
return first ? first - 1 : null;
}
module.exports = {greatestLowerBound};

View File

@@ -0,0 +1 @@
"use strict";

View File

@@ -0,0 +1,68 @@
/**
* 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-local
* @format
* @oncall react_native
*/
'use strict';
import type {IterationOrder, LookupBias} from './constants';
import type {Number0, Number1} from 'ob1';
export type {IterationOrder, LookupBias};
export type GeneratedOffset = {+lines: Number0, +columns: Number0};
export type SourcePosition = {
source: ?string,
line: ?Number1,
column: ?Number0,
name: ?string,
...
};
export type GeneratedPosition = {
+line: Number1,
+column: Number0,
...
};
export type GeneratedPositionLookup = {
+line: ?Number1,
+column: ?Number0,
+bias?: LookupBias,
...
};
export type Mapping = {
source: ?string,
generatedLine: Number1,
generatedColumn: Number0,
originalLine: ?Number1,
originalColumn: ?Number0,
name: ?string,
...
};
export interface IConsumer {
originalPositionFor(
generatedPosition: GeneratedPositionLookup,
): SourcePosition;
generatedMappings(): Iterable<Mapping>;
eachMapping(
callback: (mapping: Mapping) => mixed,
context?: mixed,
order?: IterationOrder,
): void;
// flowlint-next-line unsafe-getters-setters:off
get file(): ?string;
sourceContentFor(
source: string,
/* nullOnMissing = false behaves inconsistently upstream, so we don't support it */
nullOnMissing: true,
): ?string;
}