includio-cms 0.1.4 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/ROADMAP.md +18 -13
- package/dist/admin/api/accept-invite.js +1 -5
- package/dist/admin/api/invite.js +7 -16
- package/dist/admin/client/account/account-page.svelte +20 -50
- package/dist/admin/client/account/lang.d.ts +15 -23
- package/dist/admin/client/account/lang.js +51 -67
- package/dist/admin/client/account/preferences-section.svelte +26 -84
- package/dist/admin/client/account/profile-section.svelte +60 -40
- package/dist/admin/client/account/schema.d.ts +11 -3
- package/dist/admin/client/account/schema.js +25 -16
- package/dist/admin/client/account/security-section.svelte +139 -105
- package/dist/admin/client/account/sessions-section.svelte +35 -34
- package/dist/admin/client/admin/admin-after-login-layout-content.svelte +3 -5
- package/dist/admin/client/admin/admin-layout.svelte +3 -2
- package/dist/admin/client/admin/admin-preloader.svelte +36 -0
- package/dist/admin/client/admin/admin-preloader.svelte.d.ts +18 -0
- package/dist/admin/client/admin/dashboard-page.svelte +55 -41
- package/dist/admin/client/collection/a11y-score-cell.svelte +45 -0
- package/dist/admin/client/collection/a11y-score-cell.svelte.d.ts +6 -0
- package/dist/admin/client/collection/bulk-actions-bar.svelte +83 -0
- package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +9 -0
- package/dist/admin/client/collection/collection-entries.svelte +255 -260
- package/dist/admin/client/collection/collection-view.svelte.d.ts +4 -3
- package/dist/admin/client/collection/collection-view.svelte.js +9 -5
- package/dist/admin/client/collection/collection.svelte +22 -12
- package/dist/admin/client/collection/data-table.svelte +50 -39
- package/dist/admin/client/collection/data-table.svelte.d.ts +1 -0
- package/dist/admin/client/collection/date-cell.svelte +7 -5
- package/dist/admin/client/collection/date-cell.svelte.d.ts +1 -1
- package/dist/admin/client/collection/empty-state.svelte +28 -0
- package/dist/admin/client/collection/empty-state.svelte.d.ts +9 -0
- package/dist/admin/client/collection/entry-link.svelte +10 -4
- package/dist/admin/client/collection/entry-link.svelte.d.ts +1 -0
- package/dist/admin/client/collection/grid-view.svelte +21 -23
- package/dist/admin/client/collection/grid-view.svelte.d.ts +1 -2
- package/dist/admin/client/collection/row-actions.svelte +60 -0
- package/dist/admin/client/collection/row-actions.svelte.d.ts +9 -0
- package/dist/admin/client/collection/status-badge.svelte +7 -8
- package/dist/admin/client/collection/table-pagination.svelte +122 -79
- package/dist/admin/client/collection/table-pagination.svelte.d.ts +1 -0
- package/dist/admin/client/collection/table-toolbar.svelte +108 -88
- package/dist/admin/client/collection/table-toolbar.svelte.d.ts +8 -9
- package/dist/admin/client/entry/entry-form.svelte +109 -1
- package/dist/admin/client/entry/entry-header.svelte +96 -37
- package/dist/admin/client/entry/entry-header.svelte.d.ts +5 -0
- package/dist/admin/client/entry/entry.svelte +171 -60
- package/dist/admin/client/entry/header/a11y-validator.d.ts +46 -0
- package/dist/admin/client/entry/header/a11y-validator.js +311 -0
- package/dist/admin/client/entry/header/publish-panel.svelte +373 -131
- package/dist/admin/client/entry/header/publish-panel.svelte.d.ts +4 -0
- package/dist/admin/client/entry/header/save-indicator.svelte +33 -23
- package/dist/admin/client/entry/header/schedule-popover.svelte +1 -1
- package/dist/admin/client/entry/header/status-badge.svelte +25 -118
- package/dist/admin/client/entry/header/version-history-sheet.svelte +314 -98
- package/dist/admin/client/form/form-submission/form-submission.svelte +271 -83
- package/dist/admin/client/form/form-submission/submission-field.svelte +12 -12
- package/dist/admin/client/form/form-submissions.svelte +421 -139
- package/dist/admin/client/form/submission-link.svelte +8 -2
- package/dist/admin/client/form/submission-link.svelte.d.ts +1 -0
- package/dist/admin/client/form/submission-status-badge.svelte +18 -4
- package/dist/admin/client/form/submission-status-badge.svelte.d.ts +1 -0
- package/dist/admin/client/login/lang.d.ts +32 -0
- package/dist/admin/client/login/lang.js +66 -2
- package/dist/admin/client/login/login-form.svelte +237 -95
- package/dist/admin/client/login/login-form.svelte.d.ts +2 -17
- package/dist/admin/client/login/login-page.svelte +34 -98
- package/dist/admin/client/login/reset-password-page.svelte +235 -0
- package/dist/admin/client/login/reset-password-page.svelte.d.ts +4 -0
- package/dist/admin/client/login/schema.d.ts +15 -0
- package/dist/admin/client/login/schema.js +21 -0
- package/dist/admin/client/users/accept-invite-page.svelte +166 -37
- package/dist/admin/client/users/create-user-dialog.svelte +15 -7
- package/dist/admin/client/users/delete-user-dialog.svelte +81 -16
- package/dist/admin/client/users/delete-user-dialog.svelte.d.ts +4 -1
- package/dist/admin/client/users/edit-user-dialog.svelte +3 -0
- package/dist/admin/client/users/invite-user-dialog.svelte +16 -3
- package/dist/admin/client/users/lang.d.ts +27 -0
- package/dist/admin/client/users/lang.js +64 -10
- package/dist/admin/client/users/pending-invitations.svelte +59 -23
- package/dist/admin/client/users/users-page.svelte +471 -72
- package/dist/admin/components/accessibility/accessibility-overview.svelte +2 -7
- package/dist/admin/components/dashboard/a11y-gauge.svelte +90 -0
- package/dist/admin/components/dashboard/a11y-gauge.svelte.d.ts +18 -0
- package/dist/admin/components/dashboard/accessibility-hub.svelte +13 -12
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +71 -113
- package/dist/admin/components/dashboard/index.d.ts +4 -2
- package/dist/admin/components/dashboard/index.js +4 -2
- package/dist/admin/components/dashboard/recent-activity.svelte +53 -75
- package/dist/admin/components/dashboard/recent-entries.svelte +94 -0
- package/dist/admin/components/dashboard/recent-entries.svelte.d.ts +18 -0
- package/dist/admin/components/dashboard/stat-card.svelte +2 -2
- package/dist/admin/components/dashboard/tip-of-the-day.svelte +109 -0
- package/dist/admin/components/dashboard/tip-of-the-day.svelte.d.ts +3 -0
- package/dist/admin/components/dashboard/welcome-header.svelte +45 -0
- package/dist/admin/components/dashboard/welcome-header.svelte.d.ts +3 -0
- package/dist/admin/components/fields/{array-field.svelte → blocks-field.svelte} +4 -4
- package/dist/admin/components/fields/{array-field.svelte.d.ts → blocks-field.svelte.d.ts} +5 -5
- package/dist/admin/components/fields/content-field.svelte +27 -0
- package/dist/admin/components/fields/content-field.svelte.d.ts +31 -0
- package/dist/admin/components/fields/field-renderer.svelte +9 -7
- package/dist/admin/components/fields/image-field.svelte +2 -2
- package/dist/admin/components/fields/media-field.svelte +2 -2
- package/dist/admin/components/fields/seo-field.svelte +205 -25
- package/dist/admin/components/fields/simple-array-field.svelte +289 -0
- package/dist/admin/components/fields/simple-array-field.svelte.d.ts +30 -0
- package/dist/admin/components/fields/slug-field.svelte +3 -2
- package/dist/admin/components/fields/standalone-field-renderer.svelte +148 -0
- package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +9 -0
- package/dist/admin/components/fields/text-field-wrapper.svelte +13 -1
- package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
- package/dist/admin/components/fields/url-field.svelte +5 -4
- package/dist/admin/components/layout/app-sidebar.svelte +27 -24
- package/dist/admin/components/layout/lang.d.ts +6 -0
- package/dist/admin/components/layout/lang.js +13 -1
- package/dist/admin/components/layout/layout-renderer.svelte +352 -0
- package/dist/admin/components/layout/layout-renderer.svelte.d.ts +14 -0
- package/dist/admin/components/layout/nav-breadcrumbs.svelte +4 -4
- package/dist/admin/components/layout/nav-collections.svelte +65 -36
- package/dist/admin/components/layout/nav-footer.svelte +31 -0
- package/dist/admin/components/layout/nav-footer.svelte.d.ts +18 -0
- package/dist/admin/components/layout/nav-forms.svelte +55 -30
- package/dist/admin/components/layout/nav-main.svelte +14 -52
- package/dist/admin/components/layout/nav-search.svelte +4 -3
- package/dist/admin/components/layout/nav-singletons.svelte +59 -17
- package/dist/admin/components/layout/nav-singletons.svelte.d.ts +17 -8
- package/dist/admin/components/layout/site-header.svelte +74 -13
- package/dist/admin/components/media/alt-input.svelte +32 -22
- package/dist/admin/components/media/bulk-action-bar.svelte +139 -150
- package/dist/admin/components/media/file/file-details.svelte +299 -217
- package/dist/admin/components/media/file/file-miniature.svelte +54 -41
- package/dist/admin/components/media/file/file-miniature.svelte.d.ts +1 -0
- package/dist/admin/components/media/file/file-preview.svelte +1 -1
- package/dist/admin/components/media/file-upload.svelte +24 -26
- package/dist/admin/components/media/files-list.svelte +112 -40
- package/dist/admin/components/media/files-list.svelte.d.ts +2 -0
- package/dist/admin/components/media/focal-point-input.svelte +122 -26
- package/dist/admin/components/media/media-library.svelte +127 -70
- package/dist/admin/components/media/media-search.svelte +6 -6
- package/dist/admin/components/media/media-sort.svelte +3 -1
- package/dist/admin/components/media/multi-file-summary.svelte +88 -68
- package/dist/admin/components/media/tag-combobox.svelte +141 -66
- package/dist/admin/components/media/tag-combobox.svelte.d.ts +1 -0
- package/dist/admin/components/media/tag-sidebar.svelte +139 -121
- package/dist/admin/components/tiptap/FigureNodeView.svelte +144 -15
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +254 -0
- package/dist/admin/components/tiptap/InlineBlockNodeView.svelte.d.ts +4 -0
- package/dist/admin/components/tiptap/SlashCommandPopup.svelte +212 -0
- package/dist/admin/components/tiptap/SlashCommandPopup.svelte.d.ts +8 -0
- package/dist/admin/components/tiptap/content-editor.svelte +280 -0
- package/dist/admin/components/tiptap/content-editor.svelte.d.ts +9 -0
- package/dist/admin/components/tiptap/editor-toolbar.svelte +230 -0
- package/dist/admin/components/tiptap/editor-toolbar.svelte.d.ts +16 -0
- package/dist/admin/components/tiptap/heading-a11y-plugin.d.ts +2 -0
- package/dist/admin/components/tiptap/heading-a11y-plugin.js +67 -0
- package/dist/admin/components/tiptap/image-dialog.svelte +172 -11
- package/dist/admin/components/tiptap/inline-block-node.d.ts +19 -0
- package/dist/admin/components/tiptap/inline-block-node.js +98 -0
- package/dist/admin/components/tiptap/link-dialog.svelte +9 -4
- package/dist/admin/components/tiptap/slash-command.d.ts +17 -0
- package/dist/admin/components/tiptap/slash-command.js +181 -0
- package/dist/admin/components/tiptap/structured-content-utils.d.ts +21 -0
- package/dist/admin/components/tiptap/structured-content-utils.js +150 -0
- package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -190
- package/dist/admin/email/invite-template.d.ts +8 -0
- package/dist/admin/email/invite-template.js +99 -0
- package/dist/admin/email/reset-password-template.d.ts +7 -0
- package/dist/admin/email/reset-password-template.js +96 -0
- package/dist/admin/remote/ai.remote.d.ts +1 -0
- package/dist/admin/remote/ai.remote.js +4 -1
- package/dist/admin/remote/entry.remote.d.ts +8 -0
- package/dist/admin/remote/entry.remote.js +53 -4
- package/dist/admin/remote/preview.remote.js +2 -1
- package/dist/admin/shared/password-schema.d.ts +5 -0
- package/dist/admin/shared/password-schema.js +10 -0
- package/dist/admin/styles/admin.css +1530 -151
- package/dist/admin/utils/formatDate.d.ts +1 -0
- package/dist/admin/utils/formatDate.js +8 -0
- package/dist/admin/utils/roleLabel.d.ts +2 -0
- package/dist/admin/utils/roleLabel.js +13 -0
- package/dist/ai-claude/index.d.ts +2 -0
- package/dist/ai-claude/index.js +56 -0
- package/dist/cms/runtime/api.d.ts +6 -1
- package/dist/cms/runtime/api.js +3 -0
- package/dist/cms/runtime/schemas.d.ts +9 -1
- package/dist/cms/runtime/schemas.js +8 -0
- package/dist/cms/runtime/types.d.ts +82 -10
- package/dist/cms/runtime/types.js +4 -0
- package/dist/components/ui/accordion/accordion.stories.svelte +39 -0
- package/dist/components/ui/accordion/accordion.stories.svelte.d.ts +27 -0
- package/dist/components/ui/alert/alert.stories.svelte +53 -0
- package/dist/components/ui/alert/alert.stories.svelte.d.ts +27 -0
- package/dist/components/ui/alert/alert.svelte +5 -0
- package/dist/components/ui/alert/alert.svelte.d.ts +9 -0
- package/dist/components/ui/avatar/avatar.stories.svelte +16 -0
- package/dist/components/ui/avatar/avatar.stories.svelte.d.ts +27 -0
- package/dist/components/ui/badge/badge.stories.svelte +33 -0
- package/dist/components/ui/badge/badge.stories.svelte.d.ts +27 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +33 -0
- package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte.d.ts +27 -0
- package/dist/components/ui/button/button.stories.svelte +43 -0
- package/dist/components/ui/button/button.stories.svelte.d.ts +27 -0
- package/dist/components/ui/button/button.svelte +1 -2
- package/dist/components/ui/button/button.svelte.d.ts +0 -3
- package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
- package/dist/components/ui/card/card.stories.svelte +42 -0
- package/dist/components/ui/card/card.stories.svelte.d.ts +27 -0
- package/dist/components/ui/command/command.stories.svelte +51 -0
- package/dist/components/ui/command/command.stories.svelte.d.ts +27 -0
- package/dist/components/ui/dialog/dialog.stories.svelte +29 -0
- package/dist/components/ui/dialog/dialog.stories.svelte.d.ts +27 -0
- package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
- package/dist/components/ui/field/field.stories.svelte +21 -0
- package/dist/components/ui/field/field.stories.svelte.d.ts +27 -0
- package/dist/components/ui/input/input.stories.svelte +40 -0
- package/dist/components/ui/input/input.stories.svelte.d.ts +27 -0
- package/dist/components/ui/input/input.svelte +2 -4
- package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
- package/dist/components/ui/label/label.stories.svelte +20 -0
- package/dist/components/ui/label/label.stories.svelte.d.ts +27 -0
- package/dist/components/ui/popover/popover.stories.svelte +29 -0
- package/dist/components/ui/popover/popover.stories.svelte.d.ts +27 -0
- package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
- package/dist/components/ui/select/select.stories.svelte +23 -0
- package/dist/components/ui/select/select.stories.svelte.d.ts +27 -0
- package/dist/components/ui/separator/separator.stories.svelte +24 -0
- package/dist/components/ui/separator/separator.stories.svelte.d.ts +27 -0
- package/dist/components/ui/sheet/sheet.stories.svelte +29 -0
- package/dist/components/ui/sheet/sheet.stories.svelte.d.ts +27 -0
- package/dist/components/ui/sidebar/sidebar-group.svelte +3 -3
- package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +2 -2
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +28 -30
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +7 -7
- package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +4 -4
- package/dist/components/ui/sonner/sonner.stories.svelte +22 -0
- package/dist/components/ui/sonner/sonner.stories.svelte.d.ts +26 -0
- package/dist/components/ui/sonner/sonner.svelte +8 -2
- package/dist/components/ui/sonner/toast-demo.svelte +29 -0
- package/dist/components/ui/sonner/toast-demo.svelte.d.ts +6 -0
- package/dist/components/ui/textarea/textarea.stories.svelte +22 -0
- package/dist/components/ui/textarea/textarea.stories.svelte.d.ts +27 -0
- package/dist/components/ui/textarea/textarea.svelte +0 -2
- package/dist/components/ui/toggle/toggle.stories.svelte +22 -0
- package/dist/components/ui/toggle/toggle.stories.svelte.d.ts +27 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte +17 -0
- package/dist/components/ui/toggle-group/toggle-group.stories.svelte.d.ts +27 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte +26 -0
- package/dist/components/ui/tooltip/tooltip.stories.svelte.d.ts +27 -0
- package/dist/core/fields/fieldSchemaToTs.d.ts +1 -0
- package/dist/core/fields/fieldSchemaToTs.js +133 -1
- package/dist/core/fields/layoutUtils.d.ts +17 -0
- package/dist/core/fields/layoutUtils.js +149 -0
- package/dist/core/fields/structuredToHtml.d.ts +9 -0
- package/dist/core/fields/structuredToHtml.js +161 -0
- package/dist/core/server/entries/operations/create.js +2 -1
- package/dist/core/server/entries/operations/get.js +8 -6
- package/dist/core/server/entries/operations/update.d.ts +3 -0
- package/dist/core/server/entries/operations/update.js +30 -2
- package/dist/core/server/fields/queryStructuredContent.d.ts +15 -0
- package/dist/core/server/fields/queryStructuredContent.js +65 -0
- package/dist/core/server/fields/resolveImageFields.js +51 -2
- package/dist/core/server/fields/resolveRelationFields.js +2 -2
- package/dist/core/server/fields/resolveRichtextLinks.js +80 -13
- package/dist/core/server/fields/resolveUrlFields.js +57 -6
- package/dist/core/server/fields/slugResolver.d.ts +10 -0
- package/dist/core/server/fields/slugResolver.js +34 -0
- package/dist/core/server/generator/fields.js +15 -4
- package/dist/core/server/generator/generator.js +3 -2
- package/dist/files-local/index.js +126 -64
- package/dist/server/auth.d.ts +5 -0
- package/dist/server/auth.js +12 -1
- package/dist/sveltekit/components/structured-content.svelte +204 -0
- package/dist/sveltekit/components/structured-content.svelte.d.ts +21 -0
- package/dist/sveltekit/config.d.ts +13 -3
- package/dist/sveltekit/index.d.ts +3 -0
- package/dist/sveltekit/index.js +3 -0
- package/dist/sveltekit/server/handle.js +1 -0
- package/dist/types/config.d.ts +3 -0
- package/dist/types/fields.d.ts +19 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +2 -0
- package/dist/types/layout.d.ts +54 -0
- package/dist/types/layout.js +6 -0
- package/dist/types/structured-content.d.ts +63 -0
- package/dist/types/structured-content.js +1 -0
- package/dist/updates/0.1.5/index.d.ts +2 -0
- package/dist/updates/0.1.5/index.js +18 -0
- package/dist/updates/0.2.0/index.d.ts +2 -0
- package/dist/updates/0.2.0/index.js +11 -0
- package/dist/updates/0.2.2/index.d.ts +2 -0
- package/dist/updates/0.2.2/index.js +13 -0
- package/dist/updates/0.5.0/index.d.ts +2 -0
- package/dist/updates/0.5.0/index.js +14 -0
- package/dist/updates/index.js +5 -1
- package/package.json +16 -9
|
@@ -15,76 +15,138 @@ const ffmpegPath = process.env.FFMPEG_PATH || '/usr/bin/ffmpeg';
|
|
|
15
15
|
const ffprobePath = process.env.FFPROBE_PATH || '/usr/bin/ffprobe';
|
|
16
16
|
ffmpeg.setFfmpegPath(ffmpegPath);
|
|
17
17
|
ffmpeg.setFfprobePath(ffprobePath);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
function withTimeout(promise, ms, label) {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
21
|
+
promise.then((val) => {
|
|
22
|
+
clearTimeout(timer);
|
|
23
|
+
resolve(val);
|
|
24
|
+
}, (err) => {
|
|
25
|
+
clearTimeout(timer);
|
|
26
|
+
reject(err);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function probeVideo(filepath) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
ffmpeg.ffprobe(filepath, (err, metadata) => {
|
|
33
|
+
if (err) {
|
|
34
|
+
reject(new Error(`ffprobe failed: ${err.message || err}`));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const videoStream = metadata.streams.find((s) => s.codec_type === 'video');
|
|
38
|
+
const duration = metadata.format.duration ?? null;
|
|
27
39
|
resolve({
|
|
28
|
-
width: null,
|
|
29
|
-
height: null,
|
|
30
|
-
duration: null
|
|
31
|
-
thumbnailUrl: null,
|
|
32
|
-
posterUrl: null
|
|
33
|
-
});
|
|
34
|
-
})
|
|
35
|
-
.on('end', () => {
|
|
36
|
-
// Po wygenerowaniu thumbnaiła, generujemy poster (wyższa jakość)
|
|
37
|
-
ffmpeg(filepath)
|
|
38
|
-
.on('error', () => {
|
|
39
|
-
// Poster failed, continue with thumbnail only
|
|
40
|
-
ffmpeg.ffprobe(filepath, (err, metadata) => {
|
|
41
|
-
if (err) {
|
|
42
|
-
resolve({ width: null, height: null, duration: null, thumbnailUrl, posterUrl: null });
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
const videoStream = metadata.streams.find((s) => s.codec_type === 'video');
|
|
46
|
-
const duration = metadata.format.duration || null;
|
|
47
|
-
resolve({
|
|
48
|
-
width: videoStream?.width || null,
|
|
49
|
-
height: videoStream?.height || null,
|
|
50
|
-
duration: duration ? Math.round(duration) : null,
|
|
51
|
-
thumbnailUrl,
|
|
52
|
-
posterUrl: null
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
})
|
|
56
|
-
.on('end', () => {
|
|
57
|
-
ffmpeg.ffprobe(filepath, (err, metadata) => {
|
|
58
|
-
if (err) {
|
|
59
|
-
resolve({ width: null, height: null, duration: null, thumbnailUrl, posterUrl });
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const videoStream = metadata.streams.find((s) => s.codec_type === 'video');
|
|
63
|
-
const duration = metadata.format.duration || null;
|
|
64
|
-
resolve({
|
|
65
|
-
width: videoStream?.width || null,
|
|
66
|
-
height: videoStream?.height || null,
|
|
67
|
-
duration: duration ? Math.round(duration) : null,
|
|
68
|
-
thumbnailUrl,
|
|
69
|
-
posterUrl
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
})
|
|
73
|
-
.screenshots({
|
|
74
|
-
timestamps: ['00:00:01'],
|
|
75
|
-
filename: posterFilename,
|
|
76
|
-
folder: fullDir,
|
|
77
|
-
size: '1280x?' // Poster: szerszy, proporcjonalny
|
|
40
|
+
width: videoStream?.width ?? null,
|
|
41
|
+
height: videoStream?.height ?? null,
|
|
42
|
+
duration: duration ? Math.round(duration * 100) / 100 : null
|
|
78
43
|
});
|
|
79
|
-
})
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function takeScreenshot(filepath, config) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
ffmpeg(filepath)
|
|
50
|
+
.on('error', (err) => reject(new Error(`Screenshot failed: ${err.message || err}`)))
|
|
51
|
+
.on('end', () => resolve())
|
|
80
52
|
.screenshots({
|
|
81
|
-
timestamps: [
|
|
82
|
-
filename:
|
|
83
|
-
folder:
|
|
84
|
-
size:
|
|
53
|
+
timestamps: [config.timestamp],
|
|
54
|
+
filename: config.filename,
|
|
55
|
+
folder: config.folder,
|
|
56
|
+
size: config.size
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function getSafeTimestamp(duration) {
|
|
61
|
+
if (duration === null || duration <= 0)
|
|
62
|
+
return '00:00:00.000';
|
|
63
|
+
if (duration < 1)
|
|
64
|
+
return '00:00:00.000';
|
|
65
|
+
if (duration < 3) {
|
|
66
|
+
const t = duration * 0.1;
|
|
67
|
+
return formatTimestamp(t);
|
|
68
|
+
}
|
|
69
|
+
return formatTimestamp(Math.min(1, duration * 0.1));
|
|
70
|
+
}
|
|
71
|
+
function formatTimestamp(seconds) {
|
|
72
|
+
const h = Math.floor(seconds / 3600);
|
|
73
|
+
const m = Math.floor((seconds % 3600) / 60);
|
|
74
|
+
const s = seconds % 60;
|
|
75
|
+
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${s.toFixed(3).padStart(6, '0')}`;
|
|
76
|
+
}
|
|
77
|
+
let ffmpegAvailable = null;
|
|
78
|
+
async function checkFfmpegAvailable() {
|
|
79
|
+
if (ffmpegAvailable !== null)
|
|
80
|
+
return ffmpegAvailable;
|
|
81
|
+
return new Promise((resolve) => {
|
|
82
|
+
ffmpeg.ffprobe('/dev/null', (err) => {
|
|
83
|
+
if (err && (String(err).includes('ENOENT') || String(err).includes('spawn'))) {
|
|
84
|
+
console.warn('[video] ffmpeg/ffprobe not found — video thumbnails disabled');
|
|
85
|
+
ffmpegAvailable = false;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
ffmpegAvailable = true;
|
|
89
|
+
}
|
|
90
|
+
resolve(ffmpegAvailable);
|
|
85
91
|
});
|
|
86
92
|
});
|
|
87
93
|
}
|
|
94
|
+
async function processVideo(filepath, filename) {
|
|
95
|
+
if (!(await checkFfmpegAvailable())) {
|
|
96
|
+
console.warn(`[video] Skipping processing for ${filename}: ffmpeg not available`);
|
|
97
|
+
return { width: null, height: null, duration: null, thumbnailUrl: null, posterUrl: null };
|
|
98
|
+
}
|
|
99
|
+
const thumbnailFilename = `${filename}_thumb.jpg`;
|
|
100
|
+
const thumbnailUrl = `/uploads/${thumbnailFilename}`;
|
|
101
|
+
const posterFilename = `${filename}_poster.jpg`;
|
|
102
|
+
const posterUrl = `/uploads/${posterFilename}`;
|
|
103
|
+
// 1. Probe — get metadata first
|
|
104
|
+
let probe;
|
|
105
|
+
try {
|
|
106
|
+
probe = await withTimeout(probeVideo(filepath), 10_000, 'ffprobe');
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
console.warn(`[video] ffprobe failed for ${filename}:`, err);
|
|
110
|
+
return { width: null, height: null, duration: null, thumbnailUrl: null, posterUrl: null };
|
|
111
|
+
}
|
|
112
|
+
const timestamp = getSafeTimestamp(probe.duration);
|
|
113
|
+
// 2. Thumbnail (320px wide, maintain aspect ratio)
|
|
114
|
+
let finalThumbnailUrl = null;
|
|
115
|
+
try {
|
|
116
|
+
await withTimeout(takeScreenshot(filepath, {
|
|
117
|
+
timestamp,
|
|
118
|
+
filename: thumbnailFilename,
|
|
119
|
+
folder: fullDir,
|
|
120
|
+
size: '320x?'
|
|
121
|
+
}), 15_000, 'thumbnail');
|
|
122
|
+
finalThumbnailUrl = thumbnailUrl;
|
|
123
|
+
}
|
|
124
|
+
catch (err) {
|
|
125
|
+
console.warn(`[video] Thumbnail failed for ${filename}:`, err);
|
|
126
|
+
}
|
|
127
|
+
// 3. Poster (up to 1280px wide, no upscale)
|
|
128
|
+
let finalPosterUrl = null;
|
|
129
|
+
const posterWidth = Math.min(1280, probe.width ?? 1280);
|
|
130
|
+
try {
|
|
131
|
+
await withTimeout(takeScreenshot(filepath, {
|
|
132
|
+
timestamp,
|
|
133
|
+
filename: posterFilename,
|
|
134
|
+
folder: fullDir,
|
|
135
|
+
size: `${posterWidth}x?`
|
|
136
|
+
}), 15_000, 'poster');
|
|
137
|
+
finalPosterUrl = posterUrl;
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
console.warn(`[video] Poster failed for ${filename}:`, err);
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
width: probe.width,
|
|
144
|
+
height: probe.height,
|
|
145
|
+
duration: probe.duration ? Math.round(probe.duration) : null,
|
|
146
|
+
thumbnailUrl: finalThumbnailUrl,
|
|
147
|
+
posterUrl: finalPosterUrl
|
|
148
|
+
};
|
|
149
|
+
}
|
|
88
150
|
async function ensureDir(dir) {
|
|
89
151
|
try {
|
|
90
152
|
await mkdir(dir, { recursive: true });
|
package/dist/server/auth.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ export declare const auth: import("better-auth", { with: { "resolution-mode": "r
|
|
|
2
2
|
database: (options: import("better-auth", { with: { "resolution-mode": "require" } }).BetterAuthOptions) => import("better-auth/adapters/drizzle", { with: { "resolution-mode": "require" } }).DBAdapter<import("better-auth", { with: { "resolution-mode": "require" } }).BetterAuthOptions>;
|
|
3
3
|
emailAndPassword: {
|
|
4
4
|
enabled: true;
|
|
5
|
+
sendResetPassword({ user, url }: {
|
|
6
|
+
user: import("better-auth", { with: { "resolution-mode": "require" } }).User;
|
|
7
|
+
url: string;
|
|
8
|
+
token: string;
|
|
9
|
+
}, request: Request | undefined): Promise<void>;
|
|
5
10
|
};
|
|
6
11
|
plugins: [{
|
|
7
12
|
id: "admin";
|
package/dist/server/auth.js
CHANGED
|
@@ -2,12 +2,23 @@ import { betterAuth } from 'better-auth';
|
|
|
2
2
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
|
|
3
3
|
import { db } from './db/index.js';
|
|
4
4
|
import { admin } from 'better-auth/plugins';
|
|
5
|
+
import { getCMS } from '../core/cms.js';
|
|
6
|
+
import { resetPasswordEmailTemplate } from '../admin/email/reset-password-template.js';
|
|
5
7
|
export const auth = betterAuth({
|
|
6
8
|
database: drizzleAdapter(db, {
|
|
7
9
|
provider: 'pg'
|
|
8
10
|
}),
|
|
9
11
|
emailAndPassword: {
|
|
10
|
-
enabled: true
|
|
12
|
+
enabled: true,
|
|
13
|
+
async sendResetPassword({ user, url }, request) {
|
|
14
|
+
const emailAdapter = getCMS().emailAdapter;
|
|
15
|
+
if (!emailAdapter) {
|
|
16
|
+
throw new Error('Email adapter not configured');
|
|
17
|
+
}
|
|
18
|
+
const lang = request?.headers.get('Accept-Language')?.startsWith('pl') ? 'pl' : 'en';
|
|
19
|
+
const { subject, html } = resetPasswordEmailTemplate({ resetUrl: url, lang });
|
|
20
|
+
await emailAdapter.sendMail({ to: [user.email], subject, html });
|
|
21
|
+
}
|
|
11
22
|
},
|
|
12
23
|
plugins: [admin()]
|
|
13
24
|
});
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { SCNode, SCMark, StructuredContentDoc, SCInlineBlockAttrs } from '../../types/structured-content.js';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
|
|
5
|
+
export interface StructuredContentProps {
|
|
6
|
+
doc: StructuredContentDoc;
|
|
7
|
+
class?: string;
|
|
8
|
+
/** Override rendering for inline blocks. Receives blockType, blockData, blockId. */
|
|
9
|
+
inlineBlock?: Snippet<[string, Record<string, unknown>, string]>;
|
|
10
|
+
/** Override rendering for figure nodes. Receives node attrs. */
|
|
11
|
+
figure?: Snippet<[Record<string, unknown>]>;
|
|
12
|
+
/** Override rendering for video nodes. Receives node attrs. */
|
|
13
|
+
video?: Snippet<[Record<string, unknown>]>;
|
|
14
|
+
/** Override rendering for heading nodes. Receives level and children snippet. */
|
|
15
|
+
heading?: Snippet<[number, Snippet]>;
|
|
16
|
+
/** Override rendering for paragraph nodes. Receives children snippet. */
|
|
17
|
+
paragraph?: Snippet<[Snippet]>;
|
|
18
|
+
/** Override rendering for code block nodes. Receives language and text content. */
|
|
19
|
+
codeBlock?: Snippet<[string | undefined, string]>;
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<script lang="ts">
|
|
24
|
+
import Image from './image.svelte';
|
|
25
|
+
|
|
26
|
+
let {
|
|
27
|
+
doc,
|
|
28
|
+
class: className,
|
|
29
|
+
inlineBlock: inlineBlockSnippet,
|
|
30
|
+
figure: figureSnippet,
|
|
31
|
+
video: videoSnippet,
|
|
32
|
+
heading: headingSnippet,
|
|
33
|
+
paragraph: paragraphSnippet,
|
|
34
|
+
codeBlock: codeBlockSnippet
|
|
35
|
+
}: StructuredContentProps = $props();
|
|
36
|
+
|
|
37
|
+
function getTextContent(node: SCNode): string {
|
|
38
|
+
if (node.type === 'text') return node.text ?? '';
|
|
39
|
+
return node.content?.map(getTextContent).join('') ?? '';
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
{#snippet renderMark(text: string, marks: SCMark[], index: number)}
|
|
44
|
+
{#if index >= marks.length}
|
|
45
|
+
{text}
|
|
46
|
+
{:else}
|
|
47
|
+
{@const mark = marks[index]}
|
|
48
|
+
{#if mark.type === 'bold'}
|
|
49
|
+
<strong>{@render renderMark(text, marks, index + 1)}</strong>
|
|
50
|
+
{:else if mark.type === 'italic'}
|
|
51
|
+
<em>{@render renderMark(text, marks, index + 1)}</em>
|
|
52
|
+
{:else if mark.type === 'underline'}
|
|
53
|
+
<u>{@render renderMark(text, marks, index + 1)}</u>
|
|
54
|
+
{:else if mark.type === 'strike'}
|
|
55
|
+
<s>{@render renderMark(text, marks, index + 1)}</s>
|
|
56
|
+
{:else if mark.type === 'code'}
|
|
57
|
+
<code>{@render renderMark(text, marks, index + 1)}</code>
|
|
58
|
+
{:else if mark.type === 'highlight'}
|
|
59
|
+
<mark>{@render renderMark(text, marks, index + 1)}</mark>
|
|
60
|
+
{:else if mark.type === 'link'}
|
|
61
|
+
{@const href = (mark.attrs?.href as string) ?? ''}
|
|
62
|
+
{@const target = mark.attrs?.target as string | undefined}
|
|
63
|
+
{@const title = mark.attrs?.title as string | undefined}
|
|
64
|
+
{@const ariaLabel = mark.attrs?.['aria-label'] as string | undefined}
|
|
65
|
+
<a
|
|
66
|
+
{href}
|
|
67
|
+
target={target ?? undefined}
|
|
68
|
+
rel={target === '_blank' ? 'noopener noreferrer' : undefined}
|
|
69
|
+
{title}
|
|
70
|
+
aria-label={ariaLabel ?? undefined}
|
|
71
|
+
>{@render renderMark(text, marks, index + 1)}</a>
|
|
72
|
+
{:else}
|
|
73
|
+
{@render renderMark(text, marks, index + 1)}
|
|
74
|
+
{/if}
|
|
75
|
+
{/if}
|
|
76
|
+
{/snippet}
|
|
77
|
+
|
|
78
|
+
{#snippet renderNode(node: SCNode)}
|
|
79
|
+
{#if node.type === 'text'}
|
|
80
|
+
{#if node.marks?.length}
|
|
81
|
+
{@render renderMark(node.text ?? '', node.marks, 0)}
|
|
82
|
+
{:else}
|
|
83
|
+
{node.text}
|
|
84
|
+
{/if}
|
|
85
|
+
{:else if node.type === 'paragraph'}
|
|
86
|
+
{#if paragraphSnippet}
|
|
87
|
+
{@render paragraphSnippet(renderChildren)}
|
|
88
|
+
{:else}
|
|
89
|
+
<p>{@render renderChildren()}</p>
|
|
90
|
+
{/if}
|
|
91
|
+
{:else if node.type === 'heading'}
|
|
92
|
+
{@const level = (node.attrs?.level as number) ?? 2}
|
|
93
|
+
{#if headingSnippet}
|
|
94
|
+
{@render headingSnippet(level, renderChildren)}
|
|
95
|
+
{:else if level === 2}
|
|
96
|
+
<h2>{@render renderChildren()}</h2>
|
|
97
|
+
{:else if level === 3}
|
|
98
|
+
<h3>{@render renderChildren()}</h3>
|
|
99
|
+
{/if}
|
|
100
|
+
{:else if node.type === 'blockquote'}
|
|
101
|
+
<blockquote>{@render renderChildren()}</blockquote>
|
|
102
|
+
{:else if node.type === 'bulletList'}
|
|
103
|
+
<ul>{@render renderChildren()}</ul>
|
|
104
|
+
{:else if node.type === 'orderedList'}
|
|
105
|
+
<ol>{@render renderChildren()}</ol>
|
|
106
|
+
{:else if node.type === 'listItem'}
|
|
107
|
+
<li>{@render renderChildren()}</li>
|
|
108
|
+
{:else if node.type === 'codeBlock'}
|
|
109
|
+
{#if codeBlockSnippet}
|
|
110
|
+
{@render codeBlockSnippet(node.attrs?.language as string | undefined, getTextContent(node))}
|
|
111
|
+
{:else}
|
|
112
|
+
{@const lang = node.attrs?.language as string | undefined}
|
|
113
|
+
<pre><code class={lang ? `language-${lang}` : undefined}>{@render renderChildren()}</code></pre>
|
|
114
|
+
{/if}
|
|
115
|
+
{:else if node.type === 'horizontalRule'}
|
|
116
|
+
<hr>
|
|
117
|
+
{:else if node.type === 'hardBreak'}
|
|
118
|
+
<br>
|
|
119
|
+
{:else if node.type === 'figure'}
|
|
120
|
+
{#if figureSnippet}
|
|
121
|
+
{@render figureSnippet(node.attrs ?? {})}
|
|
122
|
+
{:else}
|
|
123
|
+
{@const attrs = node.attrs ?? {}}
|
|
124
|
+
{@const rawMedia = attrs._media as { data: import('../../types/media.js').MediaFile; styles?: Record<string, import('../../types/media.js').ImageStyle>; blurDataUrl?: string | null } | undefined}
|
|
125
|
+
{@const figMedia = rawMedia?.data ? { data: rawMedia.data, styles: rawMedia.styles ?? {}, blurDataUrl: rawMedia.blurDataUrl } : undefined}
|
|
126
|
+
<figure>
|
|
127
|
+
{#if figMedia}
|
|
128
|
+
<Image data={figMedia} alt={attrs.alt as string ?? figMedia.data.alt ?? ''} />
|
|
129
|
+
{:else}
|
|
130
|
+
<img
|
|
131
|
+
src={attrs.src as string}
|
|
132
|
+
alt={(attrs.alt as string) ?? ''}
|
|
133
|
+
width={attrs.width as number ?? undefined}
|
|
134
|
+
height={attrs.height as number ?? undefined}
|
|
135
|
+
loading="lazy"
|
|
136
|
+
>
|
|
137
|
+
{/if}
|
|
138
|
+
{#if attrs.caption}
|
|
139
|
+
<figcaption>{attrs.caption}</figcaption>
|
|
140
|
+
{/if}
|
|
141
|
+
</figure>
|
|
142
|
+
{/if}
|
|
143
|
+
{:else if node.type === 'image'}
|
|
144
|
+
{@const attrs = node.attrs ?? {}}
|
|
145
|
+
{@const rawImgMedia = attrs._media as { data: import('../../types/media.js').MediaFile; styles?: Record<string, import('../../types/media.js').ImageStyle>; blurDataUrl?: string | null } | undefined}
|
|
146
|
+
{@const imgMedia = rawImgMedia?.data ? { data: rawImgMedia.data, styles: rawImgMedia.styles ?? {}, blurDataUrl: rawImgMedia.blurDataUrl } : undefined}
|
|
147
|
+
{#if imgMedia}
|
|
148
|
+
<Image data={imgMedia} alt={attrs.alt as string ?? imgMedia.data.alt ?? ''} />
|
|
149
|
+
{:else}
|
|
150
|
+
<img
|
|
151
|
+
src={attrs.src as string}
|
|
152
|
+
alt={(attrs.alt as string) ?? ''}
|
|
153
|
+
width={attrs.width as number ?? undefined}
|
|
154
|
+
height={attrs.height as number ?? undefined}
|
|
155
|
+
loading="lazy"
|
|
156
|
+
>
|
|
157
|
+
{/if}
|
|
158
|
+
{:else if node.type === 'video'}
|
|
159
|
+
{#if videoSnippet}
|
|
160
|
+
{@render videoSnippet(node.attrs ?? {})}
|
|
161
|
+
{:else}
|
|
162
|
+
{@const attrs = node.attrs ?? {}}
|
|
163
|
+
<video
|
|
164
|
+
controls
|
|
165
|
+
poster={attrs.poster as string ?? undefined}
|
|
166
|
+
width={attrs.width as number ?? undefined}
|
|
167
|
+
height={attrs.height as number ?? undefined}
|
|
168
|
+
>
|
|
169
|
+
<source src={attrs.src as string}>
|
|
170
|
+
</video>
|
|
171
|
+
{/if}
|
|
172
|
+
{:else if node.type === 'table'}
|
|
173
|
+
<table>{@render renderChildren()}</table>
|
|
174
|
+
{:else if node.type === 'tableRow'}
|
|
175
|
+
<tr>{@render renderChildren()}</tr>
|
|
176
|
+
{:else if node.type === 'tableCell'}
|
|
177
|
+
<td>{@render renderChildren()}</td>
|
|
178
|
+
{:else if node.type === 'tableHeader'}
|
|
179
|
+
<th>{@render renderChildren()}</th>
|
|
180
|
+
{:else if node.type === 'inlineBlock'}
|
|
181
|
+
{#if inlineBlockSnippet}
|
|
182
|
+
{@const attrs = node.attrs as unknown as SCInlineBlockAttrs}
|
|
183
|
+
{@render inlineBlockSnippet(attrs.blockType, attrs.blockData, attrs.blockId)}
|
|
184
|
+
{/if}
|
|
185
|
+
{:else}
|
|
186
|
+
{@render renderChildren()}
|
|
187
|
+
{/if}
|
|
188
|
+
|
|
189
|
+
{#snippet renderChildren()}
|
|
190
|
+
{#if node.content}
|
|
191
|
+
{#each node.content as child}
|
|
192
|
+
{@render renderNode(child)}
|
|
193
|
+
{/each}
|
|
194
|
+
{/if}
|
|
195
|
+
{/snippet}
|
|
196
|
+
{/snippet}
|
|
197
|
+
|
|
198
|
+
{#if doc?.content}
|
|
199
|
+
<div class={className}>
|
|
200
|
+
{#each doc.content as node}
|
|
201
|
+
{@render renderNode(node)}
|
|
202
|
+
{/each}
|
|
203
|
+
</div>
|
|
204
|
+
{/if}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { StructuredContentDoc } from '../../types/structured-content.js';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
export interface StructuredContentProps {
|
|
4
|
+
doc: StructuredContentDoc;
|
|
5
|
+
class?: string;
|
|
6
|
+
/** Override rendering for inline blocks. Receives blockType, blockData, blockId. */
|
|
7
|
+
inlineBlock?: Snippet<[string, Record<string, unknown>, string]>;
|
|
8
|
+
/** Override rendering for figure nodes. Receives node attrs. */
|
|
9
|
+
figure?: Snippet<[Record<string, unknown>]>;
|
|
10
|
+
/** Override rendering for video nodes. Receives node attrs. */
|
|
11
|
+
video?: Snippet<[Record<string, unknown>]>;
|
|
12
|
+
/** Override rendering for heading nodes. Receives level and children snippet. */
|
|
13
|
+
heading?: Snippet<[number, Snippet]>;
|
|
14
|
+
/** Override rendering for paragraph nodes. Receives children snippet. */
|
|
15
|
+
paragraph?: Snippet<[Snippet]>;
|
|
16
|
+
/** Override rendering for code block nodes. Receives language and text content. */
|
|
17
|
+
codeBlock?: Snippet<[string | undefined, string]>;
|
|
18
|
+
}
|
|
19
|
+
declare const StructuredContent: import("svelte").Component<StructuredContentProps, {}, "">;
|
|
20
|
+
type StructuredContent = ReturnType<typeof StructuredContent>;
|
|
21
|
+
export default StructuredContent;
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import type { CMSConfig } from '../types/cms.js';
|
|
2
2
|
import type { CollectionConfig } from '../types/collections.js';
|
|
3
3
|
import type { SingleConfig } from '../types/singles.js';
|
|
4
|
-
import type { ObjectField } from '../types/fields.js';
|
|
4
|
+
import type { Field, ObjectField } from '../types/fields.js';
|
|
5
5
|
import type { FormConfig } from '../types/forms.js';
|
|
6
|
+
import type { Layout } from '../types/layout.js';
|
|
7
|
+
type CollectionInput = Omit<CollectionConfig, 'fields'> & {
|
|
8
|
+
fields: Field[];
|
|
9
|
+
layout?: Layout;
|
|
10
|
+
};
|
|
11
|
+
type SingleInput = Omit<SingleConfig, 'fields'> & {
|
|
12
|
+
fields: Field[];
|
|
13
|
+
layout?: Layout;
|
|
14
|
+
};
|
|
6
15
|
export declare function defineConfig(config: CMSConfig): CMSConfig;
|
|
7
|
-
export declare function defineCollection(config:
|
|
8
|
-
export declare function defineSingle(config:
|
|
16
|
+
export declare function defineCollection(config: CollectionInput): CollectionConfig;
|
|
17
|
+
export declare function defineSingle(config: SingleInput): SingleConfig;
|
|
9
18
|
export declare function defineForm(config: FormConfig): FormConfig;
|
|
10
19
|
export declare function defineObject(config: Omit<ObjectField, 'type'>): ObjectField;
|
|
20
|
+
export {};
|
|
@@ -5,5 +5,8 @@ export { default as HybridTarget } from './components/hybrid-target.svelte';
|
|
|
5
5
|
export { default as Image } from './components/image.svelte';
|
|
6
6
|
export { default as Video } from './components/video.svelte';
|
|
7
7
|
export { default as Media } from './components/media.svelte';
|
|
8
|
+
export { default as StructuredContent } from './components/structured-content.svelte';
|
|
8
9
|
export { enableHybridEditing } from './components/hybrid-context.js';
|
|
9
10
|
export { getLink, isImageFieldData, isVideoFieldData } from './utils/index.js';
|
|
11
|
+
export { structuredToHtml } from '../core/fields/structuredToHtml.js';
|
|
12
|
+
export { extractBlocks, extractInlineBlocks, extractText, extractMediaRefs } from '../core/server/fields/queryStructuredContent.js';
|
package/dist/sveltekit/index.js
CHANGED
|
@@ -5,5 +5,8 @@ export { default as HybridTarget } from './components/hybrid-target.svelte';
|
|
|
5
5
|
export { default as Image } from './components/image.svelte';
|
|
6
6
|
export { default as Video } from './components/video.svelte';
|
|
7
7
|
export { default as Media } from './components/media.svelte';
|
|
8
|
+
export { default as StructuredContent } from './components/structured-content.svelte';
|
|
8
9
|
export { enableHybridEditing } from './components/hybrid-context.js';
|
|
9
10
|
export { getLink, isImageFieldData, isVideoFieldData } from './utils/index.js';
|
|
11
|
+
export { structuredToHtml } from '../core/fields/structuredToHtml.js';
|
|
12
|
+
export { extractBlocks, extractInlineBlocks, extractText, extractMediaRefs } from '../core/server/fields/queryStructuredContent.js';
|
|
@@ -10,6 +10,7 @@ const adminGuard = async ({ event, resolve }) => {
|
|
|
10
10
|
!event.url.pathname.startsWith('/api/admin/login') &&
|
|
11
11
|
!event.url.pathname.startsWith('/admin/accept-invite') &&
|
|
12
12
|
!event.url.pathname.startsWith('/admin/api/accept-invite') &&
|
|
13
|
+
!event.url.pathname.startsWith('/admin/reset-password') &&
|
|
13
14
|
(!user || !session)) {
|
|
14
15
|
setFlash({
|
|
15
16
|
message: 'You must be logged in to access the admin panel.',
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { Field } from './fields.js';
|
|
2
2
|
import type { Icon } from '@tabler/icons-svelte';
|
|
3
|
+
import type { Layout } from './layout.js';
|
|
3
4
|
export interface ConfigBase {
|
|
4
5
|
sidebarIcon?: Icon;
|
|
5
6
|
slug: string;
|
|
6
7
|
previewUrl?: string;
|
|
7
8
|
fields: Field[];
|
|
9
|
+
layout?: Layout;
|
|
10
|
+
slugField?: string;
|
|
8
11
|
}
|
package/dist/types/fields.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { FormatEnum } from 'sharp';
|
|
2
2
|
import type { ImageStyle, MediaFile } from './media.js';
|
|
3
3
|
import type { Localized } from './languages.js';
|
|
4
|
-
|
|
4
|
+
import type { StructuredContentDoc } from './structured-content.js';
|
|
5
|
+
export type FieldType = 'text' | 'richtext' | 'content' | 'number' | 'boolean' | 'date' | 'datetime' | 'file' | 'image' | 'media' | 'select' | 'radio' | 'checkboxes' | 'relation' | 'object' | 'array' | 'blocks' | 'slug' | 'seo' | 'url';
|
|
5
6
|
export interface BaseField {
|
|
6
7
|
slug: string;
|
|
7
8
|
label?: Localized;
|
|
@@ -25,6 +26,11 @@ export interface RichtextField extends BaseField {
|
|
|
25
26
|
allowedFormats?: string[];
|
|
26
27
|
defaultValue?: string;
|
|
27
28
|
}
|
|
29
|
+
export interface ContentField extends BaseField {
|
|
30
|
+
type: 'content';
|
|
31
|
+
inlineBlocks?: ObjectField[];
|
|
32
|
+
defaultValue?: StructuredContentDoc;
|
|
33
|
+
}
|
|
28
34
|
export interface NumberField extends BaseField {
|
|
29
35
|
type: 'number';
|
|
30
36
|
min?: number;
|
|
@@ -141,8 +147,16 @@ export interface ObjectFieldData {
|
|
|
141
147
|
slug?: string;
|
|
142
148
|
data: Record<string, unknown>;
|
|
143
149
|
}
|
|
150
|
+
export type SimpleArrayItemType = 'text' | 'number' | 'url';
|
|
144
151
|
export interface ArrayField extends BaseField {
|
|
145
152
|
type: 'array';
|
|
153
|
+
of: SimpleArrayItemType;
|
|
154
|
+
minItems?: number;
|
|
155
|
+
maxItems?: number;
|
|
156
|
+
defaultValue?: (string | number | UrlFieldData)[];
|
|
157
|
+
}
|
|
158
|
+
export interface BlocksField extends BaseField {
|
|
159
|
+
type: 'blocks';
|
|
146
160
|
of: ObjectField[];
|
|
147
161
|
minItems?: number;
|
|
148
162
|
maxItems?: number;
|
|
@@ -152,10 +166,13 @@ export interface ArrayField extends BaseField {
|
|
|
152
166
|
export interface SlugField extends BaseField {
|
|
153
167
|
type: 'slug';
|
|
154
168
|
pattern?: string;
|
|
169
|
+
sourceField?: string;
|
|
155
170
|
defaultValue?: string;
|
|
156
171
|
}
|
|
157
172
|
export interface SeoField extends BaseField {
|
|
158
173
|
type: 'seo';
|
|
174
|
+
slugSource?: string;
|
|
175
|
+
titleSource?: string;
|
|
159
176
|
}
|
|
160
177
|
export interface SeoFieldData {
|
|
161
178
|
slug: string;
|
|
@@ -178,4 +195,4 @@ export type UrlFieldData = {
|
|
|
178
195
|
text?: Record<string, string>;
|
|
179
196
|
newTab?: boolean;
|
|
180
197
|
};
|
|
181
|
-
export type Field = TextField | RichtextField | NumberField | BooleanField | DateField | DateTimeField | FileField | ImageField | MediaField | SelectField | RadioField | CheckboxesField | RelationField | ObjectField | ArrayField | SlugField | SeoField | UrlField;
|
|
198
|
+
export type Field = TextField | RichtextField | ContentField | NumberField | BooleanField | DateField | DateTimeField | FileField | ImageField | MediaField | SelectField | RadioField | CheckboxesField | RelationField | ObjectField | ArrayField | BlocksField | SlugField | SeoField | UrlField;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './fields.js';
|
|
2
|
+
export { type StructuredContentDoc, type SCNode, type SCMark, type SCInlineBlockAttrs, type SCFigureAttrs, type SCVideoAttrs } from './structured-content.js';
|
|
2
3
|
export { type MediaFile, type MediaFileType, type ImageStyle, type MediaTag } from './media.js';
|
|
3
4
|
export { type ConsentLogData } from './consent.js';
|
|
4
5
|
export { type Entry, type EntryType, type EntryStatus, type EntryVersionStatus } from './entries.js';
|
|
@@ -8,3 +9,4 @@ export { type SingleConfig } from './singles.js';
|
|
|
8
9
|
export { type FormConfig, type FormSubmission } from './forms.js';
|
|
9
10
|
export { type CMSConfig } from './cms.js';
|
|
10
11
|
export { type Language, type Localized } from './languages.js';
|
|
12
|
+
export { type Layout, type LayoutNode, type LayoutPreset, type LayoutNodeType, type ColumnRatio, type SectionNode, type ColumnsNode, type CardNode, type AccordionNode, type StackNode } from './layout.js';
|
package/dist/types/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './fields.js';
|
|
2
|
+
export {} from './structured-content.js';
|
|
2
3
|
export {} from './media.js';
|
|
3
4
|
export {} from './consent.js';
|
|
4
5
|
export {} from './entries.js';
|
|
@@ -8,3 +9,4 @@ export {} from './singles.js';
|
|
|
8
9
|
export {} from './forms.js';
|
|
9
10
|
export {} from './cms.js';
|
|
10
11
|
export {} from './languages.js';
|
|
12
|
+
export {} from './layout.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { Localized } from './languages.js';
|
|
2
|
+
export type Layout = LayoutPreset | LayoutNode[];
|
|
3
|
+
export type LayoutPreset = 'sidebar-right' | 'two-column' | {
|
|
4
|
+
preset: 'sidebar-right';
|
|
5
|
+
sidebar: string[];
|
|
6
|
+
} | {
|
|
7
|
+
preset: 'two-column';
|
|
8
|
+
left?: string[];
|
|
9
|
+
};
|
|
10
|
+
export type LayoutNodeType = 'section' | 'columns' | 'card' | 'accordion' | 'stack';
|
|
11
|
+
export type ColumnRatio = '1fr 1fr' | '2fr 1fr' | '1fr 2fr' | '3fr 1fr' | '1fr 3fr' | '1fr 1fr 1fr';
|
|
12
|
+
interface LayoutNodeBase {
|
|
13
|
+
type: LayoutNodeType;
|
|
14
|
+
label?: Localized;
|
|
15
|
+
icon?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SectionNode extends LayoutNodeBase {
|
|
18
|
+
type: 'section';
|
|
19
|
+
label: Localized;
|
|
20
|
+
fields?: string[];
|
|
21
|
+
children?: LayoutNode[];
|
|
22
|
+
}
|
|
23
|
+
export interface ColumnsNode extends LayoutNodeBase {
|
|
24
|
+
type: 'columns';
|
|
25
|
+
ratio: ColumnRatio;
|
|
26
|
+
children: LayoutNode[];
|
|
27
|
+
}
|
|
28
|
+
export interface CardNode extends LayoutNodeBase {
|
|
29
|
+
type: 'card';
|
|
30
|
+
label: Localized;
|
|
31
|
+
fields?: string[];
|
|
32
|
+
children?: LayoutNode[];
|
|
33
|
+
autoGrid?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface AccordionNode extends LayoutNodeBase {
|
|
36
|
+
type: 'accordion';
|
|
37
|
+
label: Localized;
|
|
38
|
+
defaultOpen?: boolean;
|
|
39
|
+
fields?: string[];
|
|
40
|
+
children?: LayoutNode[];
|
|
41
|
+
}
|
|
42
|
+
export interface StackNode extends LayoutNodeBase {
|
|
43
|
+
type: 'stack';
|
|
44
|
+
fields?: string[];
|
|
45
|
+
children?: LayoutNode[];
|
|
46
|
+
}
|
|
47
|
+
export type LayoutNode = SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode;
|
|
48
|
+
export declare function isLayoutLeaf(node: LayoutNode): node is LayoutNode & {
|
|
49
|
+
fields: string[];
|
|
50
|
+
};
|
|
51
|
+
export declare function isLayoutBranch(node: LayoutNode): node is LayoutNode & {
|
|
52
|
+
children: LayoutNode[];
|
|
53
|
+
};
|
|
54
|
+
export {};
|