Add a remote endpoint
Implement a new RemoteOperation for this library the way the existing ones are written. The full,
authoritative standards live in AGENTS.md — this skill is the step-by-step
procedure. When they disagree, AGENTS.md wins.
0. Ground yourself in the reference
Read the canonical package before writing anything:
library/src/main/java/com/nextcloud/android/lib/resources/governance/— operations (GET/POST/DELETE)library/src/main/java/com/nextcloud/android/lib/resources/governance/model/—@Serializablemodels + enumslibrary/src/main/java/com/owncloud/android/lib/ocs/OcsResponse.kt— sharedOcsResponse<T>,ocsJson,SEPARATOR
Pick the existing operation closest to the one you're adding (list-returning GET, single-object GET, POST with body, DELETE) and mirror its structure.
1. Confirm the contract
Establish, from the user or the API: HTTP method, path (base + segments), path/query params, request body shape (if any), and the JSON response shape. If any of these is unclear, ask before coding.
2. Models — under <feature>.model
For each new wire type create a Kotlin @Serializable data class (or enum with @SerialName) in
com.nextcloud.android.lib.resources.<feature>.model. Never put models beside the operation or in an
unrelated package. Reuse the shared OcsResponse<T> envelope — do not model the ocs/data/meta
wrapper yourself.
3. Constants
- Reuse
com.owncloud.android.lib.ocs.SEPARATORfor"/"— never inline it. - Put the base path and each path segment in the operation's
companion objectasprivate const val(ENDPOINT,AVAILABLE, …). No hardcoded endpoint strings, param keys, or headers.
4. Operation
Extend OCSRemoteOperation<T> and follow the template in AGENTS.md exactly:
@Suppress("TooGenericExceptionCaught")onrun().- Build the method (
GetMethod/PostMethod/DeleteMethod), thenreturn try { … } catch (e: Exception) { failure(e) } finally { method.releaseConnection() }. - Guard clause first:
if (status != HttpStatus.SC_OK) return RemoteOperationResult(false, method). No nested if/else; keep the body linear. - Decode with
ocsJson.decodeFromString<OcsResponse<T>>(method.getResponseBodyAsString()).ocs.data. - Success:
RemoteOperationResult<T>(true, method).apply { resultData = data }(property, not a setter). - Keep ≤ 2
returnkeywords total (guard +return try). The success andfailurevalues are expressions, not returns. - Add the
private fun failure(e: Exception)helper with@Suppress("DEPRECATION")(forlogMessage) that logs viaLog_OC.eand returnsRemoteOperationResult(e). - No class-level KDoc that just restates the class name.
5. Tests
Add unit tests beside the existing ones in
library/src/test/java/com/nextcloud/android/lib/resources/<feature>/, mirroring the governance
parsing tests — feed a sample OCS JSON string through ocsJson.decodeFromString<OcsResponse<…>>(json)
and assert the decoded fields.
Add integration test that makes the actual API call and add an instrumented test under
library/src/androidTest/java/com/nextcloud/android/lib/resources/<feature>/ that runs the operation
against a live server and asserts the RemoteOperationResult (mirror the existing *IT tests).
6. Verify
Verify — detekt, spotlessKotlinCheck, and lint (see .github/workflows/check.yml):
./gradlew :library:compileDebugKotlin
./gradlew :library:testDebugUnitTest --tests "com.nextcloud.android.lib.resources.<feature>.*"
./gradlew :library:detekt
./gradlew :library:spotlessKotlinCheck
./gradlew :library:lint
All must pass. Check lines are ≤ 120 (spotless check can't always be relied on locally — see AGENTS.md). Then review the diff against the "Definition of done" checklist in AGENTS.md and remove anything unrelated.