import * as jose from 'jose';
/** 5 minutes — fits "one tab, one read" review flows. */
export const DEFAULT_PREVIEW_TOKEN_TTL_SECONDS = 7 * 24 * 60 * 60; // 7 days
/**
 * Upper bound for token lifetime. Tokens are JWT-signed and stateless, so a
 * leaked token is valid until expiry — keep the ceiling reasonable. Sites
 * that need shareable URLs for months should use draft-publishing instead.
 */
export const MAX_PREVIEW_TOKEN_TTL_SECONDS = 30 * 24 * 60 * 60; // 30 days
export function createPreviewAdapter(secret, db) {
    const secretKey = new TextEncoder().encode(secret);
    return {
        async createPreviewSession(collection, documentId, options) {
            const requested = options?.ttlSeconds ?? DEFAULT_PREVIEW_TOKEN_TTL_SECONDS;
            const ttl = Math.max(60, Math.min(requested, MAX_PREVIEW_TOKEN_TTL_SECONDS));
            const expiresAt = new Date(Date.now() + ttl * 1000);
            let builder = new jose.SignJWT({ collection, documentId })
                .setProtectedHeader({ alg: 'HS256' })
                .setIssuedAt()
                .setExpirationTime(expiresAt)
                .setIssuer('actuate-cms-preview');
            if (options?.issuedBy) {
                builder = builder.setSubject(options.issuedBy);
            }
            const token = await builder.sign(secretKey);
            return {
                token,
                collection,
                documentId,
                expiresAt,
                issuedBy: options?.issuedBy,
            };
        },
        async validatePreviewToken(token) {
            try {
                const { payload } = await jose.jwtVerify(token, secretKey, {
                    issuer: 'actuate-cms-preview',
                });
                return {
                    token,
                    collection: payload.collection,
                    documentId: payload.documentId,
                    expiresAt: new Date((payload.exp ?? 0) * 1000),
                    issuedBy: typeof payload.sub === 'string' ? payload.sub : undefined,
                };
            }
            catch {
                return null;
            }
        },
        async exitPreview(_token) {
            // JWT-based tokens are stateless; no server-side invalidation needed.
            // For revocation, rotate the global CMS_SECRET (invalidates all tokens
            // at once). Per-token revocation requires a backing table — track via
            // future Slice if needed.
        },
        async getPreviewData(session) {
            const prisma = db;
            const doc = await prisma.document.findFirst({
                where: { id: session.documentId, collection: session.collection },
            });
            if (!doc)
                return null;
            return { ...doc, data: doc.data };
        },
    };
}
//# sourceMappingURL=index.js.map