includio-cms 0.37.1 → 0.37.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.
Files changed (75) hide show
  1. package/API.md +54 -4
  2. package/CHANGELOG.md +19 -0
  3. package/DOCS.md +1 -1
  4. package/ROADMAP.md +19 -0
  5. package/dist/admin/remote/booking.remote.js +1 -1
  6. package/dist/booking/payment-amount.d.ts +23 -0
  7. package/dist/booking/payment-amount.js +37 -0
  8. package/dist/booking/server/http/portal-handler.js +2 -1
  9. package/dist/booking/server/payments.d.ts +14 -4
  10. package/dist/booking/server/payments.js +11 -5
  11. package/dist/booking/server/portal.d.ts +5 -2
  12. package/dist/booking/server/portal.js +10 -4
  13. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  14. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  15. package/dist/core/cms.d.ts +4 -1
  16. package/dist/core/cms.js +9 -2
  17. package/dist/core/fields/jsonLd/builders.d.ts +74 -0
  18. package/dist/core/fields/jsonLd/builders.js +88 -0
  19. package/dist/core/fields/jsonLd/graph.d.ts +15 -0
  20. package/dist/core/fields/jsonLd/graph.js +43 -0
  21. package/dist/core/fields/jsonLd/index.d.ts +2 -0
  22. package/dist/core/fields/jsonLd/index.js +2 -0
  23. package/dist/core/fields/resolveSeo.d.ts +1 -1
  24. package/dist/core/fields/resolveSeo.js +1 -1
  25. package/dist/core/fields/slugPath.d.ts +1 -1
  26. package/dist/core/fields/slugPath.js +3 -2
  27. package/dist/core/fields/slugifyFilename.d.ts +7 -0
  28. package/dist/core/fields/slugifyFilename.js +14 -0
  29. package/dist/core/i18n/localeUrl.d.ts +20 -0
  30. package/dist/core/i18n/localeUrl.js +36 -0
  31. package/dist/core/index.d.ts +2 -0
  32. package/dist/core/index.js +3 -0
  33. package/dist/core/server/entries/operations/get.js +1 -1
  34. package/dist/core/server/entries/operations/resolveEntry.js +1 -1
  35. package/dist/core/server/fields/resolveRelationFields.js +1 -1
  36. package/dist/core/server/fields/resolveRichtextLinks.js +1 -1
  37. package/dist/core/server/fields/resolveUrlFields.js +1 -1
  38. package/dist/core/server/fields/slugResolver.d.ts +2 -2
  39. package/dist/core/server/fields/slugResolver.js +12 -4
  40. package/dist/core/server/fields/utils/fixOrphans.d.ts +15 -3
  41. package/dist/core/server/fields/utils/fixOrphans.js +30 -7
  42. package/dist/core/server/generator/generator.js +60 -1
  43. package/dist/files-local/index.js +5 -5
  44. package/dist/paraglide/messages/_index.d.ts +3 -36
  45. package/dist/paraglide/messages/_index.js +3 -71
  46. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  47. package/dist/paraglide/messages/hello_world.js +33 -0
  48. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  49. package/dist/paraglide/messages/login_hello.js +34 -0
  50. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  51. package/dist/paraglide/messages/login_please_login.js +34 -0
  52. package/dist/sveltekit/components/json-ld.svelte +12 -0
  53. package/dist/sveltekit/components/json-ld.svelte.d.ts +6 -0
  54. package/dist/sveltekit/components/seo.svelte +62 -11
  55. package/dist/sveltekit/components/seo.svelte.d.ts +10 -0
  56. package/dist/sveltekit/index.d.ts +2 -0
  57. package/dist/sveltekit/index.js +2 -0
  58. package/dist/sveltekit/server/handle.js +5 -5
  59. package/dist/sveltekit/server/index.d.ts +1 -0
  60. package/dist/sveltekit/server/index.js +2 -0
  61. package/dist/sveltekit/server/sitemap.d.ts +19 -0
  62. package/dist/sveltekit/server/sitemap.js +43 -0
  63. package/dist/types/cms.d.ts +3 -2
  64. package/dist/types/cms.schema.d.ts +10 -0
  65. package/dist/types/cms.schema.js +7 -1
  66. package/dist/types/languages.d.ts +13 -0
  67. package/dist/types/languages.js +2 -1
  68. package/dist/updates/0.37.2/index.d.ts +2 -0
  69. package/dist/updates/0.37.2/index.js +20 -0
  70. package/dist/updates/index.js +3 -1
  71. package/package.json +1 -1
  72. package/dist/paraglide/messages/en.d.ts +0 -5
  73. package/dist/paraglide/messages/en.js +0 -14
  74. package/dist/paraglide/messages/pl.d.ts +0 -5
  75. package/dist/paraglide/messages/pl.js +0 -14
@@ -1,72 +1,4 @@
1
1
  /* eslint-disable */
2
- import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from "../runtime.js"
3
- import * as en from "./en.js"
4
- import * as pl from "./pl.js"
5
- /**
6
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
7
- *
8
- * - Changing this function will be over-written by the next build.
9
- *
10
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
11
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
12
- *
13
- * @param {{ name: NonNullable<unknown> }} inputs
14
- * @param {{ locale?: "en" | "pl" }} options
15
- * @returns {string}
16
- */
17
- /* @__NO_SIDE_EFFECTS__ */
18
- export const hello_world = (inputs, options = {}) => {
19
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
20
- return /** @type {any} */ (globalThis).__paraglide_ssr.hello_world(inputs)
21
- }
22
- const locale = options.locale ?? getLocale()
23
- trackMessageCall("hello_world", locale)
24
- if (locale === "en") return en.hello_world(inputs)
25
- return pl.hello_world(inputs)
26
- };
27
- /**
28
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
29
- *
30
- * - Changing this function will be over-written by the next build.
31
- *
32
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
33
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
34
- *
35
- * @param {{}} inputs
36
- * @param {{ locale?: "en" | "pl" }} options
37
- * @returns {string}
38
- */
39
- /* @__NO_SIDE_EFFECTS__ */
40
- const login_hello = (inputs = {}, options = {}) => {
41
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
42
- return /** @type {any} */ (globalThis).__paraglide_ssr.login_hello(inputs)
43
- }
44
- const locale = options.locale ?? getLocale()
45
- trackMessageCall("login_hello", locale)
46
- if (locale === "en") return en.login_hello(inputs)
47
- return pl.login_hello(inputs)
48
- };
49
- export { login_hello as "login.hello" }
50
- /**
51
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
52
- *
53
- * - Changing this function will be over-written by the next build.
54
- *
55
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
56
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
57
- *
58
- * @param {{}} inputs
59
- * @param {{ locale?: "en" | "pl" }} options
60
- * @returns {string}
61
- */
62
- /* @__NO_SIDE_EFFECTS__ */
63
- const login_please_login = (inputs = {}, options = {}) => {
64
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
65
- return /** @type {any} */ (globalThis).__paraglide_ssr.login_please_login(inputs)
66
- }
67
- const locale = options.locale ?? getLocale()
68
- trackMessageCall("login_please_login", locale)
69
- if (locale === "en") return en.login_please_login(inputs)
70
- return pl.login_please_login(inputs)
71
- };
72
- export { login_please_login as "login.please_login" }
2
+ export * from './hello_world.js'
3
+ export * from './login_hello.js'
4
+ export * from './login_please_login.js'
@@ -0,0 +1,5 @@
1
+ export function hello_world(inputs: {
2
+ name: NonNullable<unknown>;
3
+ }, options?: {
4
+ locale?: "en" | "pl";
5
+ }): string;
@@ -0,0 +1,33 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+
4
+ const en_hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
5
+ return `Hello, ${i.name} from en!`
6
+ };
7
+
8
+ const pl_hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
9
+ return `Hello, ${i.name} from pl!`
10
+ };
11
+
12
+ /**
13
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
+ *
15
+ * - Changing this function will be over-written by the next build.
16
+ *
17
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
+ *
20
+ * @param {{ name: NonNullable<unknown> }} inputs
21
+ * @param {{ locale?: "en" | "pl" }} options
22
+ * @returns {string}
23
+ */
24
+ /* @__NO_SIDE_EFFECTS__ */
25
+ export const hello_world = (inputs, options = {}) => {
26
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
+ return /** @type {any} */ (globalThis).__paraglide_ssr.hello_world(inputs)
28
+ }
29
+ const locale = options.locale ?? getLocale()
30
+ trackMessageCall("hello_world", locale)
31
+ if (locale === "en") return en_hello_world(inputs)
32
+ return pl_hello_world(inputs)
33
+ };
@@ -0,0 +1,16 @@
1
+ export { login_hello as login.hello };
2
+ /**
3
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
4
+ *
5
+ * - Changing this function will be over-written by the next build.
6
+ *
7
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
8
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
9
+ *
10
+ * @param {{}} inputs
11
+ * @param {{ locale?: "en" | "pl" }} options
12
+ * @returns {string}
13
+ */
14
+ declare function login_hello(inputs?: {}, options?: {
15
+ locale?: "en" | "pl";
16
+ }): string;
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+
4
+ const en_login_hello = /** @type {(inputs: {}) => string} */ () => {
5
+ return `Welcome back`
6
+ };
7
+
8
+ const pl_login_hello = /** @type {(inputs: {}) => string} */ () => {
9
+ return `Witaj ponownie`
10
+ };
11
+
12
+ /**
13
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
+ *
15
+ * - Changing this function will be over-written by the next build.
16
+ *
17
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
+ *
20
+ * @param {{}} inputs
21
+ * @param {{ locale?: "en" | "pl" }} options
22
+ * @returns {string}
23
+ */
24
+ /* @__NO_SIDE_EFFECTS__ */
25
+ const login_hello = (inputs = {}, options = {}) => {
26
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
+ return /** @type {any} */ (globalThis).__paraglide_ssr.login_hello(inputs)
28
+ }
29
+ const locale = options.locale ?? getLocale()
30
+ trackMessageCall("login_hello", locale)
31
+ if (locale === "en") return en_login_hello(inputs)
32
+ return pl_login_hello(inputs)
33
+ };
34
+ export { login_hello as "login.hello" }
@@ -0,0 +1,16 @@
1
+ export { login_please_login as login.please_login };
2
+ /**
3
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
4
+ *
5
+ * - Changing this function will be over-written by the next build.
6
+ *
7
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
8
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
9
+ *
10
+ * @param {{}} inputs
11
+ * @param {{ locale?: "en" | "pl" }} options
12
+ * @returns {string}
13
+ */
14
+ declare function login_please_login(inputs?: {}, options?: {
15
+ locale?: "en" | "pl";
16
+ }): string;
@@ -0,0 +1,34 @@
1
+ /* eslint-disable */
2
+ import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
+
4
+ const en_login_please_login = /** @type {(inputs: {}) => string} */ () => {
5
+ return `Login to your account`
6
+ };
7
+
8
+ const pl_login_please_login = /** @type {(inputs: {}) => string} */ () => {
9
+ return `Zaloguj się na swoje konto`
10
+ };
11
+
12
+ /**
13
+ * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
+ *
15
+ * - Changing this function will be over-written by the next build.
16
+ *
17
+ * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
+ * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
+ *
20
+ * @param {{}} inputs
21
+ * @param {{ locale?: "en" | "pl" }} options
22
+ * @returns {string}
23
+ */
24
+ /* @__NO_SIDE_EFFECTS__ */
25
+ const login_please_login = (inputs = {}, options = {}) => {
26
+ if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
+ return /** @type {any} */ (globalThis).__paraglide_ssr.login_please_login(inputs)
28
+ }
29
+ const locale = options.locale ?? getLocale()
30
+ trackMessageCall("login_please_login", locale)
31
+ if (locale === "en") return en_login_please_login(inputs)
32
+ return pl_login_please_login(inputs)
33
+ };
34
+ export { login_please_login as "login.please_login" }
@@ -0,0 +1,12 @@
1
+ <script lang="ts">
2
+ /** Wstrzykuje blok schema.org JSON-LD do <head>. `data` = obiekt lub tablica (np. z jsonLdGraph). */
3
+ let { data }: { data: unknown } = $props();
4
+ // Escape `<` → <: breakout ze <script> niemożliwy. Dane pochodzą od dewelopera (schema.org), nie od usera.
5
+ const json = $derived(JSON.stringify(data).replaceAll('<', '\\u003c'));
6
+ </script>
7
+
8
+ <svelte:head>
9
+ <!-- Bezpieczne: `<` w danych zescapowane, `<\/script>` chroni źródło przed wczesnym zamknięciem tagu. -->
10
+ <!-- eslint-disable-next-line svelte/no-at-html-tags, no-useless-escape -->
11
+ {@html `<script type="application/ld+json">${json}<\/script>`}
12
+ </svelte:head>
@@ -0,0 +1,6 @@
1
+ type $$ComponentProps = {
2
+ data: unknown;
3
+ };
4
+ declare const JsonLd: import("svelte").Component<$$ComponentProps, {}, "">;
5
+ type JsonLd = ReturnType<typeof JsonLd>;
6
+ export default JsonLd;
@@ -8,9 +8,33 @@
8
8
  keywords?: string;
9
9
  ogImage?: MediaFile | string;
10
10
  canonicalUrl?: string;
11
+ ogType?: string;
12
+ noindex?: boolean;
13
+ siteName?: string;
14
+ article?: {
15
+ publishedTime?: string;
16
+ modifiedTime?: string;
17
+ author?: string;
18
+ section?: string;
19
+ tags?: string[];
20
+ };
11
21
  };
12
22
 
13
- let { title, description, keywords, ogImage, canonicalUrl }: Props = $props();
23
+ let {
24
+ title,
25
+ description,
26
+ keywords,
27
+ ogImage,
28
+ canonicalUrl,
29
+ ogType = 'website',
30
+ noindex = false,
31
+ siteName,
32
+ article
33
+ }: Props = $props();
34
+
35
+ const url = $derived(canonicalUrl ?? page.url.toString());
36
+ const imageUrl = $derived(ogImage ? (typeof ogImage === 'string' ? ogImage : ogImage.url) : undefined);
37
+ const imageMeta = $derived(ogImage && typeof ogImage !== 'string' ? ogImage : undefined);
14
38
  </script>
15
39
 
16
40
  <svelte:head>
@@ -20,10 +44,13 @@
20
44
  <meta property="og:title" content={title} />
21
45
  <meta name="twitter:title" content={title} />
22
46
  {/if}
23
- <meta name="og:url" content={canonicalUrl ?? page.url.toString()} />
24
- <meta name="og:type" content="website" />
47
+ <meta property="og:url" content={url} />
48
+ <meta property="og:type" content={ogType} />
49
+ {#if siteName}
50
+ <meta property="og:site_name" content={siteName} />
51
+ {/if}
25
52
  <meta property="twitter:domain" content={page.url.hostname} />
26
- <meta property="twitter:url" content={canonicalUrl ?? page.url.toString()} />
53
+ <meta property="twitter:url" content={url} />
27
54
  {#if description}
28
55
  <meta name="description" content={description} />
29
56
  <meta property="og:description" content={description} />
@@ -32,17 +59,41 @@
32
59
  {#if keywords}
33
60
  <meta name="keywords" content={keywords} />
34
61
  {/if}
62
+ {#if noindex}
63
+ <meta name="robots" content="noindex" />
64
+ {/if}
35
65
  {#if canonicalUrl}
36
66
  <link rel="canonical" href={canonicalUrl} />
37
67
  {/if}
38
- {#if ogImage}
39
- {#if typeof ogImage === 'string'}
40
- <meta property="og:image" content={ogImage} />
41
- <meta name="twitter:image" content={ogImage} />
42
- {:else}
43
- <meta property="og:image" content={ogImage.url} />
44
- <meta name="twitter:image" content={ogImage.url} />
68
+ {#if imageUrl}
69
+ <meta property="og:image" content={imageUrl} />
70
+ <meta name="twitter:image" content={imageUrl} />
71
+ {#if imageMeta?.width}
72
+ <meta property="og:image:width" content={String(imageMeta.width)} />
73
+ {/if}
74
+ {#if imageMeta?.height}
75
+ <meta property="og:image:height" content={String(imageMeta.height)} />
76
+ {/if}
77
+ {#if imageMeta?.alt}
78
+ <meta property="og:image:alt" content={imageMeta.alt} />
45
79
  {/if}
46
80
  <meta name="twitter:card" content="summary_large_image" />
47
81
  {/if}
82
+ {#if ogType === 'article' && article}
83
+ {#if article.publishedTime}
84
+ <meta property="article:published_time" content={article.publishedTime} />
85
+ {/if}
86
+ {#if article.modifiedTime}
87
+ <meta property="article:modified_time" content={article.modifiedTime} />
88
+ {/if}
89
+ {#if article.author}
90
+ <meta property="article:author" content={article.author} />
91
+ {/if}
92
+ {#if article.section}
93
+ <meta property="article:section" content={article.section} />
94
+ {/if}
95
+ {#each article.tags ?? [] as tag, i (i)}
96
+ <meta property="article:tag" content={tag} />
97
+ {/each}
98
+ {/if}
48
99
  </svelte:head>
@@ -5,6 +5,16 @@ type Props = {
5
5
  keywords?: string;
6
6
  ogImage?: MediaFile | string;
7
7
  canonicalUrl?: string;
8
+ ogType?: string;
9
+ noindex?: boolean;
10
+ siteName?: string;
11
+ article?: {
12
+ publishedTime?: string;
13
+ modifiedTime?: string;
14
+ author?: string;
15
+ section?: string;
16
+ tags?: string[];
17
+ };
8
18
  };
9
19
  declare const Seo: import("svelte").Component<Props, {}, "">;
10
20
  type Seo = ReturnType<typeof Seo>;
@@ -8,6 +8,8 @@ export { default as Video } from './components/video.svelte';
8
8
  export { default as CmsProvider } from './components/cms-provider.svelte';
9
9
  export { default as Media } from './components/media.svelte';
10
10
  export { default as StructuredContent } from './components/structured-content.svelte';
11
+ export { default as JsonLd } from './components/json-ld.svelte';
12
+ export { default as Seo } from './components/seo.svelte';
11
13
  export { enableHybridEditing } from './components/hybrid-context.js';
12
14
  export { setPreferMp4 } from './components/video-context.js';
13
15
  export { getLink, isImageFieldData, isVideoFieldData } from './utils/index.js';
@@ -8,6 +8,8 @@ export { default as Video } from './components/video.svelte';
8
8
  export { default as CmsProvider } from './components/cms-provider.svelte';
9
9
  export { default as Media } from './components/media.svelte';
10
10
  export { default as StructuredContent } from './components/structured-content.svelte';
11
+ export { default as JsonLd } from './components/json-ld.svelte';
12
+ export { default as Seo } from './components/seo.svelte';
11
13
  export { enableHybridEditing } from './components/hybrid-context.js';
12
14
  export { setPreferMp4 } from './components/video-context.js';
13
15
  export { getLink, isImageFieldData, isVideoFieldData } from './utils/index.js';
@@ -7,7 +7,8 @@ import { building } from '$app/environment';
7
7
  import { csrfGuard } from '../../server/security/csrf.js';
8
8
  import { rateLimitGuard } from '../../server/security/rate-limit.js';
9
9
  import { buildCspHeader } from '../../server/security/csp.js';
10
- import { baseLocale, extractLocaleFromRequest, isLocale } from '../../paraglide/runtime.js';
10
+ import { baseLocale } from '../../paraglide/runtime.js';
11
+ import { localeFromPath } from '../../core/i18n/localeUrl.js';
11
12
  const adminGuard = async ({ event, resolve }) => {
12
13
  const { user, session } = event.locals;
13
14
  // Secure the admin routes
@@ -62,12 +63,11 @@ const handleAuth = async ({ event, resolve }) => {
62
63
  return svelteKitHandler({ event, resolve, auth, building });
63
64
  };
64
65
  const paraglideLang = async ({ event, resolve }) => {
66
+ // Locale storefrontu z URL (prefiks z cms.config.languages), config-driven, bez cookie.
67
+ // Trasy bez prefiksu (np. /admin) → defaultLocale.
65
68
  let locale = baseLocale;
66
69
  try {
67
- const detected = extractLocaleFromRequest(event.request);
68
- if (detected && isLocale(detected)) {
69
- locale = detected;
70
- }
70
+ locale = localeFromPath(getCMS().localeUrl, event.url.pathname);
71
71
  }
72
72
  catch {
73
73
  // fall back to baseLocale
@@ -10,3 +10,4 @@ export { createRestApiHandler } from '../../admin/api/rest/handler.js';
10
10
  export { generateApiKey } from '../../admin/api/rest/middleware/generateApiKey.js';
11
11
  export { createAdminApiHandler } from '../../admin/api/handler.js';
12
12
  export { extractBlocks, extractInlineBlocks, extractText, extractMediaRefs } from '../../core/server/fields/queryStructuredContent.js';
13
+ export { buildSitemap, buildRobots, type SitemapEntry, type RobotsRule, type RobotsOptions } from './sitemap.js';
@@ -14,3 +14,5 @@ export { generateApiKey } from '../../admin/api/rest/middleware/generateApiKey.j
14
14
  // Folded from `./admin/api/handler` (dropped as separate export in 0.26.1)
15
15
  export { createAdminApiHandler } from '../../admin/api/handler.js';
16
16
  export { extractBlocks, extractInlineBlocks, extractText, extractMediaRefs } from '../../core/server/fields/queryStructuredContent.js';
17
+ // SEO: sitemap.xml / robots.txt builders — pure, projekt posiada route.
18
+ export { buildSitemap, buildRobots } from './sitemap.js';
@@ -0,0 +1,19 @@
1
+ export interface SitemapEntry {
2
+ url: string;
3
+ lastmod?: string | Date;
4
+ changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
5
+ priority?: number;
6
+ }
7
+ /** Build a sitemap.xml document from a list of URL entries. */
8
+ export declare function buildSitemap(entries: SitemapEntry[]): string;
9
+ export interface RobotsRule {
10
+ userAgent?: string;
11
+ allow?: string[];
12
+ disallow?: string[];
13
+ }
14
+ export interface RobotsOptions {
15
+ sitemapUrl?: string;
16
+ rules?: RobotsRule[];
17
+ }
18
+ /** Build a robots.txt document. Defaults to allow-all + optional sitemap link. */
19
+ export declare function buildRobots(options?: RobotsOptions): string;
@@ -0,0 +1,43 @@
1
+ function escapeXml(s) {
2
+ return s
3
+ .replace(/&/g, '&amp;')
4
+ .replace(/</g, '&lt;')
5
+ .replace(/>/g, '&gt;')
6
+ .replace(/"/g, '&quot;')
7
+ .replace(/'/g, '&apos;');
8
+ }
9
+ function formatLastmod(v) {
10
+ return v instanceof Date ? v.toISOString() : v;
11
+ }
12
+ /** Build a sitemap.xml document from a list of URL entries. */
13
+ export function buildSitemap(entries) {
14
+ const urls = entries
15
+ .map((e) => {
16
+ const parts = [` <loc>${escapeXml(e.url)}</loc>`];
17
+ if (e.lastmod !== undefined)
18
+ parts.push(` <lastmod>${escapeXml(formatLastmod(e.lastmod))}</lastmod>`);
19
+ if (e.changefreq)
20
+ parts.push(` <changefreq>${e.changefreq}</changefreq>`);
21
+ if (e.priority !== undefined)
22
+ parts.push(` <priority>${e.priority.toFixed(1)}</priority>`);
23
+ return ` <url>\n${parts.join('\n')}\n </url>`;
24
+ })
25
+ .join('\n');
26
+ return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${urls ? '\n' + urls + '\n' : ''}</urlset>`;
27
+ }
28
+ /** Build a robots.txt document. Defaults to allow-all + optional sitemap link. */
29
+ export function buildRobots(options = {}) {
30
+ const rules = options.rules && options.rules.length > 0 ? options.rules : [{ userAgent: '*', allow: ['/'] }];
31
+ const blocks = rules.map((r) => {
32
+ const lines = [`User-agent: ${r.userAgent ?? '*'}`];
33
+ for (const a of r.allow ?? [])
34
+ lines.push(`Allow: ${a}`);
35
+ for (const d of r.disallow ?? [])
36
+ lines.push(`Disallow: ${d}`);
37
+ return lines.join('\n');
38
+ });
39
+ let out = blocks.join('\n\n');
40
+ if (options.sitemapUrl)
41
+ out += `\n\nSitemap: ${options.sitemapUrl}`;
42
+ return out + '\n';
43
+ }
@@ -1,7 +1,7 @@
1
1
  import type { DatabaseAdapter } from './adapters/db.js';
2
2
  import type { FilesAdapter } from './adapters/files.js';
3
3
  import type { CollectionConfig, CollectionConfigWithType } from './collections.js';
4
- import type { Language } from './languages.js';
4
+ import type { Language, LanguageEntry } from './languages.js';
5
5
  import type { SingleConfig, SingleConfigWithType } from './singles.js';
6
6
  import type { CustomFieldDefinition, IconSetPlugin, Plugin } from './plugins.js';
7
7
  import type { FormConfig } from './forms.js';
@@ -144,7 +144,8 @@ export interface AdminConfig {
144
144
  extraNavItems?: import('../admin/types.js').AdminNavItem[];
145
145
  }
146
146
  export interface CMSConfig {
147
- languages: Language[];
147
+ /** Kod ISO albo obiekt `{ code, default?, url? }`. Znormalizowane do kodów w `CMS.languages`. */
148
+ languages: LanguageEntry[];
148
149
  collections?: CollectionConfig[];
149
150
  singles?: SingleConfig[];
150
151
  forms?: FormConfig[];
@@ -22,6 +22,11 @@ export declare const cmsConfigSchema: z.ZodObject<{
22
22
  code: z.ZodString;
23
23
  label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
24
24
  default: z.ZodOptional<z.ZodBoolean>;
25
+ url: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
26
+ pathPrefix: z.ZodString;
27
+ }, z.core.$strip>, z.ZodObject<{
28
+ host: z.ZodString;
29
+ }, z.core.$strip>]>>;
25
30
  }, z.core.$loose>]>>;
26
31
  collections: z.ZodOptional<z.ZodArray<z.ZodObject<{
27
32
  entryAdminTitle: z.ZodOptional<z.ZodString>;
@@ -382,6 +387,11 @@ export declare const _internal: {
382
387
  code: z.ZodString;
383
388
  label: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
384
389
  default: z.ZodOptional<z.ZodBoolean>;
390
+ url: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
391
+ pathPrefix: z.ZodString;
392
+ }, z.core.$strip>, z.ZodObject<{
393
+ host: z.ZodString;
394
+ }, z.core.$strip>]>>;
385
395
  }, z.core.$loose>]>>;
386
396
  collections: z.ZodOptional<z.ZodArray<z.ZodObject<{
387
397
  entryAdminTitle: z.ZodOptional<z.ZodString>;
@@ -24,7 +24,13 @@ const languageEntrySchema = z.union([
24
24
  message: "must be a 2-letter ISO code (e.g. 'en' or 'pl-PL')"
25
25
  }),
26
26
  label: localizedSchema.optional(),
27
- default: z.boolean().optional()
27
+ default: z.boolean().optional(),
28
+ url: z
29
+ .union([
30
+ z.object({ pathPrefix: z.string().startsWith('/') }),
31
+ z.object({ host: z.string() })
32
+ ])
33
+ .optional()
28
34
  })
29
35
  .passthrough()
30
36
  ]);
@@ -1,4 +1,17 @@
1
1
  import type { locales } from '../paraglide/runtime.js';
2
2
  export type Language = 'en' | 'pl';
3
+ /** Wpis `cms.config.languages`: kod ISO albo obiekt z domyślnością/strategią URL. */
4
+ export type LanguageEntry = string | {
5
+ code: string;
6
+ label?: Localized;
7
+ default?: boolean;
8
+ url?: {
9
+ pathPrefix?: string;
10
+ } | {
11
+ host?: string;
12
+ };
13
+ };
14
+ /** Kod locale z wpisu (string lub `{ code }`). */
15
+ export declare const languageCode: (l: LanguageEntry) => string;
3
16
  export type InterfaceLanguage = (typeof locales)[number];
4
17
  export type Localized = Partial<Record<InterfaceLanguage, string>> | string;
@@ -1 +1,2 @@
1
- export {};
1
+ /** Kod locale z wpisu (string lub `{ code }`). */
2
+ export const languageCode = (l) => (typeof l === 'string' ? l : l.code);
@@ -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.37.2',
3
+ date: '2026-07-16',
4
+ description: 'Powierzchnia SEO/AEO rdzenia — reużywalne helpery, które raz naprawione w rdzeniu działają u każdego klienta (wyszły z wdrożenia SEO u pod-zwrotnikami). W tym samym patchu domyka się też łatka bezpieczeństwa bookingu (kwota płatności).',
5
+ features: [
6
+ '**Buildery JSON-LD (schema.org) w `includio-cms/core`.** Typowane, czyste funkcje: `organization`, `localBusiness`, `website`, `webPage`, `breadcrumbList`, `article`, `blogPosting`, `faqPage` + generyk `thing` i `jsonLdGraph`. Opt-in — nic nie emitują domyślnie. `undefined`/puste wartości wypadają z outputu, więc częściowe dane dają poprawny minimalny JSON-LD. Bespoke typy (np. `TouristTrip + Offer`, `Product`) składasz po stronie projektu przez `thing("TouristTrip", { ... })` — rdzeń zostaje generyczny.',
7
+ '**Komponent `<JsonLd>` w `includio-cms/sveltekit`.** Renderuje `<script type="application/ld+json">` w `<svelte:head>` (SSR), escapuje `<` → breakout ze `<script>` jest niemożliwy. Przyjmuje obiekt albo tablicę (np. wynik `jsonLdGraph`).',
8
+ '**`buildSitemap` / `buildRobots` w `includio-cms/sveltekit/server`.** Czyste buildery: `buildSitemap(entries)` → string `sitemap.xml` (URL-e XML-escaped, `lastmod` `Date`→ISO lub string, opcjonalne `changefreq`/`priority`), `buildRobots(options)` → `robots.txt` (domyślnie allow-all + link do sitemapy, konfigurowalne reguły). Projekt posiada route i wpina helper: `export const GET = async () => new Response(buildSitemap(entries), { headers: { "content-type": "application/xml" } });`.'
9
+ ],
10
+ fixes: [
11
+ '**Slugifikacja nazw plików mediów.** Upload i zmiana nazwy przepuszczają basename przez `slugifyFilename` (nowy helper w `includio-cms/core`): `"IMG-1234 (1).jpeg"` → `img-1234-1.jpeg`, polskie znaki transliterowane, spacje/wielkość/nawiasy usunięte. Tylko nowe pliki — istniejące URL-e w bazie nietknięte (bez migracji). Cap 200 znaków, path-traversal niemożliwy (slug nie zawiera `/` ani `.`).',
12
+ '**`<Seo>` dopełniony i wyeksportowany z `includio-cms/sveltekit`.** Wcześniej komponent istniał, ale nie był eksportowany (martwy). Bugfix: `og:url` i `og:type` używają `property=` zamiast `name=` (wymóg Open Graph). Nowe propsy: `ogType` (domyślnie `website`; `article` dokłada `article:published_time`/`modified_time`/`author`/`section`/`tag`), `noindex` (→ `<meta name="robots" content="noindex">`), `siteName` (→ `og:site_name`). `ogImage` typu `MediaFile` emituje `og:image:width`/`height`/`alt`.',
13
+ '**Typografia — łamanie sierot przyimkowych.** `fixOrphans` wstawia NBSP nie tylko po jednoliterowych spójnikach (`i/w/z/o/u/a/e`), ale też po krótkich przyimkach (`do na od po we za ze ku nad pod bez dla przy`). Lista konfigurowalna parametrem `words` + eksport `DEFAULT_ORPHAN_WORDS`. Domyślnie konserwatywnie (bez spójników typu `oraz/lub`), żeby nie NBSP-ować za dużo.',
14
+ '**Bezpieczeństwo (booking): kwota dopłaty przestaje pochodzić z żądania HTTP.** Domknięcie łuku 0.37.1 (cena szła z katalogu, ale kwota wpłaty — nie): `portalPay` podawał `amount` z ciała żądania prosto do `createInstallmentPayment`, bez konfrontacji z saldem — przeglądarka dyktowała kwotę (nadpłata do ręcznego zwrotu albo link na grosz). Bramka kwotowa oparta na aktorze (bliźniak bramki cenowej): `portal` NIE dyktuje (serwer obciąża `totals.balance`, fail-closed gdy brak salda), `staff` może. Portalowa wpłata zapisuje się teraz z `createdBy` aktora — nie zahardkodowanym `staff` (koniec kłamstwa w audycie).',
15
+ '**Booking: `ledger.balance` przestaje gubić rabaty.** `portalView` liczył `ledger` z `totals.gross` → `balance = gross − paid`, pomijając `discount`/`surcharge`/`manualDiscount`; portal pokazywał dwa różne salda i przycisk płatności brał gorzej policzone. Teraz `toPortalView` karmi `ledgerSummary` wartością netto (`netOf(totals)`), więc `ledger.balance === totals.balance`.'
16
+ ],
17
+ breakingChanges: [
18
+ '**`createInstallmentPayment(bookingId, amount)` → `createInstallmentPayment(bookingId, { actor, amount? })`.** `actor: "portal" | "staff"` jest wymagany. Dla `portal` kwota jest ignorowana (serwer obciąża saldo); dla `staff` podajesz `amount`. `portalPay(token, amount)` → `portalPay(token)` (kwota nie jest już parametrem). Dotyczy tylko konsumentów wołających te funkcje bezpośrednio — ścieżka przez handler portalu/remote admina zaktualizowana w rdzeniu.'
19
+ ]
20
+ };
@@ -77,6 +77,7 @@ import { update as update0368 } from './0.36.8/index.js';
77
77
  import { update as update0369 } from './0.36.9/index.js';
78
78
  import { update as update0370 } from './0.37.0/index.js';
79
79
  import { update as update0371 } from './0.37.1/index.js';
80
+ import { update as update0372 } from './0.37.2/index.js';
80
81
  export const updates = [
81
82
  update0065,
82
83
  update0066,
@@ -156,7 +157,8 @@ export const updates = [
156
157
  update0368,
157
158
  update0369,
158
159
  update0370,
159
- update0371
160
+ update0371,
161
+ update0372
160
162
  ];
161
163
  export const getUpdatesFrom = (fromVersion) => {
162
164
  const fromParts = fromVersion.split('.').map(Number);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.37.1",
3
+ "version": "0.37.3",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -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;