includio-cms 0.21.0 → 0.23.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.
Files changed (81) hide show
  1. package/API.md +20 -20
  2. package/CHANGELOG.md +111 -0
  3. package/DOCS.md +1169 -146
  4. package/README.md +138 -32
  5. package/ROADMAP.md +8 -330
  6. package/dist/admin/api/rest/handler.d.ts +13 -1
  7. package/dist/admin/api/rest/handler.js +13 -1
  8. package/dist/admin/api/rest/middleware/generateApiKey.d.ts +9 -0
  9. package/dist/admin/api/rest/middleware/generateApiKey.js +9 -0
  10. package/dist/admin/client/collection/collection-entries.svelte +1 -1
  11. package/dist/admin/client/collection/empty-state.svelte +1 -1
  12. package/dist/admin/client/collection/row-actions.svelte +3 -3
  13. package/dist/admin/client/collection/table-toolbar.svelte +3 -1
  14. package/dist/admin/client/entry/entry-header.svelte +3 -1
  15. package/dist/admin/client/users/create-user-dialog.svelte +4 -4
  16. package/dist/admin/client/users/delete-user-dialog.svelte +2 -0
  17. package/dist/admin/client/users/users-page.svelte +3 -2
  18. package/dist/admin/components/media/file-upload.svelte +2 -0
  19. package/dist/ai-claude/index.d.ts +9 -1
  20. package/dist/ai-claude/index.js +9 -1
  21. package/dist/ai-openai/index.d.ts +9 -1
  22. package/dist/ai-openai/index.js +9 -1
  23. package/dist/cli/index.js +115 -13
  24. package/dist/cms/runtime/schema.d.ts +2 -0
  25. package/dist/cms/runtime/schema.js +4 -0
  26. package/dist/cms/runtime/types.d.ts +1 -1
  27. package/dist/core/cms.d.ts +13 -1
  28. package/dist/core/cms.js +13 -1
  29. package/dist/core/errors.d.ts +71 -0
  30. package/dist/core/errors.js +179 -0
  31. package/dist/core/server/consentLogs/operations/create.d.ts +13 -1
  32. package/dist/core/server/consentLogs/operations/create.js +13 -1
  33. package/dist/core/server/entries/operations/create.js +6 -1
  34. package/dist/core/server/entries/operations/get.js +14 -3
  35. package/dist/core/server/entries/operations/resolveEntry.d.ts +32 -1
  36. package/dist/core/server/entries/operations/resolveEntry.js +36 -4
  37. package/dist/core/server/entries/operations/update.js +5 -1
  38. package/dist/core/server/fields/utils/resolveMedia.d.ts +18 -1
  39. package/dist/core/server/fields/utils/resolveMedia.js +13 -1
  40. package/dist/core/server/forms/submissions/operations/create.d.ts +21 -1
  41. package/dist/core/server/forms/submissions/operations/create.js +18 -2
  42. package/dist/core/server/forms/submissions/utils/parseMultipart.d.ts +15 -1
  43. package/dist/core/server/forms/submissions/utils/parseMultipart.js +15 -1
  44. package/dist/db-postgres/index.d.ts +10 -0
  45. package/dist/db-postgres/index.js +10 -0
  46. package/dist/email-nodemailer/index.d.ts +13 -1
  47. package/dist/email-nodemailer/index.js +13 -1
  48. package/dist/entity/index.d.ts +16 -1
  49. package/dist/entity/index.js +16 -1
  50. package/dist/files-local/index.d.ts +12 -1
  51. package/dist/files-local/index.js +12 -1
  52. package/dist/paraglide/messages/_index.d.ts +3 -36
  53. package/dist/paraglide/messages/_index.js +3 -71
  54. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  55. package/dist/paraglide/messages/hello_world.js +33 -0
  56. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  57. package/dist/paraglide/messages/login_hello.js +34 -0
  58. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  59. package/dist/paraglide/messages/login_please_login.js +34 -0
  60. package/dist/server/auth.d.ts +11 -0
  61. package/dist/server/auth.js +11 -0
  62. package/dist/sveltekit/config.d.ts +67 -4
  63. package/dist/sveltekit/config.js +73 -4
  64. package/dist/sveltekit/server/handle.d.ts +15 -1
  65. package/dist/sveltekit/server/handle.js +15 -1
  66. package/dist/sveltekit/server/layout.d.ts +12 -1
  67. package/dist/sveltekit/server/layout.js +12 -1
  68. package/dist/sveltekit/server/preview.d.ts +21 -1
  69. package/dist/sveltekit/server/preview.js +21 -1
  70. package/dist/types/cms.schema.d.ts +452 -0
  71. package/dist/types/cms.schema.js +629 -0
  72. package/dist/updates/0.22.0/index.d.ts +2 -0
  73. package/dist/updates/0.22.0/index.js +75 -0
  74. package/dist/updates/0.23.0/index.d.ts +2 -0
  75. package/dist/updates/0.23.0/index.js +21 -0
  76. package/dist/updates/index.js +3 -1
  77. package/package.json +4 -1
  78. package/dist/paraglide/messages/en.d.ts +0 -5
  79. package/dist/paraglide/messages/en.js +0 -14
  80. package/dist/paraglide/messages/pl.d.ts +0 -5
  81. package/dist/paraglide/messages/pl.js +0 -14
@@ -0,0 +1,75 @@
1
+ export const update = {
2
+ version: '0.22.0',
3
+ date: '2026-04-30',
4
+ description: 'Faza 9 — DX & config validation pass. `defineConfig()` waliduje config strict Zodem z czytelnymi błędami (path + hint), resolvery / operacje throwują typowane `CmsError` z `code` + `context`, CLI ma `--help` per subcommand i `--version`, README przepisany pod nowych userów (system requirements + 5-min quickstart), `.env.example` rozszerzony o wszystkie `INCLUDIO_*` envy, JSDoc na każdym `@public` symbolu (opis + `@param` + `@returns` + `@example`).',
5
+ features: [
6
+ '`defineConfig()` (`includio-cms/sveltekit`) — runtime Zod validation z agregacją wszystkich błędów. Invalid config → `ConfigValidationError` (extends `CmsError`) z `issues[]` (path + message + hint), bullet-list message ready-to-paste do PR. `superRefine`: unique slugs (collections/singles/forms), default locale ≤ 1, relation targets w deklarowanych kolekcjach, `apiKeys[].permissions` referuje istniejące collection slugs.',
7
+ '`CmsError` + `ConfigValidationError` (`includio-cms` → `core/errors`) — bazowa klasa z `code` (SCREAMING_SNAKE_CASE), `context: Record<string, unknown>`, `cause?`. Stabilne kody: `ENTRY_NOT_FOUND`, `ENTRY_VERSION_NOT_FOUND`, `INVALID_DATA`, `MISSING_REQUIRED_PARAM`, `CONFIG_VALIDATION_FAILED`. `toString()` = `[CODE] message (k=v, k=v)`.',
8
+ '`formatZodDataIssues(error)` helper — render Zod errora z entry/form data jako lista `path: message`. Używany w `createEntryVersion`, `updateEntryVersion`, `createFormSubmission`.',
9
+ 'CLI: `includio --help`, `includio scaffold admin --help`, `includio install-peers --help`, `includio create-user --help` — exit 0 + Usage/Options/Example block. `includio --version` / `-v` z `package.json`. Unknown command → exit 1 + top-level help.',
10
+ '`.env.example` rozszerzony — 11 envów z komentarzami i sekcjami (Required / Media & Uploads / Security & Rate Limits). Demo vars usunięte (były tylko dla `src/lib/demo/` skasowanego w Fazie 1).',
11
+ 'README rebuild: TOC, sekcja **System requirements** (Node 18+, PG 14+, ffmpeg optional), 5-step **Quick start** (install → .env → config → scaffold → create-user → dev), poprawiony link do `DOCS.md`, dodana tabelka adapterów, sekcja CLI z subcommandami.',
12
+ 'JSDoc bodies (opis + `@param` + `@returns` + `@example`) na każdym `@public` symbolu — `defineConfig`, `defineCollection`, `defineSingle`, `defineForm`, `defineObject`, `getCMS`, `resolveEntry`, `resolveEntries`, `countEntries`, `createFormSubmission`, `parseFormDataForSubmission`, `createConsentLog`, `resolveMediaWithStyles`, `createEntityAPI`, `createRestApiHandler`, `generateApiKey`, `getAuth`, `includioCMS`, `getPreviewEntry`, `cmsLayoutLoad`, factory adapterów (`pg`, `local`, `nodemailerAdapter`, `openAIAdapter`, `claudeAdapter`).'
13
+ ],
14
+ fixes: [
15
+ '`MISSING_REQUIRED_PARAM` zamiast `throw new Error(\'... is required\')` w `resolveEntry` / `resolveEntries` / `countEntries`. Context zawiera `op` + `missing`.',
16
+ '`INVALID_DATA` zamiast `throw Error(\'Invalid data: \' + JSON.stringify(parsedData.error.flatten()))` w `createEntryVersion` / `updateEntryVersion` / `createFormSubmission`. Context zawiera `collection`/`entryId`/`lang` (entries) lub `formSlug` (forms). Body errora to czytelna lista `field.path: message`.',
17
+ '`ENTRY_NOT_FOUND` z `{ collection, id }` w `_getDbEntryOrThrow` / `_getRawEntryOrThrow`; `ENTRY_VERSION_NOT_FOUND` z `{ versionId, entryId, lang }` w `_getDbEntryVersionOrThrow`.'
18
+ ],
19
+ breakingChanges: [
20
+ '**Strict config validation w `defineConfig`** — invalid configs które wcześniej "działały" w runtime (np. duplicate slug, brak default locale, relation do nieistniejącej kolekcji, brak metody w adapterze) **teraz throwują `ConfigValidationError` na starcie**. Najczęstsze przypadki + fix:\n - **Duplicate slug**: dwie kolekcje/singles/forms z tym samym `slug` → unique slug per kategoria.\n - **Invalid language code**: `code: \'ENGLISH\'` → `code: \'en\'` (ISO-639-1, opcjonalnie z regionem `\'pl-PL\'`).\n - **Multiple default locales**: dwa `{ default: true }` → tylko jeden.\n - **Missing adapter method**: stub adaptera bez `getEntries` etc. → zaimportuj pełen `pg()` / `local()` lub doimplementuj brakujące metody.\n - **Invalid relation target**: `{ type: \'relation\', collection: \'authors\' }` przy braku kolekcji `authors` → dodaj kolekcję lub popraw target.',
21
+ '**Resolver / operation error format** — błędy z `resolveEntry` / `resolveEntries` / `countEntries` / `createEntryVersion` / `updateEntryVersion` / `createFormSubmission` rzucają teraz `CmsError` (extends `Error`). `error.message` zachowuje stary opis (przy `toString()` poprzedzony `[CODE]`) — string-matching `error.message === \'Entry not found\'` może się rozjechać. **Migracja:**\n ```ts\n import { CmsError } from \'includio-cms\';\n\n try { await resolveEntry({ id }); }\n catch (e) {\n if (e instanceof CmsError && e.code === \'ENTRY_NOT_FOUND\') { ... }\n }\n ```',
22
+ '**`.env.example` reformatted** — `DEMO_USER_EMAIL`, `DEMO_USER_PASSWORD`, `DEMO_RESET_KEY` usunięte (były tylko dla wewnętrznego demo skasowanego w Fazie 1). Jeśli polegałeś na nich → trzymaj w lokalnym `.env`, nie w `.env.example`.'
23
+ ],
24
+ notes: `## Czytelność błędów config
25
+
26
+ Po update — invalid config wyrzuci na starcie:
27
+
28
+ \`\`\`
29
+ ConfigValidationError: CMSConfig validation failed (2 issues):
30
+ - languages[0]: must be a 2-letter ISO code (e.g. 'en' or 'pl-PL')
31
+ - collections[1].slug: duplicate collection slug 'posts' — Hint: each collection/single/form must have a unique \`slug\`
32
+ \`\`\`
33
+
34
+ Każdy issue ma \`path\` (JS-notation: \`collections[1].slug\`, \`apiKeys[0].permissions[2]\`) i \`message\`. Tam gdzie da się rozsądnie zgadnąć, dochodzi \`Hint:\` z fix-suggestion.
35
+
36
+ ## Pattern: branchowanie po error code
37
+
38
+ Stary kod string-matchujący po \`error.message\` musi się przepisać:
39
+
40
+ \`\`\`ts
41
+ // PRZED
42
+ catch (e) {
43
+ if ((e as Error).message === 'Entry not found') { /* 404 */ }
44
+ }
45
+
46
+ // PO
47
+ import { CmsError } from 'includio-cms';
48
+ catch (e) {
49
+ if (e instanceof CmsError && e.code === 'ENTRY_NOT_FOUND') { /* 404 */ }
50
+ }
51
+ \`\`\`
52
+
53
+ Dostępne kody w v0.22.0: \`ENTRY_NOT_FOUND\`, \`ENTRY_VERSION_NOT_FOUND\`, \`INVALID_DATA\`, \`MISSING_REQUIRED_PARAM\`, \`CONFIG_VALIDATION_FAILED\`.
54
+
55
+ ## Nowe envy (opt-in)
56
+
57
+ Skopiuj \`node_modules/includio-cms/.env.example\` do swojego \`.env\` — domyślne wartości działają OOTB:
58
+
59
+ - \`INCLUDIO_SHARP_TIMEOUT_MS\` (default 30000)
60
+ - \`INCLUDIO_RATE_LIMIT_MAX\` / \`INCLUDIO_RATE_LIMIT_WINDOW_MS\` (default 200/60000)
61
+ - \`INCLUDIO_FORM_RATE_LIMIT_MAX\` / \`INCLUDIO_FORM_RATE_LIMIT_WINDOW_MS\` (default 5/3600000)
62
+ - \`INCLUDIO_CSRF_ALLOWED_ORIGINS\` (default: same-origin only)
63
+
64
+ ## CLI helpy
65
+
66
+ \`\`\`bash
67
+ includio --help
68
+ includio scaffold admin --help
69
+ includio install-peers --help
70
+ includio create-user --help
71
+ includio --version
72
+ \`\`\`
73
+
74
+ Brak SQL migration.`
75
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,21 @@
1
+ export const update = {
2
+ version: '0.23.0',
3
+ date: '2026-04-30',
4
+ description: 'Faza 10 — Documentation Pass. DOCS.md uzupełniony (REST cURL + error codes, Entries error handling + transaction patterns, Admin UI a11y guide, Adapter Contracts z interfaces + peer deps + lazy import, Shop retry-payment lifecycle, edge cases dla number/boolean/date/datetime). Nowe sekcje: Stability Promise (semver, @public/@experimental/@internal, deprecation timeline) i Security Model (CSRF, CSP, rate-limit, API keys, link do KNOWN-RISKS.md). Migration Guide rozszerzony o master cheatsheet 0.x → 1.0 (agregat 0.16-0.22). ROADMAP cleanup: pre-v1.0 historia → ROADMAP-ARCHIVE.md.',
5
+ features: [
6
+ '`docs/stability-promise/` — nowa strona: SemVer 2.0, JSDoc tagi (@public semver-protected, @experimental opt-in to change, @internal poza kontraktem), deprecation timeline (1 minor cycle z @deprecated → remove w MAJOR), reference do `API.md` jako single source of truth public surface.',
7
+ '`docs/security/` — nowa strona: threat model in/out of scope, CSRF (Origin/Referer guard na `/admin/api/*`), CSP (`default-src self`, `unsafe-inline` na script/style + uzasadnienie TipTap/Paraglide), rate limiting (200/60s admin, 5/h forms, env override), API keys (opt-in `expiresAt`, audit `rotatedAt`, `generateApiKey()`), Sharp 30s timeout, link do `KNOWN-RISKS.md` (5 zaakceptowanych ryzyk).',
8
+ '`docs/migration/` — sekcja "Migrating from 0.x to 1.0 — master cheatsheet": global find-replace (getEntry → resolveEntry, language → locale), per-version blocks dla 0.16.0, 0.18.0, 0.19.0, 0.20.0, 0.21.0, 0.22.0 z migration steps + code examples, suggested upgrade path (pnpm + check + db:push + test).',
9
+ '`docs/adapters/` — sekcja "Adapter contracts": tabela 4 interfaces (DatabaseAdapter 38 metod, FilesAdapter 5+3 optional, EmailAdapter 1+config, AIAdapter 1) z source paths, peer deps required vs optional, lazy import pattern (przykład `email-nodemailer`), error contracts, best practices (timeouts, retry, partial state).',
10
+ '`docs/api/` — REST cURL examples (GET/POST/PUT/DELETE, upload), tabela error responses (HTTP × `CmsError.code`: UNAUTHORIZED, ENTRY_NOT_FOUND, INVALID_DATA, MISSING_REQUIRED_PARAM, RATE_LIMITED, etc.), authentication (Bearer header), opt-in `expiresAt` w API keys. Remote Functions section zaktualizowana na `resolveEntry/resolveEntries/countEntries`.',
11
+ '`docs/entries/` — sekcja "Error handling" (CmsError instanceof + stable codes), sekcja "Transaction patterns" (last-write-wins versioning, custom Drizzle tx z `cms.db.driver`, plugin hooks vs partial failure). Querying przepisany na `resolveEntry/resolveEntries/countEntries` (status enum: published/draft/scheduled, archived = ops nie status).',
12
+ '`docs/admin-ui/` — sekcja "Accessibility": WCAG 2.1 AA targets per surface (color contrast, keyboard nav, focus management, skip-link, heading hierarchy, ARIA roles, reduced motion), pattern dla custom plugin panels.',
13
+ '`docs/shop/retry-payment/` — pełen lifecycle (5 kroków + ASCII diagram), server endpoint scaffold, headless SDK + `createOrderState`, error responses (400/401/404/409/429/502 z `CmsError.code`), constraints (same totals, token-gated, rate-limited, idempotent gateway, no auto-retry), admin override.',
14
+ '`docs/fields/{number,boolean,date,datetime}/` — sekcje "Edge cases": number (NaN/Infinity rejection, floating-point precision, integer-only via step:1, parseFloat guards), boolean (null vs false, no string coercion, defaultValue vs runtime backfill), date (no timezone, ISO-8601 calendar string, null handling, edge years), datetime (UTC storage + local render, DST traps, ISO datetime validation).',
15
+ '`ROADMAP-ARCHIVE.md` (root) — pełna historia 0.0.69 → 0.16.0 wycięta z `ROADMAP.md`. `ROADMAP.md` zawiera od teraz wyłącznie v1.0+ (header + legenda + v1.0 + v1.x + Security + Backlog), z linkiem do archive.',
16
+ '`_config/nav.ts` + `scripts/compile-docs.ts` — zsynchronizowane: dodane "Stability Promise" w Guides, "Security Model" w "Authentication & Security" (renamed z "Authentication"). Brakujący "InPost Carrier" w nav.ts dodany dla parity z compile-docs.'
17
+ ],
18
+ fixes: [],
19
+ breakingChanges: [],
20
+ notes: 'Brak code changes — only docs + ROADMAP cleanup. DOCS.md regeneruje się przez `pnpm docs:compile` (część `prepublishOnly`). Po publikacji pełen TOC widoczny w DOCS.md z 10 zaktualizowanymi/nowymi sekcjami. Dla user-facing changes — żadnych. Dla devów customizujących admin UI lub piszących adaptery — pełny stable contract w jednym miejscu.'
21
+ };
@@ -55,7 +55,9 @@ import { update as update0180 } from './0.18.0/index.js';
55
55
  import { update as update0190 } from './0.19.0/index.js';
56
56
  import { update as update0200 } from './0.20.0/index.js';
57
57
  import { update as update0210 } from './0.21.0/index.js';
58
- 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, update0132, update0133, update0134, update0140, update0141, update0142, update0143, update0144, update0145, update0146, update0150, update0151, update0152, update0153, update0154, update0155, update0160, update0180, update0190, update0200, update0210];
58
+ import { update as update0220 } from './0.22.0/index.js';
59
+ import { update as update0230 } from './0.23.0/index.js';
60
+ 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, update0132, update0133, update0134, update0140, update0141, update0142, update0143, update0144, update0145, update0146, update0150, update0151, update0152, update0153, update0154, update0155, update0160, update0180, update0190, update0200, update0210, update0220, update0230];
59
61
  export const getUpdatesFrom = (fromVersion) => {
60
62
  const fromParts = fromVersion.split('.').map(Number);
61
63
  return updates.filter((update) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.21.0",
3
+ "version": "0.23.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -24,6 +24,9 @@
24
24
  "db:test:up": "docker compose --profile test up -d db_test",
25
25
  "db:test:down": "docker compose --profile test down db_test",
26
26
  "db:test:migrate": "DATABASE_URL=postgres://root:mysecretpassword@localhost:5434/test drizzle-kit push --force",
27
+ "db:e2e:up": "docker compose --profile test up -d db_test_e2e",
28
+ "db:e2e:down": "docker compose --profile test down db_test_e2e",
29
+ "db:e2e:migrate": "DATABASE_URL=postgres://root:mysecretpassword@localhost:5435/test_e2e drizzle-kit push --force",
27
30
  "storybook": "storybook dev -p 6006",
28
31
  "build-storybook": "storybook build",
29
32
  "create:user": "tsx cli/addUser/index.ts",
@@ -1,5 +0,0 @@
1
- export const hello_world: (inputs: {
2
- name: NonNullable<unknown>;
3
- }) => string;
4
- export const login_hello: (inputs: {}) => string;
5
- export const login_please_login: (inputs: {}) => string;
@@ -1,14 +0,0 @@
1
- /* eslint-disable */
2
-
3
-
4
- export const hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
5
- return `Hello, ${i.name} from en!`
6
- };
7
-
8
- export const login_hello = /** @type {(inputs: {}) => string} */ () => {
9
- return `Welcome back`
10
- };
11
-
12
- export const login_please_login = /** @type {(inputs: {}) => string} */ () => {
13
- return `Login to your account`
14
- };
@@ -1,5 +0,0 @@
1
- export const hello_world: (inputs: {
2
- name: NonNullable<unknown>;
3
- }) => string;
4
- export const login_hello: (inputs: {}) => string;
5
- export const login_please_login: (inputs: {}) => string;
@@ -1,14 +0,0 @@
1
- /* eslint-disable */
2
-
3
-
4
- export const hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
5
- return `Hello, ${i.name} from pl!`
6
- };
7
-
8
- export const login_hello = /** @type {(inputs: {}) => string} */ () => {
9
- return `Witaj ponownie`
10
- };
11
-
12
- export const login_please_login = /** @type {(inputs: {}) => string} */ () => {
13
- return `Zaloguj się na swoje konto`
14
- };