includio-cms 0.19.0 → 0.21.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 (86) hide show
  1. package/API.md +410 -0
  2. package/CHANGELOG.md +112 -0
  3. package/DOCS.md +1 -1
  4. package/ROADMAP.md +8 -4
  5. package/dist/admin/api/rest/handler.d.ts +4 -0
  6. package/dist/admin/api/rest/handler.js +4 -0
  7. package/dist/admin/api/rest/middleware/apiKey.js +9 -1
  8. package/dist/admin/api/rest/middleware/generateApiKey.d.ts +7 -0
  9. package/dist/admin/api/rest/middleware/generateApiKey.js +10 -0
  10. package/dist/admin/client/index.d.ts +2 -0
  11. package/dist/admin/client/index.js +4 -0
  12. package/dist/admin/client/users/delete-user-dialog.svelte +2 -2
  13. package/dist/admin/client/users/lang.d.ts +10 -2
  14. package/dist/admin/client/users/lang.js +10 -4
  15. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  16. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  17. package/dist/core/cms.d.ts +4 -0
  18. package/dist/core/cms.js +4 -0
  19. package/dist/core/index.d.ts +2 -0
  20. package/dist/core/index.js +2 -0
  21. package/dist/core/server/consentLogs/operations/create.d.ts +4 -0
  22. package/dist/core/server/consentLogs/operations/create.js +4 -0
  23. package/dist/core/server/fields/utils/resolveMedia.d.ts +5 -2
  24. package/dist/core/server/fields/utils/resolveMedia.js +2 -2
  25. package/dist/core/server/forms/submissions/operations/create.d.ts +7 -0
  26. package/dist/core/server/forms/submissions/operations/create.js +4 -0
  27. package/dist/core/server/forms/submissions/utils/parseMultipart.d.ts +4 -0
  28. package/dist/core/server/forms/submissions/utils/parseMultipart.js +4 -0
  29. package/dist/core/server/media/operations/uploadFile.js +4 -3
  30. package/dist/core/server/media/styles/sharp/generateImageStyle.js +3 -2
  31. package/dist/core/server/media/utils/generateAdminThumbnail.js +3 -2
  32. package/dist/core/server/media/utils/generateBlurDataUrl.js +2 -1
  33. package/dist/db-postgres/index.d.ts +2 -0
  34. package/dist/db-postgres/index.js +3 -0
  35. package/dist/entity/index.d.ts +4 -0
  36. package/dist/entity/index.js +4 -0
  37. package/dist/files-local/index.d.ts +1 -0
  38. package/dist/files-local/index.js +1 -0
  39. package/dist/index.d.ts +0 -2
  40. package/dist/index.js +0 -1
  41. package/dist/paraglide/messages/_index.d.ts +36 -3
  42. package/dist/paraglide/messages/_index.js +71 -3
  43. package/dist/paraglide/messages/en.d.ts +5 -0
  44. package/dist/paraglide/messages/en.js +14 -0
  45. package/dist/paraglide/messages/pl.d.ts +5 -0
  46. package/dist/paraglide/messages/pl.js +14 -0
  47. package/dist/server/auth.d.ts +4 -0
  48. package/dist/server/auth.js +4 -0
  49. package/dist/server/security/csp.d.ts +16 -0
  50. package/dist/server/security/csp.js +33 -0
  51. package/dist/server/security/csrf.d.ts +13 -0
  52. package/dist/server/security/csrf.js +49 -0
  53. package/dist/server/security/index.d.ts +3 -0
  54. package/dist/server/security/index.js +3 -0
  55. package/dist/server/security/rate-limit.d.ts +44 -0
  56. package/dist/server/security/rate-limit.js +97 -0
  57. package/dist/server/utils/withTimeout.d.ts +21 -0
  58. package/dist/server/utils/withTimeout.js +37 -0
  59. package/dist/shop/client/index.d.ts +4 -0
  60. package/dist/shop/client/index.js +4 -0
  61. package/dist/sveltekit/config.d.ts +20 -0
  62. package/dist/sveltekit/config.js +20 -0
  63. package/dist/sveltekit/server/handle.d.ts +4 -0
  64. package/dist/sveltekit/server/handle.js +11 -0
  65. package/dist/sveltekit/server/index.d.ts +2 -0
  66. package/dist/sveltekit/server/index.js +3 -0
  67. package/dist/sveltekit/server/layout.d.ts +4 -0
  68. package/dist/sveltekit/server/layout.js +4 -0
  69. package/dist/sveltekit/server/preview.d.ts +4 -0
  70. package/dist/sveltekit/server/preview.js +4 -0
  71. package/dist/types/cms.d.ts +4 -0
  72. package/dist/types/index.d.ts +1 -0
  73. package/dist/types/index.js +1 -0
  74. package/dist/types/plugins.d.ts +8 -0
  75. package/dist/updates/0.20.0/index.d.ts +2 -0
  76. package/dist/updates/0.20.0/index.js +54 -0
  77. package/dist/updates/0.21.0/index.d.ts +2 -0
  78. package/dist/updates/0.21.0/index.js +55 -0
  79. package/dist/updates/index.js +3 -1
  80. package/package.json +15 -68
  81. package/dist/paraglide/messages/hello_world.d.ts +0 -5
  82. package/dist/paraglide/messages/hello_world.js +0 -33
  83. package/dist/paraglide/messages/login_hello.d.ts +0 -16
  84. package/dist/paraglide/messages/login_hello.js +0 -34
  85. package/dist/paraglide/messages/login_please_login.d.ts +0 -16
  86. package/dist/paraglide/messages/login_please_login.js +0 -34
@@ -82,7 +82,7 @@
82
82
  {lang.deleteWarningTitle}
83
83
  </p>
84
84
  <p class="mt-1 text-sm" style="color: var(--muted-foreground);">
85
- {@html lang.deleteWarningDesc(user.name)}
85
+ {lang.deleteWarningDesc.before}<strong>{user.name}</strong>{lang.deleteWarningDesc.after}
86
86
  </p>
87
87
  </div>
88
88
  </div>
@@ -90,7 +90,7 @@
90
90
  <!-- Confirm input -->
91
91
  <div class="space-y-2">
92
92
  <Label for="delete-confirm">
93
- {@html lang.deleteConfirmType}
93
+ {lang.deleteConfirmType.before}<strong>{lang.deleteConfirmWord}</strong>{lang.deleteConfirmType.after}
94
94
  </Label>
95
95
  <Input
96
96
  id="delete-confirm"
@@ -24,8 +24,16 @@ export declare const usersLang: Record<InterfaceLanguage, {
24
24
  deleteConfirmTitle: string;
25
25
  deleteConfirmDescription: string;
26
26
  deleteWarningTitle: string;
27
- deleteWarningDesc: (name: string) => string;
28
- deleteConfirmType: string;
27
+ /** Split into `before` / `after`; the user name is rendered between them in template (avoids `{@html}`). */
28
+ deleteWarningDesc: {
29
+ before: string;
30
+ after: string;
31
+ };
32
+ /** Split into `before` / `after`; `deleteConfirmWord` is rendered between them. */
33
+ deleteConfirmType: {
34
+ before: string;
35
+ after: string;
36
+ };
29
37
  deleteConfirmWord: string;
30
38
  userCreated: string;
31
39
  userUpdated: string;
@@ -24,8 +24,11 @@ export const usersLang = {
24
24
  deleteConfirmTitle: 'Delete user?',
25
25
  deleteConfirmDescription: 'This action cannot be undone. The user will be permanently deleted.',
26
26
  deleteWarningTitle: 'This action cannot be undone',
27
- deleteWarningDesc: (name) => `User <strong>${name}</strong> will be permanently deleted along with all their data.`,
28
- deleteConfirmType: 'Type <strong>DELETE</strong> to confirm',
27
+ deleteWarningDesc: {
28
+ before: 'User ',
29
+ after: ' will be permanently deleted along with all their data.'
30
+ },
31
+ deleteConfirmType: { before: 'Type ', after: ' to confirm' },
29
32
  deleteConfirmWord: 'DELETE',
30
33
  userCreated: 'User created',
31
34
  userUpdated: 'User updated',
@@ -107,8 +110,11 @@ export const usersLang = {
107
110
  deleteConfirmTitle: 'Usunąć użytkownika?',
108
111
  deleteConfirmDescription: 'Ta akcja jest nieodwracalna. Użytkownik zostanie trwale usunięty.',
109
112
  deleteWarningTitle: 'Tej operacji nie można cofnąć',
110
- deleteWarningDesc: (name) => `Użytkownik <strong>${name}</strong> zostanie trwale usunięty wraz ze wszystkimi danymi.`,
111
- deleteConfirmType: 'Wpisz <strong>USUŃ</strong>, żeby potwierdzić',
113
+ deleteWarningDesc: {
114
+ before: 'Użytkownik ',
115
+ after: ' zostanie trwale usunięty wraz ze wszystkimi danymi.'
116
+ },
117
+ deleteConfirmType: { before: 'Wpisz ', after: ', żeby potwierdzić' },
112
118
  deleteConfirmWord: 'USUŃ',
113
119
  userCreated: 'Użytkownik utworzony',
114
120
  userUpdated: 'Użytkownik zaktualizowany',
@@ -2,7 +2,7 @@ declare const InputGroupInput: import("svelte").Component<(Omit<import("svelte/e
2
2
  type: "file";
3
3
  files?: FileList;
4
4
  } | {
5
- type?: "number" | "image" | "url" | "text" | "date" | "radio" | "color" | "button" | "checkbox" | "search" | (string & {}) | "email" | "time" | "password" | "hidden" | "reset" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
5
+ type?: "number" | "image" | "url" | "text" | "date" | "radio" | "color" | "button" | "checkbox" | "search" | (string & {}) | "email" | "password" | "time" | "hidden" | "reset" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
6
6
  files?: undefined;
7
7
  })) & {
8
8
  ref?: HTMLElement | null | undefined;
@@ -2,7 +2,7 @@ declare const SidebarInput: import("svelte").Component<(Omit<import("svelte/elem
2
2
  type: "file";
3
3
  files?: FileList;
4
4
  } | {
5
- type?: "number" | "image" | "url" | "text" | "date" | "radio" | "color" | "button" | "checkbox" | "search" | (string & {}) | "email" | "time" | "password" | "hidden" | "reset" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
5
+ type?: "number" | "image" | "url" | "text" | "date" | "radio" | "color" | "button" | "checkbox" | "search" | (string & {}) | "email" | "password" | "time" | "hidden" | "reset" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
6
6
  files?: undefined;
7
7
  })) & {
8
8
  ref?: HTMLElement | null | undefined;
@@ -38,4 +38,8 @@ export declare class CMS implements ICMS {
38
38
  getFormBySlug(slug: string): FormConfig;
39
39
  }
40
40
  export declare function initCMS(config: CMSConfig): CMS;
41
+ /**
42
+ * Returns the singleton CMS instance. Must be called after `includioCMS()` initializes the CMS in `hooks.server.ts`.
43
+ * @public
44
+ */
41
45
  export declare function getCMS(): CMS;
package/dist/core/cms.js CHANGED
@@ -159,6 +159,10 @@ export function initCMS(config) {
159
159
  .catch((e) => console.warn('[cms] Failed to start background maintenance:', e));
160
160
  return cms;
161
161
  }
162
+ /**
163
+ * Returns the singleton CMS instance. Must be called after `includioCMS()` initializes the CMS in `hooks.server.ts`.
164
+ * @public
165
+ */
162
166
  export function getCMS() {
163
167
  if (!cms) {
164
168
  throw new Error('CMS not initialized. Call initCMS() first with your CMS config.');
@@ -1,2 +1,4 @@
1
1
  export { getCMS } from './cms.js';
2
2
  export { resolveMediaWithStyles, type ResolvedMedia } from './server/fields/utils/resolveMedia.js';
3
+ export { createEntityAPI } from '../entity/index.js';
4
+ export { getAuth } from '../server/auth.js';
@@ -1,2 +1,4 @@
1
1
  export { getCMS } from './cms.js';
2
2
  export { resolveMediaWithStyles } from './server/fields/utils/resolveMedia.js';
3
+ export { createEntityAPI } from '../entity/index.js';
4
+ export { getAuth } from '../server/auth.js';
@@ -1,2 +1,6 @@
1
1
  import type { ConsentLogData } from '../../../../types/consent.js';
2
+ /**
3
+ * Persists a CMP consent log entry via the database adapter.
4
+ * @public
5
+ */
2
6
  export declare const createConsentLog: (data: ConsentLogData) => Promise<void>;
@@ -1,4 +1,8 @@
1
1
  import { getCMS } from '../../../cms.js';
2
+ /**
3
+ * Persists a CMP consent log entry via the database adapter.
4
+ * @public
5
+ */
2
6
  export const createConsentLog = async (data) => {
3
7
  await getCMS().databaseAdapter.createConsentLog(data);
4
8
  };
@@ -1,12 +1,15 @@
1
1
  import type { ImageFieldStyle } from '../../../../types/fields.js';
2
2
  import type { ImageStyle, MediaFile } from '../../../../types/media.js';
3
+ /**
4
+ * @public
5
+ */
3
6
  export interface ResolvedMedia {
4
7
  data: MediaFile;
5
8
  styles: Record<string, ImageStyle>;
6
9
  blurDataUrl: string | null;
7
10
  }
8
11
  /**
9
- * Resolve media files by IDs and generate image styles.
10
- * Useful for plugins that need to resolve media references (e.g. photo-grid).
12
+ * Resolve media files by IDs and generate image styles. Useful for plugins resolving media references (e.g. photo-grid).
13
+ * @public
11
14
  */
12
15
  export declare function resolveMediaWithStyles(mediaIds: string[], styles?: ImageFieldStyle[]): Promise<Record<string, ResolvedMedia>>;
@@ -1,8 +1,8 @@
1
1
  import { getCMS } from '../../../cms.js';
2
2
  import { getImageStyles } from './imageStyles.js';
3
3
  /**
4
- * Resolve media files by IDs and generate image styles.
5
- * Useful for plugins that need to resolve media references (e.g. photo-grid).
4
+ * Resolve media files by IDs and generate image styles. Useful for plugins resolving media references (e.g. photo-grid).
5
+ * @public
6
6
  */
7
7
  export async function resolveMediaWithStyles(mediaIds, styles) {
8
8
  if (!mediaIds.length)
@@ -1,7 +1,14 @@
1
+ /**
2
+ * @public
3
+ */
1
4
  export interface CreateFormSubmissionOptions {
2
5
  slug: string;
3
6
  data: Record<string, unknown>;
4
7
  ip?: string;
5
8
  userAgent?: string;
6
9
  }
10
+ /**
11
+ * Persists a form submission and triggers best-effort notification email. Returns `true` if the row was written (email failures are logged, do not affect return).
12
+ * @public
13
+ */
7
14
  export declare const createFormSubmission: (options: CreateFormSubmissionOptions) => Promise<boolean>;
@@ -1,6 +1,10 @@
1
1
  import { getLocalizedLabel } from '../../../../../admin/utils/collectionLabel.js';
2
2
  import { getCMS } from '../../../../cms.js';
3
3
  import { generateZodSchemaFromFormFields } from '../../../../fields/formFieldSchemaToTs.js';
4
+ /**
5
+ * Persists a form submission and triggers best-effort notification email. Returns `true` if the row was written (email failures are logged, do not affect return).
6
+ * @public
7
+ */
4
8
  export const createFormSubmission = async (options) => {
5
9
  const { slug, data, ip, userAgent } = options;
6
10
  const config = getCMS().getFormBySlug(slug);
@@ -1,2 +1,6 @@
1
1
  import type { FormField } from '../../../../../types/formFields.js';
2
+ /**
3
+ * Parses multipart `FormData` into a typed record of field values, handling file uploads via the configured files adapter.
4
+ * @public
5
+ */
2
6
  export declare function parseFormDataForSubmission(formData: FormData, fields: FormField[]): Promise<Record<string, unknown>>;
@@ -25,6 +25,10 @@ function validateMagicBytes(buffer, declaredMime) {
25
25
  }
26
26
  return false;
27
27
  }
28
+ /**
29
+ * Parses multipart `FormData` into a typed record of field values, handling file uploads via the configured files adapter.
30
+ * @public
31
+ */
28
32
  export async function parseFormDataForSubmission(formData, fields) {
29
33
  const result = {};
30
34
  const fileFields = new Map(fields.filter((f) => f.type === 'file').map((f) => [f.slug, f]));
@@ -4,6 +4,7 @@ import { generateAdminThumbnail } from '../utils/generateAdminThumbnail.js';
4
4
  import { generateDefaultStylesInBackground } from '../styles/operations/generateDefaultStyles.js';
5
5
  import { generateDefaultVideoStylesInBackground } from '../styles/operations/generateDefaultVideoStyles.js';
6
6
  import sharp from 'sharp';
7
+ import { withTimeout, sharpTimeoutMs } from '../../../../server/utils/withTimeout.js';
7
8
  async function maybeDownscale(file) {
8
9
  const cms = getCMS();
9
10
  const { maxOriginalWidth, maxOriginalHeight } = cms.mediaConfig;
@@ -14,19 +15,19 @@ async function maybeDownscale(file) {
14
15
  return file;
15
16
  try {
16
17
  const buffer = Buffer.from(await file.arrayBuffer());
17
- const metadata = await sharp(buffer).metadata();
18
+ const metadata = await withTimeout(sharp(buffer).metadata(), sharpTimeoutMs(), 'sharp.metadata');
18
19
  const w = metadata.width || 0;
19
20
  const h = metadata.height || 0;
20
21
  const exceedsWidth = maxOriginalWidth && w > maxOriginalWidth;
21
22
  const exceedsHeight = maxOriginalHeight && h > maxOriginalHeight;
22
23
  if (!exceedsWidth && !exceedsHeight)
23
24
  return file;
24
- const resized = await sharp(buffer)
25
+ const resized = await withTimeout(sharp(buffer)
25
26
  .resize(maxOriginalWidth, maxOriginalHeight, {
26
27
  fit: 'inside',
27
28
  withoutEnlargement: true
28
29
  })
29
- .toBuffer();
30
+ .toBuffer(), sharpTimeoutMs(), 'sharp.resize');
30
31
  return new File([new Uint8Array(resized)], file.name, { type: file.type });
31
32
  }
32
33
  catch (e) {
@@ -1,6 +1,7 @@
1
1
  import { getCMS } from '../../../../cms.js';
2
2
  import sharp from 'sharp';
3
3
  import { calculateFocalCropRegion } from '../../utils/calculateFocalCropRegion.js';
4
+ import { withTimeout, sharpTimeoutMs } from '../../../../../server/utils/withTimeout.js';
4
5
  export async function generateImageStyle(mediaFileId, style) {
5
6
  const mediaFile = await getCMS().databaseAdapter.getMediaFile({
6
7
  data: {
@@ -19,7 +20,7 @@ export async function generateImageStyle(mediaFileId, style) {
19
20
  }
20
21
  export async function generateImageStyleFromBuffer(buf, mediaFile, style) {
21
22
  // Read EXIF orientation before processing
22
- const metadata = await sharp(buf).metadata();
23
+ const metadata = await withTimeout(sharp(buf).metadata(), sharpTimeoutMs(), 'sharp.metadata');
23
24
  // .rotate() applies EXIF orientation to pixels AND strips the tag from output.
24
25
  // Prevents double-rotation in WebP/JPEG where EXIF orientation tag may persist.
25
26
  let sharpInstance = sharp(buf).rotate();
@@ -79,7 +80,7 @@ export async function generateImageStyleFromBuffer(buf, mediaFile, style) {
79
80
  const originalExt = mediaFile.mimeType?.split('/').pop() ?? mediaFile.url.split('.').pop();
80
81
  const format = style.format ?? originalExt ?? 'jpeg';
81
82
  sharpInstance = sharpInstance.toFormat(format, style.quality != null ? { quality: Math.max(1, Math.min(100, style.quality)) } : undefined);
82
- const outputBuffer = await sharpInstance.toBuffer();
83
+ const outputBuffer = await withTimeout(sharpInstance.toBuffer(), sharpTimeoutMs(), 'sharp.toBuffer');
83
84
  return getCMS().filesAdapter.uploadFile(new File([new Uint8Array(outputBuffer)], `${mediaFile.id}_${style.name}_${Date.now().toString(36)}.${format}`, {
84
85
  type: `image/${format}`
85
86
  }));
@@ -1,14 +1,15 @@
1
1
  import { getCMS } from '../../../cms.js';
2
2
  import { isProcessableImage } from '../../fields/utils/imageStyles.js';
3
3
  import sharp from 'sharp';
4
+ import { withTimeout, sharpTimeoutMs } from '../../../../server/utils/withTimeout.js';
4
5
  const THUMB_WIDTH = 400;
5
6
  const THUMB_QUALITY = 70;
6
7
  export async function generateAdminThumbnail(buffer, mediaFile) {
7
- const output = await sharp(buffer)
8
+ const output = await withTimeout(sharp(buffer)
8
9
  .rotate()
9
10
  .resize(THUMB_WIDTH, undefined, { withoutEnlargement: true })
10
11
  .toFormat('webp', { quality: THUMB_QUALITY })
11
- .toBuffer();
12
+ .toBuffer(), sharpTimeoutMs(), 'sharp.adminThumbnail');
12
13
  const filename = `${mediaFile.id}_admin_thumb_${Date.now().toString(36)}.webp`;
13
14
  const uploaded = await getCMS().filesAdapter.uploadFile(new File([new Uint8Array(output)], filename, { type: 'image/webp' }));
14
15
  return uploaded.url;
@@ -1,5 +1,6 @@
1
1
  import sharp from 'sharp';
2
+ import { withTimeout, sharpTimeoutMs } from '../../../../server/utils/withTimeout.js';
2
3
  export async function generateBlurDataUrl(buffer) {
3
- const blurBuffer = await sharp(buffer).resize(20).blur(10).toFormat('webp').toBuffer();
4
+ const blurBuffer = await withTimeout(sharp(buffer).resize(20).blur(10).toFormat('webp').toBuffer(), sharpTimeoutMs(), 'sharp.blurDataUrl');
4
5
  return `data:image/webp;base64,${blurBuffer.toString('base64')}`;
5
6
  }
@@ -2,6 +2,8 @@ import { drizzle } from 'drizzle-orm/postgres-js';
2
2
  import type { Config } from './types.js';
3
3
  import * as schema from './schema/index.js';
4
4
  import type { DatabaseAdapter } from '../types/adapters/db.js';
5
+ export * from './schema/index.js';
6
+ export * from '../server/db/schema/auth-schema.js';
5
7
  export type DatabaseAdapterWithDrizzle = DatabaseAdapter & {
6
8
  _drizzle: ReturnType<typeof drizzle<typeof schema>>;
7
9
  };
@@ -262,6 +262,9 @@ function buildMediaFileConditions(db, options) {
262
262
  }
263
263
  return conditions;
264
264
  }
265
+ // Schema re-exports (folded from `./db-postgres/schema-core`, `./db-postgres/schema-shop`, `./auth-schema` in 0.20.0)
266
+ export * from './schema/index.js';
267
+ export * from '../server/db/schema/auth-schema.js';
265
268
  /**
266
269
  * Postgres database adapter (drizzle + `postgres`).
267
270
  * @public
@@ -7,6 +7,10 @@ interface CreateOptions {
7
7
  skipValidation?: boolean;
8
8
  sortOrder?: number;
9
9
  }
10
+ /**
11
+ * Creates a high-level Entity API (CRUD + publish/archive) bound to a CMS instance and a user.
12
+ * @public
13
+ */
10
14
  export declare function createEntityAPI(cms: CMS, opts?: EntityAPIOptions): {
11
15
  create(slug: string, data?: EntryData, options?: CreateOptions & {
12
16
  lang?: string;
@@ -1,6 +1,10 @@
1
1
  import { generateZodSchemaFromFields } from '../core/fields/fieldSchemaToTs.js';
2
2
  import { getFieldsFromConfig } from '../core/fields/layoutUtils.js';
3
3
  import { _getRawEntries as getRawEntries } from '../core/server/entries/operations/get.js';
4
+ /**
5
+ * Creates a high-level Entity API (CRUD + publish/archive) bound to a CMS instance and a user.
6
+ * @public
7
+ */
4
8
  export function createEntityAPI(cms, opts) {
5
9
  const db = cms.databaseAdapter;
6
10
  const userId = opts?.userId ?? 'system';
@@ -1,4 +1,5 @@
1
1
  import type { FilesAdapter } from '../types/adapters/files.js';
2
+ /** @internal */
2
3
  export declare const fullDir: string;
3
4
  export interface LocalFilesConfig {
4
5
  ffmpegPath?: string;
@@ -9,6 +9,7 @@ import { processVideo, setFfmpegPaths } from './video.js';
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = dirname(__filename);
11
11
  global.__dirname = __dirname ?? '';
12
+ /** @internal */
12
13
  export const fullDir = process.env.NODE_ENV === 'production' ? `/data/uploads` : `./static/uploads`;
13
14
  const privateDir = process.env.NODE_ENV === 'production' ? `/data/private-uploads` : `./data/private-uploads`;
14
15
  async function ensureDir(dir) {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,2 @@
1
- export * from './admin/index.js';
2
- export type * from './admin/index.js';
3
1
  export * from './core/index.js';
4
2
  export type * from './core/index.js';
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
- export * from './admin/index.js';
2
1
  export * from './core/index.js';
@@ -1,3 +1,36 @@
1
- export * from "./hello_world.js";
2
- export * from "./login_hello.js";
3
- export * from "./login_please_login.js";
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,4 +1,72 @@
1
1
  /* eslint-disable */
2
- export * from './hello_world.js'
3
- export * from './login_hello.js'
4
- export * from './login_please_login.js'
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" }
@@ -0,0 +1,5 @@
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;
@@ -0,0 +1,14 @@
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
+ };
@@ -0,0 +1,5 @@
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;
@@ -0,0 +1,14 @@
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
+ };
@@ -1 +1,5 @@
1
+ /**
2
+ * Returns the underlying `better-auth` instance from the initialized CMS.
3
+ * @public
4
+ */
1
5
  export declare function getAuth(): import("better-auth", { with: { "resolution-mode": "require" } }).Auth<import("better-auth", { with: { "resolution-mode": "require" } }).BetterAuthOptions>;
@@ -1,4 +1,8 @@
1
1
  import { getCMS } from '../core/cms.js';
2
+ /**
3
+ * Returns the underlying `better-auth` instance from the initialized CMS.
4
+ * @public
5
+ */
2
6
  export function getAuth() {
3
7
  return getCMS().auth;
4
8
  }
@@ -0,0 +1,16 @@
1
+ export interface CspOptions {
2
+ scriptSrc?: string[];
3
+ styleSrc?: string[];
4
+ imgSrc?: string[];
5
+ mediaSrc?: string[];
6
+ fontSrc?: string[];
7
+ connectSrc?: string[];
8
+ frameAncestors?: string[];
9
+ }
10
+ /**
11
+ * Build a Content-Security-Policy header value with v1.0 defaults.
12
+ * `'unsafe-inline'` is allowed on `script-src`/`style-src` because TipTap and
13
+ * paraglide emit inline code; documented in `KNOWN-RISKS.md`.
14
+ * @internal
15
+ */
16
+ export declare function buildCspHeader(opts?: CspOptions): string;
@@ -0,0 +1,33 @@
1
+ const DEFAULTS = {
2
+ scriptSrc: ["'self'", "'unsafe-inline'"],
3
+ styleSrc: ["'self'", "'unsafe-inline'"],
4
+ imgSrc: ["'self'", 'data:', 'blob:'],
5
+ mediaSrc: ["'self'", 'blob:'],
6
+ fontSrc: ["'self'", 'data:'],
7
+ connectSrc: ["'self'"],
8
+ frameAncestors: ["'self'"]
9
+ };
10
+ /**
11
+ * Build a Content-Security-Policy header value with v1.0 defaults.
12
+ * `'unsafe-inline'` is allowed on `script-src`/`style-src` because TipTap and
13
+ * paraglide emit inline code; documented in `KNOWN-RISKS.md`.
14
+ * @internal
15
+ */
16
+ export function buildCspHeader(opts = {}) {
17
+ const merge = (key, extra) => {
18
+ const base = DEFAULTS[key];
19
+ return extra && extra.length ? Array.from(new Set([...base, ...extra])) : [...base];
20
+ };
21
+ return [
22
+ `default-src 'self'`,
23
+ `script-src ${merge('scriptSrc', opts.scriptSrc).join(' ')}`,
24
+ `style-src ${merge('styleSrc', opts.styleSrc).join(' ')}`,
25
+ `img-src ${merge('imgSrc', opts.imgSrc).join(' ')}`,
26
+ `media-src ${merge('mediaSrc', opts.mediaSrc).join(' ')}`,
27
+ `font-src ${merge('fontSrc', opts.fontSrc).join(' ')}`,
28
+ `connect-src ${merge('connectSrc', opts.connectSrc).join(' ')}`,
29
+ `object-src 'none'`,
30
+ `base-uri 'self'`,
31
+ `frame-ancestors ${merge('frameAncestors', opts.frameAncestors).join(' ')}`
32
+ ].join('; ');
33
+ }
@@ -0,0 +1,13 @@
1
+ import type { Handle, RequestEvent } from '@sveltejs/kit';
2
+ /**
3
+ * Returns true when a request is CSRF-safe: a non-mutating method, or a mutating
4
+ * method whose Origin/Referer matches the request URL origin (or the env allowlist).
5
+ * @internal
6
+ */
7
+ export declare function isCsrfSafe(event: RequestEvent): boolean;
8
+ /**
9
+ * SvelteKit handle that rejects mutating requests under `/admin/api/*` lacking a
10
+ * matching Origin/Referer header. Other paths and safe methods pass through.
11
+ * @internal
12
+ */
13
+ export declare const csrfGuard: Handle;