@btst/stack 2.11.0 → 2.11.2

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.
Files changed (71) hide show
  1. package/dist/packages/stack/src/plugins/blog/api/mutations.cjs +170 -0
  2. package/dist/packages/stack/src/plugins/blog/api/mutations.mjs +166 -0
  3. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +34 -157
  4. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +40 -163
  5. package/dist/packages/stack/src/plugins/media/api/plugin.cjs +4 -1
  6. package/dist/packages/stack/src/plugins/media/api/plugin.mjs +5 -2
  7. package/dist/plugins/blog/api/index.cjs +4 -0
  8. package/dist/plugins/blog/api/index.d.cts +2 -2
  9. package/dist/plugins/blog/api/index.d.mts +2 -2
  10. package/dist/plugins/blog/api/index.d.ts +2 -2
  11. package/dist/plugins/blog/api/index.mjs +1 -0
  12. package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
  13. package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
  14. package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
  15. package/dist/plugins/blog/client/index.d.cts +2 -2
  16. package/dist/plugins/blog/client/index.d.mts +2 -2
  17. package/dist/plugins/blog/client/index.d.ts +2 -2
  18. package/dist/plugins/blog/query-keys.d.cts +2 -2
  19. package/dist/plugins/blog/query-keys.d.mts +2 -2
  20. package/dist/plugins/blog/query-keys.d.ts +2 -2
  21. package/dist/plugins/kanban/api/index.d.cts +1 -1
  22. package/dist/plugins/kanban/api/index.d.mts +1 -1
  23. package/dist/plugins/kanban/api/index.d.ts +1 -1
  24. package/dist/plugins/kanban/query-keys.d.cts +1 -1
  25. package/dist/plugins/kanban/query-keys.d.mts +1 -1
  26. package/dist/plugins/kanban/query-keys.d.ts +1 -1
  27. package/dist/{packages/stack/src/plugins → plugins}/media/api/adapters/local.cjs +7 -1
  28. package/dist/plugins/media/api/adapters/local.d.cts +30 -0
  29. package/dist/plugins/media/api/adapters/local.d.mts +30 -0
  30. package/dist/plugins/media/api/adapters/local.d.ts +30 -0
  31. package/dist/{packages/stack/src/plugins → plugins}/media/api/adapters/local.mjs +7 -1
  32. package/dist/plugins/media/api/adapters/s3.d.cts +1 -1
  33. package/dist/plugins/media/api/adapters/s3.d.mts +1 -1
  34. package/dist/plugins/media/api/adapters/s3.d.ts +1 -1
  35. package/dist/plugins/media/api/adapters/vercel-blob.d.cts +1 -1
  36. package/dist/plugins/media/api/adapters/vercel-blob.d.mts +1 -1
  37. package/dist/plugins/media/api/adapters/vercel-blob.d.ts +1 -1
  38. package/dist/plugins/media/api/index.cjs +0 -2
  39. package/dist/plugins/media/api/index.d.cts +5 -102
  40. package/dist/plugins/media/api/index.d.mts +5 -102
  41. package/dist/plugins/media/api/index.d.ts +5 -102
  42. package/dist/plugins/media/api/index.mjs +0 -1
  43. package/dist/plugins/media/query-keys.d.cts +2 -2
  44. package/dist/plugins/media/query-keys.d.mts +2 -2
  45. package/dist/plugins/media/query-keys.d.ts +2 -2
  46. package/dist/shared/{stack.Bci0-plK.d.ts → stack.C5ucdatf.d.ts} +76 -3
  47. package/dist/shared/{stack.D7HSzZdG.d.ts → stack.D0p6oNme.d.ts} +90 -7
  48. package/dist/shared/{stack.6mEHS2WH.d.mts → stack.DOZ1EXjM.d.mts} +3 -3
  49. package/dist/shared/{stack.IUeyQKrm.d.mts → stack.DWipT53I.d.cts} +90 -7
  50. package/dist/shared/{stack.AJTXI7kw.d.cts → stack.DX-tQ93o.d.cts} +3 -3
  51. package/dist/shared/{stack.C_MUwwgR.d.mts → stack.DpZoZd98.d.mts} +76 -3
  52. package/dist/shared/{stack.DjgpFWq3.d.cts → stack.E17kSK1W.d.mts} +90 -7
  53. package/dist/shared/{stack.QYn-Px94.d.ts → stack.VF6FhyZw.d.ts} +3 -3
  54. package/dist/shared/{stack.DO6vOGQG.d.cts → stack.lkebw2nj.d.cts} +1 -1
  55. package/dist/shared/{stack.DO6vOGQG.d.mts → stack.lkebw2nj.d.mts} +1 -1
  56. package/dist/shared/{stack.DO6vOGQG.d.ts → stack.lkebw2nj.d.ts} +1 -1
  57. package/dist/shared/{stack.D6zyQnMo.d.cts → stack.vVFh38aS.d.cts} +76 -3
  58. package/package.json +14 -1
  59. package/src/plugins/blog/api/index.ts +7 -0
  60. package/src/plugins/blog/api/mutations.ts +287 -0
  61. package/src/plugins/blog/api/plugin.ts +43 -184
  62. package/src/plugins/media/__tests__/storage-adapters.test.ts +11 -0
  63. package/src/plugins/media/api/adapters/local.ts +10 -1
  64. package/src/plugins/media/api/index.ts +0 -5
  65. package/src/plugins/media/api/plugin.ts +6 -0
  66. package/dist/shared/{stack.eq5eg1yt.d.cts → stack.B6S3cgwN.d.cts} +6 -6
  67. package/dist/shared/{stack.BQmuNl5p.d.ts → stack.BWp0hcm9.d.cts} +3 -3
  68. package/dist/shared/{stack.BQmuNl5p.d.cts → stack.BWp0hcm9.d.mts} +3 -3
  69. package/dist/shared/{stack.BQmuNl5p.d.mts → stack.BWp0hcm9.d.ts} +3 -3
  70. package/dist/shared/{stack.Dj04W2c3.d.mts → stack.Bzfx-_lq.d.mts} +6 -6
  71. package/dist/shared/{stack.CMbX8Q5C.d.ts → stack.j5SFLC1d.d.ts} +6 -6
@@ -1,7 +1,7 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { QueryClient } from '@tanstack/react-query';
3
3
  import { createApiClient } from '@btst/stack/plugins/client';
4
- import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BQmuNl5p.js';
4
+ import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BWp0hcm9.js';
5
5
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
6
6
  import { DBAdapter } from '@btst/db';
7
7
  import * as better_call from 'better-call';
@@ -67,6 +67,86 @@ declare function getPostBySlug(adapter: DBAdapter, slug: string): Promise<(Post
67
67
  */
68
68
  declare function getAllTags(adapter: DBAdapter): Promise<Tag[]>;
69
69
 
70
+ type TagInput = {
71
+ name: string;
72
+ } | {
73
+ id: string;
74
+ name: string;
75
+ slug: string;
76
+ };
77
+ /**
78
+ * Input for creating a new blog post.
79
+ * `slug` must already be slugified by the caller.
80
+ */
81
+ interface CreatePostInput {
82
+ title: string;
83
+ content: string;
84
+ excerpt: string;
85
+ /** Pre-slugified URL slug — use {@link slugify} before passing. */
86
+ slug: string;
87
+ image?: string;
88
+ published?: boolean;
89
+ publishedAt?: Date;
90
+ createdAt?: Date;
91
+ updatedAt?: Date;
92
+ tags?: TagInput[];
93
+ }
94
+ /**
95
+ * Input for updating an existing blog post.
96
+ * If `slug` is provided it must already be slugified by the caller.
97
+ */
98
+ interface UpdatePostInput {
99
+ title?: string;
100
+ content?: string;
101
+ excerpt?: string;
102
+ /** Pre-slugified URL slug — use {@link slugify} before passing. */
103
+ slug?: string;
104
+ image?: string;
105
+ published?: boolean;
106
+ publishedAt?: Date;
107
+ createdAt?: Date;
108
+ updatedAt?: Date;
109
+ tags?: TagInput[];
110
+ }
111
+ /**
112
+ * Create a new blog post with optional tag associations.
113
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side and SSG use.
114
+ *
115
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeCreatePost`) are NOT
116
+ * called. The caller is responsible for any access-control checks before
117
+ * invoking this function.
118
+ *
119
+ * @param adapter - The database adapter
120
+ * @param input - Post data; `slug` must be pre-slugified
121
+ */
122
+ declare function createPost(adapter: DBAdapter, input: CreatePostInput): Promise<Post>;
123
+ /**
124
+ * Update an existing blog post and reconcile its tag associations.
125
+ * Returns `null` if no post with the given `id` exists.
126
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side use.
127
+ *
128
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeUpdatePost`) are NOT
129
+ * called. The caller is responsible for any access-control checks before
130
+ * invoking this function.
131
+ *
132
+ * @param adapter - The database adapter
133
+ * @param id - The post ID to update
134
+ * @param input - Partial post data to apply; `slug` must be pre-slugified if provided
135
+ */
136
+ declare function updatePost(adapter: DBAdapter, id: string, input: UpdatePostInput): Promise<Post | null>;
137
+ /**
138
+ * Delete a blog post by ID.
139
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side use.
140
+ *
141
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeDeletePost`) are NOT
142
+ * called. The caller is responsible for any access-control checks before
143
+ * invoking this function.
144
+ *
145
+ * @param adapter - The database adapter
146
+ * @param id - The post ID to delete
147
+ */
148
+ declare function deletePost(adapter: DBAdapter, id: string): Promise<void>;
149
+
70
150
  /**
71
151
  * Route keys for the blog plugin — matches the keys returned by
72
152
  * `stackClient.router.getRoute(path).routeKey`.
@@ -244,11 +324,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
244
324
  slug: string;
245
325
  })[] | undefined;
246
326
  slug?: string | undefined;
327
+ published?: boolean | undefined;
328
+ publishedAt?: unknown;
247
329
  createdAt?: unknown;
248
330
  updatedAt?: unknown;
249
- publishedAt?: unknown;
250
331
  image?: string | undefined;
251
- published?: boolean | undefined;
252
332
  }, {
253
333
  title: string;
254
334
  content: string;
@@ -261,11 +341,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
261
341
  slug: string;
262
342
  })[] | undefined;
263
343
  slug?: string | undefined;
344
+ published?: boolean | undefined;
345
+ publishedAt?: unknown;
264
346
  createdAt?: unknown;
265
347
  updatedAt?: unknown;
266
- publishedAt?: unknown;
267
348
  image?: string | undefined;
268
- published?: boolean | undefined;
269
349
  }>;
270
350
  }, Post>;
271
351
  readonly updatePost: better_call.StrictEndpoint<"/posts/:id", {} & {
@@ -366,6 +446,9 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
366
446
  }) | null>;
367
447
  getAllTags: () => Promise<Tag[]>;
368
448
  prefetchForRoute: BlogPrefetchForRoute;
449
+ createPost: (input: CreatePostInput) => Promise<Post>;
450
+ updatePost: (id: string, input: UpdatePostInput) => Promise<Post | null>;
451
+ deletePost: (id: string) => Promise<void>;
369
452
  }>;
370
453
  type BlogApiRouter = ReturnType<ReturnType<typeof blogBackendPlugin>["routes"]>;
371
454
 
@@ -476,5 +559,5 @@ declare function createBlogQueryKeys(client: ReturnType<typeof createApiClient<B
476
559
  };
477
560
  };
478
561
 
479
- export { BLOG_QUERY_KEYS as B, NextPreviousPostsQuerySchema as N, getPostBySlug as a, getAllTags as b, createBlogQueryKeys as d, PostListQuerySchema as f, getAllPosts as g, blogBackendPlugin as j };
480
- export type { PostListParams as P, PostListResult as c, BlogRouteKey as e, BlogApiContext as h, BlogBackendHooks as i, BlogApiRouter as k };
562
+ export { BLOG_QUERY_KEYS as B, NextPreviousPostsQuerySchema as N, getPostBySlug as a, getAllTags as b, createPost as d, deletePost as e, createBlogQueryKeys as f, getAllPosts as g, PostListQuerySchema as i, blogBackendPlugin as l, updatePost as u };
563
+ export type { CreatePostInput as C, PostListParams as P, UpdatePostInput as U, PostListResult as c, BlogRouteKey as h, BlogApiContext as j, BlogBackendHooks as k, BlogApiRouter as m };
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.BQmuNl5p.mjs';
2
+ import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.BWp0hcm9.mjs';
3
3
  import { z } from 'zod';
4
4
 
5
5
  /**
@@ -135,14 +135,14 @@ declare function useCreatePost(): _tanstack_react_query.UseMutationResult<Serial
135
135
  name: string;
136
136
  slug: string;
137
137
  })[];
138
+ published: boolean;
138
139
  title: string;
139
140
  content: string;
140
141
  excerpt: string;
141
- published: boolean;
142
142
  slug?: string | undefined;
143
+ publishedAt?: Date | undefined;
143
144
  createdAt?: Date | undefined;
144
145
  updatedAt?: Date | undefined;
145
- publishedAt?: Date | undefined;
146
146
  image?: string | undefined;
147
147
  }, unknown>;
148
148
  /** Update an existing post by id */
@@ -1,7 +1,7 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { QueryClient } from '@tanstack/react-query';
3
3
  import { createApiClient } from '@btst/stack/plugins/client';
4
- import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BQmuNl5p.mjs';
4
+ import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BWp0hcm9.cjs';
5
5
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
6
6
  import { DBAdapter } from '@btst/db';
7
7
  import * as better_call from 'better-call';
@@ -67,6 +67,86 @@ declare function getPostBySlug(adapter: DBAdapter, slug: string): Promise<(Post
67
67
  */
68
68
  declare function getAllTags(adapter: DBAdapter): Promise<Tag[]>;
69
69
 
70
+ type TagInput = {
71
+ name: string;
72
+ } | {
73
+ id: string;
74
+ name: string;
75
+ slug: string;
76
+ };
77
+ /**
78
+ * Input for creating a new blog post.
79
+ * `slug` must already be slugified by the caller.
80
+ */
81
+ interface CreatePostInput {
82
+ title: string;
83
+ content: string;
84
+ excerpt: string;
85
+ /** Pre-slugified URL slug — use {@link slugify} before passing. */
86
+ slug: string;
87
+ image?: string;
88
+ published?: boolean;
89
+ publishedAt?: Date;
90
+ createdAt?: Date;
91
+ updatedAt?: Date;
92
+ tags?: TagInput[];
93
+ }
94
+ /**
95
+ * Input for updating an existing blog post.
96
+ * If `slug` is provided it must already be slugified by the caller.
97
+ */
98
+ interface UpdatePostInput {
99
+ title?: string;
100
+ content?: string;
101
+ excerpt?: string;
102
+ /** Pre-slugified URL slug — use {@link slugify} before passing. */
103
+ slug?: string;
104
+ image?: string;
105
+ published?: boolean;
106
+ publishedAt?: Date;
107
+ createdAt?: Date;
108
+ updatedAt?: Date;
109
+ tags?: TagInput[];
110
+ }
111
+ /**
112
+ * Create a new blog post with optional tag associations.
113
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side and SSG use.
114
+ *
115
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeCreatePost`) are NOT
116
+ * called. The caller is responsible for any access-control checks before
117
+ * invoking this function.
118
+ *
119
+ * @param adapter - The database adapter
120
+ * @param input - Post data; `slug` must be pre-slugified
121
+ */
122
+ declare function createPost(adapter: DBAdapter, input: CreatePostInput): Promise<Post>;
123
+ /**
124
+ * Update an existing blog post and reconcile its tag associations.
125
+ * Returns `null` if no post with the given `id` exists.
126
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side use.
127
+ *
128
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeUpdatePost`) are NOT
129
+ * called. The caller is responsible for any access-control checks before
130
+ * invoking this function.
131
+ *
132
+ * @param adapter - The database adapter
133
+ * @param id - The post ID to update
134
+ * @param input - Partial post data to apply; `slug` must be pre-slugified if provided
135
+ */
136
+ declare function updatePost(adapter: DBAdapter, id: string, input: UpdatePostInput): Promise<Post | null>;
137
+ /**
138
+ * Delete a blog post by ID.
139
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side use.
140
+ *
141
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeDeletePost`) are NOT
142
+ * called. The caller is responsible for any access-control checks before
143
+ * invoking this function.
144
+ *
145
+ * @param adapter - The database adapter
146
+ * @param id - The post ID to delete
147
+ */
148
+ declare function deletePost(adapter: DBAdapter, id: string): Promise<void>;
149
+
70
150
  /**
71
151
  * Route keys for the blog plugin — matches the keys returned by
72
152
  * `stackClient.router.getRoute(path).routeKey`.
@@ -244,11 +324,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
244
324
  slug: string;
245
325
  })[] | undefined;
246
326
  slug?: string | undefined;
327
+ published?: boolean | undefined;
328
+ publishedAt?: unknown;
247
329
  createdAt?: unknown;
248
330
  updatedAt?: unknown;
249
- publishedAt?: unknown;
250
331
  image?: string | undefined;
251
- published?: boolean | undefined;
252
332
  }, {
253
333
  title: string;
254
334
  content: string;
@@ -261,11 +341,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
261
341
  slug: string;
262
342
  })[] | undefined;
263
343
  slug?: string | undefined;
344
+ published?: boolean | undefined;
345
+ publishedAt?: unknown;
264
346
  createdAt?: unknown;
265
347
  updatedAt?: unknown;
266
- publishedAt?: unknown;
267
348
  image?: string | undefined;
268
- published?: boolean | undefined;
269
349
  }>;
270
350
  }, Post>;
271
351
  readonly updatePost: better_call.StrictEndpoint<"/posts/:id", {} & {
@@ -366,6 +446,9 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
366
446
  }) | null>;
367
447
  getAllTags: () => Promise<Tag[]>;
368
448
  prefetchForRoute: BlogPrefetchForRoute;
449
+ createPost: (input: CreatePostInput) => Promise<Post>;
450
+ updatePost: (id: string, input: UpdatePostInput) => Promise<Post | null>;
451
+ deletePost: (id: string) => Promise<void>;
369
452
  }>;
370
453
  type BlogApiRouter = ReturnType<ReturnType<typeof blogBackendPlugin>["routes"]>;
371
454
 
@@ -476,5 +559,5 @@ declare function createBlogQueryKeys(client: ReturnType<typeof createApiClient<B
476
559
  };
477
560
  };
478
561
 
479
- export { BLOG_QUERY_KEYS as B, NextPreviousPostsQuerySchema as N, getPostBySlug as a, getAllTags as b, createBlogQueryKeys as d, PostListQuerySchema as f, getAllPosts as g, blogBackendPlugin as j };
480
- export type { PostListParams as P, PostListResult as c, BlogRouteKey as e, BlogApiContext as h, BlogBackendHooks as i, BlogApiRouter as k };
562
+ export { BLOG_QUERY_KEYS as B, NextPreviousPostsQuerySchema as N, getPostBySlug as a, getAllTags as b, createPost as d, deletePost as e, createBlogQueryKeys as f, getAllPosts as g, PostListQuerySchema as i, blogBackendPlugin as l, updatePost as u };
563
+ export type { CreatePostInput as C, PostListParams as P, UpdatePostInput as U, PostListResult as c, BlogRouteKey as h, BlogApiContext as j, BlogBackendHooks as k, BlogApiRouter as m };
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.BQmuNl5p.cjs';
2
+ import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.BWp0hcm9.cjs';
3
3
  import { z } from 'zod';
4
4
 
5
5
  /**
@@ -135,14 +135,14 @@ declare function useCreatePost(): _tanstack_react_query.UseMutationResult<Serial
135
135
  name: string;
136
136
  slug: string;
137
137
  })[];
138
+ published: boolean;
138
139
  title: string;
139
140
  content: string;
140
141
  excerpt: string;
141
- published: boolean;
142
142
  slug?: string | undefined;
143
+ publishedAt?: Date | undefined;
143
144
  createdAt?: Date | undefined;
144
145
  updatedAt?: Date | undefined;
145
- publishedAt?: Date | undefined;
146
146
  image?: string | undefined;
147
147
  }, unknown>;
148
148
  /** Update an existing post by id */
@@ -1,9 +1,10 @@
1
1
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
2
- import { a as StorageAdapter, b as S3UploadToken } from './stack.DO6vOGQG.mjs';
2
+ import { S as StorageAdapter, b as S3UploadToken } from './stack.lkebw2nj.mjs';
3
3
  import { d as AssetListResult, l as listAssets, a as listFolders, A as AssetListParams } from './stack.C7u9lq9T.mjs';
4
4
  import * as better_call from 'better-call';
5
5
  import { z } from 'zod';
6
6
  import { A as Asset, F as Folder } from './stack.BMlLOMED.mjs';
7
+ import { DBAdapter } from '@btst/db';
7
8
 
8
9
  declare const AssetListQuerySchema: z.ZodObject<{
9
10
  folderId: z.ZodOptional<z.ZodString>;
@@ -21,6 +22,75 @@ declare const createFolderSchema: z.ZodObject<{
21
22
  parentId: z.ZodOptional<z.ZodString>;
22
23
  }, z.core.$strip>;
23
24
 
25
+ /**
26
+ * Input for creating a new asset record.
27
+ */
28
+ interface CreateAssetInput {
29
+ filename: string;
30
+ originalName: string;
31
+ mimeType: string;
32
+ size: number;
33
+ url: string;
34
+ folderId?: string;
35
+ alt?: string;
36
+ tenantId?: string;
37
+ }
38
+ /**
39
+ * Input for updating an existing asset record.
40
+ */
41
+ interface UpdateAssetInput {
42
+ alt?: string;
43
+ folderId?: string | null;
44
+ }
45
+ /**
46
+ * Input for creating a new folder.
47
+ */
48
+ interface CreateFolderInput {
49
+ name: string;
50
+ parentId?: string;
51
+ tenantId?: string;
52
+ }
53
+ /**
54
+ * Create an asset record in the database.
55
+ * Pure DB function — no authorization hooks, no HTTP context.
56
+ *
57
+ * @remarks **Security:** No authorization hooks (e.g. `onBeforeUpload`) are called.
58
+ * The caller is responsible for any access-control checks before invoking this function.
59
+ */
60
+ declare function createAsset(adapter: DBAdapter, input: CreateAssetInput): Promise<Asset>;
61
+ /**
62
+ * Update an asset's `alt` text or `folderId`.
63
+ * Pure DB function — no authorization hooks, no HTTP context.
64
+ *
65
+ * @remarks **Security:** No authorization hooks are called.
66
+ */
67
+ declare function updateAsset(adapter: DBAdapter, id: string, input: UpdateAssetInput): Promise<Asset | null>;
68
+ /**
69
+ * Delete an asset record from the database by its ID.
70
+ * Does NOT delete the underlying file — the caller must do that via the storage adapter.
71
+ * Pure DB function — no authorization hooks, no HTTP context.
72
+ *
73
+ * @remarks **Security:** No authorization hooks are called.
74
+ */
75
+ declare function deleteAsset(adapter: DBAdapter, id: string): Promise<void>;
76
+ /**
77
+ * Create a folder record in the database.
78
+ * Pure DB function — no authorization hooks, no HTTP context.
79
+ *
80
+ * @remarks **Security:** No authorization hooks are called.
81
+ */
82
+ declare function createFolder(adapter: DBAdapter, input: CreateFolderInput): Promise<Folder>;
83
+ /**
84
+ * Delete a folder record from the database by its ID.
85
+ * Child folders are cascade-deleted automatically. Throws if the folder or
86
+ * any of its descendants contain assets (which have associated storage files
87
+ * that must be deleted via the storage adapter first).
88
+ * Pure DB function — no authorization hooks, no HTTP context.
89
+ *
90
+ * @remarks **Security:** No authorization hooks are called.
91
+ */
92
+ declare function deleteFolder(adapter: DBAdapter, id: string): Promise<void>;
93
+
24
94
  /**
25
95
  * Context passed to media API hooks.
26
96
  */
@@ -270,9 +340,12 @@ declare const mediaBackendPlugin: (config: MediaBackendConfig) => _btst_stack_pl
270
340
  }, {
271
341
  listAssets: (params?: Parameters<typeof listAssets>[1]) => Promise<AssetListResult>;
272
342
  getAssetById: (id: string) => Promise<Asset | null>;
343
+ createAsset: (input: Parameters<typeof createAsset>[1]) => Promise<Asset>;
344
+ updateAsset: (id: string, input: Parameters<typeof updateAsset>[2]) => Promise<Asset | null>;
273
345
  listFolders: (params?: Parameters<typeof listFolders>[1]) => Promise<Folder[]>;
274
346
  getFolderById: (id: string) => Promise<Folder | null>;
275
347
  getFolderByName: (name: string, parentId?: string | null, tenantId?: string) => Promise<Folder | null>;
348
+ createFolder: (input: Parameters<typeof createFolder>[1]) => Promise<Folder>;
276
349
  }>;
277
350
  type MediaApiRouter = ReturnType<ReturnType<typeof mediaBackendPlugin>["routes"]>;
278
351
 
@@ -300,5 +373,5 @@ declare const MEDIA_QUERY_KEYS: {
300
373
  foldersList: (parentId?: string | null) => readonly ["media", "folders", "list", string];
301
374
  };
302
375
 
303
- export { MEDIA_QUERY_KEYS as a, assetListDiscriminator as b, mediaBackendPlugin as m };
304
- export type { AssetListDiscriminator as A, MediaApiRouter as M, MediaApiContext as c, MediaBackendHooks as d, MediaBackendConfig as e };
376
+ export { MEDIA_QUERY_KEYS as M, createFolder as a, deleteFolder as b, createAsset as c, deleteAsset as d, assetListDiscriminator as f, mediaBackendPlugin as m, updateAsset as u };
377
+ export type { AssetListDiscriminator as A, CreateAssetInput as C, UpdateAssetInput as U, CreateFolderInput as e, MediaApiContext as g, MediaBackendHooks as h, MediaBackendConfig as i, MediaApiRouter as j };
@@ -1,7 +1,7 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { QueryClient } from '@tanstack/react-query';
3
3
  import { createApiClient } from '@btst/stack/plugins/client';
4
- import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BQmuNl5p.cjs';
4
+ import { P as Post, T as Tag, c as createPostSchema, u as updatePostSchema, S as SerializedPost, a as SerializedTag } from './stack.BWp0hcm9.mjs';
5
5
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
6
6
  import { DBAdapter } from '@btst/db';
7
7
  import * as better_call from 'better-call';
@@ -67,6 +67,86 @@ declare function getPostBySlug(adapter: DBAdapter, slug: string): Promise<(Post
67
67
  */
68
68
  declare function getAllTags(adapter: DBAdapter): Promise<Tag[]>;
69
69
 
70
+ type TagInput = {
71
+ name: string;
72
+ } | {
73
+ id: string;
74
+ name: string;
75
+ slug: string;
76
+ };
77
+ /**
78
+ * Input for creating a new blog post.
79
+ * `slug` must already be slugified by the caller.
80
+ */
81
+ interface CreatePostInput {
82
+ title: string;
83
+ content: string;
84
+ excerpt: string;
85
+ /** Pre-slugified URL slug — use {@link slugify} before passing. */
86
+ slug: string;
87
+ image?: string;
88
+ published?: boolean;
89
+ publishedAt?: Date;
90
+ createdAt?: Date;
91
+ updatedAt?: Date;
92
+ tags?: TagInput[];
93
+ }
94
+ /**
95
+ * Input for updating an existing blog post.
96
+ * If `slug` is provided it must already be slugified by the caller.
97
+ */
98
+ interface UpdatePostInput {
99
+ title?: string;
100
+ content?: string;
101
+ excerpt?: string;
102
+ /** Pre-slugified URL slug — use {@link slugify} before passing. */
103
+ slug?: string;
104
+ image?: string;
105
+ published?: boolean;
106
+ publishedAt?: Date;
107
+ createdAt?: Date;
108
+ updatedAt?: Date;
109
+ tags?: TagInput[];
110
+ }
111
+ /**
112
+ * Create a new blog post with optional tag associations.
113
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side and SSG use.
114
+ *
115
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeCreatePost`) are NOT
116
+ * called. The caller is responsible for any access-control checks before
117
+ * invoking this function.
118
+ *
119
+ * @param adapter - The database adapter
120
+ * @param input - Post data; `slug` must be pre-slugified
121
+ */
122
+ declare function createPost(adapter: DBAdapter, input: CreatePostInput): Promise<Post>;
123
+ /**
124
+ * Update an existing blog post and reconcile its tag associations.
125
+ * Returns `null` if no post with the given `id` exists.
126
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side use.
127
+ *
128
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeUpdatePost`) are NOT
129
+ * called. The caller is responsible for any access-control checks before
130
+ * invoking this function.
131
+ *
132
+ * @param adapter - The database adapter
133
+ * @param id - The post ID to update
134
+ * @param input - Partial post data to apply; `slug` must be pre-slugified if provided
135
+ */
136
+ declare function updatePost(adapter: DBAdapter, id: string, input: UpdatePostInput): Promise<Post | null>;
137
+ /**
138
+ * Delete a blog post by ID.
139
+ * Pure DB function — no hooks, no HTTP context. Safe for server-side use.
140
+ *
141
+ * @remarks **Security:** Authorization hooks (e.g. `onBeforeDeletePost`) are NOT
142
+ * called. The caller is responsible for any access-control checks before
143
+ * invoking this function.
144
+ *
145
+ * @param adapter - The database adapter
146
+ * @param id - The post ID to delete
147
+ */
148
+ declare function deletePost(adapter: DBAdapter, id: string): Promise<void>;
149
+
70
150
  /**
71
151
  * Route keys for the blog plugin — matches the keys returned by
72
152
  * `stackClient.router.getRoute(path).routeKey`.
@@ -244,11 +324,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
244
324
  slug: string;
245
325
  })[] | undefined;
246
326
  slug?: string | undefined;
327
+ published?: boolean | undefined;
328
+ publishedAt?: unknown;
247
329
  createdAt?: unknown;
248
330
  updatedAt?: unknown;
249
- publishedAt?: unknown;
250
331
  image?: string | undefined;
251
- published?: boolean | undefined;
252
332
  }, {
253
333
  title: string;
254
334
  content: string;
@@ -261,11 +341,11 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
261
341
  slug: string;
262
342
  })[] | undefined;
263
343
  slug?: string | undefined;
344
+ published?: boolean | undefined;
345
+ publishedAt?: unknown;
264
346
  createdAt?: unknown;
265
347
  updatedAt?: unknown;
266
- publishedAt?: unknown;
267
348
  image?: string | undefined;
268
- published?: boolean | undefined;
269
349
  }>;
270
350
  }, Post>;
271
351
  readonly updatePost: better_call.StrictEndpoint<"/posts/:id", {} & {
@@ -366,6 +446,9 @@ declare const blogBackendPlugin: (hooks?: BlogBackendHooks) => _btst_stack_plugi
366
446
  }) | null>;
367
447
  getAllTags: () => Promise<Tag[]>;
368
448
  prefetchForRoute: BlogPrefetchForRoute;
449
+ createPost: (input: CreatePostInput) => Promise<Post>;
450
+ updatePost: (id: string, input: UpdatePostInput) => Promise<Post | null>;
451
+ deletePost: (id: string) => Promise<void>;
369
452
  }>;
370
453
  type BlogApiRouter = ReturnType<ReturnType<typeof blogBackendPlugin>["routes"]>;
371
454
 
@@ -476,5 +559,5 @@ declare function createBlogQueryKeys(client: ReturnType<typeof createApiClient<B
476
559
  };
477
560
  };
478
561
 
479
- export { BLOG_QUERY_KEYS as B, NextPreviousPostsQuerySchema as N, getPostBySlug as a, getAllTags as b, createBlogQueryKeys as d, PostListQuerySchema as f, getAllPosts as g, blogBackendPlugin as j };
480
- export type { PostListParams as P, PostListResult as c, BlogRouteKey as e, BlogApiContext as h, BlogBackendHooks as i, BlogApiRouter as k };
562
+ export { BLOG_QUERY_KEYS as B, NextPreviousPostsQuerySchema as N, getPostBySlug as a, getAllTags as b, createPost as d, deletePost as e, createBlogQueryKeys as f, getAllPosts as g, PostListQuerySchema as i, blogBackendPlugin as l, updatePost as u };
563
+ export type { CreatePostInput as C, PostListParams as P, UpdatePostInput as U, PostListResult as c, BlogRouteKey as h, BlogApiContext as j, BlogBackendHooks as k, BlogApiRouter as m };
@@ -1,5 +1,5 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
- import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.BQmuNl5p.js';
2
+ import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from './stack.BWp0hcm9.js';
3
3
  import { z } from 'zod';
4
4
 
5
5
  /**
@@ -135,14 +135,14 @@ declare function useCreatePost(): _tanstack_react_query.UseMutationResult<Serial
135
135
  name: string;
136
136
  slug: string;
137
137
  })[];
138
+ published: boolean;
138
139
  title: string;
139
140
  content: string;
140
141
  excerpt: string;
141
- published: boolean;
142
142
  slug?: string | undefined;
143
+ publishedAt?: Date | undefined;
143
144
  createdAt?: Date | undefined;
144
145
  updatedAt?: Date | undefined;
145
- publishedAt?: Date | undefined;
146
146
  image?: string | undefined;
147
147
  }, unknown>;
148
148
  /** Update an existing post by id */
@@ -131,4 +131,4 @@ interface VercelBlobStorageAdapter {
131
131
  }
132
132
  type StorageAdapter = DirectStorageAdapter | S3StorageAdapter | VercelBlobStorageAdapter;
133
133
 
134
- export type { DirectStorageAdapter as D, S3StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
134
+ export type { DirectStorageAdapter as D, StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, S3StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
@@ -131,4 +131,4 @@ interface VercelBlobStorageAdapter {
131
131
  }
132
132
  type StorageAdapter = DirectStorageAdapter | S3StorageAdapter | VercelBlobStorageAdapter;
133
133
 
134
- export type { DirectStorageAdapter as D, S3StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
134
+ export type { DirectStorageAdapter as D, StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, S3StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
@@ -131,4 +131,4 @@ interface VercelBlobStorageAdapter {
131
131
  }
132
132
  type StorageAdapter = DirectStorageAdapter | S3StorageAdapter | VercelBlobStorageAdapter;
133
133
 
134
- export type { DirectStorageAdapter as D, S3StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };
134
+ export type { DirectStorageAdapter as D, StorageAdapter as S, UploadOptions as U, VercelBlobStorageAdapter as V, S3StorageAdapter as a, S3UploadToken as b, VercelBlobHandlerCallbacks as c };