Skip to content

Commit bce352c

Browse files
hyperpolymathclaude
andcommitted
refactor: migrate Js.Dict to Dict in src/app/devices/ (16 files)
Replace deprecated Js.Dict API with modern Dict equivalents: - Js.Dict.empty() -> Dict.make() - Js.Dict.get/set -> Dict.get/set - Js.Dict.entries -> Dict.toArray - Js.Dict.keys -> Dict.keysToArray - Js.Dict.t<X> -> dict<X> Part of #28. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 24d3281 commit bce352c

16 files changed

+178
-178
lines changed

src/app/devices/CameraDevice.res

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ type cameraState = {
5555
}
5656

5757
// Global camera states keyed by IP address
58-
let cameraStates: Js.Dict.t<cameraState> = Js.Dict.empty()
58+
let cameraStates: dict<cameraState> = Dict.make()
5959

6060
let getCameraState = (ipAddress: string): cameraState => {
61-
switch Js.Dict.get(cameraStates, ipAddress) {
61+
switch Dict.get(cameraStates, ipAddress) {
6262
| Some(state) => state
6363
| None =>
6464
let state = {
@@ -68,7 +68,7 @@ let getCameraState = (ipAddress: string): cameraState => {
6868
loopedMotionState: false,
6969
loopedHackerPosition: None,
7070
}
71-
Js.Dict.set(cameraStates, ipAddress, state)
71+
Dict.set(cameraStates, ipAddress, state)
7272
state
7373
}
7474
}

src/app/devices/CameraFeed.res

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ let getFeedData = (): option<cameraFeedData> => {
2323
// Motion detection callbacks - keyed by camera IP address
2424
// WorldScreen registers callbacks to update camera sprite indicators
2525
// Callback receives: None = disabled/grey, Some(false) = no motion/blue, Some(true) = motion/orange
26-
let motionCallbacks: Js.Dict.t<option<bool> => unit> = Js.Dict.empty()
26+
let motionCallbacks: dict<option<bool> => unit> = Dict.make()
2727

2828
let registerMotionCallback = (cameraIp: string, callback: option<bool> => unit): unit => {
29-
Js.Dict.set(motionCallbacks, cameraIp, callback)
29+
Dict.set(motionCallbacks, cameraIp, callback)
3030
}
3131

3232
let unregisterMotionCallback = (cameraIp: string): unit => {
@@ -35,15 +35,15 @@ let unregisterMotionCallback = (cameraIp: string): unit => {
3535

3636
// Motion status: None = disabled/grey, Some(false) = no motion/blue, Some(true) = motion/orange
3737
let notifyMotionStatus = (cameraIp: string, motionDetected: bool): unit => {
38-
switch Js.Dict.get(motionCallbacks, cameraIp) {
38+
switch Dict.get(motionCallbacks, cameraIp) {
3939
| Some(callback) => callback(Some(motionDetected))
4040
| None => ()
4141
}
4242
}
4343

4444
// Notify camera is disabled (grey indicator)
4545
let notifyCameraDisabled = (cameraIp: string): unit => {
46-
switch Js.Dict.get(motionCallbacks, cameraIp) {
46+
switch Dict.get(motionCallbacks, cameraIp) {
4747
| Some(callback) => callback(None)
4848
| None => ()
4949
}
@@ -81,17 +81,17 @@ let getHackerRelativePosition = (cameraX: float, viewWidth: float): option<float
8181

8282
// Camera positions in world - used for background motion checking
8383
// Maps IP address to (worldX, viewWidth)
84-
let cameraPositions: Js.Dict.t<(float, float)> = Js.Dict.empty()
84+
let cameraPositions: dict<(float, float)> = Dict.make()
8585

8686
// Track which cameras are disabled (to skip in background motion check)
8787
let disabledCameras: Set.t<string> = Set.make()
8888

8989
// Track which cameras are looping and their frozen motion state
9090
// Maps IP to frozen motion state (true = motion detected, false = no motion)
91-
let loopingCameras: Js.Dict.t<bool> = Js.Dict.empty()
91+
let loopingCameras: dict<bool> = Dict.make()
9292

9393
let registerCameraPosition = (cameraIp: string, worldX: float, viewWidth: float): unit => {
94-
Js.Dict.set(cameraPositions, cameraIp, (worldX, viewWidth))
94+
Dict.set(cameraPositions, cameraIp, (worldX, viewWidth))
9595
}
9696

9797
let setCameraEnabled = (cameraIp: string, enabled: bool): unit => {
@@ -104,7 +104,7 @@ let setCameraEnabled = (cameraIp: string, enabled: bool): unit => {
104104

105105
let setCameraLooping = (cameraIp: string, looping: bool, frozenMotionState: bool): unit => {
106106
if looping {
107-
Js.Dict.set(loopingCameras, cameraIp, frozenMotionState)
107+
Dict.set(loopingCameras, cameraIp, frozenMotionState)
108108
} else {
109109
Dict.delete(loopingCameras, cameraIp)
110110
}
@@ -113,7 +113,7 @@ let setCameraLooping = (cameraIp: string, looping: bool, frozenMotionState: bool
113113
// Update all camera motion statuses based on hacker position
114114
// Called from WorldScreen update loop
115115
let updateAllCameraMotion = (): unit => {
116-
Js.Dict.entries(cameraPositions)->Belt.Array.forEach(((ip, position)) => {
116+
Dict.toArray(cameraPositions)->Belt.Array.forEach(((ip, position)) => {
117117
let (worldX, viewWidth) = position
118118

119119
// Skip disabled cameras
@@ -124,16 +124,16 @@ let updateAllCameraMotion = (): unit => {
124124
let hasPower = PowerManager.isDeviceOperational(ip)
125125
if !hasPower {
126126
// No power - show grey indicator
127-
switch Js.Dict.get(motionCallbacks, ip) {
127+
switch Dict.get(motionCallbacks, ip) {
128128
| Some(callback) => callback(None)
129129
| None => ()
130130
}
131131
} else {
132132
// Check if this camera has a motion callback registered
133-
switch Js.Dict.get(motionCallbacks, ip) {
133+
switch Dict.get(motionCallbacks, ip) {
134134
| Some(callback) =>
135135
// Check if camera is looping - use frozen state instead of live detection
136-
switch Js.Dict.get(loopingCameras, ip) {
136+
switch Dict.get(loopingCameras, ip) {
137137
| Some(frozenMotion) =>
138138
// Camera is looping - show the frozen motion state
139139
callback(Some(frozenMotion))

src/app/devices/CoprocessorBridge.res

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,16 @@ open Coprocessor
5252

5353
// Resolved coprocessor results waiting to be read by RECV, keyed by device ID.
5454
// Populated asynchronously by Promise.then callbacks after each SEND dispatch.
55-
let outputBuffers: Js.Dict.t<ref<array<string>>> = Js.Dict.empty()
55+
let outputBuffers: dict<ref<array<string>>> = Dict.make()
5656

5757
// Retrieve or lazily create the result buffer for a device.
5858
// All SEND and RECV calls for a device share the same buffer reference.
5959
let getBuffer = (deviceId: string): ref<array<string>> => {
60-
switch Js.Dict.get(outputBuffers, deviceId) {
60+
switch Dict.get(outputBuffers, deviceId) {
6161
| Some(b) => b
6262
| None =>
6363
let b = ref([])
64-
Js.Dict.set(outputBuffers, deviceId, b)
64+
Dict.set(outputBuffers, deviceId, b)
6565
b
6666
}
6767
}

src/app/devices/CovertLink.res

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -281,41 +281,41 @@ let formatShort = (conn: t): string => {
281281

282282
module Registry = {
283283
// All connections in the current level
284-
let connections: Js.Dict.t<t> = Js.Dict.empty()
284+
let connections: dict<t> = Dict.make()
285285

286286
// Register a connection
287287
let add = (conn: t): unit => {
288-
Js.Dict.set(connections, conn.id, conn)
288+
Dict.set(connections, conn.id, conn)
289289
}
290290

291291
// Get a connection by ID
292292
let get = (id: string): option<t> => {
293-
Js.Dict.get(connections, id)
293+
Dict.get(connections, id)
294294
}
295295

296296
// Get all connections
297297
let getAll = (): array<t> => {
298-
Js.Dict.values(connections)
298+
Dict.valuesToArray(connections)
299299
}
300300

301301
// Get connections by state
302302
let getByState = (state: connectionState): array<t> => {
303-
Js.Dict.values(connections)->Belt.Array.keep(c => c.state == state)
303+
Dict.valuesToArray(connections)->Belt.Array.keep(c => c.state == state)
304304
}
305305

306306
// Get active connections for a specific IP
307307
let getActiveForIp = (ip: string): array<t> => {
308-
Js.Dict.values(connections)->Belt.Array.keep(c => c.state == Active && hasEndpoint(c, ip))
308+
Dict.valuesToArray(connections)->Belt.Array.keep(c => c.state == Active && hasEndpoint(c, ip))
309309
}
310310

311311
// Get all discovered-or-active connections (for overlay map)
312312
let getVisible = (): array<t> => {
313-
Js.Dict.values(connections)->Belt.Array.keep(c => c.state == Discovered || c.state == Active)
313+
Dict.valuesToArray(connections)->Belt.Array.keep(c => c.state == Discovered || c.state == Active)
314314
}
315315

316316
// Find an active covert route between two IPs
317317
let findRoute = (sourceIp: string, destIp: string): option<t> => {
318-
Belt.Array.getBy(Js.Dict.values(connections), c =>
318+
Belt.Array.getBy(Dict.valuesToArray(connections), c =>
319319
c.state == Active && connects(c, sourceIp, destIp)
320320
)
321321
}
@@ -327,14 +327,14 @@ module Registry = {
327327

328328
// Update all connections (call each frame)
329329
let updateAll = (deltaSeconds: float): unit => {
330-
Js.Dict.values(connections)->Belt.Array.forEach(conn => {
330+
Dict.valuesToArray(connections)->Belt.Array.forEach(conn => {
331331
update(conn, deltaSeconds)
332332
})
333333
}
334334

335335
// Reset all connections (new level)
336336
let clear = (): unit => {
337-
Js.Dict.keys(connections)->Belt.Array.forEach(key => {
337+
Dict.keysToArray(connections)->Belt.Array.forEach(key => {
338338
Dict.delete(connections, key)
339339
})
340340
}

src/app/devices/DeviceActivity.res

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44

55
let getCurrentTime: unit => float = %raw(`function() { return Date.now(); }`)
66

7-
let lastActivity: Js.Dict.t<float> = Js.Dict.empty()
7+
let lastActivity: dict<float> = Dict.make()
88
let activityTimeoutMs = 30000.0 // 30 seconds
99

1010
let recordActivity = (ip: string): unit => {
11-
Js.Dict.set(lastActivity, ip, getCurrentTime())
11+
Dict.set(lastActivity, ip, getCurrentTime())
1212
}
1313

1414
let isActive = (ip: string): bool => {
15-
switch Js.Dict.get(lastActivity, ip) {
15+
switch Dict.get(lastActivity, ip) {
1616
| Some(time) => getCurrentTime() -. time < activityTimeoutMs
1717
| None => false
1818
}

src/app/devices/DeviceRegistry.res

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,30 @@
2424
// - All mutation is single-threaded (no concurrent write hazard in Deno).
2525

2626
// The singleton backing store: ipAddress -> device
27-
let registry: dict<DeviceTypes.device> = Js.Dict.empty()
27+
let registry: dict<DeviceTypes.device> = Dict.make()
2828

2929
// Defence flags backing store: ipAddress -> defenceFlags (ADR-0013).
3030
// Populated by NetworkManager.applyLevelDefences; cleared on level unload.
31-
let defenceRegistry: dict<DeviceType.defenceFlags> = Js.Dict.empty()
31+
let defenceRegistry: dict<DeviceType.defenceFlags> = Dict.make()
3232

3333
// Register a device under its IP address.
3434
// If a device is already registered at this IP it will be overwritten —
3535
// this is intentional for hot-reload during development.
3636
let register = (ipAddress: string, device: DeviceTypes.device): unit => {
37-
Js.Dict.set(registry, ipAddress, device)
37+
Dict.set(registry, ipAddress, device)
3838
}
3939

4040
// Look up a device by IP address. Returns None if not registered.
4141
let lookup = (ipAddress: string): option<DeviceTypes.device> => {
42-
Js.Dict.get(registry, ipAddress)
42+
Dict.get(registry, ipAddress)
4343
}
4444

4545
// Look up a device and call f with it. Returns None if not registered.
4646
let withDevice = (
4747
ipAddress: string,
4848
f: DeviceTypes.device => 'a,
4949
): option<'a> => {
50-
switch Js.Dict.get(registry, ipAddress) {
50+
switch Dict.get(registry, ipAddress) {
5151
| Some(device) => Some(f(device))
5252
| None => None
5353
}
@@ -64,17 +64,17 @@ let unregister = (ipAddress: string): unit => {
6464

6565
// Return all registered IP addresses.
6666
let allIps = (): array<string> => {
67-
Js.Dict.keys(registry)
67+
Dict.keysToArray(registry)
6868
}
6969

7070
// Return all registered devices as (ipAddress, device) pairs.
7171
let allEntries = (): array<(string, DeviceTypes.device)> => {
72-
Js.Dict.entries(registry)
72+
Dict.toArray(registry)
7373
}
7474

7575
// Return all devices whose deviceType matches the given type.
7676
let byType = (targetType: DeviceTypes.deviceType): array<DeviceTypes.device> => {
77-
Js.Dict.values(registry)->Belt.Array.keep(device => {
77+
Dict.valuesToArray(registry)->Belt.Array.keep(device => {
7878
let info = device.getInfo()
7979
info.deviceType == targetType
8080
})
@@ -93,15 +93,15 @@ let byMinSecurityLevel = (
9393
| DeviceType.Medium => 2
9494
| DeviceType.Strong => 3
9595
}
96-
Js.Dict.values(registry)->Belt.Array.keep(device => {
96+
Dict.valuesToArray(registry)->Belt.Array.keep(device => {
9797
let info = device.getInfo()
9898
rank((info.securityLevel :> DeviceType.securityLevel)) >= rank(minLevel)
9999
})
100100
}
101101

102102
// Return the number of currently registered devices.
103103
let count = (): int => {
104-
Js.Dict.keys(registry)->Belt.Array.length
104+
Dict.keysToArray(registry)->Belt.Array.length
105105
}
106106

107107
// --- Defence flags (ADR-0013) ---
@@ -115,24 +115,24 @@ let count = (): int => {
115115
// Overwrites any previously stored flags for the same IP (safe — missions
116116
// always reset flags before the level starts).
117117
let setDefenceFlags = (ipAddress: string, flags: DeviceType.defenceFlags): unit => {
118-
Js.Dict.set(defenceRegistry, ipAddress, flags)
118+
Dict.set(defenceRegistry, ipAddress, flags)
119119
}
120120

121121
// Read defence flags for a device.
122122
// Returns DeviceType.defaultDefenceFlags (all inactive) if no override
123123
// has been registered for this IP — i.e. the device has stock behaviour.
124124
let getDefenceFlags = (ipAddress: string): DeviceType.defenceFlags => {
125-
Js.Dict.get(defenceRegistry, ipAddress)->Belt.Option.getWithDefault(DeviceType.defaultDefenceFlags)
125+
Dict.get(defenceRegistry, ipAddress)->Belt.Option.getWithDefault(DeviceType.defaultDefenceFlags)
126126
}
127127

128128
// Remove all registered devices and defence flag overrides.
129129
// Called on level unload / game reset to prevent stale state leaking
130130
// between missions.
131131
let clear = (): unit => {
132132
// Delete all device entries
133-
let deviceKeys = Js.Dict.keys(registry)
133+
let deviceKeys = Dict.keysToArray(registry)
134134
Belt.Array.forEach(deviceKeys, k => Dict.delete(registry, k))
135135
// Delete all defence flag overrides
136-
let defenceKeys = Js.Dict.keys(defenceRegistry)
136+
let defenceKeys = Dict.keysToArray(defenceRegistry)
137137
Belt.Array.forEach(defenceKeys, k => Dict.delete(defenceRegistry, k))
138138
}

0 commit comments

Comments
 (0)