Security config (3.1): - config/session.ts: cookie.secure now follows app.inProduction instead of being hardcoded to false - config/shield.ts: enable CSP with baseline directives compatible with Vite dev server and Inertia (self + @viteDevUrl/@viteHmrUrl) Frontend typing (3.2): - Replace 'any' props with concrete types (Computer, Component, ComponentType, ComputerState) across computers/*.vue and components/*.vue, using the existing inertia/pages/types/UITypes.ts definitions - Fix UITypes.ts: export ComponentType/ComputerState, switch from interface to type (interfaces are never assignable to Inertia's ComponentProps index signature), drop the stale componentTypeId/componentStateId fields that didn't match the actual Lucid schema (real field is typeId, no component state exists) - Add an asPageProp() boundary cast in the two controllers: Lucid's serialize() returns a loosely typed ModelObject that isn't structurally assignable to the concrete page prop shapes (and the inertia/** tree is excluded from the backend tsconfig, so real types can't be imported directly across that boundary) UTF-8 mojibake fixes (3.3): - Repair broken accented characters (├®/├á/├┤ -> é/à/ô, Ôé¼ -> €) left over from a bad encoding during the GWT->Inertia migration, across ComponentEditor.vue, ComputerComponentsTable.vue, SimpleGallery.vue, TableComponent.vue, isAdminMode.ts and the custom directives Misc cleanup (3.5): - computer.ts: replace console.warn with the app logger (includes computerId) when .cost is accessed without preloading components
65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
import { DateTime } from 'luxon'
|
|
import { BaseModel, belongsTo, column, computed, hasMany } from '@adonisjs/lucid/orm'
|
|
import type { BelongsTo, HasMany } from '@adonisjs/lucid/types/relations'
|
|
import logger from '@adonisjs/core/services/logger'
|
|
import ComputerState from '#models/computer_state'
|
|
import ComputerPicture from '#models/computer_picture'
|
|
import Component from '#models/component'
|
|
|
|
export default class Computer extends BaseModel {
|
|
@column({ isPrimary: true })
|
|
declare id: number
|
|
|
|
@column()
|
|
declare title: string
|
|
|
|
@column()
|
|
declare sellPrice: number
|
|
|
|
@column()
|
|
declare gpuScore: number
|
|
|
|
@column()
|
|
declare cpuScore: number
|
|
|
|
@column()
|
|
declare globalScore: number
|
|
|
|
@column({ serializeAs: null })
|
|
declare stateId: number
|
|
|
|
@belongsTo(() => ComputerState, {
|
|
foreignKey: 'stateId',
|
|
})
|
|
declare state: BelongsTo<typeof ComputerState>
|
|
|
|
@hasMany(() => Component)
|
|
declare components: HasMany<typeof Component>
|
|
|
|
@hasMany(() => ComputerPicture, {
|
|
foreignKey: 'computerId',
|
|
})
|
|
declare pictures: HasMany<typeof ComputerPicture>
|
|
|
|
@column({ serializeAs: null })
|
|
declare userId: number
|
|
|
|
@column.dateTime({ autoCreate: true })
|
|
declare createdAt: DateTime
|
|
|
|
@column.dateTime({ autoCreate: true, autoUpdate: true })
|
|
declare updatedAt: DateTime | null
|
|
|
|
@computed()
|
|
get cost(): number {
|
|
if (!this.$preloaded.components) {
|
|
logger.warn(
|
|
{ computerId: this.id },
|
|
'Computer.cost accessed without preloading "components"; returning 0'
|
|
)
|
|
return 0
|
|
}
|
|
return this.components.reduce((total, component) => total + Number(component.price), 0)
|
|
}
|
|
}
|