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 +1 -1
- package/CHANGELOG.md +9 -0
- package/DOCS.md +1 -1
- package/ROADMAP.md +1 -0
- package/dist/core/fields/fieldSchemaToTs.js +5 -1
- package/dist/core/server/fields/resolveRelationFields.js +4 -2
- package/dist/updates/0.36.3/index.d.ts +2 -0
- package/dist/updates/0.36.3/index.js +12 -0
- package/dist/updates/index.js +3 -1
- package/package.json +1 -1
package/API.md
CHANGED
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
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
|
-
|
|
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,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
|
+
};
|
package/dist/updates/index.js
CHANGED
|
@@ -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);
|