import { LogLevel } from './enums/LogLevel.enum'; import { FailedPhase, FailureErrorCode } from './internals/CodePushApiSdk.types'; import { NativeRNAppZungCodePushModule } from './internals/NativeRNAppZungCodePushModule'; import { log } from './internals/utils/log'; export { FailedPhase, FailureErrorCode }; /** * Input for {@link reportDeploymentFailure}. All wire-level caps and value * normalization are enforced server-side AND mirrored on native — passing * over-long values is safe (they get truncated) but returning the same * normalized value is not currently exposed back to JS. */ export interface ReportDeploymentFailureOptions { /** * Recommended values from {@link FailureErrorCode}; free strings are * accepted but discouraged (the server's Top-N aggregation view buckets * by exact string). Server cap: 64 chars. */ errorCode: FailureErrorCode | string; /** * Free-form text (e.g. raw exception message). Optional — omit to skip. * Server cap: 500 chars. */ errorMessage?: string; /** * Which CodePush lifecycle phase the failure happened in. Must be one of * {@link FailedPhase}; anything else is coerced to `"unknown"` server-side. * Server cap: 20 chars. */ failedPhase: FailedPhase | string; } /** * Reports a deployment failure for the currently-running CodePush update, * routed through the same code path as the library's automatic * download/rollback failure detection. * * **Behaviour on native:** * * 1. Persists `{errorCode, errorMessage, failedPhase}` into the native * `FailedUpdates` slot (alongside the package metadata) and sets the * rollback-report flag. This guarantees the failure is also re-uploaded * on the next `sync()` / `notifyAppReady()` cycle (next-sync fallback). * 2. Fires an immediate native HTTP `POST /report_status/deploy` on a * background thread (primary channel). Failure is silent — the next-sync * fallback above is the safety net. * 3. Does NOT roll back the running bundle. The caller is responsible for * deciding whether to call {@link restartApp} or take other action. * 4. No-ops (with a native log) if there is no current CodePush package * on disk (the app is running off the binary-bundled JS). Callers are * expected to verify package presence — e.g. via {@link getUpdateMetadata} * — before invoking. * * **The Promise resolves once the bridge dispatch completes**, NOT when the * server confirms receipt — the underlying mechanism is fire-and-forget. A * rejection only indicates the bridge call itself failed (unusual; normally * a logic bug in the JS↔native marshalling). * * **Where to call this from:** * * - Use this JS API when the failure is detected from JS code (e.g. an * integrity check after the bundle is loaded, a runtime sanity check * that decides to abandon a deployment). * - When the failure is detected in native code BEFORE the JS bridge is up * (e.g. a startup-time integrity check), call the native API directly: * - iOS: `[CodePush reportDeploymentFailureWithErrorCode:errorMessage:failedPhase:]` * - Android: `CodePush.getInstance(context).reportDeploymentFailure(...)` * * Both paths funnel into the exact same persistence + HTTP-fire logic. * * @example * ```ts * import { * reportDeploymentFailure, * FailureErrorCode, * FailedPhase, * } from 'john-react-native-code-push'; * * try { * await runIntegrityCheck(); * } catch (e) { * await reportDeploymentFailure({ * errorCode: FailureErrorCode.HASH_MISMATCH, * errorMessage: e.message, * failedPhase: FailedPhase.RUNTIME, * }); * } * ``` */ export async function reportDeploymentFailure({ errorCode, errorMessage, failedPhase, }: ReportDeploymentFailureOptions): Promise { log( LogLevel.DEBUG, `reportDeploymentFailure: errorCode=${errorCode}, failedPhase=${failedPhase}`, ); await NativeRNAppZungCodePushModule.reportDeploymentFailure( errorCode, errorMessage ?? '', failedPhase, ); }