From ed923b93635352cb0e87ab60d24484b7ab63b51f Mon Sep 17 00:00:00 2001 From: beatzaplenty Date: Tue, 25 Nov 2025 09:39:00 +1000 Subject: [PATCH] modified: src/db/index.ts deleted: src/db/seed.test.ts deleted: src/db/seed.ts --- src/db/index.ts | 4 +- src/db/seed.test.ts | 121 ------------------------------------------ src/db/seed.ts | 125 -------------------------------------------- 3 files changed, 1 insertion(+), 249 deletions(-) delete mode 100644 src/db/seed.test.ts delete mode 100644 src/db/seed.ts diff --git a/src/db/index.ts b/src/db/index.ts index 227ae39..4668e75 100644 --- a/src/db/index.ts +++ b/src/db/index.ts @@ -7,7 +7,6 @@ import { PickList } from '../models/PickList'; import { Product } from '../models/Product'; import { ImportExportLog } from '../models/ImportExportLog'; import { applyMigrations } from './migrations'; -import { seedDatabase } from './seed'; export class StockFillDB extends Dexie { products!: Table; @@ -254,5 +253,4 @@ export const db = new StockFillDB(); export const initializeDatabase = async () => { await applyMigrations(db); - await seedDatabase(db); -}; + }; diff --git a/src/db/seed.test.ts b/src/db/seed.test.ts deleted file mode 100644 index d5394e1..0000000 --- a/src/db/seed.test.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { v4 as uuidv4 } from 'uuid'; -import { describe, expect, it } from 'vitest'; -import { seedAreas, seedCategories, seedDatabase, seedProducts } from './seed'; -import { Area } from '../models/Area'; -import { Category } from '../models/Category'; -import { DEFAULT_BULK_NAME, DEFAULT_UNIT_TYPE, Product } from '../models/Product'; -import { StockFillDB } from './index'; - -const normalizeName = (name: string) => name.trim().toLowerCase(); - -class MockTable { - constructor(public items: T[] = []) {} - - async count() { - return this.items.length; - } - - async bulkAdd(records: T[]) { - this.items.push(...records); - } - - async bulkDelete(ids: string[]) { - this.items = this.items.filter((item) => !ids.includes(item.id)); - } - - async toArray() { - return [...this.items]; - } -} - -const buildArea = (overrides: Partial = {}): Area => ({ - id: overrides.id ?? uuidv4(), - name: overrides.name ?? 'Area', - created_at: overrides.created_at ?? Date.now(), - updated_at: overrides.updated_at ?? Date.now(), -}); - -const buildProduct = (overrides: Partial = {}): Product => ({ - id: overrides.id ?? uuidv4(), - name: overrides.name ?? 'Product', - category: overrides.category ?? 'Category', - unit_type: overrides.unit_type ?? DEFAULT_UNIT_TYPE, - bulk_name: overrides.bulk_name ?? DEFAULT_BULK_NAME, - barcode: overrides.barcode, - archived: overrides.archived ?? false, - created_at: overrides.created_at ?? Date.now(), - updated_at: overrides.updated_at ?? Date.now(), -}); - -const buildCategory = (overrides: Partial = {}): Category => ({ - id: overrides.id ?? uuidv4(), - name: overrides.name ?? 'Category', - created_at: overrides.created_at ?? Date.now(), - updated_at: overrides.updated_at ?? Date.now(), -}); - -const createMockDb = (options: { - areas?: Area[]; - products?: Product[]; - categories?: Category[]; -} = {}) => { - const db = { - areas: new MockTable(options.areas ?? []), - products: new MockTable(options.products ?? []), - categories: new MockTable(options.categories ?? []), - pickLists: new MockTable(), - pickItems: new MockTable(), - } as unknown as StockFillDB; - - return db; -}; - -describe('seedDatabase', () => { - it('deduplicates seeded areas, categories, and products', async () => { - const duplicateSeedArea = buildArea({ name: seedAreas[0] }); - const trailingSpaceArea = buildArea({ name: `${seedAreas[0]} ` }); - const customArea = buildArea({ name: 'Produce' }); - - const duplicateProduct = buildProduct({ name: seedProducts[0].name, category: seedProducts[0].category }); - const duplicateProductWithWhitespace = buildProduct({ name: `${seedProducts[0].name} `, category: seedProducts[0].category }); - const customProduct = buildProduct({ name: 'Custom Item', category: 'Specials' }); - - const duplicateCategory = buildCategory({ name: seedCategories[0] }); - const trailingSpaceCategory = buildCategory({ name: `${seedCategories[0]} ` }); - - const db = createMockDb({ - areas: [duplicateSeedArea, trailingSpaceArea, customArea], - products: [duplicateProduct, duplicateProductWithWhitespace, customProduct], - categories: [duplicateCategory, trailingSpaceCategory], - }); - - await seedDatabase(db); - - const areas = await db.areas.toArray(); - const areaNames = areas.map((area) => normalizeName(area.name)); - const seededAreaNames = new Set(seedAreas.map(normalizeName)); - - expect(areaNames.filter((name) => name === normalizeName(seedAreas[0]))).toHaveLength(1); - expect(new Set(areaNames.filter((name) => seededAreaNames.has(name)))).toEqual(seededAreaNames); - expect(areaNames).toContain(normalizeName(customArea.name)); - - const products = await db.products.toArray(); - const seededProductNames = new Set(seedProducts.map((product) => normalizeName(product.name))); - const productNamesInDb = products.map((product) => normalizeName(product.name)); - - expect(productNamesInDb.filter((name) => name === normalizeName(seedProducts[0].name))).toHaveLength(1); - expect(new Set(productNamesInDb.filter((name) => seededProductNames.has(name)))).toEqual( - seededProductNames, - ); - expect(productNamesInDb).toContain(normalizeName(customProduct.name)); - - const categories = await db.categories.toArray(); - const seededCategoryNames = new Set(seedCategories.map(normalizeName)); - const categoryNamesInDb = categories.map((category) => normalizeName(category.name)); - - expect(categoryNamesInDb.filter((name) => name === normalizeName(seedCategories[0]))).toHaveLength(1); - expect(new Set(categoryNamesInDb.filter((name) => seededCategoryNames.has(name)))).toEqual( - seededCategoryNames, - ); - }); -}); diff --git a/src/db/seed.ts b/src/db/seed.ts deleted file mode 100644 index 7d6a497..0000000 --- a/src/db/seed.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { Table } from 'dexie'; -import { v4 as uuidv4 } from 'uuid'; -import { StockFillDB } from './index'; -import { DEFAULT_BULK_NAME, DEFAULT_UNIT_TYPE } from '../models/Product'; - -const now = () => Date.now(); - -export const seedAreas = ['Drinks', 'Snacks', 'Dairy']; - -export const seedProducts = [ - { name: 'Nutrient Water Endurance', category: 'Drinks' }, - { name: 'Nutrient Water Focus', category: 'Drinks' }, - { name: 'Cocobella Choc', category: 'Drinks' }, - { name: 'Cocobella straight', category: 'Drinks' }, - { name: 'Cocobella watermelon', category: 'Drinks' }, - { name: 'Cocoa Coast Chocolate', category: 'Drinks' }, - { name: 'Cocoa Coast Mango', category: 'Drinks' }, - { name: 'Cocoa Coast Lychee', category: 'Drinks' }, - { name: 'Cocoa Coast Raspberry', category: 'Drinks' }, - { name: 'Cocoa Coast Pasionfruit', category: 'Drinks' }, - { name: 'Mount Franklin Sparkling Lime', category: 'Drinks' }, - { name: 'Mount Franklin Sparkling', category: 'Drinks' }, - { name: 'Mount Franklin 600ml', category: 'Drinks' }, - { name: 'Nu 600ml', category: 'Drinks' }, - { name: 'Mt Cooroy 600ml', category: 'Drinks' }, - { name: 'Mt Coory 1L', category: 'Drinks' }, - { name: 'Mt Cooroy 1.5L', category: 'Drinks' }, - { name: 'Pump 750', category: 'Drinks' }, - { name: 'Pump Lime', category: 'Drinks' }, - { name: 'Pump Berry', category: 'Drinks' }, - { name: 'Pump Watermelon', category: 'Drinks' }, - { name: 'Mount Franklin 1.5L', category: 'Drinks' }, - { name: 'Pump 1.5L', category: 'Drinks' }, - { name: 'Nu 1.5L', category: 'Drinks' }, - { name: 'Smiths Salt n Vinegar 90g', category: 'Chips' }, - { name: 'Mars Bar', category: 'Chocolates' }, -]; - -export const seedCategories = Array.from( - new Set(seedProducts.map(({ category }) => category)), -).sort(); - -const normalizeName = (name: string) => name.trim().toLowerCase(); - -const dedupeSeedRecords = async ( - table: Table, - seededNames: Set, -) => { - const existing = await table.toArray(); - const seen = new Set(); - const duplicateIds: string[] = []; - - existing.forEach((record) => { - const normalized = normalizeName(record.name); - if (!seededNames.has(normalized)) return; - - if (seen.has(normalized)) { - duplicateIds.push(record.id); - return; - } - - seen.add(normalized); - }); - - if (duplicateIds.length > 0) { - await table.bulkDelete(duplicateIds); - } - - return seen; -}; - -const buildProductRecord = (product: { name: string; category: string }) => ({ - id: uuidv4(), - name: product.name, - category: product.category, - unit_type: DEFAULT_UNIT_TYPE, - bulk_name: DEFAULT_BULK_NAME, - archived: false, - created_at: now(), - updated_at: now(), -}); - -export const seedDatabase = async (db: StockFillDB) => { - const seededAreaNames = new Set(seedAreas.map(normalizeName)); - const existingSeedAreas = await dedupeSeedRecords(db.areas, seededAreaNames); - const missingAreas = seedAreas.filter((area) => !existingSeedAreas.has(normalizeName(area))); - - if (missingAreas.length > 0) { - await db.areas.bulkAdd( - missingAreas.map((name) => ({ - id: uuidv4(), - name, - created_at: now(), - updated_at: now(), - })), - ); - } - - const seededCategoryNames = new Set(seedCategories.map(normalizeName)); - const existingSeedCategories = await dedupeSeedRecords(db.categories, seededCategoryNames); - const missingCategories = seedCategories.filter( - (category) => !existingSeedCategories.has(normalizeName(category)), - ); - - if (missingCategories.length > 0) { - await db.categories.bulkAdd( - missingCategories.map((category) => ({ - id: uuidv4(), - name: category, - created_at: now(), - updated_at: now(), - })), - ); - } - - const seededProductNames = new Set(seedProducts.map(({ name }) => normalizeName(name))); - const existingSeedProducts = await dedupeSeedRecords(db.products, seededProductNames); - const missingProducts = seedProducts.filter( - (product) => !existingSeedProducts.has(normalizeName(product.name)), - ); - - if (missingProducts.length > 0) { - await db.products.bulkAdd(missingProducts.map(buildProductRecord)); - } -};