A library for building Fluid objects and Fluid containers within the Fluid Framework, providing base classes and factory patterns for collaborative data objects.
npx @tessl/cli install tessl/npm-fluidframework--aqueduct@2.60.0@fluidframework/aqueduct is the foundational library for building Fluid objects and Fluid containers within the Fluid Framework. It provides base classes, factory patterns, and container runtime utilities that enable developers to quickly create collaborative, real-time applications. The library serves as a thin abstraction layer over core Fluid Framework interfaces, offering three tiers of data objects and corresponding factories for different architectural needs.
npm install @fluidframework/aqueductimport {
DataObject,
PureDataObject,
TreeDataObject,
DataObjectFactory,
PureDataObjectFactory,
TreeDataObjectFactory,
ContainerRuntimeFactoryWithDefaultDataStore
} from "@fluidframework/aqueduct";For CommonJS:
const {
DataObject,
PureDataObject,
DataObjectFactory,
ContainerRuntimeFactoryWithDefaultDataStore
} = require("@fluidframework/aqueduct");import { DataObject, DataObjectFactory, ContainerRuntimeFactoryWithDefaultDataStore } from "@fluidframework/aqueduct";
import { SharedCounter } from "@fluidframework/counter";
import type { IFluidHandle } from "@fluidframework/core-interfaces";
// 1. Create a data object by extending DataObject
class ClickerDataObject extends DataObject {
private _counter: SharedCounter | undefined;
protected async initializingFirstTime() {
const counter = SharedCounter.create(this.runtime);
this.root.set("clicks", counter.handle);
}
protected async hasInitialized() {
const counterHandle = this.root.get<IFluidHandle<SharedCounter>>("clicks");
this._counter = await counterHandle.get();
}
public get counter() {
if (this._counter === undefined) {
throw new Error("SharedCounter not initialized");
}
return this._counter;
}
}
// 2. Create a factory for the data object
const ClickerFactory = new DataObjectFactory({
type: "clicker",
ctor: ClickerDataObject,
sharedObjects: [SharedCounter.getFactory()],
});
// 3. Create a container runtime factory
export const fluidExport = new ContainerRuntimeFactoryWithDefaultDataStore({
defaultFactory: ClickerFactory,
registryEntries: [ClickerFactory.registryEntry],
});@fluidframework/aqueduct is built around several key architectural patterns:
Core base classes for creating Fluid objects with different levels of built-in functionality, from minimal to full-featured with shared data structures.
abstract class PureDataObject<I extends DataObjectTypes = DataObjectTypes>
abstract class DataObject<I extends DataObjectTypes = DataObjectTypes> extends PureDataObject<I>
abstract class TreeDataObject<TDataObjectTypes extends DataObjectTypes = DataObjectTypes> extends PureDataObject<TDataObjectTypes>Factory classes for instantiating, managing, and creating data objects with proper runtime configuration and shared object registration.
class PureDataObjectFactory<TObj extends PureDataObject<I>, I extends DataObjectTypes = DataObjectTypes>
class DataObjectFactory<TObj extends DataObject<I>, I extends DataObjectTypes = DataObjectTypes> extends PureDataObjectFactory<TObj, I>
class TreeDataObjectFactory<TDataObject extends TreeDataObject<TDataObjectTypes>, TDataObjectTypes extends DataObjectTypes = DataObjectTypes>Factory classes for creating and managing container runtimes, providing the infrastructure for hosting and coordinating multiple data objects within Fluid containers.
class BaseContainerRuntimeFactory extends RuntimeFactoryHelper
class ContainerRuntimeFactoryWithDefaultDataStore extends BaseContainerRuntimeFactoryHelper functions and utilities for advanced data object creation and management patterns.
/**
* Utility for creating SharedObjectKind instances for data objects.
* @internal
*/
function createDataObjectKind<T extends DataObjectKind>(
factory: T
): T & SharedObjectKind<T extends DataObjectKind<infer I> ? I : unknown>interface DataObjectTypes {
OptionalProviders?: FluidObject;
InitialState?: any;
Events?: IEvent;
}
interface IDataObjectProps<I extends DataObjectTypes = DataObjectTypes> {
readonly runtime: IFluidDataStoreRuntime;
readonly context: IFluidDataStoreContext;
readonly providers: AsyncFluidObjectProvider<I["OptionalProviders"]>;
readonly initProps?: I["InitialState"];
}
type DataObjectKind<T = unknown> = {
readonly factory: IFluidDataStoreFactory;
} & (
| {
readonly makeCovariant?: T | undefined;
}
| (new (...args: never[]) => T)
);interface DataObjectFactoryProps<TObj extends PureDataObject<I>, I extends DataObjectTypes = DataObjectTypes> {
readonly type: string;
readonly ctor: new (props: IDataObjectProps<I>) => TObj;
readonly sharedObjects?: readonly IChannelFactory[];
readonly optionalProviders?: FluidObjectSymbolProvider<I["OptionalProviders"]>;
readonly registryEntries?: NamedFluidDataStoreRegistryEntries;
readonly runtimeClass?: typeof FluidDataStoreRuntime;
readonly policies?: Partial<IFluidDataStorePolicies>;
}
interface BaseContainerRuntimeFactoryProps {
registryEntries: NamedFluidDataStoreRegistryEntries;
dependencyContainer?: IFluidDependencySynthesizer;
requestHandlers?: RuntimeRequestHandler[];
runtimeOptions?: IContainerRuntimeOptions;
provideEntryPoint: (runtime: IContainerRuntime) => Promise<FluidObject>;
minVersionForCollab?: MinimumVersionForCollab | undefined;
}
interface ContainerRuntimeFactoryWithDefaultDataStoreProps {
defaultFactory: IFluidDataStoreFactory;
registryEntries: NamedFluidDataStoreRegistryEntries;
dependencyContainer?: IFluidDependencySynthesizer;
requestHandlers?: RuntimeRequestHandler[];
runtimeOptions?: IContainerRuntimeOptions;
provideEntryPoint?: (runtime: IContainerRuntime) => Promise<FluidObject>;
}The following types are from other Fluid Framework packages and are used in the @fluidframework/aqueduct API:
// From @fluidframework/core-interfaces
interface FluidObject {
[key: string]: any;
}
interface IEvent {
[key: string]: any;
}
interface IRequest {
url: string;
headers?: { [key: string]: any };
}
interface IResponse {
mimeType: string;
status: number;
value: any;
}
interface IFluidHandle<T = any> {
get(): Promise<T>;
bind(handle: IFluidHandle): void;
}
interface IFluidHandleInternal<T = any> extends IFluidHandle<T> {
// Internal implementation details
}
// From @fluidframework/datastore-definitions
interface IFluidDataStoreRuntime {
id: string;
entryPoint: IFluidHandle;
createChannel(id: string, type: string): any;
getChannel(id: string): Promise<any>;
bindToContext(): void;
}
interface IFluidDataStoreContext {
containerRuntime: any;
packagePath: readonly string[];
scope: FluidObject;
createProps?: any;
}
// From @fluidframework/runtime-definitions
interface IFluidDataStoreFactory {
type: string;
instantiateDataStore(context: IFluidDataStoreContext, existing: boolean): Promise<any>;
}
type NamedFluidDataStoreRegistryEntries = [string, Promise<IFluidDataStoreFactory>][];
type NamedFluidDataStoreRegistryEntry = [string, Promise<IFluidDataStoreFactory>];
// From @fluidframework/map
interface ISharedDirectory {
set(key: string, value: any): void;
get<T>(key: string): T | undefined;
// Additional SharedDirectory methods...
}
// From @fluidframework/tree
interface ITree {
viewWith<T>(schema: T): any;
// Additional SharedTree methods...
}
// From @fluidframework/synthesize
type AsyncFluidObjectProvider<T> = {
[K in keyof T]: Promise<T[K] | undefined>;
};
type FluidObjectSymbolProvider<T> = {
[K in keyof T]: symbol;
};
// From @fluidframework/container-runtime
interface IContainerRuntime {
createDataStore(type: string): Promise<any>;
getAliasedDataStoreEntryPoint(alias: string): Promise<IFluidHandle | undefined>;
}
interface IContainerRuntimeOptions {
summaryOptions?: any;
gcOptions?: any;
compressionOptions?: any;
[key: string]: any;
}
// From @fluidframework/datastore
class FluidDataStoreRuntime {
constructor(...args: any[]);
}
interface IFluidDataStorePolicies {
gcOptions?: any;
[key: string]: any;
}
interface IChannelFactory {
type: string;
create(runtime: any, id?: string): any;
}
// From @fluidframework/request-handler (deprecated)
type RuntimeRequestHandler = (request: IRequest, runtime: any) => Promise<IResponse | undefined>;
// From @fluidframework/container-runtime-definitions
type MinimumVersionForCollab = string;
// From @fluidframework/synthesize
interface IFluidDependencySynthesizer {
synthesize<T>(providers: any, scope: any): any;
}
// From @fluidframework/shared-object-base
type SharedObjectKind<T = unknown> = {
readonly factory: any;
};