@plutocms/pluto 0.8.1 → 0.9.0

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/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.9.0](https://github.com/plutocms/pluto/compare/v0.8.1...v0.9.0) (2026-09-13)
5
+
6
+
7
+ ### Features
8
+
9
+ * **content:** add newPath/editPath overrides to PlutoContentType ([#139](https://github.com/plutocms/pluto/issues/139)) ([8a69550](https://github.com/plutocms/pluto/commit/8a69550bb1825a6edd143d9e47720815ce2d9b3e))
10
+
4
11
  ## [0.8.1](https://github.com/plutocms/pluto/compare/v0.8.0...v0.8.1) (2026-09-13)
5
12
 
6
13
 
@@ -27,6 +27,14 @@ const canWrite = computed(
27
27
  const editing = computed(() => props.id !== undefined)
28
28
  const basePath = computed(() => contentType.value?.basePath ?? `/admin/content/${props.type}`)
29
29
 
30
+ // editPath exists so an already-deployed layer's edit URL never has to
31
+ // change to adopt this component — see the doc comment on
32
+ // PlutoContentType.editPath for why a single basePath cannot always
33
+ // express it.
34
+ function editPath(id: string | number) {
35
+ return contentType.value?.editPath?.(id) ?? `${basePath.value}/${id}`
36
+ }
37
+
30
38
  const { item, save } = usePlutoContentItem(props.type, () => props.id)
31
39
 
32
40
  function sortedFields(region: 'main' | 'side') {
@@ -131,7 +139,7 @@ async function onSave() {
131
139
  const saved = await save(payload)
132
140
 
133
141
  if (!editing.value) {
134
- await navigateTo(`${basePath.value}/${saved.id}`)
142
+ await navigateTo(editPath(saved.id))
135
143
  return
136
144
  }
137
145
 
@@ -29,6 +29,15 @@ const canDelete = computed(
29
29
 
30
30
  const basePath = computed(() => contentType.value?.basePath ?? `/admin/content/${props.type}`)
31
31
 
32
+ // newPath/editPath exist so an already-deployed layer's URLs never have
33
+ // to change to adopt this component — see the doc comments on
34
+ // PlutoContentType.newPath/editPath for why a single basePath cannot
35
+ // always express both.
36
+ const newPath = computed(() => contentType.value?.newPath ?? `${basePath.value}/new`)
37
+ function editPath(id: string | number) {
38
+ return contentType.value?.editPath?.(id) ?? `${basePath.value}/${id}`
39
+ }
40
+
32
41
  const { items, pending, refresh, remove } = usePlutoContentList(props.type)
33
42
 
34
43
  const listFields = computed(() =>
@@ -102,7 +111,7 @@ async function confirmDelete() {
102
111
 
103
112
  <div v-if="canWrite" class="flex lg:shrink-0">
104
113
  <UButton
105
- :to="`${basePath}/new`"
114
+ :to="newPath"
106
115
  icon="lucide:plus"
107
116
  as="NuxtLink"
108
117
  class="flex-1 justify-center lg:flex-none"
@@ -117,7 +126,7 @@ async function confirmDelete() {
117
126
  <div class="flex flex-col gap-4">
118
127
  <div class="min-w-0">
119
128
  <NuxtLink
120
- :to="`${basePath}/${item.id}`"
129
+ :to="editPath(item.id)"
121
130
  class="block truncate text-lg font-semibold hover:underline"
122
131
  >
123
132
  {{ item[contentType.titleField] }}
@@ -134,7 +143,7 @@ async function confirmDelete() {
134
143
  <div class="flex gap-2 border-t border-default pt-3">
135
144
  <UButton
136
145
  v-if="canWrite"
137
- :to="`${basePath}/${item.id}`"
146
+ :to="editPath(item.id)"
138
147
  icon="lucide:pen-line"
139
148
  color="neutral"
140
149
  variant="soft"
@@ -165,7 +174,7 @@ async function confirmDelete() {
165
174
  <div class="flex justify-end gap-3">
166
175
  <NuxtLink
167
176
  v-if="canWrite"
168
- :to="`${basePath}/${row.original.id}`"
177
+ :to="editPath(row.original.id)"
169
178
  class="text-info px-0 py-0.5 hover:underline"
170
179
  >
171
180
  Edit
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plutocms/pluto",
3
3
  "type": "module",
4
- "version": "0.8.1",
4
+ "version": "0.9.0",
5
5
  "description": "The layerable CMS",
6
6
  "author": "Victor Ribeiro",
7
7
  "license": "MIT",
@@ -177,10 +177,34 @@ export interface PlutoContentType {
177
177
  field: string
178
178
  direction: 'asc' | 'desc'
179
179
  }
180
- /** Whether a later wave should generate list/edit/create admin routes for this content type. */
180
+ /** Whether nav/pages entries should be derived automatically for this content type. `false` when a layer keeps its own hand-declared `nav`/`pages` at its own URLs. */
181
181
  autoRoutes?: boolean
182
- /** Base admin path for generated routes, for example '/admin/posts'. Only meaningful when `autoRoutes` is true. */
182
+ /**
183
+ * Base admin path `PlutoContentList`/`PlutoContentForm` build their own
184
+ * links from, for example '/admin/posts'. Used regardless of
185
+ * `autoRoutes` — it is not only for auto-derived nav/pages, it is also
186
+ * what the generic components' own "add new" button, row edit links,
187
+ * and post-create redirect are built from. Defaults to
188
+ * `/admin/content/<name>` when unset.
189
+ */
183
190
  basePath?: string
191
+ /**
192
+ * Overrides the "create new" link the generic list page links to.
193
+ * Defaults to `${basePath}/new`. Set this when an existing layer's
194
+ * create URL does not follow that convention (for example
195
+ * `/admin/post/new`, singular, alongside a plural `basePath`) — this
196
+ * field exists specifically so an already-deployed URL never has to
197
+ * change to adopt the content model.
198
+ */
199
+ newPath?: string
200
+ /**
201
+ * Overrides the edit link (and the post-create redirect target) for a
202
+ * given id. Defaults to `${basePath}/${id}`. Set this when an existing
203
+ * layer's edit URL does not follow that convention (for example
204
+ * `/admin/post/edit/:id`, with an extra literal segment `basePath`
205
+ * alone cannot express) — the same reasoning as `newPath`.
206
+ */
207
+ editPath?: (id: string | number) => string
184
208
  navOrder?: number
185
209
  i18n?: PlutoContentI18n
186
210
  /**