includio-cms 0.20.0 → 0.22.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/API.md +22 -21
- package/CHANGELOG.md +147 -0
- package/DOCS.md +1 -1
- package/README.md +138 -32
- package/ROADMAP.md +11 -4
- package/dist/admin/api/rest/handler.d.ts +13 -1
- package/dist/admin/api/rest/handler.js +13 -1
- package/dist/admin/api/rest/middleware/apiKey.js +9 -1
- package/dist/admin/api/rest/middleware/generateApiKey.d.ts +16 -0
- package/dist/admin/api/rest/middleware/generateApiKey.js +19 -0
- package/dist/admin/client/collection/collection-entries.svelte +1 -1
- package/dist/admin/client/collection/empty-state.svelte +1 -1
- package/dist/admin/client/collection/row-actions.svelte +3 -3
- package/dist/admin/client/collection/table-toolbar.svelte +3 -1
- package/dist/admin/client/entry/entry-header.svelte +3 -1
- package/dist/admin/client/users/create-user-dialog.svelte +4 -4
- package/dist/admin/client/users/delete-user-dialog.svelte +4 -2
- package/dist/admin/client/users/lang.d.ts +10 -2
- package/dist/admin/client/users/lang.js +10 -4
- package/dist/admin/client/users/users-page.svelte +3 -2
- package/dist/admin/components/media/file-upload.svelte +2 -0
- package/dist/ai-claude/index.d.ts +9 -1
- package/dist/ai-claude/index.js +9 -1
- package/dist/ai-openai/index.d.ts +9 -1
- package/dist/ai-openai/index.js +9 -1
- package/dist/cli/index.js +115 -13
- package/dist/cms/runtime/schema.d.ts +2 -0
- package/dist/cms/runtime/schema.js +4 -0
- package/dist/cms/runtime/types.d.ts +1 -1
- package/dist/core/cms.d.ts +13 -1
- package/dist/core/cms.js +13 -1
- package/dist/core/errors.d.ts +71 -0
- package/dist/core/errors.js +179 -0
- package/dist/core/server/consentLogs/operations/create.d.ts +13 -1
- package/dist/core/server/consentLogs/operations/create.js +13 -1
- package/dist/core/server/entries/operations/create.js +6 -1
- package/dist/core/server/entries/operations/get.js +14 -3
- package/dist/core/server/entries/operations/resolveEntry.d.ts +32 -1
- package/dist/core/server/entries/operations/resolveEntry.js +36 -4
- package/dist/core/server/entries/operations/update.js +5 -1
- package/dist/core/server/fields/utils/resolveMedia.d.ts +18 -1
- package/dist/core/server/fields/utils/resolveMedia.js +13 -1
- package/dist/core/server/forms/submissions/operations/create.d.ts +21 -1
- package/dist/core/server/forms/submissions/operations/create.js +18 -2
- package/dist/core/server/forms/submissions/utils/parseMultipart.d.ts +15 -1
- package/dist/core/server/forms/submissions/utils/parseMultipart.js +15 -1
- package/dist/core/server/media/operations/uploadFile.js +4 -3
- package/dist/core/server/media/styles/sharp/generateImageStyle.js +3 -2
- package/dist/core/server/media/utils/generateAdminThumbnail.js +3 -2
- package/dist/core/server/media/utils/generateBlurDataUrl.js +2 -1
- package/dist/db-postgres/index.d.ts +10 -0
- package/dist/db-postgres/index.js +10 -0
- package/dist/email-nodemailer/index.d.ts +13 -1
- package/dist/email-nodemailer/index.js +13 -1
- package/dist/entity/index.d.ts +16 -1
- package/dist/entity/index.js +16 -1
- package/dist/files-local/index.d.ts +12 -1
- package/dist/files-local/index.js +12 -1
- package/dist/paraglide/messages/_index.d.ts +3 -36
- package/dist/paraglide/messages/_index.js +3 -71
- package/dist/paraglide/messages/hello_world.d.ts +5 -0
- package/dist/paraglide/messages/hello_world.js +33 -0
- package/dist/paraglide/messages/login_hello.d.ts +16 -0
- package/dist/paraglide/messages/login_hello.js +34 -0
- package/dist/paraglide/messages/login_please_login.d.ts +16 -0
- package/dist/paraglide/messages/login_please_login.js +34 -0
- package/dist/server/auth.d.ts +11 -0
- package/dist/server/auth.js +11 -0
- package/dist/server/security/csp.d.ts +16 -0
- package/dist/server/security/csp.js +33 -0
- package/dist/server/security/csrf.d.ts +13 -0
- package/dist/server/security/csrf.js +49 -0
- package/dist/server/security/index.d.ts +3 -0
- package/dist/server/security/index.js +3 -0
- package/dist/server/security/rate-limit.d.ts +44 -0
- package/dist/server/security/rate-limit.js +97 -0
- package/dist/server/utils/withTimeout.d.ts +21 -0
- package/dist/server/utils/withTimeout.js +37 -0
- package/dist/sveltekit/config.d.ts +67 -4
- package/dist/sveltekit/config.js +73 -4
- package/dist/sveltekit/server/handle.d.ts +15 -1
- package/dist/sveltekit/server/handle.js +22 -1
- package/dist/sveltekit/server/index.d.ts +1 -0
- package/dist/sveltekit/server/index.js +1 -0
- package/dist/sveltekit/server/layout.d.ts +12 -1
- package/dist/sveltekit/server/layout.js +12 -1
- package/dist/sveltekit/server/preview.d.ts +21 -1
- package/dist/sveltekit/server/preview.js +21 -1
- package/dist/types/cms.d.ts +4 -0
- package/dist/types/cms.schema.d.ts +452 -0
- package/dist/types/cms.schema.js +629 -0
- package/dist/updates/0.21.0/index.d.ts +2 -0
- package/dist/updates/0.21.0/index.js +55 -0
- package/dist/updates/0.22.0/index.d.ts +2 -0
- package/dist/updates/0.22.0/index.js +75 -0
- package/dist/updates/index.js +3 -1
- package/package.json +12 -2
- package/dist/paraglide/messages/en.d.ts +0 -5
- package/dist/paraglide/messages/en.js +0 -14
- package/dist/paraglide/messages/pl.d.ts +0 -5
- 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
|
+
};
|
package/dist/updates/index.js
CHANGED
|
@@ -54,7 +54,9 @@ import { update as update0160 } from './0.16.0/index.js';
|
|
|
54
54
|
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
|
+
import { update as update0220 } from './0.22.0/index.js';
|
|
59
|
+
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];
|
|
58
60
|
export const getUpdatesFrom = (fromVersion) => {
|
|
59
61
|
const fromParts = fromVersion.split('.').map(Number);
|
|
60
62
|
return updates.filter((update) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "includio-cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vite dev",
|
|
6
6
|
"build": "vite build && npm run prepack",
|
|
@@ -14,10 +14,19 @@
|
|
|
14
14
|
"test:unit": "vitest",
|
|
15
15
|
"test": "npm run test:unit -- --run && npm run test:e2e",
|
|
16
16
|
"test:e2e": "playwright test",
|
|
17
|
+
"test:coverage": "vitest run --coverage",
|
|
18
|
+
"pretest:integration": "pnpm prepack",
|
|
19
|
+
"test:integration": "TEST_DATABASE_URL=postgres://root:mysecretpassword@localhost:5434/test vitest run --project=integration",
|
|
17
20
|
"db:start": "docker compose up",
|
|
18
21
|
"db:push": "drizzle-kit push",
|
|
19
22
|
"db:migrate": "drizzle-kit migrate",
|
|
20
23
|
"db:studio": "drizzle-kit studio",
|
|
24
|
+
"db:test:up": "docker compose --profile test up -d db_test",
|
|
25
|
+
"db:test:down": "docker compose --profile test down db_test",
|
|
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",
|
|
21
30
|
"storybook": "storybook dev -p 6006",
|
|
22
31
|
"build-storybook": "storybook build",
|
|
23
32
|
"create:user": "tsx cli/addUser/index.ts",
|
|
@@ -229,7 +238,8 @@
|
|
|
229
238
|
"typescript": "^5.0.0",
|
|
230
239
|
"typescript-eslint": "^8.20.0",
|
|
231
240
|
"vite": "^7.2.2",
|
|
232
|
-
"vitest": "^3.2.3"
|
|
241
|
+
"vitest": "^3.2.3",
|
|
242
|
+
"@vitest/coverage-v8": "^3.2.3"
|
|
233
243
|
},
|
|
234
244
|
"keywords": [
|
|
235
245
|
"svelte"
|
|
@@ -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,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
|
-
};
|