@tmlmobilidade/interfaces
Version:
This package provides SDK-style connectors for interacting with databases (e.g., stops, plans, rides, alerts) and external providers (e.g., authentication, storage). It simplifies data access and integration across projects.
218 lines (217 loc) • 7.93 kB
JavaScript
/* * */
import { samsAnalysisTimelineRowsExpr, samsDetailSnapExpr, samsListViewCarryFieldsExpr, samsTimelineSummaryFromBucketsExpr, } from './batch-timeline-from-analysis.js';
/**
* List view: derive `timeline_summary` from embedded `analysis` (same shape as
* {@link samsTimelineSummaryFromBucketsExpr}: month + counts per bucket).
*/
function samsListFacetMergeTimelineStages() {
return [
{
$addFields: {
__carry: samsListViewCarryFieldsExpr(),
__rowCount: { $size: { $ifNull: ['$analysis', []] } },
},
},
{
$facet: {
emptyAnalysis: [
{ $match: { __rowCount: 0 } },
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
'$__carry',
{ timeline_summary: { months: [], undated: null } },
],
},
},
},
],
fromAnalysis: [
{ $match: { __rowCount: { $gt: 0 } } },
{ $addFields: { __rows: samsAnalysisTimelineRowsExpr() } },
{ $unwind: '$__rows' },
{
$group: {
_id: { m: '$__rows.monthKey', sam: '$__carry._id' },
__carry: { $first: '$__carry' },
f: { $sum: '$__rows.failed' },
s: { $sum: '$__rows.successful' },
},
},
{
$group: {
_id: '$_id.sam',
__carry: { $first: '$__carry' },
buckets: { $push: { f: '$f', m: '$_id.m', s: '$s' } },
},
},
{ $addFields: { timeline_summary: samsTimelineSummaryFromBucketsExpr() } },
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
'$__carry',
{ timeline_summary: '$timeline_summary' },
],
},
},
},
],
},
},
{
$project: {
merged: { $concatArrays: ['$emptyAnalysis', '$fromAnalysis'] },
},
},
{ $unwind: '$merged' },
{ $replaceRoot: { newRoot: '$merged' } },
{ $sort: { created_at: -1 } },
];
}
function samsDetailFacetMergeTimelineStages() {
return [
{
$addFields: {
__rowCount: { $size: { $ifNull: ['$analysis', []] } },
__snap: samsDetailSnapExpr(),
},
},
{
$facet: {
emptyAnalysis: [
{ $match: { __rowCount: 0 } },
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
'$__snap',
{ timeline_summary: { months: [], undated: null } },
],
},
},
},
],
fromAnalysis: [
{ $match: { __rowCount: { $gt: 0 } } },
{ $addFields: { __rows: samsAnalysisTimelineRowsExpr() } },
{ $unwind: '$__rows' },
{
$group: {
_id: { m: '$__rows.monthKey', sam: '$__snap._id' },
__snap: { $first: '$__snap' },
analysis: { $first: '$analysis' },
f: { $sum: '$__rows.failed' },
s: { $sum: '$__rows.successful' },
},
},
{
$group: {
_id: '$_id.sam',
__snap: { $first: '$__snap' },
analysis: { $first: '$analysis' },
buckets: { $push: { f: '$f', m: '$_id.m', s: '$s' } },
},
},
{ $addFields: { timeline_summary: samsTimelineSummaryFromBucketsExpr() } },
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
'$__snap',
{ timeline_summary: '$timeline_summary' },
{ __analysis: '$analysis' },
],
},
},
},
],
},
},
{
$project: {
merged: { $concatArrays: ['$emptyAnalysis', '$fromAnalysis'] },
},
},
{ $unwind: '$merged' },
{ $replaceRoot: { newRoot: '$merged' } },
];
}
/**
* Builds a pipeline to return all matching SAMs for list view (no skip/limit).
* Excludes `analysis` from list fields; `timeline_summary` is computed from `analysis`.
*
* @param matchAnd - An array of $match conditions (ANDed).
* @returns Aggregation pipeline for MongoDB.
*/
export function samsBatchAggregationPipeline({ matchAnd, }) {
return [
...(matchAnd.length > 0 ? [{ $match: { $and: matchAnd } }] : []),
{ $sort: { created_at: -1 } },
...samsListFacetMergeTimelineStages(),
];
}
/**
* Same list row shape as {@link samsBatchAggregationPipeline} for explicit `_id`s (e.g. favorites).
*/
export function samsByIdsListViewAggregationPipeline({ agencyIds, ids, restrictByAgency, }) {
const matchAnd = [{ _id: { $in: ids } }];
if (restrictByAgency && agencyIds?.length)
matchAnd.push({ agency_id: { $in: agencyIds } });
return [
{ $match: { $and: matchAnd } },
{ $sort: { created_at: -1 } },
...samsListFacetMergeTimelineStages(),
];
}
/**
* Full SAM by id: all fields preserved; `timeline_summary` is recomputed from `analysis`.
*/
export function samsByIdAggregationPipeline(id) {
return [
{ $match: { _id: id } },
...samsDetailFacetMergeTimelineStages(),
];
}
/**
* Returns stored timeline summary rows for explicit SAM `_id`s.
* Used for fast SAM list timeline hydration.
*/
export function samsByIdsTimelineSummaryAggregationPipeline({ agencyIds, ids, restrictByAgency, }) {
const matchAnd = [{ _id: { $in: ids } }];
if (restrictByAgency && agencyIds?.length)
matchAnd.push({ agency_id: { $in: agencyIds } });
return [
{ $match: { $and: matchAnd } },
{
$project: {
_id: 1,
timeline_summary: { $ifNull: ['$timeline_summary', { months: [] }] },
},
},
];
}
/**
* Lightweight SAM list rows without timeline data (used for fast initial list loading).
*/
function samsListBaseProjectionStages() {
return [
{
$project: {
analysis: 0,
timeline_summary: 0,
},
},
{ $sort: { created_at: -1 } },
];
}
/**
* Lightweight SAM list rows without timeline data (used for fast initial list loading).
*/
export function samsBatchBaseAggregationPipeline({ matchAnd, }) {
return [
...(matchAnd.length > 0 ? [{ $match: { $and: matchAnd } }] : []),
...samsListBaseProjectionStages(),
];
}