feat: establish auth listing and image vertical slices

Includes MFA-capable authentication, session and CSRF security, password recovery, listing lifecycle and ownership rules, inventory image metadata, local ImageStorage, migrations, tests, and implementation status documentation. Verification: npm test (62 passing) and integration suite (14 passing).
This commit is contained in:
2026-09-08 17:32:03 -04:00
commit c728016dec
128 changed files with 9788 additions and 0 deletions
View File
+23
View File
@@ -0,0 +1,23 @@
function toIsoString(value) {
return value instanceof Date ? value.toISOString() : value;
}
export function toSessionDto(session, currentSessionId) {
return {
id: session.id,
createdAt: toIsoString(session.createdAt),
expiresAt: toIsoString(session.expiresAt),
lastActivityAt: toIsoString(session.lastActivityAt),
ipAddress: session.ipAddress,
userAgent: session.userAgent,
isCurrent: session.id === currentSessionId,
};
}
export function toMfaMethodDto(method) {
return {
id: method.id,
name: method.name,
type: method.type,
};
}
+22
View File
@@ -0,0 +1,22 @@
function toIsoString(value) {
return value instanceof Date ? value.toISOString() : value;
}
export function toAdminInventoryImageDto(image) {
return {
id: image.id,
inventoryItemId: image.inventoryItemId,
storageKey: image.storageKey,
originalFilename: image.originalFilename,
mimeType: image.mimeType,
fileSize: image.fileSize,
width: image.width,
height: image.height,
altText: image.altText ?? null,
sortOrder: image.sortOrder,
isPrimary: image.isPrimary,
processingStatus: image.processingStatus,
createdAt: toIsoString(image.createdAt),
updatedAt: toIsoString(image.updatedAt),
};
}
+15
View File
@@ -0,0 +1,15 @@
function toIsoString(value) {
return value instanceof Date ? value.toISOString() : value;
}
export function toAdminInventoryItemDto(inventoryItem) {
return {
id: inventoryItem.id,
productId: inventoryItem.productId,
conditionId: inventoryItem.conditionId,
status: inventoryItem.status,
notes: inventoryItem.notes ?? null,
createdAt: toIsoString(inventoryItem.createdAt),
updatedAt: toIsoString(inventoryItem.updatedAt),
};
}
+19
View File
@@ -0,0 +1,19 @@
function toIsoString(value) {
return value instanceof Date ? value.toISOString() : value;
}
export function toAdminListingDto(listing) {
return {
id: listing.id,
inventoryItemId: listing.inventoryItemId,
productName: listing.productName,
categoryId: listing.categoryId,
conditionId: listing.conditionId,
askingPriceMinor: listing.askingPriceMinor,
imageCount: listing.imageCount,
status: listing.status,
notes: listing.notes ?? null,
createdAt: toIsoString(listing.createdAt),
updatedAt: toIsoString(listing.updatedAt),
};
}
+12
View File
@@ -0,0 +1,12 @@
{
"name": "@pokemon-inventory/contracts",
"private": true,
"type": "module",
"exports": {
"./auth": "./auth.js",
"./inventory": "./inventory.js",
"./image": "./image.js",
"./listing": "./listing.js",
"./product": "./product.js"
}
}
+21
View File
@@ -0,0 +1,21 @@
function toIsoString(value) {
return value instanceof Date ? value.toISOString() : value;
}
export function toAdminProductDto(product) {
return {
id: product.id,
sellerId: product.sellerId,
categoryId: product.categoryId,
name: product.name,
slug: product.slug,
description: product.description ?? null,
brand: product.brand ?? null,
setName: product.setName ?? null,
cardNumber: product.cardNumber ?? null,
eventName: product.eventName ?? null,
releaseYear: product.releaseYear ?? null,
createdAt: toIsoString(product.createdAt),
updatedAt: toIsoString(product.updatedAt),
};
}