@helloleo/plugins 0.2.0-beta.0 → 0.2.0-beta.1

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/dist/index.js CHANGED
@@ -24918,6 +24918,7 @@ var scaffold = tool({
24918
24918
  "Notes:",
24919
24919
  "- This is a TanStack Start project. The server entry is src/server.ts. There is no index.html or client entrypoint.",
24920
24920
  "- Add routes as files in src/routes/. Do not default export route components.",
24921
+ "- For JSON/CRUD APIs, add server routes under src/routes/api/. Read src/routes/api/health.ts first, add routes as needed.",
24921
24922
  "- shadcn/ui components are already in src/components/ui.",
24922
24923
  "- Design system: edit the tokens in src/styles.css (light and dark blocks).",
24923
24924
  "- The database schema lives in src/db/schema.ts. Migrations run automatically.",
@@ -25004,17 +25005,20 @@ export function signInWithNetSuite(returnTo: string = window.location.href) {
25004
25005
  // refuses to render -- looks like "nothing happens" to the user. Navigate
25005
25006
  // the top frame instead so the OAuth flow runs at the top level and the
25006
25007
  // callback redirect lands on the same top frame, which then reads the
25007
- // #nssid= fragment. Fallback to same-frame navigation if the top window
25008
- // is cross-origin and can't be reassigned.
25008
+ // #nssid= fragment. Use \`location.href =\` (NOT \`location.assign()\`):
25009
+ // reading the \`.assign\` method off a cross-origin \`window.top.location\`
25010
+ // throws a SecurityError, which would drop us into the same-frame fallback
25011
+ // and load NetSuite inside the iframe (X-Frame-Options: DENY -> "refused to
25012
+ // connect"). Assigning \`.href\` is a navigation, allowed cross-origin.
25009
25013
  try {
25010
25014
  if (window.top && window.top !== window) {
25011
- window.top.location.assign(url.toString());
25015
+ window.top.location.href = url.toString();
25012
25016
  return;
25013
25017
  }
25014
25018
  } catch {
25015
25019
  /* top window not accessible \u2014 fall through to same-frame navigation */
25016
25020
  }
25017
- window.location.assign(url.toString());
25021
+ window.location.href = url.toString();
25018
25022
  }
25019
25023
 
25020
25024
  export interface NetSuiteSession {
@@ -0,0 +1,81 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+ import { db } from '#/db'
3
+ import { entries } from '#/db/schema'
4
+
5
+ /**
6
+ * Server route example: GET /api/health. Use this file as the base for
7
+ * building JSON APIs (CRUD endpoints, webhooks) with TanStack Start
8
+ * server routes:
9
+ * https://tanstack.com/start/latest/docs/framework/react/guide/server-routes
10
+ *
11
+ * How server routes work:
12
+ * - Files under src/routes/ can export server handlers. The URL matches
13
+ * the file path: src/routes/api/health.ts serves /api/health.
14
+ * - Add one handler per HTTP method under server.handlers (GET, POST,
15
+ * PUT, PATCH, DELETE). A handler receives ({ request, params }) and
16
+ * returns a Response, usually Response.json().
17
+ * - Dynamic segments use $: src/routes/api/todos/$id.ts serves
18
+ * /api/todos/:id and the handler reads params.id.
19
+ * - Read the request body with await request.json() and validate it
20
+ * before use. Return proper status codes (201 created, 404 not found).
21
+ * - Query the database with `import { db } from '#/db'` INSIDE the
22
+ * handler, never at module scope (the binding only exists per request).
23
+ */
24
+ export const Route = createFileRoute('/api/health')({
25
+ server: {
26
+ handlers: {
27
+ GET: async () => {
28
+ const startedAt = Date.now()
29
+
30
+ const server = {
31
+ status: 'ok' as const,
32
+ uptimeSeconds: Math.round(
33
+ typeof process !== 'undefined' &&
34
+ typeof process.uptime === 'function'
35
+ ? process.uptime()
36
+ : 0,
37
+ ),
38
+ timestamp: new Date().toISOString(),
39
+ runtime: 'cloudflare-workers',
40
+ }
41
+
42
+ // Database health: lightweight query against a known table
43
+ let database: {
44
+ status: 'ok' | 'error'
45
+ latencyMs: number
46
+ error: string | null
47
+ }
48
+ const dbStart = Date.now()
49
+ try {
50
+ await db.select({ id: entries.id }).from(entries).limit(1)
51
+ database = {
52
+ status: 'ok',
53
+ latencyMs: Date.now() - dbStart,
54
+ error: null,
55
+ }
56
+ } catch (err) {
57
+ database = {
58
+ status: 'error',
59
+ latencyMs: Date.now() - dbStart,
60
+ error: err instanceof Error ? err.message : String(err),
61
+ }
62
+ }
63
+
64
+ const overall =
65
+ server.status === 'ok' && database.status === 'ok'
66
+ ? 'ok'
67
+ : 'degraded'
68
+
69
+ return Response.json(
70
+ {
71
+ status: overall,
72
+ server,
73
+ database,
74
+ checkedInMs: Date.now() - startedAt,
75
+ },
76
+ { status: overall === 'ok' ? 200 : 503 },
77
+ )
78
+ },
79
+ },
80
+ },
81
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helloleo/plugins",
3
- "version": "0.2.0-beta.0",
3
+ "version": "0.2.0-beta.1",
4
4
  "description": "OpenCode plugins for HelloLeo",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -0,0 +1,81 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+ import { db } from '#/db'
3
+ import { entries } from '#/db/schema'
4
+
5
+ /**
6
+ * Server route example: GET /api/health. Use this file as the base for
7
+ * building JSON APIs (CRUD endpoints, webhooks) with TanStack Start
8
+ * server routes:
9
+ * https://tanstack.com/start/latest/docs/framework/react/guide/server-routes
10
+ *
11
+ * How server routes work:
12
+ * - Files under src/routes/ can export server handlers. The URL matches
13
+ * the file path: src/routes/api/health.ts serves /api/health.
14
+ * - Add one handler per HTTP method under server.handlers (GET, POST,
15
+ * PUT, PATCH, DELETE). A handler receives ({ request, params }) and
16
+ * returns a Response, usually Response.json().
17
+ * - Dynamic segments use $: src/routes/api/todos/$id.ts serves
18
+ * /api/todos/:id and the handler reads params.id.
19
+ * - Read the request body with await request.json() and validate it
20
+ * before use. Return proper status codes (201 created, 404 not found).
21
+ * - Query the database with `import { db } from '#/db'` INSIDE the
22
+ * handler, never at module scope (the binding only exists per request).
23
+ */
24
+ export const Route = createFileRoute('/api/health')({
25
+ server: {
26
+ handlers: {
27
+ GET: async () => {
28
+ const startedAt = Date.now()
29
+
30
+ const server = {
31
+ status: 'ok' as const,
32
+ uptimeSeconds: Math.round(
33
+ typeof process !== 'undefined' &&
34
+ typeof process.uptime === 'function'
35
+ ? process.uptime()
36
+ : 0,
37
+ ),
38
+ timestamp: new Date().toISOString(),
39
+ runtime: 'cloudflare-workers',
40
+ }
41
+
42
+ // Database health: lightweight query against a known table
43
+ let database: {
44
+ status: 'ok' | 'error'
45
+ latencyMs: number
46
+ error: string | null
47
+ }
48
+ const dbStart = Date.now()
49
+ try {
50
+ await db.select({ id: entries.id }).from(entries).limit(1)
51
+ database = {
52
+ status: 'ok',
53
+ latencyMs: Date.now() - dbStart,
54
+ error: null,
55
+ }
56
+ } catch (err) {
57
+ database = {
58
+ status: 'error',
59
+ latencyMs: Date.now() - dbStart,
60
+ error: err instanceof Error ? err.message : String(err),
61
+ }
62
+ }
63
+
64
+ const overall =
65
+ server.status === 'ok' && database.status === 'ok'
66
+ ? 'ok'
67
+ : 'degraded'
68
+
69
+ return Response.json(
70
+ {
71
+ status: overall,
72
+ server,
73
+ database,
74
+ checkedInMs: Date.now() - startedAt,
75
+ },
76
+ { status: overall === 'ok' ? 200 : 503 },
77
+ )
78
+ },
79
+ },
80
+ },
81
+ })
@@ -88,6 +88,7 @@ export const scaffold = tool({
88
88
  "Notes:",
89
89
  "- This is a TanStack Start project. The server entry is src/server.ts. There is no index.html or client entrypoint.",
90
90
  "- Add routes as files in src/routes/. Do not default export route components.",
91
+ "- For JSON/CRUD APIs, add server routes under src/routes/api/. Read src/routes/api/health.ts first, add routes as needed.",
91
92
  "- shadcn/ui components are already in src/components/ui.",
92
93
  "- Design system: edit the tokens in src/styles.css (light and dark blocks).",
93
94
  "- The database schema lives in src/db/schema.ts. Migrations run automatically.",
@@ -82,17 +82,20 @@ export function signInWithNetSuite(returnTo: string = window.location.href) {
82
82
  // refuses to render -- looks like "nothing happens" to the user. Navigate
83
83
  // the top frame instead so the OAuth flow runs at the top level and the
84
84
  // callback redirect lands on the same top frame, which then reads the
85
- // #nssid= fragment. Fallback to same-frame navigation if the top window
86
- // is cross-origin and can't be reassigned.
85
+ // #nssid= fragment. Use \`location.href =\` (NOT \`location.assign()\`):
86
+ // reading the \`.assign\` method off a cross-origin \`window.top.location\`
87
+ // throws a SecurityError, which would drop us into the same-frame fallback
88
+ // and load NetSuite inside the iframe (X-Frame-Options: DENY -> "refused to
89
+ // connect"). Assigning \`.href\` is a navigation, allowed cross-origin.
87
90
  try {
88
91
  if (window.top && window.top !== window) {
89
- window.top.location.assign(url.toString());
92
+ window.top.location.href = url.toString();
90
93
  return;
91
94
  }
92
95
  } catch {
93
96
  /* top window not accessible — fall through to same-frame navigation */
94
97
  }
95
- window.location.assign(url.toString());
98
+ window.location.href = url.toString();
96
99
  }
97
100
 
98
101
  export interface NetSuiteSession {
@@ -1,66 +0,0 @@
1
- import { createFileRoute } from "@tanstack/react-router";
2
- import { supabaseAdmin } from "@/integrations/supabase/client.server";
3
-
4
- export const Route = createFileRoute("/api/health")({
5
- server: {
6
- handlers: {
7
- GET: async () => {
8
- const startedAt = Date.now();
9
-
10
- // Server health
11
- const server = {
12
- status: "ok" as const,
13
- uptimeSeconds: Math.round(
14
- typeof process !== "undefined" &&
15
- typeof process.uptime === "function"
16
- ? process.uptime()
17
- : 0,
18
- ),
19
- timestamp: new Date().toISOString(),
20
- runtime: "cloudflare-workers",
21
- };
22
-
23
- // Database health — lightweight query against a known table
24
- let database: {
25
- status: "ok" | "error";
26
- latencyMs: number;
27
- error: string | null;
28
- };
29
- const dbStart = Date.now();
30
- try {
31
- const { error } = await supabaseAdmin
32
- .from("notes")
33
- .select("id", { count: "exact", head: true })
34
- .limit(1);
35
- if (error) throw error;
36
- database = {
37
- status: "ok",
38
- latencyMs: Date.now() - dbStart,
39
- error: null,
40
- };
41
- } catch (err) {
42
- database = {
43
- status: "error",
44
- latencyMs: Date.now() - dbStart,
45
- error: err instanceof Error ? err.message : String(err),
46
- };
47
- }
48
-
49
- const overall =
50
- server.status === "ok" && database.status === "ok"
51
- ? "ok"
52
- : "degraded";
53
-
54
- return Response.json(
55
- {
56
- status: overall,
57
- server,
58
- database,
59
- checkedInMs: Date.now() - startedAt,
60
- },
61
- { status: overall === "ok" ? 200 : 503 },
62
- );
63
- },
64
- },
65
- },
66
- });
@@ -1,66 +0,0 @@
1
- import { createFileRoute } from "@tanstack/react-router";
2
- import { supabaseAdmin } from "@/integrations/supabase/client.server";
3
-
4
- export const Route = createFileRoute("/api/health")({
5
- server: {
6
- handlers: {
7
- GET: async () => {
8
- const startedAt = Date.now();
9
-
10
- // Server health
11
- const server = {
12
- status: "ok" as const,
13
- uptimeSeconds: Math.round(
14
- typeof process !== "undefined" &&
15
- typeof process.uptime === "function"
16
- ? process.uptime()
17
- : 0,
18
- ),
19
- timestamp: new Date().toISOString(),
20
- runtime: "cloudflare-workers",
21
- };
22
-
23
- // Database health — lightweight query against a known table
24
- let database: {
25
- status: "ok" | "error";
26
- latencyMs: number;
27
- error: string | null;
28
- };
29
- const dbStart = Date.now();
30
- try {
31
- const { error } = await supabaseAdmin
32
- .from("notes")
33
- .select("id", { count: "exact", head: true })
34
- .limit(1);
35
- if (error) throw error;
36
- database = {
37
- status: "ok",
38
- latencyMs: Date.now() - dbStart,
39
- error: null,
40
- };
41
- } catch (err) {
42
- database = {
43
- status: "error",
44
- latencyMs: Date.now() - dbStart,
45
- error: err instanceof Error ? err.message : String(err),
46
- };
47
- }
48
-
49
- const overall =
50
- server.status === "ok" && database.status === "ok"
51
- ? "ok"
52
- : "degraded";
53
-
54
- return Response.json(
55
- {
56
- status: overall,
57
- server,
58
- database,
59
- checkedInMs: Date.now() - startedAt,
60
- },
61
- { status: overall === "ok" ? 200 : 503 },
62
- );
63
- },
64
- },
65
- },
66
- });