diff --git a/app/app.vue b/app/app.vue index 9a6378a..fe9d35b 100644 --- a/app/app.vue +++ b/app/app.vue @@ -72,6 +72,7 @@ // Reset default button styles button { border: none; + padding: 0; } } diff --git a/app/assets/styles/_base.scss b/app/assets/styles/_base.scss index e0a8cb6..96f7c2a 100644 --- a/app/assets/styles/_base.scss +++ b/app/assets/styles/_base.scss @@ -11,6 +11,7 @@ --screen-mobile-m: #{$screen-mobile-m}; --screen-mobile-l: #{$screen-mobile-l}; --screen-tablet: #{$screen-tablet}; + --screen-laptop: #{$screen-laptop}; --screen-desktop-s: #{$screen-desktop-s}; --screen-desktop-m: #{$screen-desktop-m}; --screen-desktop-l: #{$screen-desktop-l}; diff --git a/app/assets/styles/_media.scss b/app/assets/styles/_media.scss index d58754c..161c564 100644 --- a/app/assets/styles/_media.scss +++ b/app/assets/styles/_media.scss @@ -6,8 +6,20 @@ } } +@mixin mobileMedium() { + @media screen and (min-width: $screen-mobile-m) { + @content; + } +} + @mixin tablet() { @media screen and (min-width: $screen-tablet) { @content; } } + +@mixin laptop() { + @media screen and (min-width: $screen-laptop) { + @content; + } +} diff --git a/app/assets/styles/_variables.scss b/app/assets/styles/_variables.scss index c0393ec..60ace67 100644 --- a/app/assets/styles/_variables.scss +++ b/app/assets/styles/_variables.scss @@ -3,6 +3,7 @@ $screen-mobile-s: 320px; $screen-mobile-m: 375px; $screen-mobile-l: 414px; $screen-tablet: 768px; +$screen-laptop: 1024px; $screen-desktop-s: 1280px; $screen-desktop-m: 1440px; $screen-desktop-l: 1920px; diff --git a/app/components/ImageUpload.vue b/app/components/ImageUpload.vue new file mode 100644 index 0000000..a4df13c --- /dev/null +++ b/app/components/ImageUpload.vue @@ -0,0 +1,118 @@ + + + + + + + + + + + + + diff --git a/app/components/PerdInput.vue b/app/components/PerdInput.vue index f5348fa..1a37809 100644 --- a/app/components/PerdInput.vue +++ b/app/components/PerdInput.vue @@ -64,7 +64,7 @@ .label { position: absolute; - left: 0; + left: var(--input-spacing-horizontal); top: 0; bottom: 0; right: 0; @@ -72,7 +72,6 @@ align-items: center; pointer-events: none; color: var(--input-color-main); - left: var(--input-spacing-horizontal); transform-origin: top left; user-select: none; transition: diff --git a/app/components/PerdMenu/OptionBase.vue b/app/components/PerdMenu/OptionBase.vue index f7714a9..038a49b 100644 --- a/app/components/PerdMenu/OptionBase.vue +++ b/app/components/PerdMenu/OptionBase.vue @@ -25,7 +25,7 @@ background-color: var(--color-background); color: var(--color-blue-600); cursor: pointer; - transition: background-color 0.2s ease-out; + transition: background-color var(--transition-time-quick) ease-out; font-size: var(--font-size-14); white-space: nowrap; diff --git a/app/components/PerdSelect.vue b/app/components/PerdSelect.vue new file mode 100644 index 0000000..a977644 --- /dev/null +++ b/app/components/PerdSelect.vue @@ -0,0 +1,128 @@ + + + + + + + {{ placeholder }} + + + + {{ option.label }} + + + + + + + + diff --git a/app/components/PerdTextArea.vue b/app/components/PerdTextArea.vue new file mode 100644 index 0000000..4f10bb0 --- /dev/null +++ b/app/components/PerdTextArea.vue @@ -0,0 +1,108 @@ + + + + + + {{ label }} + + + + + + + diff --git a/app/components/experimental/ExperimentalSelect.vue b/app/components/experimental/ExperimentalSelect.vue new file mode 100644 index 0000000..3c410ac --- /dev/null +++ b/app/components/experimental/ExperimentalSelect.vue @@ -0,0 +1,154 @@ + + + + + + + + + + {{ placeholder }} + + + + {{ option.label }} + + + + + + + diff --git a/app/composables/use-toaster.ts b/app/composables/use-toaster.ts index fabb7da..e1d7393 100644 --- a/app/composables/use-toaster.ts +++ b/app/composables/use-toaster.ts @@ -1,5 +1,5 @@ export interface Toast { - readonly id: number; + readonly id: string; readonly message: string; readonly title?: string; readonly duration?: number | null; @@ -17,7 +17,12 @@ export default function useToaster() { duration = defaultDuration, title } : ToastParams) { - const id = Date.now(); + // Skip SSR rendering + if (import.meta.server) { + return; + } + + const id = crypto.randomUUID(); toasts.value.unshift({ id, @@ -27,7 +32,7 @@ export default function useToaster() { }); } - function removeToast(id: number) { + function removeToast(id: string) { const foundIndex = toasts.value.findIndex(toast => toast.id === id); if (foundIndex >= 0) { diff --git a/app/composables/use-user-equipment.ts b/app/composables/use-user-equipment.ts index 4d1a4f1..e7ff7c1 100644 --- a/app/composables/use-user-equipment.ts +++ b/app/composables/use-user-equipment.ts @@ -8,14 +8,15 @@ interface EquipmentItem { export async function useUserEquipment() { const equipment = useState('userEquipment', () => []) - const { data } = await useFetch('/api/user/equipment') + const { data } = await useFetch('/api/inventory') - async function updateEquipment() { + async function refetchEquipment() { try { - const response = await $fetch('/api/user/equipment') + const response = await $fetch('/api/inventory') equipment.value = response } catch { + // TODO: Handle error console.error('Failed to update equipment') } } @@ -26,6 +27,6 @@ export async function useUserEquipment() { return { equipment, - updateEquipment + refetchEquipment } } diff --git a/app/layouts/page.vue b/app/layouts/page.vue index 4357467..3cacda2 100644 --- a/app/layouts/page.vue +++ b/app/layouts/page.vue @@ -30,5 +30,7 @@ .content { padding: var(--spacing-16); + max-width: var(--screen-laptop); + margin: 0 auto; } diff --git a/app/pages/checklists/[checklistId].vue b/app/pages/checklists/[checklistId].vue index c7346d9..d0210f9 100644 --- a/app/pages/checklists/[checklistId].vue +++ b/app/pages/checklists/[checklistId].vue @@ -146,7 +146,7 @@ try { isSearching.value = true; - const resultPromise = $fetch('/api/inventory', { + const resultPromise = $fetch('/api/search/checklist-inventory', { params: { search: searchString, checklistId: checklistId diff --git a/app/pages/inventory.vue b/app/pages/inventory.vue index dd29f13..7dc0123 100644 --- a/app/pages/inventory.vue +++ b/app/pages/inventory.vue @@ -50,14 +50,14 @@ const isSearching = ref(false); const options = ref([]); - const { equipment, updateEquipment } = await useUserEquipment() + const { equipment, refetchEquipment } = await useUserEquipment() const hasItems = computed(() => equipment.value.length > 0) async function search(searchString: string) { try { isSearching.value = true; - const resultPromise = $fetch('/api/equipment', { + const resultPromise = $fetch('/api/search/equipment', { params: { searchString, filterOwned: true @@ -81,7 +81,7 @@ async function addItem(item: EquipmentItem) { try { - await $fetch('/api/equipment', { + await $fetch('/api/inventory', { method: 'POST', body: { @@ -91,7 +91,7 @@ options.value = options.value.filter(({ id }) => id !== item.id) - await updateEquipment() + await refetchEquipment() } catch (error) { console.error(error) } @@ -99,11 +99,11 @@ async function removeItem(item: EquipmentItem) { try { - await $fetch(`/api/user/equipment/${item.id}`, { + await $fetch(`/api/inventory/${item.id}`, { method: 'DELETE' }) - await updateEquipment() + await refetchEquipment() } catch (error) { console.error(error) } diff --git a/app/pages/manager/equipment/_add.vue b/app/pages/manager/equipment/_add.vue deleted file mode 100644 index 57e21c1..0000000 --- a/app/pages/manager/equipment/_add.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - Add item - - - - - - - diff --git a/app/pages/manager/equipment/add.vue b/app/pages/manager/equipment/add.vue index 0f0bd4c..5a768ec 100644 --- a/app/pages/manager/equipment/add.vue +++ b/app/pages/manager/equipment/add.vue @@ -1,14 +1,292 @@ - Add page + + + + + + + + + + + + + + + + + + + Add equipment + + + + diff --git a/app/pages/manager/equipment/index.vue b/app/pages/manager/equipment/index.vue index 9a54c37..79b8d24 100644 --- a/app/pages/manager/equipment/index.vue +++ b/app/pages/manager/equipment/index.vue @@ -1,50 +1,41 @@ - - + Add item - + - - Types - + + Types + - - Groups - - - - Old form - - + + Groups + + + - - - - {{ item.name }} - - + + diff --git a/constants.ts b/constants.ts index 3499ef6..89f31d6 100644 --- a/constants.ts +++ b/constants.ts @@ -9,11 +9,13 @@ export const publicApiPaths = [ export const limits = { maxChecklistNameLength: 32, + maxEquipmentAttributeNameLength: 32, + maxEquipmentDescriptionLength: 1024, + maxEquipmentGroupNameLength: 32, maxEquipmentItemNameLength: 64, + maxEquipmentItemStatusLength: 16, maxEquipmentTypeNameLength: 32, - maxEquipmentGroupNameLength: 32, - maxEquipmentAttributeNameLength: 32, - maxOAuthProviderTypeLength: 32, maxOAuthProviderNameLength: 32, + maxOAuthProviderTypeLength: 32, maxUserNameLength: 32 } diff --git a/nuxt.config.ts b/nuxt.config.ts index 1d81d7e..e198437 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -44,6 +44,17 @@ export default defineNuxtConfig({ } }, + vue: { + compilerOptions: { + /** + * We're using new `` customizations + * + * @see [RFC Customizable Select](https://developer.chrome.com/blog/rfc-customizable-select?hl=en) + */ + isCustomElement: (tag) => tag === 'selectedoption' + } + }, + vite: { css: { preprocessorOptions: { diff --git a/server/api/admin/create-equipment.post.ts b/server/api/admin/create-equipment.post.ts deleted file mode 100644 index 371e213..0000000 --- a/server/api/admin/create-equipment.post.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as v from 'valibot' - -const bodySchema = v.object({ - name: v.pipe(v.string(), v.minLength(1)), - weight: v.number() -}) - -function validateBody(body: unknown) { - return v.parse(bodySchema, body) -} - -export default defineEventHandler(async (event) => { - const { db } = event.context - const body = await readValidatedBody(event, validateBody) - const { name, weight } = body - - await validateAdmin(event, { - force: true - }) - - const [foundItem] = await db - .insert(tables.equipment) - .values({ - name, - weight - }) - .returning({ - itemId: tables.equipment.id - }) - - if (foundItem === undefined) { - throw createError({ - statusCode: 500, - message: 'Failed to create equipment' - }) - } - - setResponseStatus(event, 201) - - return { - itemId: foundItem.itemId - } -}) diff --git a/server/api/equipment/index.post.ts b/server/api/equipment/index.post.ts index d39e12c..0e00e10 100644 --- a/server/api/equipment/index.post.ts +++ b/server/api/equipment/index.post.ts @@ -1,7 +1,42 @@ import * as v from 'valibot' +import { limits } from '~~/constants' + +type EquipmentStatus = 'draft' | 'active' const bodySchema = v.object({ - equipmentId: idValidatorNumber + name: v.pipe( + v.string(), + v.nonEmpty(), + v.maxLength(limits.maxEquipmentItemNameLength) + ), + + description: v.union([ + v.undefined(), + + v.pipe( + v.string(), + v.nonEmpty(), + v.maxLength(limits.maxEquipmentDescriptionLength) + ) + ]), + + weight: v.pipe( + v.number(), + v.integer(), + v.minValue(0) + ), + + typeId: v.pipe( + v.number(), + v.integer(), + v.minValue(1) + ), + + groupId: v.pipe( + v.number(), + v.integer(), + v.minValue(1) + ) }) function validateBody(body: unknown) { @@ -12,21 +47,30 @@ export default defineEventHandler(async (event) => { const { db } = event.context const userId = await validateSessionUser(event) const body = await readValidatedBody(event, validateBody) - const { equipmentId } = body - - try { - await db - .insert(tables.userEquipment) - .values({ - userId, - equipmentId - }) - - setResponseStatus(event, 201) - } catch { + const status: EquipmentStatus = 'draft' + const description = body.description ?? null + + const [inserted] = await db + .insert(tables.equipment) + .values({ + description, + status, + creatorId: userId, + name: body.name, + weight: body.weight, + equipmentTypeId: body.typeId, + equipmentGroupId: body.groupId + }) + .returning({ + id: tables.equipment.id + }) + + if (inserted?.id === undefined) { throw createError({ - statusCode: 400, - message: 'Cannot assign equipment to user' + statusCode: 500, + message: 'Failed to create equipment item' }) } + + setResponseStatus(event, 201) }) diff --git a/server/api/user/equipment/[id].delete.ts b/server/api/inventory/[id].delete.ts similarity index 100% rename from server/api/user/equipment/[id].delete.ts rename to server/api/inventory/[id].delete.ts diff --git a/server/api/inventory/index.get.ts b/server/api/inventory/index.get.ts index 7b4f561..b32c4cf 100644 --- a/server/api/inventory/index.get.ts +++ b/server/api/inventory/index.get.ts @@ -1,22 +1,14 @@ -import { and, asc, eq, isNull, like } from 'drizzle-orm' +import { and, asc, eq } from 'drizzle-orm' -interface ReturnData { - readonly id: number; - readonly name: string; -} - -export default defineEventHandler(async (event) : Promise => { +export default defineEventHandler(async (event) => { const userId = await validateSessionUser(event) - const { search, checklistId } = getQuery(event) - - if (typeof search !== 'string' || typeof checklistId !== 'string') { - return [] - } const result = await event.context.db .select({ id: tables.equipment.id, - name: tables.equipment.name + name: tables.equipment.name, + weight: tables.equipment.weight, + createdAt: tables.equipment.createdAt }) .from(tables.equipment) .innerJoin( @@ -26,22 +18,7 @@ export default defineEventHandler(async (event) : Promise => { eq(tables.userEquipment.equipmentId, tables.equipment.id) ) ) - .leftJoin( - tables.checklistItems, - and( - eq(tables.checklistItems.equipmentId, tables.equipment.id), - eq(tables.checklistItems.checklistId, checklistId) - ) - ) - .where( - and( - isNull(tables.checklistItems.id), - like(tables.equipment.name, `%${search}%`) - ) - ) - .orderBy( - asc(tables.equipment.name) - ) + .orderBy(asc(tables.equipment.name)) .limit(100) return result diff --git a/server/api/inventory/index.post.ts b/server/api/inventory/index.post.ts new file mode 100644 index 0000000..d39e12c --- /dev/null +++ b/server/api/inventory/index.post.ts @@ -0,0 +1,32 @@ +import * as v from 'valibot' + +const bodySchema = v.object({ + equipmentId: idValidatorNumber +}) + +function validateBody(body: unknown) { + return v.parse(bodySchema, body) +} + +export default defineEventHandler(async (event) => { + const { db } = event.context + const userId = await validateSessionUser(event) + const body = await readValidatedBody(event, validateBody) + const { equipmentId } = body + + try { + await db + .insert(tables.userEquipment) + .values({ + userId, + equipmentId + }) + + setResponseStatus(event, 201) + } catch { + throw createError({ + statusCode: 400, + message: 'Cannot assign equipment to user' + }) + } +}) diff --git a/server/api/search/checklist-inventory.get.ts b/server/api/search/checklist-inventory.get.ts new file mode 100644 index 0000000..7b4f561 --- /dev/null +++ b/server/api/search/checklist-inventory.get.ts @@ -0,0 +1,48 @@ +import { and, asc, eq, isNull, like } from 'drizzle-orm' + +interface ReturnData { + readonly id: number; + readonly name: string; +} + +export default defineEventHandler(async (event) : Promise => { + const userId = await validateSessionUser(event) + const { search, checklistId } = getQuery(event) + + if (typeof search !== 'string' || typeof checklistId !== 'string') { + return [] + } + + const result = await event.context.db + .select({ + id: tables.equipment.id, + name: tables.equipment.name + }) + .from(tables.equipment) + .innerJoin( + tables.userEquipment, + and( + eq(tables.userEquipment.userId, userId), + eq(tables.userEquipment.equipmentId, tables.equipment.id) + ) + ) + .leftJoin( + tables.checklistItems, + and( + eq(tables.checklistItems.equipmentId, tables.equipment.id), + eq(tables.checklistItems.checklistId, checklistId) + ) + ) + .where( + and( + isNull(tables.checklistItems.id), + like(tables.equipment.name, `%${search}%`) + ) + ) + .orderBy( + asc(tables.equipment.name) + ) + .limit(100) + + return result +}) diff --git a/server/api/equipment/index.get.ts b/server/api/search/equipment.get.ts similarity index 100% rename from server/api/equipment/index.get.ts rename to server/api/search/equipment.get.ts diff --git a/server/api/user/equipment/index.get.ts b/server/api/user/equipment/index.get.ts deleted file mode 100644 index b32c4cf..0000000 --- a/server/api/user/equipment/index.get.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { and, asc, eq } from 'drizzle-orm' - -export default defineEventHandler(async (event) => { - const userId = await validateSessionUser(event) - - const result = await event.context.db - .select({ - id: tables.equipment.id, - name: tables.equipment.name, - weight: tables.equipment.weight, - createdAt: tables.equipment.createdAt - }) - .from(tables.equipment) - .innerJoin( - tables.userEquipment, - and( - eq(tables.userEquipment.userId, userId), - eq(tables.userEquipment.equipmentId, tables.equipment.id) - ) - ) - .orderBy(asc(tables.equipment.name)) - .limit(100) - - return result -}) diff --git a/server/database/migrations/0002_equipment-description-check.sql b/server/database/migrations/0002_equipment-description-check.sql new file mode 100644 index 0000000..cbf597e --- /dev/null +++ b/server/database/migrations/0002_equipment-description-check.sql @@ -0,0 +1,6 @@ +-- Purpose: Add a check constraint to the description column of +-- the equipment table to ensure that the length of the description is +-- less than or equal to 1024 characters. +ALTER TABLE equipment +ADD CONSTRAINT equipment_description_check +CHECK (char_length(description) <= 1024); diff --git a/server/database/migrations/0003_eager_solo.sql b/server/database/migrations/0003_eager_solo.sql new file mode 100644 index 0000000..e1bc642 --- /dev/null +++ b/server/database/migrations/0003_eager_solo.sql @@ -0,0 +1,7 @@ +ALTER TABLE "equipment" ADD COLUMN "userId" "ulid";--> statement-breakpoint +ALTER TABLE "equipment" ADD COLUMN "status" varchar(16) NOT NULL;--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "equipment" ADD CONSTRAINT "equipment_userId_users_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE cascade; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/server/database/migrations/0004_nice_blockbuster.sql b/server/database/migrations/0004_nice_blockbuster.sql new file mode 100644 index 0000000..147f693 --- /dev/null +++ b/server/database/migrations/0004_nice_blockbuster.sql @@ -0,0 +1,8 @@ +ALTER TABLE "equipment" RENAME COLUMN "userId" TO "creatorId";--> statement-breakpoint +ALTER TABLE "equipment" DROP CONSTRAINT "equipment_userId_users_id_fk"; +--> statement-breakpoint +DO $$ BEGIN + ALTER TABLE "equipment" ADD CONSTRAINT "equipment_creatorId_users_id_fk" FOREIGN KEY ("creatorId") REFERENCES "public"."users"("id") ON DELETE set null ON UPDATE cascade; +EXCEPTION + WHEN duplicate_object THEN null; +END $$; diff --git a/server/database/migrations/meta/0002_snapshot.json b/server/database/migrations/meta/0002_snapshot.json new file mode 100644 index 0000000..6382677 --- /dev/null +++ b/server/database/migrations/meta/0002_snapshot.json @@ -0,0 +1,804 @@ +{ + "id": "20b1130e-84b3-46e2-a4a4-491ea813a057", + "prevId": "cae70a06-cd81-4810-bf4d-d6393003a156", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.checklistItems": { + "name": "checklistItems", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "checklistId": { + "name": "checklistId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "checklistItems_checklistId_checklists_id_fk": { + "name": "checklistItems_checklistId_checklists_id_fk", + "tableFrom": "checklistItems", + "columnsFrom": [ + "checklistId" + ], + "tableTo": "checklists", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + }, + "checklistItems_equipmentId_equipment_id_fk": { + "name": "checklistItems_equipmentId_equipment_id_fk", + "tableFrom": "checklistItems", + "columnsFrom": [ + "equipmentId" + ], + "tableTo": "equipment", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "checklistItems_checklistId_equipmentId_unique": { + "name": "checklistItems_checklistId_equipmentId_unique", + "columns": [ + "checklistId", + "equipmentId" + ], + "nullsNotDistinct": false + } + } + }, + "public.checklists": { + "name": "checklists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "createdAtIndex": { + "name": "createdAtIndex", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "checklists_userId_users_id_fk": { + "name": "checklists_userId_users_id_fk", + "tableFrom": "checklists", + "columnsFrom": [ + "userId" + ], + "tableTo": "users", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipment": { + "name": "equipment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "weight": { + "name": "weight", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "equipmentTypeId": { + "name": "equipmentTypeId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "equipmentGroupId": { + "name": "equipmentGroupId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "equipment_equipmentTypeId_index": { + "name": "equipment_equipmentTypeId_index", + "columns": [ + { + "expression": "equipmentTypeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + }, + "equipment_equipmentGroupId_index": { + "name": "equipment_equipmentGroupId_index", + "columns": [ + { + "expression": "equipmentGroupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "equipment_equipmentTypeId_equipmentTypes_id_fk": { + "name": "equipment_equipmentTypeId_equipmentTypes_id_fk", + "tableFrom": "equipment", + "columnsFrom": [ + "equipmentTypeId" + ], + "tableTo": "equipmentTypes", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "set null" + }, + "equipment_equipmentGroupId_equipmentGroups_id_fk": { + "name": "equipment_equipmentGroupId_equipmentGroups_id_fk", + "tableFrom": "equipment", + "columnsFrom": [ + "equipmentGroupId" + ], + "tableTo": "equipmentGroups", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "set null" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentAttributeValues": { + "name": "equipmentAttributeValues", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "equipmentAttributeId": { + "name": "equipmentAttributeId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "equipmentAttributeValues_equipmentId_index": { + "name": "equipmentAttributeValues_equipmentId_index", + "columns": [ + { + "expression": "equipmentId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + }, + "equipmentAttributeValues_equipmentAttributeId_index": { + "name": "equipmentAttributeValues_equipmentAttributeId_index", + "columns": [ + { + "expression": "equipmentAttributeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "equipmentAttributeValues_equipmentId_equipment_id_fk": { + "name": "equipmentAttributeValues_equipmentId_equipment_id_fk", + "tableFrom": "equipmentAttributeValues", + "columnsFrom": [ + "equipmentId" + ], + "tableTo": "equipment", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + }, + "equipmentAttributeValues_equipmentAttributeId_equipmentAttributes_id_fk": { + "name": "equipmentAttributeValues_equipmentAttributeId_equipmentAttributes_id_fk", + "tableFrom": "equipmentAttributeValues", + "columnsFrom": [ + "equipmentAttributeId" + ], + "tableTo": "equipmentAttributes", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "equipmentAttributeValues_equipmentId_equipmentAttributeId_unique": { + "name": "equipmentAttributeValues_equipmentId_equipmentAttributeId_unique", + "columns": [ + "equipmentId", + "equipmentAttributeId" + ], + "nullsNotDistinct": false + } + } + }, + "public.equipmentAttributes": { + "name": "equipmentAttributes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "dataType": { + "name": "dataType", + "type": "equipmentAttributeDataType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentGroups": { + "name": "equipmentGroups", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentTypeAttributes": { + "name": "equipmentTypeAttributes", + "schema": "", + "columns": { + "equipmentTypeId": { + "name": "equipmentTypeId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "equipmentAttributeId": { + "name": "equipmentAttributeId", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "equipmentTypeAttributes_equipmentTypeId_index": { + "name": "equipmentTypeAttributes_equipmentTypeId_index", + "columns": [ + { + "expression": "equipmentTypeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + }, + "equipmentTypeAttributes_equipmentAttributeId_index": { + "name": "equipmentTypeAttributes_equipmentAttributeId_index", + "columns": [ + { + "expression": "equipmentAttributeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": { + "equipmentTypeAttributes_equipmentTypeId_equipmentTypes_id_fk": { + "name": "equipmentTypeAttributes_equipmentTypeId_equipmentTypes_id_fk", + "tableFrom": "equipmentTypeAttributes", + "columnsFrom": [ + "equipmentTypeId" + ], + "tableTo": "equipmentTypes", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + }, + "equipmentTypeAttributes_equipmentAttributeId_equipmentAttributes_id_fk": { + "name": "equipmentTypeAttributes_equipmentAttributeId_equipmentAttributes_id_fk", + "tableFrom": "equipmentTypeAttributes", + "columnsFrom": [ + "equipmentAttributeId" + ], + "tableTo": "equipmentAttributes", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": { + "equipmentTypeAttributes_equipmentTypeId_equipmentAttributeId_pk": { + "name": "equipmentTypeAttributes_equipmentTypeId_equipmentAttributeId_pk", + "columns": [ + "equipmentTypeId", + "equipmentAttributeId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.equipmentTypes": { + "name": "equipmentTypes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "equipmentTypes_name_index": { + "name": "equipmentTypes_name_index", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "with": {}, + "method": "btree", + "concurrently": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.oauthAccounts": { + "name": "oauthAccounts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "providerId": { + "name": "providerId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "accountId": { + "name": "accountId", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "oauthAccounts_userId_users_id_fk": { + "name": "oauthAccounts_userId_users_id_fk", + "tableFrom": "oauthAccounts", + "columnsFrom": [ + "userId" + ], + "tableTo": "users", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + }, + "oauthAccounts_providerId_oauthProviders_id_fk": { + "name": "oauthAccounts_providerId_oauthProviders_id_fk", + "tableFrom": "oauthAccounts", + "columnsFrom": [ + "providerId" + ], + "tableTo": "oauthProviders", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauthAccounts_providerId_accountId_unique": { + "name": "oauthAccounts_providerId_accountId_unique", + "columns": [ + "providerId", + "accountId" + ], + "nullsNotDistinct": false + } + } + }, + "public.oauthProviders": { + "name": "oauthProviders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauthProviders_type_unique": { + "name": "oauthProviders_type_unique", + "columns": [ + "type" + ], + "nullsNotDistinct": false + } + } + }, + "public.userEquipment": { + "name": "userEquipment", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": false + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "userEquipment_userId_users_id_fk": { + "name": "userEquipment_userId_users_id_fk", + "tableFrom": "userEquipment", + "columnsFrom": [ + "userId" + ], + "tableTo": "users", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + }, + "userEquipment_equipmentId_equipment_id_fk": { + "name": "userEquipment_equipmentId_equipment_id_fk", + "tableFrom": "userEquipment", + "columnsFrom": [ + "equipmentId" + ], + "tableTo": "equipment", + "columnsTo": [ + "id" + ], + "onUpdate": "cascade", + "onDelete": "cascade" + } + }, + "compositePrimaryKeys": { + "userEquipment_userId_equipmentId_pk": { + "name": "userEquipment_userId_equipmentId_pk", + "columns": [ + "userId", + "equipmentId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "isAdmin": { + "name": "isAdmin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.equipmentAttributeDataType": { + "name": "equipmentAttributeDataType", + "schema": "public", + "values": [ + "boolean", + "string", + "integer", + "decimal" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/server/database/migrations/meta/0003_snapshot.json b/server/database/migrations/meta/0003_snapshot.json new file mode 100644 index 0000000..627ee7d --- /dev/null +++ b/server/database/migrations/meta/0003_snapshot.json @@ -0,0 +1,829 @@ +{ + "id": "24dc87a8-7eed-4db1-ba8c-be01124dfd32", + "prevId": "20b1130e-84b3-46e2-a4a4-491ea813a057", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.checklistItems": { + "name": "checklistItems", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "checklistId": { + "name": "checklistId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "checklistItems_checklistId_checklists_id_fk": { + "name": "checklistItems_checklistId_checklists_id_fk", + "tableFrom": "checklistItems", + "tableTo": "checklists", + "columnsFrom": [ + "checklistId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "checklistItems_equipmentId_equipment_id_fk": { + "name": "checklistItems_equipmentId_equipment_id_fk", + "tableFrom": "checklistItems", + "tableTo": "equipment", + "columnsFrom": [ + "equipmentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "checklistItems_checklistId_equipmentId_unique": { + "name": "checklistItems_checklistId_equipmentId_unique", + "nullsNotDistinct": false, + "columns": [ + "checklistId", + "equipmentId" + ] + } + } + }, + "public.checklists": { + "name": "checklists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "createdAtIndex": { + "name": "createdAtIndex", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "checklists_userId_users_id_fk": { + "name": "checklists_userId_users_id_fk", + "tableFrom": "checklists", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipment": { + "name": "equipment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "weight": { + "name": "weight", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "equipmentTypeId": { + "name": "equipmentTypeId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "equipmentGroupId": { + "name": "equipmentGroupId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "equipment_equipmentTypeId_index": { + "name": "equipment_equipmentTypeId_index", + "columns": [ + { + "expression": "equipmentTypeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "equipment_equipmentGroupId_index": { + "name": "equipment_equipmentGroupId_index", + "columns": [ + { + "expression": "equipmentGroupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "equipment_userId_users_id_fk": { + "name": "equipment_userId_users_id_fk", + "tableFrom": "equipment", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "equipment_equipmentTypeId_equipmentTypes_id_fk": { + "name": "equipment_equipmentTypeId_equipmentTypes_id_fk", + "tableFrom": "equipment", + "tableTo": "equipmentTypes", + "columnsFrom": [ + "equipmentTypeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "equipment_equipmentGroupId_equipmentGroups_id_fk": { + "name": "equipment_equipmentGroupId_equipmentGroups_id_fk", + "tableFrom": "equipment", + "tableTo": "equipmentGroups", + "columnsFrom": [ + "equipmentGroupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentAttributeValues": { + "name": "equipmentAttributeValues", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "equipmentAttributeId": { + "name": "equipmentAttributeId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "equipmentAttributeValues_equipmentId_index": { + "name": "equipmentAttributeValues_equipmentId_index", + "columns": [ + { + "expression": "equipmentId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "equipmentAttributeValues_equipmentAttributeId_index": { + "name": "equipmentAttributeValues_equipmentAttributeId_index", + "columns": [ + { + "expression": "equipmentAttributeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "equipmentAttributeValues_equipmentId_equipment_id_fk": { + "name": "equipmentAttributeValues_equipmentId_equipment_id_fk", + "tableFrom": "equipmentAttributeValues", + "tableTo": "equipment", + "columnsFrom": [ + "equipmentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "equipmentAttributeValues_equipmentAttributeId_equipmentAttributes_id_fk": { + "name": "equipmentAttributeValues_equipmentAttributeId_equipmentAttributes_id_fk", + "tableFrom": "equipmentAttributeValues", + "tableTo": "equipmentAttributes", + "columnsFrom": [ + "equipmentAttributeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "equipmentAttributeValues_equipmentId_equipmentAttributeId_unique": { + "name": "equipmentAttributeValues_equipmentId_equipmentAttributeId_unique", + "nullsNotDistinct": false, + "columns": [ + "equipmentId", + "equipmentAttributeId" + ] + } + } + }, + "public.equipmentAttributes": { + "name": "equipmentAttributes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "dataType": { + "name": "dataType", + "type": "equipmentAttributeDataType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentGroups": { + "name": "equipmentGroups", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentTypeAttributes": { + "name": "equipmentTypeAttributes", + "schema": "", + "columns": { + "equipmentTypeId": { + "name": "equipmentTypeId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "equipmentAttributeId": { + "name": "equipmentAttributeId", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "equipmentTypeAttributes_equipmentTypeId_index": { + "name": "equipmentTypeAttributes_equipmentTypeId_index", + "columns": [ + { + "expression": "equipmentTypeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "equipmentTypeAttributes_equipmentAttributeId_index": { + "name": "equipmentTypeAttributes_equipmentAttributeId_index", + "columns": [ + { + "expression": "equipmentAttributeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "equipmentTypeAttributes_equipmentTypeId_equipmentTypes_id_fk": { + "name": "equipmentTypeAttributes_equipmentTypeId_equipmentTypes_id_fk", + "tableFrom": "equipmentTypeAttributes", + "tableTo": "equipmentTypes", + "columnsFrom": [ + "equipmentTypeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "equipmentTypeAttributes_equipmentAttributeId_equipmentAttributes_id_fk": { + "name": "equipmentTypeAttributes_equipmentAttributeId_equipmentAttributes_id_fk", + "tableFrom": "equipmentTypeAttributes", + "tableTo": "equipmentAttributes", + "columnsFrom": [ + "equipmentAttributeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "equipmentTypeAttributes_equipmentTypeId_equipmentAttributeId_pk": { + "name": "equipmentTypeAttributes_equipmentTypeId_equipmentAttributeId_pk", + "columns": [ + "equipmentTypeId", + "equipmentAttributeId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.equipmentTypes": { + "name": "equipmentTypes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "equipmentTypes_name_index": { + "name": "equipmentTypes_name_index", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.oauthAccounts": { + "name": "oauthAccounts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "providerId": { + "name": "providerId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "accountId": { + "name": "accountId", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "oauthAccounts_userId_users_id_fk": { + "name": "oauthAccounts_userId_users_id_fk", + "tableFrom": "oauthAccounts", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "oauthAccounts_providerId_oauthProviders_id_fk": { + "name": "oauthAccounts_providerId_oauthProviders_id_fk", + "tableFrom": "oauthAccounts", + "tableTo": "oauthProviders", + "columnsFrom": [ + "providerId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauthAccounts_providerId_accountId_unique": { + "name": "oauthAccounts_providerId_accountId_unique", + "nullsNotDistinct": false, + "columns": [ + "providerId", + "accountId" + ] + } + } + }, + "public.oauthProviders": { + "name": "oauthProviders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauthProviders_type_unique": { + "name": "oauthProviders_type_unique", + "nullsNotDistinct": false, + "columns": [ + "type" + ] + } + } + }, + "public.userEquipment": { + "name": "userEquipment", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": false + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "userEquipment_userId_users_id_fk": { + "name": "userEquipment_userId_users_id_fk", + "tableFrom": "userEquipment", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "userEquipment_equipmentId_equipment_id_fk": { + "name": "userEquipment_equipmentId_equipment_id_fk", + "tableFrom": "userEquipment", + "tableTo": "equipment", + "columnsFrom": [ + "equipmentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "userEquipment_userId_equipmentId_pk": { + "name": "userEquipment_userId_equipmentId_pk", + "columns": [ + "userId", + "equipmentId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "isAdmin": { + "name": "isAdmin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.equipmentAttributeDataType": { + "name": "equipmentAttributeDataType", + "schema": "public", + "values": [ + "boolean", + "string", + "integer", + "decimal" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/server/database/migrations/meta/0004_snapshot.json b/server/database/migrations/meta/0004_snapshot.json new file mode 100644 index 0000000..7b3815a --- /dev/null +++ b/server/database/migrations/meta/0004_snapshot.json @@ -0,0 +1,829 @@ +{ + "id": "4ba59159-5a11-4967-a8cb-1d97e736f7e9", + "prevId": "24dc87a8-7eed-4db1-ba8c-be01124dfd32", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.checklistItems": { + "name": "checklistItems", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "checklistId": { + "name": "checklistId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "checklistItems_checklistId_checklists_id_fk": { + "name": "checklistItems_checklistId_checklists_id_fk", + "tableFrom": "checklistItems", + "tableTo": "checklists", + "columnsFrom": [ + "checklistId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "checklistItems_equipmentId_equipment_id_fk": { + "name": "checklistItems_equipmentId_equipment_id_fk", + "tableFrom": "checklistItems", + "tableTo": "equipment", + "columnsFrom": [ + "equipmentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "checklistItems_checklistId_equipmentId_unique": { + "name": "checklistItems_checklistId_equipmentId_unique", + "nullsNotDistinct": false, + "columns": [ + "checklistId", + "equipmentId" + ] + } + } + }, + "public.checklists": { + "name": "checklists", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "createdAtIndex": { + "name": "createdAtIndex", + "columns": [ + { + "expression": "createdAt", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "checklists_userId_users_id_fk": { + "name": "checklists_userId_users_id_fk", + "tableFrom": "checklists", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipment": { + "name": "equipment", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "creatorId": { + "name": "creatorId", + "type": "ulid", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "varchar(16)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "weight": { + "name": "weight", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "equipmentTypeId": { + "name": "equipmentTypeId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "equipmentGroupId": { + "name": "equipmentGroupId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "equipment_equipmentTypeId_index": { + "name": "equipment_equipmentTypeId_index", + "columns": [ + { + "expression": "equipmentTypeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "equipment_equipmentGroupId_index": { + "name": "equipment_equipmentGroupId_index", + "columns": [ + { + "expression": "equipmentGroupId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "equipment_creatorId_users_id_fk": { + "name": "equipment_creatorId_users_id_fk", + "tableFrom": "equipment", + "tableTo": "users", + "columnsFrom": [ + "creatorId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "equipment_equipmentTypeId_equipmentTypes_id_fk": { + "name": "equipment_equipmentTypeId_equipmentTypes_id_fk", + "tableFrom": "equipment", + "tableTo": "equipmentTypes", + "columnsFrom": [ + "equipmentTypeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + }, + "equipment_equipmentGroupId_equipmentGroups_id_fk": { + "name": "equipment_equipmentGroupId_equipmentGroups_id_fk", + "tableFrom": "equipment", + "tableTo": "equipmentGroups", + "columnsFrom": [ + "equipmentGroupId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentAttributeValues": { + "name": "equipmentAttributeValues", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "equipmentAttributeId": { + "name": "equipmentAttributeId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "varchar", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "equipmentAttributeValues_equipmentId_index": { + "name": "equipmentAttributeValues_equipmentId_index", + "columns": [ + { + "expression": "equipmentId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "equipmentAttributeValues_equipmentAttributeId_index": { + "name": "equipmentAttributeValues_equipmentAttributeId_index", + "columns": [ + { + "expression": "equipmentAttributeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "equipmentAttributeValues_equipmentId_equipment_id_fk": { + "name": "equipmentAttributeValues_equipmentId_equipment_id_fk", + "tableFrom": "equipmentAttributeValues", + "tableTo": "equipment", + "columnsFrom": [ + "equipmentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "equipmentAttributeValues_equipmentAttributeId_equipmentAttributes_id_fk": { + "name": "equipmentAttributeValues_equipmentAttributeId_equipmentAttributes_id_fk", + "tableFrom": "equipmentAttributeValues", + "tableTo": "equipmentAttributes", + "columnsFrom": [ + "equipmentAttributeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "equipmentAttributeValues_equipmentId_equipmentAttributeId_unique": { + "name": "equipmentAttributeValues_equipmentId_equipmentAttributeId_unique", + "nullsNotDistinct": false, + "columns": [ + "equipmentId", + "equipmentAttributeId" + ] + } + } + }, + "public.equipmentAttributes": { + "name": "equipmentAttributes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "dataType": { + "name": "dataType", + "type": "equipmentAttributeDataType", + "typeSchema": "public", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentGroups": { + "name": "equipmentGroups", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.equipmentTypeAttributes": { + "name": "equipmentTypeAttributes", + "schema": "", + "columns": { + "equipmentTypeId": { + "name": "equipmentTypeId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "equipmentAttributeId": { + "name": "equipmentAttributeId", + "type": "integer", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "equipmentTypeAttributes_equipmentTypeId_index": { + "name": "equipmentTypeAttributes_equipmentTypeId_index", + "columns": [ + { + "expression": "equipmentTypeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "equipmentTypeAttributes_equipmentAttributeId_index": { + "name": "equipmentTypeAttributes_equipmentAttributeId_index", + "columns": [ + { + "expression": "equipmentAttributeId", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "equipmentTypeAttributes_equipmentTypeId_equipmentTypes_id_fk": { + "name": "equipmentTypeAttributes_equipmentTypeId_equipmentTypes_id_fk", + "tableFrom": "equipmentTypeAttributes", + "tableTo": "equipmentTypes", + "columnsFrom": [ + "equipmentTypeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "equipmentTypeAttributes_equipmentAttributeId_equipmentAttributes_id_fk": { + "name": "equipmentTypeAttributes_equipmentAttributeId_equipmentAttributes_id_fk", + "tableFrom": "equipmentTypeAttributes", + "tableTo": "equipmentAttributes", + "columnsFrom": [ + "equipmentAttributeId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "equipmentTypeAttributes_equipmentTypeId_equipmentAttributeId_pk": { + "name": "equipmentTypeAttributes_equipmentTypeId_equipmentAttributeId_pk", + "columns": [ + "equipmentTypeId", + "equipmentAttributeId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.equipmentTypes": { + "name": "equipmentTypes", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updatedAt": { + "name": "updatedAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "equipmentTypes_name_index": { + "name": "equipmentTypes_name_index", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.oauthAccounts": { + "name": "oauthAccounts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": true + }, + "providerId": { + "name": "providerId", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "accountId": { + "name": "accountId", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "oauthAccounts_userId_users_id_fk": { + "name": "oauthAccounts_userId_users_id_fk", + "tableFrom": "oauthAccounts", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "oauthAccounts_providerId_oauthProviders_id_fk": { + "name": "oauthAccounts_providerId_oauthProviders_id_fk", + "tableFrom": "oauthAccounts", + "tableTo": "oauthProviders", + "columnsFrom": [ + "providerId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauthAccounts_providerId_accountId_unique": { + "name": "oauthAccounts_providerId_accountId_unique", + "nullsNotDistinct": false, + "columns": [ + "providerId", + "accountId" + ] + } + } + }, + "public.oauthProviders": { + "name": "oauthProviders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": true + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "oauthProviders_type_unique": { + "name": "oauthProviders_type_unique", + "nullsNotDistinct": false, + "columns": [ + "type" + ] + } + } + }, + "public.userEquipment": { + "name": "userEquipment", + "schema": "", + "columns": { + "userId": { + "name": "userId", + "type": "ulid", + "primaryKey": false, + "notNull": false + }, + "equipmentId": { + "name": "equipmentId", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "userEquipment_userId_users_id_fk": { + "name": "userEquipment_userId_users_id_fk", + "tableFrom": "userEquipment", + "tableTo": "users", + "columnsFrom": [ + "userId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + }, + "userEquipment_equipmentId_equipment_id_fk": { + "name": "userEquipment_equipmentId_equipment_id_fk", + "tableFrom": "userEquipment", + "tableTo": "equipment", + "columnsFrom": [ + "equipmentId" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "cascade" + } + }, + "compositePrimaryKeys": { + "userEquipment_userId_equipmentId_pk": { + "name": "userEquipment_userId_equipmentId_pk", + "columns": [ + "userId", + "equipmentId" + ] + } + }, + "uniqueConstraints": {} + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "ulid", + "primaryKey": true, + "notNull": true, + "default": "gen_ulid()" + }, + "name": { + "name": "name", + "type": "varchar(32)", + "primaryKey": false, + "notNull": false + }, + "createdAt": { + "name": "createdAt", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "isAdmin": { + "name": "isAdmin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.equipmentAttributeDataType": { + "name": "equipmentAttributeDataType", + "schema": "public", + "values": [ + "boolean", + "string", + "integer", + "decimal" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/server/database/migrations/meta/_journal.json b/server/database/migrations/meta/_journal.json index 27840a2..d8142f9 100644 --- a/server/database/migrations/meta/_journal.json +++ b/server/database/migrations/meta/_journal.json @@ -15,6 +15,27 @@ "when": 1727206294447, "tag": "0001_abandoned_redwing", "breakpoints": true + }, + { + "idx": 2, + "version": "7", + "when": 1728326791898, + "tag": "0002_equipment-description-check", + "breakpoints": true + }, + { + "idx": 3, + "version": "7", + "when": 1728327385467, + "tag": "0003_eager_solo", + "breakpoints": true + }, + { + "idx": 4, + "version": "7", + "when": 1728498221877, + "tag": "0004_nice_blockbuster", + "breakpoints": true } ] } \ No newline at end of file diff --git a/server/database/schema.ts b/server/database/schema.ts index 1ae2997..6f8c5ed 100644 --- a/server/database/schema.ts +++ b/server/database/schema.ts @@ -38,24 +38,24 @@ const ulid = customType<{ data: string }>({ export const users = pgTable('users', { id: - ulid('id') + ulid() .notNull() .default(sql`gen_ulid()`) .primaryKey(), - name: varchar('name', { + name: varchar({ length: limits.maxUserNameLength }), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() .defaultNow(), isAdmin: - boolean('isAdmin') + boolean() .notNull() .default(false) }) @@ -69,24 +69,24 @@ export const users = pgTable('users', { export const oauthProviders = pgTable('oauthProviders', { id: - serial('id') + serial() .primaryKey(), type: - varchar('type', { + varchar({ length: limits.maxOAuthProviderTypeLength }) .notNull() .unique(), name: - varchar('name', { + varchar({ length: limits.maxOAuthProviderNameLength }) .notNull(), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() @@ -102,13 +102,13 @@ export const oauthProviders = pgTable('oauthProviders', { export const oauthAccounts = pgTable('oauthAccounts', { id: - ulid('id') + ulid() .notNull() .default(sql`gen_ulid()`) .primaryKey(), userId: - ulid('userId') + ulid() .notNull() .references(() => users.id, { onDelete: 'cascade', @@ -116,7 +116,7 @@ export const oauthAccounts = pgTable('oauthAccounts', { }), providerId: - integer('providerId') + integer() .notNull() .references(() => oauthProviders.id, { onDelete: 'cascade', @@ -124,11 +124,11 @@ export const oauthAccounts = pgTable('oauthAccounts', { }), accountId: - varchar('accountId') + varchar() .notNull(), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() @@ -145,24 +145,24 @@ export const oauthAccounts = pgTable('oauthAccounts', { export const equipmentTypes = pgTable('equipmentTypes', { id: - serial('id') + serial() .primaryKey(), name: - varchar('name', { + varchar({ length: limits.maxEquipmentTypeNameLength }) .notNull(), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() .defaultNow(), updatedAt: - timestamp('updatedAt', { + timestamp({ withTimezone: true }) .notNull() @@ -181,24 +181,24 @@ export const equipmentTypes = pgTable('equipmentTypes', { export const equipmentGroups = pgTable('equipmentGroups', { id: - serial('id') + serial() .primaryKey(), name: - varchar('name', { + varchar({ length: limits.maxEquipmentGroupNameLength }) .notNull(), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() .defaultNow(), updatedAt: - timestamp('updatedAt', { + timestamp({ withTimezone: true }) .notNull() @@ -214,45 +214,58 @@ export const equipmentGroups = pgTable('equipmentGroups', { export const equipment = pgTable('equipment', { id: - serial('id') + serial() .primaryKey(), + creatorId: + ulid() + .references(() => users.id, { + onDelete: 'set null', + onUpdate: 'cascade' + }), + + status: + varchar({ + length: limits.maxEquipmentItemStatusLength + }) + .notNull(), + name: - varchar('name', { + varchar({ length: limits.maxEquipmentItemNameLength }) .notNull(), - description: text('description'), + description: text(), weight: - integer('weight') + integer() .notNull() .default(0), equipmentTypeId: - integer('equipmentTypeId') + integer() .references(() => equipmentTypes.id, { onDelete: 'set null', onUpdate: 'cascade' }), equipmentGroupId: - integer('equipmentGroupId') + integer() .references(() => equipmentGroups.id, { onDelete: 'set null', onUpdate: 'cascade' }), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() .defaultNow(), updatedAt: - timestamp('updatedAt', { + timestamp({ withTimezone: true }) .notNull() @@ -286,17 +299,17 @@ export const equipmentAttributeDataType = pgEnum('equipmentAttributeDataType', [ export const equipmentAttributes = pgTable('equipmentAttributes', { id: - serial('id') + serial() .primaryKey(), name: - varchar('name', { + varchar({ length: limits.maxEquipmentAttributeNameLength }) .notNull(), dataType: - equipmentAttributeDataType('dataType') + equipmentAttributeDataType() .notNull() }) @@ -308,14 +321,14 @@ export const equipmentAttributes = pgTable('equipmentAttributes', { export const equipmentTypeAttributes = pgTable('equipmentTypeAttributes', { equipmentTypeId: - integer('equipmentTypeId') + integer() .references(() => equipmentTypes.id, { onDelete: 'cascade', onUpdate: 'cascade' }), equipmentAttributeId: - integer('equipmentAttributeId') + integer() .references(() => equipmentAttributes.id, { onDelete: 'cascade', onUpdate: 'cascade' @@ -337,11 +350,11 @@ export const equipmentTypeAttributes = pgTable('equipmentTypeAttributes', { export const equipmentAttributeValues = pgTable('equipmentAttributeValues', { id: - serial('id') + serial() .primaryKey(), equipmentId: - integer('equipmentId') + integer() .notNull() .references(() => equipment.id, { onDelete: 'cascade', @@ -349,7 +362,7 @@ export const equipmentAttributeValues = pgTable('equipmentAttributeValues', { }), equipmentAttributeId: - integer('equipmentAttributeId') + integer() .notNull() .references(() => equipmentAttributes.id, { onDelete: 'cascade', @@ -357,7 +370,7 @@ export const equipmentAttributeValues = pgTable('equipmentAttributeValues', { }), value: - varchar('value') + varchar() .notNull() }, (table) => ({ uniqueEquipmentIdAttributeId: unique().on(table.equipmentId, table.equipmentAttributeId), @@ -373,21 +386,21 @@ export const equipmentAttributeValues = pgTable('equipmentAttributeValues', { export const userEquipment = pgTable('userEquipment', { userId: - ulid('userId') + ulid() .references(() => users.id, { onDelete: 'cascade', onUpdate: 'cascade' }), equipmentId: - integer('equipmentId') + integer() .references(() => equipment.id, { onDelete: 'cascade', onUpdate: 'cascade' }), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() @@ -406,13 +419,13 @@ export const userEquipment = pgTable('userEquipment', { export const checklists = pgTable('checklists', { id: - ulid('id') + ulid() .notNull() .default(sql`gen_ulid()`) .primaryKey(), userId: - ulid('userId') + ulid() .notNull() .references(() => users.id, { onDelete: 'cascade', @@ -420,13 +433,13 @@ export const checklists = pgTable('checklists', { }), name: - varchar('name', { + varchar({ length: limits.maxChecklistNameLength }) .notNull(), createdAt: - timestamp('createdAt', { + timestamp({ withTimezone: true }) .notNull() @@ -445,11 +458,11 @@ export const checklists = pgTable('checklists', { export const checklistItems = pgTable('checklistItems', { id: - serial('id') + serial() .primaryKey(), checklistId: - ulid('checklistId') + ulid() .notNull() .references(() => checklists.id, { onDelete: 'cascade', @@ -457,7 +470,7 @@ export const checklistItems = pgTable('checklistItems', { }), equipmentId: - integer('equipmentId') + integer() .notNull() .references(() => equipment.id, { onDelete: 'cascade', @@ -472,6 +485,7 @@ export const checklistItems = pgTable('checklistItems', { */ export const usersRelations = relations(users, ({ many }) => ({ + equipment: many(equipment), userEquipment: many(userEquipment), checklists: many(checklists), oauthAccounts: many(oauthAccounts) @@ -493,6 +507,7 @@ export const equipmentGroupsRelations = relations(equipmentGroups, ({ many }) => export const equipmentRelations = relations(equipment, ({ many, one }) => ({ userEquipment: many(userEquipment), checklistItems: many(checklistItems), + equipmentAttributeValues: many(equipmentAttributeValues), equipmentType: one(equipmentTypes, { fields: [equipment.equipmentTypeId], @@ -504,7 +519,10 @@ export const equipmentRelations = relations(equipment, ({ many, one }) => ({ references: [equipmentGroups.id] }), - equipmentAttributeValues: many(equipmentAttributeValues) + creatorId: one(users, { + fields: [equipment.creatorId], + references: [users.id] + }) })) export const equipmentAttributesRelations = relations(equipmentAttributes, ({ many }) => ({ diff --git a/tools/migrate.ts b/tools/migrate.ts index 34ac44a..ee2ab04 100644 --- a/tools/migrate.ts +++ b/tools/migrate.ts @@ -30,6 +30,9 @@ async function afterMigration() { /** * Migrate the database + * + * @todo Move to custom migrations + * @see {@link https://orm.drizzle.team/docs/kit-custom-migrations} */ await beforeMigration()