@onflow/util-actor
Advanced tools
Comparing version 1.3.0-alpha.0 to 1.3.0
# @onflow/util-actor | ||
## 1.3.0 | ||
### Minor Changes | ||
- [#1728](https://github.com/onflow/fcl-js/pull/1728) [`a4f8c00c`](https://github.com/onflow/fcl-js/commit/a4f8c00c4cf292d3a4afac610dedbc89ff3affea) Thanks [@nialexsan](https://github.com/nialexsan)! - TS build | ||
- [#1761](https://github.com/onflow/fcl-js/pull/1761) [`92b966d3`](https://github.com/onflow/fcl-js/commit/92b966d39936ba0a90629ee320e62e4fed5d2296) Thanks [@jribbink](https://github.com/jribbink)! - Enhance TS support for @onflow/util-actor | ||
## 1.3.0-alpha.0 | ||
@@ -4,0 +12,0 @@ |
@@ -5,68 +5,24 @@ 'use strict'; | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { | ||
return value instanceof P ? value : new P(function (resolve) { | ||
resolve(value); | ||
}); | ||
} | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
const mailbox = () => { | ||
const queue = []; | ||
let next; | ||
return { | ||
async deliver(msg) { | ||
queue.push(msg); | ||
if (next) { | ||
next(queue.shift()); | ||
next = undefined; | ||
} | ||
}, | ||
receive() { | ||
return new Promise(function innerReceive(resolve) { | ||
const msg = queue.shift(); | ||
if (msg) return resolve(msg); | ||
next = resolve; | ||
}); | ||
} | ||
function rejected(value) { | ||
try { | ||
step(generator["throw"](value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
} | ||
function step(result) { | ||
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); | ||
} | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
const mailbox = () => { | ||
const queue = []; | ||
var next; | ||
return { | ||
deliver(msg) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
queue.push(msg); | ||
if (next) { | ||
next(queue.shift()); | ||
next = undefined; | ||
} | ||
}); | ||
}, | ||
receive() { | ||
return new Promise(function innerReceive(resolve) { | ||
const msg = queue.shift(); | ||
if (msg) | ||
return resolve(msg); | ||
next = resolve; | ||
}); | ||
}, | ||
}; | ||
}; | ||
}; | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const queueMicrotask = require("queue-microtask"); | ||
@@ -80,141 +36,149 @@ const INIT = "INIT"; | ||
const TERMINATE = "TERMINATE"; | ||
const root = (typeof self === "object" && self.self === self && self) || | ||
(typeof global === "object" && global.global === global && global) || | ||
(typeof window === "object" && window.window === window && window) || | ||
{ FCL_REGISTRY: null }; | ||
const root = typeof self === "object" && self.self === self && self || typeof global === "object" && global.global === global && global || typeof window === "object" && window.window === window && window || { | ||
FCL_REGISTRY: null | ||
}; | ||
root.FCL_REGISTRY = root.FCL_REGISTRY == null ? {} : root.FCL_REGISTRY; | ||
const FCL_REGISTRY = root.FCL_REGISTRY; | ||
var pid = 0b0; | ||
let pid = 0b0; | ||
const DEFAULT_TIMEOUT = 5000; | ||
const send = (addr, tag, data, opts = {}) => new Promise((reply, reject) => { | ||
function send(addr, tag, data) { | ||
let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { | ||
expectReply: false | ||
}; | ||
return new Promise((resolve, reject) => { | ||
const expectReply = opts.expectReply || false; | ||
const timeout = opts.timeout != null ? opts.timeout : DEFAULT_TIMEOUT; | ||
if (expectReply && timeout) { | ||
setTimeout(() => reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), timeout); | ||
setTimeout(() => reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), timeout); | ||
} | ||
const payload = { | ||
to: addr, | ||
from: opts.from, | ||
tag, | ||
data, | ||
timeout, | ||
reply, | ||
reject, | ||
to: addr, | ||
from: opts.from, | ||
tag, | ||
data, | ||
timeout, | ||
reply: resolve, | ||
reject | ||
}; | ||
try { | ||
FCL_REGISTRY[addr] && | ||
FCL_REGISTRY[addr].mailbox.deliver(payload); | ||
if (!expectReply) | ||
reply(true); | ||
if (FCL_REGISTRY[addr]) { | ||
FCL_REGISTRY[addr].mailbox.deliver(payload); | ||
} | ||
if (!expectReply) { | ||
resolve(true); | ||
} | ||
} catch (error) { | ||
console.error("FCL.Actor -- Could Not Deliver Message", payload, FCL_REGISTRY[addr], error); | ||
reject(error); | ||
} | ||
catch (error) { | ||
console.error("FCL.Actor -- Could Not Deliver Message", payload, FCL_REGISTRY[addr], error); | ||
} | ||
}); | ||
}); | ||
} | ||
const kill = addr => { | ||
delete FCL_REGISTRY[addr]; | ||
delete FCL_REGISTRY[addr]; | ||
}; | ||
const fromHandlers = (handlers = {}) => (ctx) => __awaiter(void 0, void 0, void 0, function* () { | ||
if (typeof handlers[INIT] === "function") | ||
yield handlers[INIT](ctx); | ||
__loop: while (1) { | ||
const letter = yield ctx.receive(); | ||
try { | ||
if (letter.tag === EXIT) { | ||
if (typeof handlers[TERMINATE] === "function") { | ||
yield handlers[TERMINATE](ctx, letter, letter.data || {}); | ||
} | ||
break __loop; | ||
} | ||
yield handlers[letter.tag](ctx, letter, letter.data || {}); | ||
const fromHandlers = handlers => async ctx => { | ||
if (typeof handlers[INIT] === "function") await handlers[INIT](ctx); | ||
__loop: while (1) { | ||
const letter = await ctx.receive(); | ||
try { | ||
if (letter.tag === EXIT) { | ||
if (typeof handlers[TERMINATE] === "function") { | ||
await handlers[TERMINATE](ctx, letter, letter.data || {}); | ||
} | ||
catch (error) { | ||
console.error(`${ctx.self()} Error`, letter, error); | ||
} | ||
finally { | ||
continue __loop; | ||
} | ||
break __loop; | ||
} | ||
await handlers[letter.tag]?.(ctx, letter, letter.data || {}); | ||
} catch (error) { | ||
console.error(`${ctx.self()} Error`, letter, error); | ||
} finally { | ||
continue __loop; | ||
} | ||
}); | ||
const parseAddr = (addr) => { | ||
if (addr == null) { | ||
return String(++pid); | ||
} | ||
return String(addr); | ||
} | ||
}; | ||
const spawn = (fn, rawAddr = null) => { | ||
const addr = parseAddr(rawAddr); | ||
if (FCL_REGISTRY[addr] != null) | ||
return addr; | ||
FCL_REGISTRY[addr] = { | ||
addr, | ||
mailbox: mailbox(), | ||
subs: new Set(), | ||
kvs: {}, | ||
error: null, | ||
}; | ||
const ctx = { | ||
self: () => addr, | ||
receive: () => FCL_REGISTRY[addr].mailbox.receive(), | ||
send: (to, tag, data, opts = {}) => { | ||
opts.from = addr; | ||
return send(to, tag, data, opts); | ||
}, | ||
sendSelf: (tag, data, opts) => { | ||
if (FCL_REGISTRY[addr]) | ||
send(addr, tag, data, opts); | ||
}, | ||
broadcast: (tag, data, opts = {}) => { | ||
opts.from = addr; | ||
for (let to of FCL_REGISTRY[addr].subs) | ||
send(to, tag, data, opts); | ||
}, | ||
subscribe: sub => sub != null && FCL_REGISTRY[addr].subs.add(sub), | ||
unsubscribe: sub => sub != null && FCL_REGISTRY[addr].subs.delete(sub), | ||
subscriberCount: () => FCL_REGISTRY[addr].subs.size, | ||
hasSubs: () => !!FCL_REGISTRY[addr].subs.size, | ||
put: (key, value) => { | ||
if (key != null) | ||
FCL_REGISTRY[addr].kvs[key] = value; | ||
}, | ||
get: (key, fallback) => { | ||
const value = FCL_REGISTRY[addr].kvs[key]; | ||
return value == null ? fallback : value; | ||
}, | ||
delete: key => { | ||
delete FCL_REGISTRY[addr].kvs[key]; | ||
}, | ||
update: (key, fn) => { | ||
if (key != null) | ||
FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]); | ||
}, | ||
keys: () => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs); | ||
}, | ||
all: () => { | ||
return FCL_REGISTRY[addr].kvs; | ||
}, | ||
where: pattern => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { | ||
return pattern.test(key) | ||
? Object.assign(Object.assign({}, acc), { [key]: FCL_REGISTRY[addr].kvs[key] }) : acc; | ||
}, {}); | ||
}, | ||
merge: (data = {}) => { | ||
Object.keys(data).forEach(key => (FCL_REGISTRY[addr].kvs[key] = data[key])); | ||
}, | ||
fatalError: error => { | ||
FCL_REGISTRY[addr].error = error; | ||
for (let to of FCL_REGISTRY[addr].subs) | ||
send(to, UPDATED); | ||
}, | ||
}; | ||
if (typeof fn === "object") | ||
fn = fromHandlers(fn); | ||
queueMicrotask(() => __awaiter(void 0, void 0, void 0, function* () { | ||
yield fn(ctx); | ||
kill(addr); | ||
})); | ||
return addr; | ||
const parseAddr = addr => { | ||
if (addr == null) { | ||
return String(++pid); | ||
} | ||
return String(addr); | ||
}; | ||
const spawn = function (fnOrHandlers) { | ||
let rawAddr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; | ||
const addr = parseAddr(rawAddr); | ||
if (FCL_REGISTRY[addr] != null) return addr; | ||
FCL_REGISTRY[addr] = { | ||
addr, | ||
mailbox: mailbox(), | ||
subs: new Set(), | ||
kvs: {}, | ||
error: null | ||
}; | ||
const ctx = createCtx(addr); | ||
let fn; | ||
if (typeof fnOrHandlers === "object") fn = fromHandlers(fnOrHandlers);else fn = fnOrHandlers; | ||
queueMicrotask(async () => { | ||
await fn(ctx); | ||
kill(addr); | ||
}); | ||
return addr; | ||
}; | ||
const createCtx = addr => ({ | ||
self: () => addr, | ||
receive: () => FCL_REGISTRY[addr].mailbox.receive(), | ||
send: function (to, tag, data) { | ||
let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
if (to == null) return; | ||
opts.from = addr; | ||
return send(to, tag, data, opts); | ||
}, | ||
sendSelf: function (tag, data) { | ||
let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
if (FCL_REGISTRY[addr]) send(addr, tag, data, opts); | ||
}, | ||
broadcast: function (tag, data) { | ||
let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
opts.from = addr; | ||
for (const to of FCL_REGISTRY[addr].subs) send(to, tag, data, opts); | ||
}, | ||
subscribe: sub => sub != null && FCL_REGISTRY[addr].subs.add(sub), | ||
unsubscribe: sub => sub != null && FCL_REGISTRY[addr].subs.delete(sub), | ||
subscriberCount: () => FCL_REGISTRY[addr].subs.size, | ||
hasSubs: () => !!FCL_REGISTRY[addr].subs.size, | ||
put: (key, value) => { | ||
if (key != null) FCL_REGISTRY[addr].kvs[key] = value; | ||
}, | ||
get: function (key) { | ||
let fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; | ||
const value = FCL_REGISTRY[addr].kvs[key]; | ||
return value == null ? fallback : value; | ||
}, | ||
delete: key => { | ||
delete FCL_REGISTRY[addr].kvs[key]; | ||
}, | ||
update: (key, fn) => { | ||
if (key != null) FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]); | ||
}, | ||
keys: () => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs); | ||
}, | ||
all: () => { | ||
return FCL_REGISTRY[addr].kvs; | ||
}, | ||
where: pattern => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { | ||
return pattern.test(key) ? { | ||
...acc, | ||
[key]: FCL_REGISTRY[addr].kvs[key] | ||
} : acc; | ||
}, {}); | ||
}, | ||
merge: function () { | ||
let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
Object.keys(data).forEach(key => FCL_REGISTRY[addr].kvs[key] = data[key]); | ||
}, | ||
fatalError: error => { | ||
FCL_REGISTRY[addr].error = error; | ||
for (const to of FCL_REGISTRY[addr].subs) send(to, UPDATED); | ||
} | ||
}); | ||
// Returns an unsubscribe function | ||
@@ -229,23 +193,23 @@ // A SUBSCRIBE handler will need to be created to handle the subscription event | ||
function subscriber(address, spawnFn, callback) { | ||
spawnFn(address); | ||
const EXIT = "@EXIT"; | ||
const self = spawn((ctx) => __awaiter(this, void 0, void 0, function* () { | ||
ctx.send(address, SUBSCRIBE); | ||
while (1) { | ||
const letter = yield ctx.receive(); | ||
const error = FCL_REGISTRY[address].error; | ||
if (letter.tag === EXIT) { | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
if (error) { | ||
callback(null, error); | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
callback(letter.data, null); | ||
} | ||
})); | ||
return () => send(self, EXIT); | ||
spawnFn(address); | ||
const self = spawn(async ctx => { | ||
ctx.send(address, SUBSCRIBE); | ||
while (1) { | ||
const letter = await ctx.receive(); | ||
const error = FCL_REGISTRY[address].error; | ||
if (letter.tag === EXIT) { | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
if (error) { | ||
callback(null, error); | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
callback(letter.data, null); | ||
} | ||
}); | ||
return () => send(self, EXIT); | ||
} | ||
// Returns a promise that returns a result | ||
@@ -259,4 +223,7 @@ // A SNAPSHOT handler will need to be created to handle the snapshot event | ||
function snapshoter(address, spawnFn) { | ||
spawnFn(address); | ||
return send(address, SNAPSHOT, null, { expectReply: true, timeout: 0 }); | ||
spawnFn(address); | ||
return send(address, SNAPSHOT, null, { | ||
expectReply: true, | ||
timeout: 0 | ||
}); | ||
} | ||
@@ -263,0 +230,0 @@ |
@@ -1,67 +0,23 @@ | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { | ||
return value instanceof P ? value : new P(function (resolve) { | ||
resolve(value); | ||
}); | ||
} | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
const mailbox = () => { | ||
const queue = []; | ||
let next; | ||
return { | ||
async deliver(msg) { | ||
queue.push(msg); | ||
if (next) { | ||
next(queue.shift()); | ||
next = undefined; | ||
} | ||
}, | ||
receive() { | ||
return new Promise(function innerReceive(resolve) { | ||
const msg = queue.shift(); | ||
if (msg) return resolve(msg); | ||
next = resolve; | ||
}); | ||
} | ||
function rejected(value) { | ||
try { | ||
step(generator["throw"](value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
} | ||
function step(result) { | ||
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); | ||
} | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
} | ||
const mailbox = () => { | ||
const queue = []; | ||
var next; | ||
return { | ||
deliver(msg) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
queue.push(msg); | ||
if (next) { | ||
next(queue.shift()); | ||
next = undefined; | ||
} | ||
}); | ||
}, | ||
receive() { | ||
return new Promise(function innerReceive(resolve) { | ||
const msg = queue.shift(); | ||
if (msg) | ||
return resolve(msg); | ||
next = resolve; | ||
}); | ||
}, | ||
}; | ||
}; | ||
}; | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const queueMicrotask = require("queue-microtask"); | ||
@@ -75,141 +31,149 @@ const INIT = "INIT"; | ||
const TERMINATE = "TERMINATE"; | ||
const root = (typeof self === "object" && self.self === self && self) || | ||
(typeof global === "object" && global.global === global && global) || | ||
(typeof window === "object" && window.window === window && window) || | ||
{ FCL_REGISTRY: null }; | ||
const root = typeof self === "object" && self.self === self && self || typeof global === "object" && global.global === global && global || typeof window === "object" && window.window === window && window || { | ||
FCL_REGISTRY: null | ||
}; | ||
root.FCL_REGISTRY = root.FCL_REGISTRY == null ? {} : root.FCL_REGISTRY; | ||
const FCL_REGISTRY = root.FCL_REGISTRY; | ||
var pid = 0b0; | ||
let pid = 0b0; | ||
const DEFAULT_TIMEOUT = 5000; | ||
const send = (addr, tag, data, opts = {}) => new Promise((reply, reject) => { | ||
function send(addr, tag, data) { | ||
let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { | ||
expectReply: false | ||
}; | ||
return new Promise((resolve, reject) => { | ||
const expectReply = opts.expectReply || false; | ||
const timeout = opts.timeout != null ? opts.timeout : DEFAULT_TIMEOUT; | ||
if (expectReply && timeout) { | ||
setTimeout(() => reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), timeout); | ||
setTimeout(() => reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), timeout); | ||
} | ||
const payload = { | ||
to: addr, | ||
from: opts.from, | ||
tag, | ||
data, | ||
timeout, | ||
reply, | ||
reject, | ||
to: addr, | ||
from: opts.from, | ||
tag, | ||
data, | ||
timeout, | ||
reply: resolve, | ||
reject | ||
}; | ||
try { | ||
FCL_REGISTRY[addr] && | ||
FCL_REGISTRY[addr].mailbox.deliver(payload); | ||
if (!expectReply) | ||
reply(true); | ||
if (FCL_REGISTRY[addr]) { | ||
FCL_REGISTRY[addr].mailbox.deliver(payload); | ||
} | ||
if (!expectReply) { | ||
resolve(true); | ||
} | ||
} catch (error) { | ||
console.error("FCL.Actor -- Could Not Deliver Message", payload, FCL_REGISTRY[addr], error); | ||
reject(error); | ||
} | ||
catch (error) { | ||
console.error("FCL.Actor -- Could Not Deliver Message", payload, FCL_REGISTRY[addr], error); | ||
} | ||
}); | ||
}); | ||
} | ||
const kill = addr => { | ||
delete FCL_REGISTRY[addr]; | ||
delete FCL_REGISTRY[addr]; | ||
}; | ||
const fromHandlers = (handlers = {}) => (ctx) => __awaiter(void 0, void 0, void 0, function* () { | ||
if (typeof handlers[INIT] === "function") | ||
yield handlers[INIT](ctx); | ||
__loop: while (1) { | ||
const letter = yield ctx.receive(); | ||
try { | ||
if (letter.tag === EXIT) { | ||
if (typeof handlers[TERMINATE] === "function") { | ||
yield handlers[TERMINATE](ctx, letter, letter.data || {}); | ||
} | ||
break __loop; | ||
} | ||
yield handlers[letter.tag](ctx, letter, letter.data || {}); | ||
const fromHandlers = handlers => async ctx => { | ||
if (typeof handlers[INIT] === "function") await handlers[INIT](ctx); | ||
__loop: while (1) { | ||
const letter = await ctx.receive(); | ||
try { | ||
if (letter.tag === EXIT) { | ||
if (typeof handlers[TERMINATE] === "function") { | ||
await handlers[TERMINATE](ctx, letter, letter.data || {}); | ||
} | ||
catch (error) { | ||
console.error(`${ctx.self()} Error`, letter, error); | ||
} | ||
finally { | ||
continue __loop; | ||
} | ||
break __loop; | ||
} | ||
await handlers[letter.tag]?.(ctx, letter, letter.data || {}); | ||
} catch (error) { | ||
console.error(`${ctx.self()} Error`, letter, error); | ||
} finally { | ||
continue __loop; | ||
} | ||
}); | ||
const parseAddr = (addr) => { | ||
if (addr == null) { | ||
return String(++pid); | ||
} | ||
return String(addr); | ||
} | ||
}; | ||
const spawn = (fn, rawAddr = null) => { | ||
const addr = parseAddr(rawAddr); | ||
if (FCL_REGISTRY[addr] != null) | ||
return addr; | ||
FCL_REGISTRY[addr] = { | ||
addr, | ||
mailbox: mailbox(), | ||
subs: new Set(), | ||
kvs: {}, | ||
error: null, | ||
}; | ||
const ctx = { | ||
self: () => addr, | ||
receive: () => FCL_REGISTRY[addr].mailbox.receive(), | ||
send: (to, tag, data, opts = {}) => { | ||
opts.from = addr; | ||
return send(to, tag, data, opts); | ||
}, | ||
sendSelf: (tag, data, opts) => { | ||
if (FCL_REGISTRY[addr]) | ||
send(addr, tag, data, opts); | ||
}, | ||
broadcast: (tag, data, opts = {}) => { | ||
opts.from = addr; | ||
for (let to of FCL_REGISTRY[addr].subs) | ||
send(to, tag, data, opts); | ||
}, | ||
subscribe: sub => sub != null && FCL_REGISTRY[addr].subs.add(sub), | ||
unsubscribe: sub => sub != null && FCL_REGISTRY[addr].subs.delete(sub), | ||
subscriberCount: () => FCL_REGISTRY[addr].subs.size, | ||
hasSubs: () => !!FCL_REGISTRY[addr].subs.size, | ||
put: (key, value) => { | ||
if (key != null) | ||
FCL_REGISTRY[addr].kvs[key] = value; | ||
}, | ||
get: (key, fallback) => { | ||
const value = FCL_REGISTRY[addr].kvs[key]; | ||
return value == null ? fallback : value; | ||
}, | ||
delete: key => { | ||
delete FCL_REGISTRY[addr].kvs[key]; | ||
}, | ||
update: (key, fn) => { | ||
if (key != null) | ||
FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]); | ||
}, | ||
keys: () => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs); | ||
}, | ||
all: () => { | ||
return FCL_REGISTRY[addr].kvs; | ||
}, | ||
where: pattern => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { | ||
return pattern.test(key) | ||
? Object.assign(Object.assign({}, acc), { [key]: FCL_REGISTRY[addr].kvs[key] }) : acc; | ||
}, {}); | ||
}, | ||
merge: (data = {}) => { | ||
Object.keys(data).forEach(key => (FCL_REGISTRY[addr].kvs[key] = data[key])); | ||
}, | ||
fatalError: error => { | ||
FCL_REGISTRY[addr].error = error; | ||
for (let to of FCL_REGISTRY[addr].subs) | ||
send(to, UPDATED); | ||
}, | ||
}; | ||
if (typeof fn === "object") | ||
fn = fromHandlers(fn); | ||
queueMicrotask(() => __awaiter(void 0, void 0, void 0, function* () { | ||
yield fn(ctx); | ||
kill(addr); | ||
})); | ||
return addr; | ||
const parseAddr = addr => { | ||
if (addr == null) { | ||
return String(++pid); | ||
} | ||
return String(addr); | ||
}; | ||
const spawn = function (fnOrHandlers) { | ||
let rawAddr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; | ||
const addr = parseAddr(rawAddr); | ||
if (FCL_REGISTRY[addr] != null) return addr; | ||
FCL_REGISTRY[addr] = { | ||
addr, | ||
mailbox: mailbox(), | ||
subs: new Set(), | ||
kvs: {}, | ||
error: null | ||
}; | ||
const ctx = createCtx(addr); | ||
let fn; | ||
if (typeof fnOrHandlers === "object") fn = fromHandlers(fnOrHandlers);else fn = fnOrHandlers; | ||
queueMicrotask(async () => { | ||
await fn(ctx); | ||
kill(addr); | ||
}); | ||
return addr; | ||
}; | ||
const createCtx = addr => ({ | ||
self: () => addr, | ||
receive: () => FCL_REGISTRY[addr].mailbox.receive(), | ||
send: function (to, tag, data) { | ||
let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
if (to == null) return; | ||
opts.from = addr; | ||
return send(to, tag, data, opts); | ||
}, | ||
sendSelf: function (tag, data) { | ||
let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
if (FCL_REGISTRY[addr]) send(addr, tag, data, opts); | ||
}, | ||
broadcast: function (tag, data) { | ||
let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
opts.from = addr; | ||
for (const to of FCL_REGISTRY[addr].subs) send(to, tag, data, opts); | ||
}, | ||
subscribe: sub => sub != null && FCL_REGISTRY[addr].subs.add(sub), | ||
unsubscribe: sub => sub != null && FCL_REGISTRY[addr].subs.delete(sub), | ||
subscriberCount: () => FCL_REGISTRY[addr].subs.size, | ||
hasSubs: () => !!FCL_REGISTRY[addr].subs.size, | ||
put: (key, value) => { | ||
if (key != null) FCL_REGISTRY[addr].kvs[key] = value; | ||
}, | ||
get: function (key) { | ||
let fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; | ||
const value = FCL_REGISTRY[addr].kvs[key]; | ||
return value == null ? fallback : value; | ||
}, | ||
delete: key => { | ||
delete FCL_REGISTRY[addr].kvs[key]; | ||
}, | ||
update: (key, fn) => { | ||
if (key != null) FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]); | ||
}, | ||
keys: () => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs); | ||
}, | ||
all: () => { | ||
return FCL_REGISTRY[addr].kvs; | ||
}, | ||
where: pattern => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { | ||
return pattern.test(key) ? { | ||
...acc, | ||
[key]: FCL_REGISTRY[addr].kvs[key] | ||
} : acc; | ||
}, {}); | ||
}, | ||
merge: function () { | ||
let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
Object.keys(data).forEach(key => FCL_REGISTRY[addr].kvs[key] = data[key]); | ||
}, | ||
fatalError: error => { | ||
FCL_REGISTRY[addr].error = error; | ||
for (const to of FCL_REGISTRY[addr].subs) send(to, UPDATED); | ||
} | ||
}); | ||
// Returns an unsubscribe function | ||
@@ -224,23 +188,23 @@ // A SUBSCRIBE handler will need to be created to handle the subscription event | ||
function subscriber(address, spawnFn, callback) { | ||
spawnFn(address); | ||
const EXIT = "@EXIT"; | ||
const self = spawn((ctx) => __awaiter(this, void 0, void 0, function* () { | ||
ctx.send(address, SUBSCRIBE); | ||
while (1) { | ||
const letter = yield ctx.receive(); | ||
const error = FCL_REGISTRY[address].error; | ||
if (letter.tag === EXIT) { | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
if (error) { | ||
callback(null, error); | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
callback(letter.data, null); | ||
} | ||
})); | ||
return () => send(self, EXIT); | ||
spawnFn(address); | ||
const self = spawn(async ctx => { | ||
ctx.send(address, SUBSCRIBE); | ||
while (1) { | ||
const letter = await ctx.receive(); | ||
const error = FCL_REGISTRY[address].error; | ||
if (letter.tag === EXIT) { | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
if (error) { | ||
callback(null, error); | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
callback(letter.data, null); | ||
} | ||
}); | ||
return () => send(self, EXIT); | ||
} | ||
// Returns a promise that returns a result | ||
@@ -254,4 +218,7 @@ // A SNAPSHOT handler will need to be created to handle the snapshot event | ||
function snapshoter(address, spawnFn) { | ||
spawnFn(address); | ||
return send(address, SNAPSHOT, null, { expectReply: true, timeout: 0 }); | ||
spawnFn(address); | ||
return send(address, SNAPSHOT, null, { | ||
expectReply: true, | ||
timeout: 0 | ||
}); | ||
} | ||
@@ -258,0 +225,0 @@ |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["onflowUtil-actor"] = {})); | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["onflowUtil-actor"] = {})); | ||
})(this, (function (exports) { 'use strict'; | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function __awaiter(thisArg, _arguments, P, generator) { | ||
function adopt(value) { | ||
return value instanceof P ? value : new P(function (resolve) { | ||
resolve(value); | ||
const mailbox = () => { | ||
const queue = []; | ||
let next; | ||
return { | ||
async deliver(msg) { | ||
queue.push(msg); | ||
if (next) { | ||
next(queue.shift()); | ||
next = undefined; | ||
} | ||
}, | ||
receive() { | ||
return new Promise(function innerReceive(resolve) { | ||
const msg = queue.shift(); | ||
if (msg) return resolve(msg); | ||
next = resolve; | ||
}); | ||
} | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
}; | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const queueMicrotask = require("queue-microtask"); | ||
const INIT = "INIT"; | ||
const SUBSCRIBE = "SUBSCRIBE"; | ||
const UNSUBSCRIBE = "UNSUBSCRIBE"; | ||
const UPDATED = "UPDATED"; | ||
const SNAPSHOT = "SNAPSHOT"; | ||
const EXIT = "EXIT"; | ||
const TERMINATE = "TERMINATE"; | ||
const root = typeof self === "object" && self.self === self && self || typeof global === "object" && global.global === global && global || typeof window === "object" && window.window === window && window || { | ||
FCL_REGISTRY: null | ||
}; | ||
root.FCL_REGISTRY = root.FCL_REGISTRY == null ? {} : root.FCL_REGISTRY; | ||
const FCL_REGISTRY = root.FCL_REGISTRY; | ||
let pid = 0b0; | ||
const DEFAULT_TIMEOUT = 5000; | ||
function send(addr, tag, data) { | ||
let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : { | ||
expectReply: false | ||
}; | ||
return new Promise((resolve, reject) => { | ||
const expectReply = opts.expectReply || false; | ||
const timeout = opts.timeout != null ? opts.timeout : DEFAULT_TIMEOUT; | ||
if (expectReply && timeout) { | ||
setTimeout(() => reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), timeout); | ||
} | ||
const payload = { | ||
to: addr, | ||
from: opts.from, | ||
tag, | ||
data, | ||
timeout, | ||
reply: resolve, | ||
reject | ||
}; | ||
try { | ||
if (FCL_REGISTRY[addr]) { | ||
FCL_REGISTRY[addr].mailbox.deliver(payload); | ||
} | ||
function rejected(value) { | ||
try { | ||
step(generator["throw"](value)); | ||
} catch (e) { | ||
reject(e); | ||
if (!expectReply) { | ||
resolve(true); | ||
} | ||
} catch (error) { | ||
console.error("FCL.Actor -- Could Not Deliver Message", payload, FCL_REGISTRY[addr], error); | ||
reject(error); | ||
} | ||
}); | ||
} | ||
const kill = addr => { | ||
delete FCL_REGISTRY[addr]; | ||
}; | ||
const fromHandlers = handlers => async ctx => { | ||
if (typeof handlers[INIT] === "function") await handlers[INIT](ctx); | ||
__loop: while (1) { | ||
const letter = await ctx.receive(); | ||
try { | ||
if (letter.tag === EXIT) { | ||
if (typeof handlers[TERMINATE] === "function") { | ||
await handlers[TERMINATE](ctx, letter, letter.data || {}); | ||
} | ||
break __loop; | ||
} | ||
function step(result) { | ||
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); | ||
} | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
await handlers[letter.tag]?.(ctx, letter, letter.data || {}); | ||
} catch (error) { | ||
console.error(`${ctx.self()} Error`, letter, error); | ||
} finally { | ||
continue __loop; | ||
} | ||
} | ||
const mailbox = () => { | ||
const queue = []; | ||
var next; | ||
return { | ||
deliver(msg) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
queue.push(msg); | ||
if (next) { | ||
next(queue.shift()); | ||
next = undefined; | ||
} | ||
}); | ||
}, | ||
receive() { | ||
return new Promise(function innerReceive(resolve) { | ||
const msg = queue.shift(); | ||
if (msg) | ||
return resolve(msg); | ||
next = resolve; | ||
}); | ||
}, | ||
}; | ||
}; | ||
const parseAddr = addr => { | ||
if (addr == null) { | ||
return String(++pid); | ||
} | ||
return String(addr); | ||
}; | ||
const spawn = function (fnOrHandlers) { | ||
let rawAddr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; | ||
const addr = parseAddr(rawAddr); | ||
if (FCL_REGISTRY[addr] != null) return addr; | ||
FCL_REGISTRY[addr] = { | ||
addr, | ||
mailbox: mailbox(), | ||
subs: new Set(), | ||
kvs: {}, | ||
error: null | ||
}; | ||
const ctx = createCtx(addr); | ||
let fn; | ||
if (typeof fnOrHandlers === "object") fn = fromHandlers(fnOrHandlers);else fn = fnOrHandlers; | ||
queueMicrotask(async () => { | ||
await fn(ctx); | ||
kill(addr); | ||
}); | ||
return addr; | ||
}; | ||
const createCtx = addr => ({ | ||
self: () => addr, | ||
receive: () => FCL_REGISTRY[addr].mailbox.receive(), | ||
send: function (to, tag, data) { | ||
let opts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
if (to == null) return; | ||
opts.from = addr; | ||
return send(to, tag, data, opts); | ||
}, | ||
sendSelf: function (tag, data) { | ||
let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
if (FCL_REGISTRY[addr]) send(addr, tag, data, opts); | ||
}, | ||
broadcast: function (tag, data) { | ||
let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
opts.from = addr; | ||
for (const to of FCL_REGISTRY[addr].subs) send(to, tag, data, opts); | ||
}, | ||
subscribe: sub => sub != null && FCL_REGISTRY[addr].subs.add(sub), | ||
unsubscribe: sub => sub != null && FCL_REGISTRY[addr].subs.delete(sub), | ||
subscriberCount: () => FCL_REGISTRY[addr].subs.size, | ||
hasSubs: () => !!FCL_REGISTRY[addr].subs.size, | ||
put: (key, value) => { | ||
if (key != null) FCL_REGISTRY[addr].kvs[key] = value; | ||
}, | ||
get: function (key) { | ||
let fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; | ||
const value = FCL_REGISTRY[addr].kvs[key]; | ||
return value == null ? fallback : value; | ||
}, | ||
delete: key => { | ||
delete FCL_REGISTRY[addr].kvs[key]; | ||
}, | ||
update: (key, fn) => { | ||
if (key != null) FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]); | ||
}, | ||
keys: () => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs); | ||
}, | ||
all: () => { | ||
return FCL_REGISTRY[addr].kvs; | ||
}, | ||
where: pattern => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { | ||
return pattern.test(key) ? { | ||
...acc, | ||
[key]: FCL_REGISTRY[addr].kvs[key] | ||
} : acc; | ||
}, {}); | ||
}, | ||
merge: function () { | ||
let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; | ||
Object.keys(data).forEach(key => FCL_REGISTRY[addr].kvs[key] = data[key]); | ||
}, | ||
fatalError: error => { | ||
FCL_REGISTRY[addr].error = error; | ||
for (const to of FCL_REGISTRY[addr].subs) send(to, UPDATED); | ||
} | ||
}); | ||
const queueMicrotask = require("queue-microtask"); | ||
const INIT = "INIT"; | ||
const SUBSCRIBE = "SUBSCRIBE"; | ||
const UNSUBSCRIBE = "UNSUBSCRIBE"; | ||
const UPDATED = "UPDATED"; | ||
const SNAPSHOT = "SNAPSHOT"; | ||
const EXIT = "EXIT"; | ||
const TERMINATE = "TERMINATE"; | ||
const root = (typeof self === "object" && self.self === self && self) || | ||
(typeof global === "object" && global.global === global && global) || | ||
(typeof window === "object" && window.window === window && window) || | ||
{ FCL_REGISTRY: null }; | ||
root.FCL_REGISTRY = root.FCL_REGISTRY == null ? {} : root.FCL_REGISTRY; | ||
const FCL_REGISTRY = root.FCL_REGISTRY; | ||
var pid = 0b0; | ||
const DEFAULT_TIMEOUT = 5000; | ||
const send = (addr, tag, data, opts = {}) => new Promise((reply, reject) => { | ||
const expectReply = opts.expectReply || false; | ||
const timeout = opts.timeout != null ? opts.timeout : DEFAULT_TIMEOUT; | ||
if (expectReply && timeout) { | ||
setTimeout(() => reject(new Error(`Timeout: ${timeout}ms passed without a response.`)), timeout); | ||
// Returns an unsubscribe function | ||
// A SUBSCRIBE handler will need to be created to handle the subscription event | ||
// | ||
// [SUBSCRIBE]: (ctx, letter) => { | ||
// ctx.subscribe(letter.from) | ||
// ctx.send(letter.from, UPDATED, ctx.all()) | ||
// } | ||
// | ||
function subscriber(address, spawnFn, callback) { | ||
spawnFn(address); | ||
const self = spawn(async ctx => { | ||
ctx.send(address, SUBSCRIBE); | ||
while (1) { | ||
const letter = await ctx.receive(); | ||
const error = FCL_REGISTRY[address].error; | ||
if (letter.tag === EXIT) { | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
const payload = { | ||
to: addr, | ||
from: opts.from, | ||
tag, | ||
data, | ||
timeout, | ||
reply, | ||
reject, | ||
}; | ||
try { | ||
FCL_REGISTRY[addr] && | ||
FCL_REGISTRY[addr].mailbox.deliver(payload); | ||
if (!expectReply) | ||
reply(true); | ||
if (error) { | ||
callback(null, error); | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
catch (error) { | ||
console.error("FCL.Actor -- Could Not Deliver Message", payload, FCL_REGISTRY[addr], error); | ||
} | ||
callback(letter.data, null); | ||
} | ||
}); | ||
const kill = addr => { | ||
delete FCL_REGISTRY[addr]; | ||
}; | ||
const fromHandlers = (handlers = {}) => (ctx) => __awaiter(void 0, void 0, void 0, function* () { | ||
if (typeof handlers[INIT] === "function") | ||
yield handlers[INIT](ctx); | ||
__loop: while (1) { | ||
const letter = yield ctx.receive(); | ||
try { | ||
if (letter.tag === EXIT) { | ||
if (typeof handlers[TERMINATE] === "function") { | ||
yield handlers[TERMINATE](ctx, letter, letter.data || {}); | ||
} | ||
break __loop; | ||
} | ||
yield handlers[letter.tag](ctx, letter, letter.data || {}); | ||
} | ||
catch (error) { | ||
console.error(`${ctx.self()} Error`, letter, error); | ||
} | ||
finally { | ||
continue __loop; | ||
} | ||
} | ||
return () => send(self, EXIT); | ||
} | ||
// Returns a promise that returns a result | ||
// A SNAPSHOT handler will need to be created to handle the snapshot event | ||
// | ||
// [SNAPSHOT]: (ctx, letter) => { | ||
// letter.reply(ctx.all()) | ||
// } | ||
// | ||
function snapshoter(address, spawnFn) { | ||
spawnFn(address); | ||
return send(address, SNAPSHOT, null, { | ||
expectReply: true, | ||
timeout: 0 | ||
}); | ||
const parseAddr = (addr) => { | ||
if (addr == null) { | ||
return String(++pid); | ||
} | ||
return String(addr); | ||
}; | ||
const spawn = (fn, rawAddr = null) => { | ||
const addr = parseAddr(rawAddr); | ||
if (FCL_REGISTRY[addr] != null) | ||
return addr; | ||
FCL_REGISTRY[addr] = { | ||
addr, | ||
mailbox: mailbox(), | ||
subs: new Set(), | ||
kvs: {}, | ||
error: null, | ||
}; | ||
const ctx = { | ||
self: () => addr, | ||
receive: () => FCL_REGISTRY[addr].mailbox.receive(), | ||
send: (to, tag, data, opts = {}) => { | ||
opts.from = addr; | ||
return send(to, tag, data, opts); | ||
}, | ||
sendSelf: (tag, data, opts) => { | ||
if (FCL_REGISTRY[addr]) | ||
send(addr, tag, data, opts); | ||
}, | ||
broadcast: (tag, data, opts = {}) => { | ||
opts.from = addr; | ||
for (let to of FCL_REGISTRY[addr].subs) | ||
send(to, tag, data, opts); | ||
}, | ||
subscribe: sub => sub != null && FCL_REGISTRY[addr].subs.add(sub), | ||
unsubscribe: sub => sub != null && FCL_REGISTRY[addr].subs.delete(sub), | ||
subscriberCount: () => FCL_REGISTRY[addr].subs.size, | ||
hasSubs: () => !!FCL_REGISTRY[addr].subs.size, | ||
put: (key, value) => { | ||
if (key != null) | ||
FCL_REGISTRY[addr].kvs[key] = value; | ||
}, | ||
get: (key, fallback) => { | ||
const value = FCL_REGISTRY[addr].kvs[key]; | ||
return value == null ? fallback : value; | ||
}, | ||
delete: key => { | ||
delete FCL_REGISTRY[addr].kvs[key]; | ||
}, | ||
update: (key, fn) => { | ||
if (key != null) | ||
FCL_REGISTRY[addr].kvs[key] = fn(FCL_REGISTRY[addr].kvs[key]); | ||
}, | ||
keys: () => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs); | ||
}, | ||
all: () => { | ||
return FCL_REGISTRY[addr].kvs; | ||
}, | ||
where: pattern => { | ||
return Object.keys(FCL_REGISTRY[addr].kvs).reduce((acc, key) => { | ||
return pattern.test(key) | ||
? Object.assign(Object.assign({}, acc), { [key]: FCL_REGISTRY[addr].kvs[key] }) : acc; | ||
}, {}); | ||
}, | ||
merge: (data = {}) => { | ||
Object.keys(data).forEach(key => (FCL_REGISTRY[addr].kvs[key] = data[key])); | ||
}, | ||
fatalError: error => { | ||
FCL_REGISTRY[addr].error = error; | ||
for (let to of FCL_REGISTRY[addr].subs) | ||
send(to, UPDATED); | ||
}, | ||
}; | ||
if (typeof fn === "object") | ||
fn = fromHandlers(fn); | ||
queueMicrotask(() => __awaiter(void 0, void 0, void 0, function* () { | ||
yield fn(ctx); | ||
kill(addr); | ||
})); | ||
return addr; | ||
}; | ||
// Returns an unsubscribe function | ||
// A SUBSCRIBE handler will need to be created to handle the subscription event | ||
// | ||
// [SUBSCRIBE]: (ctx, letter) => { | ||
// ctx.subscribe(letter.from) | ||
// ctx.send(letter.from, UPDATED, ctx.all()) | ||
// } | ||
// | ||
function subscriber(address, spawnFn, callback) { | ||
spawnFn(address); | ||
const EXIT = "@EXIT"; | ||
const self = spawn((ctx) => __awaiter(this, void 0, void 0, function* () { | ||
ctx.send(address, SUBSCRIBE); | ||
while (1) { | ||
const letter = yield ctx.receive(); | ||
const error = FCL_REGISTRY[address].error; | ||
if (letter.tag === EXIT) { | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
if (error) { | ||
callback(null, error); | ||
ctx.send(address, UNSUBSCRIBE); | ||
return; | ||
} | ||
callback(letter.data, null); | ||
} | ||
})); | ||
return () => send(self, EXIT); | ||
} | ||
// Returns a promise that returns a result | ||
// A SNAPSHOT handler will need to be created to handle the snapshot event | ||
// | ||
// [SNAPSHOT]: (ctx, letter) => { | ||
// letter.reply(ctx.all()) | ||
// } | ||
// | ||
function snapshoter(address, spawnFn) { | ||
spawnFn(address); | ||
return send(address, SNAPSHOT, null, { expectReply: true, timeout: 0 }); | ||
} | ||
} | ||
exports.EXIT = EXIT; | ||
exports.INIT = INIT; | ||
exports.SNAPSHOT = SNAPSHOT; | ||
exports.SUBSCRIBE = SUBSCRIBE; | ||
exports.TERMINATE = TERMINATE; | ||
exports.UNSUBSCRIBE = UNSUBSCRIBE; | ||
exports.UPDATED = UPDATED; | ||
exports.kill = kill; | ||
exports.send = send; | ||
exports.snapshoter = snapshoter; | ||
exports.spawn = spawn; | ||
exports.subscriber = subscriber; | ||
exports.EXIT = EXIT; | ||
exports.INIT = INIT; | ||
exports.SNAPSHOT = SNAPSHOT; | ||
exports.SUBSCRIBE = SUBSCRIBE; | ||
exports.TERMINATE = TERMINATE; | ||
exports.UNSUBSCRIBE = UNSUBSCRIBE; | ||
exports.UPDATED = UPDATED; | ||
exports.kill = kill; | ||
exports.send = send; | ||
exports.snapshoter = snapshoter; | ||
exports.spawn = spawn; | ||
exports.subscriber = subscriber; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); | ||
//# sourceMappingURL=actor.umd.js.map |
{ | ||
"name": "@onflow/util-actor", | ||
"version": "1.3.0-alpha.0", | ||
"version": "1.3.0", | ||
"description": "A mechanism for forcing order/transitions of scoped async state", | ||
@@ -16,3 +16,9 @@ "license": "Apache-2.0", | ||
"devDependencies": { | ||
"@onflow/fcl-bundle": "^1.4.0-alpha.0", | ||
"@babel/preset-typescript": "^7.22.5", | ||
"@onflow/fcl-bundle": "^1.4.0", | ||
"@types/jest": "^29.5.3", | ||
"@typescript-eslint/eslint-plugin": "^6.4.0", | ||
"@typescript-eslint/parser": "^6.4.0", | ||
"eslint": "^8.47.0", | ||
"eslint-plugin-jsdoc": "^46.4.6", | ||
"jest": "^29.5.0" | ||
@@ -28,2 +34,3 @@ }, | ||
"unpkg": "dist/actor.umd.js", | ||
"types": "dist/index.d.ts", | ||
"scripts": { | ||
@@ -34,4 +41,5 @@ "prepublishOnly": "npm test && npm run build", | ||
"test:watch": "jest --watch", | ||
"start": "fcl-bundle --watch" | ||
"start": "fcl-bundle --watch", | ||
"lint": "eslint src --ext .ts" | ||
} | ||
} |
@@ -9,4 +9,4 @@ { | ||
// next to the .js files | ||
"outDir": "types", | ||
"outDir": "types" | ||
} | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
18
830
0
0
92507
8