/**
 * NOTE: Added reference types here to avoid a `pnpm` bug during build.
 * https://github.com/enboxorg/enbox/pull/507
 */
/// <reference types="@enbox/dwn-sdk-js" />
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { AnonymousDwnApi } from '@enbox/agent';
import { EnboxRpcClient } from '@enbox/dwn-clients';
import { DidDht, DidJwk, DidKey, DidResolverCacheMemory, DidWeb, UniversalResolver } from '@enbox/dids';
import { DidApi } from './did-api.js';
import { DwnApi } from './dwn-api.js';
import { DwnReaderApi } from './dwn-reader-api.js';
import { TypedEnbox } from './typed-enbox.js';
import { VcApi } from './vc-api.js';
/**
 * The main Enbox API interface. It provides protocol-scoped access to
 * Decentralized Web Nodes (DWNs), Decentralized Identifiers (DIDs),
 * and Verifiable Credentials (VCs).
 *
 * Authentication and identity management are handled externally by
 * `@enbox/auth`. Use {@link Enbox.connect} to create an instance from
 * an {@link AuthSession} or raw parameters.
 *
 * @example
 * ```ts
 * import { AuthManager } from '@enbox/auth';
 * import { Enbox } from '@enbox/api';
 *
 * const auth = await AuthManager.create({ sync: '15s' });
 * const session = await auth.connect();
 *
 * const enbox = Enbox.connect({ session });
 * const social = enbox.using(SocialProtocol);
 * ```
 */
export class Enbox {
    constructor({ agent, connectedDid, delegateDid }) {
        /**
         * Cache of {@link TypedEnbox} instances keyed by protocol URI.
         *
         * Ensures that `enbox.using(Protocol)` returns the **same** `TypedEnbox`
         * instance for a given protocol across multiple call sites, avoiding
         * redundant protocol installations and duplicated internal state.
         */
        this._typedInstances = new Map();
        this.agent = agent;
        this.did = new DidApi({ agent, connectedDid });
        this._dwn = new DwnApi({ agent, connectedDid, delegateDid });
        this.vc = new VcApi({ agent, connectedDid });
    }
    /**
     * Returns a {@link TypedEnbox} instance scoped to the given protocol.
     *
     * This is the **primary developer interface** for interacting with
     * protocol-backed records. It auto-injects the protocol URI, protocolPath,
     * and schema into every operation, and provides compile-time path
     * autocompletion plus typed data payloads via the schema map.
     *
     * Instances are **cached by protocol URI** — calling `using()` multiple
     * times with the same protocol returns the same `TypedEnbox` instance,
     * so auto-configure only runs once and all call sites share state.
     *
     * @param protocol - A typed protocol created via `defineProtocol()`.
     * @returns A `TypedEnbox` instance bound to the given protocol.
     *
     * @example
     * ```ts
     * const social = enbox.using(SocialProtocol);
     *
     * await social.configure();
     *
     * const { record } = await social.records.write('friend', {
     *   data: { did: 'did:example:alice', alias: 'Alice' },
     * });
     *
     * const { records } = await social.records.query('friend');
     * ```
     */
    using(protocol) {
        const uri = protocol.definition.protocol;
        const cached = this._typedInstances.get(uri);
        if (cached) {
            // The map stores a type-erased instance; restore the caller's generics.
            return cached;
        }
        const instance = new TypedEnbox(this._dwn, protocol);
        // Store with erased generics so the map value type stays uniform.
        this._typedInstances.set(uri, instance);
        return instance;
    }
    /**
     * Stops DWN sync and clears the cached {@link TypedEnbox} instances.
     *
     * Call this when the application is shutting down or the user is
     * disconnecting to cleanly release background resources. After calling
     * `disconnect()`, the `Enbox` instance should not be reused.
     *
     * @param timeout - Maximum milliseconds to wait for an in-progress sync
     *   cycle to finish before force-stopping. Defaults to `2000`.
     *
     * @example
     * ```ts
     * await enbox.disconnect();
     * ```
     *
     * @beta
     */
    disconnect(timeout) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a;
            // Stop any active sync.
            if ('sync' in this.agent && typeof ((_a = this.agent.sync) === null || _a === void 0 ? void 0 : _a.stopSync) === 'function') {
                yield this.agent.sync.stopSync(timeout);
            }
            // Clear cached TypedEnbox instances so they are not accidentally reused.
            this._typedInstances.clear();
        });
    }
    /**
     * Creates a lightweight, read-only Enbox instance for querying public DWN data.
     *
     * No identity, vault, password, or signing keys are required. The returned
     * API supports querying and reading published records and protocols from any
     * remote DWN, using **unsigned** (anonymous) DWN messages.
     *
     * @param options - Optional configuration overrides.
     * @returns An {@link EnboxAnonymousApi} with a read-only `dwn` property.
     *
     * @example
     * ```ts
     * const { dwn } = Enbox.anonymous();
     *
     * const { records } = await dwn.records.query({
     *   from: 'did:dht:alice...',
     *   filter: { protocol: 'https://social.example/posts', protocolPath: 'post' },
     * });
     *
     * for (const record of records) {
     *   console.log(record.id, await record.data.text());
     * }
     * ```
     *
     * @beta
     */
    static anonymous(options) {
        var _a;
        const didResolver = new UniversalResolver({
            didResolvers: (_a = options === null || options === void 0 ? void 0 : options.didResolvers) !== null && _a !== void 0 ? _a : [DidDht, DidJwk, DidKey, DidWeb],
            cache: new DidResolverCacheMemory(),
        });
        const rpcClient = new EnboxRpcClient();
        const anonymousDwn = new AnonymousDwnApi({ didResolver, rpcClient });
        return {
            dwn: new DwnReaderApi(anonymousDwn),
        };
    }
    /**
     * Creates an {@link Enbox} instance from an {@link AuthSession} or raw parameters.
     *
     * This is a thin factory — all authentication, identity management, vault
     * initialization, DWN registration, and sync setup are handled externally
     * by `@enbox/auth` via {@link AuthSession}.
     *
     * @param params - Either `{ session }` with an {@link AuthSession} from
     *   `@enbox/auth`, or raw `{ agent, connectedDid, delegateDid? }` parameters.
     * @returns A new {@link Enbox} instance ready for use.
     *
     * @example
     * ```ts
     * // Using an AuthSession from @enbox/auth
     * import { AuthManager } from '@enbox/auth';
     * const auth = await AuthManager.create({ sync: '15s' });
     * const session = await auth.connect();
     * const enbox = Enbox.connect({ session });
     *
     * // Using raw parameters
     * const enbox = Enbox.connect({ agent, connectedDid: did });
     * ```
     */
    static connect(params) {
        if ('session' in params) {
            const { session } = params;
            return new Enbox({
                agent: session.agent,
                connectedDid: session.did,
                delegateDid: session.delegateDid,
            });
        }
        return new Enbox(params);
    }
}
//# sourceMappingURL=enbox.js.map