Files
php-qml/framework/qml/src/BackendConnection.h

92 lines
2.6 KiB
C
Raw Normal View History

#pragma once
#include <QObject>
#include <QString>
#include <QtQmlIntegration>
class QNetworkAccessManager;
class QNetworkReply;
class QTimer;
class QQmlEngine;
class QJSEngine;
namespace PhpQml::Bridge {
/// Owns the backend lifecycle and exposes its health to QML.
///
/// Phase 1 implements **dev mode**: reads `BRIDGE_URL` and `BRIDGE_TOKEN`
/// from env, periodically probes `<url>/healthz`, and reports the result
/// as `connectionState`. Bundled mode (spawning FrankenPHP as a child)
/// arrives in Phase 4. See PLAN.md §3 (Run modes), §7 (BackendConnection).
class BackendConnection : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(Mode mode READ mode CONSTANT)
Q_PROPERTY(QString url READ url CONSTANT)
Q_PROPERTY(QString token READ token NOTIFY tokenChanged)
Q_PROPERTY(ConnectionState connectionState READ connectionState NOTIFY connectionStateChanged)
Q_PROPERTY(QString error READ error NOTIFY errorChanged)
public:
enum class Mode {
Dev,
Bundled, // Phase 4
};
Q_ENUM(Mode)
/// Phase 1 surfaces only Connecting / Online / Error. The full enum
/// (Reconnecting, Offline) lands with the Update Semantics layer in
/// Phase 2 (PLAN.md §5).
enum class ConnectionState {
Connecting,
Online,
Error,
};
Q_ENUM(ConnectionState)
explicit BackendConnection(QObject* parent = nullptr);
~BackendConnection() override;
static BackendConnection* create(QQmlEngine* engine, QJSEngine*);
Mode mode() const noexcept { return m_mode; }
QString url() const { return m_url; }
QString token() const { return m_token; }
ConnectionState connectionState() const noexcept { return m_state; }
QString error() const { return m_error; }
Q_INVOKABLE void restart();
signals:
void tokenChanged();
void connectionStateChanged();
void errorChanged();
/// Forward-compatible signal for §3 *Edge cases — Per-session secret
/// rotation*. In Phase 1 dev mode it is never emitted; bundled mode
/// in Phase 4 will fire it on child restart.
void tokenRotated(const QString& newToken);
private slots:
void probe();
void onProbeFinished();
private:
void setState(ConnectionState s);
void setError(const QString& msg);
Mode m_mode = Mode::Dev;
QString m_url;
QString m_token;
ConnectionState m_state = ConnectionState::Connecting;
QString m_error;
QNetworkAccessManager* m_nam = nullptr;
QNetworkReply* m_pendingReply = nullptr;
QTimer* m_retryTimer = nullptr;
};
} // namespace PhpQml::Bridge