@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
@@ -0,0 +1,170 @@
1
+ 'use strict';
2
+
3
+ const utils = require('../utils.cjs');
4
+
5
+ async function findOrCreateTags(adapter, tagInputs) {
6
+ if (tagInputs.length === 0) return [];
7
+ const normalizeTagName = (name) => name.trim();
8
+ const tagsWithIds = [];
9
+ const tagsToFindOrCreate = [];
10
+ for (const tagInput of tagInputs) {
11
+ if ("id" in tagInput && tagInput.id) {
12
+ tagsWithIds.push({
13
+ id: tagInput.id,
14
+ name: normalizeTagName(tagInput.name),
15
+ slug: tagInput.slug,
16
+ createdAt: /* @__PURE__ */ new Date(),
17
+ updatedAt: /* @__PURE__ */ new Date()
18
+ });
19
+ } else {
20
+ tagsToFindOrCreate.push({ name: normalizeTagName(tagInput.name) });
21
+ }
22
+ }
23
+ if (tagsToFindOrCreate.length === 0) {
24
+ return tagsWithIds;
25
+ }
26
+ const allTags = await adapter.findMany({ model: "tag" });
27
+ const tagMapBySlug = /* @__PURE__ */ new Map();
28
+ for (const tag of allTags) {
29
+ tagMapBySlug.set(tag.slug, tag);
30
+ }
31
+ const tagSlugs = tagsToFindOrCreate.map((tag) => utils.slugify(tag.name));
32
+ const foundTags = [];
33
+ for (const slug of tagSlugs) {
34
+ const tag = tagMapBySlug.get(slug);
35
+ if (tag) {
36
+ foundTags.push(tag);
37
+ }
38
+ }
39
+ const existingSlugs = /* @__PURE__ */ new Set([
40
+ ...tagsWithIds.map((tag) => tag.slug),
41
+ ...foundTags.map((tag) => tag.slug)
42
+ ]);
43
+ const tagsToCreate = tagsToFindOrCreate.filter(
44
+ (tag) => !existingSlugs.has(utils.slugify(tag.name))
45
+ );
46
+ const createdTags = [];
47
+ for (const tag of tagsToCreate) {
48
+ const normalizedName = normalizeTagName(tag.name);
49
+ const newTag = await adapter.create({
50
+ model: "tag",
51
+ data: {
52
+ name: normalizedName,
53
+ slug: utils.slugify(normalizedName),
54
+ createdAt: /* @__PURE__ */ new Date(),
55
+ updatedAt: /* @__PURE__ */ new Date()
56
+ }
57
+ });
58
+ createdTags.push(newTag);
59
+ }
60
+ return [...tagsWithIds, ...foundTags, ...createdTags];
61
+ }
62
+ async function createPost(adapter, input) {
63
+ const { tags: tagInputs, ...postData } = input;
64
+ const tagList = tagInputs ?? [];
65
+ const newPost = await adapter.create({
66
+ model: "post",
67
+ data: {
68
+ ...postData,
69
+ published: postData.published ?? false,
70
+ tags: [],
71
+ createdAt: postData.createdAt ?? /* @__PURE__ */ new Date(),
72
+ updatedAt: postData.updatedAt ?? /* @__PURE__ */ new Date()
73
+ }
74
+ });
75
+ if (tagList.length > 0) {
76
+ const resolvedTags = await findOrCreateTags(adapter, tagList);
77
+ await adapter.transaction(async (tx) => {
78
+ for (const tag of resolvedTags) {
79
+ await tx.create({
80
+ model: "postTag",
81
+ data: {
82
+ postId: newPost.id,
83
+ tagId: tag.id
84
+ }
85
+ });
86
+ }
87
+ });
88
+ newPost.tags = resolvedTags.map((tag) => ({ ...tag }));
89
+ } else {
90
+ newPost.tags = [];
91
+ }
92
+ return newPost;
93
+ }
94
+ async function updatePost(adapter, id, input) {
95
+ const { tags: tagInputs, ...postData } = input;
96
+ return adapter.transaction(async (tx) => {
97
+ const updatedPost = await tx.update({
98
+ model: "post",
99
+ where: [{ field: "id", value: id }],
100
+ update: {
101
+ ...postData,
102
+ updatedAt: /* @__PURE__ */ new Date()
103
+ }
104
+ });
105
+ if (!updatedPost) return null;
106
+ if (tagInputs !== void 0) {
107
+ const existingPostTags = await tx.findMany({
108
+ model: "postTag",
109
+ where: [{ field: "postId", value: id, operator: "eq" }]
110
+ });
111
+ for (const postTag of existingPostTags) {
112
+ await tx.delete({
113
+ model: "postTag",
114
+ where: [
115
+ {
116
+ field: "postId",
117
+ value: postTag.postId,
118
+ operator: "eq"
119
+ },
120
+ {
121
+ field: "tagId",
122
+ value: postTag.tagId,
123
+ operator: "eq"
124
+ }
125
+ ]
126
+ });
127
+ }
128
+ if (tagInputs.length > 0) {
129
+ const resolvedTags = await findOrCreateTags(adapter, tagInputs);
130
+ for (const tag of resolvedTags) {
131
+ await tx.create({
132
+ model: "postTag",
133
+ data: {
134
+ postId: id,
135
+ tagId: tag.id
136
+ }
137
+ });
138
+ }
139
+ updatedPost.tags = resolvedTags.map((tag) => ({ ...tag }));
140
+ } else {
141
+ updatedPost.tags = [];
142
+ }
143
+ } else {
144
+ const existingPostTags = await tx.findMany({
145
+ model: "postTag",
146
+ where: [{ field: "postId", value: id, operator: "eq" }]
147
+ });
148
+ if (existingPostTags.length > 0) {
149
+ const tagIds = existingPostTags.map((pt) => pt.tagId);
150
+ const tags = await tx.findMany({
151
+ model: "tag"
152
+ });
153
+ updatedPost.tags = tags.filter((tag) => tagIds.includes(tag.id)).map((tag) => ({ ...tag }));
154
+ } else {
155
+ updatedPost.tags = [];
156
+ }
157
+ }
158
+ return updatedPost;
159
+ });
160
+ }
161
+ async function deletePost(adapter, id) {
162
+ await adapter.delete({
163
+ model: "post",
164
+ where: [{ field: "id", value: id }]
165
+ });
166
+ }
167
+
168
+ exports.createPost = createPost;
169
+ exports.deletePost = deletePost;
170
+ exports.updatePost = updatePost;
@@ -0,0 +1,166 @@
1
+ import { slugify } from '../utils.mjs';
2
+
3
+ async function findOrCreateTags(adapter, tagInputs) {
4
+ if (tagInputs.length === 0) return [];
5
+ const normalizeTagName = (name) => name.trim();
6
+ const tagsWithIds = [];
7
+ const tagsToFindOrCreate = [];
8
+ for (const tagInput of tagInputs) {
9
+ if ("id" in tagInput && tagInput.id) {
10
+ tagsWithIds.push({
11
+ id: tagInput.id,
12
+ name: normalizeTagName(tagInput.name),
13
+ slug: tagInput.slug,
14
+ createdAt: /* @__PURE__ */ new Date(),
15
+ updatedAt: /* @__PURE__ */ new Date()
16
+ });
17
+ } else {
18
+ tagsToFindOrCreate.push({ name: normalizeTagName(tagInput.name) });
19
+ }
20
+ }
21
+ if (tagsToFindOrCreate.length === 0) {
22
+ return tagsWithIds;
23
+ }
24
+ const allTags = await adapter.findMany({ model: "tag" });
25
+ const tagMapBySlug = /* @__PURE__ */ new Map();
26
+ for (const tag of allTags) {
27
+ tagMapBySlug.set(tag.slug, tag);
28
+ }
29
+ const tagSlugs = tagsToFindOrCreate.map((tag) => slugify(tag.name));
30
+ const foundTags = [];
31
+ for (const slug of tagSlugs) {
32
+ const tag = tagMapBySlug.get(slug);
33
+ if (tag) {
34
+ foundTags.push(tag);
35
+ }
36
+ }
37
+ const existingSlugs = /* @__PURE__ */ new Set([
38
+ ...tagsWithIds.map((tag) => tag.slug),
39
+ ...foundTags.map((tag) => tag.slug)
40
+ ]);
41
+ const tagsToCreate = tagsToFindOrCreate.filter(
42
+ (tag) => !existingSlugs.has(slugify(tag.name))
43
+ );
44
+ const createdTags = [];
45
+ for (const tag of tagsToCreate) {
46
+ const normalizedName = normalizeTagName(tag.name);
47
+ const newTag = await adapter.create({
48
+ model: "tag",
49
+ data: {
50
+ name: normalizedName,
51
+ slug: slugify(normalizedName),
52
+ createdAt: /* @__PURE__ */ new Date(),
53
+ updatedAt: /* @__PURE__ */ new Date()
54
+ }
55
+ });
56
+ createdTags.push(newTag);
57
+ }
58
+ return [...tagsWithIds, ...foundTags, ...createdTags];
59
+ }
60
+ async function createPost(adapter, input) {
61
+ const { tags: tagInputs, ...postData } = input;
62
+ const tagList = tagInputs ?? [];
63
+ const newPost = await adapter.create({
64
+ model: "post",
65
+ data: {
66
+ ...postData,
67
+ published: postData.published ?? false,
68
+ tags: [],
69
+ createdAt: postData.createdAt ?? /* @__PURE__ */ new Date(),
70
+ updatedAt: postData.updatedAt ?? /* @__PURE__ */ new Date()
71
+ }
72
+ });
73
+ if (tagList.length > 0) {
74
+ const resolvedTags = await findOrCreateTags(adapter, tagList);
75
+ await adapter.transaction(async (tx) => {
76
+ for (const tag of resolvedTags) {
77
+ await tx.create({
78
+ model: "postTag",
79
+ data: {
80
+ postId: newPost.id,
81
+ tagId: tag.id
82
+ }
83
+ });
84
+ }
85
+ });
86
+ newPost.tags = resolvedTags.map((tag) => ({ ...tag }));
87
+ } else {
88
+ newPost.tags = [];
89
+ }
90
+ return newPost;
91
+ }
92
+ async function updatePost(adapter, id, input) {
93
+ const { tags: tagInputs, ...postData } = input;
94
+ return adapter.transaction(async (tx) => {
95
+ const updatedPost = await tx.update({
96
+ model: "post",
97
+ where: [{ field: "id", value: id }],
98
+ update: {
99
+ ...postData,
100
+ updatedAt: /* @__PURE__ */ new Date()
101
+ }
102
+ });
103
+ if (!updatedPost) return null;
104
+ if (tagInputs !== void 0) {
105
+ const existingPostTags = await tx.findMany({
106
+ model: "postTag",
107
+ where: [{ field: "postId", value: id, operator: "eq" }]
108
+ });
109
+ for (const postTag of existingPostTags) {
110
+ await tx.delete({
111
+ model: "postTag",
112
+ where: [
113
+ {
114
+ field: "postId",
115
+ value: postTag.postId,
116
+ operator: "eq"
117
+ },
118
+ {
119
+ field: "tagId",
120
+ value: postTag.tagId,
121
+ operator: "eq"
122
+ }
123
+ ]
124
+ });
125
+ }
126
+ if (tagInputs.length > 0) {
127
+ const resolvedTags = await findOrCreateTags(adapter, tagInputs);
128
+ for (const tag of resolvedTags) {
129
+ await tx.create({
130
+ model: "postTag",
131
+ data: {
132
+ postId: id,
133
+ tagId: tag.id
134
+ }
135
+ });
136
+ }
137
+ updatedPost.tags = resolvedTags.map((tag) => ({ ...tag }));
138
+ } else {
139
+ updatedPost.tags = [];
140
+ }
141
+ } else {
142
+ const existingPostTags = await tx.findMany({
143
+ model: "postTag",
144
+ where: [{ field: "postId", value: id, operator: "eq" }]
145
+ });
146
+ if (existingPostTags.length > 0) {
147
+ const tagIds = existingPostTags.map((pt) => pt.tagId);
148
+ const tags = await tx.findMany({
149
+ model: "tag"
150
+ });
151
+ updatedPost.tags = tags.filter((tag) => tagIds.includes(tag.id)).map((tag) => ({ ...tag }));
152
+ } else {
153
+ updatedPost.tags = [];
154
+ }
155
+ }
156
+ return updatedPost;
157
+ });
158
+ }
159
+ async function deletePost(adapter, id) {
160
+ await adapter.delete({
161
+ model: "post",
162
+ where: [{ field: "id", value: id }]
163
+ });
164
+ }
165
+
166
+ export { createPost, deletePost, updatePost };
@@ -6,6 +6,7 @@ const db = require('../db.cjs');
6
6
  const utils$1 = require('../utils.cjs');
7
7
  const schemas = require('../schemas.cjs');
8
8
  const getters = require('./getters.cjs');
9
+ const mutations = require('./mutations.cjs');
9
10
  const queryKeyDefs = require('./query-key-defs.cjs');
10
11
  const serializers = require('./serializers.cjs');
11
12
  const utils = require('../../utils.cjs');
@@ -81,70 +82,13 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
81
82
  getAllPosts: (params) => getters.getAllPosts(adapter, params),
82
83
  getPostBySlug: (slug) => getters.getPostBySlug(adapter, slug),
83
84
  getAllTags: () => getters.getAllTags(adapter),
84
- prefetchForRoute: createBlogPrefetchForRoute(adapter)
85
+ prefetchForRoute: createBlogPrefetchForRoute(adapter),
86
+ // Mutations
87
+ createPost: (input) => mutations.createPost(adapter, input),
88
+ updatePost: (id, input) => mutations.updatePost(adapter, id, input),
89
+ deletePost: (id) => mutations.deletePost(adapter, id)
85
90
  }),
86
91
  routes: (adapter) => {
87
- const findOrCreateTags = async (tagInputs) => {
88
- if (tagInputs.length === 0) return [];
89
- const normalizeTagName = (name) => {
90
- return name.trim();
91
- };
92
- const tagsWithIds = [];
93
- const tagsToFindOrCreate = [];
94
- for (const tagInput of tagInputs) {
95
- if ("id" in tagInput && tagInput.id) {
96
- tagsWithIds.push({
97
- id: tagInput.id,
98
- name: normalizeTagName(tagInput.name),
99
- slug: tagInput.slug,
100
- createdAt: /* @__PURE__ */ new Date(),
101
- updatedAt: /* @__PURE__ */ new Date()
102
- });
103
- } else {
104
- tagsToFindOrCreate.push({ name: normalizeTagName(tagInput.name) });
105
- }
106
- }
107
- if (tagsToFindOrCreate.length === 0) {
108
- return tagsWithIds;
109
- }
110
- const allTags = await adapter.findMany({
111
- model: "tag"
112
- });
113
- const tagMapBySlug = /* @__PURE__ */ new Map();
114
- for (const tag of allTags) {
115
- tagMapBySlug.set(tag.slug, tag);
116
- }
117
- const tagSlugs = tagsToFindOrCreate.map((tag) => utils$1.slugify(tag.name));
118
- const foundTags = [];
119
- for (const slug of tagSlugs) {
120
- const tag = tagMapBySlug.get(slug);
121
- if (tag) {
122
- foundTags.push(tag);
123
- }
124
- }
125
- const existingSlugs = /* @__PURE__ */ new Set([
126
- ...tagsWithIds.map((tag) => tag.slug),
127
- ...foundTags.map((tag) => tag.slug)
128
- ]);
129
- const tagsToCreate = tagsToFindOrCreate.filter(
130
- (tag) => !existingSlugs.has(utils$1.slugify(tag.name))
131
- );
132
- const createdTags = [];
133
- for (const tag of tagsToCreate) {
134
- const normalizedName = normalizeTagName(tag.name);
135
- const newTag = await adapter.create({
136
- model: "tag",
137
- data: {
138
- name: normalizedName,
139
- slug: utils$1.slugify(normalizedName),
140
- createdAt: /* @__PURE__ */ new Date(),
141
- updatedAt: /* @__PURE__ */ new Date()
142
- }
143
- });
144
- createdTags.push(newTag);
145
- }
146
- return [...tagsWithIds, ...foundTags, ...createdTags];
147
- };
148
92
  const listPosts = api.createEndpoint(
149
93
  "/posts",
150
94
  {
@@ -194,41 +138,26 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
194
138
  "Unauthorized: Cannot create post"
195
139
  );
196
140
  }
197
- const { tags, ...postData } = ctx.body;
198
- const tagNames = tags || [];
199
- const slug = utils$1.slugify(postData.slug || postData.title);
141
+ const {
142
+ tags,
143
+ slug: rawSlug,
144
+ createdAt: _ca,
145
+ updatedAt: _ua,
146
+ ...postData
147
+ } = ctx.body;
148
+ const slug = utils$1.slugify(rawSlug || postData.title);
200
149
  if (!slug) {
201
150
  throw ctx.error(400, {
202
151
  message: "Invalid slug: must contain at least one alphanumeric character"
203
152
  });
204
153
  }
205
- const newPost = await adapter.create({
206
- model: "post",
207
- data: {
208
- ...postData,
209
- slug,
210
- tags: [],
211
- createdAt: /* @__PURE__ */ new Date(),
212
- updatedAt: /* @__PURE__ */ new Date()
213
- }
154
+ const newPost = await mutations.createPost(adapter, {
155
+ ...postData,
156
+ slug,
157
+ tags: tags ?? [],
158
+ createdAt: /* @__PURE__ */ new Date(),
159
+ updatedAt: /* @__PURE__ */ new Date()
214
160
  });
215
- if (tagNames.length > 0) {
216
- const createdTags = await findOrCreateTags(tagNames);
217
- await adapter.transaction(async (tx) => {
218
- for (const tag of createdTags) {
219
- await tx.create({
220
- model: "postTag",
221
- data: {
222
- postId: newPost.id,
223
- tagId: tag.id
224
- }
225
- });
226
- }
227
- });
228
- newPost.tags = createdTags.map((tag) => ({ ...tag }));
229
- } else {
230
- newPost.tags = [];
231
- }
232
161
  if (hooks?.onPostCreated) {
233
162
  await hooks.onPostCreated(newPost, context);
234
163
  }
@@ -261,76 +190,27 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
261
190
  "Unauthorized: Cannot update post"
262
191
  );
263
192
  }
264
- const { tags, slug: rawSlug, ...restPostData } = ctx.body;
265
- const tagNames = tags || [];
193
+ const {
194
+ tags,
195
+ slug: rawSlug,
196
+ createdAt: _ca,
197
+ updatedAt: _ua,
198
+ ...restPostData
199
+ } = ctx.body;
266
200
  const slugified = rawSlug ? utils$1.slugify(rawSlug) : void 0;
267
201
  if (rawSlug && !slugified) {
268
202
  throw ctx.error(400, {
269
203
  message: "Invalid slug: must contain at least one alphanumeric character"
270
204
  });
271
205
  }
272
- const postData = {
206
+ const updated = await mutations.updatePost(adapter, ctx.params.id, {
273
207
  ...restPostData,
274
- ...slugified ? { slug: slugified } : {}
275
- };
276
- const updated = await adapter.transaction(async (tx) => {
277
- const existingPostTags = await tx.findMany({
278
- model: "postTag",
279
- where: [
280
- {
281
- field: "postId",
282
- value: ctx.params.id,
283
- operator: "eq"
284
- }
285
- ]
286
- });
287
- const updatedPost = await tx.update({
288
- model: "post",
289
- where: [{ field: "id", value: ctx.params.id }],
290
- update: {
291
- ...postData,
292
- updatedAt: /* @__PURE__ */ new Date()
293
- }
294
- });
295
- if (!updatedPost) {
296
- throw ctx.error(404, {
297
- message: "Post not found"
298
- });
299
- }
300
- for (const postTag of existingPostTags) {
301
- await tx.delete({
302
- model: "postTag",
303
- where: [
304
- {
305
- field: "postId",
306
- value: postTag.postId,
307
- operator: "eq"
308
- },
309
- {
310
- field: "tagId",
311
- value: postTag.tagId,
312
- operator: "eq"
313
- }
314
- ]
315
- });
316
- }
317
- if (tagNames.length > 0) {
318
- const createdTags = await findOrCreateTags(tagNames);
319
- for (const tag of createdTags) {
320
- await tx.create({
321
- model: "postTag",
322
- data: {
323
- postId: ctx.params.id,
324
- tagId: tag.id
325
- }
326
- });
327
- }
328
- updatedPost.tags = createdTags.map((tag) => ({ ...tag }));
329
- } else {
330
- updatedPost.tags = [];
331
- }
332
- return updatedPost;
208
+ ...slugified ? { slug: slugified } : {},
209
+ tags: tags ?? []
333
210
  });
211
+ if (!updated) {
212
+ throw ctx.error(404, { message: "Post not found" });
213
+ }
334
214
  if (hooks?.onPostUpdated) {
335
215
  await hooks.onPostUpdated(updated, context);
336
216
  }
@@ -361,10 +241,7 @@ const blogBackendPlugin = (hooks) => api.defineBackendPlugin({
361
241
  "Unauthorized: Cannot delete post"
362
242
  );
363
243
  }
364
- await adapter.delete({
365
- model: "post",
366
- where: [{ field: "id", value: ctx.params.id }]
367
- });
244
+ await mutations.deletePost(adapter, ctx.params.id);
368
245
  if (hooks?.onPostDeleted) {
369
246
  await hooks.onPostDeleted(ctx.params.id, context);
370
247
  }