@endora-commerce/mod-blog 0.100.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/LICENSE +21 -0
- package/README.md +62 -0
- package/dist/admin/api/blog-client.d.ts +70 -0
- package/dist/admin/api/blog-client.d.ts.map +1 -0
- package/dist/admin/api/blog-client.js +137 -0
- package/dist/admin/api/blog-client.js.map +1 -0
- package/dist/admin/components/CategoryTreeNode.d.ts +25 -0
- package/dist/admin/components/CategoryTreeNode.d.ts.map +1 -0
- package/dist/admin/components/CategoryTreeNode.js +14 -0
- package/dist/admin/components/CategoryTreeNode.js.map +1 -0
- package/dist/admin/components/PostStatusBadge.d.ts +7 -0
- package/dist/admin/components/PostStatusBadge.d.ts.map +1 -0
- package/dist/admin/components/PostStatusBadge.js +16 -0
- package/dist/admin/components/PostStatusBadge.js.map +1 -0
- package/dist/admin/components/RelatedPostsPicker.d.ts +11 -0
- package/dist/admin/components/RelatedPostsPicker.d.ts.map +1 -0
- package/dist/admin/components/RelatedPostsPicker.js +77 -0
- package/dist/admin/components/RelatedPostsPicker.js.map +1 -0
- package/dist/admin/components/RelatedProductsPicker.d.ts +9 -0
- package/dist/admin/components/RelatedProductsPicker.d.ts.map +1 -0
- package/dist/admin/components/RelatedProductsPicker.js +66 -0
- package/dist/admin/components/RelatedProductsPicker.js.map +1 -0
- package/dist/admin/components/TagPicker.d.ts +9 -0
- package/dist/admin/components/TagPicker.d.ts.map +1 -0
- package/dist/admin/components/TagPicker.js +66 -0
- package/dist/admin/components/TagPicker.js.map +1 -0
- package/dist/admin/index.d.ts +33 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +114 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/BlogCategoryEditor.d.ts +9 -0
- package/dist/admin/pages/BlogCategoryEditor.d.ts.map +1 -0
- package/dist/admin/pages/BlogCategoryEditor.js +196 -0
- package/dist/admin/pages/BlogCategoryEditor.js.map +1 -0
- package/dist/admin/pages/BlogCategoryTreePage.d.ts +9 -0
- package/dist/admin/pages/BlogCategoryTreePage.d.ts.map +1 -0
- package/dist/admin/pages/BlogCategoryTreePage.js +122 -0
- package/dist/admin/pages/BlogCategoryTreePage.js.map +1 -0
- package/dist/admin/pages/BlogPostEditor.d.ts +9 -0
- package/dist/admin/pages/BlogPostEditor.d.ts.map +1 -0
- package/dist/admin/pages/BlogPostEditor.js +314 -0
- package/dist/admin/pages/BlogPostEditor.js.map +1 -0
- package/dist/admin/pages/BlogPostListPage.d.ts +9 -0
- package/dist/admin/pages/BlogPostListPage.d.ts.map +1 -0
- package/dist/admin/pages/BlogPostListPage.js +75 -0
- package/dist/admin/pages/BlogPostListPage.js.map +1 -0
- package/dist/admin/pages/BlogTagListPage.d.ts +9 -0
- package/dist/admin/pages/BlogTagListPage.d.ts.map +1 -0
- package/dist/admin/pages/BlogTagListPage.js +145 -0
- package/dist/admin/pages/BlogTagListPage.js.map +1 -0
- package/dist/backend/entities/blog-category-language.entity.d.ts +11 -0
- package/dist/backend/entities/blog-category-language.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-category-language.entity.js +35 -0
- package/dist/backend/entities/blog-category-language.entity.js.map +1 -0
- package/dist/backend/entities/blog-category-sales-channel.entity.d.ts +17 -0
- package/dist/backend/entities/blog-category-sales-channel.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-category-sales-channel.entity.js +48 -0
- package/dist/backend/entities/blog-category-sales-channel.entity.js.map +1 -0
- package/dist/backend/entities/blog-category.entity.d.ts +32 -0
- package/dist/backend/entities/blog-category.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-category.entity.js +113 -0
- package/dist/backend/entities/blog-category.entity.js.map +1 -0
- package/dist/backend/entities/blog-post-category.entity.d.ts +10 -0
- package/dist/backend/entities/blog-post-category.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post-category.entity.js +34 -0
- package/dist/backend/entities/blog-post-category.entity.js.map +1 -0
- package/dist/backend/entities/blog-post-language.entity.d.ts +9 -0
- package/dist/backend/entities/blog-post-language.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post-language.entity.js +33 -0
- package/dist/backend/entities/blog-post-language.entity.js.map +1 -0
- package/dist/backend/entities/blog-post-related-post.entity.d.ts +15 -0
- package/dist/backend/entities/blog-post-related-post.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post-related-post.entity.js +42 -0
- package/dist/backend/entities/blog-post-related-post.entity.js.map +1 -0
- package/dist/backend/entities/blog-post-related-product.entity.d.ts +14 -0
- package/dist/backend/entities/blog-post-related-product.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post-related-product.entity.js +41 -0
- package/dist/backend/entities/blog-post-related-product.entity.js.map +1 -0
- package/dist/backend/entities/blog-post-sales-channel.entity.d.ts +16 -0
- package/dist/backend/entities/blog-post-sales-channel.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post-sales-channel.entity.js +47 -0
- package/dist/backend/entities/blog-post-sales-channel.entity.js.map +1 -0
- package/dist/backend/entities/blog-post-tag.entity.d.ts +14 -0
- package/dist/backend/entities/blog-post-tag.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post-tag.entity.js +41 -0
- package/dist/backend/entities/blog-post-tag.entity.js.map +1 -0
- package/dist/backend/entities/blog-post.entity.d.ts +31 -0
- package/dist/backend/entities/blog-post.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-post.entity.js +106 -0
- package/dist/backend/entities/blog-post.entity.js.map +1 -0
- package/dist/backend/entities/blog-tag.entity.d.ts +18 -0
- package/dist/backend/entities/blog-tag.entity.d.ts.map +1 -0
- package/dist/backend/entities/blog-tag.entity.js +66 -0
- package/dist/backend/entities/blog-tag.entity.js.map +1 -0
- package/dist/backend/index.d.ts +100 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +182 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +12 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +148 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +6 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +72 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/blog-asset-references.d.ts +4 -0
- package/dist/backend/services/blog-asset-references.d.ts.map +1 -0
- package/dist/backend/services/blog-asset-references.js +79 -0
- package/dist/backend/services/blog-asset-references.js.map +1 -0
- package/dist/backend/services/blog-cache.d.ts +55 -0
- package/dist/backend/services/blog-cache.d.ts.map +1 -0
- package/dist/backend/services/blog-cache.js +111 -0
- package/dist/backend/services/blog-cache.js.map +1 -0
- package/dist/backend/services/blog-category-service.d.ts +53 -0
- package/dist/backend/services/blog-category-service.d.ts.map +1 -0
- package/dist/backend/services/blog-category-service.js +446 -0
- package/dist/backend/services/blog-category-service.js.map +1 -0
- package/dist/backend/services/blog-language-reference.d.ts +18 -0
- package/dist/backend/services/blog-language-reference.d.ts.map +1 -0
- package/dist/backend/services/blog-language-reference.js +43 -0
- package/dist/backend/services/blog-language-reference.js.map +1 -0
- package/dist/backend/services/blog-post-service.d.ts +79 -0
- package/dist/backend/services/blog-post-service.d.ts.map +1 -0
- package/dist/backend/services/blog-post-service.js +539 -0
- package/dist/backend/services/blog-post-service.js.map +1 -0
- package/dist/backend/services/blog-settings-resolver.d.ts +36 -0
- package/dist/backend/services/blog-settings-resolver.d.ts.map +1 -0
- package/dist/backend/services/blog-settings-resolver.js +68 -0
- package/dist/backend/services/blog-settings-resolver.js.map +1 -0
- package/dist/backend/services/blog-slug-collision.d.ts +35 -0
- package/dist/backend/services/blog-slug-collision.d.ts.map +1 -0
- package/dist/backend/services/blog-slug-collision.js +84 -0
- package/dist/backend/services/blog-slug-collision.js.map +1 -0
- package/dist/backend/services/blog-storefront-resolver.d.ts +107 -0
- package/dist/backend/services/blog-storefront-resolver.d.ts.map +1 -0
- package/dist/backend/services/blog-storefront-resolver.js +492 -0
- package/dist/backend/services/blog-storefront-resolver.js.map +1 -0
- package/dist/backend/services/blog-tag-service.d.ts +45 -0
- package/dist/backend/services/blog-tag-service.d.ts.map +1 -0
- package/dist/backend/services/blog-tag-service.js +198 -0
- package/dist/backend/services/blog-tag-service.js.map +1 -0
- package/dist/backend/services/seed-default-category.d.ts +25 -0
- package/dist/backend/services/seed-default-category.d.ts.map +1 -0
- package/dist/backend/services/seed-default-category.js +48 -0
- package/dist/backend/services/seed-default-category.js.map +1 -0
- package/dist/backend/services/seed-roles.d.ts +41 -0
- package/dist/backend/services/seed-roles.d.ts.map +1 -0
- package/dist/backend/services/seed-roles.js +98 -0
- package/dist/backend/services/seed-roles.js.map +1 -0
- package/dist/manifest.d.ts +226 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +236 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260506T081055_blog_init.d.ts +33 -0
- package/dist/migrations/20260506T081055_blog_init.d.ts.map +1 -0
- package/dist/migrations/20260506T081055_blog_init.js +260 -0
- package/dist/migrations/20260506T081055_blog_init.js.map +1 -0
- package/dist/migrations/20260903T101744_blog_namespace_block_names.d.ts +6 -0
- package/dist/migrations/20260903T101744_blog_namespace_block_names.d.ts.map +1 -0
- package/dist/migrations/20260903T101744_blog_namespace_block_names.js +58 -0
- package/dist/migrations/20260903T101744_blog_namespace_block_names.js.map +1 -0
- package/dist/migrations/index.d.ts +34 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +37 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/blog/index.md +199 -0
- package/i18n/en.json +166 -0
- package/i18n/pl.json +166 -0
- package/package.json +108 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in settings manifest for the Blog module — feature 016 / R7.
|
|
3
|
+
*
|
|
4
|
+
* Reserves the `blog` group and registers four settings the module
|
|
5
|
+
* consumes through `settings.service.getValue(...)`:
|
|
6
|
+
*
|
|
7
|
+
* - blog.enabled (boolean, default true)
|
|
8
|
+
* - blog.url_prefix (string, default 'blog') — single URL segment
|
|
9
|
+
* - blog.latest_count (number, default 5) — index "latest N"
|
|
10
|
+
* - blog.posts_per_page (number, default 12) — pagination page size
|
|
11
|
+
*
|
|
12
|
+
* Range bounds (`latest_count` ≥ 1, `posts_per_page` ≥ 1) and the
|
|
13
|
+
* url-prefix shape + reserved-segments check live in
|
|
14
|
+
* `services/blog-settings-resolver.ts` (the Settings module's value-type
|
|
15
|
+
* registry only validates primitive shapes).
|
|
16
|
+
*/
|
|
17
|
+
export declare const BLOG_SETTING_CODES: {
|
|
18
|
+
/**
|
|
19
|
+
* Feature 074 — the operator-activation control, and a **different switch**
|
|
20
|
+
* from `ENABLED` below.
|
|
21
|
+
*
|
|
22
|
+
* `blog.enabled` is channel-scoped by design ("disable the blog for a
|
|
23
|
+
* specific audience while leaving it on globally") and governs storefront
|
|
24
|
+
* URLs only; the admin blog screens keep working under it. Activation is
|
|
25
|
+
* platform-wide by construction — `resolveActivation` stops at
|
|
26
|
+
* `global_value` → `default_value` and never joins the per-channel tier
|
|
27
|
+
* (Constitution XII) — and it governs the whole module. Adopting the
|
|
28
|
+
* existing code would have collapsed the two, and would have switched the
|
|
29
|
+
* module off in every deployment that had set the storefront switch to
|
|
30
|
+
* false globally, which is the state change FR-012 forbids on merge.
|
|
31
|
+
*/
|
|
32
|
+
readonly ACTIVATION: "blog.activation";
|
|
33
|
+
readonly ENABLED: "blog.enabled";
|
|
34
|
+
readonly URL_PREFIX: "blog.url_prefix";
|
|
35
|
+
readonly LATEST_COUNT: "blog.latest_count";
|
|
36
|
+
readonly POSTS_PER_PAGE: "blog.posts_per_page";
|
|
37
|
+
};
|
|
38
|
+
export declare const BLOG_DEFAULT_ENABLED = true;
|
|
39
|
+
export declare const BLOG_DEFAULT_URL_PREFIX = "blog";
|
|
40
|
+
export declare const BLOG_DEFAULT_LATEST_COUNT = 5;
|
|
41
|
+
export declare const BLOG_DEFAULT_POSTS_PER_PAGE = 12;
|
|
42
|
+
/** Module-lifecycle manifest (feature 018). */
|
|
43
|
+
export declare const manifest: {
|
|
44
|
+
id: string;
|
|
45
|
+
name: string;
|
|
46
|
+
version: string;
|
|
47
|
+
dependencies: string[];
|
|
48
|
+
description?: string | undefined;
|
|
49
|
+
acknowledgedDependencies?: {
|
|
50
|
+
moduleId: string;
|
|
51
|
+
port: string;
|
|
52
|
+
reason: string;
|
|
53
|
+
}[] | undefined;
|
|
54
|
+
nonBindingDependencies?: {
|
|
55
|
+
moduleId: string;
|
|
56
|
+
name: string;
|
|
57
|
+
kind: "contributes-to" | "degrades-without" | "refuses-without";
|
|
58
|
+
reason: string;
|
|
59
|
+
whenAbsent?: string | undefined;
|
|
60
|
+
}[] | undefined;
|
|
61
|
+
activation?: {
|
|
62
|
+
settingCode: string;
|
|
63
|
+
default: boolean;
|
|
64
|
+
} | {
|
|
65
|
+
nonDeactivatable: true;
|
|
66
|
+
reason: string;
|
|
67
|
+
} | undefined;
|
|
68
|
+
settings?: {
|
|
69
|
+
moduleCode: string;
|
|
70
|
+
groups: {
|
|
71
|
+
code: string;
|
|
72
|
+
name: string;
|
|
73
|
+
salesChannelCodes?: string[] | undefined;
|
|
74
|
+
isSystemProtected?: boolean | undefined;
|
|
75
|
+
}[];
|
|
76
|
+
settings: {
|
|
77
|
+
code: string;
|
|
78
|
+
name: string;
|
|
79
|
+
valueType: "string" | "number" | "boolean" | "json" | "string_list" | "secret" | "credential_ref";
|
|
80
|
+
defaultValue: unknown;
|
|
81
|
+
description?: string | undefined;
|
|
82
|
+
groupCode?: string | undefined;
|
|
83
|
+
previousDefaultValues?: unknown[] | undefined;
|
|
84
|
+
salesChannelCodes?: string[] | undefined;
|
|
85
|
+
enumOptions?: string[] | undefined;
|
|
86
|
+
configurationType?: string | undefined;
|
|
87
|
+
hidden?: boolean | undefined;
|
|
88
|
+
}[];
|
|
89
|
+
} | undefined;
|
|
90
|
+
i18n?: {
|
|
91
|
+
bundlesDir: string;
|
|
92
|
+
} | undefined;
|
|
93
|
+
docs?: false | {
|
|
94
|
+
dir: string;
|
|
95
|
+
} | undefined;
|
|
96
|
+
demo?: false | {
|
|
97
|
+
summary: string;
|
|
98
|
+
seed: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoSeedResult>;
|
|
99
|
+
reset: (context: import("@endora-commerce/contracts").ModuleDemoContext<never>) => Promise<import("@endora-commerce/contracts").DemoResetResult>;
|
|
100
|
+
after?: readonly string[] | undefined;
|
|
101
|
+
package?: string | undefined;
|
|
102
|
+
} | undefined;
|
|
103
|
+
actions?: {
|
|
104
|
+
id: string;
|
|
105
|
+
labelKey: string;
|
|
106
|
+
icon: "Plus" | "Sparkles" | "Settings" | "Search" | "Boxes" | "Layers" | "Menu" | "PlusCircle" | "PlusSquare" | "FilePlus" | "FolderPlus" | "Upload" | "FileUp" | "CloudUpload" | "Download" | "FileDown" | "FileText" | "BookOpen" | "Rss" | "Package" | "Tag" | "ShoppingCart" | "Receipt" | "CreditCard" | "Users" | "UserPlus" | "Inbox" | "ListChecks" | "ClipboardList" | "Image" | "Video" | "LayoutDashboard" | "PanelLeft" | "KeyRound" | "ShieldCheck" | "Edit" | "Archive" | "Box" | "Truck" | "CircleDollarSign" | "Activity" | "LineChart" | "Smartphone" | "Webhook" | "Scale" | "PlugZap" | "PercentDiamond" | "Newspaper" | "Languages" | "Eraser" | "Warehouse" | "TrendingDown" | "Bell" | "PackageOpen" | "Building2" | "Store" | "ClipboardCheck";
|
|
107
|
+
targetRoute: string;
|
|
108
|
+
keywords: string[];
|
|
109
|
+
weight: number;
|
|
110
|
+
descriptionKey?: string | undefined;
|
|
111
|
+
requiredPermission?: string | undefined;
|
|
112
|
+
}[] | undefined;
|
|
113
|
+
permissions?: {
|
|
114
|
+
code: string;
|
|
115
|
+
label: string;
|
|
116
|
+
module?: string | undefined;
|
|
117
|
+
description?: string | undefined;
|
|
118
|
+
requires?: string[] | undefined;
|
|
119
|
+
}[] | undefined;
|
|
120
|
+
transactionalEmails?: {
|
|
121
|
+
code: string;
|
|
122
|
+
name: string;
|
|
123
|
+
variables: {
|
|
124
|
+
key: string;
|
|
125
|
+
label: string;
|
|
126
|
+
sampleValue?: string | undefined;
|
|
127
|
+
description?: string | undefined;
|
|
128
|
+
}[];
|
|
129
|
+
description?: string | undefined;
|
|
130
|
+
group?: string | undefined;
|
|
131
|
+
}[] | undefined;
|
|
132
|
+
capabilities?: string[] | undefined;
|
|
133
|
+
exclusiveCapabilities?: {
|
|
134
|
+
key: string;
|
|
135
|
+
errorCode: string;
|
|
136
|
+
}[] | undefined;
|
|
137
|
+
errorCodes?: {
|
|
138
|
+
code: string;
|
|
139
|
+
tokens?: string[] | undefined;
|
|
140
|
+
}[] | undefined;
|
|
141
|
+
blocks?: {
|
|
142
|
+
name: string;
|
|
143
|
+
labelKey: string;
|
|
144
|
+
category: string;
|
|
145
|
+
contexts: ("cms" | "invoice" | "email" | "newsletter")[];
|
|
146
|
+
fields: Record<string, {
|
|
147
|
+
type: "number" | "object" | "array" | "text" | "textarea" | "select" | "radio" | "external" | "uuid" | "richtext";
|
|
148
|
+
label?: string | undefined;
|
|
149
|
+
required?: boolean | undefined;
|
|
150
|
+
options?: {
|
|
151
|
+
label: string;
|
|
152
|
+
value: string | number;
|
|
153
|
+
}[] | undefined;
|
|
154
|
+
refKind?: string | undefined;
|
|
155
|
+
}>;
|
|
156
|
+
descriptionKey?: string | undefined;
|
|
157
|
+
defaultProps?: Record<string, unknown> | undefined;
|
|
158
|
+
responsiveFields?: string[] | undefined;
|
|
159
|
+
previewIcon?: string | undefined;
|
|
160
|
+
weight?: number | undefined;
|
|
161
|
+
}[] | undefined;
|
|
162
|
+
blockCategories?: {
|
|
163
|
+
key: string;
|
|
164
|
+
titleKey: string;
|
|
165
|
+
contexts: ("cms" | "invoice" | "email" | "newsletter")[];
|
|
166
|
+
weight?: number | undefined;
|
|
167
|
+
visible?: boolean | undefined;
|
|
168
|
+
}[] | undefined;
|
|
169
|
+
env?: {
|
|
170
|
+
name: string;
|
|
171
|
+
describes: {
|
|
172
|
+
en: string;
|
|
173
|
+
pl: string;
|
|
174
|
+
};
|
|
175
|
+
requirement: {
|
|
176
|
+
kind: "required";
|
|
177
|
+
} | {
|
|
178
|
+
kind: "requiredWhen";
|
|
179
|
+
input: string;
|
|
180
|
+
equals: string;
|
|
181
|
+
} | {
|
|
182
|
+
kind: "optional";
|
|
183
|
+
without: {
|
|
184
|
+
en: string;
|
|
185
|
+
pl: string;
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
secret: boolean;
|
|
189
|
+
generable: boolean;
|
|
190
|
+
owner: {
|
|
191
|
+
kind: "platform";
|
|
192
|
+
} | {
|
|
193
|
+
kind: "application";
|
|
194
|
+
application: "admin" | "backend" | "storefront";
|
|
195
|
+
} | {
|
|
196
|
+
kind: "module";
|
|
197
|
+
moduleId: string;
|
|
198
|
+
};
|
|
199
|
+
consumers: ("admin" | "backend" | "storefront")[];
|
|
200
|
+
addressOf: "admin" | "backend" | "storefront" | null;
|
|
201
|
+
}[] | undefined;
|
|
202
|
+
};
|
|
203
|
+
/** Legacy export retained for backward compatibility. */
|
|
204
|
+
export declare const blogManifest: {
|
|
205
|
+
moduleCode: string;
|
|
206
|
+
groups: {
|
|
207
|
+
code: string;
|
|
208
|
+
name: string;
|
|
209
|
+
salesChannelCodes?: string[] | undefined;
|
|
210
|
+
isSystemProtected?: boolean | undefined;
|
|
211
|
+
}[];
|
|
212
|
+
settings: {
|
|
213
|
+
code: string;
|
|
214
|
+
name: string;
|
|
215
|
+
valueType: "string" | "number" | "boolean" | "json" | "string_list" | "secret" | "credential_ref";
|
|
216
|
+
defaultValue: unknown;
|
|
217
|
+
description?: string | undefined;
|
|
218
|
+
groupCode?: string | undefined;
|
|
219
|
+
previousDefaultValues?: unknown[] | undefined;
|
|
220
|
+
salesChannelCodes?: string[] | undefined;
|
|
221
|
+
enumOptions?: string[] | undefined;
|
|
222
|
+
configurationType?: string | undefined;
|
|
223
|
+
hidden?: boolean | undefined;
|
|
224
|
+
}[];
|
|
225
|
+
};
|
|
226
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;;;;;;;;;;;;OAaG;;;;;;CAMK,CAAC;AAEX,eAAO,MAAM,oBAAoB,OAAO,CAAC;AACzC,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAC9C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,2BAA2B,KAAK,CAAC;AA8D9C,+CAA+C;AAC/C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwInB,CAAC;AAEH,yDAAyD;AACzD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;CAAW,CAAC"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { defineModuleManifest, defineModuleSettingsManifest, } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in settings manifest for the Blog module — feature 016 / R7.
|
|
4
|
+
*
|
|
5
|
+
* Reserves the `blog` group and registers four settings the module
|
|
6
|
+
* consumes through `settings.service.getValue(...)`:
|
|
7
|
+
*
|
|
8
|
+
* - blog.enabled (boolean, default true)
|
|
9
|
+
* - blog.url_prefix (string, default 'blog') — single URL segment
|
|
10
|
+
* - blog.latest_count (number, default 5) — index "latest N"
|
|
11
|
+
* - blog.posts_per_page (number, default 12) — pagination page size
|
|
12
|
+
*
|
|
13
|
+
* Range bounds (`latest_count` ≥ 1, `posts_per_page` ≥ 1) and the
|
|
14
|
+
* url-prefix shape + reserved-segments check live in
|
|
15
|
+
* `services/blog-settings-resolver.ts` (the Settings module's value-type
|
|
16
|
+
* registry only validates primitive shapes).
|
|
17
|
+
*/
|
|
18
|
+
export const BLOG_SETTING_CODES = {
|
|
19
|
+
/**
|
|
20
|
+
* Feature 074 — the operator-activation control, and a **different switch**
|
|
21
|
+
* from `ENABLED` below.
|
|
22
|
+
*
|
|
23
|
+
* `blog.enabled` is channel-scoped by design ("disable the blog for a
|
|
24
|
+
* specific audience while leaving it on globally") and governs storefront
|
|
25
|
+
* URLs only; the admin blog screens keep working under it. Activation is
|
|
26
|
+
* platform-wide by construction — `resolveActivation` stops at
|
|
27
|
+
* `global_value` → `default_value` and never joins the per-channel tier
|
|
28
|
+
* (Constitution XII) — and it governs the whole module. Adopting the
|
|
29
|
+
* existing code would have collapsed the two, and would have switched the
|
|
30
|
+
* module off in every deployment that had set the storefront switch to
|
|
31
|
+
* false globally, which is the state change FR-012 forbids on merge.
|
|
32
|
+
*/
|
|
33
|
+
ACTIVATION: 'blog.activation',
|
|
34
|
+
ENABLED: 'blog.enabled',
|
|
35
|
+
URL_PREFIX: 'blog.url_prefix',
|
|
36
|
+
LATEST_COUNT: 'blog.latest_count',
|
|
37
|
+
POSTS_PER_PAGE: 'blog.posts_per_page',
|
|
38
|
+
};
|
|
39
|
+
export const BLOG_DEFAULT_ENABLED = true;
|
|
40
|
+
export const BLOG_DEFAULT_URL_PREFIX = 'blog';
|
|
41
|
+
export const BLOG_DEFAULT_LATEST_COUNT = 5;
|
|
42
|
+
export const BLOG_DEFAULT_POSTS_PER_PAGE = 12;
|
|
43
|
+
const settings = defineModuleSettingsManifest({
|
|
44
|
+
moduleCode: 'blog',
|
|
45
|
+
groups: [
|
|
46
|
+
{
|
|
47
|
+
code: 'blog',
|
|
48
|
+
name: 'Blog',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
settings: [
|
|
52
|
+
{
|
|
53
|
+
// Feature 074 — the operator's activation control. Platform-wide, and
|
|
54
|
+
// never channel-scoped: the reconciler's channel scope is additive-only,
|
|
55
|
+
// so a channel-scoped first commit would have no way back.
|
|
56
|
+
code: BLOG_SETTING_CODES.ACTIVATION,
|
|
57
|
+
name: 'Blog enabled',
|
|
58
|
+
description: 'Switches the blog on or off as a whole: the storefront blog, its admin screens and its API. Nothing is dropped — every post, category, tag and media reference stays in the database and comes back exactly as it was when you switch it on again.',
|
|
59
|
+
groupCode: 'blog',
|
|
60
|
+
valueType: 'boolean',
|
|
61
|
+
defaultValue: true,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
code: BLOG_SETTING_CODES.ENABLED,
|
|
65
|
+
name: 'Blog storefront enabled',
|
|
66
|
+
description: 'When false, every blog URL on the storefront returns 404 in this scope. Set per Sales Channel to disable the blog for a specific audience while leaving it on globally.',
|
|
67
|
+
groupCode: 'blog',
|
|
68
|
+
valueType: 'boolean',
|
|
69
|
+
defaultValue: BLOG_DEFAULT_ENABLED,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
code: BLOG_SETTING_CODES.URL_PREFIX,
|
|
73
|
+
name: 'Blog URL prefix',
|
|
74
|
+
description: "Single URL segment under which the blog is served (e.g. 'blog' → /blog, 'aktualnosci' → /aktualnosci). Must match ^[a-z0-9-]+$ and avoid reserved segments.",
|
|
75
|
+
groupCode: 'blog',
|
|
76
|
+
valueType: 'string',
|
|
77
|
+
defaultValue: BLOG_DEFAULT_URL_PREFIX,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
code: BLOG_SETTING_CODES.LATEST_COUNT,
|
|
81
|
+
name: 'Latest posts on the blog index',
|
|
82
|
+
description: 'How many newest posts the blog index page shows. Sensible range 1..20.',
|
|
83
|
+
groupCode: 'blog',
|
|
84
|
+
valueType: 'number',
|
|
85
|
+
defaultValue: BLOG_DEFAULT_LATEST_COUNT,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
code: BLOG_SETTING_CODES.POSTS_PER_PAGE,
|
|
89
|
+
name: 'Posts per page in Category and Tag views',
|
|
90
|
+
description: 'Page size for the paginated post list on Category and Tag pages. Sensible range 1..100.',
|
|
91
|
+
groupCode: 'blog',
|
|
92
|
+
valueType: 'number',
|
|
93
|
+
defaultValue: BLOG_DEFAULT_POSTS_PER_PAGE,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
/** Module-lifecycle manifest (feature 018). */
|
|
98
|
+
export const manifest = defineModuleManifest({
|
|
99
|
+
id: 'blog',
|
|
100
|
+
name: 'Blog',
|
|
101
|
+
description: 'Multi-channel, multi-language blog with categories, tags, and Page Builder posts.',
|
|
102
|
+
version: '1.0.0',
|
|
103
|
+
dependencies: [
|
|
104
|
+
// Two seams, both in the boot seeder, both into `admin_roles`.
|
|
105
|
+
//
|
|
106
|
+
// `systemRoleCodePort` (feature 075, Phase C) registers this module's two
|
|
107
|
+
// role codes as deletion-protected, where the seeder used to import
|
|
108
|
+
// `admin_roles`' module-level function. That registry is ungated.
|
|
109
|
+
//
|
|
110
|
+
// `adminRolePort` (feature 075, the boundary drain) is where the two role
|
|
111
|
+
// rows are written, in place of the three raw SQL statements that named
|
|
112
|
+
// `admin_roles`' own table. That one is gated, so it fails closed: with no
|
|
113
|
+
// `admin_roles` in the composition the seeder throws, `runBootHooks`
|
|
114
|
+
// re-throws as `ModuleCompositionError` and the platform exits rather than
|
|
115
|
+
// serving with two roles nobody granted. `admin_roles` is non-deactivatable,
|
|
116
|
+
// so no operator flip reaches that state — only a deployment that never
|
|
117
|
+
// shipped the module, which `composeModules` refuses up front. The
|
|
118
|
+
// declaration therefore buys install and migration order rather than a
|
|
119
|
+
// flip-time refusal.
|
|
120
|
+
'admin_roles',
|
|
121
|
+
'assets_library',
|
|
122
|
+
// Feature 072 (T061) — blog resolves the `requireAdmin` port, which `auth`
|
|
123
|
+
// owns. Every admin route in this module is gated by it, so `auth` being
|
|
124
|
+
// absent is not a degraded blog, it is a blog whose admin surface cannot be
|
|
125
|
+
// guarded. The edge existed before this declaration; it simply existed
|
|
126
|
+
// nowhere the lifecycle, the migration order or an operator could see it.
|
|
127
|
+
'auth',
|
|
128
|
+
'catalog',
|
|
129
|
+
'cms',
|
|
130
|
+
'dictionaries',
|
|
131
|
+
// `languages` owns `languageReferenceRegistry`, the registry this module
|
|
132
|
+
// contributes its two "which languages do posts and categories carry"
|
|
133
|
+
// descriptors to (feature 077, D-87). `languages` used to ask the question
|
|
134
|
+
// itself, with two `count(*)` statements naming this module's tables.
|
|
135
|
+
'languages',
|
|
136
|
+
'sales_channels',
|
|
137
|
+
'settings',
|
|
138
|
+
],
|
|
139
|
+
settings,
|
|
140
|
+
// Feature 074 (Constitution XVII) — a control this module never had. Before
|
|
141
|
+
// it, an operator could not decline the blog at all: a module with no
|
|
142
|
+
// activation declaration resolves as activated. Editorial content is an
|
|
143
|
+
// additional capability in ruling 1's sense — the catalogue stands without it
|
|
144
|
+
// — so it is operator-controlled, and the default is `true` so that merging
|
|
145
|
+
// this changes no deployment's state (FR-012).
|
|
146
|
+
activation: { settingCode: BLOG_SETTING_CODES.ACTIVATION, default: true },
|
|
147
|
+
/**
|
|
148
|
+
* The nineteen error codes this module owns — feature 090 Phase 3
|
|
149
|
+
* (`specs/090-module-owned-error-codes/contracts/error-code-declaration.md`
|
|
150
|
+
* §1.1). This is where the sentence for each is looked up from: `errors.<CODE>`
|
|
151
|
+
* in this module's own `i18n/{en,pl}.json`, which holds all nineteen in both
|
|
152
|
+
* languages. None of them is a `check-error-translations.ts`
|
|
153
|
+
* `UNTRANSLATED_ERROR_CODES` entry.
|
|
154
|
+
*
|
|
155
|
+
* The list is answer-preserving, not a judgement (§6.2 and §6.5), and it was
|
|
156
|
+
* not written by hand: it is the verbatim output of the runbook's step-1
|
|
157
|
+
* derivation over the frozen capture at
|
|
158
|
+
* `backend/test/fixtures/error-code-routing/chain-answers.ts`, which records
|
|
159
|
+
* what the prefix chain in `@endora-commerce/mod-i18n` answered at
|
|
160
|
+
* `49f3c6817`. Re-routing a code to a better owner is
|
|
161
|
+
* `specs/082-error-code-ownership/rulings.md` §9's remaining work and is
|
|
162
|
+
* deliberately not done here.
|
|
163
|
+
*
|
|
164
|
+
* **No code here is a shadow, and that is worth stating rather than leaving a
|
|
165
|
+
* reader to check.** Trap T1 exists because the chain is an ordered `if` and
|
|
166
|
+
* an earlier rule can claim a code a later one names — it cost `inventory` two
|
|
167
|
+
* codes and gave `catalog` four. `blog` has a single rule, `BLOG_`, no misc
|
|
168
|
+
* set, and nothing above it claims a `BLOG_`-prefixed code: the nineteen the
|
|
169
|
+
* chain answers with are exactly the nineteen `BLOG_`-prefixed members of
|
|
170
|
+
* `ERROR_CODES`, so the source reading and the answer reading coincide for this
|
|
171
|
+
* module. The derivation was still run from the answer, because "no shadow
|
|
172
|
+
* reaches me" is a conclusion of reading the whole chain and not a premise a
|
|
173
|
+
* migrating author is entitled to.
|
|
174
|
+
*
|
|
175
|
+
* **Five of the nineteen are raised nowhere in the tree** —
|
|
176
|
+
* `BLOG_ASSET_KIND_MISMATCH`, `BLOG_CATEGORY_NO_CHANNEL`,
|
|
177
|
+
* `BLOG_POST_NO_CHANNEL`, `BLOG_POST_NO_LANGUAGE` and `BLOG_SLUG_INVALID`. Each
|
|
178
|
+
* is a member of `ERROR_CODES` with a sentence in both languages that no
|
|
179
|
+
* `throw` in `backend/src` or `packages` can produce; the refusals they were
|
|
180
|
+
* written for are delivered by the schemas instead, as `VALIDATION_FAILED`
|
|
181
|
+
* (`test/contract/blog/admin-posts.contract.test.ts` says so in its own
|
|
182
|
+
* comment). Ownership follows the capture and not the raise sites, so they are
|
|
183
|
+
* declared: dropping them would red the progress test as `undeclared` and
|
|
184
|
+
* would move an answer this merge request is not allowed to move. Whether the
|
|
185
|
+
* codes should exist at all is a separate question from who owns them.
|
|
186
|
+
*
|
|
187
|
+
* The inverse is also true here and is T2's shape: this module raises
|
|
188
|
+
* `VERSION_CONFLICT` (three sites) and `INTERNAL` (two), which the chain routes
|
|
189
|
+
* to `core`, so they are not declared here and the sentences stay where they
|
|
190
|
+
* are.
|
|
191
|
+
*
|
|
192
|
+
* No `tokens`: no code here carries a refusal discriminator. Derived from the
|
|
193
|
+
* raise sites per the runbook's §5 — every `errors.<CODE>.<token>` key is a
|
|
194
|
+
* value the envelope reads out of `details.code`, no `new HttpError` in this
|
|
195
|
+
* module passes a `code` member at all, and the module's bundles hold no
|
|
196
|
+
* `errors.BLOG_*.<token>` key in the other direction.
|
|
197
|
+
*/
|
|
198
|
+
errorCodes: [
|
|
199
|
+
{ code: 'BLOG_ASSET_KIND_MISMATCH' },
|
|
200
|
+
{ code: 'BLOG_CATEGORY_CYCLE' },
|
|
201
|
+
{ code: 'BLOG_CATEGORY_HAS_CHILDREN' },
|
|
202
|
+
{ code: 'BLOG_CATEGORY_IN_USE' },
|
|
203
|
+
{ code: 'BLOG_CATEGORY_NOT_FOUND' },
|
|
204
|
+
{ code: 'BLOG_CATEGORY_NO_CHANNEL' },
|
|
205
|
+
{ code: 'BLOG_CATEGORY_PROTECTED' },
|
|
206
|
+
{ code: 'BLOG_DISABLED' },
|
|
207
|
+
{ code: 'BLOG_POST_NOT_FOUND' },
|
|
208
|
+
{ code: 'BLOG_POST_NO_CHANNEL' },
|
|
209
|
+
{ code: 'BLOG_POST_NO_LANGUAGE' },
|
|
210
|
+
{ code: 'BLOG_RELATED_POST_SELF_REFERENCE' },
|
|
211
|
+
{ code: 'BLOG_SLUG_INVALID' },
|
|
212
|
+
{ code: 'BLOG_SLUG_TAKEN' },
|
|
213
|
+
{ code: 'BLOG_TAG_CODE_TAKEN' },
|
|
214
|
+
{ code: 'BLOG_TAG_IN_USE' },
|
|
215
|
+
{ code: 'BLOG_TAG_NOT_FOUND' },
|
|
216
|
+
{ code: 'BLOG_URL_PREFIX_INVALID' },
|
|
217
|
+
{ code: 'BLOG_URL_PREFIX_RESERVED' },
|
|
218
|
+
],
|
|
219
|
+
i18n: { bundlesDir: 'i18n' },
|
|
220
|
+
docs: { dir: 'docs' },
|
|
221
|
+
actions: [
|
|
222
|
+
{
|
|
223
|
+
id: 'new-post',
|
|
224
|
+
labelKey: 'actions.newPost.label',
|
|
225
|
+
descriptionKey: 'actions.newPost.description',
|
|
226
|
+
icon: 'BookOpen',
|
|
227
|
+
targetRoute: '/blog/posts/new',
|
|
228
|
+
requiredPermission: 'blog.write',
|
|
229
|
+
keywords: ['post', 'new', 'create', 'wpis', 'nowy'],
|
|
230
|
+
weight: 140,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
});
|
|
234
|
+
/** Legacy export retained for backward compatibility. */
|
|
235
|
+
export const blogManifest = settings;
|
|
236
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Migration } from '@mikro-orm/migrations';
|
|
2
|
+
/**
|
|
3
|
+
* Blog module — feature 016 / data-model.md.
|
|
4
|
+
*
|
|
5
|
+
* Schema changes (one atomic migration):
|
|
6
|
+
* - new tables: blog_categories + blog_category_sales_channels +
|
|
7
|
+
* blog_category_languages + blog_posts + blog_post_sales_channels +
|
|
8
|
+
* blog_post_languages + blog_post_categories + blog_post_tags +
|
|
9
|
+
* blog_post_related_posts + blog_post_related_products + blog_tags.
|
|
10
|
+
* - GIN index on blog_posts.content (jsonb_path_ops) so the asset-reference
|
|
11
|
+
* scan stays fast (R13).
|
|
12
|
+
* - btree index on blog_posts(status, published_at DESC) drives the
|
|
13
|
+
* storefront's "newest first" listing.
|
|
14
|
+
* - btree index on blog_categories(parent_id, position) drives the
|
|
15
|
+
* per-tree fetch.
|
|
16
|
+
* - PARTIAL unique indexes on blog_post_sales_channels(sales_channel_id,
|
|
17
|
+
* slug) WHERE deleted_at IS NULL and the analogous one on
|
|
18
|
+
* blog_category_sales_channels — defensive guards for the cross-table
|
|
19
|
+
* uniqueness contract documented in research.md § R3 (the cross-table
|
|
20
|
+
* check itself runs at the service layer with a pg_advisory_xact_lock).
|
|
21
|
+
* - PARTIAL unique on blog_tags(code) WHERE deleted_at IS NULL — global
|
|
22
|
+
* tag-code uniqueness (R14).
|
|
23
|
+
*
|
|
24
|
+
* No seed rows; the seeded `Default` Category and the two seeded admin
|
|
25
|
+
* roles are inserted by runtime reconcilers in `services/seed-default-
|
|
26
|
+
* category.ts` and `services/seed-roles.ts` so admin edits across deploys
|
|
27
|
+
* stay safe (R8 + R11).
|
|
28
|
+
*/
|
|
29
|
+
export declare class Migration20260506T081055BlogInit extends Migration {
|
|
30
|
+
up(): Promise<void>;
|
|
31
|
+
down(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=20260506T081055_blog_init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"20260506T081055_blog_init.d.ts","sourceRoot":"","sources":["../../src/migrations/20260506T081055_blog_init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,gCAAiC,SAAQ,SAAS;IAC9C,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC;IA6PnB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAarC"}
|