From b0401f3a3414e6aff6897b2299b935b511f523d1 Mon Sep 17 00:00:00 2001
From: Tygo Egmond <35234103+tygoegmond@users.noreply.github.com>
Date: Thu, 8 Oct 2026 11:45:44 +0200
Subject: [PATCH] feat!: drop the network action, use reconnect
BREAKING CHANGE: LinkAction.network (iOS, Android), LinkAction.NETWORK (Android) and action: 'network' (React Native) are gone. Open reconnect instead; it also changes a charger's network.
---
README.md | 2 +-
.../com/plugchoice/example/MainActivity.kt | 5 ++---
.../example/src/main/res/values/strings.xml | 2 +-
.../src/main/java/com/plugchoice/LinkAction.kt | 15 ++++++---------
.../src/main/java/com/plugchoice/Plugchoice.kt | 4 ++--
.../java/com/plugchoice/internal/BridgeTest.kt | 6 +++---
.../com/plugchoice/internal/InstancesTest.kt | 6 +++---
.../plugchoice/internal/LinkDestinationTest.kt | 11 +++++------
bridge/PROTOCOL.md | 2 +-
ios/Example/Example/ContentView.swift | 10 +++-------
ios/Sources/PlugchoiceSDK/Plugchoice.swift | 13 +++++--------
ios/Tests/PlugchoiceSDKTests/BridgeTests.swift | 4 ++--
.../ClientSecretsTests.swift | 4 ++--
.../PlugchoiceSDKTests/LinkTargetTests.swift | 18 ++++++++----------
react-native/__tests__/clientSecret.test.ts | 12 ++++++------
react-native/__tests__/openLink.test.ts | 18 +++++++++---------
react-native/src/openLink.ts | 4 ++--
react-native/src/types.ts | 4 ++--
18 files changed, 63 insertions(+), 77 deletions(-)
diff --git a/README.md b/README.md
index 382eb0d..3579511 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Let the people using your app connect their EV chargers to Plugchoice, without l
## Features
-- **Charger setup**: add a charger, set it up, connect it to Wi-Fi, or reconnect it, guided screen by screen.
+- **Charger setup**: add a charger, set it up, or reconnect it (which also changes its network, such as its Wi-Fi), guided screen by screen.
- **Many brands, no app update**: new charger brands and fixes reach your users without a new release of your app.
- **One backend endpoint**: your server creates a session, scoped to the chargers your user may touch; the SDK fetches it when it needs one.
- **Native where it counts**: Wi-Fi hotspots, local network discovery, Bluetooth LE and QR scanning, behind each platform's own permission prompts.
diff --git a/android/example/src/main/java/com/plugchoice/example/MainActivity.kt b/android/example/src/main/java/com/plugchoice/example/MainActivity.kt
index 67c5d49..4f6cba0 100644
--- a/android/example/src/main/java/com/plugchoice/example/MainActivity.kt
+++ b/android/example/src/main/java/com/plugchoice/example/MainActivity.kt
@@ -126,7 +126,7 @@ class MainActivity : ComponentActivity() {
// Testing aid, like the iOS example's `-autoOpen`:
// `adb shell am start -n com.plugchoice.example/.MainActivity --es clientSecret cs_… \
- // --es host 10.0.2.2:5173 --es action network --es chargerId 42 --ez autoOpen true`
+ // --es host 10.0.2.2:5173 --es action reconnect --es chargerId 42 --ez autoOpen true`
if (savedInstanceState == null) {
intent.getStringExtra(EXTRA_CLIENT_SECRET)?.let(secretField::setText)
intent.getStringExtra(EXTRA_HOST)?.let(hostField::setText)
@@ -174,7 +174,6 @@ class MainActivity : ComponentActivity() {
val siteId = siteIdField.text.toString().trim().ifEmpty { null }
return when (val name = ACTIONS[actionPicker.selectedItemPosition]) {
LinkAction.ADD -> LinkAction.addCharger(siteId)
- LinkAction.NETWORK -> LinkAction.network(chargerId)
LinkAction.SETUP -> LinkAction.setup(chargerId)
LinkAction.RECONNECT -> LinkAction.reconnect(chargerId)
else -> customActionField.text.toString().trim().takeIf { it.isNotEmpty() && name == CUSTOM }
@@ -217,6 +216,6 @@ class MainActivity : ComponentActivity() {
const val EXTRA_AUTO_OPEN = "autoOpen"
const val CUSTOM = "custom…"
- val ACTIONS = listOf(LinkAction.ADD, LinkAction.NETWORK, LinkAction.SETUP, LinkAction.RECONNECT, CUSTOM)
+ val ACTIONS = listOf(LinkAction.ADD, LinkAction.SETUP, LinkAction.RECONNECT, CUSTOM)
}
}
diff --git a/android/example/src/main/res/values/strings.xml b/android/example/src/main/res/values/strings.xml
index 589671b..ef938fb 100644
--- a/android/example/src/main/res/values/strings.xml
+++ b/android/example/src/main/res/values/strings.xml
@@ -9,7 +9,7 @@
Action
Action name
Enter an action name
- Charger id (network, setup, reconnect)
+ Charger id (setup, reconnect)
42
Site id (add, optional)
Optional
diff --git a/android/plugchoice/src/main/java/com/plugchoice/LinkAction.kt b/android/plugchoice/src/main/java/com/plugchoice/LinkAction.kt
index f261165..e24da31 100644
--- a/android/plugchoice/src/main/java/com/plugchoice/LinkAction.kt
+++ b/android/plugchoice/src/main/java/com/plugchoice/LinkAction.kt
@@ -6,16 +6,15 @@ package com.plugchoice
* ```kotlin
* LinkAction.addCharger() // add a charger
* LinkAction.addCharger(siteId) // add a charger at a site
- * LinkAction.network(chargerId) // change a charger's network (Wi-Fi)
* LinkAction.setup(chargerId) // set a charger up
- * LinkAction.reconnect(chargerId) // reconnect a charger to Plugchoice
+ * LinkAction.reconnect(chargerId) // get a charger reaching Plugchoice again, or change its network
* LinkAction.custom("later-action", chargerId)
* ```
*
* The SDK passes the action to the page without reading it, so an action the page learns later
* works through [custom] before it gets a helper here. Empty ids are left out.
*
- * @property name The action, for example `"add"` or `"network"`.
+ * @property name The action, for example `"add"` or `"reconnect"`.
*/
public class LinkAction private constructor(
public val name: String,
@@ -31,7 +30,6 @@ public class LinkAction private constructor(
public companion object {
public const val ADD: String = "add"
- public const val NETWORK: String = "network"
public const val SETUP: String = "setup"
public const val RECONNECT: String = "reconnect"
@@ -40,15 +38,14 @@ public class LinkAction private constructor(
@JvmOverloads
public fun addCharger(siteId: String? = null): LinkAction = of(ADD, chargerId = null, siteId = siteId)
- /** Change the network (Wi-Fi) of the charger [chargerId]. */
- @JvmStatic
- public fun network(chargerId: String): LinkAction = of(NETWORK, chargerId, siteId = null)
-
/** Set up the charger [chargerId]. */
@JvmStatic
public fun setup(chargerId: String): LinkAction = of(SETUP, chargerId, siteId = null)
- /** Reconnect the charger [chargerId] to Plugchoice. */
+ /**
+ * Get the charger [chargerId], already on Plugchoice, reaching Plugchoice again. This also
+ * changes its network (Wi-Fi and the like), so open it from a "Network settings" button too.
+ */
@JvmStatic
public fun reconnect(chargerId: String): LinkAction = of(RECONNECT, chargerId, siteId = null)
diff --git a/android/plugchoice/src/main/java/com/plugchoice/Plugchoice.kt b/android/plugchoice/src/main/java/com/plugchoice/Plugchoice.kt
index 2333d14..2a85caf 100644
--- a/android/plugchoice/src/main/java/com/plugchoice/Plugchoice.kt
+++ b/android/plugchoice/src/main/java/com/plugchoice/Plugchoice.kt
@@ -16,7 +16,7 @@ import com.plugchoice.internal.Transports
* val plugchoice = Plugchoice(fetchClientSecret = { action -> backend.plugchoiceClientSecret(action) })
*
* private val openLink = registerForActivityResult(plugchoice.link.contract()) { result: LinkResult -> … }
- * openLink.launch(LinkAction.network(chargerId))
+ * openLink.launch(LinkAction.reconnect(chargerId))
* ```
*
* @param fetchClientSecret Returns a client secret your server got from
@@ -34,7 +34,7 @@ public class Plugchoice(
) {
internal val fetchClientSecret: suspend (LinkAction) -> String = fetchClientSecret
- /** Link, the onboarding feature: add a charger, change its network, set it up, reconnect it. */
+ /** Link, the onboarding feature: add a charger, set it up, reconnect it (or change its network). */
public val link: Link = Link(this)
/**
diff --git a/android/plugchoice/src/test/java/com/plugchoice/internal/BridgeTest.kt b/android/plugchoice/src/test/java/com/plugchoice/internal/BridgeTest.kt
index 4157177..fab4ed3 100644
--- a/android/plugchoice/src/test/java/com/plugchoice/internal/BridgeTest.kt
+++ b/android/plugchoice/src/test/java/com/plugchoice/internal/BridgeTest.kt
@@ -61,13 +61,13 @@ class BridgeTest {
json(
"status" to "success",
"sessionId" to "ls_1",
- "action" to "network",
+ "action" to "reconnect",
"devices" to JSONArray().put(json("type" to "charger", "id" to "42")).put(json("type" to "meter", "id" to "m1")),
),
- openedAction = "network",
+ openedAction = "reconnect",
)
assertEquals(
- LinkResult(LinkResult.Status.SUCCESS, "network", "ls_1", listOf(Device("charger", "42"), Device("meter", "m1"))),
+ LinkResult(LinkResult.Status.SUCCESS, "reconnect", "ls_1", listOf(Device("charger", "42"), Device("meter", "m1"))),
result,
)
}
diff --git a/android/plugchoice/src/test/java/com/plugchoice/internal/InstancesTest.kt b/android/plugchoice/src/test/java/com/plugchoice/internal/InstancesTest.kt
index 8bdfd3b..8e79d2d 100644
--- a/android/plugchoice/src/test/java/com/plugchoice/internal/InstancesTest.kt
+++ b/android/plugchoice/src/test/java/com/plugchoice/internal/InstancesTest.kt
@@ -21,13 +21,13 @@ class InstancesTest {
seen += action
"cs_${action.name}_${action.chargerId}"
})
- val action = LinkAction.network("42")
+ val action = LinkAction.reconnect("42")
val id = Instances.register(plugchoice, action)
try {
val secrets = ClientSecrets(this, Instances.clientSecretSource(id)!!)
secrets.prefetch()
- assertEquals("cs_network_42", secrets.next())
- assertEquals("cs_network_42", secrets.next())
+ assertEquals("cs_reconnect_42", secrets.next())
+ assertEquals("cs_reconnect_42", secrets.next())
assertEquals(2, seen.size)
seen.forEach { assertSame("the very action launched", action, it) }
} finally {
diff --git a/android/plugchoice/src/test/java/com/plugchoice/internal/LinkDestinationTest.kt b/android/plugchoice/src/test/java/com/plugchoice/internal/LinkDestinationTest.kt
index 78582d2..b501021 100644
--- a/android/plugchoice/src/test/java/com/plugchoice/internal/LinkDestinationTest.kt
+++ b/android/plugchoice/src/test/java/com/plugchoice/internal/LinkDestinationTest.kt
@@ -18,7 +18,6 @@ class LinkDestinationTest {
fun `the URL carries the action and ids in the fragment`() {
assertEquals("https://connect.plugchoice.com/#action=add", resolve(LinkAction.addCharger()).url)
assertEquals("https://connect.plugchoice.com/#action=add&site_id=site_1", resolve(LinkAction.addCharger("site_1")).url)
- assertEquals("https://connect.plugchoice.com/#action=network&charger_id=42", resolve(LinkAction.network("42")).url)
assertEquals("https://connect.plugchoice.com/#action=setup&charger_id=42", resolve(LinkAction.setup("42")).url)
assertEquals("https://connect.plugchoice.com/#action=reconnect&charger_id=42", resolve(LinkAction.reconnect("42")).url)
assertEquals(
@@ -42,7 +41,7 @@ class LinkDestinationTest {
@Test
fun `empty ids are left out`() {
assertEquals("action=add", LinkDestination.fragment(LinkAction.addCharger("")))
- assertNull(LinkAction.custom("network", chargerId = "").chargerId)
+ assertNull(LinkAction.custom("reconnect", chargerId = "").chargerId)
}
@Test
@@ -58,8 +57,8 @@ class LinkDestinationTest {
@Test
fun `actions compare by value`() {
- assertEquals(LinkAction.network("42"), LinkAction.custom("network", "42"))
- assertEquals(LinkAction.network("42").hashCode(), LinkAction.custom("network", "42").hashCode())
+ assertEquals(LinkAction.reconnect("42"), LinkAction.custom("reconnect", "42"))
+ assertEquals(LinkAction.reconnect("42").hashCode(), LinkAction.custom("reconnect", "42").hashCode())
assertEquals("add", LinkAction.addCharger().name)
}
@@ -73,8 +72,8 @@ class LinkDestinationTest {
@Test
fun `the override replaces scheme, host and port in debug builds`() {
val ignored = mutableListOf()
- val destination = resolve(LinkAction.network("42"), "http://192.168.1.20:5173", ignored = ignored)
- assertEquals("http://192.168.1.20:5173/#action=network&charger_id=42", destination.url)
+ val destination = resolve(LinkAction.reconnect("42"), "http://192.168.1.20:5173", ignored = ignored)
+ assertEquals("http://192.168.1.20:5173/#action=reconnect&charger_id=42", destination.url)
assertEquals("http://192.168.1.20:5173", destination.origin)
assertTrue(ignored.isEmpty())
}
diff --git a/bridge/PROTOCOL.md b/bridge/PROTOCOL.md
index ce52e24..32baf49 100644
--- a/bridge/PROTOCOL.md
+++ b/bridge/PROTOCOL.md
@@ -34,7 +34,7 @@ The host app creates one SDK instance with a callback that fetches a **client se
Before showing anything the shell:
-1. Builds `https://connect.plugchoice.com/#action=`, plus `&charger_id=` and `&site_id=` when given (and not empty), each value percent-encoded (everything but RFC 3986's unreserved characters). The action is an open string (`add`, `network`, `setup`, `reconnect`, or a later one) that the shell passes on without reading it. The URL never holds the secret.
+1. Builds `https://connect.plugchoice.com/#action=`, plus `&charger_id=` and `&site_id=` when given (and not empty), each value percent-encoded (everything but RFC 3986's unreserved characters). The action is an open string (`add`, `setup`, `reconnect`, or a later one) that the shell passes on without reading it. The URL never holds the secret.
2. Uses `https://connect.plugchoice.com` as the **only** allowed origin, for the bridge and for main-frame navigation (an explicit `:443` is the same origin).
3. **Debug override**: `options.hostOverride` (for example `http://192.168.1.20:5173`, a local copy of the page) replaces the scheme, host and port and becomes the only allowed origin. It must be `http` or `https`, a host and an optional port, with at most a trailing `/`. It is honoured only in debug builds of the host app (iOS: `#if DEBUG`, as the package builds from source with the app's configuration; Android: the app's `FLAG_DEBUGGABLE`), and otherwise ignored with a log line, as is a malformed one.
4. Calls the host's callback once with the action, in parallel with loading the page, and keeps the answer for the page's first `auth.clientSecret` (§7).
diff --git a/ios/Example/Example/ContentView.swift b/ios/Example/Example/ContentView.swift
index 396ee8f..dcbee5a 100644
--- a/ios/Example/Example/ContentView.swift
+++ b/ios/Example/Example/ContentView.swift
@@ -15,7 +15,7 @@ struct ContentView: View {
}
enum ActionKind: String, CaseIterable, Identifiable {
- case add, network, setup, reconnect, custom
+ case add, setup, reconnect, custom
var id: String { rawValue }
}
@@ -180,16 +180,12 @@ struct ContentView: View {
return nil
}
return .custom(name, chargerId: chargerId.isEmpty ? nil : chargerId)
- case .network, .setup, .reconnect:
+ case .setup, .reconnect:
guard !chargerId.isEmpty else {
inputError = "Enter the charger's id."
return nil
}
- switch actionKind {
- case .network: return .network(chargerId: chargerId)
- case .setup: return .setup(chargerId: chargerId)
- default: return .reconnect(chargerId: chargerId)
- }
+ return actionKind == .setup ? .setup(chargerId: chargerId) : .reconnect(chargerId: chargerId)
}
}
diff --git a/ios/Sources/PlugchoiceSDK/Plugchoice.swift b/ios/Sources/PlugchoiceSDK/Plugchoice.swift
index a610441..7e4b936 100644
--- a/ios/Sources/PlugchoiceSDK/Plugchoice.swift
+++ b/ios/Sources/PlugchoiceSDK/Plugchoice.swift
@@ -94,7 +94,7 @@ public final class Plugchoice: Sendable {
///
/// - Parameters:
/// - action: What to do, such as `.addCharger()` or
- /// `.network(chargerId:)`.
+ /// `.reconnect(chargerId:)`.
/// - presenter: The view controller to present from.
/// - completion: Called with the result.
@MainActor
@@ -120,7 +120,7 @@ public final class Plugchoice: Sendable {
/// open string; the hosted page decides what it means. `fetchClientSecret`
/// gets it too, so your server can scope the client secret.
public struct LinkAction: Sendable, Equatable, Hashable {
- /// `add`, `network`, `setup`, `reconnect`, or a later one.
+ /// `add`, `setup`, `reconnect`, or a later one.
public let action: String
public let chargerId: String?
public let siteId: String?
@@ -136,17 +136,14 @@ public struct LinkAction: Sendable, Equatable, Hashable {
LinkAction(action: "add", siteId: siteId)
}
- /// Change a charger's network connection.
- public static func network(chargerId: String) -> LinkAction {
- LinkAction(action: "network", chargerId: chargerId)
- }
-
/// Set up a charger's electrical settings.
public static func setup(chargerId: String) -> LinkAction {
LinkAction(action: "setup", chargerId: chargerId)
}
- /// Reconnect a charger to Plugchoice.
+ /// Get a charger already on Plugchoice reaching Plugchoice again. This
+ /// also changes its network (Wi-Fi and the like), so open it from a
+ /// "Network settings" button too.
public static func reconnect(chargerId: String) -> LinkAction {
LinkAction(action: "reconnect", chargerId: chargerId)
}
diff --git a/ios/Tests/PlugchoiceSDKTests/BridgeTests.swift b/ios/Tests/PlugchoiceSDKTests/BridgeTests.swift
index 79b8e78..49c6604 100644
--- a/ios/Tests/PlugchoiceSDKTests/BridgeTests.swift
+++ b/ios/Tests/PlugchoiceSDKTests/BridgeTests.swift
@@ -61,12 +61,12 @@ final class BridgeTests: XCTestCase {
let close = try close([
"status": "success",
"sessionId": "s1",
- "action": "network",
+ "action": "reconnect",
"devices": [["type": "charger", "id": "c1"], ["type": "meter", "id": "m1"]],
])
XCTAssertEqual(close, Bridge.SessionClose(
status: .success,
- action: "network",
+ action: "reconnect",
sessionId: "s1",
devices: [Device(type: "charger", id: "c1"), Device(type: "meter", id: "m1")],
error: nil
diff --git a/ios/Tests/PlugchoiceSDKTests/ClientSecretsTests.swift b/ios/Tests/PlugchoiceSDKTests/ClientSecretsTests.swift
index 2363cd1..6da73f7 100644
--- a/ios/Tests/PlugchoiceSDKTests/ClientSecretsTests.swift
+++ b/ios/Tests/PlugchoiceSDKTests/ClientSecretsTests.swift
@@ -43,7 +43,7 @@ final class ClientSecretsTests: XCTestCase {
private struct Failure: Error {}
- private let opened = LinkAction.network(chargerId: "c-1")
+ private let opened = LinkAction.reconnect(chargerId: "c-1")
private func secrets(_ backend: Backend, timeout: TimeInterval = ClientSecrets.defaultTimeout) -> ClientSecrets {
ClientSecrets(action: opened, fetch: { try await backend.fetch($0) }, timeout: timeout)
@@ -84,7 +84,7 @@ final class ClientSecretsTests: XCTestCase {
XCTAssertEqual([first, second, third], ["cs_test_1", "cs_test_2", "cs_test_3"])
XCTAssertEqual(backend.calls, 3)
XCTAssertEqual(backend.actions, [opened, opened, opened], "refreshes get the same action")
- XCTAssertEqual(backend.actions.first?.action, "network")
+ XCTAssertEqual(backend.actions.first?.action, "reconnect")
XCTAssertEqual(backend.actions.first?.chargerId, "c-1")
}
diff --git a/ios/Tests/PlugchoiceSDKTests/LinkTargetTests.swift b/ios/Tests/PlugchoiceSDKTests/LinkTargetTests.swift
index 7203b80..325ef80 100644
--- a/ios/Tests/PlugchoiceSDKTests/LinkTargetTests.swift
+++ b/ios/Tests/PlugchoiceSDKTests/LinkTargetTests.swift
@@ -16,7 +16,6 @@ final class LinkTargetTests: XCTestCase {
func testEveryActionAndItsIds() {
let cases: [(LinkAction, String)] = [
(.addCharger(siteId: "site-1"), "#action=add&site_id=site-1"),
- (.network(chargerId: "c-1"), "#action=network&charger_id=c-1"),
(.setup(chargerId: "c-1"), "#action=setup&charger_id=c-1"),
(.reconnect(chargerId: "c-1"), "#action=reconnect&charger_id=c-1"),
(.custom("diagnose", chargerId: "c-1"), "#action=diagnose&charger_id=c-1"),
@@ -54,8 +53,8 @@ final class LinkTargetTests: XCTestCase {
// MARK: - hostOverride
func testOverrideReplacesSchemeHostAndPortInDebug() {
- let target = LinkTarget(action: .network(chargerId: "c-1"), hostOverride: "http://192.168.1.20:5173", honourOverride: true)
- XCTAssertEqual(target.url.absoluteString, "http://192.168.1.20:5173/#action=network&charger_id=c-1")
+ let target = LinkTarget(action: .reconnect(chargerId: "c-1"), hostOverride: "http://192.168.1.20:5173", honourOverride: true)
+ XCTAssertEqual(target.url.absoluteString, "http://192.168.1.20:5173/#action=reconnect&charger_id=c-1")
XCTAssertEqual(target.allowedOrigin.description, "http://192.168.1.20:5173")
let allowList = OriginAllowList([target.allowedOrigin])
XCTAssertTrue(allowList.allows(url: target.url))
@@ -95,12 +94,11 @@ final class LinkTargetTests: XCTestCase {
func testActions() {
XCTAssertEqual(LinkAction.addCharger(), LinkAction(action: "add"))
XCTAssertEqual(LinkAction.addCharger(siteId: "s"), LinkAction(action: "add", siteId: "s"))
- XCTAssertEqual(LinkAction.network(chargerId: "c"), LinkAction(action: "network", chargerId: "c"))
XCTAssertEqual(LinkAction.setup(chargerId: "c"), LinkAction(action: "setup", chargerId: "c"))
XCTAssertEqual(LinkAction.reconnect(chargerId: "c"), LinkAction(action: "reconnect", chargerId: "c"))
XCTAssertEqual(LinkAction.custom("x", chargerId: "c"), LinkAction(action: "x", chargerId: "c"))
- let network = LinkAction.network(chargerId: "c")
- XCTAssertEqual([network.action, network.chargerId, network.siteId], ["network", "c", nil])
+ let reconnect = LinkAction.reconnect(chargerId: "c")
+ XCTAssertEqual([reconnect.action, reconnect.chargerId, reconnect.siteId], ["reconnect", "c", nil])
}
func testTransportsInTheTestHost() {
@@ -125,9 +123,9 @@ final class LinkTargetTests: XCTestCase {
func testAScreenClosedByTheHostReportsTheOpenedAction() throws {
let plugchoice = Plugchoice(fetchClientSecret: { _ in "cs_test_secret" })
var result: LinkResult?
- let controller = plugchoice.link.makeController(.network(chargerId: "c-1")) { result = $0 }
+ let controller = plugchoice.link.makeController(.reconnect(chargerId: "c-1")) { result = $0 }
controller.closeForHost()
- XCTAssertEqual(result, LinkResult(status: .cancelled, action: "network"))
+ XCTAssertEqual(result, LinkResult(status: .cancelled, action: "reconnect"))
}
@MainActor
@@ -137,8 +135,8 @@ final class LinkTargetTests: XCTestCase {
LinkResult(status: .cancelled, action: "add", sessionId: nil, devices: [], error: nil)
)
XCTAssertEqual(
- LinkViewController.ownResult(action: "network", loadErrorMessage: "offline"),
- LinkResult(status: .error, action: "network", error: LinkError(code: "pageLoadFailed", message: "offline"))
+ LinkViewController.ownResult(action: "reconnect", loadErrorMessage: "offline"),
+ LinkResult(status: .error, action: "reconnect", error: LinkError(code: "pageLoadFailed", message: "offline"))
)
}
diff --git a/react-native/__tests__/clientSecret.test.ts b/react-native/__tests__/clientSecret.test.ts
index f1ec993..bb628e6 100644
--- a/react-native/__tests__/clientSecret.test.ts
+++ b/react-native/__tests__/clientSecret.test.ts
@@ -45,10 +45,10 @@ describe('the client-secret bridge', () => {
const { configurePlugchoice } = await load();
configurePlugchoice({ fetchClientSecret });
- const answer = await fake.requestClientSecret({ action: 'network', chargerId: 'ch_1' });
+ const answer = await fake.requestClientSecret({ action: 'reconnect', chargerId: 'ch_1' });
expect(answer).toEqual({ secret: 'cs_test_123' });
- expect(fetchClientSecret).toHaveBeenCalledWith({ action: 'network', chargerId: 'ch_1' });
+ expect(fetchClientSecret).toHaveBeenCalledWith({ action: 'reconnect', chargerId: 'ch_1' });
expect(fake.module.provideClientSecret).toHaveBeenCalledWith('request-1', 'cs_test_123');
expect(fake.module.rejectClientSecret).not.toHaveBeenCalled();
});
@@ -217,17 +217,17 @@ describe('the client-secret bridge', () => {
const { configurePlugchoice, openLink } = await load();
configurePlugchoice({ fetchClientSecret });
- const result = await openLink({ action: 'network', chargerId: 'ch_1' });
+ const result = await openLink({ action: 'reconnect', chargerId: 'ch_1' });
expect(result).toEqual({
status: 'success',
- action: 'network',
+ action: 'reconnect',
sessionId: 'ls_1',
devices: [{ type: 'charger', id: 'ch_1' }],
});
expect(fetchClientSecret.mock.calls).toEqual([
- [{ action: 'network', chargerId: 'ch_1' }],
- [{ action: 'network', chargerId: 'ch_1' }],
+ [{ action: 'reconnect', chargerId: 'ch_1' }],
+ [{ action: 'reconnect', chargerId: 'ch_1' }],
]);
});
diff --git a/react-native/__tests__/openLink.test.ts b/react-native/__tests__/openLink.test.ts
index f6b0fc0..2711fbc 100644
--- a/react-native/__tests__/openLink.test.ts
+++ b/react-native/__tests__/openLink.test.ts
@@ -47,11 +47,11 @@ describe('openLink', () => {
});
it('passes chargerId and siteId, and leaves out empty or missing ids', async () => {
- fake.module.openLink.mockResolvedValue({ status: 'cancelled', action: 'network', devices: [] });
+ fake.module.openLink.mockResolvedValue({ status: 'cancelled', action: 'reconnect', devices: [] });
const { openLink } = await configured();
- await openLink({ action: 'network', chargerId: 'ch_1' });
- expect(fake.module.openLink).toHaveBeenLastCalledWith({ action: 'network', chargerId: 'ch_1' }, {});
+ await openLink({ action: 'reconnect', chargerId: 'ch_1' });
+ expect(fake.module.openLink).toHaveBeenLastCalledWith({ action: 'reconnect', chargerId: 'ch_1' }, {});
await openLink({ action: 'add', siteId: 'site_1', chargerId: '' });
expect(fake.module.openLink).toHaveBeenLastCalledWith({ action: 'add', siteId: 'site_1' }, {});
@@ -107,9 +107,9 @@ describe('openLink', () => {
fake.module.openLink.mockResolvedValue({ status: 'cancelled', devices: [] });
const { openLink } = await configured();
- await expect(openLink({ action: 'network', chargerId: 'ch_1' })).resolves.toEqual({
+ await expect(openLink({ action: 'reconnect', chargerId: 'ch_1' })).resolves.toEqual({
status: 'cancelled',
- action: 'network',
+ action: 'reconnect',
sessionId: null,
devices: [],
});
@@ -169,7 +169,7 @@ describe('openLink', () => {
const { openLink } = await configured();
const firstCall = openLink({ action: 'add' });
- await expect(openLink({ action: 'network', chargerId: 'ch_1' })).rejects.toMatchObject({
+ await expect(openLink({ action: 'reconnect', chargerId: 'ch_1' })).rejects.toMatchObject({
code: 'ERR_LINK_ALREADY_OPEN',
});
expect(fake.module.openLink).toHaveBeenCalledTimes(1);
@@ -179,11 +179,11 @@ describe('openLink', () => {
fake.module.openLink.mockResolvedValueOnce({
status: 'success',
- action: 'network',
+ action: 'reconnect',
sessionId: 'ls_2',
devices: [{ type: 'charger', id: 'ch_1' }],
});
- await expect(openLink({ action: 'network', chargerId: 'ch_1' })).resolves.toMatchObject({
+ await expect(openLink({ action: 'reconnect', chargerId: 'ch_1' })).resolves.toMatchObject({
status: 'success',
sessionId: 'ls_2',
});
@@ -241,7 +241,7 @@ describe('openLink', () => {
{ action: '' },
{ action: ' ' },
{ action: 42 },
- { action: 'network', chargerId: 42 },
+ { action: 'reconnect', chargerId: 42 },
{ action: 'add', siteId: {} },
]) {
await expect(untyped(action)).rejects.toBeInstanceOf(TypeError);
diff --git a/react-native/src/openLink.ts b/react-native/src/openLink.ts
index 54f9e6f..b8a47b0 100644
--- a/react-native/src/openLink.ts
+++ b/react-native/src/openLink.ts
@@ -12,7 +12,7 @@ let isOpen = false;
* {@link configurePlugchoice} with this action.
*
* ```ts
- * const result = await openLink({ action: 'network', chargerId });
+ * const result = await openLink({ action: 'reconnect', chargerId });
* ```
*
* Throws a `TypeError` for an action that isn't `{ action: string, chargerId?, siteId? }`. Rejects
@@ -54,7 +54,7 @@ export async function openLink(action: LinkAction): Promise {
/** The action as the native module takes it, or a `TypeError`. */
function checkedAction(value: unknown): NativeLinkAction {
if (!isRecord(value)) {
- throw new TypeError("openLink: pass an action such as { action: 'add' } or { action: 'network', chargerId }");
+ throw new TypeError("openLink: pass an action such as { action: 'add' } or { action: 'reconnect', chargerId }");
}
if (typeof value.action !== 'string' || value.action.trim() === '') {
throw new TypeError('openLink: action.action must be a non-empty string');
diff --git a/react-native/src/types.ts b/react-native/src/types.ts
index 9dcbbc4..e9a3201 100644
--- a/react-native/src/types.ts
+++ b/react-native/src/types.ts
@@ -4,8 +4,8 @@
* names it.
*/
export type LinkAction = {
- /** `add`, `network`, `setup`, `reconnect`, or a later one. */
- action: 'add' | 'network' | 'setup' | 'reconnect' | (string & {});
+ /** `add`, `setup`, `reconnect` (which also changes a charger's network), or a later one. */
+ action: 'add' | 'setup' | 'reconnect' | (string & {});
/** The charger. Every action but `add` needs one. */
chargerId?: string;
/** `add` only: the site to add the charger to. */