@actuate-media/cms-core 0.1.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__/actions/document-crud.test.d.ts +2 -0
- package/dist/__tests__/actions/document-crud.test.d.ts.map +1 -0
- package/dist/__tests__/actions/document-crud.test.js +156 -0
- package/dist/__tests__/actions/document-crud.test.js.map +1 -0
- package/dist/__tests__/auth/password.test.d.ts +2 -0
- package/dist/__tests__/auth/password.test.d.ts.map +1 -0
- package/dist/__tests__/auth/password.test.js +102 -0
- package/dist/__tests__/auth/password.test.js.map +1 -0
- package/dist/__tests__/auth/session.test.d.ts +2 -0
- package/dist/__tests__/auth/session.test.d.ts.map +1 -0
- package/dist/__tests__/auth/session.test.js +66 -0
- package/dist/__tests__/auth/session.test.js.map +1 -0
- package/dist/__tests__/codegen/generate-types.test.d.ts +2 -0
- package/dist/__tests__/codegen/generate-types.test.d.ts.map +1 -0
- package/dist/__tests__/codegen/generate-types.test.js +173 -0
- package/dist/__tests__/codegen/generate-types.test.js.map +1 -0
- package/dist/__tests__/scheduling/scheduling.test.d.ts +2 -0
- package/dist/__tests__/scheduling/scheduling.test.d.ts.map +1 -0
- package/dist/__tests__/scheduling/scheduling.test.js +84 -0
- package/dist/__tests__/scheduling/scheduling.test.js.map +1 -0
- package/dist/__tests__/security/access.test.d.ts +2 -0
- package/dist/__tests__/security/access.test.d.ts.map +1 -0
- package/dist/__tests__/security/access.test.js +181 -0
- package/dist/__tests__/security/access.test.js.map +1 -0
- package/dist/__tests__/security/csrf.test.d.ts +2 -0
- package/dist/__tests__/security/csrf.test.d.ts.map +1 -0
- package/dist/__tests__/security/csrf.test.js +40 -0
- package/dist/__tests__/security/csrf.test.js.map +1 -0
- package/dist/__tests__/security/rate-limit.test.d.ts +2 -0
- package/dist/__tests__/security/rate-limit.test.d.ts.map +1 -0
- package/dist/__tests__/security/rate-limit.test.js +62 -0
- package/dist/__tests__/security/rate-limit.test.js.map +1 -0
- package/dist/__tests__/security/reauth.test.d.ts +2 -0
- package/dist/__tests__/security/reauth.test.d.ts.map +1 -0
- package/dist/__tests__/security/reauth.test.js +30 -0
- package/dist/__tests__/security/reauth.test.js.map +1 -0
- package/dist/__tests__/security/sanitize.test.d.ts +2 -0
- package/dist/__tests__/security/sanitize.test.d.ts.map +1 -0
- package/dist/__tests__/security/sanitize.test.js +75 -0
- package/dist/__tests__/security/sanitize.test.js.map +1 -0
- package/dist/__tests__/webhooks/webhooks.test.d.ts +2 -0
- package/dist/__tests__/webhooks/webhooks.test.d.ts.map +1 -0
- package/dist/__tests__/webhooks/webhooks.test.js +96 -0
- package/dist/__tests__/webhooks/webhooks.test.js.map +1 -0
- package/dist/a11y/index.d.ts +25 -0
- package/dist/a11y/index.d.ts.map +1 -0
- package/dist/a11y/index.js +88 -0
- package/dist/a11y/index.js.map +1 -0
- package/dist/actions.d.ts +42 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +391 -0
- package/dist/actions.js.map +1 -0
- package/dist/api/handler-factory.d.ts +7 -0
- package/dist/api/handler-factory.d.ts.map +1 -0
- package/dist/api/handler-factory.js +120 -0
- package/dist/api/handler-factory.js.map +1 -0
- package/dist/api/handlers.d.ts +4 -0
- package/dist/api/handlers.d.ts.map +1 -0
- package/dist/api/handlers.js +2119 -0
- package/dist/api/handlers.js.map +1 -0
- package/dist/api/index.d.ts +23 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +57 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/openapi.d.ts +3 -0
- package/dist/api/openapi.d.ts.map +1 -0
- package/dist/api/openapi.js +348 -0
- package/dist/api/openapi.js.map +1 -0
- package/dist/auth/index.d.ts +11 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +9 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/oauth.d.ts +84 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +201 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/password.d.ts +13 -0
- package/dist/auth/password.d.ts.map +1 -0
- package/dist/auth/password.js +47 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/auth/providers/github.d.ts +9 -0
- package/dist/auth/providers/github.d.ts.map +1 -0
- package/dist/auth/providers/github.js +10 -0
- package/dist/auth/providers/github.js.map +1 -0
- package/dist/auth/providers/google.d.ts +9 -0
- package/dist/auth/providers/google.d.ts.map +1 -0
- package/dist/auth/providers/google.js +10 -0
- package/dist/auth/providers/google.js.map +1 -0
- package/dist/auth/providers/microsoft.d.ts +9 -0
- package/dist/auth/providers/microsoft.d.ts.map +1 -0
- package/dist/auth/providers/microsoft.js +11 -0
- package/dist/auth/providers/microsoft.js.map +1 -0
- package/dist/auth/session.d.ts +21 -0
- package/dist/auth/session.d.ts.map +1 -0
- package/dist/auth/session.js +35 -0
- package/dist/auth/session.js.map +1 -0
- package/dist/auth/totp.d.ts +5 -0
- package/dist/auth/totp.d.ts.map +1 -0
- package/dist/auth/totp.js +86 -0
- package/dist/auth/totp.js.map +1 -0
- package/dist/backup/index.d.ts +19 -0
- package/dist/backup/index.d.ts.map +1 -0
- package/dist/backup/index.js +22 -0
- package/dist/backup/index.js.map +1 -0
- package/dist/cache/index.d.ts +15 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +32 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/client.d.ts +30 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +50 -0
- package/dist/client.js.map +1 -0
- package/dist/codegen/index.d.ts +4 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +370 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/collections/index.d.ts +17 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/collections/index.js +29 -0
- package/dist/collections/index.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +74 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +307 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +3 -0
- package/dist/config/types.js.map +1 -0
- package/dist/content/ai-api.d.ts +21 -0
- package/dist/content/ai-api.d.ts.map +1 -0
- package/dist/content/ai-api.js +19 -0
- package/dist/content/ai-api.js.map +1 -0
- package/dist/content/content-graph.d.ts +25 -0
- package/dist/content/content-graph.d.ts.map +1 -0
- package/dist/content/content-graph.js +40 -0
- package/dist/content/content-graph.js.map +1 -0
- package/dist/content/extract.d.ts +7 -0
- package/dist/content/extract.d.ts.map +1 -0
- package/dist/content/extract.js +33 -0
- package/dist/content/extract.js.map +1 -0
- package/dist/content/index.d.ts +8 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +5 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/structured-data.d.ts +80 -0
- package/dist/content/structured-data.d.ts.map +1 -0
- package/dist/content/structured-data.js +295 -0
- package/dist/content/structured-data.js.map +1 -0
- package/dist/db/adapters/mysql.d.ts +5 -0
- package/dist/db/adapters/mysql.d.ts.map +1 -0
- package/dist/db/adapters/mysql.js +18 -0
- package/dist/db/adapters/mysql.js.map +1 -0
- package/dist/db/adapters/postgres.d.ts +7 -0
- package/dist/db/adapters/postgres.d.ts.map +1 -0
- package/dist/db/adapters/postgres.js +20 -0
- package/dist/db/adapters/postgres.js.map +1 -0
- package/dist/db/adapters/sqlite.d.ts +5 -0
- package/dist/db/adapters/sqlite.d.ts.map +1 -0
- package/dist/db/adapters/sqlite.js +19 -0
- package/dist/db/adapters/sqlite.js.map +1 -0
- package/dist/db/create-adapter.d.ts +11 -0
- package/dist/db/create-adapter.d.ts.map +1 -0
- package/dist/db/create-adapter.js +43 -0
- package/dist/db/create-adapter.js.map +1 -0
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +5 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db.d.ts +20 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +35 -0
- package/dist/db.js.map +1 -0
- package/dist/fields/index.d.ts +15 -0
- package/dist/fields/index.d.ts.map +1 -0
- package/dist/fields/index.js +87 -0
- package/dist/fields/index.js.map +1 -0
- package/dist/forms/analytics.d.ts +62 -0
- package/dist/forms/analytics.d.ts.map +1 -0
- package/dist/forms/analytics.js +95 -0
- package/dist/forms/analytics.js.map +1 -0
- package/dist/forms/attribution.d.ts +29 -0
- package/dist/forms/attribution.d.ts.map +1 -0
- package/dist/forms/attribution.js +216 -0
- package/dist/forms/attribution.js.map +1 -0
- package/dist/forms/index.d.ts +5 -0
- package/dist/forms/index.d.ts.map +1 -0
- package/dist/forms/index.js +3 -0
- package/dist/forms/index.js.map +1 -0
- package/dist/graphql/index.d.ts +11 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +58 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/resolvers.d.ts +8 -0
- package/dist/graphql/resolvers.d.ts.map +1 -0
- package/dist/graphql/resolvers.js +93 -0
- package/dist/graphql/resolvers.js.map +1 -0
- package/dist/graphql/schema-builder.d.ts +3 -0
- package/dist/graphql/schema-builder.d.ts.map +1 -0
- package/dist/graphql/schema-builder.js +103 -0
- package/dist/graphql/schema-builder.js.map +1 -0
- package/dist/health/index.d.ts +27 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/index.js +43 -0
- package/dist/health/index.js.map +1 -0
- package/dist/i18n/index.d.ts +22 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +37 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +81 -0
- package/dist/index.js.map +1 -0
- package/dist/media/index.d.ts +3 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +2 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/optimize.d.ts +40 -0
- package/dist/media/optimize.d.ts.map +1 -0
- package/dist/media/optimize.js +137 -0
- package/dist/media/optimize.js.map +1 -0
- package/dist/middleware.d.ts +7 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +86 -0
- package/dist/middleware.js.map +1 -0
- package/dist/multisite/index.d.ts +20 -0
- package/dist/multisite/index.d.ts.map +1 -0
- package/dist/multisite/index.js +26 -0
- package/dist/multisite/index.js.map +1 -0
- package/dist/next/preview.d.ts +10 -0
- package/dist/next/preview.d.ts.map +1 -0
- package/dist/next/preview.js +17 -0
- package/dist/next/preview.js.map +1 -0
- package/dist/next.d.ts +9 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +35 -0
- package/dist/next.js.map +1 -0
- package/dist/notifications/index.d.ts +20 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +22 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/presence/index.d.ts +24 -0
- package/dist/presence/index.d.ts.map +1 -0
- package/dist/presence/index.js +99 -0
- package/dist/presence/index.js.map +1 -0
- package/dist/preview/index.d.ts +14 -0
- package/dist/preview/index.d.ts.map +1 -0
- package/dist/preview/index.js +45 -0
- package/dist/preview/index.js.map +1 -0
- package/dist/privacy/index.d.ts +33 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +15 -0
- package/dist/privacy/index.js.map +1 -0
- package/dist/relationships/index.d.ts +13 -0
- package/dist/relationships/index.d.ts.map +1 -0
- package/dist/relationships/index.js +12 -0
- package/dist/relationships/index.js.map +1 -0
- package/dist/scheduling/index.d.ts +44 -0
- package/dist/scheduling/index.d.ts.map +1 -0
- package/dist/scheduling/index.js +119 -0
- package/dist/scheduling/index.js.map +1 -0
- package/dist/search/index.d.ts +25 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +168 -0
- package/dist/search/index.js.map +1 -0
- package/dist/security/access.d.ts +26 -0
- package/dist/security/access.d.ts.map +1 -0
- package/dist/security/access.js +92 -0
- package/dist/security/access.js.map +1 -0
- package/dist/security/anomaly-detection.d.ts +17 -0
- package/dist/security/anomaly-detection.d.ts.map +1 -0
- package/dist/security/anomaly-detection.js +17 -0
- package/dist/security/anomaly-detection.js.map +1 -0
- package/dist/security/api-key-enhanced.d.ts +25 -0
- package/dist/security/api-key-enhanced.d.ts.map +1 -0
- package/dist/security/api-key-enhanced.js +25 -0
- package/dist/security/api-key-enhanced.js.map +1 -0
- package/dist/security/audit.d.ts +39 -0
- package/dist/security/audit.d.ts.map +1 -0
- package/dist/security/audit.js +40 -0
- package/dist/security/audit.js.map +1 -0
- package/dist/security/breach-check.d.ts +3 -0
- package/dist/security/breach-check.d.ts.map +1 -0
- package/dist/security/breach-check.js +27 -0
- package/dist/security/breach-check.js.map +1 -0
- package/dist/security/cors.d.ts +11 -0
- package/dist/security/cors.d.ts.map +1 -0
- package/dist/security/cors.js +33 -0
- package/dist/security/cors.js.map +1 -0
- package/dist/security/csp-nonces.d.ts +5 -0
- package/dist/security/csp-nonces.d.ts.map +1 -0
- package/dist/security/csp-nonces.js +24 -0
- package/dist/security/csp-nonces.js.map +1 -0
- package/dist/security/csrf.d.ts +5 -0
- package/dist/security/csrf.d.ts.map +1 -0
- package/dist/security/csrf.js +20 -0
- package/dist/security/csrf.js.map +1 -0
- package/dist/security/encrypted-fields.d.ts +5 -0
- package/dist/security/encrypted-fields.d.ts.map +1 -0
- package/dist/security/encrypted-fields.js +40 -0
- package/dist/security/encrypted-fields.js.map +1 -0
- package/dist/security/headers.d.ts +11 -0
- package/dist/security/headers.d.ts.map +1 -0
- package/dist/security/headers.js +32 -0
- package/dist/security/headers.js.map +1 -0
- package/dist/security/index.d.ts +31 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +20 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/ip-allowlist.d.ts +3 -0
- package/dist/security/ip-allowlist.d.ts.map +1 -0
- package/dist/security/ip-allowlist.js +35 -0
- package/dist/security/ip-allowlist.js.map +1 -0
- package/dist/security/middleware.d.ts +20 -0
- package/dist/security/middleware.d.ts.map +1 -0
- package/dist/security/middleware.js +45 -0
- package/dist/security/middleware.js.map +1 -0
- package/dist/security/rate-limit.d.ts +24 -0
- package/dist/security/rate-limit.d.ts.map +1 -0
- package/dist/security/rate-limit.js +84 -0
- package/dist/security/rate-limit.js.map +1 -0
- package/dist/security/reauth.d.ts +15 -0
- package/dist/security/reauth.d.ts.map +1 -0
- package/dist/security/reauth.js +38 -0
- package/dist/security/reauth.js.map +1 -0
- package/dist/security/sanitize.d.ts +13 -0
- package/dist/security/sanitize.d.ts.map +1 -0
- package/dist/security/sanitize.js +34 -0
- package/dist/security/sanitize.js.map +1 -0
- package/dist/security/security-txt.d.ts +12 -0
- package/dist/security/security-txt.d.ts.map +1 -0
- package/dist/security/security-txt.js +19 -0
- package/dist/security/security-txt.js.map +1 -0
- package/dist/security/session-limits.d.ts +17 -0
- package/dist/security/session-limits.d.ts.map +1 -0
- package/dist/security/session-limits.js +14 -0
- package/dist/security/session-limits.js.map +1 -0
- package/dist/security/upload.d.ts +13 -0
- package/dist/security/upload.d.ts.map +1 -0
- package/dist/security/upload.js +34 -0
- package/dist/security/upload.js.map +1 -0
- package/dist/security/webhook.d.ts +12 -0
- package/dist/security/webhook.d.ts.map +1 -0
- package/dist/security/webhook.js +38 -0
- package/dist/security/webhook.js.map +1 -0
- package/dist/seo/analysis.d.ts +66 -0
- package/dist/seo/analysis.d.ts.map +1 -0
- package/dist/seo/analysis.js +594 -0
- package/dist/seo/analysis.js.map +1 -0
- package/dist/seo/index.d.ts +9 -0
- package/dist/seo/index.d.ts.map +1 -0
- package/dist/seo/index.js +5 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/seo/llms-txt.d.ts +16 -0
- package/dist/seo/llms-txt.d.ts.map +1 -0
- package/dist/seo/llms-txt.js +70 -0
- package/dist/seo/llms-txt.js.map +1 -0
- package/dist/seo/meta-tags.d.ts +33 -0
- package/dist/seo/meta-tags.d.ts.map +1 -0
- package/dist/seo/meta-tags.js +159 -0
- package/dist/seo/meta-tags.js.map +1 -0
- package/dist/seo/title-templates.d.ts +17 -0
- package/dist/seo/title-templates.d.ts.map +1 -0
- package/dist/seo/title-templates.js +28 -0
- package/dist/seo/title-templates.js.map +1 -0
- package/dist/setup/index.d.ts +38 -0
- package/dist/setup/index.d.ts.map +1 -0
- package/dist/setup/index.js +77 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/storage/index.d.ts +11 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +11 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/templates/index.d.ts +16 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +23 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/upgrade/changelog.d.ts +13 -0
- package/dist/upgrade/changelog.d.ts.map +1 -0
- package/dist/upgrade/changelog.js +54 -0
- package/dist/upgrade/changelog.js.map +1 -0
- package/dist/upgrade/index.d.ts +7 -0
- package/dist/upgrade/index.d.ts.map +1 -0
- package/dist/upgrade/index.js +4 -0
- package/dist/upgrade/index.js.map +1 -0
- package/dist/upgrade/upgrade-pr.d.ts +16 -0
- package/dist/upgrade/upgrade-pr.d.ts.map +1 -0
- package/dist/upgrade/upgrade-pr.js +38 -0
- package/dist/upgrade/upgrade-pr.js.map +1 -0
- package/dist/upgrade/version-check.d.ts +17 -0
- package/dist/upgrade/version-check.d.ts.map +1 -0
- package/dist/upgrade/version-check.js +30 -0
- package/dist/upgrade/version-check.js.map +1 -0
- package/dist/webhooks/index.d.ts +46 -0
- package/dist/webhooks/index.d.ts.map +1 -0
- package/dist/webhooks/index.js +245 -0
- package/dist/webhooks/index.js.map +1 -0
- package/dist/workflow/index.d.ts +8 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +56 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflows/index.d.ts +30 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +14 -0
- package/dist/workflows/index.js.map +1 -0
- package/generated/browser.ts +109 -0
- package/generated/client.ts +133 -0
- package/generated/commonInputTypes.ts +709 -0
- package/generated/enums.ts +125 -0
- package/generated/internal/class.ts +376 -0
- package/generated/internal/prismaNamespace.ts +2617 -0
- package/generated/internal/prismaNamespaceBrowser.ts +611 -0
- package/generated/models/ApiKey.ts +1550 -0
- package/generated/models/AuditLog.ts +1206 -0
- package/generated/models/BackupRecord.ts +1250 -0
- package/generated/models/ContentLock.ts +1472 -0
- package/generated/models/ContentTemplate.ts +1416 -0
- package/generated/models/Document.ts +3005 -0
- package/generated/models/Folder.ts +1904 -0
- package/generated/models/FormSubmission.ts +1200 -0
- package/generated/models/InAppNotification.ts +1457 -0
- package/generated/models/Media.ts +2340 -0
- package/generated/models/MediaUsage.ts +1472 -0
- package/generated/models/OAuthAccount.ts +1463 -0
- package/generated/models/Redirect.ts +1284 -0
- package/generated/models/Session.ts +1492 -0
- package/generated/models/Site.ts +1206 -0
- package/generated/models/User.ts +3513 -0
- package/generated/models/Version.ts +1511 -0
- package/generated/models/WorkflowState.ts +1514 -0
- package/generated/models.ts +29 -0
- package/package.json +83 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as jose from 'jose';
|
|
2
|
+
export function createPreviewAdapter(secret, db) {
|
|
3
|
+
const secretKey = new TextEncoder().encode(secret);
|
|
4
|
+
return {
|
|
5
|
+
async createPreviewSession(collection, documentId) {
|
|
6
|
+
const expiresAt = new Date(Date.now() + 5 * 60 * 1000);
|
|
7
|
+
const token = await new jose.SignJWT({ collection, documentId })
|
|
8
|
+
.setProtectedHeader({ alg: 'HS256' })
|
|
9
|
+
.setIssuedAt()
|
|
10
|
+
.setExpirationTime(expiresAt)
|
|
11
|
+
.setIssuer('actuate-cms-preview')
|
|
12
|
+
.sign(secretKey);
|
|
13
|
+
return { token, collection, documentId, expiresAt };
|
|
14
|
+
},
|
|
15
|
+
async validatePreviewToken(token) {
|
|
16
|
+
try {
|
|
17
|
+
const { payload } = await jose.jwtVerify(token, secretKey, {
|
|
18
|
+
issuer: 'actuate-cms-preview',
|
|
19
|
+
});
|
|
20
|
+
return {
|
|
21
|
+
token,
|
|
22
|
+
collection: payload.collection,
|
|
23
|
+
documentId: payload.documentId,
|
|
24
|
+
expiresAt: new Date((payload.exp ?? 0) * 1000),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
async exitPreview(_token) {
|
|
32
|
+
// JWT-based tokens are stateless; no server-side invalidation needed
|
|
33
|
+
},
|
|
34
|
+
async getPreviewData(session) {
|
|
35
|
+
const prisma = db;
|
|
36
|
+
const doc = await prisma.document.findFirst({
|
|
37
|
+
where: { id: session.documentId, collection: session.collection },
|
|
38
|
+
});
|
|
39
|
+
if (!doc)
|
|
40
|
+
return null;
|
|
41
|
+
return { ...doc, data: doc.data };
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/preview/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAgB7B,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,EAAW;IAC9D,MAAM,SAAS,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEnD,OAAO;QACL,KAAK,CAAC,oBAAoB,CAAC,UAAU,EAAE,UAAU;YAC/C,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YACvD,MAAM,KAAK,GAAG,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;iBAC7D,kBAAkB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;iBACpC,WAAW,EAAE;iBACb,iBAAiB,CAAC,SAAS,CAAC;iBAC5B,SAAS,CAAC,qBAAqB,CAAC;iBAChC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnB,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;QACtD,CAAC;QAED,KAAK,CAAC,oBAAoB,CAAC,KAAK;YAC9B,IAAI,CAAC;gBACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE;oBACzD,MAAM,EAAE,qBAAqB;iBAC9B,CAAC,CAAC;gBACH,OAAO;oBACL,KAAK;oBACL,UAAU,EAAE,OAAO,CAAC,UAAoB;oBACxC,UAAU,EAAE,OAAO,CAAC,UAAoB;oBACxC,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;iBAC/C,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,MAAM;YACtB,qEAAqE;QACvE,CAAC;QAED,KAAK,CAAC,cAAc,CAAC,OAAO;YAC1B,MAAM,MAAM,GAAG,EAAS,CAAC;YACzB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;gBAC1C,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;aAClE,CAAC,CAAC;YACH,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAC;YACtB,OAAO,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface UserDataExport {
|
|
2
|
+
user: Record<string, unknown>;
|
|
3
|
+
documents: Record<string, unknown>[];
|
|
4
|
+
media: Record<string, unknown>[];
|
|
5
|
+
auditLogs: Record<string, unknown>[];
|
|
6
|
+
sessions: Record<string, unknown>[];
|
|
7
|
+
exportedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface RetentionPolicy {
|
|
10
|
+
collection: string;
|
|
11
|
+
maxAgeDays: number;
|
|
12
|
+
action: "delete" | "anonymize" | "archive";
|
|
13
|
+
}
|
|
14
|
+
export interface ErasureResult {
|
|
15
|
+
deletedDocuments: number;
|
|
16
|
+
anonymizedRecords: number;
|
|
17
|
+
deletedMedia: number;
|
|
18
|
+
deletedSessions: number;
|
|
19
|
+
}
|
|
20
|
+
/** Export all data associated with a user (GDPR Article 20 - Right to Data Portability). */
|
|
21
|
+
export declare function exportUserData(_userId: string, _db: unknown): Promise<UserDataExport>;
|
|
22
|
+
/** Erase all personal data for a user (GDPR Article 17 - Right to Erasure). */
|
|
23
|
+
export declare function eraseUserData(_userId: string, _db: unknown): Promise<ErasureResult>;
|
|
24
|
+
/** Apply retention policies to documents past their retention period. */
|
|
25
|
+
export declare function applyRetentionPolicies(_policies: RetentionPolicy[], _db: unknown): Promise<{
|
|
26
|
+
processed: number;
|
|
27
|
+
actions: Array<{
|
|
28
|
+
collection: string;
|
|
29
|
+
count: number;
|
|
30
|
+
action: string;
|
|
31
|
+
}>;
|
|
32
|
+
}>;
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/privacy/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,SAAS,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,4FAA4F;AAC5F,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,cAAc,CAAC,CAGzB;AAED,+EAA+E;AAC/E,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,aAAa,CAAC,CAGxB;AAED,yEAAyE;AACzE,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,eAAe,EAAE,EAC5B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAEvG"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Export all data associated with a user (GDPR Article 20 - Right to Data Portability). */
|
|
2
|
+
export async function exportUserData(_userId, _db) {
|
|
3
|
+
// TODO: gather all user-related data from all tables
|
|
4
|
+
throw new Error("Not implemented");
|
|
5
|
+
}
|
|
6
|
+
/** Erase all personal data for a user (GDPR Article 17 - Right to Erasure). */
|
|
7
|
+
export async function eraseUserData(_userId, _db) {
|
|
8
|
+
// TODO: delete or anonymize all user data, revoke sessions, remove PII
|
|
9
|
+
throw new Error("Not implemented");
|
|
10
|
+
}
|
|
11
|
+
/** Apply retention policies to documents past their retention period. */
|
|
12
|
+
export async function applyRetentionPolicies(_policies, _db) {
|
|
13
|
+
throw new Error("Not implemented");
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/privacy/index.ts"],"names":[],"mappings":"AAsBA,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAe,EACf,GAAY;IAEZ,qDAAqD;IACrD,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,GAAY;IAEZ,uEAAuE;IACvE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,SAA4B,EAC5B,GAAY;IAEZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ReverseRelationship {
|
|
2
|
+
sourceDocumentId: string;
|
|
3
|
+
sourceCollection: string;
|
|
4
|
+
fieldName: string;
|
|
5
|
+
}
|
|
6
|
+
/** Find all documents that reference a target document via relationship fields. */
|
|
7
|
+
export declare function getReverseRelationships(targetDocumentId: string, _db: unknown): Promise<ReverseRelationship[]>;
|
|
8
|
+
/** Check if deleting a document would orphan any references. */
|
|
9
|
+
export declare function checkOrphanedReferences(documentId: string, _db: unknown): Promise<{
|
|
10
|
+
hasReferences: boolean;
|
|
11
|
+
references: ReverseRelationship[];
|
|
12
|
+
}>;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/relationships/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,mFAAmF;AACnF,wBAAsB,uBAAuB,CAC3C,gBAAgB,EAAE,MAAM,EACxB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAIhC;AAED,gEAAgE;AAChE,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC,CAGxE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Find all documents that reference a target document via relationship fields. */
|
|
2
|
+
export async function getReverseRelationships(targetDocumentId, _db) {
|
|
3
|
+
// TODO: query content_graph edges where `to` matches targetDocumentId
|
|
4
|
+
void targetDocumentId;
|
|
5
|
+
throw new Error("Not implemented");
|
|
6
|
+
}
|
|
7
|
+
/** Check if deleting a document would orphan any references. */
|
|
8
|
+
export async function checkOrphanedReferences(documentId, _db) {
|
|
9
|
+
const references = await getReverseRelationships(documentId, _db);
|
|
10
|
+
return { hasReferences: references.length > 0, references };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/relationships/index.ts"],"names":[],"mappings":"AAMA,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,gBAAwB,EACxB,GAAY;IAEZ,sEAAsE;IACtE,KAAK,gBAAgB,CAAC;IACtB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;AACrC,CAAC;AAED,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAAkB,EAClB,GAAY;IAEZ,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAClE,OAAO,EAAE,aAAa,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface ScheduledAction {
|
|
2
|
+
documentId: string;
|
|
3
|
+
collection: string;
|
|
4
|
+
action: "publish" | "unpublish" | "archive";
|
|
5
|
+
scheduledAt: Date;
|
|
6
|
+
}
|
|
7
|
+
export interface ScheduleCalendarEntry {
|
|
8
|
+
id: string;
|
|
9
|
+
documentId: string;
|
|
10
|
+
collection: string;
|
|
11
|
+
title: string;
|
|
12
|
+
action: "publish" | "unpublish";
|
|
13
|
+
scheduledAt: Date;
|
|
14
|
+
}
|
|
15
|
+
type PrismaDB = any;
|
|
16
|
+
/** Get all scheduled actions within a date range for a calendar view. */
|
|
17
|
+
export declare function getScheduleCalendar(from: Date, to: Date, db: PrismaDB): Promise<ScheduleCalendarEntry[]>;
|
|
18
|
+
/** Process documents due for scheduled publishing. */
|
|
19
|
+
export declare function processScheduledPublish(db: PrismaDB): Promise<{
|
|
20
|
+
published: number;
|
|
21
|
+
errors: Array<{
|
|
22
|
+
documentId: string;
|
|
23
|
+
error: string;
|
|
24
|
+
}>;
|
|
25
|
+
}>;
|
|
26
|
+
/** Process documents due for scheduled unpublishing. */
|
|
27
|
+
export declare function processScheduledUnpublish(db: PrismaDB): Promise<{
|
|
28
|
+
unpublished: number;
|
|
29
|
+
errors: Array<{
|
|
30
|
+
documentId: string;
|
|
31
|
+
error: string;
|
|
32
|
+
}>;
|
|
33
|
+
}>;
|
|
34
|
+
/** Cron handler that runs both publish and unpublish processing. */
|
|
35
|
+
export declare function schedulingCronHandler(db: PrismaDB): Promise<{
|
|
36
|
+
published: number;
|
|
37
|
+
unpublished: number;
|
|
38
|
+
errors: Array<{
|
|
39
|
+
documentId: string;
|
|
40
|
+
error: string;
|
|
41
|
+
}>;
|
|
42
|
+
}>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduling/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC5C,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAChC,WAAW,EAAE,IAAI,CAAC;CACnB;AAED,KAAK,QAAQ,GAAG,GAAG,CAAC;AAEpB,yEAAyE;AACzE,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,IAAI,EACR,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA4ClC;AAED,sDAAsD;AACtD,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAiCtF;AAED,wDAAwD;AACxD,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,QAAQ,GACX,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAgCxF;AAED,oEAAoE;AACpE,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC,CASD"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/** Get all scheduled actions within a date range for a calendar view. */
|
|
2
|
+
export async function getScheduleCalendar(from, to, db) {
|
|
3
|
+
const docs = await db.document.findMany({
|
|
4
|
+
where: {
|
|
5
|
+
deletedAt: null,
|
|
6
|
+
OR: [
|
|
7
|
+
{ scheduledAt: { gte: from, lte: to } },
|
|
8
|
+
{ scheduledUnpublishAt: { gte: from, lte: to } },
|
|
9
|
+
],
|
|
10
|
+
},
|
|
11
|
+
select: {
|
|
12
|
+
id: true,
|
|
13
|
+
collection: true,
|
|
14
|
+
title: true,
|
|
15
|
+
scheduledAt: true,
|
|
16
|
+
scheduledUnpublishAt: true,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
const entries = [];
|
|
20
|
+
for (const doc of docs) {
|
|
21
|
+
if (doc.scheduledAt && doc.scheduledAt >= from && doc.scheduledAt <= to) {
|
|
22
|
+
entries.push({
|
|
23
|
+
id: `${doc.id}-publish`,
|
|
24
|
+
documentId: doc.id,
|
|
25
|
+
collection: doc.collection,
|
|
26
|
+
title: doc.title ?? 'Untitled',
|
|
27
|
+
action: 'publish',
|
|
28
|
+
scheduledAt: doc.scheduledAt,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (doc.scheduledUnpublishAt && doc.scheduledUnpublishAt >= from && doc.scheduledUnpublishAt <= to) {
|
|
32
|
+
entries.push({
|
|
33
|
+
id: `${doc.id}-unpublish`,
|
|
34
|
+
documentId: doc.id,
|
|
35
|
+
collection: doc.collection,
|
|
36
|
+
title: doc.title ?? 'Untitled',
|
|
37
|
+
action: 'unpublish',
|
|
38
|
+
scheduledAt: doc.scheduledUnpublishAt,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return entries.sort((a, b) => a.scheduledAt.getTime() - b.scheduledAt.getTime());
|
|
43
|
+
}
|
|
44
|
+
/** Process documents due for scheduled publishing. */
|
|
45
|
+
export async function processScheduledPublish(db) {
|
|
46
|
+
const now = new Date();
|
|
47
|
+
const docs = await db.document.findMany({
|
|
48
|
+
where: {
|
|
49
|
+
status: 'SCHEDULED',
|
|
50
|
+
scheduledAt: { lte: now },
|
|
51
|
+
deletedAt: null,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
let published = 0;
|
|
55
|
+
const errors = [];
|
|
56
|
+
for (const doc of docs) {
|
|
57
|
+
try {
|
|
58
|
+
await db.document.update({
|
|
59
|
+
where: { id: doc.id },
|
|
60
|
+
data: {
|
|
61
|
+
status: 'PUBLISHED',
|
|
62
|
+
publishedAt: now,
|
|
63
|
+
scheduledAt: null,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
published++;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
errors.push({
|
|
70
|
+
documentId: doc.id,
|
|
71
|
+
error: err instanceof Error ? err.message : 'Unknown error',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { published, errors };
|
|
76
|
+
}
|
|
77
|
+
/** Process documents due for scheduled unpublishing. */
|
|
78
|
+
export async function processScheduledUnpublish(db) {
|
|
79
|
+
const now = new Date();
|
|
80
|
+
const docs = await db.document.findMany({
|
|
81
|
+
where: {
|
|
82
|
+
status: 'PUBLISHED',
|
|
83
|
+
scheduledUnpublishAt: { lte: now },
|
|
84
|
+
deletedAt: null,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
let unpublished = 0;
|
|
88
|
+
const errors = [];
|
|
89
|
+
for (const doc of docs) {
|
|
90
|
+
try {
|
|
91
|
+
await db.document.update({
|
|
92
|
+
where: { id: doc.id },
|
|
93
|
+
data: {
|
|
94
|
+
status: 'DRAFT',
|
|
95
|
+
scheduledUnpublishAt: null,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
unpublished++;
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
errors.push({
|
|
102
|
+
documentId: doc.id,
|
|
103
|
+
error: err instanceof Error ? err.message : 'Unknown error',
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { unpublished, errors };
|
|
108
|
+
}
|
|
109
|
+
/** Cron handler that runs both publish and unpublish processing. */
|
|
110
|
+
export async function schedulingCronHandler(db) {
|
|
111
|
+
const publishResult = await processScheduledPublish(db);
|
|
112
|
+
const unpublishResult = await processScheduledUnpublish(db);
|
|
113
|
+
return {
|
|
114
|
+
published: publishResult.published,
|
|
115
|
+
unpublished: unpublishResult.unpublished,
|
|
116
|
+
errors: [...publishResult.errors, ...unpublishResult.errors],
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduling/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface SearchOptions {
|
|
2
|
+
collection?: string;
|
|
3
|
+
locale?: string;
|
|
4
|
+
status?: string;
|
|
5
|
+
page?: number;
|
|
6
|
+
pageSize?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SearchResult {
|
|
9
|
+
id: string;
|
|
10
|
+
title: string;
|
|
11
|
+
slug: string;
|
|
12
|
+
collection: string;
|
|
13
|
+
excerpt: string;
|
|
14
|
+
score: number;
|
|
15
|
+
highlights: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface SearchResponse {
|
|
18
|
+
results: SearchResult[];
|
|
19
|
+
total: number;
|
|
20
|
+
page: number;
|
|
21
|
+
pageSize: number;
|
|
22
|
+
}
|
|
23
|
+
/** Search documents using Postgres full-text search with relevance ranking. */
|
|
24
|
+
export declare function searchDocuments(query: string, options?: SearchOptions): Promise<SearchResponse>;
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAgBD,+EAA+E;AAC/E,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CAiHzB"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { getDB } from '../db';
|
|
2
|
+
/**
|
|
3
|
+
* Convert a user query into a Postgres tsquery-compatible string.
|
|
4
|
+
* Splits on whitespace, strips non-word chars, joins with & for AND matching.
|
|
5
|
+
*/
|
|
6
|
+
function toTsQuery(query) {
|
|
7
|
+
const terms = query
|
|
8
|
+
.replace(/[^\w\s]/g, ' ')
|
|
9
|
+
.trim()
|
|
10
|
+
.split(/\s+/)
|
|
11
|
+
.filter(Boolean)
|
|
12
|
+
.map((t) => `${t}:*`);
|
|
13
|
+
return terms.join(' & ');
|
|
14
|
+
}
|
|
15
|
+
/** Search documents using Postgres full-text search with relevance ranking. */
|
|
16
|
+
export async function searchDocuments(query, options = {}) {
|
|
17
|
+
const db = getDB();
|
|
18
|
+
const { collection, locale, status, page = 1, pageSize = 20 } = options;
|
|
19
|
+
const offset = (page - 1) * pageSize;
|
|
20
|
+
const sanitized = query.replace(/[^\w\s]/g, ' ').trim();
|
|
21
|
+
if (!sanitized) {
|
|
22
|
+
return { results: [], total: 0, page, pageSize };
|
|
23
|
+
}
|
|
24
|
+
const tsQueryStr = toTsQuery(sanitized);
|
|
25
|
+
if (!tsQueryStr) {
|
|
26
|
+
return { results: [], total: 0, page, pageSize };
|
|
27
|
+
}
|
|
28
|
+
const conditions = [`d."deletedAt" IS NULL`];
|
|
29
|
+
const params = [];
|
|
30
|
+
let paramIdx = 1;
|
|
31
|
+
// tsquery as a parameter instead of inline interpolation
|
|
32
|
+
params.push(tsQueryStr);
|
|
33
|
+
const tsQueryParam = `$${paramIdx++}`;
|
|
34
|
+
if (collection) {
|
|
35
|
+
conditions.push(`d."collection" = $${paramIdx++}`);
|
|
36
|
+
params.push(collection);
|
|
37
|
+
}
|
|
38
|
+
if (locale) {
|
|
39
|
+
conditions.push(`d."locale" = $${paramIdx++}`);
|
|
40
|
+
params.push(locale);
|
|
41
|
+
}
|
|
42
|
+
if (status) {
|
|
43
|
+
conditions.push(`d."status"::text = $${paramIdx++}`);
|
|
44
|
+
params.push(status);
|
|
45
|
+
}
|
|
46
|
+
const whereClause = conditions.join(' AND ');
|
|
47
|
+
const ftsVector = `to_tsvector('english', COALESCE(d."title", '') || ' ' || COALESCE(d."plainText", ''))`;
|
|
48
|
+
const ftsCondition = `(${ftsVector} @@ to_tsquery('english', ${tsQueryParam}))`;
|
|
49
|
+
const ilikePlaceholder = `$${paramIdx}`;
|
|
50
|
+
params.push(`%${sanitized}%`);
|
|
51
|
+
paramIdx++;
|
|
52
|
+
const fallbackCondition = `(d."title" ILIKE ${ilikePlaceholder} OR d."plainText" ILIKE ${ilikePlaceholder})`;
|
|
53
|
+
const rankExpr = `ts_rank_cd(${ftsVector}, to_tsquery('english', ${tsQueryParam}))`;
|
|
54
|
+
const headline = `ts_headline('english', COALESCE(d."plainText", ''), to_tsquery('english', ${tsQueryParam}), 'StartSel=<mark>, StopSel=</mark>, MaxWords=35, MinWords=15, MaxFragments=2')`;
|
|
55
|
+
const limitParam = `$${paramIdx++}`;
|
|
56
|
+
params.push(pageSize);
|
|
57
|
+
const offsetParam = `$${paramIdx++}`;
|
|
58
|
+
params.push(offset);
|
|
59
|
+
const sql = `
|
|
60
|
+
SELECT
|
|
61
|
+
d."id",
|
|
62
|
+
d."title",
|
|
63
|
+
d."slug",
|
|
64
|
+
d."collection",
|
|
65
|
+
d."status",
|
|
66
|
+
d."updatedAt",
|
|
67
|
+
${rankExpr} AS score,
|
|
68
|
+
${headline} AS headline,
|
|
69
|
+
LEFT(COALESCE(d."plainText", ''), 200) AS excerpt
|
|
70
|
+
FROM "actuate_documents" d
|
|
71
|
+
WHERE ${whereClause}
|
|
72
|
+
AND (${ftsCondition} OR ${fallbackCondition})
|
|
73
|
+
ORDER BY score DESC, d."updatedAt" DESC
|
|
74
|
+
LIMIT ${limitParam}
|
|
75
|
+
OFFSET ${offsetParam}
|
|
76
|
+
`;
|
|
77
|
+
const countSql = `
|
|
78
|
+
SELECT COUNT(*)::int AS total
|
|
79
|
+
FROM "actuate_documents" d
|
|
80
|
+
WHERE ${whereClause}
|
|
81
|
+
AND (${ftsCondition} OR ${fallbackCondition})
|
|
82
|
+
`;
|
|
83
|
+
const countParams = params.slice(0, -2);
|
|
84
|
+
try {
|
|
85
|
+
const [rows, countRows] = await Promise.all([
|
|
86
|
+
db.$queryRawUnsafe(sql, ...params),
|
|
87
|
+
db.$queryRawUnsafe(countSql, ...countParams),
|
|
88
|
+
]);
|
|
89
|
+
const total = countRows[0]?.total ?? 0;
|
|
90
|
+
const results = rows.map((row) => {
|
|
91
|
+
const headlineText = row.headline ?? '';
|
|
92
|
+
const highlights = headlineText
|
|
93
|
+
.match(/<mark>(.*?)<\/mark>/g)
|
|
94
|
+
?.map((m) => m.replace(/<\/?mark>/g, '')) ?? [];
|
|
95
|
+
return {
|
|
96
|
+
id: row.id,
|
|
97
|
+
title: row.title ?? '',
|
|
98
|
+
slug: row.slug ?? '',
|
|
99
|
+
collection: row.collection,
|
|
100
|
+
excerpt: headlineText || row.excerpt || '',
|
|
101
|
+
score: parseFloat(row.score) || 0,
|
|
102
|
+
highlights,
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
return { results, total, page, pageSize };
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return fallbackSearch(sanitized, options);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Fallback search using Prisma contains (for non-Postgres or when FTS fails). */
|
|
112
|
+
async function fallbackSearch(query, options) {
|
|
113
|
+
const db = getDB();
|
|
114
|
+
const { collection, locale, status, page = 1, pageSize = 20 } = options;
|
|
115
|
+
const offset = (page - 1) * pageSize;
|
|
116
|
+
const where = {
|
|
117
|
+
deletedAt: null,
|
|
118
|
+
OR: [
|
|
119
|
+
{ plainText: { contains: query, mode: 'insensitive' } },
|
|
120
|
+
{ title: { contains: query, mode: 'insensitive' } },
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
if (collection)
|
|
124
|
+
where.collection = collection;
|
|
125
|
+
if (locale)
|
|
126
|
+
where.locale = locale;
|
|
127
|
+
if (status)
|
|
128
|
+
where.status = status;
|
|
129
|
+
const [results, total] = await Promise.all([
|
|
130
|
+
db.document.findMany({
|
|
131
|
+
where,
|
|
132
|
+
orderBy: { updatedAt: 'desc' },
|
|
133
|
+
skip: offset,
|
|
134
|
+
take: pageSize,
|
|
135
|
+
select: {
|
|
136
|
+
id: true,
|
|
137
|
+
title: true,
|
|
138
|
+
slug: true,
|
|
139
|
+
collection: true,
|
|
140
|
+
plainText: true,
|
|
141
|
+
},
|
|
142
|
+
}),
|
|
143
|
+
db.document.count({ where }),
|
|
144
|
+
]);
|
|
145
|
+
return {
|
|
146
|
+
results: results.map((doc) => {
|
|
147
|
+
const text = doc.plainText ?? '';
|
|
148
|
+
const idx = text.toLowerCase().indexOf(query.toLowerCase());
|
|
149
|
+
const start = Math.max(0, idx - 40);
|
|
150
|
+
const excerpt = idx >= 0
|
|
151
|
+
? '...' + text.substring(start, start + 200) + '...'
|
|
152
|
+
: text.substring(0, 200);
|
|
153
|
+
return {
|
|
154
|
+
id: doc.id,
|
|
155
|
+
title: doc.title ?? '',
|
|
156
|
+
slug: doc.slug ?? '',
|
|
157
|
+
collection: doc.collection,
|
|
158
|
+
excerpt,
|
|
159
|
+
score: doc.title?.toLowerCase().includes(query.toLowerCase()) ? 2 : 1,
|
|
160
|
+
highlights: [query],
|
|
161
|
+
};
|
|
162
|
+
}),
|
|
163
|
+
total,
|
|
164
|
+
page,
|
|
165
|
+
pageSize,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FieldDefinition } from "../config/types";
|
|
2
|
+
export type Role = "ADMIN" | "EDITOR" | "AUTHOR" | "CLIENT";
|
|
3
|
+
export type FieldAccessUser = {
|
|
4
|
+
id: string;
|
|
5
|
+
role: string;
|
|
6
|
+
} | null;
|
|
7
|
+
export interface Permission {
|
|
8
|
+
action: "create" | "read" | "update" | "delete" | "publish";
|
|
9
|
+
resource: string;
|
|
10
|
+
fields?: string[];
|
|
11
|
+
}
|
|
12
|
+
/** Check whether a user with the given role can perform an action on a resource. */
|
|
13
|
+
export declare function checkAccess(userRole: Role, requiredRole: Role): boolean;
|
|
14
|
+
/** Return the list of permissions granted to a role. */
|
|
15
|
+
export declare function getPermissionsForRole(role: Role): Permission[];
|
|
16
|
+
/** Filter field definitions to only include those the user is allowed to read. */
|
|
17
|
+
export declare function filterFieldsByRole(fields: Record<string, FieldDefinition>, user: FieldAccessUser): Promise<Record<string, FieldDefinition>>;
|
|
18
|
+
/** Filter incoming data to only include keys the user is allowed to update. */
|
|
19
|
+
export declare function filterWritableFields(fields: Record<string, FieldDefinition>, data: Record<string, unknown>, user: FieldAccessUser): Promise<Record<string, unknown>>;
|
|
20
|
+
/**
|
|
21
|
+
* Apply field-level access control to a data object.
|
|
22
|
+
* For 'read': strips keys the user cannot read.
|
|
23
|
+
* For 'write': strips keys the user cannot update.
|
|
24
|
+
*/
|
|
25
|
+
export declare function applyFieldAccess(operation: "read" | "write", fields: Record<string, FieldDefinition>, data: Record<string, unknown>, user: FieldAccessUser): Promise<Record<string, unknown>>;
|
|
26
|
+
//# sourceMappingURL=access.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access.d.ts","sourceRoot":"","sources":["../../src/security/access.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AASD,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,QAAQ,EAAE,IAAI,EACd,YAAY,EAAE,IAAI,GACjB,OAAO,CAET;AAED,wDAAwD;AACxD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,EAAE,CAkB9D;AAED,kFAAkF;AAClF,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAe1C;AAED,+EAA+E;AAC/E,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAgBlC;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA6BlC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const ROLE_HIERARCHY = {
|
|
2
|
+
ADMIN: 100,
|
|
3
|
+
EDITOR: 75,
|
|
4
|
+
AUTHOR: 50,
|
|
5
|
+
CLIENT: 25,
|
|
6
|
+
};
|
|
7
|
+
/** Check whether a user with the given role can perform an action on a resource. */
|
|
8
|
+
export function checkAccess(userRole, requiredRole) {
|
|
9
|
+
return ROLE_HIERARCHY[userRole] >= ROLE_HIERARCHY[requiredRole];
|
|
10
|
+
}
|
|
11
|
+
/** Return the list of permissions granted to a role. */
|
|
12
|
+
export function getPermissionsForRole(role) {
|
|
13
|
+
const permissions = [
|
|
14
|
+
{ action: "read", resource: "*" },
|
|
15
|
+
];
|
|
16
|
+
if (checkAccess(role, "AUTHOR")) {
|
|
17
|
+
permissions.push({ action: "create", resource: "*" });
|
|
18
|
+
permissions.push({ action: "update", resource: "own" });
|
|
19
|
+
}
|
|
20
|
+
if (checkAccess(role, "EDITOR")) {
|
|
21
|
+
permissions.push({ action: "update", resource: "*" });
|
|
22
|
+
permissions.push({ action: "publish", resource: "*" });
|
|
23
|
+
}
|
|
24
|
+
if (checkAccess(role, "ADMIN")) {
|
|
25
|
+
permissions.push({ action: "delete", resource: "*" });
|
|
26
|
+
}
|
|
27
|
+
return permissions;
|
|
28
|
+
}
|
|
29
|
+
/** Filter field definitions to only include those the user is allowed to read. */
|
|
30
|
+
export async function filterFieldsByRole(fields, user) {
|
|
31
|
+
const result = {};
|
|
32
|
+
for (const [name, field] of Object.entries(fields)) {
|
|
33
|
+
if (!field.access?.read) {
|
|
34
|
+
result[name] = field;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const allowed = await field.access.read({ user });
|
|
38
|
+
if (allowed) {
|
|
39
|
+
result[name] = field;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
/** Filter incoming data to only include keys the user is allowed to update. */
|
|
45
|
+
export async function filterWritableFields(fields, data, user) {
|
|
46
|
+
const result = {};
|
|
47
|
+
for (const [key, value] of Object.entries(data)) {
|
|
48
|
+
const field = fields[key];
|
|
49
|
+
if (!field || !field.access?.update) {
|
|
50
|
+
result[key] = value;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const allowed = await field.access.update({ user });
|
|
54
|
+
if (allowed) {
|
|
55
|
+
result[key] = value;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Apply field-level access control to a data object.
|
|
62
|
+
* For 'read': strips keys the user cannot read.
|
|
63
|
+
* For 'write': strips keys the user cannot update.
|
|
64
|
+
*/
|
|
65
|
+
export async function applyFieldAccess(operation, fields, data, user) {
|
|
66
|
+
const accessKey = operation === "read" ? "read" : "update";
|
|
67
|
+
const result = {};
|
|
68
|
+
const SYSTEM_KEYS = new Set([
|
|
69
|
+
'title', 'slug', 'status', '_aiScore', '_embedding',
|
|
70
|
+
]);
|
|
71
|
+
for (const [key, value] of Object.entries(data)) {
|
|
72
|
+
const field = fields[key];
|
|
73
|
+
if (!field) {
|
|
74
|
+
if (operation === 'write' && !SYSTEM_KEYS.has(key)) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
result[key] = value;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const check = field.access?.[accessKey];
|
|
81
|
+
if (!check) {
|
|
82
|
+
result[key] = value;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const allowed = await check({ user });
|
|
86
|
+
if (allowed) {
|
|
87
|
+
result[key] = value;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=access.js.map
|