includio-cms 0.7.2 → 0.13.1

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 (185) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/ROADMAP.md +54 -2
  3. package/dist/admin/api/generate-styles.d.ts +2 -0
  4. package/dist/admin/api/generate-styles.js +32 -0
  5. package/dist/admin/api/handler.js +33 -0
  6. package/dist/admin/api/media-gc.js +10 -4
  7. package/dist/admin/api/rest/handler.js +17 -0
  8. package/dist/admin/api/rest/routes/collections.js +25 -13
  9. package/dist/admin/api/rest/routes/entries.d.ts +1 -1
  10. package/dist/admin/api/rest/routes/entries.js +10 -10
  11. package/dist/admin/api/rest/routes/media.d.ts +2 -0
  12. package/dist/admin/api/rest/routes/media.js +9 -0
  13. package/dist/admin/api/rest/routes/schema.d.ts +5 -0
  14. package/dist/admin/api/rest/routes/schema.js +152 -0
  15. package/dist/admin/api/rest/routes/singletons.d.ts +1 -1
  16. package/dist/admin/api/rest/routes/singletons.js +8 -7
  17. package/dist/admin/api/rest/routes/upload.d.ts +2 -0
  18. package/dist/admin/api/rest/routes/upload.js +28 -0
  19. package/dist/admin/api/upload.js +13 -0
  20. package/dist/admin/client/collection/collection-entries.svelte +35 -13
  21. package/dist/admin/client/entry/entry.svelte +21 -23
  22. package/dist/admin/client/entry/header/a11y-validator.js +2 -2
  23. package/dist/admin/client/entry/header/publish-panel.svelte +33 -85
  24. package/dist/admin/client/entry/header/status-badge.svelte +2 -2
  25. package/dist/admin/client/entry/header/version-history-sheet.svelte +9 -9
  26. package/dist/admin/client/entry/header/visibility.svelte +16 -10
  27. package/dist/admin/client/entry/utils.d.ts +3 -0
  28. package/dist/admin/client/entry/utils.js +22 -4
  29. package/dist/admin/client/form/form-submission/form-submission-page.svelte +4 -1
  30. package/dist/admin/client/form/form-submission/submission-field.svelte +10 -0
  31. package/dist/admin/client/index.d.ts +1 -0
  32. package/dist/admin/client/index.js +1 -0
  33. package/dist/admin/client/maintenance/maintenance-page.svelte +146 -2
  34. package/dist/admin/client/users/users-page.svelte +5 -6
  35. package/dist/admin/client/users/users-page.svelte.d.ts +1 -4
  36. package/dist/admin/components/fields/block-picker-modal.svelte +13 -4
  37. package/dist/admin/components/fields/blocks-field.svelte +40 -19
  38. package/dist/admin/components/fields/field-renderer.svelte +4 -8
  39. package/dist/admin/components/fields/object-field.svelte +7 -12
  40. package/dist/admin/components/fields/select-field.svelte +8 -2
  41. package/dist/admin/components/fields/seo-field.svelte +40 -93
  42. package/dist/admin/components/fields/simple-array-field.svelte +27 -16
  43. package/dist/admin/components/fields/text-field-wrapper.svelte +52 -197
  44. package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
  45. package/dist/admin/components/fields/url-field-wrapper.svelte +15 -25
  46. package/dist/admin/components/fields/url-field.svelte +61 -72
  47. package/dist/admin/components/layout/layout-renderer.svelte +10 -4
  48. package/dist/admin/components/media/file-preview.svelte +10 -1
  49. package/dist/admin/components/media/file-upload.svelte +5 -1
  50. package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
  51. package/dist/admin/components/media/files-list.svelte +12 -3
  52. package/dist/admin/components/media/media-library.svelte +109 -37
  53. package/dist/admin/components/media/media-selector.svelte +90 -16
  54. package/dist/admin/components/media/tag-sidebar.svelte +10 -6
  55. package/dist/admin/components/media/tag-sidebar.svelte.d.ts +7 -2
  56. package/dist/admin/components/tiptap/FigureNodeView.svelte +15 -10
  57. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +53 -94
  58. package/dist/admin/components/tiptap/SlashCommandPopup.svelte +8 -3
  59. package/dist/admin/components/tiptap/editor-toolbar.svelte +28 -23
  60. package/dist/admin/components/tiptap/image-dialog.svelte +12 -7
  61. package/dist/admin/components/tiptap/inline-block-node.js +6 -5
  62. package/dist/admin/components/tiptap/lang.d.ts +77 -0
  63. package/dist/admin/components/tiptap/lang.js +170 -0
  64. package/dist/admin/components/tiptap/link-dialog.svelte +31 -28
  65. package/dist/admin/components/tiptap/slash-command.js +27 -23
  66. package/dist/admin/components/tiptap/table-dialog.svelte +9 -4
  67. package/dist/admin/components/tiptap/video-dialog.svelte +6 -1
  68. package/dist/admin/remote/email.remote.d.ts +1 -0
  69. package/dist/admin/remote/email.remote.js +5 -0
  70. package/dist/admin/remote/entry.remote.d.ts +2 -5
  71. package/dist/admin/remote/entry.remote.js +23 -28
  72. package/dist/admin/remote/index.d.ts +1 -0
  73. package/dist/admin/remote/index.js +1 -0
  74. package/dist/admin/remote/media.remote.d.ts +15 -0
  75. package/dist/admin/remote/media.remote.js +18 -2
  76. package/dist/admin/remote/preview.remote.js +3 -1
  77. package/dist/admin/utils/entryLabel.js +9 -6
  78. package/dist/admin/utils/translationStatus.js +1 -2
  79. package/dist/cli/scaffold/admin.js +34 -2
  80. package/dist/cms/runtime/api.d.ts +16 -12
  81. package/dist/cms/runtime/api.js +7 -6
  82. package/dist/cms/runtime/remote.js +2 -2
  83. package/dist/cms/runtime/schemas.d.ts +1 -1
  84. package/dist/cms/runtime/schemas.js +1 -1
  85. package/dist/cms/runtime/types.d.ts +118 -112
  86. package/dist/cms/runtime/types.js +0 -12
  87. package/dist/core/cms.d.ts +3 -1
  88. package/dist/core/cms.js +30 -0
  89. package/dist/core/fields/fieldSchemaToTs.js +9 -15
  90. package/dist/core/fields/formFieldSchemaToTs.js +7 -0
  91. package/dist/core/server/entries/operations/create.js +10 -4
  92. package/dist/core/server/entries/operations/get.d.ts +1 -0
  93. package/dist/core/server/entries/operations/get.js +186 -191
  94. package/dist/core/server/entries/operations/update.d.ts +6 -7
  95. package/dist/core/server/entries/operations/update.js +20 -38
  96. package/dist/core/server/fields/populateEntry.js +16 -52
  97. package/dist/core/server/fields/resolveImageFields.js +69 -120
  98. package/dist/core/server/fields/resolveRelationFields.js +30 -51
  99. package/dist/core/server/fields/resolveRichtextLinks.js +46 -100
  100. package/dist/core/server/fields/resolveTypographyOrphans.bench.d.ts +1 -0
  101. package/dist/core/server/fields/resolveTypographyOrphans.bench.js +87 -0
  102. package/dist/core/server/fields/resolveTypographyOrphans.d.ts +3 -0
  103. package/dist/core/server/fields/resolveTypographyOrphans.js +128 -0
  104. package/dist/core/server/fields/resolveUrlFields.js +47 -56
  105. package/dist/core/server/fields/utils/fixOrphans.d.ts +5 -0
  106. package/dist/core/server/fields/utils/fixOrphans.js +12 -0
  107. package/dist/core/server/fields/utils/imageStyles.d.ts +4 -2
  108. package/dist/core/server/fields/utils/imageStyles.js +41 -25
  109. package/dist/core/server/fields/utils/resolveMedia.js +1 -6
  110. package/dist/core/server/forms/submissions/operations/delete.js +26 -2
  111. package/dist/core/server/forms/submissions/utils/parseMultipart.d.ts +2 -0
  112. package/dist/core/server/forms/submissions/utils/parseMultipart.js +75 -0
  113. package/dist/core/server/generator/fields.d.ts +6 -0
  114. package/dist/core/server/generator/fields.js +43 -5
  115. package/dist/core/server/generator/formFieldSchemaToString.js +10 -0
  116. package/dist/core/server/generator/formFields.js +1 -0
  117. package/dist/core/server/generator/generator.js +98 -30
  118. package/dist/core/server/media/operations/getFiles.d.ts +5 -0
  119. package/dist/core/server/media/operations/getFiles.js +6 -0
  120. package/dist/core/server/media/operations/uploadPrivateFile.d.ts +4 -0
  121. package/dist/core/server/media/operations/uploadPrivateFile.js +8 -0
  122. package/dist/core/server/media/styles/operations/batchGenerateStyles.d.ts +16 -0
  123. package/dist/core/server/media/styles/operations/batchGenerateStyles.js +144 -0
  124. package/dist/db-postgres/index.js +303 -37
  125. package/dist/db-postgres/schema/entry.d.ts +0 -94
  126. package/dist/db-postgres/schema/entry.js +0 -6
  127. package/dist/db-postgres/schema/entryVersion.d.ts +17 -0
  128. package/dist/db-postgres/schema/entryVersion.js +1 -0
  129. package/dist/entity/index.d.ts +9 -4
  130. package/dist/entity/index.js +24 -24
  131. package/dist/files-local/index.js +43 -0
  132. package/dist/paraglide/messages/_index.d.ts +36 -3
  133. package/dist/paraglide/messages/_index.js +71 -3
  134. package/dist/paraglide/messages/en.d.ts +5 -0
  135. package/dist/paraglide/messages/en.js +14 -0
  136. package/dist/paraglide/messages/pl.d.ts +5 -0
  137. package/dist/paraglide/messages/pl.js +14 -0
  138. package/dist/sveltekit/components/preview.svelte +2 -326
  139. package/dist/sveltekit/components/preview.svelte.d.ts +5 -16
  140. package/dist/sveltekit/server/index.d.ts +2 -1
  141. package/dist/sveltekit/server/index.js +2 -1
  142. package/dist/sveltekit/server/preview.js +4 -7
  143. package/dist/types/adapters/db.d.ts +15 -1
  144. package/dist/types/adapters/files.d.ts +6 -0
  145. package/dist/types/cms.d.ts +5 -0
  146. package/dist/types/entries.d.ts +54 -18
  147. package/dist/types/fields.d.ts +14 -24
  148. package/dist/types/formFields.d.ts +7 -2
  149. package/dist/types/index.d.ts +2 -2
  150. package/dist/types/layout.d.ts +0 -1
  151. package/dist/types/structured-content.d.ts +5 -0
  152. package/dist/updates/0.10.0/index.d.ts +2 -0
  153. package/dist/updates/0.10.0/index.js +15 -0
  154. package/dist/updates/0.11.0/index.d.ts +2 -0
  155. package/dist/updates/0.11.0/index.js +12 -0
  156. package/dist/updates/0.12.0/index.d.ts +2 -0
  157. package/dist/updates/0.12.0/index.js +12 -0
  158. package/dist/updates/0.13.0/index.d.ts +2 -0
  159. package/dist/updates/0.13.0/index.js +10 -0
  160. package/dist/updates/0.13.1/index.d.ts +2 -0
  161. package/dist/updates/0.13.1/index.js +20 -0
  162. package/dist/updates/0.7.3/index.d.ts +2 -0
  163. package/dist/updates/0.7.3/index.js +10 -0
  164. package/dist/updates/0.8.0/index.d.ts +2 -0
  165. package/dist/updates/0.8.0/index.js +18 -0
  166. package/dist/updates/0.8.0/migrate.d.ts +2 -0
  167. package/dist/updates/0.8.0/migrate.js +101 -0
  168. package/dist/updates/0.9.0/index.d.ts +2 -0
  169. package/dist/updates/0.9.0/index.js +38 -0
  170. package/dist/updates/index.js +9 -1
  171. package/package.json +7 -6
  172. package/dist/admin/components/fields/image-field.svelte +0 -198
  173. package/dist/admin/components/fields/image-field.svelte.d.ts +0 -8
  174. package/dist/admin/components/fields/richtext-field.svelte +0 -13
  175. package/dist/admin/components/fields/richtext-field.svelte.d.ts +0 -8
  176. package/dist/admin/components/tiptap.svelte +0 -11
  177. package/dist/admin/components/tiptap.svelte.d.ts +0 -6
  178. package/dist/core/server/entries/utils/getEntryTranslation.d.ts +0 -1
  179. package/dist/core/server/entries/utils/getEntryTranslation.js +0 -18
  180. package/dist/paraglide/messages/hello_world.d.ts +0 -5
  181. package/dist/paraglide/messages/hello_world.js +0 -33
  182. package/dist/paraglide/messages/login_hello.d.ts +0 -16
  183. package/dist/paraglide/messages/login_hello.js +0 -34
  184. package/dist/paraglide/messages/login_please_login.d.ts +0 -16
  185. package/dist/paraglide/messages/login_please_login.js +0 -34
@@ -2,7 +2,7 @@ import type { FormatEnum } from 'sharp';
2
2
  import type { ImageStyle, MediaFile } from './media.js';
3
3
  import type { Localized } from './languages.js';
4
4
  import type { StructuredContentDoc } from './structured-content.js';
5
- export type FieldType = 'text' | 'richtext' | 'content' | 'number' | 'boolean' | 'date' | 'datetime' | 'file' | 'image' | 'media' | 'select' | 'radio' | 'checkboxes' | 'relation' | 'object' | 'array' | 'blocks' | 'slug' | 'seo' | 'url' | 'custom';
5
+ export type FieldType = 'text' | 'content' | 'number' | 'boolean' | 'date' | 'datetime' | 'file' | 'media' | 'select' | 'radio' | 'checkboxes' | 'relation' | 'object' | 'array' | 'blocks' | 'slug' | 'seo' | 'url' | 'custom';
6
6
  export interface FieldCondition {
7
7
  field: string;
8
8
  equals?: string | string[];
@@ -26,12 +26,6 @@ export interface TextField extends BaseField {
26
26
  multiline?: boolean;
27
27
  defaultValue?: string;
28
28
  }
29
- export interface RichtextField extends BaseField {
30
- type: 'richtext';
31
- allowedTags?: string[];
32
- allowedFormats?: string[];
33
- defaultValue?: string;
34
- }
35
29
  export interface ContentField extends BaseField {
36
30
  type: 'content';
37
31
  inlineBlocks?: ObjectField[];
@@ -67,18 +61,6 @@ export interface FileField extends BaseField {
67
61
  multiple?: boolean;
68
62
  defaultValue?: string | string[];
69
63
  }
70
- export interface ImageField extends BaseField {
71
- type: 'image';
72
- accept?: string;
73
- maxSizeMB?: number;
74
- multiple?: boolean;
75
- width?: number;
76
- height?: number;
77
- aspectRatio?: number;
78
- thumbnail?: boolean;
79
- defaultValue?: string | string[];
80
- styles?: ImageFieldStyle[];
81
- }
82
64
  export interface ImageFieldStyle {
83
65
  name: string;
84
66
  width?: number;
@@ -109,6 +91,15 @@ export interface VideoFieldData {
109
91
  audioDescription: MediaFile | null;
110
92
  }
111
93
  export type MediaFieldData = ImageFieldData | VideoFieldData;
94
+ export type FlatImageFieldData = MediaFile & {
95
+ _styles: Record<string, ImageStyle>;
96
+ _blurDataUrl?: string | null;
97
+ };
98
+ export type FlatVideoFieldData = MediaFile & {
99
+ _transcript: MediaFile | null;
100
+ _audioDescription: MediaFile | null;
101
+ };
102
+ export type FlatMediaFieldData = FlatImageFieldData | FlatVideoFieldData;
112
103
  export interface SelectField extends BaseField {
113
104
  type: 'select';
114
105
  options: {
@@ -149,11 +140,10 @@ export interface ObjectField extends BaseField {
149
140
  defaultValue?: ObjectFieldData;
150
141
  thumbnail?: string;
151
142
  }
152
- export interface ObjectFieldData {
143
+ export type ObjectFieldData = {
153
144
  _id?: string;
154
- slug?: string;
155
- data: Record<string, unknown>;
156
- }
145
+ _slug?: string;
146
+ } & Record<string, unknown>;
157
147
  export type SimpleArrayItemType = 'text' | 'number' | 'url';
158
148
  export interface ArrayField extends BaseField {
159
149
  type: 'array';
@@ -211,4 +201,4 @@ export interface CustomField extends BaseField {
211
201
  /** Plugin-specific configuration, opaque to core */
212
202
  config?: Record<string, unknown>;
213
203
  }
214
- export type Field = TextField | RichtextField | ContentField | NumberField | BooleanField | DateField | DateTimeField | FileField | ImageField | MediaField | SelectField | RadioField | CheckboxesField | RelationField | ObjectField | ArrayField | BlocksField | SlugField | SeoField | UrlField | CustomField;
204
+ export type Field = TextField | ContentField | NumberField | BooleanField | DateField | DateTimeField | FileField | MediaField | SelectField | RadioField | CheckboxesField | RelationField | ObjectField | ArrayField | BlocksField | SlugField | SeoField | UrlField | CustomField;
@@ -1,5 +1,5 @@
1
1
  import type { Localized } from './languages.js';
2
- export type FormFieldType = 'text' | 'email' | 'textarea' | 'checkbox' | 'select';
2
+ export type FormFieldType = 'text' | 'email' | 'textarea' | 'checkbox' | 'select' | 'file';
3
3
  export interface FormBaseField {
4
4
  slug: string;
5
5
  label?: Localized;
@@ -37,4 +37,9 @@ export interface FormSelectField extends FormBaseField {
37
37
  }[];
38
38
  defaultValue?: string;
39
39
  }
40
- export type FormField = FormTextField | FormEmailField | FormTextareaField | FormCheckboxField | FormSelectField;
40
+ export interface FormFileField extends FormBaseField {
41
+ type: 'file';
42
+ accept?: string;
43
+ maxSize?: number;
44
+ }
45
+ export type FormField = FormTextField | FormEmailField | FormTextareaField | FormCheckboxField | FormSelectField | FormFileField;
@@ -1,5 +1,5 @@
1
1
  export * from './fields.js';
2
- export { type StructuredContentDoc, type SCNode, type SCMark, type SCInlineBlockAttrs, type SCFigureAttrs, type SCVideoAttrs } from './structured-content.js';
2
+ export { type StructuredContentDoc, type SCNode, type SCMark, type SCInlineBlockAttrs, type SCTypedInlineBlock, type SCFigureAttrs, type SCVideoAttrs } from './structured-content.js';
3
3
  export { type MediaFile, type MediaFileType, type ImageStyle, type MediaTag } from './media.js';
4
4
  export { type ConsentLogData } from './consent.js';
5
5
  export { type Entry, type EntryType, type EntryStatus, type EntryVersionStatus } from './entries.js';
@@ -9,7 +9,7 @@ export { type CollectionConfig } from './collections.js';
9
9
  export { type SingleConfig } from './singles.js';
10
10
  export { type FormConfig, type FormSubmission } from './forms.js';
11
11
  export { type FormField, type FormFieldType, type FormBaseField, type FormTextField, type FormEmailField, type FormTextareaField, type FormCheckboxField, type FormSelectField } from './formFields.js';
12
- export { type CMSConfig, type ApiKeyConfig, type AuthConfig } from './cms.js';
12
+ export { type CMSConfig, type ApiKeyConfig, type AuthConfig, type TypographyConfig } from './cms.js';
13
13
  export { type PluginConfig, type CustomFieldDefinition } from './plugins.js';
14
14
  export { type Language, type Localized } from './languages.js';
15
15
  export { type Layout, type LayoutNode, type LayoutPreset, type LayoutNodeType, type ColumnRatio, type SectionNode, type ColumnsNode, type CardNode, type AccordionNode, type StackNode } from './layout.js';
@@ -31,7 +31,6 @@ export interface ColumnsNode extends LayoutNodeBase {
31
31
  }
32
32
  export interface CardNode extends LayoutNodeBase {
33
33
  type: 'card';
34
- label: Localized;
35
34
  /**
36
35
  * Field references — supports top-level slugs and dot-notation for object fields.
37
36
  * @example ['companyInfo.name', 'companyInfo.motto'] — fields from different objects in one card
@@ -57,6 +57,11 @@ export interface SCInlineBlockAttrs {
57
57
  blockData: Record<string, unknown>;
58
58
  blockId: string;
59
59
  }
60
+ export interface SCTypedInlineBlock<T = Record<string, unknown>> {
61
+ blockType: string;
62
+ blockData: T;
63
+ blockId: string;
64
+ }
60
65
  export interface StructuredContentDoc {
61
66
  type: 'doc';
62
67
  content: SCNode[];
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,15 @@
1
+ export const update = {
2
+ version: '0.10.0',
3
+ date: '2026-03-18',
4
+ description: 'Remove image, video, richtext field types — consolidate to media and content',
5
+ features: [],
6
+ fixes: [],
7
+ breakingChanges: [
8
+ 'Removed `image` field type — use `media` with `accept: "image/*"` instead',
9
+ 'Removed `richtext` field type — use `content` (structured ProseMirror JSON) instead',
10
+ 'Removed `ImageField` and `RichtextField` TypeScript interfaces',
11
+ '`image-field.svelte` and `richtext-field.svelte` components removed',
12
+ '`tiptap.svelte` (HTML richtext wrapper) removed'
13
+ ],
14
+ notes: 'No automatic data migration. Replace `type: "image"` with `type: "media", accept: "image/*"` in your collection/singleton configs. Replace `type: "richtext"` with `type: "content"`. Existing stored data (media UUIDs, ProseMirror docs) remains compatible.'
15
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,12 @@
1
+ export const update = {
2
+ version: '0.11.0',
3
+ date: '2026-03-18',
4
+ description: 'Codegen overhaul and REST API consolidation',
5
+ features: [
6
+ 'Codegen: flat entry types, inline block types, `countEntries` query helper, simplified API surface',
7
+ 'REST API: catch-all route handler, file upload endpoint, media endpoint, schema template endpoints',
8
+ 'Admin scaffold updated for new REST route structure'
9
+ ],
10
+ fixes: [],
11
+ breakingChanges: []
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,12 @@
1
+ export const update = {
2
+ version: '0.12.0',
3
+ date: '2026-03-18',
4
+ description: 'File field type, dataOrderBy, and _url population',
5
+ features: [
6
+ 'File field type with multipart upload, file validation, and rate limiting',
7
+ '`dataOrderBy` — sort entries by JSON data fields in queries',
8
+ 'Auto-populate `_url` field on entries from slug resolver and `pathTemplate`'
9
+ ],
10
+ fixes: [],
11
+ breakingChanges: []
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,10 @@
1
+ export const update = {
2
+ version: '0.13.0',
3
+ date: '2026-03-19',
4
+ description: 'Private file uploads for form submissions',
5
+ features: [
6
+ 'Private file uploads — form submissions can upload files to a non-public directory with access control'
7
+ ],
8
+ fixes: [],
9
+ breakingChanges: []
10
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,20 @@
1
+ export const update = {
2
+ version: '0.13.1',
3
+ date: '2026-03-20',
4
+ description: 'Admin UI i18n, codegen cleanup, docs rewrite',
5
+ features: [
6
+ 'Admin UI i18n — TipTap editor, blocks field, array field, media components support pl/en interface language',
7
+ 'Inline block accordion labels — show field value in collapsed block header',
8
+ 'Blocks field UrlFieldData label support',
9
+ 'Email configuration remote endpoint'
10
+ ],
11
+ fixes: [
12
+ 'Codegen: remove unused FlatImageFieldData/FlatVideoFieldData, use ImageFieldData/VideoFieldData',
13
+ 'Layout renderer: hide card header when label is empty',
14
+ 'Collection entries: improved relation label fetching with UUID validation and multi-version support',
15
+ 'Users page: client-side email config check, remove server load dependency',
16
+ 'Entry remote: stricter UUID validation for ids parameter',
17
+ 'Layout type: remove unused label property from layout node'
18
+ ],
19
+ breakingChanges: []
20
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,10 @@
1
+ export const update = {
2
+ version: '0.7.3',
3
+ date: '2026-03-17',
4
+ description: 'Typography orphan fix for Polish conjunctions',
5
+ features: [
6
+ 'Read-time orphan fix — replace space after single-letter Polish conjunctions (i, w, z, o, u, a) with non-breaking space `\\u00A0`'
7
+ ],
8
+ fixes: [],
9
+ breakingChanges: []
10
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,18 @@
1
+ export const update = {
2
+ version: '0.8.0',
3
+ date: '2026-03-17',
4
+ description: 'Flat entry format — remove data wrapper from objects/blocks',
5
+ features: [
6
+ 'Flat entry format: objects use `_slug` + spread fields instead of `slug` + `data` wrapper',
7
+ 'Blocks use `_slug` instead of `slug` with flat fields',
8
+ 'Entry type unified: `FlatEntry` renamed to `Entry`, old `Entry` removed'
9
+ ],
10
+ fixes: [],
11
+ breakingChanges: [
12
+ 'Object field data format: `{ slug, data: {...} }` → `{ _slug, ...fields }`',
13
+ 'Blocks field data format: `{ _id, slug, data: {...} }` → `{ _id, _slug, ...fields }`',
14
+ '`FlatEntry` type removed — use `Entry` instead',
15
+ '`flattenEntry`/`flattenFields` removed — data is flat from resolve functions'
16
+ ],
17
+ notes: 'Run `includio update` to migrate existing entry data in the database.'
18
+ };
@@ -0,0 +1,2 @@
1
+ import type { DatabaseAdapter } from '../../types/adapters/db.js';
2
+ export declare function migrateEntryData(db: DatabaseAdapter): Promise<number>;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Migrate entry version data from wrapped format to flat format.
3
+ *
4
+ * Objects: { slug, data: {...} } → { _slug, ...fields }
5
+ * Blocks: [{ _id, slug, data: {...} }] → [{ _id, _slug, ...fields }]
6
+ * Content inline blocks: blockData with nested objects/blocks also transformed.
7
+ */
8
+ function isWrappedObject(val) {
9
+ return (val != null &&
10
+ typeof val === 'object' &&
11
+ 'slug' in val &&
12
+ 'data' in val &&
13
+ typeof val.slug === 'string' &&
14
+ typeof val.data === 'object' &&
15
+ val.data !== null);
16
+ }
17
+ function migrateValue(val) {
18
+ if (val == null)
19
+ return val;
20
+ if (Array.isArray(val)) {
21
+ return val.map((item) => {
22
+ if (isWrappedObject(item)) {
23
+ const { slug, data, _id, ...rest } = item;
24
+ const flatData = migrateRecord(data);
25
+ return {
26
+ ...rest,
27
+ ...(_id != null ? { _id } : {}),
28
+ _slug: slug,
29
+ ...flatData
30
+ };
31
+ }
32
+ return migrateValue(item);
33
+ });
34
+ }
35
+ if (typeof val === 'object') {
36
+ // Check if this is a wrapped object (not an array)
37
+ if (isWrappedObject(val)) {
38
+ const { slug, data, _id, ...rest } = val;
39
+ const flatData = migrateRecord(data);
40
+ return {
41
+ ...rest,
42
+ ...(_id != null ? { _id } : {}),
43
+ _slug: slug,
44
+ ...flatData
45
+ };
46
+ }
47
+ // Check if this is a structured content doc — recurse into inline blocks
48
+ if ('type' in val && val.type === 'doc') {
49
+ return migrateStructuredDoc(val);
50
+ }
51
+ // Generic object — recurse into values
52
+ return migrateRecord(val);
53
+ }
54
+ return val;
55
+ }
56
+ function migrateRecord(record) {
57
+ const result = {};
58
+ for (const [key, value] of Object.entries(record)) {
59
+ result[key] = migrateValue(value);
60
+ }
61
+ return result;
62
+ }
63
+ function migrateStructuredDoc(doc) {
64
+ if (!doc.content || !Array.isArray(doc.content))
65
+ return doc;
66
+ return {
67
+ ...doc,
68
+ content: doc.content.map((node) => {
69
+ if (node.type === 'inlineBlock' && node.attrs) {
70
+ const attrs = { ...node.attrs };
71
+ if (attrs.blockData && typeof attrs.blockData === 'object') {
72
+ attrs.blockData = migrateRecord(attrs.blockData);
73
+ }
74
+ return { ...node, attrs };
75
+ }
76
+ // Recurse into child content
77
+ if (node.content && Array.isArray(node.content)) {
78
+ return migrateStructuredDoc(node);
79
+ }
80
+ return node;
81
+ })
82
+ };
83
+ }
84
+ export async function migrateEntryData(db) {
85
+ // Get all entries
86
+ const entries = await db.getEntries({});
87
+ let migratedCount = 0;
88
+ for (const entry of entries) {
89
+ const versions = await db.getEntryVersions({ entryIds: [entry.id] });
90
+ for (const version of versions) {
91
+ const originalData = version.data;
92
+ const migratedData = migrateRecord(originalData);
93
+ // Only update if data actually changed
94
+ if (JSON.stringify(originalData) !== JSON.stringify(migratedData)) {
95
+ await db.updateEntryVersion(version.id, { data: migratedData });
96
+ migratedCount++;
97
+ }
98
+ }
99
+ }
100
+ return migratedCount;
101
+ }
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,38 @@
1
+ export const update = {
2
+ version: '0.9.0',
3
+ date: '2026-03-17',
4
+ description: 'Per-language entry versions — separate entry_version per language',
5
+ features: [
6
+ 'Per-language entry versions: each language gets its own entry_version with flat data',
7
+ 'Per-language publication: publish/unpublish each language independently',
8
+ 'Simplified data format: no more nested `{ pl: "X", en: "Y" }` — values are flat strings',
9
+ 'Language switching in admin loads different version data'
10
+ ],
11
+ fixes: [],
12
+ breakingChanges: [
13
+ '`entry_version` table: new `lang` column (NOT NULL)',
14
+ '`entry` table: removed `published_at`, `published_version_id`, `published_by`, `available_locales` columns',
15
+ '`RawEntry`: `publishedVersion`/`draftVersion`/`scheduledVersion` replaced with per-lang `publishedVersions`/`draftVersions`/`scheduledVersions` records',
16
+ '`DbEntryVersion`/`DbEntryVersionInsert`: new required `lang` field',
17
+ '`translateObject` removed — data is single-language per version',
18
+ 'Resolve functions (relation, media, url, richtext) expect flat content/richtext values, not `Record<lang, value>`',
19
+ '`upsertDraftVersion` and `pruneOldDraftVersions` now require `lang` parameter',
20
+ '`unpublishEntry` renamed to `unpublishEntryLang` with required `lang` parameter'
21
+ ],
22
+ sql: `-- Step 1: Add lang column as nullable
23
+ ALTER TABLE entry_version ADD COLUMN lang TEXT;
24
+
25
+ -- Step 2: Run migration script to split multi-lang versions (scripts/migrate-lang-versions.ts)
26
+ -- After migration, set NOT NULL:
27
+ ALTER TABLE entry_version ALTER COLUMN lang SET NOT NULL;
28
+
29
+ -- Step 3: Create index for performance
30
+ CREATE INDEX idx_entry_version_publish ON entry_version(entry_id, lang, published_at);
31
+
32
+ -- Step 4: Remove entry-level publish columns
33
+ ALTER TABLE entry DROP COLUMN IF EXISTS published_at;
34
+ ALTER TABLE entry DROP COLUMN IF EXISTS published_version_id;
35
+ ALTER TABLE entry DROP COLUMN IF EXISTS published_by;
36
+ ALTER TABLE entry DROP COLUMN IF EXISTS available_locales;`,
37
+ notes: 'Run the migration script BEFORE setting lang to NOT NULL. See scripts/migrate-lang-versions.ts for data migration.'
38
+ };
@@ -26,7 +26,15 @@ import { update as update062 } from './0.6.2/index.js';
26
26
  import { update as update070 } from './0.7.0/index.js';
27
27
  import { update as update071 } from './0.7.1/index.js';
28
28
  import { update as update072 } from './0.7.2/index.js';
29
- export const updates = [update0065, update0066, update0067, update0068, update0069, update010, update011, update012, update013, update014, update015, update020, update022, update050, update051, update052, update053, update054, update055, update056, update057, update058, update060, update061, update062, update070, update071, update072];
29
+ import { update as update073 } from './0.7.3/index.js';
30
+ import { update as update080 } from './0.8.0/index.js';
31
+ import { update as update090 } from './0.9.0/index.js';
32
+ import { update as update0100 } from './0.10.0/index.js';
33
+ import { update as update0110 } from './0.11.0/index.js';
34
+ import { update as update0120 } from './0.12.0/index.js';
35
+ import { update as update0130 } from './0.13.0/index.js';
36
+ import { update as update0131 } from './0.13.1/index.js';
37
+ export const updates = [update0065, update0066, update0067, update0068, update0069, update010, update011, update012, update013, update014, update015, update020, update022, update050, update051, update052, update053, update054, update055, update056, update057, update058, update060, update061, update062, update070, update071, update072, update073, update080, update090, update0100, update0110, update0120, update0130, update0131];
30
38
  export const getUpdatesFrom = (fromVersion) => {
31
39
  const fromParts = fromVersion.split('.').map(Number);
32
40
  return updates.filter((update) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.7.2",
3
+ "version": "0.13.1",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -214,18 +214,18 @@
214
214
  "flexsearch": "^0.8.212",
215
215
  "formsnap": "^2.0.1",
216
216
  "globals": "^16.0.0",
217
- "paneforge": "^1.0.2",
218
- "postgres": "^3.4.5",
219
217
  "jsdom": "^26.0.0",
220
218
  "mdsvex": "^0.12.3",
219
+ "paneforge": "^1.0.2",
220
+ "postgres": "^3.4.5",
221
221
  "prettier": "^3.4.2",
222
222
  "prettier-plugin-svelte": "^3.3.3",
223
223
  "prettier-plugin-tailwindcss": "^0.6.11",
224
224
  "publint": "^0.3.2",
225
- "runed": "^0.35.1",
226
225
  "rehype-autolink-headings": "^7.1.0",
227
226
  "rehype-slug": "^6.0.0",
228
227
  "remark-gfm": "^4.0.1",
228
+ "runed": "^0.35.1",
229
229
  "sharp": "^0.34.2",
230
230
  "shiki": "^3.21.0",
231
231
  "storybook": "^10.2.10",
@@ -234,11 +234,11 @@
234
234
  "svelte-sonner": "^1.0.5",
235
235
  "svelte-tiptap": "^3.0.1",
236
236
  "sveltekit-superforms": "^2.28.1",
237
+ "tailwind-merge": "^3.3.1",
238
+ "tailwindcss": "^4.1.13",
237
239
  "ts-morph": "^26.0.0",
238
240
  "tsx": "^4.20.3",
239
241
  "typescript": "^5.0.0",
240
- "tailwind-merge": "^3.3.1",
241
- "tailwindcss": "^4.1.13",
242
242
  "typescript-eslint": "^8.20.0",
243
243
  "vite": "^7.2.2",
244
244
  "vitest": "^3.2.3"
@@ -279,6 +279,7 @@
279
279
  "fluent-ffmpeg": "^2.1.3",
280
280
  "isomorphic-dompurify": "3.0.0-rc.2",
281
281
  "lowlight": "^3.3.0",
282
+ "mrmime": "^2.0.1",
282
283
  "nodemailer": "^7.0.11",
283
284
  "openai": "^6.9.0",
284
285
  "path-to-regexp": "^8.2.0",