@plutocms/pluto 0.9.0 → 0.10.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,20 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.10.0](https://github.com/plutocms/pluto/compare/v0.9.1...v0.10.0) (2026-09-13)
5
+
6
+
7
+ ### Features
8
+
9
+ * **content:** add virtual field flag for column-less content-type fields ([#143](https://github.com/plutocms/pluto/issues/143)) ([cf9091e](https://github.com/plutocms/pluto/commit/cf9091e57d21520d92197ba562eef073ef469ee1))
10
+
11
+ ## [0.9.1](https://github.com/plutocms/pluto/compare/v0.9.0...v0.9.1) (2026-09-13)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * **content:** import content types explicitly instead of relying on auto-import ([#141](https://github.com/plutocms/pluto/issues/141)) ([57bd5ab](https://github.com/plutocms/pluto/commit/57bd5ab7d8c9c4748fe679196a0ed08222040082))
17
+
4
18
  ## [0.9.0](https://github.com/plutocms/pluto/compare/v0.8.1...v0.9.0) (2026-09-13)
5
19
 
6
20
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plutocms/pluto",
3
3
  "type": "module",
4
- "version": "0.9.0",
4
+ "version": "0.10.0",
5
5
  "description": "The layerable CMS",
6
6
  "author": "Victor Ribeiro",
7
7
  "license": "MIT",
@@ -25,6 +25,8 @@ export interface PlutoFieldBase {
25
25
  description?: string
26
26
  /** Storage column, when it differs from `name`. Falls back to `name` when unset. */
27
27
  column?: string
28
+ /** This field has no storage column. Its value never reaches `mapFieldsToColumns`'s output, but still passes through validation and the generic form payload — letting a `hooks.afterCreate`/`afterUpdate` read it from `rawBody` without a matching database column. */
29
+ virtual?: boolean
28
30
  required?: boolean
29
31
  /** Show this field as a column in the generic list view. Default false. */
30
32
  inList?: boolean
@@ -1,3 +1,5 @@
1
+ import type { PlutoContentItem, PlutoContentType, PlutoField } from '../types/content'
2
+
1
3
  /** Resolves the storage column for a field. Falls back to `field.name` when `field.column` is unset. */
2
4
  export function fieldColumn(field: PlutoField): string {
3
5
  return field.column ?? field.name
@@ -9,6 +11,9 @@ export function fieldColumn(field: PlutoField): string {
9
11
  * left out of the result, so a partial update payload stays partial after
10
12
  * mapping. An adapter (a later wave) sends the result straight to its
11
13
  * storage layer.
14
+ *
15
+ * A field with `virtual: true` never appears in the result, even when
16
+ * `payload` has a value for it — it has no storage column by design.
12
17
  */
13
18
  export function mapFieldsToColumns(
14
19
  type: PlutoContentType,
@@ -17,6 +22,9 @@ export function mapFieldsToColumns(
17
22
  const columns: Record<string, unknown> = {}
18
23
 
19
24
  for (const field of type.fields) {
25
+ if (field.virtual) {
26
+ continue
27
+ }
20
28
  if (Object.hasOwn(payload, field.name)) {
21
29
  columns[fieldColumn(field)] = payload[field.name]
22
30
  }
@@ -30,6 +38,11 @@ export function mapFieldsToColumns(
30
38
  * every field in `type.fields`, plus the primary key column (`type.primaryKey`,
31
39
  * default `'id'`) mapped to `item.id`. A column absent from `row` is left
32
40
  * out of the result field.
41
+ *
42
+ * A field with `virtual: true` is skipped, for symmetry with
43
+ * `mapFieldsToColumns` — it has no column to read back from `row` in the
44
+ * first place, so this only guards against a stray column that happens to
45
+ * share the field's name.
33
46
  */
34
47
  export function mapColumnsToFields(
35
48
  type: PlutoContentType,
@@ -39,6 +52,9 @@ export function mapColumnsToFields(
39
52
  const item: Record<string, unknown> = { id: row[primaryKey] }
40
53
 
41
54
  for (const field of type.fields) {
55
+ if (field.virtual) {
56
+ continue
57
+ }
42
58
  const column = fieldColumn(field)
43
59
  if (Object.hasOwn(row, column)) {
44
60
  item[field.name] = row[column]
@@ -1,3 +1,5 @@
1
+ import type { PlutoContentType } from '../types/content'
2
+
1
3
  export interface ContentValidationError {
2
4
  field: string
3
5
  message: string
@@ -1,3 +1,5 @@
1
+ import type { PlutoContentType } from '../types/content'
2
+
1
3
  /**
2
4
  * Declares a content type. This is an identity function: it returns `type`
3
5
  * unchanged. Its only job is type inference at the call site — wrapping a