hyperdx/packages/api/src/models/source.ts
Karl Power e09c8c0e5d
fix: query settings length validation (#1890)
## Summary

Fixes an issue with query settings length validation. `maxlength` only works for strings, so the max amount of query settings (10) was never enforced by mongoose.

Adds a small validator to address this.

### How to test locally or on Vercel
The max length is already enforced in the app, so make a HTTP request directly to API - or trust the integration tests :)
2026-03-16 15:05:54 +00:00

126 lines
3 KiB
TypeScript

import {
MetricsDataType,
QuerySettings,
SourceKind,
TSource,
} from '@hyperdx/common-utils/dist/types';
import mongoose, { Schema } from 'mongoose';
type ObjectId = mongoose.Types.ObjectId;
export interface ISource extends Omit<TSource, 'connection'> {
team: ObjectId;
connection: ObjectId | string;
}
export type SourceDocument = mongoose.HydratedDocument<ISource>;
const maxLength =
(max: number) =>
<T>({ length }: Array<T>) =>
length <= max;
const QuerySetting = new Schema<QuerySettings[number]>(
{
setting: {
type: String,
required: true,
minlength: 1,
},
value: {
type: String,
required: true,
minlength: 1,
},
},
{ _id: false },
);
export const Source = mongoose.model<ISource>(
'Source',
new Schema<ISource>(
{
kind: {
type: String,
enum: Object.values(SourceKind),
required: true,
},
team: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Team',
},
from: {
databaseName: String,
tableName: String,
},
timestampValueExpression: String,
connection: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Connection',
},
name: String,
orderByExpression: String,
displayedTimestampValueExpression: String,
implicitColumnExpression: String,
serviceNameExpression: String,
bodyExpression: String,
tableFilterExpression: String,
eventAttributesExpression: String,
resourceAttributesExpression: String,
defaultTableSelectExpression: String,
uniqueRowIdExpression: String,
severityTextExpression: String,
traceIdExpression: String,
spanIdExpression: String,
traceSourceId: String,
sessionSourceId: String,
metricSourceId: String,
durationExpression: String,
durationPrecision: Number,
parentSpanIdExpression: String,
spanNameExpression: String,
logSourceId: String,
spanKindExpression: String,
statusCodeExpression: String,
statusMessageExpression: String,
spanEventsValueExpression: String,
highlightedTraceAttributeExpressions: {
type: mongoose.Schema.Types.Array,
},
highlightedRowAttributeExpressions: {
type: mongoose.Schema.Types.Array,
},
materializedViews: {
type: mongoose.Schema.Types.Array,
},
metricTables: {
type: {
[MetricsDataType.Gauge]: String,
[MetricsDataType.Histogram]: String,
[MetricsDataType.Sum]: String,
[MetricsDataType.Summary]: String,
[MetricsDataType.ExponentialHistogram]: String,
},
default: undefined,
},
querySettings: {
type: [QuerySetting],
validate: {
validator: maxLength(10),
message: '{PATH} exceeds the limit of 10',
},
},
},
{
toJSON: { virtuals: true },
timestamps: true,
},
),
);