includio-cms 0.37.2 → 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 (36) hide show
  1. package/API.md +1 -1
  2. package/DOCS.md +1 -1
  3. package/ROADMAP.md +1 -0
  4. package/dist/core/cms.d.ts +4 -1
  5. package/dist/core/cms.js +9 -2
  6. package/dist/core/fields/slugPath.d.ts +1 -1
  7. package/dist/core/fields/slugPath.js +3 -2
  8. package/dist/core/i18n/localeUrl.d.ts +20 -0
  9. package/dist/core/i18n/localeUrl.js +36 -0
  10. package/dist/core/server/entries/operations/get.js +1 -1
  11. package/dist/core/server/entries/operations/resolveEntry.js +1 -1
  12. package/dist/core/server/fields/resolveRelationFields.js +1 -1
  13. package/dist/core/server/fields/resolveRichtextLinks.js +1 -1
  14. package/dist/core/server/fields/resolveUrlFields.js +1 -1
  15. package/dist/core/server/fields/slugResolver.d.ts +2 -2
  16. package/dist/core/server/fields/slugResolver.js +12 -4
  17. package/dist/core/server/generator/generator.js +60 -1
  18. package/dist/paraglide/messages/_index.d.ts +3 -36
  19. package/dist/paraglide/messages/_index.js +3 -71
  20. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  21. package/dist/paraglide/messages/hello_world.js +33 -0
  22. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  23. package/dist/paraglide/messages/login_hello.js +34 -0
  24. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  25. package/dist/paraglide/messages/login_please_login.js +34 -0
  26. package/dist/sveltekit/server/handle.js +5 -5
  27. package/dist/types/cms.d.ts +3 -2
  28. package/dist/types/cms.schema.d.ts +10 -0
  29. package/dist/types/cms.schema.js +7 -1
  30. package/dist/types/languages.d.ts +13 -0
  31. package/dist/types/languages.js +2 -1
  32. package/package.json +1 -1
  33. package/dist/paraglide/messages/en.d.ts +0 -5
  34. package/dist/paraglide/messages/en.js +0 -14
  35. package/dist/paraglide/messages/pl.d.ts +0 -5
  36. package/dist/paraglide/messages/pl.js +0 -14
package/API.md CHANGED
@@ -1,4 +1,4 @@
1
- # includio-cms — Public API v0.37.2
1
+ # includio-cms — Public API v0.37.3
2
2
 
3
3
  > Auto-generated by `scripts/generate-api-md.ts`. Do not edit by hand.
4
4
 
package/DOCS.md CHANGED
@@ -1,4 +1,4 @@
1
- # Includio CMS Documentation (v0.37.2)
1
+ # Includio CMS Documentation (v0.37.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
@@ -117,6 +117,7 @@ Spec: `docs/superpowers/specs/2026-07-13-moduly-kontrakt-vs-polityka-design.md`.
117
117
  - [ ] `[feature]` `[P1]` Ban/unban UI — reason + expiry, `banUser`/`unbanUser` <!-- files: src/lib/admin/client/users/ban-user-dialog.svelte -->
118
118
  - [ ] `[feature]` `[P1]` Impersonation UI — impersonate/stop bar <!-- files: src/lib/admin/client/users/impersonation-bar.svelte -->
119
119
  - [ ] `[chore]` `[P2]` Caching/performance layer (scope TBD)
120
+ - [ ] `[perf]` Opt-out populacji media per-pole (`populate.fields` obejmujące media, nie tylko relacje) — dziś `resolveMediaFields` wołane bez `ctx`, galeria ciągnięta na marne w widokach list. Diagnoza + opcje: `docs/architecture/2026-07-16-media-populate-opt-out.md`
120
121
  - [ ] `[feature]` `[P2]` API/CLI for configuration (setup DX for less technical users)
121
122
  - [ ] `[feature]` `[P0]` Plugin hooks in CRUD ops (before/afterCreate, Update, Delete) <!-- files: src/lib/types/plugins.ts, src/lib/core/server/entries/operations/ -->
122
123
  - [ ] `[feature]` `[P0]` Plugin registration API — public surface for external plugins
@@ -2,9 +2,10 @@ import type { DatabaseAdapter } from '../types/adapters/db.js';
2
2
  import type { FilesAdapter } from '../types/adapters/files.js';
3
3
  import type { AdminConfig, ApiKeyConfig, AuthConfig, CMSConfig, ICMS, MediaConfig, TypographyConfig } from '../types/cms.js';
4
4
  import type { CollectionConfigWithType } from '../types/collections.js';
5
- import type { Language } from '../types/languages.js';
5
+ import { type Language } from '../types/languages.js';
6
6
  import type { SingleConfigWithType } from '../types/singles.js';
7
7
  import type { CustomFieldDefinition, IconSetPlugin, Plugin } from '../types/plugins.js';
8
+ import { type LocaleUrl } from './i18n/localeUrl.js';
8
9
  import type { FormConfig } from '../types/forms.js';
9
10
  import type { AIAdapter } from '../types/adapters/ai.js';
10
11
  import type { EmailAdapter, SendMailOptions } from '../types/adapters/email.js';
@@ -24,6 +25,8 @@ export declare class CMS implements ICMS {
24
25
  singles: Record<string, SingleConfigWithType>;
25
26
  forms: Record<string, FormConfig>;
26
27
  languages: Language[];
28
+ /** Znormalizowana mapa locale→URL (prefiks/host, default). Jeden punkt prawdy i18n. */
29
+ localeUrl: LocaleUrl;
27
30
  mediaConfig: MediaConfig;
28
31
  typographyConfig: TypographyConfig;
29
32
  sidebarHelp: boolean;
package/dist/core/cms.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { languageCode } from '../types/languages.js';
1
2
  import { isIconSetPlugin } from '../types/plugins.js';
2
3
  import { setSchemaGetCMS } from './fields/fieldSchemaToTs.js';
4
+ import { buildLocaleUrl } from './i18n/localeUrl.js';
3
5
  import { betterAuth } from 'better-auth';
4
6
  import { drizzleAdapter } from 'better-auth/adapters/drizzle';
5
7
  import { admin } from 'better-auth/plugins';
@@ -17,6 +19,8 @@ export class CMS {
17
19
  singles;
18
20
  forms;
19
21
  languages;
22
+ /** Znormalizowana mapa locale→URL (prefiks/host, default). Jeden punkt prawdy i18n. */
23
+ localeUrl;
20
24
  mediaConfig;
21
25
  typographyConfig;
22
26
  sidebarHelp;
@@ -67,10 +71,13 @@ export class CMS {
67
71
  ...form
68
72
  };
69
73
  });
70
- this.languages = config.languages || [];
71
- if (this.languages.length === 0) {
74
+ const rawLanguages = config.languages || [];
75
+ if (rawLanguages.length === 0) {
72
76
  throw new Error('CMS config must include at least one language.');
73
77
  }
78
+ // `languages` znormalizowane do kodów (reszta rdzenia zakłada string[]); url/default niesie localeUrl.
79
+ this.languages = rawLanguages.map(languageCode);
80
+ this.localeUrl = buildLocaleUrl(rawLanguages);
74
81
  this.apiKeys = config.apiKeys || [];
75
82
  if (config.plugins) {
76
83
  this.plugins = config.plugins;
@@ -11,7 +11,7 @@ export declare function getSlugFromEntryData(data: Record<string, unknown>, slug
11
11
  * without doubling: neither the admin list (which used to print `//blog/x`) nor
12
12
  * a consumer `href` (which used to get a *relative* `blog/x`) has to patch it.
13
13
  */
14
- export declare function applyPathTemplate(pathTemplate: string | undefined, slug: string): string;
14
+ export declare function applyPathTemplate(pathTemplate: string | undefined, slug: string, prefix?: string): string;
15
15
  /** @internal Compose full entry URL; undefined when no resolvable slug. */
16
16
  export declare function resolveEntryUrl(opts: {
17
17
  slugField?: string;
@@ -30,12 +30,13 @@ const ABSOLUTE_URL_RE = /^[a-z][a-z0-9+.-]*:\/\//i;
30
30
  * without doubling: neither the admin list (which used to print `//blog/x`) nor
31
31
  * a consumer `href` (which used to get a *relative* `blog/x`) has to patch it.
32
32
  */
33
- export function applyPathTemplate(pathTemplate, slug) {
33
+ export function applyPathTemplate(pathTemplate, slug, prefix) {
34
34
  const raw = pathTemplate ? pathTemplate.replace('{slug}', slug) : slug;
35
35
  if (ABSOLUTE_URL_RE.test(raw))
36
36
  return raw;
37
37
  const collapsed = raw.replace(/\/{2,}/g, '/');
38
- return collapsed.startsWith('/') ? collapsed : `/${collapsed}`;
38
+ const path = collapsed.startsWith('/') ? collapsed : `/${collapsed}`;
39
+ return prefix ? `${prefix}${path}` : path;
39
40
  }
40
41
  /** @internal Compose full entry URL; undefined when no resolvable slug. */
41
42
  export function resolveEntryUrl(opts) {
@@ -0,0 +1,20 @@
1
+ import type { LanguageEntry } from '../../types/languages.js';
2
+ export type LocaleUrlEntry = {
3
+ strategy: 'pathPrefix';
4
+ pathPrefix: string;
5
+ } | {
6
+ strategy: 'host';
7
+ host: string;
8
+ };
9
+ export interface LocaleUrl {
10
+ defaultLocale: string;
11
+ byCode: Record<string, LocaleUrlEntry>;
12
+ /** [prefix, code] posortowane malejąco po długości prefiksu — do dopasowania z URL. */
13
+ byPrefix: Array<[string, string]>;
14
+ }
15
+ /** Buduje znormalizowaną mapę locale→URL z `cms.config.languages`. Jeden punkt prawdy. */
16
+ export declare function buildLocaleUrl(languages: LanguageEntry[]): LocaleUrl;
17
+ /** Locale storefrontu z pathname: najdłuższy pasujący `pathPrefix`, inaczej default. */
18
+ export declare function localeFromPath(localeUrl: LocaleUrl, pathname: string): string;
19
+ /** Prefiks ścieżki dla locale (pusty dla default i strategii host). */
20
+ export declare function pathPrefixFor(localeUrl: LocaleUrl, locale: string | undefined): string;
@@ -0,0 +1,36 @@
1
+ /** Buduje znormalizowaną mapę locale→URL z `cms.config.languages`. Jeden punkt prawdy. */
2
+ export function buildLocaleUrl(languages) {
3
+ const objs = languages.map((l) => typeof l === 'string' ? { code: l } : l);
4
+ const defaultLocale = (objs.find((o) => o.default) ?? objs[0]).code;
5
+ const byCode = {};
6
+ const byPrefix = [];
7
+ for (const o of objs) {
8
+ if (o.code === defaultLocale)
9
+ continue; // domyślny — bez wyróżnika URL
10
+ if (o.url?.host) {
11
+ byCode[o.code] = { strategy: 'host', host: o.url.host };
12
+ }
13
+ else {
14
+ const pathPrefix = o.url?.pathPrefix ?? `/${o.code}`;
15
+ byCode[o.code] = { strategy: 'pathPrefix', pathPrefix };
16
+ byPrefix.push([pathPrefix, o.code]);
17
+ }
18
+ }
19
+ byPrefix.sort((a, b) => b[0].length - a[0].length);
20
+ return { defaultLocale, byCode, byPrefix };
21
+ }
22
+ /** Locale storefrontu z pathname: najdłuższy pasujący `pathPrefix`, inaczej default. */
23
+ export function localeFromPath(localeUrl, pathname) {
24
+ for (const [prefix, code] of localeUrl.byPrefix) {
25
+ if (pathname === prefix || pathname.startsWith(prefix + '/'))
26
+ return code;
27
+ }
28
+ return localeUrl.defaultLocale;
29
+ }
30
+ /** Prefiks ścieżki dla locale (pusty dla default i strategii host). */
31
+ export function pathPrefixFor(localeUrl, locale) {
32
+ if (!locale || locale === localeUrl.defaultLocale)
33
+ return '';
34
+ const e = localeUrl.byCode[locale];
35
+ return e && e.strategy === 'pathPrefix' ? e.pathPrefix : '';
36
+ }
@@ -212,7 +212,7 @@ export const getEntryVersion = async (options) => {
212
212
  });
213
213
  const slugPath = getEntrySlugPath(dbEntry.slug);
214
214
  const entrySlug = getSlugFromEntryData(dbEntryVersion.data, slugPath, language);
215
- const _url = entrySlug ? getEntryPath(dbEntry.slug, entrySlug) : undefined;
215
+ const _url = entrySlug ? getEntryPath(dbEntry.slug, entrySlug, language) : undefined;
216
216
  const result = {
217
217
  _id: dbEntry.id,
218
218
  _slug: dbEntry.slug,
@@ -30,7 +30,7 @@ async function buildEntry(dbEntry, version, ctx) {
30
30
  const populated = await _populate(version.data, fields, ctx);
31
31
  const slugPath = getEntrySlugPath(dbEntry.slug);
32
32
  const slugValue = getSlugFromEntryData(version.data, slugPath, ctx.locale);
33
- const _url = slugValue ? getEntryPath(dbEntry.slug, slugValue) : undefined;
33
+ const _url = slugValue ? getEntryPath(dbEntry.slug, slugValue, ctx.locale) : undefined;
34
34
  const result = {
35
35
  _id: dbEntry.id,
36
36
  _slug: dbEntry.slug,
@@ -148,7 +148,7 @@ export async function resolveRelationFields(data, fields, ctx) {
148
148
  const populated = await _populate(picked.data, nestedFields, nestedCtx);
149
149
  const slugPath = getEntrySlugPath(dbEntry.slug);
150
150
  const slugValue = getSlugFromEntryData(picked.data, slugPath, ctx.locale);
151
- const _url = slugValue ? getEntryPath(dbEntry.slug, slugValue) : undefined;
151
+ const _url = slugValue ? getEntryPath(dbEntry.slug, slugValue, ctx.locale) : undefined;
152
152
  entriesMap[dbEntry.id] = {
153
153
  _id: dbEntry.id,
154
154
  _slug: dbEntry.slug,
@@ -109,7 +109,7 @@ export async function resolveRichtextLinks(data, fields, ctx) {
109
109
  const slugPath = configSlug ? getEntrySlugPath(configSlug) : 'seo.slug';
110
110
  const slug = getSlugFromEntryData(rawData, slugPath, language);
111
111
  if (slug) {
112
- slugMap[entryId] = configSlug ? getEntryPath(configSlug, slug) : slug;
112
+ slugMap[entryId] = configSlug ? getEntryPath(configSlug, slug, language) : slug;
113
113
  }
114
114
  }
115
115
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -130,7 +130,7 @@ export async function resolveUrlFields(data, fields, ctx) {
130
130
  const slugPath = getEntrySlugPath(entry.slug);
131
131
  const slug = getSlugFromEntryData(version.data, slugPath, language);
132
132
  if (slug)
133
- slugMap[entry.id] = getEntryPath(entry.slug, slug);
133
+ slugMap[entry.id] = getEntryPath(entry.slug, slug, language);
134
134
  }
135
135
  }
136
136
  }
@@ -1,5 +1,5 @@
1
1
  export { getSlugFromEntryData } from '../../fields/slugPath.js';
2
2
  /** Get dot-path to slug field for a collection. Falls back to 'seo.slug'. */
3
3
  export declare function getEntrySlugPath(configSlug: string): string;
4
- /** Build full entry path using collection's pathTemplate. */
5
- export declare function getEntryPath(configSlug: string, slug: string): string;
4
+ /** Build full entry path using collection's pathTemplate, prefixed per locale. */
5
+ export declare function getEntryPath(configSlug: string, slug: string, locale?: string): string;
@@ -1,5 +1,6 @@
1
1
  import { getCMS } from '../../cms.js';
2
2
  import { getSlugFromEntryData, resolveSlugPath, applyPathTemplate } from '../../fields/slugPath.js';
3
+ import { pathPrefixFor } from '../../i18n/localeUrl.js';
3
4
  export { getSlugFromEntryData } from '../../fields/slugPath.js';
4
5
  /** Get dot-path to slug field for a collection. Falls back to 'seo.slug'. */
5
6
  export function getEntrySlugPath(configSlug) {
@@ -10,12 +11,19 @@ export function getEntrySlugPath(configSlug) {
10
11
  return resolveSlugPath(undefined);
11
12
  }
12
13
  }
13
- /** Build full entry path using collection's pathTemplate. */
14
- export function getEntryPath(configSlug, slug) {
14
+ /** Build full entry path using collection's pathTemplate, prefixed per locale. */
15
+ export function getEntryPath(configSlug, slug, locale) {
16
+ let prefix = '';
15
17
  try {
16
- return applyPathTemplate(getCMS().getBySlug(configSlug).pathTemplate, slug);
18
+ prefix = pathPrefixFor(getCMS().localeUrl, locale);
17
19
  }
18
20
  catch {
19
- return applyPathTemplate(undefined, slug);
21
+ prefix = '';
22
+ }
23
+ try {
24
+ return applyPathTemplate(getCMS().getBySlug(configSlug).pathTemplate, slug, prefix);
25
+ }
26
+ catch {
27
+ return applyPathTemplate(undefined, slug, prefix);
20
28
  }
21
29
  }
@@ -5,6 +5,8 @@ import { generateTsTypeFromFormFields } from './formFields.js';
5
5
  import { generateZodSchemaStringFromFormFieldsAsString } from './formFieldSchemaToString.js';
6
6
  import { toPascalCase, quoteKey } from './utils.js';
7
7
  import { getFieldsFromConfig } from '../../fields/layoutUtils.js';
8
+ import { buildLocaleUrl } from '../../i18n/localeUrl.js';
9
+ import { languageCode } from '../../../types/languages.js';
8
10
  function createCmsRuntimeDir() {
9
11
  const cmsDir = join(process.cwd(), 'src/lib/cms/runtime');
10
12
  mkdirSync(cmsDir, { recursive: true });
@@ -171,7 +173,7 @@ function generateTypes(config) {
171
173
  }
172
174
  }
173
175
  }
174
- code += `\n export type SiteLanguage = ${config.languages.map((lang) => JSON.stringify(lang)).join(' | ')};\n\n`;
176
+ code += `\n export type SiteLanguage = ${config.languages.map((lang) => JSON.stringify(languageCode(lang))).join(' | ')};\n\n`;
175
177
  writeIfChanged(filePath, code);
176
178
  }
177
179
  function generateAPI(config) {
@@ -307,6 +309,62 @@ function generateRemote(config) {
307
309
  });
308
310
  writeIfChanged(filePath, code);
309
311
  }
312
+ /**
313
+ * Emituje konfigurację app-owego Paraglide z `cms.config.languages` — jedno źródło prawdy i18n.
314
+ * `project.inlang/settings.json` (baseLocale=default, locales) + `src/lib/cms/runtime/i18n.ts`
315
+ * (`paraglideUrlPatterns` do vite.config + `reroute` do hooks). Konsument importuje te artefakty
316
+ * zamiast utrzymywać osobny, ręcznie synchronizowany config.
317
+ */
318
+ function generateI18n(config) {
319
+ const lu = buildLocaleUrl(config.languages);
320
+ const codes = config.languages.map((l) => typeof l === 'string' ? l : l.code);
321
+ // 1) project.inlang/settings.json
322
+ const settings = {
323
+ $schema: 'https://inlang.com/schema/project-settings',
324
+ modules: [
325
+ 'https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js',
326
+ 'https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js'
327
+ ],
328
+ 'plugin.inlang.messageFormat': { pathPattern: './messages/{locale}.json' },
329
+ baseLocale: lu.defaultLocale,
330
+ locales: codes
331
+ };
332
+ const inlangDir = join(process.cwd(), 'project.inlang');
333
+ mkdirSync(inlangDir, { recursive: true });
334
+ writeIfChanged(join(inlangDir, 'settings.json'), JSON.stringify(settings, null, '\t') + '\n');
335
+ createCmsRuntimeDir();
336
+ // 2) src/lib/cms/runtime/i18n.ts — CZYSTE dane urlPatterns (bez importów paraglide),
337
+ // żeby dało się importować w vite.config.ts (paraglide runtime jeszcze nie istnieje przy config-load).
338
+ // KOLEJNOŚĆ: prefiksowane locale NAJPIERW, domyślny (catch-all `/:path`) OSTATNI — inaczej
339
+ // catch-all złapałby `/en/...` przed wzorcem `/en`.
340
+ const ordered = [...codes].sort((a, b) => {
341
+ const aDef = a === lu.defaultLocale ? 1 : 0;
342
+ const bDef = b === lu.defaultLocale ? 1 : 0;
343
+ return aDef - bDef;
344
+ });
345
+ const localized = ordered
346
+ .map((c) => {
347
+ const e = lu.byCode[c];
348
+ const p = e && e.strategy === 'pathPrefix' ? e.pathPrefix : '';
349
+ return `\t\t\t['${c}', '${p}/:path(.*)?']`;
350
+ })
351
+ .join(',\n');
352
+ // Buduj specyfikator `$lib/...` przez konkatenację — inaczej svelte-package (build rdzenia)
353
+ // potraktuje literał jak import w tym pliku i przepisze go na relatywną ścieżkę RDZENIA.
354
+ const paraglideRuntime = '$' + 'lib/paraglide/runtime';
355
+ const i18n = `// AUTOGENEROWANE przez includio-cms (generateRuntime). Nie edytuj ręcznie.\n` +
356
+ `// \`import type\` jest wymazywany przy buildzie → można importować w vite.config.ts bez cyklu runtime.\n` +
357
+ `import type { Locale } from '${paraglideRuntime}';\n\n` +
358
+ `export const paraglideUrlPatterns: Array<{ pattern: string; localized: Array<[Locale, string]> }> = [\n` +
359
+ `\t{\n\t\tpattern: '/:path(.*)?',\n\t\tlocalized: [\n${localized}\n\t\t]\n\t}\n];\n`;
360
+ writeIfChanged(join(process.cwd(), 'src/lib/cms/runtime/i18n.ts'), i18n);
361
+ // 3) src/lib/cms/runtime/reroute.ts — reroute (importuje paraglide runtime), do wpięcia w hooks.ts
362
+ const reroute = `// AUTOGENEROWANE przez includio-cms (generateRuntime). Nie edytuj ręcznie.\n` +
363
+ `import { deLocalizeUrl } from '${paraglideRuntime}';\n` +
364
+ `import type { Reroute } from '@sveltejs/kit';\n\n` +
365
+ `export const reroute: Reroute = (request) => deLocalizeUrl(request.url).pathname;\n`;
366
+ writeIfChanged(join(process.cwd(), 'src/lib/cms/runtime/reroute.ts'), reroute);
367
+ }
310
368
  export function generateRuntime(config) {
311
369
  // Build custom fields map from plugins for type generation
312
370
  const customFields = new Map();
@@ -325,4 +383,5 @@ export function generateRuntime(config) {
325
383
  generateSchemas(config);
326
384
  generateDrizzleSchema(config);
327
385
  generateRemote(config);
386
+ generateI18n(config);
328
387
  }
@@ -1,36 +1,3 @@
1
- export function hello_world(inputs: {
2
- name: NonNullable<unknown>;
3
- }, options?: {
4
- locale?: "en" | "pl";
5
- }): string;
6
- /**
7
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
8
- *
9
- * - Changing this function will be over-written by the next build.
10
- *
11
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
12
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
13
- *
14
- * @param {{}} inputs
15
- * @param {{ locale?: "en" | "pl" }} options
16
- * @returns {string}
17
- */
18
- declare function login_hello(inputs?: {}, options?: {
19
- locale?: "en" | "pl";
20
- }): string;
21
- /**
22
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
23
- *
24
- * - Changing this function will be over-written by the next build.
25
- *
26
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
27
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
28
- *
29
- * @param {{}} inputs
30
- * @param {{ locale?: "en" | "pl" }} options
31
- * @returns {string}
32
- */
33
- declare function login_please_login(inputs?: {}, options?: {
34
- locale?: "en" | "pl";
35
- }): string;
36
- export { login_hello as login.hello, login_please_login as login.please_login };
1
+ export * from "./hello_world.js";
2
+ export * from "./login_hello.js";
3
+ export * from "./login_please_login.js";
@@ -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" }
@@ -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
@@ -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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.37.2",
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;
@@ -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
- };