/*! @azure/msal-node-extensions v1.5.17 2025-07-08 */
'use strict';
import { CrossPlatformLock } from '../lock/CrossPlatformLock.mjs';
import { pid } from 'process';

/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */
/**
 * MSAL cache plugin which enables callers to write the MSAL cache to disk on Windows,
 * macOs, and Linux.
 *
 * - Persistence can be one of:
 * - FilePersistence: Writes and reads from an unencrypted file. Can be used on Windows,
 * macOs, or Linux.
 * - FilePersistenceWithDataProtection: Used on Windows, writes and reads from file encrypted
 * with windows dpapi-addon.
 * - KeychainPersistence: Used on macOs, writes and reads from keychain.
 * - LibSecretPersistence: Used on linux, writes and reads from secret service API. Requires
 * libsecret be installed.
 */
class PersistenceCachePlugin {
    constructor(persistence, lockOptions) {
        this.persistence = persistence;
        // initialize logger
        this.logger = persistence.getLogger();
        // create file lock
        this.lockFilePath = `${this.persistence.getFilePath()}.lockfile`;
        this.crossPlatformLock = new CrossPlatformLock(this.lockFilePath, this.logger, lockOptions);
        // initialize default values
        this.lastSync = 0;
        this.currentCache = null;
    }
    /**
     * Reads from storage and saves an in-memory copy. If persistence has not been updated
     * since last time data was read, in memory copy is used.
     *
     * If cacheContext.cacheHasChanged === true, then file lock is created and not deleted until
     * afterCacheAccess() is called, to prevent the cache file from changing in between
     * beforeCacheAccess() and afterCacheAccess().
     */
    async beforeCacheAccess(cacheContext) {
        this.logger.info("Executing before cache access");
        const reloadNecessary = await this.persistence.reloadNecessary(this.lastSync);
        if (!reloadNecessary && this.currentCache !== null) {
            if (cacheContext.cacheHasChanged) {
                this.logger.verbose("Cache context has changed");
                await this.crossPlatformLock.lock();
            }
            return;
        }
        try {
            this.logger.info(`Reload necessary. Last sync time: ${this.lastSync}`);
            await this.crossPlatformLock.lock();
            this.currentCache = await this.persistence.load();
            this.lastSync = new Date().getTime();
            if (this.currentCache) {
                cacheContext.tokenCache.deserialize(this.currentCache);
            }
            else {
                this.logger.info("Cache empty.");
            }
            this.logger.info(`Last sync time updated to: ${this.lastSync}`);
        }
        finally {
            if (!cacheContext.cacheHasChanged) {
                await this.crossPlatformLock.unlock();
                this.logger.info(`Pid ${pid} released lock`);
            }
            else {
                this.logger.info(`Pid ${pid} beforeCacheAccess did not release lock`);
            }
        }
    }
    /**
     * Writes to storage if MSAL in memory copy of cache has been changed.
     */
    async afterCacheAccess(cacheContext) {
        this.logger.info("Executing after cache access");
        try {
            if (cacheContext.cacheHasChanged) {
                this.logger.info("Msal in-memory cache has changed. Writing changes to persistence");
                this.currentCache = cacheContext.tokenCache.serialize();
                await this.persistence.save(this.currentCache);
            }
            else {
                this.logger.info("Msal in-memory cache has not changed. Did not write to persistence");
            }
        }
        finally {
            await this.crossPlatformLock.unlock();
            this.logger.info(`Pid ${pid} afterCacheAccess released lock`);
        }
    }
}

export { PersistenceCachePlugin };
//# sourceMappingURL=PersistenceCachePlugin.mjs.map
