Legacy factory classes provide direct control over SharedMap and SharedDirectory creation and loading. These classes are primarily used for advanced integration scenarios and backward compatibility. For most applications, the modern SharedMap and SharedDirectory factory functions are recommended.
Factory class for creating and loading SharedMap instances with full control over the creation process.
/**
* Factory class for ISharedMap instances
* @deprecated Consider using SharedMap factory function instead
*/
class MapFactory implements IChannelFactory<ISharedMap> {
/** Channel type identifier for SharedMap */
static readonly Type: "https://graph.microsoft.com/types/map";
/** Default channel attributes for SharedMap */
static readonly Attributes: IChannelAttributes;
/** Instance type property */
get type(): string;
/** Instance attributes property */
get attributes(): IChannelAttributes;
/**
* Create a new SharedMap instance
* @param runtime - Fluid data store runtime
* @param id - Unique identifier for the map
* @returns New ISharedMap instance
*/
create(runtime: IFluidDataStoreRuntime, id: string): ISharedMap;
/**
* Load an existing SharedMap instance from storage
* @param runtime - Fluid data store runtime
* @param id - Unique identifier for the map
* @param services - Channel services for loading
* @param attributes - Channel attributes
* @returns Promise resolving to loaded ISharedMap instance
*/
load(
runtime: IFluidDataStoreRuntime,
id: string,
services: IChannelServices,
attributes: IChannelAttributes
): Promise<ISharedMap>;
}
/**
* Channel attributes interface
*/
interface IChannelAttributes {
type: string;
snapshotFormatVersion: string;
packageVersion: string;
}
/**
* Channel factory interface
*/
interface IChannelFactory<T = IFluidLoadable> {
readonly type: string;
readonly attributes: IChannelAttributes;
load(runtime: IFluidDataStoreRuntime, id: string, services: IChannelServices, channelAttributes: Readonly<IChannelAttributes>): Promise<T>;
create(document: IFluidDataStoreRuntime, id: string): T;
}Usage Examples:
import { MapFactory } from "@fluidframework/map";
// Access factory metadata
console.log("Map type:", MapFactory.Type);
console.log("Map attributes:", MapFactory.Attributes);
// Create a new map using the factory
const factory = new MapFactory();
const myMap = factory.create(runtime, "my-map-id");
// The factory approach gives you the same ISharedMap interface
myMap.set("key1", "value1");
myMap.set("key2", { nested: "object" });
console.log("Map type check:", factory.type === MapFactory.Type); // true
// Load an existing map from storage (advanced scenario)
const loadedMap = await factory.load(
runtime,
"existing-map-id",
channelServices,
MapFactory.Attributes
);Factory class for creating and loading SharedDirectory instances with full control over the creation process.
/**
* Factory class for ISharedDirectory instances
* @deprecated Consider using SharedDirectory factory function instead
*/
class DirectoryFactory implements IChannelFactory<ISharedDirectory> {
/** Channel type identifier for SharedDirectory */
static readonly Type: "https://graph.microsoft.com/types/directory";
/** Default channel attributes for SharedDirectory */
static readonly Attributes: IChannelAttributes;
/** Instance type property */
get type(): string;
/** Instance attributes property */
get attributes(): IChannelAttributes;
/**
* Create a new SharedDirectory instance
* @param runtime - Fluid data store runtime
* @param id - Unique identifier for the directory
* @returns New ISharedDirectory instance
*/
create(runtime: IFluidDataStoreRuntime, id: string): ISharedDirectory;
/**
* Load an existing SharedDirectory instance from storage
* @param runtime - Fluid data store runtime
* @param id - Unique identifier for the directory
* @param services - Channel services for loading
* @param attributes - Channel attributes
* @returns Promise resolving to loaded ISharedDirectory instance
*/
load(
runtime: IFluidDataStoreRuntime,
id: string,
services: IChannelServices,
attributes: IChannelAttributes
): Promise<ISharedDirectory>;
}Usage Examples:
import { DirectoryFactory } from "@fluidframework/map";
// Access factory metadata
console.log("Directory type:", DirectoryFactory.Type);
console.log("Directory attributes:", DirectoryFactory.Attributes);
// Create a new directory using the factory
const factory = new DirectoryFactory();
const myDirectory = factory.create(runtime, "my-directory-id");
// Use the directory normally
myDirectory.set("root-key", "root-value");
const subDir = myDirectory.createSubDirectory("subdirectory");
subDir.set("sub-key", "sub-value");
console.log("Directory type check:", factory.type === DirectoryFactory.Type); // true
// Load an existing directory from storage (advanced scenario)
const loadedDirectory = await factory.load(
runtime,
"existing-directory-id",
channelServices,
DirectoryFactory.Attributes
);Both factory classes provide static metadata that identifies the channel type and format information.
// MapFactory metadata
MapFactory.Type === "https://graph.microsoft.com/types/map";
MapFactory.Attributes.type === "https://graph.microsoft.com/types/map";
MapFactory.Attributes.snapshotFormatVersion === "0.2";
MapFactory.Attributes.packageVersion; // Current package version
// DirectoryFactory metadata
DirectoryFactory.Type === "https://graph.microsoft.com/types/directory";
DirectoryFactory.Attributes.type === "https://graph.microsoft.com/types/directory";
DirectoryFactory.Attributes.snapshotFormatVersion === "0.1";
DirectoryFactory.Attributes.packageVersion; // Current package versionUsage Examples:
// Compare factory types
const mapFactory = new MapFactory();
const dirFactory = new DirectoryFactory();
console.log("Factories have different types:", mapFactory.type !== dirFactory.type);
// Check version compatibility
function isCompatibleVersion(attributes: IChannelAttributes): boolean {
const currentVersion = MapFactory.Attributes.packageVersion;
return attributes.packageVersion === currentVersion;
}
// Use metadata for registration or configuration
const channelRegistry = new Map<string, IChannelFactory>();
channelRegistry.set(MapFactory.Type, new MapFactory());
channelRegistry.set(DirectoryFactory.Type, new DirectoryFactory());
function createChannelFromType(type: string, runtime: IFluidDataStoreRuntime, id: string) {
const factory = channelRegistry.get(type);
if (!factory) {
throw new Error(`Unknown channel type: ${type}`);
}
return factory.create(runtime, id);
}import { MapFactory, DirectoryFactory } from "@fluidframework/map";
// Register factories in a Fluid Framework application
class DataStoreFactory {
private readonly channelFactories = new Map<string, IChannelFactory>();
constructor() {
// Register the map and directory factories
this.channelFactories.set(MapFactory.Type, new MapFactory());
this.channelFactories.set(DirectoryFactory.Type, new DirectoryFactory());
}
createChannel(type: string, runtime: IFluidDataStoreRuntime, id: string) {
const factory = this.channelFactories.get(type);
if (!factory) {
throw new Error(`No factory registered for type: ${type}`);
}
return factory.create(runtime, id);
}
async loadChannel(
type: string,
runtime: IFluidDataStoreRuntime,
id: string,
services: IChannelServices
) {
const factory = this.channelFactories.get(type);
if (!factory) {
throw new Error(`No factory registered for type: ${type}`);
}
return factory.load(runtime, id, services, factory.attributes);
}
getSupportedTypes(): string[] {
return Array.from(this.channelFactories.keys());
}
}
// Usage
const dataStoreFactory = new DataStoreFactory();
console.log("Supported types:", dataStoreFactory.getSupportedTypes());
// Create channels by type
const map = dataStoreFactory.createChannel(MapFactory.Type, runtime, "map1");
const directory = dataStoreFactory.createChannel(DirectoryFactory.Type, runtime, "dir1");async function loadOrCreateChannel<T>(
factory: IChannelFactory<T>,
runtime: IFluidDataStoreRuntime,
id: string,
services?: IChannelServices
): Promise<T> {
if (services) {
try {
// Try to load existing channel
return await factory.load(runtime, id, services, factory.attributes);
} catch (error) {
console.warn(`Failed to load channel ${id}, creating new one:`, error);
}
}
// Create new channel if loading failed or no services provided
return factory.create(runtime, id);
}
// Usage examples
const mapFactory = new MapFactory();
const dirFactory = new DirectoryFactory();
// Load or create a map
const myMap = await loadOrCreateChannel(mapFactory, runtime, "persistent-map", services);
// Load or create a directory
const myDir = await loadOrCreateChannel(dirFactory, runtime, "persistent-dir", services);function checkCompatibility(
factory: IChannelFactory,
loadedAttributes: IChannelAttributes
): boolean {
// Check type compatibility
if (factory.attributes.type !== loadedAttributes.type) {
console.error("Type mismatch:", factory.attributes.type, "vs", loadedAttributes.type);
return false;
}
// Check version compatibility
if (factory.attributes.snapshotFormatVersion !== loadedAttributes.snapshotFormatVersion) {
console.warn("Snapshot format version mismatch:",
factory.attributes.snapshotFormatVersion, "vs", loadedAttributes.snapshotFormatVersion);
// Might still be compatible, depending on your versioning strategy
}
// Check package version (example: allow loading from same major version)
const factoryVersion = factory.attributes.packageVersion.split('.')[0];
const loadedVersion = loadedAttributes.packageVersion.split('.')[0];
if (factoryVersion !== loadedVersion) {
console.warn("Major version mismatch:", factoryVersion, "vs", loadedVersion);
return false;
}
return true;
}
// Usage in loading logic
async function safeLoadChannel<T>(
factory: IChannelFactory<T>,
runtime: IFluidDataStoreRuntime,
id: string,
services: IChannelServices,
loadedAttributes: IChannelAttributes
): Promise<T | null> {
if (!checkCompatibility(factory, loadedAttributes)) {
console.error(`Cannot load channel ${id} due to compatibility issues`);
return null;
}
try {
return await factory.load(runtime, id, services, loadedAttributes);
} catch (error) {
console.error(`Failed to load channel ${id}:`, error);
return null;
}
}If you're currently using legacy factory classes, here's how to migrate to the modern approach:
import { MapFactory, DirectoryFactory } from "@fluidframework/map";
// Old approach
const mapFactory = new MapFactory();
const myMap = mapFactory.create(runtime, "my-map");
const dirFactory = new DirectoryFactory();
const myDir = dirFactory.create(runtime, "my-dir");import { SharedMap, SharedDirectory } from "@fluidframework/map";
// New approach
const myMap = SharedMap.create(runtime, "my-map");
const myDir = SharedDirectory.create(runtime, "my-dir");Legacy factories are still useful for:
/**
* Core types used by factory classes
*/
// Runtime and service interfaces (re-exported from Fluid Framework)
interface IFluidDataStoreRuntime {
// Runtime interface for creating and managing channels
readonly id: string;
readonly connected: boolean;
// ... additional runtime properties and methods
}
interface IChannelServices {
// Services provided to channels for persistence and communication
readonly deltaConnection: IDeltaConnection;
readonly objectStorage: IChannelStorageService;
// ... additional service properties
}
interface IFluidLoadable {
// Base interface for loadable Fluid objects
readonly url: string;
// ... additional loadable properties
}
// Legacy serialization interfaces
interface ISerializableValue {
type: string;
value: any;
}
interface ICreateInfo {
/** Sequence number at which this subdirectory was created */
csn: number;
/** Client IDs of the clients which created this subdirectory */
ccIds: string[];
}
interface IDirectoryDataObject {
ci?: ICreateInfo;
storage?: Record<string, ISerializableValue>;
subdirectories?: Record<string, IDirectoryDataObject>;
}
interface IDirectoryNewStorageFormat {
blobs: string[];
content: IDirectoryDataObject;
}