/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import type { TypedEventEmitter } from "@fluid-internal/client-utils"; import type { IFluidLoadable } from "@fluidframework/core-interfaces"; import type { IChannelStorageService, IChannelAttributes } from "@fluidframework/datastore-definitions/internal"; import type { IIdCompressor } from "@fluidframework/id-compressor/internal"; import type { ISummaryTreeWithStats, ITelemetryContext, IExperimentalIncrementalSummaryContext, IRuntimeMessageCollection, OldestSupportedClientVersion } from "@fluidframework/runtime-definitions/internal"; import type { TelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal"; import type { IFluidSerializer } from "./serializer.js"; import { type ISharedObjectKind, type SharedObjectKindAlpha } from "./sharedObject.js"; import type { ISharedObjectEvents, ISharedObject } from "./types.js"; import type { IChannelView } from "./utils.js"; /** * Functionality specific to a particular kind of {@link ISharedObject}. * @remarks * Shared objects expose APIs for two consumers: * * 1. The runtime, which uses {@link @fluidframework/datastore-definitions#IChannel} to summarize and apply ops and {@link @fluidframework/datastore-definitions#IChannelFactory} to create the load summaries. * * 2. The app, which uses shared object kind specific APIs to read and write data. * * There is some common functionality all shared objects use, provided by {@link SharedObject} and {@link SharedObjectCore}. * SharedKernel describes the portion of the behavior required by the runtime which * differs between different kinds of shared objects. * * {@link makeSharedObjectKind} is then used to wrap up the kernel into a full {@link ISharedObject} implementation. * The runtime specific APIs are then type erased into a {@link SharedObjectKind}. * @privateRemarks * Unlike the `SharedObject` class, this interface is internal, and thus can be adjusted more easily. * Therefore this interface is not intended to address all needs, and will likely need small changes as it gets more adoption. * * @internal */ export interface SharedKernel { /** * {@inheritDoc SharedObject.summarizeCore} */ summarizeCore(serializer: IFluidSerializer, telemetryContext: ITelemetryContext | undefined, incrementalSummaryContext: IExperimentalIncrementalSummaryContext | undefined, fullTree?: boolean): ISummaryTreeWithStats; /** * {@inheritDoc SharedObjectCore.onDisconnect} */ onDisconnect(): void; /** * {@inheritDoc SharedObjectCore.reSubmitCore} */ reSubmitCore(content: unknown, localOpMetadata: unknown): void; /** * {@inheritDoc SharedObjectCore.applyStashedOp} */ applyStashedOp(content: unknown): void; /** * {@inheritDoc SharedObjectCore.processMessagesCore} */ processMessagesCore(messagesCollection: IRuntimeMessageCollection): void; /** * {@inheritDoc SharedObjectCore.rollback} */ rollback?(content: unknown, localOpMetadata: unknown): void; /** * {@inheritDoc SharedObjectCore.didAttach} */ didAttach?(): void; } /** * When present on a method, it indicates the methods return value should be replaced with `this` (the wrapper) * when wrapping the object with the method. * @remarks * This is useful when using {@link mergeAPIs} with methods where the return type is `this`, like `Map.set`. * @internal */ export declare const thisWrap: unique symbol; /** * A {@link SharedKernel} providing the implementation of some distributed data structure (DDS) and the needed runtime facing APIs, * and a separate view object which exposes the app facing APIs (`T`) * for reading and writing data which are specific to this particular data structure. * @remarks * Output from {@link SharedKernelFactory}. * This is an alternative to defining DDSs by sub-classing {@link SharedObject}. * @internal */ export interface FactoryOut { readonly kernel: SharedKernel; readonly view: T; } /** * A factory for creating DDSs. * @remarks * Outputs {@link FactoryOut}. * This is an alternative to directly implementing {@link @fluidframework/datastore-definitions#IChannelFactory}. * Use with {@link makeSharedObjectKind} to create a {@link SharedObjectKind}. * @internal */ export interface SharedKernelFactory { create(args: KernelArgs): FactoryOut; /** * Create combined with {@link SharedObjectCore.loadCore}. */ loadCore(args: KernelArgs, storage: IChannelStorageService): Promise>; } /** * Inputs for building a {@link SharedKernel} via {@link SharedKernelFactory}. * @internal */ export interface KernelArgs { /** * The shared object whose behavior is being implemented. */ readonly sharedObject: IChannelView & IFluidLoadable; /** * {@inheritdoc SharedObject.serializer} */ readonly serializer: IFluidSerializer; /** * {@inheritdoc SharedObjectCore.submitLocalMessage} */ readonly submitLocalMessage: (op: unknown, localOpMetadata: unknown) => void; /** * Top level emitter for events for this object. * @remarks * This is needed since the separate kernel and view from {@link FactoryOut} currently have to be recombined, * and having this as its own thing helps accomplish that. */ readonly eventEmitter: TypedEventEmitter; /** * {@inheritdoc SharedObjectCore.logger} */ readonly logger: TelemetryLoggerExt; /** * {@inheritdoc @fluidframework/datastore-definitions#IFluidDataStoreRuntime.idCompressor} */ readonly idCompressor: IIdCompressor | undefined; /** * {@inheritdoc @fluidframework/container-definitions#IDeltaManager.lastSequenceNumber} */ readonly lastSequenceNumber: () => number; /** * {@inheritdoc @fluidframework/container-definitions#IDeltaManager.initialSequenceNumber} */ readonly initialSequenceNumber: number; /** * Oldest Fluid Framework client version that must be able to process documents containing ops * generated by the SharedObject implementation. Used to select compatible feature flags and * formats, so choosing an older version may limit available features and write formats. * See {@link @fluidframework/container-runtime#LoadContainerRuntimeParams.oldestSupportedClient} * for more details. */ readonly minVersionForCollab: OldestSupportedClientVersion; } /** * Add getters to `base` which forward own properties from `extra`. * @remarks * This only handles use of "get" and "has". * Therefore, APIs involving setting properties should not be used as `Extra`. * * Functions from `extra` are bound to the `extra` object and support {@link thisWrap}. * * Asserts when properties collide. * @internal */ export declare function mergeAPIs(base: Base, extra: Extra): asserts base is Base & Extra; /** * Options for creating a {@link SharedObjectKind} via {@link makeSharedObjectKind}. * @typeParam T - The type of the object exposed to the app. * This can optionally include members from {@link ISharedObject} which will be provided automatically. * @internal */ export interface SharedObjectOptions { /** * {@inheritDoc @fluidframework/datastore-definitions#IChannelFactory."type"} */ readonly type: string; /** * {@inheritDoc @fluidframework/datastore-definitions#IChannelFactory.attributes} */ readonly attributes: IChannelAttributes; /** * The factory used to create the kernel and its view. * @remarks * The view produced by this factory will be grafted onto the {@link SharedObject} using {@link mergeAPIs}. * See {@link mergeAPIs} for more information on limitations that apply. */ readonly factory: SharedKernelFactory>; /** * {@inheritDoc SharedObject.telemetryContextPrefix} */ readonly telemetryContextPrefix: string; } /** * Utility to create a {@link SharedObjectKind}. * @privateRemarks * Using this API avoids having to subclasses any Fluid Framework types, * reducing the coupling between the framework and the SharedObject implementation. * @internal */ export declare function makeSharedObjectKind(options: SharedObjectOptions): ISharedObjectKind & SharedObjectKindAlpha; //# sourceMappingURL=sharedObjectKernel.d.ts.map