@actuate-media/cms-core 0.34.0 → 0.35.1

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.
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Effective site index status.
3
+ *
4
+ * Answers the one question General Settings exists to answer: "can search
5
+ * engines index this site right now, and is that what we want?" It reads the
6
+ * SAME effective SEO config used by the public renderer (`composePageMeta`) and
7
+ * the `/robots.txt` + `/sitemap.xml` routes — never a duplicate store — so the
8
+ * badge shown to editors always reflects reality.
9
+ *
10
+ * `computeSiteIndexStatus` is a pure function (easy to unit-test across
11
+ * environments); `getSiteIndexStatus` is the thin async gatherer that pulls the
12
+ * effective config, module settings, environment, and last audit from the DB.
13
+ */
14
+ import type { SiteSEOConfig } from '../config/types.js';
15
+ import { type SeoModuleSettings } from './config-store.js';
16
+ export type IndexStatusLevel = 'indexable' | 'protected' | 'blocked' | 'partially_blocked' | 'unknown';
17
+ export type IndexStatusSeverity = 'success' | 'warning' | 'danger' | 'neutral';
18
+ export type IndexCheckStatus = 'pass' | 'warning' | 'fail' | 'unknown';
19
+ export interface IndexCheck {
20
+ key: string;
21
+ label: string;
22
+ value: string;
23
+ status: IndexCheckStatus;
24
+ }
25
+ export interface IndexAction {
26
+ label: string;
27
+ href?: string;
28
+ action?: string;
29
+ }
30
+ export interface SiteIndexStatus {
31
+ status: IndexStatusLevel;
32
+ severity: IndexStatusSeverity;
33
+ label: string;
34
+ description: string;
35
+ environment: string;
36
+ checks: IndexCheck[];
37
+ actions: IndexAction[];
38
+ lastAuditAt: string | null;
39
+ }
40
+ export interface IndexStatusInputs {
41
+ environment: string | undefined;
42
+ seo: SiteSEOConfig | null | undefined;
43
+ module: SeoModuleSettings;
44
+ /** True when any SEO config exists (static config or DB overrides). */
45
+ hasSeoConfig: boolean;
46
+ lastAuditAt: string | null;
47
+ }
48
+ /**
49
+ * Detect a blanket `Disallow: /` in a custom robots.txt body — i.e. a rule that
50
+ * blocks the entire site (path is exactly `/`, optionally trailing comment).
51
+ */
52
+ export declare function robotsTxtBlocksEntireSite(robotsTxt: string): boolean;
53
+ export declare function computeSiteIndexStatus(input: IndexStatusInputs): SiteIndexStatus;
54
+ /** Gather effective SEO config + module + environment + last audit, then compute. */
55
+ export declare function getSiteIndexStatus(db: unknown): Promise<SiteIndexStatus>;
56
+ //# sourceMappingURL=index-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-status.d.ts","sourceRoot":"","sources":["../../src/seo/index-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAEvD,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAA;AAG1B,MAAM,MAAM,gBAAgB,GACxB,WAAW,GACX,WAAW,GACX,SAAS,GACT,mBAAmB,GACnB,SAAS,CAAA;AAEb,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;AAC9E,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;AAEtE,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,gBAAgB,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAA;IACxB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,GAAG,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAAA;IACrC,MAAM,EAAE,iBAAiB,CAAA;IACzB,uEAAuE;IACvE,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGpE;AAYD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,iBAAiB,GAAG,eAAe,CA+IhF;AAED,qFAAqF;AACrF,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CA+B9E"}
@@ -0,0 +1,193 @@
1
+ import { getActuateConfig } from '../config/runtime.js';
2
+ import { getSeoOverrides, applySeoOverrides, resolveSeoModuleSettings, } from './config-store.js';
3
+ import { resolveSeoEnvironment } from './robots.js';
4
+ /**
5
+ * Detect a blanket `Disallow: /` in a custom robots.txt body — i.e. a rule that
6
+ * blocks the entire site (path is exactly `/`, optionally trailing comment).
7
+ */
8
+ export function robotsTxtBlocksEntireSite(robotsTxt) {
9
+ if (!robotsTxt)
10
+ return false;
11
+ return /(^|\n)\s*disallow:\s*\/\s*(#.*)?$/im.test(robotsTxt);
12
+ }
13
+ const ACTIONS = [
14
+ { label: 'Run SEO Audit', href: '/seo?tab=audit', action: 'run_seo_audit' },
15
+ { label: 'View robots.txt', href: '/robots.txt' },
16
+ { label: 'View sitemap.xml', href: '/sitemap.xml' },
17
+ ];
18
+ function yesNo(value) {
19
+ return value ? 'Yes' : 'No';
20
+ }
21
+ export function computeSiteIndexStatus(input) {
22
+ const environment = input.environment ?? 'unknown';
23
+ const isProduction = environment === 'production';
24
+ const seo = input.seo ?? {};
25
+ const robots = seo.robots ?? {};
26
+ const siteUrl = (seo.siteUrl ?? '').trim();
27
+ const hasSiteUrl = siteUrl.length > 0;
28
+ const robotsRouteDisabled = robots.disabled === true || input.module.robotsEnabled === false;
29
+ const customRobots = input.module.robotsTxt?.trim() ? input.module.robotsTxt : '';
30
+ const robotsBlocksAll = customRobots ? robotsTxtBlocksEntireSite(customRobots) : false;
31
+ const globalNoindex = robots.defaultNoIndex === true;
32
+ const nonProdNoindex = robots.noIndexNonProduction === true;
33
+ const sitemapEnabled = seo.sitemap?.disabled !== true && input.module.sitemapEnabled !== false;
34
+ const checks = [
35
+ {
36
+ key: 'environment',
37
+ label: 'Environment',
38
+ value: environment === 'unknown' ? 'Unknown' : capitalize(environment),
39
+ status: environment === 'unknown' ? 'unknown' : 'pass',
40
+ },
41
+ {
42
+ key: 'siteUrl',
43
+ label: 'Site URL configured',
44
+ value: yesNo(hasSiteUrl),
45
+ status: hasSiteUrl ? 'pass' : 'warning',
46
+ },
47
+ {
48
+ key: 'robotsBlockAll',
49
+ label: 'Robots.txt blocking all',
50
+ value: yesNo(robotsRouteDisabled || robotsBlocksAll),
51
+ status: robotsRouteDisabled || robotsBlocksAll ? (isProduction ? 'fail' : 'warning') : 'pass',
52
+ },
53
+ {
54
+ key: 'globalNoindex',
55
+ label: 'Global noindex',
56
+ value: globalNoindex ? 'On' : 'Off',
57
+ status: globalNoindex ? (isProduction ? 'fail' : 'warning') : 'pass',
58
+ },
59
+ {
60
+ key: 'nonProdNoindex',
61
+ label: 'Non-production noindex',
62
+ value: nonProdNoindex ? 'On' : 'Off',
63
+ // Off is a warning only in a non-production environment (it may be indexed).
64
+ status: nonProdNoindex ? 'pass' : isProduction ? 'pass' : 'warning',
65
+ },
66
+ {
67
+ key: 'sitemap',
68
+ label: 'Sitemap enabled',
69
+ value: yesNo(sitemapEnabled),
70
+ status: sitemapEnabled ? 'pass' : 'warning',
71
+ },
72
+ {
73
+ key: 'lastAudit',
74
+ label: 'Last SEO audit',
75
+ value: input.lastAuditAt ? formatAuditDate(input.lastAuditAt) : 'Never',
76
+ status: input.lastAuditAt ? 'pass' : 'unknown',
77
+ },
78
+ ];
79
+ const base = { environment, checks, actions: ACTIONS, lastAuditAt: input.lastAuditAt };
80
+ if (!input.hasSeoConfig) {
81
+ return {
82
+ ...base,
83
+ status: 'unknown',
84
+ severity: 'neutral',
85
+ label: 'Unknown',
86
+ description: 'Run an SEO audit to verify crawl/index status.',
87
+ };
88
+ }
89
+ if (isProduction && (robotsRouteDisabled || robotsBlocksAll || globalNoindex)) {
90
+ return {
91
+ ...base,
92
+ status: 'blocked',
93
+ severity: 'danger',
94
+ label: 'Blocked',
95
+ description: 'Search engines are currently blocked from indexing this production site.',
96
+ };
97
+ }
98
+ if (!isProduction && nonProdNoindex) {
99
+ return {
100
+ ...base,
101
+ status: 'protected',
102
+ severity: 'warning',
103
+ label: 'Protected',
104
+ description: 'Non-production environment is noindexed. Production remains unaffected.',
105
+ };
106
+ }
107
+ // Non-production without the guard, or otherwise blocked in a non-prod env.
108
+ if (!isProduction && (robotsRouteDisabled || robotsBlocksAll || globalNoindex)) {
109
+ return {
110
+ ...base,
111
+ status: 'blocked',
112
+ severity: 'warning',
113
+ label: 'Blocked',
114
+ description: 'Indexing is disabled in this non-production environment.',
115
+ };
116
+ }
117
+ if (!hasSiteUrl) {
118
+ return {
119
+ ...base,
120
+ status: 'unknown',
121
+ severity: 'warning',
122
+ label: 'Needs attention',
123
+ description: 'Site URL is not configured — canonical, sitemap, and Open Graph URLs may be invalid.',
124
+ };
125
+ }
126
+ if (!isProduction && !nonProdNoindex) {
127
+ return {
128
+ ...base,
129
+ status: 'partially_blocked',
130
+ severity: 'warning',
131
+ label: 'Partially blocked',
132
+ description: 'This non-production environment can be indexed if publicly accessible. Enable non-production noindex to protect it.',
133
+ };
134
+ }
135
+ if (!sitemapEnabled) {
136
+ return {
137
+ ...base,
138
+ status: 'partially_blocked',
139
+ severity: 'warning',
140
+ label: 'Partially blocked',
141
+ description: 'Production pages can be indexed, but the sitemap is disabled.',
142
+ };
143
+ }
144
+ return {
145
+ ...base,
146
+ status: 'indexable',
147
+ severity: 'success',
148
+ label: 'Indexable',
149
+ description: 'Production pages can be indexed unless individually noindexed.',
150
+ };
151
+ }
152
+ /** Gather effective SEO config + module + environment + last audit, then compute. */
153
+ export async function getSiteIndexStatus(db) {
154
+ const base = getActuateConfig() ?? null;
155
+ const overrides = await getSeoOverrides(db);
156
+ const effective = applySeoOverrides(base, overrides);
157
+ const seo = effective?.seo ?? base?.seo ?? null;
158
+ const seoModule = resolveSeoModuleSettings(overrides);
159
+ const hasSeoConfig = Boolean(seo) || Boolean(overrides);
160
+ let lastAuditAt = null;
161
+ try {
162
+ const d = db;
163
+ if (d?.seoAuditRun?.findFirst) {
164
+ const run = (await d.seoAuditRun.findFirst({
165
+ where: { status: 'COMPLETED' },
166
+ orderBy: { startedAt: 'desc' },
167
+ select: { finishedAt: true, startedAt: true },
168
+ }));
169
+ const ts = run?.finishedAt ?? run?.startedAt ?? null;
170
+ lastAuditAt = ts ? new Date(ts).toISOString() : null;
171
+ }
172
+ }
173
+ catch {
174
+ // Audit table may be unavailable (older schema / mock client) — leave null.
175
+ }
176
+ return computeSiteIndexStatus({
177
+ environment: resolveSeoEnvironment(),
178
+ seo,
179
+ module: seoModule,
180
+ hasSeoConfig,
181
+ lastAuditAt,
182
+ });
183
+ }
184
+ function capitalize(value) {
185
+ return value.charAt(0).toUpperCase() + value.slice(1);
186
+ }
187
+ function formatAuditDate(iso) {
188
+ const d = new Date(iso);
189
+ if (Number.isNaN(d.getTime()))
190
+ return 'Never';
191
+ return d.toISOString().slice(0, 10);
192
+ }
193
+ //# sourceMappingURL=index-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-status.js","sourceRoot":"","sources":["../../src/seo/index-status.ts"],"names":[],"mappings":"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"}
@@ -18,4 +18,6 @@ export { runSeoAuditAnalysis, buildQuickWins, issueKeyFor } from './audit-engine
18
18
  export type { AuditEntityInput, AuditExtraSignals, DetectedIssue, AuditPageRecord, QuickWin, SeoAuditResult, } from './audit-engine.js';
19
19
  export { runAndPersistAudit, gatherAuditEntities, documentToAuditEntity, frontEndContentCollectionTypes, isInternalCollection, } from './audit-runner.js';
20
20
  export type { ContentCollectionTypes } from './audit-runner.js';
21
+ export { computeSiteIndexStatus, getSiteIndexStatus, robotsTxtBlocksEntireSite, } from './index-status.js';
22
+ export type { SiteIndexStatus, IndexStatusLevel, IndexStatusSeverity, IndexCheck, IndexCheckStatus, IndexAction, IndexStatusInputs, } from './index-status.js';
21
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAA;AAEtB,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAElG,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAE3F,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAE5E,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE1F,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAErE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE9E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE/D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAElE,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAElG,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAE1B,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE9E,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpF,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,cAAc,GACf,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAA;AAEtB,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAElG,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAE3F,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAE5E,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAE1F,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAErE,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAE9E,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE/D,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAElE,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAElG,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAE1B,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE9E,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,QAAQ,EACR,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpF,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,QAAQ,EACR,cAAc,GACf,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAE/D,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAA;AAE1B,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,mBAAmB,CAAA"}
package/dist/seo/index.js CHANGED
@@ -8,4 +8,5 @@ export { SEO_CONFIG_COLLECTION, getSeoOverrides, putSeoOverrides, applySeoOverri
8
8
  export { calculatePageSeoScore, calculateSiteSeoScore, gradeForSeoScore, countH1, PAGE_SEO_WEIGHTS, SITE_SEO_WEIGHTS, } from './score.js';
9
9
  export { runSeoAuditAnalysis, buildQuickWins, issueKeyFor } from './audit-engine.js';
10
10
  export { runAndPersistAudit, gatherAuditEntities, documentToAuditEntity, frontEndContentCollectionTypes, isInternalCollection, } from './audit-runner.js';
11
+ export { computeSiteIndexStatus, getSiteIndexStatus, robotsTxtBlocksEntireSite, } from './index-status.js';
11
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAA;AAItB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAI3F,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAI5E,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAIrE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAI/C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAIlE,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAanB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAWpF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/seo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAA;AAItB,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAI3F,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAI5E,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAIrE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAI/C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAIlE,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,gBAAgB,EAChB,OAAO,EACP,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAanB,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAWpF,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cms-core",
3
- "version": "0.34.0",
3
+ "version": "0.35.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/actuate-media/actuatecms.git",
@@ -98,7 +98,7 @@
98
98
  "prisma": "^7.8.0",
99
99
  "tsx": "^4.0.0",
100
100
  "typescript": "^5.7.0",
101
- "vitest": "^3.0.0",
101
+ "vitest": "^4.1.0",
102
102
  "ws": "^8.18.0"
103
103
  },
104
104
  "files": [