@stacksjs/defaults 0.70.356 → 0.70.357

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 (27) hide show
  1. package/ai/skills/stacks-orm/SKILL.md +6 -0
  2. package/app/Actions/Dashboard/Content/AuthorDestroyAction.ts +23 -9
  3. package/app/Actions/Dashboard/Content/AuthorIndexAction.ts +32 -26
  4. package/app/Actions/Dashboard/Content/AuthorStoreAction.ts +44 -24
  5. package/app/Actions/Dashboard/Content/AuthorUpdateAction.ts +48 -26
  6. package/app/Actions/Dashboard/Content/CategoryDestroyAction.ts +27 -8
  7. package/app/Actions/Dashboard/Content/CategoryIndexAction.ts +21 -15
  8. package/app/Actions/Dashboard/Content/CategoryStoreAction.ts +47 -29
  9. package/app/Actions/Dashboard/Content/CommentDestroyAction.ts +17 -4
  10. package/app/Actions/Dashboard/Content/CommentIndexAction.ts +23 -17
  11. package/app/Actions/Dashboard/Content/CommentUpdateAction.ts +30 -12
  12. package/app/Actions/Dashboard/Content/ContentDashboardAction.ts +43 -37
  13. package/app/Actions/Dashboard/Content/PageDestroyAction.ts +17 -4
  14. package/app/Actions/Dashboard/Content/PageIndexAction.ts +23 -17
  15. package/app/Actions/Dashboard/Content/PageStoreAction.ts +33 -18
  16. package/app/Actions/Dashboard/Content/PageUpdateAction.ts +40 -22
  17. package/app/Actions/Dashboard/Content/PostDestroyAction.ts +24 -11
  18. package/app/Actions/Dashboard/Content/PostIndexAction.ts +55 -49
  19. package/app/Actions/Dashboard/Content/PostStoreAction.ts +43 -33
  20. package/app/Actions/Dashboard/Content/PostUpdateAction.ts +46 -34
  21. package/app/Actions/Dashboard/Content/TagDestroyAction.ts +27 -8
  22. package/app/Actions/Dashboard/Content/TagIndexAction.ts +31 -25
  23. package/app/Actions/Dashboard/Content/TagStoreAction.ts +44 -23
  24. package/app/Actions/Dashboard/Content/content-input.ts +4 -4
  25. package/app/Actions/Dashboard/Content/post-input.ts +60 -8
  26. package/ide/vscode/package.json +1 -1
  27. package/package.json +1 -1
@@ -1,9 +1,11 @@
1
1
  import type { RequestInstance } from '@stacksjs/types'
2
2
  import { Action } from '@stacksjs/actions'
3
3
  import { db } from '@stacksjs/database'
4
+ import { transaction } from '@stacksjs/orm'
4
5
  import { response } from '@stacksjs/router'
5
6
  import { randomUUIDv7 } from 'bun'
6
- import { findPost, insertedId, invalidPostContent, invalidPostReference, postPayload, publishedAtFor, timestamp } from './post-input'
7
+ import { dashboardOperationalError } from '../dashboard-response'
8
+ import { findPost, insertedId, invalidPostContent, invalidPostReference, postPayload, publishedAtFor, syncPostRelations, timestamp } from './post-input'
7
9
 
8
10
  /**
9
11
  * `POST /api/dashboard/posts` — creates a CMS post from the dashboard.
@@ -23,45 +25,53 @@ export default new Action({
23
25
  if (invalidContent)
24
26
  return response.json({ message: invalidContent }, 422)
25
27
 
26
- const invalidReference = await invalidPostReference(payload)
27
- if (invalidReference)
28
- return response.json({ message: invalidReference }, 422)
28
+ try {
29
+ const result = await transaction(async (rawTrx) => {
30
+ const trx = rawTrx as unknown as typeof db
31
+ const invalidReference = await invalidPostReference(payload, trx)
32
+ if (invalidReference)
33
+ return { kind: 'invalid', message: invalidReference } as const
29
34
 
30
- const now = timestamp()
35
+ const now = timestamp()
31
36
 
32
- const result = await db
33
- .insertInto('posts')
34
- .values({
35
- uuid: randomUUIDv7(),
36
- title: payload.title,
37
- excerpt: payload.excerpt,
38
- content: payload.content,
39
- poster: payload.poster,
40
- status: payload.status,
41
- author_id: payload.authorId,
42
- is_featured: payload.featured ? 1 : 0,
43
- views: 0,
44
- published_at: publishedAtFor(payload.status, null, now),
45
- created_at: now,
46
- updated_at: now,
47
- } as any)
48
- .executeTakeFirst()
37
+ const insertResult = await trx
38
+ .insertInto('posts')
39
+ .values({
40
+ uuid: randomUUIDv7(),
41
+ title: payload.title,
42
+ excerpt: payload.excerpt,
43
+ content: payload.content,
44
+ poster: payload.poster,
45
+ status: payload.status,
46
+ author_id: payload.authorId,
47
+ is_featured: payload.featured ? 1 : 0,
48
+ views: 0,
49
+ published_at: publishedAtFor(payload.status, null, now),
50
+ created_at: now,
51
+ updated_at: now,
52
+ } as any)
53
+ .executeTakeFirst()
49
54
 
50
- const id = insertedId(result)
55
+ const id = insertedId(insertResult)
51
56
 
52
- if (!id)
53
- return response.json({ message: 'Could not create post.' }, 500)
57
+ if (!id)
58
+ throw new Error('Post insert did not return an id.')
54
59
 
55
- const post = await Post.find(id)
60
+ await syncPostRelations(trx, id, payload)
56
61
 
57
- if (!post)
58
- return response.json({ message: 'Created post could not be loaded.' }, 500)
62
+ const created = await findPost(id, trx)
63
+ if (!created)
64
+ throw new Error('Created post could not be read back.')
65
+ return { kind: 'created', post: created } as const
66
+ })
59
67
 
60
- await Promise.all([
61
- post.categories().sync(payload.categoryIds),
62
- post.tags().sync(payload.tagIds),
63
- ])
68
+ if (result.kind === 'invalid')
69
+ return response.json({ message: result.message }, 422)
64
70
 
65
- return response.json(await findPost(id), 201)
71
+ return response.json(result.post, 201)
72
+ }
73
+ catch (error) {
74
+ return dashboardOperationalError(error, 'Post could not be created.', 'PostStoreAction', 500)
75
+ }
66
76
  },
67
77
  })
@@ -1,8 +1,10 @@
1
1
  import type { RequestInstance } from '@stacksjs/types'
2
2
  import { Action } from '@stacksjs/actions'
3
3
  import { db } from '@stacksjs/database'
4
+ import { transaction } from '@stacksjs/orm'
4
5
  import { response } from '@stacksjs/router'
5
- import { findPost, invalidPostContent, invalidPostReference, postPayload, publishedAtFor, timestamp } from './post-input'
6
+ import { dashboardOperationalError } from '../dashboard-response'
7
+ import { findPost, invalidPostContent, invalidPostReference, postPayload, publishedAtFor, syncPostRelations, timestamp } from './post-input'
6
8
 
7
9
  /**
8
10
  * `PATCH /api/dashboard/posts/{id}` — updates a CMS post from the dashboard.
@@ -27,45 +29,55 @@ export default new Action({
27
29
  if (invalidContent)
28
30
  return response.json({ message: invalidContent }, 422)
29
31
 
30
- const invalidReference = await invalidPostReference(payload)
31
- if (invalidReference)
32
- return response.json({ message: invalidReference }, 422)
32
+ try {
33
+ const result = await transaction(async (rawTrx) => {
34
+ const trx = rawTrx as unknown as typeof db
35
+ const invalidReference = await invalidPostReference(payload, trx)
36
+ if (invalidReference)
37
+ return { kind: 'invalid', message: invalidReference } as const
33
38
 
34
- const existing = await db
35
- .selectFrom('posts')
36
- .select(['id', 'published_at'])
37
- .where('id', '=', id)
38
- .executeTakeFirst() as { id: number, published_at: string | null } | undefined
39
+ const existing = await trx
40
+ .selectFrom('posts')
41
+ .select(['id', 'published_at'])
42
+ .where('id', '=', id)
43
+ .executeTakeFirst() as { id: number, published_at: string | null } | undefined
39
44
 
40
- if (!existing)
41
- return response.json({ message: 'Post not found.' }, 404)
45
+ if (!existing)
46
+ return { kind: 'not-found' } as const
42
47
 
43
- await db
44
- .updateTable('posts')
45
- .set({
46
- title: payload.title,
47
- excerpt: payload.excerpt,
48
- content: payload.content,
49
- poster: payload.poster,
50
- status: payload.status,
51
- author_id: payload.authorId,
52
- is_featured: payload.featured ? 1 : 0,
53
- published_at: publishedAtFor(payload.status, existing.published_at, timestamp()),
54
- updated_at: timestamp(),
55
- } as any)
56
- .where('id', '=', id)
57
- .execute()
48
+ await trx
49
+ .updateTable('posts')
50
+ .set({
51
+ title: payload.title,
52
+ excerpt: payload.excerpt,
53
+ content: payload.content,
54
+ poster: payload.poster,
55
+ status: payload.status,
56
+ author_id: payload.authorId,
57
+ is_featured: payload.featured ? 1 : 0,
58
+ published_at: publishedAtFor(payload.status, existing.published_at, timestamp()),
59
+ updated_at: timestamp(),
60
+ } as any)
61
+ .where('id', '=', id)
62
+ .execute()
58
63
 
59
- const post = await Post.find(id)
64
+ await syncPostRelations(trx, id, payload)
60
65
 
61
- if (!post)
62
- return response.json({ message: 'Updated post could not be loaded.' }, 500)
66
+ const updated = await findPost(id, trx)
67
+ if (!updated)
68
+ throw new Error('Updated post could not be read back.')
69
+ return { kind: 'updated', post: updated } as const
70
+ })
63
71
 
64
- await Promise.all([
65
- post.categories().sync(payload.categoryIds),
66
- post.tags().sync(payload.tagIds),
67
- ])
72
+ if (result.kind === 'invalid')
73
+ return response.json({ message: result.message }, 422)
74
+ if (result.kind === 'not-found')
75
+ return response.json({ message: 'Post not found.' }, 404)
68
76
 
69
- return response.json(await findPost(id))
77
+ return response.json(result.post)
78
+ }
79
+ catch (error) {
80
+ return dashboardOperationalError(error, 'Post could not be updated.', 'PostUpdateAction', 500)
81
+ }
70
82
  },
71
83
  })
@@ -1,13 +1,16 @@
1
1
  import type { RequestInstance } from '@stacksjs/types'
2
2
  import { Action } from '@stacksjs/actions'
3
+ import { db } from '@stacksjs/database'
4
+ import { transaction } from '@stacksjs/orm'
3
5
  import { response } from '@stacksjs/router'
6
+ import { dashboardOperationalError } from '../dashboard-response'
4
7
  import { rowId } from './content-input'
5
8
 
6
9
  /**
7
10
  * `DELETE /api/dashboard/tags/{id}` — deletes a CMS tag.
8
11
  *
9
- * Detaches related posts through the model relation before removing the tag so
10
- * no pivot rows are orphaned.
12
+ * Detaches related posts through the model-declared pivot before removing the
13
+ * tag, with both writes committed by the same transaction.
11
14
  */
12
15
  export default new Action({
13
16
  name: 'TagDestroyAction',
@@ -19,13 +22,29 @@ export default new Action({
19
22
  if (!id)
20
23
  return response.json({ message: 'A valid tag id is required.' }, 422)
21
24
 
22
- const tag = await Tag.find(id)
23
- if (!tag)
24
- return response.json({ message: 'Tag not found.' }, 404)
25
+ try {
26
+ const deleted = await transaction(async (rawTrx) => {
27
+ const trx = rawTrx as unknown as typeof db
28
+ const tag = await trx.selectFrom('tags').select(['id']).where('id', '=', id).executeTakeFirst()
29
+ if (!tag)
30
+ return false
25
31
 
26
- await tag.posts().detach()
27
- await tag.delete()
32
+ await trx
33
+ .deleteFrom('taggable_models')
34
+ .where('tag_id', '=', id)
35
+ .where('taggable_type', '=', 'posts')
36
+ .execute()
37
+ await trx.deleteFrom('tags').where('id', '=', id).execute()
38
+ return true
39
+ })
28
40
 
29
- return response.json({ message: 'Tag deleted.', id })
41
+ if (!deleted)
42
+ return response.json({ message: 'Tag not found.' }, 404)
43
+
44
+ return response.json({ message: 'Tag deleted.', id })
45
+ }
46
+ catch (error) {
47
+ return dashboardOperationalError(error, 'Tag could not be deleted.', 'TagDestroyAction', 500)
48
+ }
30
49
  },
31
50
  })
@@ -1,5 +1,6 @@
1
1
  import { Action } from '@stacksjs/actions'
2
2
  import { db } from '@stacksjs/database'
3
+ import { dashboardOperationalError } from '../dashboard-response'
3
4
 
4
5
  interface TagRow {
5
6
  id: number
@@ -28,32 +29,37 @@ export default new Action({
28
29
  method: 'GET',
29
30
  apiResponse: true,
30
31
  async handle() {
31
- const [rows, countRows] = await Promise.all([
32
- db
33
- .selectFrom('tags')
34
- .select(['id', 'name', 'slug', 'description', 'color', 'created_at', 'updated_at'])
35
- .orderBy('created_at', 'desc')
36
- .execute() as unknown as Promise<TagRow[]>,
37
- db
38
- .selectFrom('taggable_models')
39
- .select(['tag_id', db.fn.count('taggable_id').as('count')])
40
- .where('taggable_type', '=', 'posts')
41
- .groupBy('tag_id')
42
- .execute() as unknown as Promise<TagCountRow[]>,
43
- ])
44
- const countByTag = new Map(countRows.map(row => [Number(row.tag_id), Number(row.count)]))
32
+ try {
33
+ const [rows, countRows] = await Promise.all([
34
+ db
35
+ .selectFrom('tags')
36
+ .select(['id', 'name', 'slug', 'description', 'color', 'created_at', 'updated_at'])
37
+ .orderBy('created_at', 'desc')
38
+ .execute() as unknown as Promise<TagRow[]>,
39
+ db
40
+ .selectFrom('taggable_models')
41
+ .select(['tag_id', db.fn.count('taggable_id').as('count')])
42
+ .where('taggable_type', '=', 'posts')
43
+ .groupBy('tag_id')
44
+ .execute() as unknown as Promise<TagCountRow[]>,
45
+ ])
46
+ const countByTag = new Map(countRows.map(row => [Number(row.tag_id), Number(row.count)]))
45
47
 
46
- const tags = rows.map(row => ({
47
- id: Number(row.id),
48
- name: String(row.name || ''),
49
- slug: String(row.slug || ''),
50
- description: String(row.description || ''),
51
- color: String(row.color || ''),
52
- post_count: countByTag.get(Number(row.id)) || 0,
53
- created_at: row.created_at || null,
54
- updated_at: row.updated_at || null,
55
- }))
48
+ const tags = rows.map(row => ({
49
+ id: Number(row.id),
50
+ name: String(row.name || ''),
51
+ slug: String(row.slug || ''),
52
+ description: String(row.description || ''),
53
+ color: String(row.color || ''),
54
+ post_count: countByTag.get(Number(row.id)) || 0,
55
+ created_at: row.created_at || null,
56
+ updated_at: row.updated_at || null,
57
+ }))
56
58
 
57
- return { tags }
59
+ return { tags }
60
+ }
61
+ catch (error) {
62
+ return dashboardOperationalError(error, 'Tags could not be loaded.', 'TagIndexAction')
63
+ }
58
64
  },
59
65
  })
@@ -1,8 +1,10 @@
1
1
  import type { RequestInstance } from '@stacksjs/types'
2
2
  import { Action } from '@stacksjs/actions'
3
3
  import { db } from '@stacksjs/database'
4
+ import { isUniqueViolation, transaction } from '@stacksjs/orm'
4
5
  import { response } from '@stacksjs/router'
5
6
  import { randomUUIDv7 } from 'bun'
7
+ import { dashboardOperationalError } from '../dashboard-response'
6
8
  import { findRow, insertedId, slugify, str, timestamp } from './content-input'
7
9
 
8
10
  /**
@@ -26,34 +28,53 @@ export default new Action({
26
28
  if (!slug)
27
29
  return response.json({ message: 'Slug could not be derived from the name; enter one.' }, 422)
28
30
 
29
- const duplicate = await db
30
- .selectFrom('tags')
31
- .select(['id'])
32
- .where('slug', '=', slug)
33
- .executeTakeFirst()
31
+ try {
32
+ const tag = await transaction(async (rawTrx) => {
33
+ const trx = rawTrx as unknown as typeof db
34
+ const duplicate = await trx
35
+ .selectFrom('tags')
36
+ .select(['id'])
37
+ .where('slug', '=', slug)
38
+ .orWhere('name', '=', name)
39
+ .executeTakeFirst()
34
40
 
35
- if (duplicate)
36
- return response.json({ message: 'A tag with that slug already exists.' }, 422)
41
+ if (duplicate)
42
+ return null
37
43
 
38
- const now = timestamp()
44
+ const now = timestamp()
39
45
 
40
- const result = await db
41
- .insertInto('tags')
42
- .values({
43
- uuid: randomUUIDv7(),
44
- name,
45
- slug,
46
- description,
47
- created_at: now,
48
- updated_at: now,
49
- } as any)
50
- .executeTakeFirst()
46
+ const result = await trx
47
+ .insertInto('tags')
48
+ .values({
49
+ uuid: randomUUIDv7(),
50
+ name,
51
+ slug,
52
+ description,
53
+ created_at: now,
54
+ updated_at: now,
55
+ } as any)
56
+ .executeTakeFirst()
51
57
 
52
- const id = insertedId(result)
58
+ const id = insertedId(result)
53
59
 
54
- if (!id)
55
- return response.json({ message: 'Could not create tag.' }, 500)
60
+ if (!id)
61
+ throw new Error('Tag insert did not return an id.')
56
62
 
57
- return response.json(await findRow('tags', id), 201)
63
+ const created = await findRow('tags', id, trx)
64
+ if (!created)
65
+ throw new Error('Created tag could not be loaded.')
66
+ return created
67
+ })
68
+
69
+ if (!tag)
70
+ return response.json({ message: 'A tag with that name or slug already exists.' }, 422)
71
+
72
+ return response.json(tag, 201)
73
+ }
74
+ catch (error) {
75
+ if (isUniqueViolation(error))
76
+ return response.json({ message: 'A tag with that name or slug already exists.' }, 422)
77
+ return dashboardOperationalError(error, 'Tag could not be created.', 'TagStoreAction', 500)
78
+ }
58
79
  },
59
80
  })
@@ -53,13 +53,13 @@ export function slugify(value: string): string {
53
53
  * `table` is a literal at every call site; the cast is only here because the
54
54
  * query builder's types want a table union rather than a `string`.
55
55
  */
56
- export async function findRow(table: string, id: number): Promise<unknown> {
57
- return await (db as any).selectFrom(table).selectAll().where('id', '=', id).executeTakeFirst()
56
+ export async function findRow(table: string, id: number, database: typeof db = db): Promise<unknown> {
57
+ return await (database as any).selectFrom(table).selectAll().where('id', '=', id).executeTakeFirst()
58
58
  }
59
59
 
60
60
  /** Whether a row with this id exists — the 404 check every write shares. */
61
- export async function rowExists(table: string, id: number): Promise<boolean> {
62
- const row = await (db as any).selectFrom(table).select(['id']).where('id', '=', id).executeTakeFirst()
61
+ export async function rowExists(table: string, id: number, database: typeof db = db): Promise<boolean> {
62
+ const row = await (database as any).selectFrom(table).select(['id']).where('id', '=', id).executeTakeFirst()
63
63
 
64
64
  return Boolean(row)
65
65
  }
@@ -1,8 +1,8 @@
1
1
  import type { RequestInstance } from '@stacksjs/types'
2
2
  import { db } from '@stacksjs/database'
3
- import { str } from './content-input'
3
+ import { insertedId, str, timestamp } from './content-input'
4
4
 
5
- export { insertedId, timestamp } from './content-input'
5
+ export { insertedId, timestamp }
6
6
 
7
7
  export interface PostPayload {
8
8
  title: string
@@ -42,8 +42,8 @@ export function publishedAtFor(status: string, existing: string | null, now: str
42
42
  }
43
43
 
44
44
  /** Reads a post row back after a write — see `findRow` for why writes re-select. */
45
- export async function findPost(id: number): Promise<unknown> {
46
- return await db.selectFrom('posts').selectAll().where('id', '=', id).executeTakeFirst()
45
+ export async function findPost(id: number, database: typeof db = db): Promise<unknown> {
46
+ return await database.selectFrom('posts').selectAll().where('id', '=', id).executeTakeFirst()
47
47
  }
48
48
 
49
49
  function ids(value: unknown): number[] {
@@ -83,16 +83,16 @@ export function invalidPostContent(payload: PostPayload): string | null {
83
83
  return null
84
84
  }
85
85
 
86
- export async function invalidPostReference(payload: PostPayload): Promise<string | null> {
86
+ export async function invalidPostReference(payload: PostPayload, database: typeof db = db): Promise<string | null> {
87
87
  const [author, categoryRows, tagRows] = await Promise.all([
88
88
  payload.authorId
89
- ? db.selectFrom('authors').select(['id']).where('id', '=', payload.authorId).executeTakeFirst()
89
+ ? database.selectFrom('authors').select(['id']).where('id', '=', payload.authorId).executeTakeFirst()
90
90
  : Promise.resolve(undefined),
91
91
  payload.categoryIds.length
92
- ? db.selectFrom('categories').whereIn('id', payload.categoryIds).select(['id']).execute()
92
+ ? database.selectFrom('categories').whereIn('id', payload.categoryIds).select(['id']).execute()
93
93
  : Promise.resolve([]),
94
94
  payload.tagIds.length
95
- ? db.selectFrom('tags').whereIn('id', payload.tagIds).select(['id']).execute()
95
+ ? database.selectFrom('tags').whereIn('id', payload.tagIds).select(['id']).execute()
96
96
  : Promise.resolve([]),
97
97
  ])
98
98
 
@@ -106,6 +106,58 @@ export async function invalidPostReference(payload: PostPayload): Promise<string
106
106
  return null
107
107
  }
108
108
 
109
+ async function replacePostPivot(
110
+ database: typeof db,
111
+ table: 'categorizable_models' | 'taggable_models',
112
+ foreignKey: 'category_id' | 'tag_id',
113
+ ownerKey: 'categorizable_id' | 'taggable_id',
114
+ typeKey: 'categorizable_type' | 'taggable_type',
115
+ postId: number,
116
+ relatedIds: number[],
117
+ now: string,
118
+ ): Promise<void> {
119
+ await (database as any)
120
+ .deleteFrom(table)
121
+ .where(ownerKey, '=', postId)
122
+ .where(typeKey, '=', 'posts')
123
+ .execute()
124
+
125
+ if (relatedIds.length === 0)
126
+ return
127
+
128
+ await (database as any)
129
+ .insertInto(table)
130
+ .values(relatedIds.map(relatedId => ({
131
+ [foreignKey]: relatedId,
132
+ [ownerKey]: postId,
133
+ [typeKey]: 'posts',
134
+ created_at: now,
135
+ updated_at: now,
136
+ })))
137
+ .execute()
138
+ }
139
+
140
+ /** Replaces both post pivot sets on the caller's database or transaction. */
141
+ export async function syncPostRelations(database: typeof db, postId: number, payload: Pick<PostPayload, 'categoryIds' | 'tagIds'>): Promise<void> {
142
+ const now = timestamp()
143
+ await replacePostPivot(database, 'categorizable_models', 'category_id', 'categorizable_id', 'categorizable_type', postId, payload.categoryIds, now)
144
+ await replacePostPivot(database, 'taggable_models', 'tag_id', 'taggable_id', 'taggable_type', postId, payload.tagIds, now)
145
+ }
146
+
147
+ /** Removes both post pivot sets on the caller's database or transaction. */
148
+ export async function detachPostRelations(database: typeof db, postId: number): Promise<void> {
149
+ await (database as any)
150
+ .deleteFrom('categorizable_models')
151
+ .where('categorizable_id', '=', postId)
152
+ .where('categorizable_type', '=', 'posts')
153
+ .execute()
154
+ await (database as any)
155
+ .deleteFrom('taggable_models')
156
+ .where('taggable_id', '=', postId)
157
+ .where('taggable_type', '=', 'posts')
158
+ .execute()
159
+ }
160
+
109
161
  /** Maps a dashboard request body onto the writable post columns. */
110
162
  export function postPayload(request: RequestInstance): PostPayload {
111
163
  return {
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.70.356",
5
+ "version": "0.70.357",
6
6
  "description": "A modern Stacks development environment.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.70.356",
5
+ "version": "0.70.357",
6
6
  "description": "The complete managed Stacks application scaffold, including runtime defaults, AI guidance, editor metadata, and npm-backed project support files.",
7
7
  "author": "Chris Breuer",
8
8
  "license": "MIT",