Ctrl K
ComunidadGuías…

server/db/schema/settings-tables.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { sql } from 'drizzle-orm'
import { check, index, integer, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core'
import { user } from './auth-tables'
import { application, organization } from './authorization-tables'

export const webhookEndpoint = sqliteTable(
  'webhook_endpoint',
  {
    id: text('id').primaryKey(),
    url: text('url').notNull(),
    events: text('events', { mode: 'json' }).$type<string[]>().notNull(),
    enabled: integer('enabled', { mode: 'boolean' }).default(true).notNull(),
    organizationId: text('organization_id').references(() => organization.id, { onDelete: 'cascade' }),
    signingSecret: text('signing_secret').notNull(),
    secretPrefix: text('secret_prefix').notNull(),
    createdByUserId: text('created_by_user_id').references(() => user.id, { onDelete: 'set null' }),
    createdAt: integer('created_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .notNull(),
    updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .$onUpdate(() => new Date())
      .notNull(),
  },
  (table) => [
    index('webhookEndpoint_enabled_idx').on(table.enabled),
    index('webhookEndpoint_organizationId_idx').on(table.organizationId),
    index('webhookEndpoint_createdByUserId_idx').on(table.createdByUserId),
  ],
)

export const webhookDeliveryRequest = sqliteTable(
  'webhook_delivery_request',
  {
    id: text('id').primaryKey(),
    endpointId: text('endpoint_id')
      .notNull()
      .references(() => webhookEndpoint.id, { onDelete: 'cascade' }),
    event: text('event').notNull(),
    status: text('status').notNull().default('pending'),
    attemptCount: integer('attempt_count').notNull().default(0),
    httpStatus: integer('http_status'),
    error: text('error'),
    requestBody: text('request_body'),
    responseBody: text('response_body'),
    nextAttemptAt: integer('next_attempt_at', { mode: 'timestamp_ms' }),
    createdAt: integer('created_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .notNull(),
    updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .$onUpdate(() => new Date())
      .notNull(),
  },
  (table) => [
    index('webhookDeliveryRequest_endpointId_idx').on(table.endpointId),
    index('webhookDeliveryRequest_status_idx').on(table.status),
    index('webhookDeliveryRequest_createdAt_idx').on(table.createdAt),
  ],
)

export const webhookDeliveryAttempt = sqliteTable(
  'webhook_delivery_attempt',
  {
    id: text('id').primaryKey(),
    requestId: text('request_id')
      .notNull()
      .references(() => webhookDeliveryRequest.id, { onDelete: 'cascade' }),
    idempotencyKey: text('idempotency_key').notNull(),
    sequence: integer('sequence').notNull(),
    status: text('status').notNull().default('pending'),
    httpStatus: integer('http_status'),
    error: text('error'),
    responseBody: text('response_body'),
    createdAt: integer('created_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .notNull(),
    completedAt: integer('completed_at', { mode: 'timestamp_ms' }),
  },
  (table) => [
    uniqueIndex('webhookDeliveryAttempt_requestSequence_uidx').on(table.requestId, table.sequence),
    uniqueIndex('webhookDeliveryAttempt_requestIdempotencyKey_uidx').on(table.requestId, table.idempotencyKey),
    index('webhookDeliveryAttempt_requestId_idx').on(table.requestId),
    index('webhookDeliveryAttempt_createdAt_idx').on(table.createdAt),
  ],
)

export const customDomain = sqliteTable(
  'custom_domain',
  {
    id: text('id').primaryKey(),
    hostname: text('hostname').notNull().unique(),
    applicationId: text('application_id').references(() => application.id, { onDelete: 'cascade' }),
    organizationId: text('organization_id').references(() => organization.id, { onDelete: 'cascade' }),
    status: text('status').notNull().default('pending'),
    verificationToken: text('verification_token').notNull().unique(),
    cnameTarget: text('cname_target'),
    tlsStatus: text('tls_status'),
    verifiedAt: integer('verified_at', { mode: 'timestamp_ms' }),
    createdAt: integer('created_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .notNull(),
    updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
      .default(sql`(cast(unixepoch('subsecond') * 1000 as integer))`)
      .$onUpdate(() => new Date())
      .notNull(),
  },
  (table) => [
    index('customDomain_applicationId_idx').on(table.applicationId),
    index('customDomain_organizationId_idx').on(table.organizationId),
    index('customDomain_status_idx').on(table.status),
  ],
)

export const siteSettings = sqliteTable(
  'site_settings',
  {
    key: text('key').primaryKey(),
    value: text('value', { mode: 'json' }).$type<Record<string, unknown>>().notNull(),
    revision: integer('revision').notNull().default(1),
    updatedAt: integer('updated_at', { mode: 'timestamp_ms' }).notNull(),
  },
  (table) => [
    check('site_settings_value_json', sql`json_valid(${table.value})`),
    check('site_settings_revision_positive', sql`${table.revision} > 0`),
  ],
)