Skip to content

Commit

Permalink
chore: adds preset tags and organize schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
luandro committed Feb 6, 2025
1 parent 4f9f226 commit 9fb06e0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 27 deletions.
14 changes: 10 additions & 4 deletions src/routes/observations.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,21 @@ export default async function observationRoutes(

let response
if (versionId) {
// Use observationToUpdate when versionId is provided
// Use observationToUpdate when versionId is provided.
// lat and lon are intentionally not updated on update.
const bodyUpdate =
/** @type {import('@sinclair/typebox').Static<typeof schemas.observationToUpdate>} */ (
req.body
)
// Destructure and ignore lat and lon if provided in the update payload.
const { attachments, tags } = bodyUpdate
const observationData = {
schemaName: /** @type {const} */ ('observation'),
attachments: (bodyUpdate.attachments || []).map((attachment) => ({
attachments: (attachments || []).map((attachment) => ({
...attachment,
hash: '', // Required by schema but not used
})),
tags: bodyUpdate.tags ?? {}, // Always include tags, default to empty object
tags: tags ?? {}, // Always include tags, default to empty object
...(preset && {
presetRef: {
docId: preset.docId,
Expand All @@ -146,7 +149,10 @@ export default async function observationRoutes(
presetRef: preset
? { docId: preset.docId, versionId: preset.versionId }
: void 0,
tags: bodyAdd.tags ?? {},
tags: {
...(preset ? preset.tags : {}),
...(bodyAdd.tags ?? {}),
},
metadata: bodyAdd.metadata || {
manualLocation: false,
position: {
Expand Down
59 changes: 36 additions & 23 deletions src/schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,29 @@ import { Type } from '@sinclair/typebox'

import { BASE32_STRING_32_BYTES } from './routes/constants.js'

// -----------------------------------------------------------------
// Constants & Base Types
// -----------------------------------------------------------------
const HEX_REGEX_32_BYTES = '^[0-9a-fA-F]{64}$'
export const HEX_STRING_32_BYTES = Type.String({ pattern: HEX_REGEX_32_BYTES })

const dateTimeString = Type.String({ format: 'date-time' })
const latitude = Type.Number({ minimum: -90, maximum: 90 })
const longitude = Type.Number({ minimum: -180, maximum: 180 })

// -----------------------------------------------------------------
// Error Schema
// -----------------------------------------------------------------
export const errorResponse = Type.Object({
error: Type.Object({
code: Type.String(),
message: Type.String(),
}),
})

// Schema for adding a project
// -----------------------------------------------------------------
// Project Schemas
// -----------------------------------------------------------------
export const projectToAdd = Type.Object({
projectName: Type.String({ minLength: 1 }),
projectKey: Type.Optional(HEX_STRING_32_BYTES),
Expand All @@ -30,19 +38,40 @@ export const projectToAdd = Type.Object({
}),
),
})

/** @typedef {import('./types/project.js').ProjectToAdd} ProjectToAdd */

// Define a dedicated attachment schema for observations
// -----------------------------------------------------------------
// Attachment Schemas
// -----------------------------------------------------------------
export const attachmentSchema = Type.Object({
driveDiscoveryId: Type.String(),
type: Type.Union([Type.Literal('photo'), Type.Literal('audio')]),
name: Type.String(),
hash: Type.Optional(Type.String()),
})

/** @typedef {import('@sinclair/typebox').Static<typeof observationToAdd>} ObservationToAdd */
/** @typedef {{driveDiscoveryId: string, type: 'photo'|'audio', name: string, hash?: string}} Attachment */

export const attachmentParams = Type.Object({
projectPublicId: BASE32_STRING_32_BYTES,
driveDiscoveryId: Type.String(),
type: Type.Union([Type.Literal('photo'), Type.Literal('audio')]),
name: Type.String(),
})
/** @typedef {import('@sinclair/typebox').Static<typeof attachmentQuerystring>} AttachmentQuerystring */
export const attachmentQuerystring = Type.Object({
variant: Type.Optional(
Type.Union([
Type.Literal('original'),
Type.Literal('preview'),
Type.Literal('thumbnail'),
]),
),
})

// -----------------------------------------------------------------
// Observation Schemas
// -----------------------------------------------------------------
export const observationToAdd = Type.Object({
lat: latitude,
lon: longitude,
Expand Down Expand Up @@ -95,25 +124,6 @@ export const observationToAdd = Type.Object({
),
})

export const attachmentParams = Type.Object({
projectPublicId: BASE32_STRING_32_BYTES,
driveDiscoveryId: Type.String(),
type: Type.Union([Type.Literal('photo'), Type.Literal('audio')]),
name: Type.String(),
})

/** @typedef {import('@sinclair/typebox').Static<typeof attachmentQuerystring>} AttachmentQuerystring */
export const attachmentQuerystring = Type.Object({
variant: Type.Optional(
Type.Union([
Type.Literal('original'),
Type.Literal('preview'),
Type.Literal('thumbnail'),
]),
),
})

// Schema for updating an observation (when versionId is provided)
export const observationToUpdate = Type.Object({
schemaName: Type.Literal('observation'),
attachments: Type.Optional(
Expand Down Expand Up @@ -178,6 +188,9 @@ export const observationResult = Type.Object({
),
})

// -----------------------------------------------------------------
// Remote Detection Alert Schemas
// -----------------------------------------------------------------
const position = Type.Tuple([longitude, latitude])

const remoteDetectionAlertCommon = {
Expand Down

0 comments on commit 9fb06e0

Please sign in to comment.