Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 1x 1x 1x 1x 5x 4x 5x 3x 1x 2x 2x 2x 2x 2x 2x 1x 1x 1x 13x 13x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import { z } from 'zod'
import { HTTPRequest, ServerSchema } from '../schema/server'
import DataParser from './DataParser'
// simulates pagination by building pages of data
// given a page size and page number
// returns the slice of data for that page
function buildPage<T>(data: T[], pageSize: number, pageNumber: number): T[] {
Iif (pageSize <= 0 || pageNumber <= 0) {
throw new Error('pageSize and pageNumber must be greater than 0')
}
const start = (pageNumber - 1) * pageSize
const end = start + pageSize
return data.slice(start, end)
}
export default class ServerParser {
protected maxPageSize: number
protected schema: z.infer<typeof ServerSchema>
constructor(schema: unknown) {
// Parse to validate and capture defaults/coercions
this.schema = ServerSchema.parse(schema)
this.maxPageSize = this.schema.options?.maxPageSize ?? 20
}
generate(request: HTTPRequest): unknown {
// Find the matching route
const route = this.schema.routes.find(r => r.method === request.method && r.routeKey === request.routeKey)
if (!route) {
throw new Error(`No matching route for ${request.method} ${request.routeKey}`)
}
// get the data schema for the response
Eif (this.schema.data && route.responseKey) {
const dataSchema = this.schema.data[route.responseKey]
Iif (!dataSchema) {
throw new Error(`No data schema found for responseKey: ${route.responseKey}`)
}
// Generate the full data set
const dataParser = new DataParser(dataSchema)
const indexKey = dataSchema.index
// If an index key is provided and exists in path parameters, return the single item
if (indexKey && request.pathParameters && request.pathParameters[indexKey]) {
const fullData = dataParser.generate()
if (Array.isArray(fullData)) {
const item = fullData.find(d => {
Eif (d && typeof d === 'object' && !Array.isArray(d) && indexKey in d) {
return String((d as Record<string, unknown>)[indexKey]) === request.pathParameters![indexKey]
}
return false
})
Iif (!item) {
return { error: `Item with ${indexKey}=${request.pathParameters[indexKey]} not found` }
}
return item
E} else if (fullData && typeof fullData === 'object' && !Array.isArray(fullData) && indexKey in fullData) {
if (String((fullData as Record<string, unknown>)[indexKey]) === request.pathParameters[indexKey]) {
return fullData
} else {
return { error: `Item with ${indexKey}=${request.pathParameters[indexKey]} not found` }
}
} else {
return { error: 'Data schema is not an array or object suitable for indexing' }
}
}
const fullData = dataParser.generate()
// If the full data is not an array, return it directly
Iif (!Array.isArray(fullData)) {
return {
item: fullData,
total: 1,
}
}
// Handle pagination if query parameters are provided
const limit = request.queryStringParameters?.limit ? parseInt(request.queryStringParameters.limit, 10) : undefined
const offset = request.queryStringParameters?.offset ? parseInt(request.queryStringParameters.offset, 10) : undefined
Eif (limit !== undefined && offset !== undefined) {
const pageNumber = Math.floor(offset / limit) + 1
const items = buildPage(fullData, limit, pageNumber)
return {
items,
from: offset + 1,
to: offset + items.length,
total: fullData.length,
pageSize: limit,
pageNumber,
totalPages: Math.ceil(fullData.length / limit),
}
}
// If no pagination parameters, return the default page
const items = buildPage(fullData, this.maxPageSize, 1)
return {
items,
from: 1,
to: items.length,
total: fullData.length,
pageSize: this.maxPageSize,
pageNumber: 1,
totalPages: Math.ceil(fullData.length / this.maxPageSize),
}
}
// No data schema, return empty object
return {}
}
}
|