narrative-studio-sdk
Version:
Narrative SDK for building apps on the Narrative Studio
133 lines (132 loc) • 5.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Narrative = void 0;
const FunctionRegistry_1 = require("./scheme/FunctionRegistry");
class WorkerMessageHandler {
postMessage(message) {
self.postMessage(message);
}
addMessageListener(listener) {
self.addEventListener('message', listener);
}
}
class Narrative {
/** @internal */
static _setMessageHandler(handler) {
this.messageHandler = handler;
}
/**
* Creates a new scheme.
* @param scheme - The scheme to create.
* @returns Promise<void | Error> - Resolves on successful scheme creation, returns the error on failure.
*/
static createScheme(scheme) {
// Clone scheme to avoid mutating consumer input
const clonedScheme = JSON.parse(JSON.stringify(scheme));
const serializedScheme = this.serializeSchemeFunctions(clonedScheme);
return new Promise((resolve, reject) => {
this.messageHandler.postMessage({ type: 'create-scheme', scheme: serializedScheme });
this.messageHandler.addMessageListener((event) => {
if (event.data.type === 'command-response') {
event.data.error ? reject(new Error(event.data.error)) : resolve();
}
});
});
}
/**
* Serializes all function references in a scheme (e.g., file transform rules)
* so they can be postMessage-safe and later looked up by ID.
*/
static serializeSchemeFunctions(scheme) {
return {
...scheme,
categories: scheme.categories.map((category) => ({
...category,
constructs: category.constructs.map((construct) => ({
...construct,
filesTransformRules: this.serializeFileTransformRules(construct.filesTransformRules),
})),
assets: category.assets.map((asset) => ({
...asset,
filesTransformRules: this.serializeFileTransformRules(asset.filesTransformRules),
})),
})),
};
}
/**
* Replaces function fields with ID references and registers them.
*/
static serializeFileTransformRules(rules = []) {
return rules.map((rule) => {
const transformedRule = { ...rule };
if (typeof rule.transformToTarget === 'function') {
const id = `transformToTarget:${rule.sourceName}->${rule.targetName}`;
(0, FunctionRegistry_1.registerFunction)(id, rule.transformToTarget);
transformedRule.transformToTarget = id;
}
if (typeof rule.transformToSource === 'function') {
const id = `transformToSource:${rule.sourceName}->${rule.targetName}`;
(0, FunctionRegistry_1.registerFunction)(id, rule.transformToSource);
transformedRule.transformToSource = id;
}
if (typeof rule.merge === 'function') {
const id = `merge:${rule.sourceName}->${rule.targetName}`;
(0, FunctionRegistry_1.registerFunction)(id, rule.merge);
transformedRule.merge = id;
}
return transformedRule;
});
}
//** Get<>(id: string): Promise<any> {
/**
* Sends a command to be processed, specifying the command class and its parameters.
* Resolves or rejects based on the command’s result.
* @param CommandClass - The constructor of the command to be sent.
* @param params - Parameters required by the command.
* @returns Promise<void | Error> - Resolves on successful command execution, returns the error on failure.
*/
static sendCommand(CommandClass, params) {
return new Promise((resolve, reject) => {
const payload = {
type: 'command',
commandClass: new CommandClass(params).name,
params,
};
this.messageHandler.postMessage(payload);
this.messageHandler.addMessageListener((event) => {
if (event.data.type === 'command-response') {
event.data.error ? reject(new Error(event.data.error)) : resolve();
}
});
});
}
/**
* Subscribes to specified events and executes a handler function when the event is received.
* @param eventClasses - An array of event constructors to subscribe to.
* @param handler - A function to handle the incoming events.
*/
static subscribeToEvents(eventClasses, handler) {
eventClasses.forEach((EventClass) => {
const payload = { type: 'subscribe', event: EventClass.type };
this.messageHandler.postMessage(payload);
this.messageHandler.addMessageListener((event) => {
if (event.data.type === 'event' && eventClasses.some((ec) => ec.type === event.data.event)) {
const eventClass = eventClasses.find((ec) => ec.type === event.data.event);
if (eventClass) {
handler(event.data.payload);
}
}
});
});
}
/**
* Updates the ReadModel with the provided data.
* @param data - The data to update the ReadModel with.
*/
static updateReadModel(data) {
const payload = { type: 'update-store', data };
this.messageHandler.postMessage(payload);
}
}
exports.Narrative = Narrative;
Narrative.messageHandler = new WorkerMessageHandler();