includio-cms 0.36.2 → 0.36.3

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/API.md CHANGED
@@ -1,4 +1,4 @@
1
- # includio-cms — Public API v0.36.2
1
+ # includio-cms — Public API v0.36.3
2
2
 
3
3
  > Auto-generated by `scripts/generate-api-md.ts`. Do not edit by hand.
4
4
 
package/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  All notable changes to includio-cms are documented here.
4
4
  Generated from `src/lib/updates/` — do not edit manually.
5
5
 
6
+ ## 0.36.3 — 2026-06-11
7
+
8
+ Relacje opcjonalne — fix: niewybrana relacja (pole bez `required`) blokowała zapis wpisu („Invalid input: expected string, received null") albo wywalała populację przy pustym stringu. Teraz „brak wyboru" działa w obie strony — Zod akceptuje null/""/undefined, a populacja pomija puste wartości.
9
+
10
+ ### Fixed
11
+ - Schemat Zod relacji niewymaganej (`generateZodSchemaFromField`) akceptuje teraz `null` obok `""`/`undefined` (`z.string().nullish().default("")`). Wcześniej `null` (znormalizowane dane lub wyczyszczenie pola w adminie) rzucał „Invalid input: expected string, received null" i blokował zapis wpisu. Bez nowej walidacji uuid — dowolny string nadal przechodzi, więc zero regresji dla istniejących danych.
12
+ - `resolveRelationFields` pomija puste stringi przy zbieraniu ID do populacji (relacje pojedyncze i multiple). Pusty string nie trafia już do zapytania `WHERE id IN ('')`, które Postgres odrzucał jako nieprawidłowy uuid (`invalid input syntax for type uuid: ""`).
13
+ - Efekt łączny: opcjonalna relacja bez wyboru działa w obie strony — zapis w adminie (Zod akceptuje null/"") oraz odczyt na froncie (populacja pomija puste). Dodany regression test dla akceptacji null/""/undefined.
14
+
6
15
  ## 0.36.2 — 2026-06-08
7
16
 
8
17
  Per-status overrides (`ShopConfig.orderStatuses`) + globalny rejestr subject placeholders (`formatSubject`/`ShopConfig.emailSubjectPlaceholders`) + nowy hook `ShopConfig.resolveStatusSubject` do czytania subject z CMS + Handlebars helper `{{{structured}}}` renderujący `StructuredContentDoc` (TipTap) jako email-safe HTML z automatycznym token replacement. Email context rozszerzony o billing fields (firma/NIP/adres/telefon). Dwa fixy bugów w resolverze CMS singletons w mailach. Zaprojektowane pod sklepy ze szkoleniami/wydarzeniami (stationary), gdzie statusy `preparing`/`sent` nie mają sensu. Wszystkie API generyczne, do reusu w innych consumer projects.
package/DOCS.md CHANGED
@@ -1,4 +1,4 @@
1
- # Includio CMS Documentation (v0.36.2)
1
+ # Includio CMS Documentation (v0.36.3)
2
2
 
3
3
  > This file is auto-generated from the docs site. For the latest version, update the package.
4
4
 
package/ROADMAP.md CHANGED
@@ -57,6 +57,7 @@
57
57
  ## Backlog
58
58
 
59
59
  - [ ] `[feature]` `[P2]` Date/datetime field — przebudowa na shadcn-svelte (bits-ui Calendar/DatePicker) zamiast natywnego inputu. Zgłoszone w QA Etap 5a (4/5); funkcjonalnie OK, odłożone jako osobny redesign pola daty. <!-- files: src/lib/admin/components/fields/date-field.svelte, datetime-field.svelte -->
60
+ - [ ] `[feature]` `[P2]` `<Video>` — eksponować ref wewnętrznego `<video>` (np. bindable `element` prop lub forward `bind:this`). Obecnie konsument potrzebujący programowej kontroli (play/pause, scrub, mute toggle) musi owijać w `<div bind:this>` + `querySelector('video')` — boilerplate i kruche. Zgłoszone przy customowym hero-wideo (autoplay + przycisk pauzy). <!-- files: src/lib/sveltekit/components/video.svelte -->
60
61
  - [ ] `[feature]` `[P1]` Re-introduce entry autosave with strict draft-only guard (opt-in via `cms.config.ts`, never touch published versions, debounced + visual countdown). Removed in 0.26.0 / S8 because old impl could touch published data ambiguously.
61
62
  - [ ] `[feature]` `[P2]` Migrate `shipping-method-form` na sveltekit-superforms + formsnap (S8 zostawił hand-rolled validation + FormErrorSummary; pełna migracja wymaga schema dla multi-lang record + dynamic carrier config + price net/gross toggle).
62
63
  - [ ] `[feature]` `[P2]` Storybook story dla `entry-page` (Default/Saving/Saved/Error/Draft/WithErrors/Confirmation) — wymaga mock context: `setRemotes` (5 commands), `setBreadcrumbs`, `setContentLanguage`, RawEntry/DbEntryVersion fixtures. S8 odłożone do S10 a11y sweep.
@@ -214,7 +214,11 @@ export function generateZodSchemaFromField(field, languages, options = {
214
214
  if (field.required) {
215
215
  return z.string().uuid({ message: msg.required });
216
216
  }
217
- return z.string().optional().default('');
217
+ // Non-required: a relation id, or "no selection". The admin (and legacy
218
+ // data) may send '', null or undefined for an unset relation — accept
219
+ // all of them (`.nullish()` adds null + undefined) so an empty optional
220
+ // relation never blocks save. Empty values are skipped at populate time.
221
+ return z.string().nullish().default('');
218
222
  }
219
223
  case 'object': {
220
224
  // Children's `required` is enforced when the object itself is required OR
@@ -30,13 +30,15 @@ export async function resolveRelationFields(data, fields, ctx) {
30
30
  }
31
31
  switch (field.type) {
32
32
  case 'relation': {
33
+ // Skip empty strings — an unset optional relation stores '' and must
34
+ // never reach the id query (Postgres rejects '' as uuid).
33
35
  if (field.multiple && Array.isArray(val)) {
34
36
  for (const id of val) {
35
- if (typeof id === 'string')
37
+ if (typeof id === 'string' && id !== '')
36
38
  entriesIds.push(id);
37
39
  }
38
40
  }
39
- else if (typeof val === 'string') {
41
+ else if (typeof val === 'string' && val !== '') {
40
42
  entriesIds.push(val);
41
43
  }
42
44
  break;
@@ -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.36.3',
3
+ date: '2026-06-11',
4
+ description: 'Relacje opcjonalne — fix: niewybrana relacja (pole bez `required`) blokowała zapis wpisu („Invalid input: expected string, received null") albo wywalała populację przy pustym stringu. Teraz „brak wyboru" działa w obie strony — Zod akceptuje null/""/undefined, a populacja pomija puste wartości.',
5
+ features: [],
6
+ fixes: [
7
+ 'Schemat Zod relacji niewymaganej (`generateZodSchemaFromField`) akceptuje teraz `null` obok `""`/`undefined` (`z.string().nullish().default("")`). Wcześniej `null` (znormalizowane dane lub wyczyszczenie pola w adminie) rzucał „Invalid input: expected string, received null" i blokował zapis wpisu. Bez nowej walidacji uuid — dowolny string nadal przechodzi, więc zero regresji dla istniejących danych.',
8
+ '`resolveRelationFields` pomija puste stringi przy zbieraniu ID do populacji (relacje pojedyncze i multiple). Pusty string nie trafia już do zapytania `WHERE id IN (\'\')`, które Postgres odrzucał jako nieprawidłowy uuid (`invalid input syntax for type uuid: ""`).',
9
+ 'Efekt łączny: opcjonalna relacja bez wyboru działa w obie strony — zapis w adminie (Zod akceptuje null/"") oraz odczyt na froncie (populacja pomija puste). Dodany regression test dla akceptacji null/""/undefined.'
10
+ ],
11
+ breakingChanges: []
12
+ };
@@ -69,6 +69,7 @@ import { update as update0350 } from './0.35.0/index.js';
69
69
  import { update as update0360 } from './0.36.0/index.js';
70
70
  import { update as update0361 } from './0.36.1/index.js';
71
71
  import { update as update0362 } from './0.36.2/index.js';
72
+ import { update as update0363 } from './0.36.3/index.js';
72
73
  export const updates = [
73
74
  update0065,
74
75
  update0066,
@@ -140,7 +141,8 @@ export const updates = [
140
141
  update0350,
141
142
  update0360,
142
143
  update0361,
143
- update0362
144
+ update0362,
145
+ update0363
144
146
  ];
145
147
  export const getUpdatesFrom = (fromVersion) => {
146
148
  const fromParts = fromVersion.split('.').map(Number);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.36.2",
3
+ "version": "0.36.3",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",