Skip to content

Commit 0e2a303

Browse files
committed
feat: Add DatabaseItem base type and require all DB records to have id and timestamp fields
1 parent b58c641 commit 0e2a303

11 files changed

Lines changed: 68 additions & 65 deletions

File tree

src/composables/getItemsToShow.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-09-17 17:25:36
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-04-29 18:44:22
7+
* Last Modified: 2026-05-04 22:52:51
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -15,7 +15,7 @@
1515
*/
1616

1717

18-
import type { Item } from "~/model/item";
18+
import type { WardrobeItem } from "~/model/item";
1919
import { SortMode } from "~/model/sort-modes";
2020
import { State } from "./state";
2121

@@ -26,7 +26,7 @@ import { State } from "./state";
2626
* @param selectedSort
2727
* @param selectedFilters
2828
*/
29-
export default function(storedItems: Item[], selectedSort?: SortMode, selectedFilters?: string[]): Item[] {
29+
export default function(storedItems: WardrobeItem[], selectedSort?: SortMode, selectedFilters?: string[]): WardrobeItem[] {
3030

3131
// Get search string ref from app.vue
3232
const searchStr: Ref<string|null> = useState(State.GLOBAL_SEARCH_STRING);

src/model/Implements.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/model/item.ts

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-09-08 15:45:56
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-04-01 19:04:46
7+
* Last Modified: 2026-05-04 22:52:22
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -15,38 +15,30 @@
1515
*/
1616

1717

18-
import type { Implements } from "./Implements";
18+
import type { DatabaseItem } from "./storage";
1919

2020

2121
// Base type for Clothing & Outfit, used by generic components & composables.
22-
export type Item = {
23-
id: string,
24-
title: string, // Used for sorting
25-
labelIDs: string[], // Label[], // Used as filters/for filtering
26-
addedTimestamp: number, // Used for sorting
27-
modifiedTimestamp: number
22+
export interface WardrobeItem extends DatabaseItem {
23+
title: string, // Used for sorting
24+
labelIDs: string[], // Used as filters/for filtering
2825
}
2926

3027

31-
// Implements Item
32-
export type Clothing = Implements<Item, {
28+
// Implements WardrobeItem
29+
export interface Clothing extends WardrobeItem {
3330
id: string,
3431
title: string,
3532
description: string,
3633
imgPath: string,
37-
labelIDs: string[], // IMPORTANT: May reference non-existent labels if dataCleanUp job did not run yet!
38-
addedTimestamp: number,
39-
modifiedTimestamp: number
40-
}>
34+
labelIDs: string[] // IMPORTANT: May reference non-existent labels if dataCleanUp job did not run yet!
35+
}
4136

4237

43-
// Implements Item
44-
export type Outfit = Implements<Item, {
45-
id: string,
38+
// Implements WardrobeItem
39+
export interface Outfit extends WardrobeItem {
4640
title: string,
4741
clothes: { order: number, clothingID: string }[], // IMPORTANT: May reference non-existent clothes if dataCleanUp job did not run yet!
4842
labelIDs: string[], // IMPORTANT: May reference non-existent labels if dataCleanUp job did not run yet!
49-
previewImgPath: string,
50-
addedTimestamp: number,
51-
modifiedTimestamp: number
52-
}>
43+
previewImgPath: string
44+
}

src/model/label-category.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-12-31 17:00:33
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-03-27 19:01:56
7+
* Last Modified: 2026-05-04 22:52:23
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -16,11 +16,11 @@
1616

1717

1818
import type { Label } from "./label";
19+
import type { DatabaseItem } from "./storage";
1920
import type { TemperatureKelvin } from "./unit";
2021

2122

22-
export type Category = {
23-
id: string,
23+
export interface Category extends DatabaseItem {
2424
name: string,
2525
specialityID: CategorySpecialityID
2626
}

src/model/label.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-09-09 21:59:50
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-03-30 17:00:01
7+
* Last Modified: 2026-05-04 22:52:28
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -14,17 +14,18 @@
1414
* You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
1515
*/
1616

17+
1718
import type { Category } from "./label-category";
1819
import { CategorySpecialityMap } from "./label-category";
20+
import type { DatabaseItem } from "./storage";
1921

2022

2123
/**
2224
* Implements type definitions and operations on labels
2325
*/
2426

2527

26-
export type Label = {
27-
id: string,
28+
export interface Label extends DatabaseItem {
2829
name: string,
2930
orderIndex: number, // Floating point number
3031
categoryID: string, // IMPORTANT: May reference non-existent category if dataCleanUp job did not run yet!

src/model/storage.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-09-08 15:21:35
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-04-29 18:48:38
7+
* Last Modified: 2026-05-04 22:52:27
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -22,6 +22,25 @@ import { SortMode } from "./sort-modes";
2222
import type { Unit } from "./unit";
2323

2424

25+
// Fields every database record is required to have
26+
export interface DatabaseItem {
27+
id: string,
28+
addedTimestamp: number,
29+
modifiedTimestamp: number
30+
}
31+
32+
/**
33+
* Updates metadata fields of a database item
34+
* @param item Item to update
35+
*/
36+
export function updateDatabaseItemMetadata(item: DatabaseItem) {
37+
if (!item.addedTimestamp) {
38+
item.addedTimestamp = Date.now();
39+
}
40+
item.modifiedTimestamp = Date.now();
41+
}
42+
43+
2544
// Storage kinds used by Wardrobe
2645
export enum StorageKind {
2746
// LOCAL_STORAGE, // Stored in Browser of user

src/pages/clothing/view.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Created Date: 2025-09-08 15:39:55
66
* Author: 3urobeat
77
*
8-
* Last Modified: 2026-04-30 09:12:47
8+
* Last Modified: 2026-05-04 22:52:32
99
* Modified By: 3urobeat
1010
*
1111
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -224,7 +224,9 @@
224224
name: name,
225225
orderIndex: getNewLastLabelOrderIndex(getLabelsOfCategory(storedLabels.value.document!, thisCategory.id)),
226226
categoryID: thisCategory.id,
227-
specialityValue: CategorySpecialityMap[thisCategory.specialityID].value // Init val
227+
specialityValue: CategorySpecialityMap[thisCategory.specialityID].value, // Init val
228+
addedTimestamp: 0,
229+
modifiedTimestamp: 0
228230
};
229231
230232
// Send new label to server

src/pages/labels/index.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Created Date: 2025-09-09 17:13:32
66
* Author: 3urobeat
77
*
8-
* Last Modified: 2026-04-28 21:57:36
8+
* Last Modified: 2026-05-04 22:52:34
99
* Modified By: 3urobeat
1010
*
1111
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -209,7 +209,9 @@
209209
name: "",
210210
orderIndex: getNewLastLabelOrderIndex(labelsPerCategory[category.id]!),
211211
categoryID: category.id,
212-
specialityValue: CategorySpecialityMap[category.specialityID].value // Init val
212+
specialityValue: CategorySpecialityMap[category.specialityID].value, // Init val
213+
addedTimestamp: 0,
214+
modifiedTimestamp: 0
213215
};
214216
215217
localLabels.value.push(newLabel);
@@ -269,7 +271,9 @@
269271
const e: Category = {
270272
id: await getUUIDFromServer(),
271273
name: "",
272-
specialityID: CategorySpecialityID.No_Speciality
274+
specialityID: CategorySpecialityID.No_Speciality,
275+
addedTimestamp: 0,
276+
modifiedTimestamp: 0
273277
};
274278
275279
localCategories.value.push(e);

src/server/utils/useClothesDb.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-12-06 17:28:44
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-04-01 18:32:45
7+
* Last Modified: 2026-05-04 22:52:38
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -19,7 +19,7 @@ import nedb from "@seald-io/nedb";
1919
import crypto from "node:crypto";
2020
import { SubscriptionEventAction } from "~/model/api";
2121
import type { Clothing } from "~/model/item";
22-
import { StorageKind } from "~/model/storage";
22+
import { StorageKind, updateDatabaseItemMetadata } from "~/model/storage";
2323
import { updateImagesOfAffectedOutfits } from "~/server/utils/outfitPreviewImage";
2424

2525

@@ -50,11 +50,7 @@ export async function upsertClothing(clothing: Clothing): Promise<Clothing | nul
5050
}
5151

5252
// Update metadata
53-
if (!clothing.addedTimestamp) {
54-
clothing.addedTimestamp = Date.now();
55-
}
56-
57-
clothing.modifiedTimestamp = Date.now();
53+
updateDatabaseItemMetadata(clothing);
5854

5955
// Unused image will be deleted by periodic database cleanup job
6056

src/server/utils/useLabelsDb.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Created Date: 2025-12-06 17:28:44
55
* Author: 3urobeat
66
*
7-
* Last Modified: 2026-04-01 18:32:48
7+
* Last Modified: 2026-05-04 22:52:40
88
* Modified By: 3urobeat
99
*
1010
* Copyright (c) 2025 - 2026 3urobeat <https://github.com/3urobeat>
@@ -19,7 +19,7 @@ import nedb from "@seald-io/nedb";
1919
import { SubscriptionEventAction } from "~/model/api";
2020
import type { Label } from "~/model/label";
2121
import type { Category } from "~/model/label-category";
22-
import { StorageKind } from "~/model/storage";
22+
import { StorageKind, updateDatabaseItemMetadata } from "~/model/storage";
2323

2424

2525
// Load database
@@ -49,6 +49,9 @@ async function upsertLabel(label: Label): Promise<Label | null> {
4949
label.id = crypto.randomUUID();
5050
}
5151

52+
// Update metadata
53+
updateDatabaseItemMetadata(label);
54+
5255
const res = await labelsDb.updateAsync({ id: label.id }, { $set: label }, { upsert: true, returnUpdatedDocs: true });
5356
const affected = res.affectedDocuments ? res.affectedDocuments as unknown as Label : null;
5457

@@ -132,6 +135,9 @@ async function upsertLabelCategory(category: Category): Promise<Category | null>
132135
category.id = crypto.randomUUID();
133136
}
134137

138+
// Update metadata
139+
updateDatabaseItemMetadata(category);
140+
135141
const res = await labelCategoriesDb.updateAsync({ id: category.id }, { $set: category }, { upsert: true, returnUpdatedDocs: true });
136142
const affected = res.affectedDocuments ? res.affectedDocuments as unknown as Category : null;
137143

0 commit comments

Comments
 (0)