@actuate-media/cms-core 0.28.0 → 0.29.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/dist/__tests__/diagnostics/env.test.js +18 -0
- package/dist/__tests__/diagnostics/env.test.js.map +1 -1
- package/dist/__tests__/media/seo.test.d.ts +2 -0
- package/dist/__tests__/media/seo.test.d.ts.map +1 -0
- package/dist/__tests__/media/seo.test.js +186 -0
- package/dist/__tests__/media/seo.test.js.map +1 -0
- package/dist/__tests__/redirects/graph.test.d.ts +2 -0
- package/dist/__tests__/redirects/graph.test.d.ts.map +1 -0
- package/dist/__tests__/redirects/graph.test.js +104 -0
- package/dist/__tests__/redirects/graph.test.js.map +1 -0
- package/dist/__tests__/redirects/suggest.test.d.ts +2 -0
- package/dist/__tests__/redirects/suggest.test.d.ts.map +1 -0
- package/dist/__tests__/redirects/suggest.test.js +28 -0
- package/dist/__tests__/redirects/suggest.test.js.map +1 -0
- package/dist/__tests__/seo/audit-engine.test.d.ts +2 -0
- package/dist/__tests__/seo/audit-engine.test.d.ts.map +1 -0
- package/dist/__tests__/seo/audit-engine.test.js +152 -0
- package/dist/__tests__/seo/audit-engine.test.js.map +1 -0
- package/dist/__tests__/seo/config-store.test.js +24 -160
- package/dist/__tests__/seo/config-store.test.js.map +1 -1
- package/dist/__tests__/seo/score.test.d.ts +2 -0
- package/dist/__tests__/seo/score.test.d.ts.map +1 -0
- package/dist/__tests__/seo/score.test.js +152 -0
- package/dist/__tests__/seo/score.test.js.map +1 -0
- package/dist/__tests__/setup/index.test.d.ts +2 -0
- package/dist/__tests__/setup/index.test.d.ts.map +1 -0
- package/dist/__tests__/setup/index.test.js +82 -0
- package/dist/__tests__/setup/index.test.js.map +1 -0
- package/dist/api/handlers.d.ts.map +1 -1
- package/dist/api/handlers.js +2095 -228
- package/dist/api/handlers.js.map +1 -1
- package/dist/diagnostics/env.d.ts.map +1 -1
- package/dist/diagnostics/env.js +9 -5
- package/dist/diagnostics/env.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/media/index.d.ts +2 -0
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +1 -0
- package/dist/media/index.js.map +1 -1
- package/dist/media/seo.d.ts +88 -0
- package/dist/media/seo.d.ts.map +1 -0
- package/dist/media/seo.js +215 -0
- package/dist/media/seo.js.map +1 -0
- package/dist/redirects/graph.d.ts +68 -0
- package/dist/redirects/graph.d.ts.map +1 -0
- package/dist/redirects/graph.js +136 -0
- package/dist/redirects/graph.js.map +1 -0
- package/dist/redirects/index.d.ts +5 -0
- package/dist/redirects/index.d.ts.map +1 -0
- package/dist/redirects/index.js +3 -0
- package/dist/redirects/index.js.map +1 -0
- package/dist/redirects/suggest.d.ts +21 -0
- package/dist/redirects/suggest.d.ts.map +1 -0
- package/dist/redirects/suggest.js +55 -0
- package/dist/redirects/suggest.js.map +1 -0
- package/dist/seo/audit-engine.d.ts +119 -0
- package/dist/seo/audit-engine.d.ts.map +1 -0
- package/dist/seo/audit-engine.js +402 -0
- package/dist/seo/audit-engine.js.map +1 -0
- package/dist/seo/audit-runner.d.ts +41 -0
- package/dist/seo/audit-runner.d.ts.map +1 -0
- package/dist/seo/audit-runner.js +223 -0
- package/dist/seo/audit-runner.js.map +1 -0
- package/dist/seo/config-store.d.ts +28 -0
- package/dist/seo/config-store.d.ts.map +1 -1
- package/dist/seo/config-store.js +22 -0
- package/dist/seo/config-store.js.map +1 -1
- package/dist/seo/index.d.ts +7 -2
- package/dist/seo/index.d.ts.map +1 -1
- package/dist/seo/index.js +4 -1
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/score.d.ts +128 -0
- package/dist/seo/score.d.ts.map +1 -0
- package/dist/seo/score.js +213 -0
- package/dist/seo/score.js.map +1 -0
- package/dist/setup/index.d.ts +16 -1
- package/dist/setup/index.d.ts.map +1 -1
- package/dist/setup/index.js +52 -2
- package/dist/setup/index.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/0008_media_center/migration.sql +47 -0
- package/prisma/migrations/0009_seo/migration.sql +143 -0
- package/prisma/schema.prisma +183 -8
package/prisma/schema.prisma
CHANGED
|
@@ -330,6 +330,12 @@ model Version {
|
|
|
330
330
|
@@map("actuate_versions")
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
+
enum MediaStatus {
|
|
334
|
+
PROCESSING
|
|
335
|
+
READY
|
|
336
|
+
FAILED
|
|
337
|
+
}
|
|
338
|
+
|
|
333
339
|
model Media {
|
|
334
340
|
id String @id @default(cuid())
|
|
335
341
|
filename String
|
|
@@ -351,11 +357,34 @@ model Media {
|
|
|
351
357
|
createdAt DateTime @default(now())
|
|
352
358
|
updatedAt DateTime @updatedAt
|
|
353
359
|
|
|
360
|
+
// ── Media Center additions ──────────────────────────────────────
|
|
361
|
+
// All nullable / defaulted so they're safe to add to a populated DB
|
|
362
|
+
// with no backfill. SEO score/issues are intentionally NOT stored —
|
|
363
|
+
// they're derived on read by `calculateMediaSeoScore()` so they can
|
|
364
|
+
// never drift from the metadata below.
|
|
365
|
+
originalFileName String?
|
|
366
|
+
caption String?
|
|
367
|
+
description String?
|
|
368
|
+
focusKeyword String?
|
|
369
|
+
tags Json?
|
|
370
|
+
// `storageKey` historically held the public URL; `publicUrl` splits
|
|
371
|
+
// that concern out. New uploads populate both; legacy rows keep the
|
|
372
|
+
// URL in `storageKey` and `mediaUrl()` still resolves it.
|
|
373
|
+
publicUrl String?
|
|
374
|
+
storageProvider String?
|
|
375
|
+
durationSeconds Float?
|
|
376
|
+
thumbnailUrl String?
|
|
377
|
+
responsiveVariants Json?
|
|
378
|
+
status MediaStatus @default(READY)
|
|
379
|
+
deletedAt DateTime?
|
|
380
|
+
|
|
354
381
|
uploadedBy User @relation(fields: [uploadedById], references: [id])
|
|
355
382
|
folder Folder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
|
356
383
|
mediaUsages MediaUsage[]
|
|
357
384
|
|
|
358
385
|
@@index([folderId])
|
|
386
|
+
@@index([deletedAt])
|
|
387
|
+
@@index([mimeType])
|
|
359
388
|
@@map("actuate_media")
|
|
360
389
|
}
|
|
361
390
|
|
|
@@ -444,19 +473,165 @@ model WorkflowState {
|
|
|
444
473
|
}
|
|
445
474
|
|
|
446
475
|
model Redirect {
|
|
447
|
-
id
|
|
448
|
-
source
|
|
449
|
-
destination
|
|
450
|
-
statusCode
|
|
451
|
-
isRegex
|
|
452
|
-
notes
|
|
453
|
-
|
|
454
|
-
|
|
476
|
+
id String @id @default(cuid())
|
|
477
|
+
source String
|
|
478
|
+
destination String
|
|
479
|
+
statusCode Int @default(301)
|
|
480
|
+
isRegex Boolean @default(false)
|
|
481
|
+
notes String?
|
|
482
|
+
// Runtime + management metadata (added in 0009_seo). All defaulted so the
|
|
483
|
+
// migration is safe to apply to a populated table with no backfill.
|
|
484
|
+
enabled Boolean @default(true)
|
|
485
|
+
priority Int @default(0)
|
|
486
|
+
preserveQuery Boolean @default(false)
|
|
487
|
+
// "manual" | "import" | "ai-404-recovery" | "chain-flatten"
|
|
488
|
+
source_kind String @default("manual")
|
|
489
|
+
hits Int @default(0)
|
|
490
|
+
lastHitAt DateTime?
|
|
491
|
+
createdById String?
|
|
492
|
+
createdAt DateTime @default(now())
|
|
493
|
+
updatedAt DateTime @updatedAt
|
|
455
494
|
|
|
456
495
|
@@unique([source])
|
|
496
|
+
@@index([enabled])
|
|
497
|
+
@@index([lastHitAt])
|
|
457
498
|
@@map("actuate_redirects")
|
|
458
499
|
}
|
|
459
500
|
|
|
501
|
+
// ─── SEO module (0009_seo) ──────────────────────────────────────────
|
|
502
|
+
|
|
503
|
+
enum SeoAuditStatus {
|
|
504
|
+
RUNNING
|
|
505
|
+
COMPLETED
|
|
506
|
+
FAILED
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
enum SeoIssueSeverity {
|
|
510
|
+
critical
|
|
511
|
+
warning
|
|
512
|
+
info
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
enum SeoIssueStatus {
|
|
516
|
+
open
|
|
517
|
+
ignored
|
|
518
|
+
resolved
|
|
519
|
+
recurring
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
enum SeoIssueCategory {
|
|
523
|
+
content
|
|
524
|
+
technical
|
|
525
|
+
redirects
|
|
526
|
+
media
|
|
527
|
+
performance
|
|
528
|
+
schema
|
|
529
|
+
social
|
|
530
|
+
indexing
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/// One execution of the SEO audit engine. Holds a snapshot of the site
|
|
534
|
+
/// score and issue counts so the Audit tab can show run history without
|
|
535
|
+
/// recomputing. Issues belong to a run via SEOIssue.auditRunId.
|
|
536
|
+
model SeoAuditRun {
|
|
537
|
+
id String @id @default(cuid())
|
|
538
|
+
status SeoAuditStatus @default(RUNNING)
|
|
539
|
+
scope String @default("full")
|
|
540
|
+
startedById String?
|
|
541
|
+
startedAt DateTime @default(now())
|
|
542
|
+
finishedAt DateTime?
|
|
543
|
+
siteScoreBefore Int?
|
|
544
|
+
siteScoreAfter Int?
|
|
545
|
+
pagesScanned Int @default(0)
|
|
546
|
+
issuesFound Int @default(0)
|
|
547
|
+
criticalCount Int @default(0)
|
|
548
|
+
warningCount Int @default(0)
|
|
549
|
+
infoCount Int @default(0)
|
|
550
|
+
errorMessage String?
|
|
551
|
+
metadata Json?
|
|
552
|
+
|
|
553
|
+
issues SeoIssue[]
|
|
554
|
+
|
|
555
|
+
@@index([status])
|
|
556
|
+
@@index([startedAt])
|
|
557
|
+
@@map("actuate_seo_audit_runs")
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/// A single SEO problem detected by an audit run. `issueKey` is a stable
|
|
561
|
+
/// hash of (type + entityId/url) used to carry status across runs so a
|
|
562
|
+
/// resolved/ignored issue stays resolved/ignored when re-detected.
|
|
563
|
+
model SeoIssue {
|
|
564
|
+
id String @id @default(cuid())
|
|
565
|
+
auditRunId String?
|
|
566
|
+
issueKey String
|
|
567
|
+
entityType String?
|
|
568
|
+
entityId String?
|
|
569
|
+
entityTitle String?
|
|
570
|
+
url String?
|
|
571
|
+
severity SeoIssueSeverity
|
|
572
|
+
category SeoIssueCategory
|
|
573
|
+
type String
|
|
574
|
+
title String
|
|
575
|
+
description String?
|
|
576
|
+
impact String?
|
|
577
|
+
recommendation String?
|
|
578
|
+
status SeoIssueStatus @default(open)
|
|
579
|
+
fixable Boolean @default(false)
|
|
580
|
+
fixActionType String?
|
|
581
|
+
relatedEntityIds Json?
|
|
582
|
+
source String @default("audit")
|
|
583
|
+
firstDetectedAt DateTime @default(now())
|
|
584
|
+
lastDetectedAt DateTime @default(now())
|
|
585
|
+
resolvedAt DateTime?
|
|
586
|
+
resolvedById String?
|
|
587
|
+
metadata Json?
|
|
588
|
+
|
|
589
|
+
auditRun SeoAuditRun? @relation(fields: [auditRunId], references: [id], onDelete: SetNull)
|
|
590
|
+
|
|
591
|
+
@@index([auditRunId])
|
|
592
|
+
@@index([status])
|
|
593
|
+
@@index([severity])
|
|
594
|
+
@@index([category])
|
|
595
|
+
@@index([issueKey])
|
|
596
|
+
@@map("actuate_seo_issues")
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/// A 404 hit observed by the redirect middleware. Aggregated per path so
|
|
600
|
+
/// the Redirects tab can surface "broken URLs still getting traffic".
|
|
601
|
+
model Redirect404Hit {
|
|
602
|
+
id String @id @default(cuid())
|
|
603
|
+
path String
|
|
604
|
+
hits Int @default(1)
|
|
605
|
+
referrer String?
|
|
606
|
+
resolvedAt DateTime?
|
|
607
|
+
firstSeenAt DateTime @default(now())
|
|
608
|
+
lastSeenAt DateTime @default(now())
|
|
609
|
+
|
|
610
|
+
@@unique([path])
|
|
611
|
+
@@index([lastSeenAt])
|
|
612
|
+
@@map("actuate_redirect_404_hits")
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/// An AI/heuristic suggestion for a 404 destination. Confidence-scored and
|
|
616
|
+
/// never auto-applied below the configured threshold.
|
|
617
|
+
model RedirectSuggestion {
|
|
618
|
+
id String @id @default(cuid())
|
|
619
|
+
fromPath String
|
|
620
|
+
toPath String
|
|
621
|
+
confidence Int @default(0)
|
|
622
|
+
reason String?
|
|
623
|
+
// "open" | "accepted" | "dismissed"
|
|
624
|
+
status String @default("open")
|
|
625
|
+
source String @default("ai-404-recovery")
|
|
626
|
+
metadata Json?
|
|
627
|
+
createdAt DateTime @default(now())
|
|
628
|
+
updatedAt DateTime @updatedAt
|
|
629
|
+
|
|
630
|
+
@@index([status])
|
|
631
|
+
@@index([fromPath])
|
|
632
|
+
@@map("actuate_redirect_suggestions")
|
|
633
|
+
}
|
|
634
|
+
|
|
460
635
|
model FormSubmission {
|
|
461
636
|
id String @id @default(cuid())
|
|
462
637
|
formId String
|