Source

models/urls/schema-definition.js

import { UrlOrigin } from "@typez/urls/enums";
import { Schema } from "mongoose";
/**
 * URL Counters Schema - Mongoose schema for UrlCounters
 * This is a subdocument schema with no _id
 * @category Models
 */
const UrlCountersSchema = new Schema({
    visitsTotal: {
        type: Number,
        default: 0,
        min: [0, "Visits total cannot be negative"],
    },
    completionsTotal: {
        type: Number,
        default: 0,
        min: [0, "Completions total cannot be negative"],
    },
}, { _id: false });
/**
 * URL Schema Definition
 * This file contains the main mongoose schema definition for URLs
 * @category Models
 */
export const UrlSchema = new Schema({
    // Identity & linkage
    investigationId: {
        type: Schema.Types.ObjectId,
        ref: "Investigation",
        required: [true, "Investigation ID is required"],
    },
    key: {
        type: String,
        required: [true, "Key is required"],
        trim: true,
        maxlength: [50, "Key cannot exceed 50 characters"],
    },
    subLink: {
        type: String,
        required: [true, "SubLink is required"],
        trim: true,
        lowercase: true,
        maxlength: [100, "SubLink cannot exceed 100 characters"],
        match: [
            /^[a-z0-9._-]+$/,
            "SubLink can only contain lowercase letters, numbers, dots, underscores, and hyphens",
        ],
    },
    description: {
        type: String,
        required: [true, "Description is required"],
        trim: true,
        maxlength: [200, "Description cannot exceed 200 characters"],
    },
    origin: {
        type: String,
        enum: Object.values(UrlOrigin),
        default: UrlOrigin.HUMAN,
        required: true,
    },
    // Per-link counters (canonical)
    counters: {
        type: UrlCountersSchema,
        default: () => ({
            visitsTotal: 0,
            completionsTotal: 0,
        }),
    },
    // Admin/trace
    createdBy: {
        type: Schema.Types.ObjectId,
        ref: "User",
        default: null,
    },
}, {
    timestamps: true,
    collection: "urls",
});