From 914833e484fb51e8de952684f488806db35e4aee Mon Sep 17 00:00:00 2001 From: Gerald Leban Date: Fri, 9 Oct 2026 12:05:22 +0200 Subject: [PATCH] feat(likes): define lexicon and kit_likes schema and model --- app/kits/models/kit.ts | 8 +++- app/kits/models/kit_like.ts | 12 +++++ database/factories/kit_like_factory.ts | 15 +++++++ .../1791532329952_create_kit_likes_table.ts | 22 +++++++++ database/schema.ts | 45 ++++++++++++++++++- lexicons/build.gunpla.like.json | 26 +++++++++++ 6 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 app/kits/models/kit_like.ts create mode 100644 database/factories/kit_like_factory.ts create mode 100644 database/migrations/1791532329952_create_kit_likes_table.ts create mode 100644 lexicons/build.gunpla.like.json diff --git a/app/kits/models/kit.ts b/app/kits/models/kit.ts index 2764633..b048a58 100644 --- a/app/kits/models/kit.ts +++ b/app/kits/models/kit.ts @@ -1,7 +1,8 @@ -import { BaseModel, belongsTo, column } from '@adonisjs/lucid/orm' -import type { BelongsTo } from '@adonisjs/lucid/types/relations' +import { BaseModel, belongsTo, column, hasMany } from '@adonisjs/lucid/orm' +import type { BelongsTo, HasMany } from '@adonisjs/lucid/types/relations' import { DateTime } from 'luxon' import Profile from '#profile/models/profile' +import KitLike from '#kits/models/kit_like' export default class Kit extends BaseModel { static table = 'kits' @@ -69,6 +70,9 @@ export default class Kit extends BaseModel { @belongsTo(() => Profile, { foreignKey: 'did', localKey: 'did' }) declare profile: BelongsTo + @hasMany(() => KitLike) + declare kitLikes: HasMany + static async hasKitsFor(did: string): Promise { const result = await Kit.query().where('did', did).count('* as total').first() return Number(result?.$extras?.total ?? 0) > 0 diff --git a/app/kits/models/kit_like.ts b/app/kits/models/kit_like.ts new file mode 100644 index 0000000..265815c --- /dev/null +++ b/app/kits/models/kit_like.ts @@ -0,0 +1,12 @@ +import { belongsTo } from '@adonisjs/lucid/orm' +import type { BelongsTo } from '@adonisjs/lucid/types/relations' +import { KitLikeSchema } from '#database/schema' +import Kit from '#kits/models/kit' + +export default class KitLike extends KitLikeSchema { + static readonly selfAssignPrimaryKey = false + static readonly updatedAtColumn = '' + + @belongsTo(() => Kit) + declare kit: BelongsTo +} diff --git a/database/factories/kit_like_factory.ts b/database/factories/kit_like_factory.ts new file mode 100644 index 0000000..8e9ac5d --- /dev/null +++ b/database/factories/kit_like_factory.ts @@ -0,0 +1,15 @@ +import Factory from '@adonisjs/lucid/factories' +import { AtUri } from '@atproto/syntax' +import { DateTime } from 'luxon' +import KitLike from '#kits/models/kit_like' + +export const KitLikeFactory = Factory.define(KitLike, ({ faker }) => { + const did = `did:plc:${faker.string.alphanumeric(24)}` + const rkey = faker.string.alphanumeric(13) + return { + did, + uri: AtUri.make(did, 'build.gunpla.like', rkey).toString(), + kitId: 0, + createdAt: DateTime.now(), + } +}).build() diff --git a/database/migrations/1791532329952_create_kit_likes_table.ts b/database/migrations/1791532329952_create_kit_likes_table.ts new file mode 100644 index 0000000..f49665f --- /dev/null +++ b/database/migrations/1791532329952_create_kit_likes_table.ts @@ -0,0 +1,22 @@ +import { BaseSchema } from '@adonisjs/lucid/schema' + +export default class extends BaseSchema { + protected tableName = 'kit_likes' + + async up() { + this.schema.createTable(this.tableName, (table) => { + table.increments('id') + table.integer('kit_id').unsigned().notNullable().references('kits.id').onDelete('CASCADE') + table.string('did').notNullable() + table.string('uri').notNullable() + table.timestamp('created_at').notNullable() + + table.unique(['did', 'kit_id'], { indexName: 'kit_likes_did_kit_unique' }) + table.index(['kit_id'], 'kit_likes_kit_id_idx') + }) + } + + async down() { + this.schema.dropTable(this.tableName) + } +} diff --git a/database/schema.ts b/database/schema.ts index 3ffc016..1383439 100644 --- a/database/schema.ts +++ b/database/schema.ts @@ -7,8 +7,40 @@ import { BaseModel, column } from '@adonisjs/lucid/orm' import { DateTime } from 'luxon' +export class KitLikeSchema extends BaseModel { + static $columns = ['createdAt', 'did', 'id', 'kitId', 'uri'] as const + $columns = KitLikeSchema.$columns + @column.dateTime({ autoCreate: true }) + declare createdAt: DateTime + @column() + declare did: string + @column({ isPrimary: true }) + declare id: number + @column() + declare kitId: number + @column() + declare uri: string +} + export class KitSchema extends BaseModel { - static $columns = ['acquiredAt', 'cid', 'createdAt', 'did', 'grade', 'id', 'indexedAt', 'manufacturer', 'name', 'photoCid', 'photos', 'recordCreatedAt', 'scale', 'status', 'updatedAt', 'uri'] as const + static $columns = [ + 'acquiredAt', + 'cid', + 'createdAt', + 'did', + 'grade', + 'id', + 'indexedAt', + 'manufacturer', + 'name', + 'photoCid', + 'photos', + 'recordCreatedAt', + 'scale', + 'status', + 'updatedAt', + 'uri', + ] as const $columns = KitSchema.$columns @column.dateTime() declare acquiredAt: DateTime | null @@ -67,7 +99,16 @@ export class OauthStateSchema extends BaseModel { } export class ProfileSchema extends BaseModel { - static $columns = ['avatarUrl', 'createdAt', 'description', 'did', 'displayName', 'handle', 'indexedAt', 'updatedAt'] as const + static $columns = [ + 'avatarUrl', + 'createdAt', + 'description', + 'did', + 'displayName', + 'handle', + 'indexedAt', + 'updatedAt', + ] as const $columns = ProfileSchema.$columns @column() declare avatarUrl: string | null diff --git a/lexicons/build.gunpla.like.json b/lexicons/build.gunpla.like.json new file mode 100644 index 0000000..4662fd8 --- /dev/null +++ b/lexicons/build.gunpla.like.json @@ -0,0 +1,26 @@ +{ + "lexicon": 1, + "id": "build.gunpla.like", + "defs": { + "main": { + "type": "record", + "key": "tid", + "description": "A like of a Gunpla kit.", + "record": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "format": "at-uri", + "description": "The AT-URI of the kit being liked." + }, + "createdAt": { + "type": "string", + "format": "datetime" + } + }, + "required": ["subject", "createdAt"] + } + } + } +} -- 2.54.0