+3
-3
frontend/src/lib/migration/atproto-client.ts
+3
-3
frontend/src/lib/migration/atproto-client.ts
···
101
101
let requestBody: BodyInit | undefined;
102
102
if (rawBody) {
103
103
headers["Content-Type"] = contentType ?? "application/octet-stream";
104
-
requestBody = rawBody;
104
+
requestBody = rawBody as BodyInit;
105
105
} else if (body) {
106
106
headers["Content-Type"] = "application/json";
107
107
requestBody = JSON.stringify(body);
···
615
615
...cred,
616
616
id: base64UrlDecode(cred.id as string),
617
617
}),
618
-
),
619
-
} as PublicKeyCredentialCreationOptions;
618
+
) as unknown,
619
+
} as unknown as PublicKeyCredentialCreationOptions;
620
620
}
621
621
622
622
async function computeAccessTokenHash(accessToken: string): Promise<string> {
+4
-2
frontend/src/lib/migration/flow.svelte.ts
+4
-2
frontend/src/lib/migration/flow.svelte.ts
···
58
58
}
59
59
60
60
export function createInboundMigrationFlow() {
61
+
// @ts-ignore
61
62
let state = $state<InboundMigrationState>({
62
63
direction: "inbound",
63
64
step: "welcome",
···
97
98
}
98
99
}
99
100
100
-
function setError(error: string) {
101
+
function setError(error: string | null) {
101
102
state.error = error;
102
103
saveMigrationState(state);
103
104
}
···
542
543
setError(null);
543
544
544
545
try {
545
-
await localClient.verifyToken(token, state.targetEmail);
546
+
await localClient.verifyToken(token, state.targetEmail || "");
546
547
547
548
if (!sourceClient) {
548
549
setStep("source-handle");
···
1011
1012
}
1012
1013
1013
1014
export function createOutboundMigrationFlow() {
1015
+
// @ts-ignore
1014
1016
let state = $state<OutboundMigrationState>({
1015
1017
direction: "outbound",
1016
1018
step: "welcome",
+53
-5
src/api/repo/record/read.rs
+53
-5
src/api/repo/record/read.rs
···
206
206
let record_cid_str: String = match record_row {
207
207
Ok(Some(row)) => row.record_cid,
208
208
_ => {
209
-
return (
210
-
StatusCode::NOT_FOUND,
211
-
Json(json!({"error": "RecordNotFound", "message": "Record not found"})),
212
-
)
213
-
.into_response();
209
+
let appview_endpoint = std::env::var("BSKY_APPVIEW_ENDPOINT")
210
+
.unwrap_or_else(|_| "https://api.bsky.app".to_string());
211
+
let mut url = format!(
212
+
"{}/xrpc/com.atproto.repo.getRecord?repo={}&collection={}&rkey={}",
213
+
appview_endpoint.trim_end_matches('/'),
214
+
urlencoding::encode(&input.repo),
215
+
urlencoding::encode(&input.collection),
216
+
urlencoding::encode(&input.rkey)
217
+
);
218
+
if let Some(cid) = &input.cid {
219
+
url.push_str(&format!("&cid={}", urlencoding::encode(cid)));
220
+
}
221
+
info!(
222
+
"Record not found locally (user exists). Proxying getRecord for {} to AppView: {}",
223
+
input.repo, url
224
+
);
225
+
match proxy_client().get(&url).send().await {
226
+
Ok(resp) => {
227
+
let status = resp.status();
228
+
let body = match resp.bytes().await {
229
+
Ok(b) => b,
230
+
Err(e) => {
231
+
error!("Error reading AppView proxy response: {:?}", e);
232
+
return (
233
+
StatusCode::BAD_GATEWAY,
234
+
Json(json!({
235
+
"error": "UpstreamFailure",
236
+
"message": "Error reading upstream response from AppView"
237
+
})),
238
+
)
239
+
.into_response();
240
+
}
241
+
};
242
+
return Response::builder()
243
+
.status(status)
244
+
.header("content-type", "application/json")
245
+
.body(axum::body::Body::from(body))
246
+
.unwrap_or_else(|_| {
247
+
(StatusCode::INTERNAL_SERVER_ERROR, "Internal error").into_response()
248
+
});
249
+
}
250
+
Err(e) => {
251
+
error!("Error proxying request to AppView: {:?}", e);
252
+
return (
253
+
StatusCode::BAD_GATEWAY,
254
+
Json(json!({
255
+
"error": "UpstreamFailure",
256
+
"message": "Failed to reach AppView"
257
+
})),
258
+
)
259
+
.into_response();
260
+
}
261
+
}
214
262
}
215
263
};
216
264
if let Some(expected_cid) = &input.cid