@alteran/astro 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -40,6 +40,28 @@ const CORE_ROUTES = [
40
40
  { pattern: '/xrpc/com.atproto.sync.getRepo.range', entrypoint: './src/pages/xrpc/com.atproto.sync.getRepo.range.ts' },
41
41
  { pattern: '/xrpc/com.atproto.sync.listBlobs', entrypoint: './src/pages/xrpc/com.atproto.sync.listBlobs.ts' },
42
42
  { pattern: '/xrpc/com.atproto.sync.listRepos', entrypoint: './src/pages/xrpc/com.atproto.sync.listRepos.ts' },
43
+ // Additional atproto endpoints
44
+ { pattern: '/xrpc/com.atproto.identity.signPlcOperation', entrypoint: './src/pages/xrpc/com.atproto.identity.signPlcOperation.ts' },
45
+ { pattern: '/xrpc/com.atproto.server.getServiceAuth', entrypoint: './src/pages/xrpc/com.atproto.server.getServiceAuth.ts' },
46
+ // AppView proxy endpoints (bsky)
47
+ { pattern: '/xrpc/app.bsky.actor.getProfile', entrypoint: './src/pages/xrpc/app.bsky.actor.getProfile.ts' },
48
+ { pattern: '/xrpc/app.bsky.actor.getProfiles', entrypoint: './src/pages/xrpc/app.bsky.actor.getProfiles.ts' },
49
+ { pattern: '/xrpc/app.bsky.actor.getPreferences', entrypoint: './src/pages/xrpc/app.bsky.actor.getPreferences.ts' },
50
+ { pattern: '/xrpc/app.bsky.actor.putPreferences', entrypoint: './src/pages/xrpc/app.bsky.actor.putPreferences.ts' },
51
+ { pattern: '/xrpc/app.bsky.feed.getAuthorFeed', entrypoint: './src/pages/xrpc/app.bsky.feed.getAuthorFeed.ts' },
52
+ { pattern: '/xrpc/app.bsky.feed.getPostThread', entrypoint: './src/pages/xrpc/app.bsky.feed.getPostThread.ts' },
53
+ { pattern: '/xrpc/app.bsky.feed.getPosts', entrypoint: './src/pages/xrpc/app.bsky.feed.getPosts.ts' },
54
+ { pattern: '/xrpc/app.bsky.feed.getTimeline', entrypoint: './src/pages/xrpc/app.bsky.feed.getTimeline.ts' },
55
+ { pattern: '/xrpc/app.bsky.graph.getFollowers', entrypoint: './src/pages/xrpc/app.bsky.graph.getFollowers.ts' },
56
+ { pattern: '/xrpc/app.bsky.graph.getFollows', entrypoint: './src/pages/xrpc/app.bsky.graph.getFollows.ts' },
57
+ { pattern: '/xrpc/app.bsky.labeler.getServices', entrypoint: './src/pages/xrpc/app.bsky.labeler.getServices.ts' },
58
+ { pattern: '/xrpc/app.bsky.notification.getUnreadCount', entrypoint: './src/pages/xrpc/app.bsky.notification.getUnreadCount.ts' },
59
+ { pattern: '/xrpc/app.bsky.notification.listNotifications', entrypoint: './src/pages/xrpc/app.bsky.notification.listNotifications.ts' },
60
+ { pattern: '/xrpc/app.bsky.unspecced.getAgeAssuranceState', entrypoint: './src/pages/xrpc/app.bsky.unspecced.getAgeAssuranceState.ts' },
61
+ { pattern: '/xrpc/app.bsky.unspecced.getConfig', entrypoint: './src/pages/xrpc/app.bsky.unspecced.getConfig.ts' },
62
+ // Chat endpoints (proxied)
63
+ { pattern: '/xrpc/chat.bsky.convo.getLog', entrypoint: './src/pages/xrpc/chat.bsky.convo.getLog.ts' },
64
+ { pattern: '/xrpc/chat.bsky.convo.listConvos', entrypoint: './src/pages/xrpc/chat.bsky.convo.listConvos.ts' },
43
65
  ];
44
66
 
45
67
  const ROOT_ROUTE = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alteran/astro",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Astro integration for running a Cloudflare-hosted Bluesky PDS with Alteran.",
5
5
  "module": "index.js",
6
6
  "types": "index.d.ts",
@@ -6,8 +6,22 @@ import { Sequencer } from '../worker/sequencer';
6
6
  export function createExports(manifest: SSRManifest) {
7
7
  const app = new App(manifest);
8
8
  const fetch = async (request: Request, env: unknown, context: unknown) => {
9
+ // Ensure ASSETS binding exists to satisfy @astrojs/cloudflare handler
10
+ // even when the worker has no static asset binding configured.
11
+ const e = env as any;
12
+ if (!e?.ASSETS || typeof e.ASSETS.fetch !== 'function') {
13
+ e.ASSETS = {
14
+ async fetch() {
15
+ return new Response('Not Found', {
16
+ status: 404,
17
+ headers: { 'Cache-Control': 'public, max-age=60' },
18
+ });
19
+ },
20
+ };
21
+ }
22
+
9
23
  // Delegate to the Cloudflare adapter handler while preserving Alteran additions.
10
- return await handle(manifest, app, request, env as any, context as any);
24
+ return await handle(manifest, app, request, e, context as any);
11
25
  };
12
26
 
13
27
  return {
@@ -79,8 +79,16 @@ export function createPdsFetchHandler(options?: CreatePdsFetchHandlerOptions): P
79
79
 
80
80
  // Fire-and-forget: let relays know this PDS exists and is reachable.
81
81
  // Throttled per isolate and safe to call frequently.
82
+ // Best-effort: notify relays, but avoid doing so on relay-initiated endpoints
83
+ // to prevent feedback loops (describeServer/subscribeRepos).
82
84
  try {
83
- ctx.waitUntil(notifyRelaysIfNeeded(resolvedEnv as any, request.url));
85
+ const pathname = new URL(request.url).pathname;
86
+ const isRelayPath =
87
+ pathname === '/xrpc/com.atproto.server.describeServer' ||
88
+ pathname === '/xrpc/com.atproto.sync.subscribeRepos';
89
+ if (!isRelayPath) {
90
+ ctx.waitUntil(notifyRelaysIfNeeded(resolvedEnv as any, request.url));
91
+ }
84
92
  } catch (err) {
85
93
  // Never block on relay notification
86
94
  }
@@ -266,6 +266,16 @@ export class Sequencer {
266
266
  console.error('Failed to send info frame:', error);
267
267
  }
268
268
 
269
+ // Keep the connection alive to avoid intermediary idle timeouts (e.g., CF edge)
270
+ // Send a lightweight #info heartbeat every ~25s. Most clients ignore unknown #info
271
+ // messages; this is safe and keeps the socket active.
272
+ const keepalive = setInterval(() => {
273
+ try {
274
+ const ka = createInfoFrame('keepalive', 'ping');
275
+ ws.send(ka.toFramedBytes());
276
+ } catch {}
277
+ }, 25_000);
278
+
269
279
  // Set up event handlers
270
280
  ws.addEventListener('message', (evt) => {
271
281
  try {
@@ -280,10 +290,12 @@ export class Sequencer {
280
290
 
281
291
  ws.addEventListener('close', () => {
282
292
  this.clients.delete(id);
293
+ clearInterval(keepalive);
283
294
  });
284
295
 
285
296
  ws.addEventListener('error', () => {
286
297
  this.clients.delete(id);
298
+ clearInterval(keepalive);
287
299
  });
288
300
 
289
301
  // Replay buffered events if cursor provided