@helloleo/plugins 0.2.15 → 0.2.16

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
@@ -24955,8 +24955,9 @@ var scaffold = tool({
24955
24955
  const typeNotes = isStart ? [
24956
24956
  "- This is a TanStack Start project. The server entry is src/server.ts. There is no index.html or client entrypoint.",
24957
24957
  "- For JSON/CRUD APIs, add server routes under src/routes/api/. Read src/routes/api/health.ts first, add routes as needed.",
24958
- "- The database schema lives in src/db/schema.ts and is the single source of truth. Migration files under drizzle/ are generated and applied automatically. Never create, edit or delete them. Prefer adding new columns/tables over renaming existing ones.",
24959
- "- Persistence goes through @helloleo/runtime exclusively: database via #/db (see src/db/index.ts), key-value store via #/lib/kv (see src/lib/kv.ts), file storage + presigned browser uploads via #/lib/storage (see src/lib/storage.ts), env/secrets via env from @helloleo/runtime. Read those files before server-side data work. Never install another DB/storage client, never import from cloudflare:workers, all of it is server-side only."
24958
+ "- The database schema lives in src/db/schema.ts and is the single source of truth. Migration files under drizzle/ are generated and applied automatically. Never create, edit or delete them.",
24959
+ "- Never rename existing tables or columns in schema.ts. Renames cannot be auto-migrated: no migration file is generated, the database keeps the old name, and every query against the new name fails at runtime with a 500. To reshape data, add a new column or table, write to it, and migrate old values in app code (e.g. fall back to the old column on read).",
24960
+ "- Persistence goes through @helloleo/runtime exclusively: database via #/db (see src/db/index.ts), key-value store via #/lib/kv (see src/lib/kv.ts), file storage via #/lib/storage (see src/lib/storage.ts -- uploads/downloads flow through your API routes; presigned URLs are NOT available), env/secrets via env from @helloleo/runtime. Read those files before server-side data work. Never install another DB/storage client, never import from cloudflare:workers, all of it is server-side only."
24960
24961
  ] : [
24961
24962
  "- This is a TanStack Router SPA. The client entry is index.html -> src/main.tsx. There is no server: no API routes, no server functions, no database.",
24962
24963
  "- Fetch data from external APIs only. If the app needs its own persistence or server-side code, it should have been scaffolded as tanstack-start."
@@ -25052,6 +25053,17 @@ function buildAuth() {
25052
25053
  emailAndPassword: {
25053
25054
  enabled: ${hasPassword},
25054
25055
  },${socialProvidersBlock}
25056
+ // The preview runs inside an iframe on another site, so the session
25057
+ // cookie lives in a third-party context: it MUST be SameSite=None +
25058
+ // Secure + Partitioned (CHIPS) or Chrome/Safari silently drop it and
25059
+ // login never sticks.
25060
+ advanced: {
25061
+ defaultCookieAttributes: {
25062
+ sameSite: 'none',
25063
+ secure: true,
25064
+ partitioned: true,
25065
+ },
25066
+ },
25055
25067
  plugins: [tanstackStartCookies()],
25056
25068
  })
25057
25069
  }
@@ -1,20 +1,34 @@
1
+ /* oxlint-disable no-unused-vars */
2
+ // ^ keeps the drizzle imports below from being stripped while unused.
3
+ // Remove this disable once your own tables use them.
1
4
  // Single source of truth for the database schema. Define tables here — the
2
5
  // SQL migration files under drizzle/ are generated and applied automatically
3
6
  // (dev on server start, production on publish). Never hand-write SQL or touch
4
7
  // drizzle/. Prefer ADDING columns/tables over renaming or deleting existing
5
8
  // ones: renames cannot be migrated automatically.
6
- //
7
- // Example:
8
- //
9
- // import { sql } from 'drizzle-orm'
10
- // import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
11
- //
12
- // export const notes = sqliteTable('notes', {
13
- // id: integer('id').primaryKey({ autoIncrement: true }),
14
- // title: text('title').notNull(),
15
- // createdAt: integer('created_at')
16
- // .notNull()
17
- // .default(sql`(unixepoch())`),
18
- // })
19
- //
20
- // export type Note = typeof notes.$inferSelect
9
+
10
+ /**
11
+ * Important note (do not remove):
12
+ *
13
+ * Never rename existing tables or columns in schema.ts. Renames cannot be
14
+ * auto-migrated: no migration file is generated, the database keeps the old
15
+ * name, and every query against the new name fails at runtime with a 500.
16
+ * To reshape data, add a new column or table, write to it, and migrate old
17
+ * values in app code (e.g. fall back to the old column on read).
18
+ */
19
+
20
+
21
+ // Example (change before deploying!) :
22
+
23
+ import { sql } from 'drizzle-orm'
24
+ import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
25
+
26
+ export const notes = sqliteTable('notes', {
27
+ id: integer('id').primaryKey({ autoIncrement: true }),
28
+ title: text('title').notNull(),
29
+ createdAt: integer('created_at')
30
+ .notNull()
31
+ .default(sql`(unixepoch())`),
32
+ })
33
+
34
+ export type Note = typeof notes.$inferSelect
@@ -15,30 +15,31 @@ import { storage } from '@helloleo/runtime'
15
15
  *
16
16
  * Rules:
17
17
  * - Server-side only (route handlers, loaders, server functions).
18
- * - Browser uploads/downloads go through PRESIGNED URLS (below) — never
19
- * stream file bytes through your own API route when a presigned URL works:
20
- * the browser talks to storage directly.
18
+ * - Files flow THROUGH YOUR API ROUTES: upload = POST route reads the body
19
+ * and `storage.put`s it; download = GET route streams `obj.body` back.
20
+ * Do NOT use presignGet/presignPut — presigned URLs are not available.
21
21
  * - Key layout is up to the app — namespace with prefixes ('avatars/',
22
- * 'exports/').
23
- */
24
-
25
- /**
26
- * Presign an upload: the server hands the browser a short-lived URL it can
27
- * `fetch(url, { method: 'PUT', body: file })` to directly. Pair with a DB row
28
- * that records the key.
22
+ * 'exports/'). Store the key in a database row to reference the file.
23
+ *
24
+ * Upload route example (src/routes/api/images/upload.ts):
25
+ *
26
+ * POST: async ({ request }) => {
27
+ * const form = await request.formData()
28
+ * const file = form.get('file') as File
29
+ * const key = `images/${crypto.randomUUID()}-${file.name}`
30
+ * await storage.put(key, file.stream(), { contentType: file.type })
31
+ * return Response.json({ key }, { status: 201 })
32
+ * }
33
+ *
34
+ * Download/serve route example (src/routes/api/images/$key.ts):
35
+ *
36
+ * GET: async ({ params }) => {
37
+ * const obj = await storage.get(`images/${params.key}`)
38
+ * if (!obj) return new Response('Not found', { status: 404 })
39
+ * return new Response(obj.body, {
40
+ * headers: { 'content-type': obj.contentType ?? 'application/octet-stream' },
41
+ * })
42
+ * }
29
43
  */
30
- export function getUploadUrl(
31
- key: string,
32
- opts?: { ttlSeconds?: number; contentType?: string },
33
- ): Promise<string> {
34
- return storage.presignPut(key, opts?.ttlSeconds ?? 600, {
35
- contentType: opts?.contentType,
36
- })
37
- }
38
-
39
- /** Presign a download — short-lived direct GET URL for the browser. */
40
- export function getDownloadUrl(key: string, ttlSeconds = 600): Promise<string> {
41
- return storage.presignGet(key, ttlSeconds)
42
- }
43
44
 
44
45
  export { storage }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helloleo/plugins",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "description": "OpenCode plugins for HelloLeo",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -1,20 +1,34 @@
1
+ /* oxlint-disable no-unused-vars */
2
+ // ^ keeps the drizzle imports below from being stripped while unused.
3
+ // Remove this disable once your own tables use them.
1
4
  // Single source of truth for the database schema. Define tables here — the
2
5
  // SQL migration files under drizzle/ are generated and applied automatically
3
6
  // (dev on server start, production on publish). Never hand-write SQL or touch
4
7
  // drizzle/. Prefer ADDING columns/tables over renaming or deleting existing
5
8
  // ones: renames cannot be migrated automatically.
6
- //
7
- // Example:
8
- //
9
- // import { sql } from 'drizzle-orm'
10
- // import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
11
- //
12
- // export const notes = sqliteTable('notes', {
13
- // id: integer('id').primaryKey({ autoIncrement: true }),
14
- // title: text('title').notNull(),
15
- // createdAt: integer('created_at')
16
- // .notNull()
17
- // .default(sql`(unixepoch())`),
18
- // })
19
- //
20
- // export type Note = typeof notes.$inferSelect
9
+
10
+ /**
11
+ * Important note (do not remove):
12
+ *
13
+ * Never rename existing tables or columns in schema.ts. Renames cannot be
14
+ * auto-migrated: no migration file is generated, the database keeps the old
15
+ * name, and every query against the new name fails at runtime with a 500.
16
+ * To reshape data, add a new column or table, write to it, and migrate old
17
+ * values in app code (e.g. fall back to the old column on read).
18
+ */
19
+
20
+
21
+ // Example (change before deploying!) :
22
+
23
+ import { sql } from 'drizzle-orm'
24
+ import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
25
+
26
+ export const notes = sqliteTable('notes', {
27
+ id: integer('id').primaryKey({ autoIncrement: true }),
28
+ title: text('title').notNull(),
29
+ createdAt: integer('created_at')
30
+ .notNull()
31
+ .default(sql`(unixepoch())`),
32
+ })
33
+
34
+ export type Note = typeof notes.$inferSelect
@@ -15,30 +15,31 @@ import { storage } from '@helloleo/runtime'
15
15
  *
16
16
  * Rules:
17
17
  * - Server-side only (route handlers, loaders, server functions).
18
- * - Browser uploads/downloads go through PRESIGNED URLS (below) — never
19
- * stream file bytes through your own API route when a presigned URL works:
20
- * the browser talks to storage directly.
18
+ * - Files flow THROUGH YOUR API ROUTES: upload = POST route reads the body
19
+ * and `storage.put`s it; download = GET route streams `obj.body` back.
20
+ * Do NOT use presignGet/presignPut — presigned URLs are not available.
21
21
  * - Key layout is up to the app — namespace with prefixes ('avatars/',
22
- * 'exports/').
23
- */
24
-
25
- /**
26
- * Presign an upload: the server hands the browser a short-lived URL it can
27
- * `fetch(url, { method: 'PUT', body: file })` to directly. Pair with a DB row
28
- * that records the key.
22
+ * 'exports/'). Store the key in a database row to reference the file.
23
+ *
24
+ * Upload route example (src/routes/api/images/upload.ts):
25
+ *
26
+ * POST: async ({ request }) => {
27
+ * const form = await request.formData()
28
+ * const file = form.get('file') as File
29
+ * const key = `images/${crypto.randomUUID()}-${file.name}`
30
+ * await storage.put(key, file.stream(), { contentType: file.type })
31
+ * return Response.json({ key }, { status: 201 })
32
+ * }
33
+ *
34
+ * Download/serve route example (src/routes/api/images/$key.ts):
35
+ *
36
+ * GET: async ({ params }) => {
37
+ * const obj = await storage.get(`images/${params.key}`)
38
+ * if (!obj) return new Response('Not found', { status: 404 })
39
+ * return new Response(obj.body, {
40
+ * headers: { 'content-type': obj.contentType ?? 'application/octet-stream' },
41
+ * })
42
+ * }
29
43
  */
30
- export function getUploadUrl(
31
- key: string,
32
- opts?: { ttlSeconds?: number; contentType?: string },
33
- ): Promise<string> {
34
- return storage.presignPut(key, opts?.ttlSeconds ?? 600, {
35
- contentType: opts?.contentType,
36
- })
37
- }
38
-
39
- /** Presign a download — short-lived direct GET URL for the browser. */
40
- export function getDownloadUrl(key: string, ttlSeconds = 600): Promise<string> {
41
- return storage.presignGet(key, ttlSeconds)
42
- }
43
44
 
44
45
  export { storage }
@@ -152,8 +152,9 @@ export const scaffold = tool({
152
152
  ? [
153
153
  "- This is a TanStack Start project. The server entry is src/server.ts. There is no index.html or client entrypoint.",
154
154
  "- For JSON/CRUD APIs, add server routes under src/routes/api/. Read src/routes/api/health.ts first, add routes as needed.",
155
- "- The database schema lives in src/db/schema.ts and is the single source of truth. Migration files under drizzle/ are generated and applied automatically. Never create, edit or delete them. Prefer adding new columns/tables over renaming existing ones.",
156
- "- Persistence goes through @helloleo/runtime exclusively: database via #/db (see src/db/index.ts), key-value store via #/lib/kv (see src/lib/kv.ts), file storage + presigned browser uploads via #/lib/storage (see src/lib/storage.ts), env/secrets via env from @helloleo/runtime. Read those files before server-side data work. Never install another DB/storage client, never import from cloudflare:workers, all of it is server-side only.",
155
+ "- The database schema lives in src/db/schema.ts and is the single source of truth. Migration files under drizzle/ are generated and applied automatically. Never create, edit or delete them.",
156
+ "- Never rename existing tables or columns in schema.ts. Renames cannot be auto-migrated: no migration file is generated, the database keeps the old name, and every query against the new name fails at runtime with a 500. To reshape data, add a new column or table, write to it, and migrate old values in app code (e.g. fall back to the old column on read).",
157
+ "- Persistence goes through @helloleo/runtime exclusively: database via #/db (see src/db/index.ts), key-value store via #/lib/kv (see src/lib/kv.ts), file storage via #/lib/storage (see src/lib/storage.ts -- uploads/downloads flow through your API routes; presigned URLs are NOT available), env/secrets via env from @helloleo/runtime. Read those files before server-side data work. Never install another DB/storage client, never import from cloudflare:workers, all of it is server-side only.",
157
158
  ]
158
159
  : [
159
160
  "- This is a TanStack Router SPA. The client entry is index.html -> src/main.tsx. There is no server: no API routes, no server functions, no database.",
@@ -78,6 +78,17 @@ function buildAuth() {
78
78
  emailAndPassword: {
79
79
  enabled: ${hasPassword},
80
80
  },${socialProvidersBlock}
81
+ // The preview runs inside an iframe on another site, so the session
82
+ // cookie lives in a third-party context: it MUST be SameSite=None +
83
+ // Secure + Partitioned (CHIPS) or Chrome/Safari silently drop it and
84
+ // login never sticks.
85
+ advanced: {
86
+ defaultCookieAttributes: {
87
+ sameSite: 'none',
88
+ secure: true,
89
+ partitioned: true,
90
+ },
91
+ },
81
92
  plugins: [tanstackStartCookies()],
82
93
  })
83
94
  }