@endora-commerce/mod-seo 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 +57 -0
- package/dist/admin/index.d.ts +31 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +35 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/SeoPage.d.ts +4 -0
- package/dist/admin/pages/SeoPage.d.ts.map +1 -0
- package/dist/admin/pages/SeoPage.js +189 -0
- package/dist/admin/pages/SeoPage.js.map +1 -0
- package/dist/backend/entities/seo-meta-override.entity.d.ts +21 -0
- package/dist/backend/entities/seo-meta-override.entity.d.ts.map +1 -0
- package/dist/backend/entities/seo-meta-override.entity.js +84 -0
- package/dist/backend/entities/seo-meta-override.entity.js.map +1 -0
- package/dist/backend/entities/sitemap-cache.entity.d.ts +17 -0
- package/dist/backend/entities/sitemap-cache.entity.d.ts.map +1 -0
- package/dist/backend/entities/sitemap-cache.entity.js +52 -0
- package/dist/backend/entities/sitemap-cache.entity.js.map +1 -0
- package/dist/backend/index.d.ts +57 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +58 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/routes.d.ts +11 -0
- package/dist/backend/routes.d.ts.map +1 -0
- package/dist/backend/routes.js +158 -0
- package/dist/backend/routes.js.map +1 -0
- package/dist/backend/services/meta-tag-resolver.service.d.ts +54 -0
- package/dist/backend/services/meta-tag-resolver.service.d.ts.map +1 -0
- package/dist/backend/services/meta-tag-resolver.service.js +208 -0
- package/dist/backend/services/meta-tag-resolver.service.js.map +1 -0
- package/dist/backend/services/sitemap-generator.service.d.ts +79 -0
- package/dist/backend/services/sitemap-generator.service.d.ts.map +1 -0
- package/dist/backend/services/sitemap-generator.service.js +293 -0
- package/dist/backend/services/sitemap-generator.service.js.map +1 -0
- package/dist/manifest.d.ts +169 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +49 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260425T154404_seo_init.d.ts +11 -0
- package/dist/migrations/20260425T154404_seo_init.d.ts.map +1 -0
- package/dist/migrations/20260425T154404_seo_init.js +45 -0
- package/dist/migrations/20260425T154404_seo_init.js.map +1 -0
- package/dist/migrations/index.d.ts +23 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +23 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/seo.md +74 -0
- package/i18n/en.json +3 -0
- package/i18n/pl.json +3 -0
- package/package.json +89 -0
- package/tailwind.css +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Endora sp. z o.o. and the Endora Commerce contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<!-- Generated by `pnpm --filter backend run manifests:generate`. Delete this line to take the file over; a README without it is never regenerated. -->
|
|
2
|
+
|
|
3
|
+
# @endora-commerce/mod-seo
|
|
4
|
+
|
|
5
|
+
SEO metadata management for catalog, CMS, and blog surfaces.
|
|
6
|
+
|
|
7
|
+
## What this is
|
|
8
|
+
|
|
9
|
+
An **Endora Commerce module package**. Its module id is `seo` — the identity of record in the platform's registries, in its migrations and in its setting, permission and translation codes.
|
|
10
|
+
|
|
11
|
+
A module is not imported by application code. The platform discovers the extension packages an instance has installed, reads the manifest on the root subpath and composes the module from it, so installing this package and starting the instance is the whole integration.
|
|
12
|
+
|
|
13
|
+
## Entry points
|
|
14
|
+
|
|
15
|
+
| Import | Contents |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `@endora-commerce/mod-seo` | the module manifest — its id, version, dependencies, settings and activation |
|
|
18
|
+
| `@endora-commerce/mod-seo/admin` | the Admin UI contribution: the screens, navigation and palette actions it adds |
|
|
19
|
+
| `@endora-commerce/mod-seo/backend` | the composition root the platform calls, with the entities, services, routes and workers it registers |
|
|
20
|
+
| `@endora-commerce/mod-seo/migrations` | the module’s own schema migrations, in the order the platform runs them |
|
|
21
|
+
| `@endora-commerce/mod-seo/tailwind.css` | the Tailwind source declaration for the admin code above |
|
|
22
|
+
|
|
23
|
+
## Depends on
|
|
24
|
+
|
|
25
|
+
Everything below is a **peer** dependency, so the application resolves exactly one copy of each — two copies of a host or of React are a runtime failure rather than a type error. An entry marked *optional* is needed only by the layers that use it.
|
|
26
|
+
|
|
27
|
+
**Endora packages**
|
|
28
|
+
|
|
29
|
+
- `@endora-commerce/admin-kit` — *optional*
|
|
30
|
+
- `@endora-commerce/contracts`
|
|
31
|
+
- `@endora-commerce/platform`
|
|
32
|
+
|
|
33
|
+
**Third-party**
|
|
34
|
+
|
|
35
|
+
- `@mikro-orm/core` ^6
|
|
36
|
+
- `@mikro-orm/migrations` ^6
|
|
37
|
+
- `@mikro-orm/postgresql` ^6
|
|
38
|
+
- `fastify` ^5
|
|
39
|
+
- `react` ^19 — *optional*
|
|
40
|
+
- `zod` ^4
|
|
41
|
+
|
|
42
|
+
## What the tarball carries
|
|
43
|
+
|
|
44
|
+
- `dist/` — the compiled JavaScript and its type declarations
|
|
45
|
+
- `i18n/` — the translation bundles this package ships (`en`, `pl`), loaded by the platform
|
|
46
|
+
- `docs/` — the package’s own pages in the Endora Commerce documentation site
|
|
47
|
+
- `tailwind.css` — the Tailwind source declaration
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm add @endora-commerce/mod-seo
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Licence
|
|
56
|
+
|
|
57
|
+
MIT — the text is in `LICENSE`, beside this file.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `seo`'s admin surface — one route and one sidebar entry, declared by the
|
|
3
|
+
* module that owns them (feature 091, Phase 4, batch 8;
|
|
4
|
+
* `specs/091-module-owned-admin-surfaces/contracts/admin-contribution.md`).
|
|
5
|
+
*
|
|
6
|
+
* **Its one drain was `catalog`'s product picker**, which the screen renders to
|
|
7
|
+
* choose the entity an SEO meta override applies to.
|
|
8
|
+
* `backend/scripts/ledgers/cross-module-imports/seo.ts` recorded it with the
|
|
9
|
+
* retiring condition this batch satisfies: the picker is generic — it renders a
|
|
10
|
+
* chooser over data `catalog` holds and knows nothing about this consumer — so
|
|
11
|
+
* it moved into `@endora-commerce/admin-kit` and the shard is deleted rather
|
|
12
|
+
* than edited.
|
|
13
|
+
*
|
|
14
|
+
* **The permission is `catalog:write`, and it is not a mistake.** Every
|
|
15
|
+
* `/api/v1/admin/seo/*` route enforces it; this module never declared a code of
|
|
16
|
+
* its own, and the hand-written sidebar entry carried the same one. Giving it
|
|
17
|
+
* one would be a product change bought to make a declaration read tidily, and
|
|
18
|
+
* the off-state test drives the code the platform actually enforces.
|
|
19
|
+
*
|
|
20
|
+
* **This entry exports data and nothing else** (R2), like every `./admin`
|
|
21
|
+
* layer: `check:module-boundary`'s D-171 rule designates a subpath as contract
|
|
22
|
+
* surface when it emits no runtime binding, and `./admin` deliberately does not
|
|
23
|
+
* qualify, so a consumer reaching into another module's `./admin` stays a
|
|
24
|
+
* counted boundary reach.
|
|
25
|
+
*
|
|
26
|
+
* **The component is a dynamic-import factory** (R6), so Vite has a split point
|
|
27
|
+
* whether or not anybody remembers to ask for one.
|
|
28
|
+
*/
|
|
29
|
+
import type { AdminContributions } from '@endora-commerce/admin-kit/contributions';
|
|
30
|
+
export declare const contributions: AdminContributions;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAQnF,eAAO,MAAM,aAAa,EAAE,kBA6B3B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** The module's only route: sitemaps and metadata overrides. */
|
|
2
|
+
const ROUTE_PATH = '/seo';
|
|
3
|
+
/** The code every `/api/v1/admin/seo/*` route enforces. */
|
|
4
|
+
const SEO_PERMISSION = 'catalog:write';
|
|
5
|
+
export const contributions = {
|
|
6
|
+
routes: [
|
|
7
|
+
{
|
|
8
|
+
path: ROUTE_PATH,
|
|
9
|
+
component: () => import('./pages/SeoPage.js'),
|
|
10
|
+
requiredPermission: SEO_PERMISSION,
|
|
11
|
+
index: true,
|
|
12
|
+
},
|
|
13
|
+
],
|
|
14
|
+
nav: [
|
|
15
|
+
{
|
|
16
|
+
to: ROUTE_PATH,
|
|
17
|
+
// Module-relative (R8), resolved in this module's own namespace out of
|
|
18
|
+
// `packages/modules/seo/i18n/`. It was `appShell.nav.seo` in the shared
|
|
19
|
+
// `_i18n` bundle, one of the four shared files a module author had to
|
|
20
|
+
// edit.
|
|
21
|
+
labelKey: 'nav.seo.label',
|
|
22
|
+
// The glyph the hand-written NAV entry carried.
|
|
23
|
+
icon: 'Search',
|
|
24
|
+
section: 'channels',
|
|
25
|
+
// The hand-written table put `/seo` last in *Channels*, after the two
|
|
26
|
+
// dictionary rows. Every other row there is still the host's, so the
|
|
27
|
+
// registry entry appends after all of them — which is the position this
|
|
28
|
+
// one already had — and the weight orders it against the converted
|
|
29
|
+
// entries that join the section later.
|
|
30
|
+
weight: 400,
|
|
31
|
+
requiredPermission: SEO_PERMISSION,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/admin/index.ts"],"names":[],"mappings":"AA8BA,gEAAgE;AAChE,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,2DAA2D;AAC3D,MAAM,cAAc,GAAG,eAAe,CAAC;AAEvC,MAAM,CAAC,MAAM,aAAa,GAAuB;IAC/C,MAAM,EAAE;QACN;YACE,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC;YAC7C,kBAAkB,EAAE,cAAc;YAClC,KAAK,EAAE,IAAI;SACZ;KACF;IACD,GAAG,EAAE;QACH;YACE,EAAE,EAAE,UAAU;YACd,uEAAuE;YACvE,wEAAwE;YACxE,sEAAsE;YACtE,QAAQ;YACR,QAAQ,EAAE,eAAe;YACzB,gDAAgD;YAChD,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,UAAU;YACnB,sEAAsE;YACtE,qEAAqE;YACrE,wEAAwE;YACxE,mEAAmE;YACnE,uCAAuC;YACvC,MAAM,EAAE,GAAG;YACX,kBAAkB,EAAE,cAAc;SACnC;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SeoPage.d.ts","sourceRoot":"","sources":["../../../src/admin/pages/SeoPage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAsCzE,wBAAgB,OAAO,IAAI,SAAS,CAcnC;AAybD,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { ApiError, apiBaseUrl, apiClient, formatDateTime } from '@endora-commerce/admin-kit/lib';
|
|
4
|
+
import { Alert, AlertDescription, Button, Card, CardContent, CardHeader, CardTitle, Input, Label, PageHeader, Select, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@endora-commerce/admin-kit/ui';
|
|
5
|
+
import { CategorySelect, ProductPicker } from '@endora-commerce/admin-kit/components';
|
|
6
|
+
import { useTranslation } from '@endora-commerce/admin-kit/i18n';
|
|
7
|
+
const ENTITY_TYPES = ['product', 'category'];
|
|
8
|
+
export function SeoPage() {
|
|
9
|
+
const t = useTranslation('core');
|
|
10
|
+
return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { title: t('seo.page.title'), description: t('seo.page.description') }), _jsxs("div", { className: "space-y-4", children: [_jsx(SitemapCard, {}), _jsx(MetaEditorCard, {})] })] }));
|
|
11
|
+
}
|
|
12
|
+
function SitemapCard() {
|
|
13
|
+
const t = useTranslation('core');
|
|
14
|
+
const [rows, setRows] = useState([]);
|
|
15
|
+
const [loading, setLoading] = useState(true);
|
|
16
|
+
const [busyChannel, setBusyChannel] = useState(null);
|
|
17
|
+
const [message, setMessage] = useState(null);
|
|
18
|
+
const [error, setError] = useState(null);
|
|
19
|
+
const refresh = useCallback(async () => {
|
|
20
|
+
setLoading(true);
|
|
21
|
+
try {
|
|
22
|
+
const res = await apiClient.get('/api/v1/admin/seo/sitemap');
|
|
23
|
+
setRows(res.data);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
setError(err instanceof ApiError ? err.envelope.error.message : t('seo.sitemap.error.load'));
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
}, [t]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
void refresh();
|
|
34
|
+
}, [refresh]);
|
|
35
|
+
const regenerate = useCallback(async (code) => {
|
|
36
|
+
setBusyChannel(code);
|
|
37
|
+
setMessage(null);
|
|
38
|
+
setError(null);
|
|
39
|
+
try {
|
|
40
|
+
const res = await apiClient.post(`/api/v1/admin/seo/sitemap/${encodeURIComponent(code)}/regenerate`);
|
|
41
|
+
setMessage(t('seo.sitemap.regenerated', {
|
|
42
|
+
code,
|
|
43
|
+
count: res.data.urlCount,
|
|
44
|
+
size: formatBytes(res.data.byteSize),
|
|
45
|
+
}));
|
|
46
|
+
await refresh();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
setError(err instanceof ApiError ? err.envelope.error.message : t('seo.sitemap.error.regenerate'));
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
setBusyChannel(null);
|
|
53
|
+
}
|
|
54
|
+
}, [refresh, t]);
|
|
55
|
+
const fetchXml = useCallback(async (code) => {
|
|
56
|
+
// The kit's published origin (`admin-kit-publishes-api-base-url`), not a second
|
|
57
|
+
// read of `import.meta.env`: the sitemap XML is downloaded rather than fetched
|
|
58
|
+
// through `apiClient`, so this screen needs the origin the client was built from.
|
|
59
|
+
const url = `${apiBaseUrl.replace(/\/+$/, '')}/api/v1/admin/seo/sitemap/${encodeURIComponent(code)}/xml`;
|
|
60
|
+
const response = await fetch(url, { credentials: 'include' });
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error(`HTTP ${response.status}`);
|
|
63
|
+
}
|
|
64
|
+
return response.blob();
|
|
65
|
+
}, []);
|
|
66
|
+
const preview = useCallback(async (code) => {
|
|
67
|
+
setBusyChannel(code);
|
|
68
|
+
setError(null);
|
|
69
|
+
try {
|
|
70
|
+
const blob = await fetchXml(code);
|
|
71
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
72
|
+
const newWindow = window.open(objectUrl, '_blank', 'noopener,noreferrer');
|
|
73
|
+
// Revoke after the new window has had a chance to load.
|
|
74
|
+
setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000);
|
|
75
|
+
if (!newWindow) {
|
|
76
|
+
setError(t('seo.sitemap.error.popupBlocked'));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
setError(err instanceof Error ? err.message : t('seo.sitemap.error.preview'));
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
setBusyChannel(null);
|
|
84
|
+
}
|
|
85
|
+
}, [fetchXml, t]);
|
|
86
|
+
const download = useCallback(async (code) => {
|
|
87
|
+
setBusyChannel(code);
|
|
88
|
+
setError(null);
|
|
89
|
+
try {
|
|
90
|
+
const blob = await fetchXml(code);
|
|
91
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
92
|
+
const a = document.createElement('a');
|
|
93
|
+
a.href = objectUrl;
|
|
94
|
+
a.download = `sitemap-${code}.xml`;
|
|
95
|
+
document.body.appendChild(a);
|
|
96
|
+
a.click();
|
|
97
|
+
document.body.removeChild(a);
|
|
98
|
+
URL.revokeObjectURL(objectUrl);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
setError(err instanceof Error ? err.message : t('seo.sitemap.error.download'));
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
setBusyChannel(null);
|
|
105
|
+
}
|
|
106
|
+
}, [fetchXml, t]);
|
|
107
|
+
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: t('seo.sitemap.title') }) }), _jsxs(CardContent, { className: "space-y-3", children: [error ? (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })) : null, message ? (_jsx(Alert, { variant: "success", children: _jsx(AlertDescription, { children: message }) })) : null, loading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('seo.sitemap.loading') })) : rows.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('seo.sitemap.empty') })) : (_jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: t('seo.sitemap.column.channel') }), _jsx(TableHead, { children: t('seo.sitemap.column.storefrontUrl') }), _jsx(TableHead, { children: t('seo.sitemap.column.lastGenerated') }), _jsx(TableHead, { className: "text-right", children: t('seo.sitemap.column.urls') }), _jsx(TableHead, { className: "text-right", children: t('seo.sitemap.column.size') }), _jsx(TableHead, { className: "text-right", children: t('seo.sitemap.column.actions') })] }) }), _jsx(TableBody, { children: rows.map((row) => {
|
|
108
|
+
const busy = busyChannel === row.salesChannelCode;
|
|
109
|
+
return (_jsxs(TableRow, { children: [_jsxs(TableCell, { children: [_jsx("div", { className: "font-medium", children: row.salesChannelName }), _jsx("div", { className: "font-mono text-xs text-muted-foreground", children: row.salesChannelCode })] }), _jsxs(TableCell, { children: [_jsx("div", { className: "font-mono text-xs", children: row.storefrontUrl }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [t('seo.sitemap.sourcePrefix'), " ", row.storefrontUrlSource] })] }), _jsx(TableCell, { children: row.generatedAt ? formatDateTime(row.generatedAt) : '—' }), _jsx(TableCell, { className: "text-right", children: row.urlCount?.toLocaleString() ?? '—' }), _jsx(TableCell, { className: "text-right", children: row.byteSize ? formatBytes(row.byteSize) : '—' }), _jsx(TableCell, { className: "text-right", children: _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(Button, { size: "sm", variant: "outline", disabled: busy, onClick: () => {
|
|
110
|
+
void regenerate(row.salesChannelCode);
|
|
111
|
+
}, children: busy ? '…' : t('seo.sitemap.regenerate') }), _jsx(Button, { size: "sm", variant: "ghost", disabled: busy || row.generatedAt === null, onClick: () => {
|
|
112
|
+
void preview(row.salesChannelCode);
|
|
113
|
+
}, children: t('seo.sitemap.preview') }), _jsx(Button, { size: "sm", variant: "ghost", disabled: busy || row.generatedAt === null, onClick: () => {
|
|
114
|
+
void download(row.salesChannelCode);
|
|
115
|
+
}, children: t('seo.sitemap.download') })] }) })] }, row.salesChannelCode));
|
|
116
|
+
}) })] })), _jsxs("p", { className: "text-xs text-muted-foreground", children: [t('seo.sitemap.help.prefix'), " ", _jsx("code", { children: "sales_channels.storefront_url" }), ' ', t('seo.sitemap.help.middle'), " ", _jsx("code", { children: "STOREFRONT_BASE_URL" }), " ", t('seo.sitemap.help.suffix')] })] })] }));
|
|
117
|
+
}
|
|
118
|
+
function MetaEditorCard() {
|
|
119
|
+
const t = useTranslation('core');
|
|
120
|
+
const [entityType, setEntityType] = useState('product');
|
|
121
|
+
const [entityId, setEntityId] = useState('');
|
|
122
|
+
const [locale, setLocale] = useState('en-US');
|
|
123
|
+
const [meta, setMeta] = useState(null);
|
|
124
|
+
const [draft, setDraft] = useState({ locale: 'en-US' });
|
|
125
|
+
const [busy, setBusy] = useState(false);
|
|
126
|
+
const [message, setMessage] = useState(null);
|
|
127
|
+
const [error, setError] = useState(null);
|
|
128
|
+
const load = useCallback(async () => {
|
|
129
|
+
if (!entityId.trim())
|
|
130
|
+
return;
|
|
131
|
+
setBusy(true);
|
|
132
|
+
setError(null);
|
|
133
|
+
setMessage(null);
|
|
134
|
+
try {
|
|
135
|
+
const res = await apiClient.get(`/api/v1/admin/seo/meta/${entityType}/${entityId}?locale=${encodeURIComponent(locale)}`);
|
|
136
|
+
setMeta(res.data);
|
|
137
|
+
setDraft({
|
|
138
|
+
locale,
|
|
139
|
+
title: res.data.override?.title ?? null,
|
|
140
|
+
description: res.data.override?.description ?? null,
|
|
141
|
+
ogTitle: res.data.override?.ogTitle ?? null,
|
|
142
|
+
ogDescription: res.data.override?.ogDescription ?? null,
|
|
143
|
+
ogImageUrl: res.data.override?.ogImageUrl ?? null,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
setError(err instanceof ApiError ? err.envelope.error.message : t('seo.meta.error.load'));
|
|
148
|
+
setMeta(null);
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
setBusy(false);
|
|
152
|
+
}
|
|
153
|
+
}, [entityType, entityId, locale, t]);
|
|
154
|
+
const save = useCallback(async () => {
|
|
155
|
+
if (!entityId.trim())
|
|
156
|
+
return;
|
|
157
|
+
setBusy(true);
|
|
158
|
+
setError(null);
|
|
159
|
+
setMessage(null);
|
|
160
|
+
try {
|
|
161
|
+
await apiClient.put(`/api/v1/admin/seo/meta/${entityType}/${entityId}`, draft);
|
|
162
|
+
setMessage(t('seo.meta.info.saved'));
|
|
163
|
+
await load();
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
setError(err instanceof ApiError ? err.envelope.error.message : t('seo.meta.error.save'));
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
setBusy(false);
|
|
170
|
+
}
|
|
171
|
+
}, [entityType, entityId, draft, load, t]);
|
|
172
|
+
return (_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx(CardTitle, { children: t('seo.meta.title') }) }), _jsxs(CardContent, { className: "space-y-4", children: [error ? (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })) : null, message ? (_jsx(Alert, { variant: "success", children: _jsx(AlertDescription, { children: message }) })) : null, _jsxs("div", { className: "flex flex-wrap items-end gap-2", children: [_jsx(Select, { className: "w-auto", value: entityType, onChange: (e) => {
|
|
173
|
+
setEntityType(e.target.value);
|
|
174
|
+
setEntityId('');
|
|
175
|
+
}, children: ENTITY_TYPES.map((et) => (_jsx("option", { value: et, children: et }, et))) }), _jsx("div", { className: "w-80", children: entityType === 'product' ? (_jsx(ProductPicker, { mode: "select", value: entityId || null, onChange: (v) => setEntityId(v ?? ''), includeArchived: true })) : (_jsx(CategorySelect, { value: entityId || null, onChange: (v) => setEntityId(v ?? '') })) }), _jsx(Input, { className: "w-24", value: locale, onChange: (e) => setLocale(e.target.value), placeholder: t('seo.meta.field.locale') }), _jsx(Button, { variant: "outline", onClick: () => {
|
|
176
|
+
void load();
|
|
177
|
+
}, disabled: busy || !entityId.trim(), children: t('seo.meta.load') })] }), meta ? (_jsxs(_Fragment, { children: [_jsxs(Card, { className: "bg-muted/30", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-sm", children: t('seo.meta.resolvedTitle', { source: meta.resolved.source }) }) }), _jsx(CardContent, { children: _jsx(Table, { children: _jsxs(TableBody, { children: [_jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-40", children: t('seo.meta.field.title') }), _jsx(TableCell, { children: meta.resolved.title })] }), _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-40", children: t('seo.meta.field.description') }), _jsx(TableCell, { children: meta.resolved.description })] }), _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-40", children: t('seo.meta.field.ogTitle') }), _jsx(TableCell, { children: meta.resolved.openGraph.title })] }), _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-40", children: t('seo.meta.field.ogDescription') }), _jsx(TableCell, { children: meta.resolved.openGraph.description })] }), _jsxs(TableRow, { children: [_jsx(TableHead, { className: "w-40", children: t('seo.meta.field.ogImage') }), _jsx(TableCell, { className: "font-mono text-xs", children: meta.resolved.openGraph.image ?? '—' })] })] }) }) })] }), _jsx("h3", { className: "text-sm font-semibold", children: t('seo.meta.overrideHeading') }), _jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: t('seo.meta.field.title') }), _jsx(Input, { value: draft.title ?? '', onChange: (e) => setDraft((d) => ({ ...d, title: e.target.value || null })) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: t('seo.meta.field.description') }), _jsx(Input, { value: draft.description ?? '', onChange: (e) => setDraft((d) => ({ ...d, description: e.target.value || null })) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: t('seo.meta.field.ogTitle') }), _jsx(Input, { value: draft.ogTitle ?? '', onChange: (e) => setDraft((d) => ({ ...d, ogTitle: e.target.value || null })) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: t('seo.meta.field.ogDescription') }), _jsx(Input, { value: draft.ogDescription ?? '', onChange: (e) => setDraft((d) => ({ ...d, ogDescription: e.target.value || null })) })] }), _jsxs("div", { className: "space-y-2 md:col-span-2", children: [_jsx(Label, { children: t('seo.meta.field.ogImageUrl') }), _jsx(Input, { type: "url", value: draft.ogImageUrl ?? '', onChange: (e) => setDraft((d) => ({ ...d, ogImageUrl: e.target.value || null })) })] })] }), _jsx(Button, { disabled: busy, onClick: () => {
|
|
178
|
+
void save();
|
|
179
|
+
}, children: busy ? t('seo.meta.saving') : t('seo.meta.saveOverride') })] })) : null] })] }));
|
|
180
|
+
}
|
|
181
|
+
function formatBytes(bytes) {
|
|
182
|
+
if (bytes < 1024)
|
|
183
|
+
return `${bytes} B`;
|
|
184
|
+
if (bytes < 1024 * 1024)
|
|
185
|
+
return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
186
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MiB`;
|
|
187
|
+
}
|
|
188
|
+
export default SeoPage;
|
|
189
|
+
//# sourceMappingURL=SeoPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SeoPage.js","sourceRoot":"","sources":["../../../src/admin/pages/SeoPage.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* Per-(entity, locale) SEO override (T235 / FR-101). When present, the
|
|
4
|
+
* resolver returns this row's fields verbatim and falls back to the rule
|
|
5
|
+
* for any nullable column that's left empty.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SeoMetaOverride {
|
|
8
|
+
[OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'title' | 'description' | 'ogTitle' | 'ogDescription' | 'ogImageUrl';
|
|
9
|
+
id: string;
|
|
10
|
+
entityType: 'product' | 'category' | 'cms_page';
|
|
11
|
+
entityId: string;
|
|
12
|
+
locale: string;
|
|
13
|
+
title?: string | null;
|
|
14
|
+
description?: string | null;
|
|
15
|
+
ogTitle?: string | null;
|
|
16
|
+
ogDescription?: string | null;
|
|
17
|
+
ogImageUrl?: string | null;
|
|
18
|
+
createdAt: Date;
|
|
19
|
+
updatedAt: Date;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=seo-meta-override.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-meta-override.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/seo-meta-override.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAgC,MAAM,iBAAiB,CAAC;AAI7F;;;;GAIG;AACH,qBAGa,eAAe;IAC1B,CAAC,aAAa,CAAC,CAAC,EACZ,IAAI,GACJ,WAAW,GACX,WAAW,GACX,OAAO,GACP,aAAa,GACb,SAAS,GACT,eAAe,GACf,YAAY,CAAC;IAGjB,EAAE,EAAE,MAAM,CAAgB;IAI1B,UAAU,EAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAIjD,QAAQ,EAAG,MAAM,CAAC;IAGlB,MAAM,EAAG,MAAM,CAAC;IAGhB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Entity, Index, OptionalProps, PrimaryKey, Property, Unique } from '@mikro-orm/core';
|
|
11
|
+
import { GlobalEntity } from '@endora-commerce/platform/tenancy';
|
|
12
|
+
import { randomUUID } from 'crypto';
|
|
13
|
+
/**
|
|
14
|
+
* Per-(entity, locale) SEO override (T235 / FR-101). When present, the
|
|
15
|
+
* resolver returns this row's fields verbatim and falls back to the rule
|
|
16
|
+
* for any nullable column that's left empty.
|
|
17
|
+
*/
|
|
18
|
+
let SeoMetaOverride = class SeoMetaOverride {
|
|
19
|
+
[OptionalProps];
|
|
20
|
+
id = randomUUID();
|
|
21
|
+
entityType;
|
|
22
|
+
entityId;
|
|
23
|
+
locale;
|
|
24
|
+
title;
|
|
25
|
+
description;
|
|
26
|
+
ogTitle;
|
|
27
|
+
ogDescription;
|
|
28
|
+
ogImageUrl;
|
|
29
|
+
createdAt = new Date();
|
|
30
|
+
updatedAt = new Date();
|
|
31
|
+
};
|
|
32
|
+
__decorate([
|
|
33
|
+
PrimaryKey({ type: 'uuid' }),
|
|
34
|
+
__metadata("design:type", String)
|
|
35
|
+
], SeoMetaOverride.prototype, "id", void 0);
|
|
36
|
+
__decorate([
|
|
37
|
+
Property({ type: 'string', length: 32 }),
|
|
38
|
+
Index(),
|
|
39
|
+
__metadata("design:type", String)
|
|
40
|
+
], SeoMetaOverride.prototype, "entityType", void 0);
|
|
41
|
+
__decorate([
|
|
42
|
+
Property({ type: 'uuid' }),
|
|
43
|
+
Index(),
|
|
44
|
+
__metadata("design:type", String)
|
|
45
|
+
], SeoMetaOverride.prototype, "entityId", void 0);
|
|
46
|
+
__decorate([
|
|
47
|
+
Property({ type: 'string', length: 10 }),
|
|
48
|
+
__metadata("design:type", String)
|
|
49
|
+
], SeoMetaOverride.prototype, "locale", void 0);
|
|
50
|
+
__decorate([
|
|
51
|
+
Property({ type: 'string', length: 160, nullable: true }),
|
|
52
|
+
__metadata("design:type", Object)
|
|
53
|
+
], SeoMetaOverride.prototype, "title", void 0);
|
|
54
|
+
__decorate([
|
|
55
|
+
Property({ type: 'string', length: 400, nullable: true }),
|
|
56
|
+
__metadata("design:type", Object)
|
|
57
|
+
], SeoMetaOverride.prototype, "description", void 0);
|
|
58
|
+
__decorate([
|
|
59
|
+
Property({ type: 'string', length: 160, nullable: true }),
|
|
60
|
+
__metadata("design:type", Object)
|
|
61
|
+
], SeoMetaOverride.prototype, "ogTitle", void 0);
|
|
62
|
+
__decorate([
|
|
63
|
+
Property({ type: 'string', length: 400, nullable: true }),
|
|
64
|
+
__metadata("design:type", Object)
|
|
65
|
+
], SeoMetaOverride.prototype, "ogDescription", void 0);
|
|
66
|
+
__decorate([
|
|
67
|
+
Property({ type: 'string', length: 2048, nullable: true }),
|
|
68
|
+
__metadata("design:type", Object)
|
|
69
|
+
], SeoMetaOverride.prototype, "ogImageUrl", void 0);
|
|
70
|
+
__decorate([
|
|
71
|
+
Property({ type: 'datetime', onCreate: () => new Date() }),
|
|
72
|
+
__metadata("design:type", Date)
|
|
73
|
+
], SeoMetaOverride.prototype, "createdAt", void 0);
|
|
74
|
+
__decorate([
|
|
75
|
+
Property({ type: 'datetime', onUpdate: () => new Date() }),
|
|
76
|
+
__metadata("design:type", Date)
|
|
77
|
+
], SeoMetaOverride.prototype, "updatedAt", void 0);
|
|
78
|
+
SeoMetaOverride = __decorate([
|
|
79
|
+
GlobalEntity(),
|
|
80
|
+
Entity({ tableName: 'seo_meta_overrides' }),
|
|
81
|
+
Unique({ name: 'uniq_seo_meta_overrides_entity_locale', properties: ['entityType', 'entityId', 'locale'] })
|
|
82
|
+
], SeoMetaOverride);
|
|
83
|
+
export { SeoMetaOverride };
|
|
84
|
+
//# sourceMappingURL=seo-meta-override.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-meta-override.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/seo-meta-override.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC7F,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;GAIG;AAII,IAAM,eAAe,GAArB,MAAM,eAAe;IAC1B,CAAC,aAAa,CAAC,CAQE;IAGjB,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,UAAU,CAAuC;IAIjD,QAAQ,CAAU;IAGlB,MAAM,CAAU;IAGhB,KAAK,CAAiB;IAGtB,WAAW,CAAiB;IAG5B,OAAO,CAAiB;IAGxB,aAAa,CAAiB;IAG9B,UAAU,CAAiB;IAG3B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAjCC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2CACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxC,KAAK,EAAE;;mDACyC;AAIjD;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,KAAK,EAAE;;iDACU;AAGlB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;+CACzB;AAGhB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;8CACpC;AAGtB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;oDAC9B;AAG5B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDAClC;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;sDAC5B;AAG9B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;mDAChC;AAG3B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;kDAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;kDAAc;AA5ClB,eAAe;IAH3B,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAC3C,MAAM,CAAC,EAAE,IAAI,EAAE,uCAAuC,EAAE,UAAU,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;GAC/F,eAAe,CA6C3B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OptionalProps } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* Single-row sitemap cache (T235 / FR-102). The generator overwrites
|
|
4
|
+
* `payload` on each regenerate; the public route streams it back. A
|
|
5
|
+
* `staleAfterMs` configuration in the service triggers an inline
|
|
6
|
+
* regeneration when the row is older than the threshold.
|
|
7
|
+
*/
|
|
8
|
+
export declare class SitemapCache {
|
|
9
|
+
[OptionalProps]?: 'generatedAt' | 'urlCount' | 'byteSize';
|
|
10
|
+
/** Stable singleton id — there is at most one sitemap per installation. */
|
|
11
|
+
key: string;
|
|
12
|
+
payload: string;
|
|
13
|
+
urlCount: number;
|
|
14
|
+
byteSize: number;
|
|
15
|
+
generatedAt: Date;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=sitemap-cache.entity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap-cache.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/sitemap-cache.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAG9E;;;;;GAKG;AACH,qBAEa,YAAY;IACvB,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa,GAAG,UAAU,GAAG,UAAU,CAAC;IAE1D,2EAA2E;IAE3E,GAAG,EAAE,MAAM,CAAa;IAGxB,OAAO,EAAG,MAAM,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAK;IAGrB,QAAQ,EAAE,MAAM,CAAK;IAGrB,WAAW,EAAE,IAAI,CAAc;CAChC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Entity, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
|
|
11
|
+
import { GlobalEntity } from '@endora-commerce/platform/tenancy';
|
|
12
|
+
/**
|
|
13
|
+
* Single-row sitemap cache (T235 / FR-102). The generator overwrites
|
|
14
|
+
* `payload` on each regenerate; the public route streams it back. A
|
|
15
|
+
* `staleAfterMs` configuration in the service triggers an inline
|
|
16
|
+
* regeneration when the row is older than the threshold.
|
|
17
|
+
*/
|
|
18
|
+
let SitemapCache = class SitemapCache {
|
|
19
|
+
[OptionalProps];
|
|
20
|
+
/** Stable singleton id — there is at most one sitemap per installation. */
|
|
21
|
+
key = 'default';
|
|
22
|
+
payload;
|
|
23
|
+
urlCount = 0;
|
|
24
|
+
byteSize = 0;
|
|
25
|
+
generatedAt = new Date();
|
|
26
|
+
};
|
|
27
|
+
__decorate([
|
|
28
|
+
PrimaryKey({ type: 'string', length: 32 }),
|
|
29
|
+
__metadata("design:type", String)
|
|
30
|
+
], SitemapCache.prototype, "key", void 0);
|
|
31
|
+
__decorate([
|
|
32
|
+
Property({ type: 'text' }),
|
|
33
|
+
__metadata("design:type", String)
|
|
34
|
+
], SitemapCache.prototype, "payload", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
Property({ type: 'integer' }),
|
|
37
|
+
__metadata("design:type", Number)
|
|
38
|
+
], SitemapCache.prototype, "urlCount", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
Property({ type: 'integer' }),
|
|
41
|
+
__metadata("design:type", Number)
|
|
42
|
+
], SitemapCache.prototype, "byteSize", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
Property({ type: 'datetime' }),
|
|
45
|
+
__metadata("design:type", Date)
|
|
46
|
+
], SitemapCache.prototype, "generatedAt", void 0);
|
|
47
|
+
SitemapCache = __decorate([
|
|
48
|
+
GlobalEntity(),
|
|
49
|
+
Entity({ tableName: 'sitemap_cache' })
|
|
50
|
+
], SitemapCache);
|
|
51
|
+
export { SitemapCache };
|
|
52
|
+
//# sourceMappingURL=sitemap-cache.entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sitemap-cache.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/sitemap-cache.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAEjE;;;;;GAKG;AAGI,IAAM,YAAY,GAAlB,MAAM,YAAY;IACvB,CAAC,aAAa,CAAC,CAA2C;IAE1D,2EAA2E;IAE3E,GAAG,GAAW,SAAS,CAAC;IAGxB,OAAO,CAAU;IAGjB,QAAQ,GAAW,CAAC,CAAC;IAGrB,QAAQ,GAAW,CAAC,CAAC;IAGrB,WAAW,GAAS,IAAI,IAAI,EAAE,CAAC;CAChC,CAAA;AAbC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;yCACnB;AAGxB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;6CACV;AAGjB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;8CACT;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;8CACT;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;8BAClB,IAAI;iDAAc;AAjBpB,YAAY;IAFxB,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;GAC1B,YAAY,CAkBxB"}
|