@getjack/jack 0.1.12 → 0.1.14

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.
@@ -373,6 +373,18 @@ export async function listAllProjects(): Promise<ResolvedProject[]> {
373
373
  projectMap.set(managed.id, resolved);
374
374
  }
375
375
  }
376
+
377
+ // Mark orphaned local managed projects (not found on control plane) as errors
378
+ for (const [, project] of projectMap) {
379
+ if (
380
+ project.deployMode === "managed" &&
381
+ project.status === "syncing" &&
382
+ !project.sources.controlPlane
383
+ ) {
384
+ project.status = "error";
385
+ project.errorMessage = "Project not found in jack cloud. Run: jack unlink && jack ship";
386
+ }
387
+ }
376
388
  } catch {
377
389
  // Control plane unavailable, use local-only data
378
390
  }
@@ -12,6 +12,7 @@ const SESSION_ID = crypto.randomUUID();
12
12
  // EVENT REGISTRY
13
13
  // ============================================
14
14
  export const Events = {
15
+ AUTH_GATE_RESOLVED: "auth_gate_resolved",
15
16
  COMMAND_INVOKED: "command_invoked",
16
17
  COMMAND_COMPLETED: "command_completed",
17
18
  COMMAND_FAILED: "command_failed",
@@ -50,11 +50,11 @@
50
50
  "path": "public/.well-known/farcaster.json",
51
51
  "successMessage": "Updated manifest URLs to {{url}}",
52
52
  "set": {
53
- "miniapp.name": "{{name}}",
54
- "miniapp.homeUrl": "{{url}}",
55
- "miniapp.iconUrl": "{{url}}/icon.png",
56
- "miniapp.imageUrl": "{{url}}/og.png",
57
- "miniapp.splashImageUrl": "{{url}}/icon.png"
53
+ "frame.name": "{{name}}",
54
+ "frame.homeUrl": "{{url}}",
55
+ "frame.iconUrl": "{{url}}/icon.png",
56
+ "frame.imageUrl": "{{url}}/og.png",
57
+ "frame.splashImageUrl": "{{url}}/icon.png"
58
58
  }
59
59
  },
60
60
  {
@@ -1,17 +1,17 @@
1
1
  {
2
- "accountAssociation": {
3
- "header": "",
4
- "payload": "",
5
- "signature": ""
6
- },
7
- "miniapp": {
8
- "version": "1",
9
- "name": "jack-template",
10
- "iconUrl": "https://example.com/icon.png",
11
- "homeUrl": "https://example.com",
12
- "imageUrl": "https://example.com/og.png",
13
- "buttonTitle": "Open App",
14
- "splashImageUrl": "https://example.com/icon.png",
15
- "splashBackgroundColor": "#0a0a0a"
16
- }
2
+ "accountAssociation": {
3
+ "header": "",
4
+ "payload": "",
5
+ "signature": ""
6
+ },
7
+ "frame": {
8
+ "version": "1",
9
+ "name": "jack-template",
10
+ "iconUrl": "https://example.com/icon.png",
11
+ "homeUrl": "https://example.com",
12
+ "imageUrl": "https://example.com/og.png",
13
+ "buttonTitle": "Open App",
14
+ "splashImageUrl": "https://example.com/icon.png",
15
+ "splashBackgroundColor": "#0a0a0a"
16
+ }
17
17
  }
@@ -1,6 +1,74 @@
1
1
  import { hc } from "hono/client";
2
2
  import type { AppType } from "../worker";
3
3
 
4
- // Type-safe API client powered by Hono RPC
5
- type ApiClient = ReturnType<typeof hc<AppType>>;
6
- export const api: ApiClient = hc<AppType>("/");
4
+ // Create Hono RPC client
5
+ // Note: Type inference may show 'unknown' in IDE but works at runtime
6
+ // The explicit response types below ensure type safety for API consumers
7
+ const client = hc<AppType>("/");
8
+
9
+ // Export typed client - if AppType inference fails, these explicit types provide safety
10
+ export const api = client as {
11
+ api: {
12
+ guestbook: {
13
+ $get: () => Promise<
14
+ Response & {
15
+ json: () => Promise<{
16
+ entries: Array<{
17
+ id: number;
18
+ fid: number;
19
+ username: string;
20
+ display_name: string | null;
21
+ pfp_url: string | null;
22
+ message: string;
23
+ created_at: string;
24
+ }>;
25
+ }>;
26
+ }
27
+ >;
28
+ $post: (options: {
29
+ json: {
30
+ fid: number;
31
+ username: string;
32
+ displayName?: string;
33
+ pfpUrl?: string;
34
+ message: string;
35
+ };
36
+ }) => Promise<
37
+ Response & {
38
+ json: () => Promise<{
39
+ entry?: {
40
+ id: number;
41
+ fid: number;
42
+ username: string;
43
+ display_name: string | null;
44
+ pfp_url: string | null;
45
+ message: string;
46
+ created_at: string;
47
+ };
48
+ error?: string;
49
+ }>;
50
+ }
51
+ >;
52
+ };
53
+ ai: {
54
+ generate: {
55
+ $post: (options: {
56
+ json: { prompt: string; schema?: object };
57
+ }) => Promise<
58
+ Response & {
59
+ json: () => Promise<{
60
+ result?: string;
61
+ provider?: "openai" | "workers-ai";
62
+ error?: string;
63
+ }>;
64
+ }
65
+ >;
66
+ };
67
+ };
68
+ notifications: {
69
+ $get: (options?: {
70
+ query: { fid: string };
71
+ }) => Promise<Response & { json: () => Promise<unknown> }>;
72
+ };
73
+ };
74
+ };
@@ -1,4 +1,5 @@
1
1
  // Server-side Worker - handles API routes, keeps secrets secure
2
+ /// <reference types="@cloudflare/workers-types" />
2
3
 
3
4
  import { Hono } from "hono";
4
5
  import { cors } from "hono/cors";
@@ -53,11 +54,7 @@ function getBaseUrl(
53
54
  }
54
55
 
55
56
  // Reject localhost or IPs - embeds won't work in local dev or IP domains
56
- if (
57
- hostname === "localhost" ||
58
- hostname === "127.0.0.1" ||
59
- isIpAddress(hostname)
60
- ) {
57
+ if (hostname === "localhost" || hostname === "127.0.0.1" || isIpAddress(hostname)) {
61
58
  return null; // Signal that we can't generate valid embed URLs
62
59
  }
63
60
 
@@ -628,6 +625,49 @@ app.get("/share", (c) => {
628
625
  });
629
626
  });
630
627
 
628
+ // GET / - Inject fc:miniapp meta tags for Farcaster embeds on the main page
629
+ // Without this, sharing the app URL in a cast won't render an embed card
630
+ app.get("/", async (c) => {
631
+ // Fetch the static index.html from Vite build
632
+ const response = await c.env.ASSETS.fetch(c.req.raw);
633
+ const html = await response.text();
634
+
635
+ const baseUrl = getBaseUrl(c.env, c);
636
+
637
+ // Local dev - serve without meta tags (they require https URLs)
638
+ if (!baseUrl) {
639
+ return c.html(html);
640
+ }
641
+
642
+ // Build embed JSON (same structure as /share route)
643
+ const embedJson = JSON.stringify({
644
+ version: "1",
645
+ imageUrl: `${baseUrl}/og.png`,
646
+ button: {
647
+ title: "Open App",
648
+ action: {
649
+ type: "launch_miniapp",
650
+ name: "jack-template",
651
+ url: baseUrl,
652
+ splashImageUrl: `${baseUrl}/icon.png`,
653
+ splashBackgroundColor: "#0a0a0a",
654
+ },
655
+ },
656
+ });
657
+
658
+ // Meta tags to inject
659
+ const metaTags = `
660
+ <meta property="og:title" content="jack-template" />
661
+ <meta property="og:image" content="${baseUrl}/og.png" />
662
+ <meta name="fc:miniapp" content='${embedJson}' />
663
+ <meta name="fc:frame" content='${embedJson}' />
664
+ `;
665
+
666
+ // Inject before </head>
667
+ const injectedHtml = html.replace("</head>", `${metaTags}</head>`);
668
+ return c.html(injectedHtml);
669
+ });
670
+
631
671
  // Serve React app for all other routes
632
672
  app.get("*", (c) => c.env.ASSETS.fetch(c.req.raw));
633
673