/**
* @author Michael Hasenstein <hasenstein@yahoo.com>
* @author Maximilian Wisgickl <wisgicklma@gmail.com>
* @copyright REFINIO GmbH & Maximilian Wisgickl 2017
* @license CC-BY-NC-SA-2.5; portions MIT License
* @version 0.0.1
*/
/**
* @private
* @module
*/
/**
* Options object for Chum importer function
* {@link
* chum-base.sendAccessibleObjectsEventsRequest|chum-base.sendAccessibleObjectsEventsRequest}
* @global
* @typedef {object} AccessibleObjectsRequestOptions
* @property {number} [lastChumTimestamp] - Numeric millisecond timestamp (since 1/1/1970) to only
* list accessible objects created later than this
* @property {boolean} [keepRunning=false] - Triggers the sending of update events while the
* websocket connection and the Chum exchange remain active, informing the Chum importer of any
* newly created objects that it has access to (may overlap with the initial list of accessible
* objects depending on millisecond timing - but the Chum importer has double-download prevention)
* @property {number} maxNotificationDelay - When `keepRunning` is true and the full
* synchronization is over, what should be the maximum delay between new accessible objects
* being created and notification events sent to us? The remote instance is going to collect all
* new accessible hashes and only sends them after waiting for this amount of milliseconds. If
* there are a lot of new hashes, exceeding a hard-coded threshold, it sends them right away though.
* If you require fast notifications about rare new-accessible-object events you can set the
* delay low (**1 ms is the minimum**), if it is not urgent you can set the delay higher and let
* the remote exporter accumulate more hashes. The delay does not have to be higher than a few
* seconds, because it will make less and less of a difference very quickly with increasing values.
*/
export interface AccessibleObjectsRequestOptions {
lastChumTimestamp?: number;
keepRunning?: boolean;
maxNotificationDelay?: number;
}
/**
* An array of these objects is the "list" property of AccessibleObjectsEventData.
*
* The data is stored using an array instead of an object with named properties because the data
* will be JSON.stringified and sent over a websocket. Repeating string literals for the property
* names for every single item wastes space needlessly.
*
* Element [0] - The hash or the ID hash (for ID objects)
* Element [1] - The type of the object pointed to by the hash, and the type of hash (regular, ID)
* Element [2] - The distance of the hash from the root node
* Element [3] - The size of the object
* @typedef {Array<SHA256Hash,HashTypes,number>} AccessibleObjectsTuple
*/
export type AccessibleObjectsTuple = [
SHA256Hash<HashTypes> | SHA256IdHash,
IteratorCbParam['type'],
number,
number
];
/**
* @typedef {object} AccessibleObjectsEventData
* @property {AccessibleObjectsTuple[]} list - Array of hash and type string pairs. Type can be
* any ONE object type name or "BIN" for all other types of files. This type is used by the
* {@link chum-exporter.ts|chum-exporter} to send events about accessible objects to the
* connected ONE instance's {@link chum-importer.ts|chum-importer}. The importer uses the
* type information to select the right method to request the hash: ONE objects are transferred
* as microdata strings, everything else (type "BLOB") as a binary stream.
* @property {number} timestamp - When a timestamp is sent it indicates that the hashes of all
* accessible objects created up to this point in time have been sent. A timestamp is only sent
* if graph iteration completed successfully.
* If the importer manages to process all those hashes (obtain them or find that it already has
* the file) it can use the timestamp as parameter for the next synchronization to tell the
* remote exporter to only send hashes created after the given time.
*/
export interface AccessibleObjectsEventData {
list: AccessibleObjectsTuple[];
timestamp?: number;
}
/**
* This event is sent when the chum-exporter has iterated through all accessible objects found
* in the initial full scan. It is mostly useful for non-ending `keepRunning:true` chums,
* although if the receiving importer's ONE instance still is not done with its own
* chum-exporter task of sending accessible objects this event still appears before the chum
* exchange is over. When both sides' chum-exporter sent this event a full-sync chum without
* `keepRunning:true` will be over.
* @global
* @typedef {object} ExporterEventFullSync
* @property {1} type
*/
export interface ExporterEventFullSync {
type: 1;
}
/**
* @global
* @typedef {object} ExporterEventError
* @property {2} type
* @property {string} code
* @property {string} message
*/
export interface ExporterEventError {
type: 2;
code: string;
message: string;
}
/**
* The union of all event types that the chum-exporter can send to the chum-importer.
* @global
* @typedef {object} ExporterEvent
*/
export type ExporterEvent = ExporterEventFullSync | ExporterEventError;
import type {IteratorCbParam} from './object-graph-bottom-up-iterator';
import type {HashTypes} from './recipes';
import type {SHA256Hash, SHA256IdHash} from './util/type-checks';
import {countEnumerableProperties} from './util/type-checks';
import {isObject, isString} from './util/type-checks-basic';
/**
* The chum-exporter may send event notifications of this type to the chum-importer through the
* websocket connection.
* @global
* @typedef {object} EXPORTER_EVENT_TYPES
* @property {1} FULL_SYNC
* @property {2} ERROR
*/
export const EXPORTER_EVENT_TYPES = {
FULL_SYNC: 1,
ERROR: 2
} as const;
/**
* Runtime type check function for {@link EXPORTER_EVENT_TYPES} chum-exporter event message
* objects. Anything received over the network needs to be fully type-checked.
* @static
* @param {*} thing
* @returns {boolean} Returns `true`if thing is an {@link ExporterEvent} object, `false` otherwise
*/
export function isExporterEventObj(thing: unknown): thing is ExporterEvent {
if (!isObject(thing)) {
return false;
}
switch (thing.type) {
case 1:
return countEnumerableProperties(thing) === 1;
case 2:
return (
countEnumerableProperties(thing) === 3 &&
isString(thing.code) &&
isString(thing.message)
);
default:
return false;
}
}
/**
* @static
* @type {object}
* @property {2} ACCESSIBLE_OBJECTS_EVENTS_REQUEST - 2
* @property {2} EXPORTER_EVENT - 3
* @property {4} ACCESSIBLE_OBJECTS_EVENT - 4
* @property {6} GET_OBJECT - 6
* @property {7} GET_ID_OBJECT -7
* @property {8} GET_BLOB - 8
* @property {9} ACKNOWLEDGE - 9
* @property {10} GET_CRDT_META_OBJECT - 10
*/
export const MESSAGE_TYPES = {
// Chum protocol version check to check if both sides are compatible
VERSION_CHECK: 1,
// Ask the exporter to send lists of accessible objects as events to the importer
// EXPORTER handles this event
ACCESSIBLE_OBJECTS_EVENTS_REQUEST: 2,
// The exporter uses this message type to send event notifications to the importer. An
// example is the event telling the importer the initial "full sync" is finished in a
// keepRunning:true chum.
// IMPORTER handles this event
EXPORTER_EVENT: 3,
// EVENT: Chum exporter sends a list of accessible object hashes to the Chum importer one or
// more times during a Chum exchange
// IMPORTER handles this event
ACCESSIBLE_OBJECTS_EVENT: 4,
// Get ONE microdata (UTF-8 string) object with hash, path (path needed for the server to check
// if the access is legit)
// EXPORTER handles this event
GET_OBJECT: 6,
// Get ONE microdata (UTF-8 string) object with hash, path (path needed for the server to check
// if the access is legit)
// EXPORTER handles this event
GET_ID_OBJECT: 7,
// Get BLOB with hash, path (path needed for the server to check if the access is legit)
// EXPORTER handles this event
GET_BLOB: 8,
// Acknowledge reception of objects (after they have been saved locally)
// EXPORTER handles this event
ACKNOWLEDGE: 9,
// Get ONE microdata (UTF-8 string) for metadata object of a crdt object.
// EXPORTER handles this event
GET_CRDT_META_OBJECT: 10
} as const;