### Install TWIN Synchronised Storage Packages Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Installs all necessary packages for the TWIN Synchronised Storage framework using npm. This includes models, service, REST client, and entity storage connector. ```bash # Install all packages npm install @twin.org/synchronised-storage-models npm install @twin.org/synchronised-storage-service npm install @twin.org/synchronised-storage-rest-client npm install @twin.org/entity-storage-connector-synchronised ``` -------------------------------- ### Install Synchronised Storage Models Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-models/README.md This snippet shows how to install the @twin.org/synchronised-storage-models package using npm. It is a prerequisite for using the synchronised storage models in your project. ```shell npm install @twin.org/synchronised-storage-models ``` -------------------------------- ### Install Synchronised Entity Storage Connector Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/entity-storage-connector-synchronised/README.md Installs the TWIN Entity Storage Connector Synchronised package using npm. This command is essential for integrating the connector into your project. ```shell npm install @twin.org/entity-storage-connector-synchronised ``` -------------------------------- ### SynchronisedStorageService Methods Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/reference/classes/SynchronisedStorageService.md Provides methods for managing the SynchronisedStorageService, including starting, stopping, retrieving decryption keys, and synchronising changesets. ```APIDOC ## SynchronisedStorageService Methods ### className() ### Description Returns the class name of the component. ### Method GET ### Endpoint N/A ### Parameters None ### Request Example None ### Response #### Success Response (200) - **className** (string) - The class name of the component. #### Response Example ```json { "className": "SynchronisedStorageService" } ``` --- ### start(nodeLoggingComponentType?) ### Description The component needs to be started when the node is initialized. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **nodeLoggingComponentType** (string) - Optional. The node logging component type. ### Request Example ```json { "nodeLoggingComponentType": "some-log-type" } ``` ### Response #### Success Response (200) `Promise` #### Response Example ```json {} ``` --- ### stop(nodeLoggingComponentType?) ### Description The component needs to be stopped when the node is closed. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **nodeLoggingComponentType** (string) - Optional. The node logging component type. ### Request Example ```json { "nodeLoggingComponentType": "some-log-type" } ``` ### Response #### Success Response (200) `Promise` #### Response Example ```json {} ``` --- ### getDecryptionKey(trustPayload) ### Description Get the decryption key for the synchronised storage. This is used to decrypt the data stored in the synchronised storage. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **trustPayload** (unknown) - Trust payload to verify the requesters identity. ### Request Example ```json { "trustPayload": { ... } } ``` ### Response #### Success Response (200) - **decryptionKey** (string) - The decryption key. #### Response Example ```json { "decryptionKey": "your-decryption-key" } ``` --- ### syncChangeSet(syncChangeSet, trustPayload) ### Description Synchronise a set of changes from an untrusted node, assumes this is a trusted node. ### Method POST ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **syncChangeSet** (ISyncChangeSet) - The change set to synchronise. - **trustPayload** (unknown) - Trust payload to verify the requesters identity. ### Request Example ```json { "syncChangeSet": { ... }, "trustPayload": { ... } } ``` ### Response #### Success Response (200) `Promise` #### Response Example ```json {} ``` ``` -------------------------------- ### SynchronisedEntityStorageConnector Setup and Usage Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Demonstrates how to set up and use the SynchronisedEntityStorageConnector to wrap an existing entity storage connector, enabling automatic data synchronization. It covers defining synchronised entities, setting up storage and event bus, performing CRUD operations, and querying entities. ```typescript import { ComponentFactory } from "@twin.org/core"; import { EntitySchemaFactory, EntitySchemaHelper, entity, property } from "@twin.org/entity"; import { MemoryEntityStorageConnector } from "@twin.org/entity-storage-connector-memory"; import { EntityStorageConnectorFactory } from "@twin.org/entity-storage-models"; import { LocalEventBusConnector } from "@twin.org/event-bus-connector-local"; import { EventBusConnectorFactory } from "@twin.org/event-bus-models"; import { EventBusService } from "@twin.org/event-bus-service"; import { SynchronisedEntityStorageConnector } from "@twin.org/entity-storage-connector-synchronised"; import type { ISynchronisedEntity } from "@twin.org/synchronised-storage-models"; // Define a synchronised entity schema @entity() class UserProfile implements ISynchronisedEntity { @property({ type: "string", isPrimary: true }) public id!: string; @property({ type: "string", isSecondary: true }) public nodeIdentity!: string; @property({ type: "string", isSecondary: true }) public dateModified!: string; @property({ type: "string" }) public displayName!: string; @property({ type: "string" }) public email!: string; } // Register the entity schema EntitySchemaFactory.register("UserProfile", () => EntitySchemaHelper.getSchema(UserProfile)); // Set up storage and event bus const memoryConnector = new MemoryEntityStorageConnector({ entitySchema: "UserProfile" }); EntityStorageConnectorFactory.register("memory", () => memoryConnector); const eventBusConnector = new LocalEventBusConnector(); EventBusConnectorFactory.register("local", () => eventBusConnector); const eventBusService = new EventBusService({ eventBusConnectorType: "local" }); ComponentFactory.register("event-bus", () => eventBusService); // Create the synchronised connector const syncConnector = new SynchronisedEntityStorageConnector({ entitySchema: "UserProfile", entityStorageConnectorType: "memory", eventBusComponentType: "event-bus", config: { storageKey: "user-profiles" } }); // Start the connector (registers storage key and subscribes to events) await syncConnector.start(); // CRUD operations automatically sync across nodes await syncConnector.set({ id: "user-001", nodeIdentity: "did:example:node-1", dateModified: new Date().toISOString(), displayName: "Alice", email: "alice@example.com" }); // Retrieve an entity const user = await syncConnector.get("user-001"); console.log(user); // Output: { id: "user-001", nodeIdentity: "did:example:node-1", dateModified: "2025-01-28T...", displayName: "Alice", email: "alice@example.com" } // Query entities with conditions const results = await syncConnector.query( { conditions: [ { property: "displayName", value: "Alice", comparison: "equals" } ] }, [{ property: "dateModified", sortDirection: "desc" }] ); console.log(results.entities); // Remove an entity (triggers sync deletion across nodes) await syncConnector.remove("user-001"); ``` -------------------------------- ### Define ISyncChangeSet and Example Change Set (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Defines the structure for representing a set of changes to be synchronized between nodes, including change operations and individual change records. An example demonstrates the complete change set structure. ```typescript import type { ISyncChangeSet, ISyncChange, SyncChangeOperation } from "@twin.org/synchronised-storage-models"; // Change operations const operations: Record = { Set: "set", // Create or update entity Delete: "delete" // Remove entity }; // Individual change record interface ISyncChange { operation: SyncChangeOperation; id: string; entity?: ISynchronisedEntityCore; // Present for "set" operations } // Complete change set structure const exampleChangeSet: ISyncChangeSet = { "@context": "https://schema.twindev.org/synchronised-storage/", type: "ChangeSet", id: "abc123def456...", storageKey: "products", dateCreated: "2025-01-28T10:00:00.000Z", dateModified: "2025-01-28T10:30:00.000Z", nodeIdentity: "did:entity-storage:0xnode123...", changes: [ { operation: "set", id: "product-001", entity: { dateModified: "2025-01-28T10:30:00.000Z" } }, { operation: "delete", id: "product-002" } ] }; ``` -------------------------------- ### Git Commit Message Conventions Source: https://github.com/twinfoundation/synchronised-storage/blob/next/CONTRIBUTING.md Defines the standard types and formats for Git commit messages to ensure consistency and clarity in the project's history. Examples illustrate both correct and incorrect usage. ```shell # Good commit messages git commit -m "feat: add JWT token validation" git commit -m "fix: prevent endless loop in data lookup" git commit -m "docs: update installation instructions" # Bad commit messages (avoid these) git commit -m "fix stuff" git commit -m "WIP" git commit -m "changes" ``` -------------------------------- ### Get Decryption Key Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/reference/functions/synchronisedStorageGetDecryptionKeyRequest.md Requests the decryption key for a given component and request context. ```APIDOC ## POST /twinfoundation/synchronised-storage/decryptionKey ### Description Requests the decryption key for a given component and request context. ### Method POST ### Endpoint /twinfoundation/synchronised-storage/decryptionKey ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **httpRequestContext** (IHttpRequestContext) - Required - The request context for the API. - **componentName** (string) - Required - The name of the component to use in the routes. - **request** (ISyncDecryptionKeyRequest) - Required - The request object. ### Request Example ```json { "httpRequestContext": {}, "componentName": "exampleComponent", "request": {} } ``` ### Response #### Success Response (200) - **ISyncDecryptionKeyResponse** - The response object with additional http response properties. #### Response Example ```json { "decryptionKey": "your_decryption_key_here" } ``` ``` -------------------------------- ### Synchronised Entity Data Models (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Defines the core TypeScript interfaces for synchronised entities, including `ISynchronisedEntityCore` for synchronization tracking properties and `ISynchronisedEntity` for essential entity details like ID and node identity. An example of a custom entity `Product` is also provided. ```typescript import type { ISynchronisedEntity, ISynchronisedEntityCore } from "@twin.org/synchronised-storage-models"; // Core properties required for synchronization tracking interface ISynchronisedEntityCore { dateModified: string; // ISO 8601 timestamp } // Full synchronised entity interface interface ISynchronisedEntity extends ISynchronisedEntityCore { id: string; // Unique identifier nodeIdentity: string; // DID of the owning node } // Example custom entity interface Product extends ISynchronisedEntity { id: string; nodeIdentity: string; dateModified: string; name: string; price: number; category: string; } ``` -------------------------------- ### Prepare Prerelease Version (GitHub Action) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/CONTRIBUTING.md Automates the creation of prerelease versions from the 'next' branch. This involves running a GitHub Action to bump versions and update changelogs, resulting in a pull request for review. ```yaml # Example workflow snippet (conceptual) - name: Prepare Release uses: twinfoundation/actions/prepare-release@v1 with: branch: next semver_type: prerelease ``` -------------------------------- ### Prepare Production Version (GitHub Action) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/CONTRIBUTING.md Initiates the process for preparing a production release by merging the 'next' branch into 'main'. This involves running a GitHub Action to update versions and changelogs, creating a PR for review. ```yaml # Example workflow snippet (conceptual) - name: Versions Prepare uses: twinfoundation/actions/versions-prepare@v1 with: branch: main type: production ``` -------------------------------- ### Synchronised Storage REST Client - Constructor Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-rest-client/docs/reference/classes/SynchronisedStorageRestClient.md Initializes a new instance of the SynchronisedStorageRestClient with the provided configuration. ```APIDOC ## Constructor SynchronisedStorageRestClient ### Description Create a new instance of SynchronisedStorageRestClient. ### Method `constructor` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```json { "config": { ... } } ``` ### Response #### Success Response (200) N/A (Constructor does not return a value in the typical sense, it initializes the object) #### Response Example N/A ``` -------------------------------- ### Initialize and Manage SynchronisedStorageService (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Demonstrates how to initialize the SynchronisedStorageService for both trusted and untrusted nodes. It covers configuration options, component registration, and starting/stopping the service. Dependencies include core Twin.org components. ```typescript import { ComponentFactory } from "@twin.org/core"; import { SynchronisedStorageService } from "@twin.org/synchronised-storage-service"; import type { ISynchronisedStorageServiceConstructorOptions } from "@twin.org/synchronised-storage-service"; // Configuration for a trusted node const trustedNodeOptions: ISynchronisedStorageServiceConstructorOptions = { loggingComponentType: "logging", eventBusComponentType: "event-bus", vaultConnectorType: "vault", syncSnapshotStorageConnectorType: "sync-snapshot-entry", blobStorageConnectorType: "blob-storage", verifiableStorageConnectorType: "verifiable-storage", taskSchedulerComponentType: "task-scheduler", trustComponentType: "trust", config: { verifiableStorageKeyId: "mainnet", entityUpdateIntervalMinutes: 5, consolidationIntervalMinutes: 60, consolidationBatchSize: 100, maxConsolidations: 5, blobStorageEncryptionKeyId: "synchronised-storage-blob-encryption-key" } }; // Create and register the service const syncService = new SynchronisedStorageService(trustedNodeOptions); ComponentFactory.register("synchronised-storage", () => syncService); // Start the service await syncService.start(); // Configuration for an untrusted node (relays through trusted node) const untrustedNodeOptions: ISynchronisedStorageServiceConstructorOptions = { eventBusComponentType: "event-bus", vaultConnectorType: "vault", trustedSynchronisedStorageComponentType: "synchronised-storage-client", // REST client to trusted node config: { verifiableStorageKeyId: "mainnet", entityUpdateIntervalMinutes: 5 } }; const untrustedSyncService = new SynchronisedStorageService(untrustedNodeOptions); // Stop the service gracefully await syncService.stop(); ``` -------------------------------- ### Get Decryption Key Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-models/docs/reference/interfaces/ISynchronisedStorageComponent.md Retrieves the decryption key for the synchronised storage, used to decrypt stored data. ```APIDOC ## GET /twinfoundation/synchronised-storage/decryptionKey ### Description Get the decryption key for the synchronised storage. This is used to decrypt the data stored in the synchronised storage. ### Method GET ### Endpoint /twinfoundation/synchronised-storage/decryptionKey ### Parameters #### Query Parameters - **trustPayload** (unknown) - Required - Trust payload to verify the requesters identity. ### Response #### Success Response (200) - **decryptionKey** (string) - The decryption key. #### Response Example { "decryptionKey": "your_decryption_key_here" } ``` -------------------------------- ### SynchronisedStorageService Constructor Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/reference/classes/SynchronisedStorageService.md Creates a new instance of the SynchronisedStorageService with specified options. ```APIDOC ## new SynchronisedStorageService(options) ### Description Create a new instance of SynchronisedStorageService. ### Method CONSTRUCTOR ### Endpoint N/A ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```json { "options": { ... } } ``` ### Response #### Success Response (200) `SynchronisedStorageService` instance #### Response Example ```json { "instance": "SynchronisedStorageService" } ``` ``` -------------------------------- ### Prepare Production Release (GitHub Action) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/CONTRIBUTING.md Generates a production release PR from the 'main' branch. Users select the semver type (major, minor, or patch) for version bumping and changelog updates. ```yaml # Example workflow snippet (conceptual) - name: Prepare Release uses: twinfoundation/actions/prepare-release@v1 with: branch: main semver_type: major # or minor, patch ``` -------------------------------- ### Schema Initialization API Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/reference/functions/initSchema.md Initializes the schema for the synchronised storage service. This function does not return any value. ```APIDOC ## POST /twinfoundation/synchronised-storage/initSchema ### Description Initializes the schema for the synchronised service. ### Method POST ### Endpoint /twinfoundation/synchronised-storage/initSchema ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **status** (string) - Indicates the success of the operation. #### Response Example { "status": "Schema initialized successfully" } ``` -------------------------------- ### SynchronisedEntityStorageConnector Constructor Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/entity-storage-connector-synchronised/docs/reference/classes/SynchronisedEntityStorageConnector.md Initializes a new instance of the SynchronisedEntityStorageConnector. ```APIDOC ## new SynchronisedEntityStorageConnector(options: ISynchronisedEntityStorageConnectorConstructorOptions): SynchronisedEntityStorageConnector ### Description Create a new instance of SynchronisedEntityStorageConnector. ### Method CONSTRUCTOR ### Parameters #### Request Body - **options** (ISynchronisedEntityStorageConnectorConstructorOptions) - Required - The options for the connector. ### Returns `SynchronisedEntityStorageConnector` A new instance of SynchronisedEntityStorageConnector. ``` -------------------------------- ### SynchronisedEntityStorageConnector Methods Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/entity-storage-connector-synchronised/docs/reference/classes/SynchronisedEntityStorageConnector.md Provides documentation for the methods of the SynchronisedEntityStorageConnector class. ```APIDOC ## className() ### Description Returns the class name of the component. ### Method GET ### Endpoint N/A (Instance method) ### Returns `string` The class name of the component. ### Implementation of `IEntityStorageConnector.className` ``` ```APIDOC ## getSchema() ### Description Get the schema for the entities. ### Method GET ### Endpoint N/A (Instance method) ### Returns `IEntitySchema` The schema for the entities. ### Implementation of `IEntityStorageConnector.getSchema` ``` ```APIDOC ## start(nodeLoggingComponentType?): Promise ### Description The component needs to be started when the node is initialized. ### Method POST ### Endpoint N/A (Instance method) ### Parameters #### Query Parameters - **nodeLoggingComponentType?** (string) - Optional - The node logging component type. ### Returns `Promise` Nothing. ### Implementation of `IEntityStorageConnector.start` ``` ```APIDOC ## get(id, secondaryIndex?, conditions?): Promise ### Description Get an entity by its ID or a secondary index. ### Method GET ### Endpoint N/A (Instance method) ### Parameters #### Query Parameters - **id** (string) - Required - The id of the entity to get, or the index value if secondaryIndex is set. - **secondaryIndex?** (keyof T) - Optional - Get the item using a secondary index. - **conditions?** (object[]) - Optional - The optional conditions to match for the entities. ### Returns `Promise` The object if it can be found or undefined. ### Implementation of `IEntityStorageConnector.get` ``` ```APIDOC ## set(entity, conditions?): Promise ### Description Set an entity in the storage. ### Method POST ### Endpoint N/A (Instance method) ### Parameters #### Request Body - **entity** (T) - Required - The entity to set. - **conditions?** (object[]) - Optional - The optional conditions to match for the entities. ### Returns `Promise` Nothing. ### Implementation of `IEntityStorageConnector.set` ``` ```APIDOC ## remove(id, conditions?): Promise ### Description Remove an entity from the storage. ### Method DELETE ### Endpoint N/A (Instance method) ### Parameters #### Query Parameters - **id** (string) - Required - The id of the entity to remove. - **conditions?** (object[]) - Optional - The optional conditions to match for the entities. ### Returns `Promise` Nothing. ### Implementation of `IEntityStorageConnector.remove` ``` ```APIDOC ## query(conditions?, sortProperties?, properties?, cursor?, limit?): Promise<{ entities: Partial[]; cursor?: string; }> ### Description Find all entities that match the specified conditions. ### Method GET ### Endpoint N/A (Instance method) ### Parameters #### Query Parameters - **conditions?** (EntityCondition) - Optional - The conditions to match for the entities. - **sortProperties?** (object[]) - Optional - The optional sort order. - **properties?** (keyof T[]) - Optional - The optional properties to return, defaults to all. - **cursor?** (string) - Optional - The cursor to request the next chunk of entities. - **limit?** (number) - Optional - The suggested number of entities to return in each chunk, in some scenarios can return a different amount. ### Returns `Promise<{ entities: Partial[]; cursor?: string; }>` All the entities for the storage matching the conditions, and a cursor which can be used to request more entities. ### Implementation of `IEntityStorageConnector.query` ``` -------------------------------- ### Synchronised Storage Event Bus Topics and Usage (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Demonstrates how to interact with the synchronised storage event bus using TypeScript. It shows how to subscribe to topics like 'local-item-change' and publish events such as 'remote-item-set' and 'batch-request'. Requires the '@twin.org/synchronised-storage-models' package. ```typescript import { SynchronisedStorageTopics } from "@twin.org/synchronised-storage-models"; import type { ISyncRegisterStorageKey, ISyncItemChange, ISyncItemRequest, ISyncItemResponse, ISyncItemSet, ISyncItemRemove, ISyncBatchRequest, ISyncBatchResponse, ISyncReset } from "@twin.org/synchronised-storage-models"; // Available event bus topics const topics = { RegisterStorageKey: "synchronised-storage:register-storage-key", // New storage key registration LocalItemChange: "synchronised-storage:local-item-change", // Local entity modification LocalItemRequest: "synchronised-storage:local-item-request", // Request for local entity data LocalItemResponse: "synchronised-storage:local-item-response", // Response with local entity data RemoteItemSet: "synchronised-storage:remote-item-set", // Remote entity creation/update RemoteItemRemove: "synchronised-storage:remote-item-remove", // Remote entity deletion BatchRequest: "synchronised-storage:batch-request", // Batch data request for consolidation BatchResponse: "synchronised-storage:batch-response", // Batch data response Reset: "synchronised-storage:reset" // Storage reset command }; // Subscribe to local item changes for monitoring await eventBusService.subscribe( SynchronisedStorageTopics.LocalItemChange, async (event) => { console.log(`Entity ${event.data.id} was ${event.data.operation}ed in ${event.data.storageKey}`); } ); // Publish a remote item set event (simulating incoming sync data) await eventBusService.publish( SynchronisedStorageTopics.RemoteItemSet, { storageKey: "user-profiles", entity: { id: "user-remote-001", nodeIdentity: "did:example:remote-node", dateModified: new Date().toISOString() } } ); // Request a batch of local entities for consolidation await eventBusService.publish( SynchronisedStorageTopics.BatchRequest, { storageKey: "user-profiles", batchSize: 100, requestMode: "local" // "local", "remote", or "all" } ); ``` -------------------------------- ### Generate REST API Routes for Synchronised Storage (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Illustrates how to generate REST API routes for the synchronised storage service, making them integrable with various API frameworks. It shows how to use helper functions to define endpoints for submitting change sets and requesting decryption keys. Dependencies include synchronised-storage-service. ```typescript import { generateRestRoutesSynchronisedStorage, tagsSynchronisedStorage, restEntryPoints } from "@twin.org/synchronised-storage-service"; // Generate REST routes for integration with your API framework const routes = generateRestRoutesSynchronisedStorage("/synchronised-storage", "synchronised-storage"); // Routes include: // POST /synchronised-storage/sync-changeset - Submit a change set for synchronization // POST /synchronised-storage/decryption-key - Request the blob storage decryption key // Example using restEntryPoints for automatic route registration console.log(restEntryPoints); // Output: [{ name: "synchronised-storage", defaultBaseRoute: "synchronised-storage", tags: [...], generateRoutes: fn }] ``` -------------------------------- ### Publish Prerelease Version (GitHub Action) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/CONTRIBUTING.md Publishes prerelease packages to NPM using the 'next' tag and creates corresponding GitHub releases. This action is typically run after the prerelease PR is merged. ```yaml # Example workflow snippet (conceptual) - name: Publish Release uses: twinfoundation/actions/publish-release@v1 with: tag: next ``` -------------------------------- ### ISyncPointerStore Object Definition Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/reference/interfaces/ISyncPointerStore.md Defines the structure of the sync pointer store, including its version and a mapping of storage keys to sync pointers. ```APIDOC ## ISyncPointerStore ### Description The object definition for the sync pointer store. ### Properties #### version - **version** (string) - The version of the sync pointer store. #### syncPointers - **syncPointers** (object) - The mapping from storage keys to sync pointers. - **Index Signature** - `key` (string): The storage key. - Value (string): The sync pointer associated with the key. ### Request Example ```json { "version": "1.0.0", "syncPointers": { "user_profile_123": "pointer_abc", "settings_456": "pointer_xyz" } } ``` ### Response Example ```json { "version": "1.0.0", "syncPointers": { "user_profile_123": "pointer_abc", "settings_456": "pointer_xyz" } } ``` ``` -------------------------------- ### SynchronisedStorageRestClient - Usage Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Demonstrates how to use the SynchronisedStorageRestClient to interact with a remote trusted node's synchronised storage service via REST. -------------------------------- ### Event Bus Topics Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt The synchronisation system uses an event bus for internal communication. This section details the available topics for monitoring and extending functionality. ```APIDOC ## Event Bus Topics ### Description The synchronisation system uses an event bus for internal communication between components. These topics can be subscribed to for monitoring or extending functionality. ### Available Topics - **synchronised-storage:register-storage-key**: New storage key registration. - **synchronised-storage:local-item-change**: Local entity modification. - **synchronised-storage:local-item-request**: Request for local entity data. - **synchronised-storage:local-item-response**: Response with local entity data. - **synchronised-storage:remote-item-set**: Remote entity creation/update. - **synchronised-storage:remote-item-remove**: Remote entity deletion. - **synchronised-storage:batch-request**: Batch data request for consolidation. - **synchronised-storage:batch-response**: Batch data response. - **synchronised-storage:reset**: Storage reset command. ### Example Usage ```typescript import { SynchronisedStorageTopics } from "@twin.org/synchronised-storage-models"; // Subscribe to local item changes for monitoring await eventBusService.subscribe( SynchronisedStorageTopics.LocalItemChange, async (event) => { console.log(`Entity ${event.data.id} was ${event.data.operation}ed in ${event.data.storageKey}`); } ); // Publish a remote item set event (simulating incoming sync data) await eventBusService.publish( SynchronisedStorageTopics.RemoteItemSet, { storageKey: "user-profiles", entity: { id: "user-remote-001", nodeIdentity: "did:example:remote-node", dateModified: new Date().toISOString() } } ); // Request a batch of local entities for consolidation await eventBusService.publish( SynchronisedStorageTopics.BatchRequest, { storageKey: "user-profiles", batchSize: 100, requestMode: "local" // "local", "remote", or "all" } ); ``` ``` -------------------------------- ### Sync Snapshot Structure (JSON) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/architecture.md Represents a snapshot of storage, containing IDs of change sets that constitute the complete data set. It includes metadata like creation date, epoch, and a flag indicating if the data is consolidated. This structure is essential for versioning and restoring storage states. ```json { "id": "0xaaa...aaa", "dateCreated": "2025-05-29T01:00:00.000Z", "dateModified": "2025-05-29T01:00:00.000Z", "isConsolidated": false, "epoch": 123, "changeSetStorageIds": [ "blob:ipfs:0x111...1111", "blob:ipfs:0x111...1112" ] } ``` -------------------------------- ### SynchronisedStorageService Configuration Interface (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Defines the configuration options for the SynchronisedStorageService. This includes intervals for entity updates and change consolidation, batch sizes, retention policies, and encryption key IDs. ```typescript interface ISynchronisedStorageServiceConfig { // How often to check for entity updates (minutes) entityUpdateIntervalMinutes?: number; // default: 5 // Interval for consolidation of changesets (trusted nodes only) consolidationIntervalMinutes?: number; // default: 60 // Entities per consolidation batch (trusted nodes only) consolidationBatchSize?: number; // default: 100 // Maximum consolidation snapshots to retain maxConsolidations?: number; // default: 5 // Vault key ID for blob storage encryption blobStorageEncryptionKeyId?: string; // default: "synchronised-storage-blob-encryption-key" // Verifiable storage network identifier verifiableStorageKeyId: "mainnet" | "testnet" | "devnet" | string; // Override trust generator type overrideTrustGeneratorType?: string; } ``` -------------------------------- ### ISynchronisedEntityStorageConnectorConstructorOptions Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/entity-storage-connector-synchronised/docs/reference/interfaces/ISynchronisedEntityStorageConnectorConstructorOptions.md Defines the structure for options used to construct a Synchronised Entity Storage Connector. ```APIDOC ## Interface: ISynchronisedEntityStorageConnectorConstructorOptions Options for the Synchronised Entity Storage Connector constructor. ### Properties #### entitySchema - **entitySchema** (string) - Required - The name of the entity schema. #### entityStorageConnectorType - **entityStorageConnectorType** (string) - Required - The entity storage connector type to use for actual data. #### eventBusComponentType - **eventBusComponentType** (string) - Optional - The event bus component type. - Default: `event-bus` #### config - **config** (ISynchronisedEntityStorageConnectorConfig) - Optional - The configuration for the connector. ``` -------------------------------- ### Apply Patch to release-please Package (Shell) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/release/README.md This shell command applies a patch to the `release-please` package. It uses `npx patch-package` to apply the changes defined in the `release` directory, ensuring the modified prerelease strategy is correctly integrated. ```shell npx patch-package release-please --patch-dir release ``` -------------------------------- ### Remote Synchronisation Flow Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/architecture.md Details the steps involved in remote synchronisation, where any node can poll verifiable storage, fetch data from decentralized storage, and then decrypt and decompress it to update the local state. ```mermaid AnyNode → [Poll] → VerifiableStorage → [Fetch] → DecentralisedStorage → [Decrypt & Decompress] → LocalState ``` -------------------------------- ### Publish Production Version (GitHub Action) Source: https://github.com/twinfoundation/synchronised-storage/blob/next/CONTRIBUTING.md Publishes stable packages to NPM with the 'latest' tag and creates official GitHub releases. This action is performed after the production release PR is merged. ```yaml # Example workflow snippet (conceptual) - name: Publish Release uses: twinfoundation/actions/publish-release@v1 with: tag: latest ``` -------------------------------- ### SynchronisedEntityStorageConnector Configuration Interface (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Defines the constructor options for the SynchronisedEntityStorageConnector. Key parameters include the entity schema name, the underlying storage connector type, and optional configuration for custom storage keys. ```typescript interface ISynchronisedEntityStorageConnectorConstructorOptions { // Entity schema name (must be registered with EntitySchemaFactory) entitySchema: string; // Underlying storage connector type entityStorageConnectorType: string; // Event bus component type (default: "event-bus") eventBusComponentType?: string; config?: { // Custom storage key (default: kebab-case of entitySchema) storageKey?: string; }; } ``` -------------------------------- ### SynchronisedStorageService Configuration Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Configuration options for the SynchronisedStorageService, controlling aspects like update intervals, consolidation settings, and storage encryption. ```APIDOC ## SynchronisedStorageService Configuration ### Description Configuration options for the `SynchronisedStorageService`. These settings allow fine-tuning of synchronization intervals, data consolidation, and security parameters. ### Method N/A (Configuration Structure Definition) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```json { "entityUpdateIntervalMinutes": 10, "consolidationIntervalMinutes": 120, "consolidationBatchSize": 200, "maxConsolidations": 10, "blobStorageEncryptionKeyId": "my-custom-encryption-key", "verifiableStorageKeyId": "mainnet" } ``` ### Response #### Success Response (200) N/A (Configuration Structure Definition) #### Response Example N/A ``` -------------------------------- ### Use SynchronisedStorageRestClient for Remote Sync (TypeScript) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Shows how to use the SynchronisedStorageRestClient to connect to remote synchronised storage endpoints. It covers fetching decryption keys and synchronizing change sets, requiring a trust payload for authentication. Dependencies include synchronised-storage-models. ```typescript import { SynchronisedStorageRestClient } from "@twin.org/synchronised-storage-rest-client"; import type { ISyncChangeSet } from "@twin.org/synchronised-storage-models"; // Create REST client pointing to trusted node const client = new SynchronisedStorageRestClient({ endpoint: "https://trusted-node.example.com/api" }); // Get decryption key from trusted node (requires trust payload for authentication) const trustPayload = "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..."; // JWT or verifiable credential const decryptionKey = await client.getDecryptionKey(trustPayload); console.log("Decryption key:", decryptionKey); // Sync a change set to the trusted node const changeSet: ISyncChangeSet = { "@context": "https://schema.twindev.org/synchronised-storage/", type: "ChangeSet", id: "0909090909090909090909090909090909090909090909090909090909090909", storageKey: "user-profiles", dateCreated: new Date().toISOString(), dateModified: new Date().toISOString(), nodeIdentity: "did:entity-storage:0xabc123...", changes: [ { operation: "set", id: "user-001", entity: { dateModified: new Date().toISOString() } }, { operation: "delete", id: "user-002" } ] }; await client.syncChangeSet(changeSet, trustPayload); ``` -------------------------------- ### Synchronised Storage Service Configuration Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/reference/interfaces/ISynchronisedStorageServiceConfig.md This section details the configuration properties for the Synchronised Storage Service. It covers intervals for entity updates and data consolidation, batch sizes, maximum consolidations, and encryption key identifiers. ```APIDOC ## Synchronised Storage Service Configuration Interface ### Description Configuration for the Synchronised Storage Service, including settings for entity updates, data consolidation, and storage keys. ### Method N/A (Configuration Object) ### Endpoint N/A (Configuration Object) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **entityUpdateIntervalMinutes** (number) - Optional - How often to check for entity updates in minutes. Default: 5 - **consolidationIntervalMinutes** (number) - Optional - Interval to perform consolidation of changesets, only used if this is a trusted node. Default: 60 - **consolidationBatchSize** (number) - Optional - The number of entities to process in a single consolidation batch, only used if this is a trusted node. Default: 1000 - **maxConsolidations** (number) - Optional - The maximum number of consolidations to keep in storage, only used if this is a trusted node. Default: 5 - **blobStorageEncryptionKeyId** (string) - Optional - The encryption key id from the vault to use for blob storage, only required for trusted nodes, untrusted nodes will request the key. Default: synchronised-storage-blob-encryption-key - **verifiableStorageKeyId** (string) - Required - The verifiable storage key to use, already expected to be created. If the key is not found in the keys.json it is considered to be a custom verifiable storage id. Default: local - **overrideTrustGeneratorType** (string) - Optional - Override the default trust generator. ### Request Example ```json { "entityUpdateIntervalMinutes": 10, "consolidationIntervalMinutes": 120, "consolidationBatchSize": 2000, "maxConsolidations": 10, "blobStorageEncryptionKeyId": "my-custom-encryption-key", "verifiableStorageKeyId": "custom-verifiable-key", "overrideTrustGeneratorType": "SomeTrustGenerator" } ``` ### Response #### Success Response (200) This configuration object itself is returned upon successful retrieval or application. #### Response Example ```json { "entityUpdateIntervalMinutes": 10, "consolidationIntervalMinutes": 120, "consolidationBatchSize": 2000, "maxConsolidations": 10, "blobStorageEncryptionKeyId": "my-custom-encryption-key", "verifiableStorageKeyId": "custom-verifiable-key", "overrideTrustGeneratorType": "SomeTrustGenerator" } ``` ``` -------------------------------- ### SynchronisedEntityStorageConnector Configuration Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Configuration options for the SynchronisedEntityStorageConnector, specifying entity schema, storage type, and optional custom storage keys. ```APIDOC ## SynchronisedEntityStorageConnector Configuration ### Description Configuration options for the `SynchronisedEntityStorageConnector`. This includes defining the entity schema, the underlying storage mechanism, and optional custom configurations. ### Method N/A (Configuration Structure Definition) ### Endpoint N/A ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```json { "entitySchema": "Product", "entityStorageConnectorType": "PostgresEntityStorageConnector", "eventBusComponentType": "custom-event-bus", "config": { "storageKey": "custom-products-storage" } } ``` ### Response #### Success Response (200) N/A (Configuration Structure Definition) #### Response Example N/A ``` -------------------------------- ### Global State Persistence Flow Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/architecture.md Describes the process of persisting global state by encrypting and compressing it before storing it in decentralized storage. The state root is then stored in verifiable storage for integrity checks. ```mermaid TrustedNode → [Encrypt & Compress] → DecentralisedStorage → [StateRoot] → VerifiableStorage ``` -------------------------------- ### Epoch Gap Detection Logic Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/architecture.md This TypeScript code snippet demonstrates the logic for detecting epoch gaps during synchronisation. It compares the newest existing epoch with the oldest sync state epoch to determine if a full consolidation snapshot is needed. ```typescript const newestExistingEpoch = existingSnapshots[0]?.epoch ?? 0; const oldestSyncStateEpoch = syncStateSnapshots[syncStateSnapshots.length - 1]?.epoch ?? 0; const hasEpochGap = newestExistingEpoch + 1 < oldestSyncStateEpoch; ``` -------------------------------- ### ISyncBatchResponse Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-models/docs/reference/interfaces/ISyncBatchResponse.md Defines the structure of a response for a local batch operation within the synchronised storage system. It includes the storage key, a list of entities, and a flag indicating if it's the last entry. ```APIDOC ## Interface: ISyncBatchResponse ### Description Response for a local batch, containing storage information and entities. ### Properties #### storageKey - **storageKey** (string) - Required - The key of the storage for the entities in the batch. #### entities - **entities** (array of ISynchronisedEntity) - Required - The entities in the batch. #### lastEntry - **lastEntry** (boolean) - Required - Indicates if this is the last entry in the batch. ``` -------------------------------- ### SyncChangeOperation Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-models/docs/reference/variables/SyncChangeOperation.md Defines the possible operations for a change within the synchronised storage. These operations indicate whether an item was set or deleted. ```APIDOC ## SyncChangeOperation ### Description Represents the operations that can occur on an item within the synchronised storage. This includes setting a new value or deleting an existing one. ### Method N/A (This is a type definition, not an endpoint) ### Endpoint N/A ### Parameters N/A ### Request Example N/A ### Response #### Success Response (200) - **Set** (string) - Represents the operation where an item was set in the storage. Value is "set". - **Delete** (string) - Represents the operation where an item was deleted from the storage. Value is "delete". #### Response Example ```json { "Set": "set", "Delete": "delete" } ``` ``` -------------------------------- ### Change Set Propagation Flow Source: https://github.com/twinfoundation/synchronised-storage/blob/next/packages/synchronised-storage-service/docs/architecture.md Illustrates the flow of data from a regular node to a trusted node through change sets and verification. This process ensures that changes are securely propagated and validated within the system. ```mermaid RegularNode → [Sign] → ChangeSet → TrustedNode → [Verify] → GlobalState ``` -------------------------------- ### Submit Changeset to Trusted Node (Bash) Source: https://context7.com/twinfoundation/synchronised-storage/llms.txt Submits a changeset from an untrusted node to a trusted node for synchronization. Requires authentication and a JSON payload detailing the changes. The expected response is '204 No Content' on success. ```bash curl -X POST https://trusted-node.example.com/api/synchronised-storage/sync-changeset \ -H "Content-Type: application/json" \ -H "Authorization: Bearer eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..." \ -d '{ "@context": "https://schema.twindev.org/synchronised-storage/", "type": "ChangeSet", "id": "0909090909090909090909090909090909090909090909090909090909090909", "storageKey": "user-profiles", "dateCreated": "2025-01-28T10:00:00.000Z", "dateModified": "2025-01-28T10:00:00.000Z", "nodeIdentity": "did:entity-storage:0xabc123...", "changes": [ { "operation": "set", "id": "user-001", "entity": { "dateModified": "2025-01-28T10:00:00.000Z" } } ] }' ```