- Add #domain, #protocol, #utils aliases to package.json imports map - Replace all relative imports (./, ../, ../..) in app/ and database/mongo_migrations/ with the corresponding #alias imports, eliminating relative path traversal across the codebase - Remove dead code: ConfigurationVersionModel.findByConfigurationIdentifier (unused, superseded by paginateVersions) and unused exception classes (NotFoundException, UnprocessableEntityException, DatabaseException) from app/exceptions/index.ts, keeping only BadRequestException - Fix pre-existing syntax error in configuration_version.ts (mismatched parenthesis) that broke tsc - Fix eqeqeq violation in configuration_service.ts and isNaN -> Number.isNaN in configuration_engine.ts / cwmp-1-0.ts / exchange_controller.ts - Fix no-shadow violation in cwmp-1-0.ts EventStruct constructor - Prettier formatting pass on touched files Validated: tsc --noEmit clean, eslint app/ clean, full test suite green.
99 lines
3.5 KiB
TypeScript
99 lines
3.5 KiB
TypeScript
import { createRequire } from 'node:module'
|
|
import type { DeviceSnapshot } from '#domain/device/device'
|
|
import type { Device } from '#domain/device/device'
|
|
import { DeviceParameter } from '#domain/device/device_parameter'
|
|
|
|
const require = createRequire(import.meta.url)
|
|
const tr181Catalog: Array<{
|
|
path: string
|
|
writable: boolean
|
|
deviceClass: string
|
|
type?: string
|
|
}> = require('../../config/tr181-catalog.json')
|
|
|
|
// Index chargé une fois au démarrage — O(1) lookup
|
|
const catalogIndex = new Map(tr181Catalog.map((e) => [e.path, e.writable]))
|
|
const catalogTypeIndex = new Map(tr181Catalog.map((e) => [e.path, e.type || 'xsd:string']))
|
|
const catalogWritableIndex = new Set(tr181Catalog.filter((e) => e.writable).map((e) => e.path))
|
|
|
|
/** Remplace les segments numériques par {i} pour matcher les entrées du catalogue */
|
|
export function normalizePath(path: string): string {
|
|
return path.replace(/\.\d+\./g, '.{i}.').replace(/\.\d+$/, '.{i}')
|
|
}
|
|
|
|
export type WritabilitySource = 'live' | 'catalog' | 'default' | 'unknown'
|
|
|
|
export interface WritabilityResult {
|
|
writable: boolean | null
|
|
source: WritabilitySource
|
|
}
|
|
|
|
/**
|
|
* Résout la writabilité d'un paramètre à partir de l'état persisté du device.
|
|
*
|
|
* Logique :
|
|
* 1. gpnStatus = 'supported' → parameters[] = writable, properties[] = RO (source fiable)
|
|
* 2. gpnStatus = 'unsupported' → catalogue TR-181 → absent = writable=true (défaut R/W)
|
|
* 3. gpnStatus = 'unknown' → catalogue TR-181 → absent = writable=null (genuinement inconnu)
|
|
*/
|
|
export function resolveWritability(snapshot: DeviceSnapshot, paramPath: string): WritabilityResult {
|
|
const { gpnStatus, parameters, properties } = snapshot
|
|
|
|
if (gpnStatus === 'supported') {
|
|
if (parameters.some((p) => p.name === paramPath)) return { writable: true, source: 'live' }
|
|
if (properties.some((p) => p.name === paramPath)) return { writable: false, source: 'live' }
|
|
}
|
|
|
|
// gpnStatus = 'unsupported' ou 'unknown' → consulter le catalogue
|
|
const normalized = normalizePath(paramPath)
|
|
if (catalogIndex.has(normalized)) {
|
|
return { writable: catalogIndex.get(normalized)!, source: 'catalog' }
|
|
}
|
|
|
|
// Absent du catalogue
|
|
if (gpnStatus === 'unsupported') return { writable: true, source: 'default' }
|
|
return { writable: null, source: 'unknown' }
|
|
}
|
|
|
|
/**
|
|
* Reclassify device properties as parameters using the TR-181 catalog.
|
|
* Properties that are writable per the catalog are moved to parameters.
|
|
* Also applies the catalog type if the parameter has type UNKNOWN.
|
|
* Should be called after updateFromValues when gpnStatus is 'unsupported'.
|
|
*/
|
|
export function reclassifyDeviceFromCatalog(device: Device): number {
|
|
const properties = device.getProperties()
|
|
let reclassified = 0
|
|
|
|
for (const prop of properties) {
|
|
const normalized = normalizePath(prop.name)
|
|
if (catalogWritableIndex.has(normalized)) {
|
|
const snap = prop.toSnapshot()
|
|
const catalogType = catalogTypeIndex.get(normalized) || snap.type
|
|
device.setParameter(
|
|
new DeviceParameter(
|
|
snap.name,
|
|
snap.value,
|
|
catalogType as any,
|
|
snap.createdAt,
|
|
snap.updatedAt,
|
|
snap.notification,
|
|
snap.accessList
|
|
)
|
|
)
|
|
;(device as any)._properties.delete(prop.name)
|
|
reclassified++
|
|
}
|
|
}
|
|
|
|
return reclassified
|
|
}
|
|
|
|
/**
|
|
* Get the XSD type for a parameter path from the TR-181 catalog.
|
|
* Returns 'xsd:string' if not found.
|
|
*/
|
|
export function getCatalogType(paramPath: string): string {
|
|
return catalogTypeIndex.get(normalizePath(paramPath)) || 'xsd:string'
|
|
}
|