Skip to content

Instantly share code, notes, and snippets.

@andrevandal
Created August 15, 2023 22:38
Show Gist options
  • Save andrevandal/ad8494d375cb2277a6c2b0ee4a07ae60 to your computer and use it in GitHub Desktop.
Save andrevandal/ad8494d375cb2277a6c2b0ee4a07ae60 to your computer and use it in GitHub Desktop.

places.ts:

import {
  mysqlTable,
  bigint,
  varchar,
  text,
  timestamp,
  double,
  int,
  uniqueIndex,
  boolean,
  primaryKey,
  json,
} from 'drizzle-orm/mysql-core'

import { relations } from 'drizzle-orm'

import { medias } from '@/server/schemas/db/medias'
import { actions } from '@/server/schemas/db/actions'
import { attractions } from '@/server/schemas/db/attractions'
import { categories } from '@/server/schemas/db/categories'
import { addresses } from '@/server/schemas/db/addresses'
import { tags } from '@/server/schemas/db/tags'
import {
  openingHours,
  specialOpeningHours,
} from '@/server/schemas/db/openingHours'

type externalMetadata = Partial<{}>

// Places table
export const places = mysqlTable(
  'places',
  {
    id: bigint('id', { mode: 'number' }).autoincrement().primaryKey().notNull(),
    uuid: varchar('uuid', { length: 12 }).notNull(),
    name: text('name').notNull(),
    slug: varchar('slug', { length: 100 }).notNull(),
    description: text('description'),
    ratingLevel: double('rating_level'),
    ratingCount: int('rating_count'),
    pricingLevel: int('pricing_level'),
    pricingLevelCount: int('pricing_level_count'),
    coverMediaId: bigint('cover_media_id', { mode: 'number' }),
    avatarMediaId: bigint('avatar_media_id', { mode: 'number' }),
    addressId: bigint('address_id', { mode: 'number' }).notNull(),
    openingHourId: bigint('opening_hour_id', { mode: 'number' }),
    externalId: bigint('external_id', { mode: 'number' }),
    active: boolean('active').default(false),
    createdAt: timestamp('created_at', { mode: 'string' })
      .defaultNow()
      .notNull(),
    updatedAt: timestamp('updated_at', { mode: 'string' }),
    externalMetadata: json('external_metadata').$type<externalMetadata>(),
  },
  (table) => {
    return {
      uuid: uniqueIndex('uuid').on(table.uuid),
      slug: uniqueIndex('slug').on(table.slug),
      externalId: uniqueIndex('external_id').on(table.externalId),
    }
  },
)

// Place relations
export const placesRelations = relations(places, ({ one, many }) => ({
  coverMedia: one(medias, {
    fields: [places.coverMediaId],
    references: [medias.id],
  }),
  avatarMedia: one(medias, {
    fields: [places.avatarMediaId],
    references: [medias.id],
  }),
  address: one(addresses, {
    fields: [places.addressId],
    references: [addresses.id],
  }),
  openingHours: one(openingHours, {
    fields: [places.openingHourId],
    references: [openingHours.id],
  }),
  attractions: many(attractions),
  actions: many(actions),
  placesToCategories: many(placesToCategories),
  placesToTags: many(placesToTags),
  placesToMedias: many(placesToMedias),
  placesToAddresses: many(placesToAddresses),
  specialOpeningHour: many(specialOpeningHours),
  openingHour: many(openingHours),
}))

// PlacesToCategories table (Many-to-Many Mapping)
export const placesToCategories = mysqlTable(
  'places_to_categories',
  {
    placeId: bigint('place_id', { mode: 'number' }).notNull(),
    categoryId: bigint('category_id', { mode: 'number' }).notNull(),
  },
  (table) => {
    return {
      pk: primaryKey(table.placeId, table.categoryId),
    }
  },
)
export const placesToCategoriesRelations = relations(
  placesToCategories,
  ({ one }) => ({
    category: one(categories, {
      fields: [placesToCategories.categoryId],
      references: [categories.id],
    }),
    place: one(places, {
      fields: [placesToCategories.placeId],
      references: [places.id],
    }),
  }),
)

// PlacesToTags table (Many-to-Many Mapping)
export const placesToTags = mysqlTable(
  'places_to_tags',
  {
    placeId: bigint('place_id', { mode: 'number' }).notNull(),
    tagId: bigint('tag_id', { mode: 'number' }).notNull(),
  },
  (table) => {
    return {
      pk: primaryKey(table.placeId, table.tagId),
    }
  },
)
export const placesToTagsRelations = relations(placesToTags, ({ one }) => ({
  tag: one(tags, {
    fields: [placesToTags.tagId],
    references: [tags.id],
  }),
  place: one(places, {
    fields: [placesToTags.placeId],
    references: [places.id],
  }),
}))

// PlacesToMedias table (Many-to-Many Mapping)
export const placesToMedias = mysqlTable(
  'places_to_medias',
  {
    mediaId: bigint('media_id', { mode: 'number' }).notNull(),
    placeId: bigint('place_id', { mode: 'number' }).notNull(),
  },
  (table) => {
    return {
      pk: primaryKey(table.mediaId, table.placeId),
    }
  },
)

export const placesToMediasRelations = relations(placesToMedias, ({ one }) => ({
  media: one(medias, {
    fields: [placesToMedias.mediaId],
    references: [medias.id],
  }),
  place: one(places, {
    fields: [placesToMedias.placeId],
    references: [places.id],
  }),
}))

// PlaceToAddress table (Many-to-Many Mapping)
export const placesToAddresses = mysqlTable(
  'places_to_addresses',
  {
    addressId: bigint('address_id', { mode: 'number' }).notNull(),
    placeId: bigint('place_id', { mode: 'number' }).notNull(),
  },
  (table) => {
    return {
      pk: primaryKey(table.addressId, table.placeId),
    }
  },
)
export const placesToAddressesRelations = relations(
  placesToAddresses,
  ({ one }) => ({
    address: one(medias, {
      fields: [placesToAddresses.addressId],
      references: [medias.id],
    }),
    place: one(places, {
      fields: [placesToAddresses.placeId],
      references: [places.id],
    }),
  }),
)

medias.ts:

import {
  mysqlTable,
  bigint,
  varchar,
  text,
  timestamp,
  uniqueIndex,
  boolean,
  json,
  mysqlEnum,
} from 'drizzle-orm/mysql-core'
import { relations } from 'drizzle-orm'
import { places } from '@/server/schemas/db/places'

type externalMetadata = Partial<{}>

// Medias table
export const medias = mysqlTable(
  'medias',
  {
    id: bigint('id', { mode: 'number' }).autoincrement().primaryKey().notNull(),
    uuid: varchar('uuid', { length: 12 }).notNull(),
    type: text('type').notNull(),
    title: text('title'),
    description: text('description'),
    alternativeText: text('alternative_text'),
    url: text('url').notNull(),
    active: boolean('active').default(false),
    status: mysqlEnum('status', ['pending', 'completed', 'error']).default(
      'pending',
    ),
    createdAt: timestamp('created_at', { mode: 'string' })
      .defaultNow()
      .notNull(),
    updatedAt: timestamp('updated_at', { mode: 'string' }),
    externalMetadata: json('external_metadata').$type<externalMetadata>(),
  },
  (table) => {
    return {
      uuid: uniqueIndex('uuid').on(table.uuid),
    }
  },
)

export const mediasRelations = relations(medias, ({ many }) => ({
  places: many(places),
}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment