"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.narImportRouter = void 0; const express_1 = require("express"); const client_1 = require("@prisma/client"); const zod_1 = require("zod"); const crypto_1 = require("crypto"); const nar_import_service_1 = require("./nar-import.service"); const redis_1 = require("../../../config/redis"); const logger_1 = require("../../../utils/logger"); const auth_middleware_1 = require("../../../middleware/auth.middleware"); const rbac_middleware_1 = require("../../../middleware/rbac.middleware"); const validate_1 = require("../../../middleware/validate"); const MAP_ADMIN_ROLES = [client_1.UserRole.SUPER_ADMIN, client_1.UserRole.MAP_ADMIN]; const serverImportSchema = zod_1.z.object({ provinceCode: zod_1.z.string().min(1).max(2), filterType: zod_1.z.enum(['none', 'city', 'postalPrefix', 'cut']).default('none'), filterCity: zod_1.z.string().optional(), filterPostalPrefix: zod_1.z.string().min(3).max(3).optional(), cutId: zod_1.z.string().optional(), residentialOnly: zod_1.z.boolean().default(true), deduplicateRadius: zod_1.z.number().min(0).max(100).default(5), batchSize: zod_1.z.number().int().min(100).max(5000).default(1000), }); const narImportRouter = (0, express_1.Router)(); exports.narImportRouter = narImportRouter; narImportRouter.use(auth_middleware_1.authenticate); narImportRouter.use((0, rbac_middleware_1.requireRole)(...MAP_ADMIN_ROLES)); // GET /api/map/nar-import/datasets — list available NAR datasets by province narImportRouter.get('/datasets', async (_req, res, next) => { try { const result = await nar_import_service_1.narImportService.listDatasets(); res.json(result); } catch (err) { next(err); } }); // GET /api/map/nar-import/status/:importId — poll import progress narImportRouter.get('/status/:importId', async (req, res, next) => { try { const importId = req.params.importId; const data = await redis_1.redis.get(`nar-import:${importId}`); if (!data) { res.status(404).json({ error: { message: 'Import not found or expired', code: 'NOT_FOUND' } }); return; } res.json(JSON.parse(data)); } catch (err) { next(err); } }); // POST /api/map/nar-import — start a province import (fire-and-forget, returns importId) narImportRouter.post('/', (0, validate_1.validate)(serverImportSchema), async (req, res, next) => { try { const importId = (0, crypto_1.randomUUID)(); const userId = req.user.id; // Write initial progress so status endpoint works immediately await (0, nar_import_service_1.writeProgress)(importId, { status: 'loading-locations', totalRows: 0, locationsCreated: 0, addressesCreated: 0, skippedDuplicate: 0, skippedOutOfBounds: 0, skippedNonResidential: 0, skippedInvalid: 0, currentFile: '', provinceName: '', }); // Fire and forget — errors are written to Redis nar_import_service_1.narImportService.importProvince(userId, req.body, importId).catch(async (err) => { const errorMsg = err instanceof Error ? err.message : 'Unknown error'; logger_1.logger.error(`NAR import ${importId} failed: ${errorMsg}`); await (0, nar_import_service_1.writeProgress)(importId, { status: 'failed', totalRows: 0, locationsCreated: 0, addressesCreated: 0, skippedDuplicate: 0, skippedOutOfBounds: 0, skippedNonResidential: 0, skippedInvalid: 0, currentFile: '', provinceName: '', error: errorMsg, }); }); res.json({ importId }); } catch (err) { next(err); } }); //# sourceMappingURL=nar-import.routes.js.map