feat: Sprint 2 — WordPress plugin (auth/api/site-info/admin) + web SiteConnector
Mirror to GitHub / mirror (push) Canceled after 0s

- plugin: Wursor_Auth (token hashing, HMAC, scoped tokens), Wursor_API (REST + auth), Wursor_Site_Info (builder/capabilities/preflight), Wursor_Admin
- plugin: test-auth.php (10 auth tests, run in a WP+PHP env)
- web: SiteConnector pairing UI (code + poll + states)
- api: PluginClient signs full REST route (matches WP get_route)
- 92 unit tests green
This commit is contained in:
SinachPat
2026-08-15 23:17:16 +01:00
parent 9801b9475b
commit 69b2481299
12 changed files with 515 additions and 4 deletions
+51
View File
@@ -0,0 +1,51 @@
import { useEffect, useState } from 'react';
type SiteConnectorProps = {
code: string;
checkConnected: () => Promise<{ connected: boolean }>;
pollIntervalMs?: number;
};
type State = 'pending' | 'connected' | 'error';
export function SiteConnector({ code, checkConnected, pollIntervalMs = 2000 }: SiteConnectorProps) {
const [state, setState] = useState<State>('pending');
useEffect(() => {
let cancelled = false;
let timer: ReturnType<typeof setTimeout> | undefined;
async function poll() {
try {
const { connected } = await checkConnected();
if (cancelled) return;
if (connected) {
setState('connected');
return;
}
timer = setTimeout(poll, pollIntervalMs);
} catch {
if (!cancelled) setState('error');
}
}
void poll();
return () => {
cancelled = true;
if (timer !== undefined) clearTimeout(timer);
};
}, [checkConnected, pollIntervalMs]);
if (state === 'connected') {
return <div className="wursor-connected">Site connected</div>;
}
if (state === 'error') {
return <div className="wursor-error">Connection failed</div>;
}
return (
<div className="wursor-pairing">
<p>Enter this code in your Wursor plugin:</p>
<code className="wursor-pairing-code">{code}</code>
</div>
);
}