feat(convex): add full domain schema and snapshot sync bridge
This commit is contained in:
121
convex/schema.ts
121
convex/schema.ts
@@ -2,6 +2,127 @@ import { defineSchema, defineTable } from "convex/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
export default defineSchema({
|
||||
users: defineTable({
|
||||
x_user_id: v.optional(v.string()),
|
||||
username: v.optional(v.string()),
|
||||
email: v.optional(v.string()),
|
||||
created_at: v.string(),
|
||||
updated_at: v.string(),
|
||||
})
|
||||
.index("by_x_user_id", ["x_user_id"])
|
||||
.index("by_username", ["username"])
|
||||
.index("by_email", ["email"]),
|
||||
|
||||
wallets: defineTable({
|
||||
user_id: v.id("users"),
|
||||
balance_credits: v.number(),
|
||||
updated_at: v.string(),
|
||||
}).index("by_user_id", ["user_id"]),
|
||||
|
||||
wallet_transactions: defineTable({
|
||||
user_id: v.id("users"),
|
||||
type: v.union(v.literal("credit"), v.literal("debit"), v.literal("refund")),
|
||||
amount: v.number(),
|
||||
reason: v.optional(v.string()),
|
||||
idempotency_key: v.string(),
|
||||
balance_after: v.number(),
|
||||
created_at: v.string(),
|
||||
})
|
||||
.index("by_user_id", ["user_id"])
|
||||
.index("by_idempotency_key", ["idempotency_key"]),
|
||||
|
||||
mention_events: defineTable({
|
||||
mention_post_id: v.string(),
|
||||
mention_author_id: v.string(),
|
||||
parent_post_id: v.string(),
|
||||
status: v.string(),
|
||||
error_code: v.optional(v.string()),
|
||||
created_at: v.string(),
|
||||
updated_at: v.string(),
|
||||
})
|
||||
.index("by_mention_post_id", ["mention_post_id"])
|
||||
.index("by_parent_post_id", ["parent_post_id"])
|
||||
.index("by_mention_author_id", ["mention_author_id"]),
|
||||
|
||||
articles: defineTable({
|
||||
x_article_id: v.optional(v.string()),
|
||||
parent_post_id: v.string(),
|
||||
author_id: v.optional(v.string()),
|
||||
title: v.string(),
|
||||
char_count: v.number(),
|
||||
content_hash: v.optional(v.string()),
|
||||
raw_content: v.optional(v.string()),
|
||||
created_at: v.string(),
|
||||
updated_at: v.string(),
|
||||
})
|
||||
.index("by_x_article_id", ["x_article_id"])
|
||||
.index("by_parent_post_id", ["parent_post_id"])
|
||||
.index("by_content_hash", ["content_hash"]),
|
||||
|
||||
audio_jobs: defineTable({
|
||||
user_id: v.id("users"),
|
||||
mention_event_id: v.optional(v.id("mention_events")),
|
||||
article_id: v.id("articles"),
|
||||
status: v.union(
|
||||
v.literal("received"),
|
||||
v.literal("validated"),
|
||||
v.literal("priced"),
|
||||
v.literal("charged"),
|
||||
v.literal("synthesizing"),
|
||||
v.literal("uploaded"),
|
||||
v.literal("completed"),
|
||||
v.literal("failed_refunded"),
|
||||
v.literal("failed_not_refunded"),
|
||||
),
|
||||
credits_charged: v.number(),
|
||||
tts_provider: v.optional(v.string()),
|
||||
tts_model: v.optional(v.string()),
|
||||
error: v.optional(v.string()),
|
||||
asset_id: v.optional(v.id("audio_assets")),
|
||||
created_at: v.string(),
|
||||
updated_at: v.string(),
|
||||
})
|
||||
.index("by_user_id", ["user_id"])
|
||||
.index("by_mention_event_id", ["mention_event_id"])
|
||||
.index("by_article_id", ["article_id"])
|
||||
.index("by_status", ["status"]),
|
||||
|
||||
audio_assets: defineTable({
|
||||
job_id: v.id("audio_jobs"),
|
||||
storage_key: v.optional(v.string()),
|
||||
duration_sec: v.optional(v.number()),
|
||||
size_bytes: v.optional(v.number()),
|
||||
codec: v.optional(v.string()),
|
||||
public_url_ttl: v.optional(v.number()),
|
||||
deleted_at: v.optional(v.string()),
|
||||
last_played_at: v.optional(v.string()),
|
||||
created_at: v.string(),
|
||||
updated_at: v.string(),
|
||||
}).index("by_job_id", ["job_id"]),
|
||||
|
||||
audio_access_grants: defineTable({
|
||||
audio_asset_id: v.id("audio_assets"),
|
||||
user_id: v.id("users"),
|
||||
granted_via: v.union(v.literal("owner"), v.literal("repurchase"), v.literal("admin")),
|
||||
credits_paid: v.number(),
|
||||
created_at: v.string(),
|
||||
})
|
||||
.index("by_audio_asset_id", ["audio_asset_id"])
|
||||
.index("by_user_id", ["user_id"])
|
||||
.index("by_asset_and_user", ["audio_asset_id", "user_id"]),
|
||||
|
||||
payment_events: defineTable({
|
||||
provider: v.string(),
|
||||
provider_event_id: v.string(),
|
||||
status: v.string(),
|
||||
payload_hash: v.optional(v.string()),
|
||||
created_at: v.string(),
|
||||
updated_at: v.string(),
|
||||
})
|
||||
.index("by_provider_event_id", ["provider_event_id"])
|
||||
.index("by_provider_and_event", ["provider", "provider_event_id"]),
|
||||
|
||||
// Legacy compatibility table while runtime is still transitioning away from snapshot persistence.
|
||||
state_snapshots: defineTable({
|
||||
snapshot: v.any(),
|
||||
updatedAt: v.string(),
|
||||
|
||||
Reference in New Issue
Block a user