
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Fork of co that describes asynchronous tasks as data.
Instead of a generator activating side-effects it instead yields data objects
that represent how side-effects ought to be executed. This pushes side-effects
to co
instead of the application itself.
Effectively this makes testing side-effects as easy as checking that each step in a generator returns the proper data structure.
This library was inspired by redux-saga
and re-frame. Whenever I left the world
of redux-saga
and wanted to test my async/await/generator functions it would require
mocking/intercepting HTTP requests which is a terrible developer experience after
coming from describing side-effects as data.
Effects as Data talk by Richard Feldman
cosed
will work exactly like co
with the exception that it can handle a new
yielded value type: effect objects. An effect object looks something like this:
{
"type": "CALL",
"fn": [function],
"args": ["list", "of", "arguments"]
}
task
is an alias for the co
function.
import { call, task } from 'cosed';
function* fetchBin() {
const resp = yield call(fetch, 'http://httpbin.org/get');
// sending an array makes `call` activate the function `json` on `resp` object
// this is required because of the way fetch uses context to determine if the Body
// promise has been used already.
const data = yield call([resp, 'json']);
return { ...data, extra: 'stuff' };
}
task(fetchBin)
.then(console.log)
.catch(console.error);
Check out the API section for more effects.
Taking the previous example, this is how you would test it:
const test = require('tape');
test('test fetchBin', (t) => {
const gen = fetchBin();
t.deepEqual(
gen.next().value,
call(fetch, 'http://httpbin.org/get'),
'should make http request',
);
const respValue = { resp: 'value', json: 'hi' };
t.deepEqual(
gen.next(respValue).value,
call([respValue, 'json']),
'should get json from response',
);
const last = gen.next({ data: 'value' });
t.ok(last.done, 'generator should finish');
t.deepEqual(
last.value,
{ data: 'value', extra: 'stuff' },
'should return data',
);
});
Using a little helper library called gen-tester we can make this even easier.
const { genTester, yields } = require('gen-tester');
test('test fetchBin', (t) => {
t.plan(1);
const respValue = { resp: 'value', json: 'hi' };
const returnValue = { data: 'value', extra: 'stuff' };
const tester = genTester(genCall);
const { actual, expect } = tester(
yields(
call(fetch, 'http://httpbin.org/get'),
respValue, // the result value of `resp` in the generator
),
yields(
call([respValue, 'json']),
{ data: 'value' }, // the result value of `data` in the generator
),
returnValue,
);
t.deepEqual(actual, expected);
});
Take a close look here. When the generator function does not get called by task
all it does is return JSON at every yield
. This is the brilliance of describing
side-effects as data: we can test our generator function synchronously, without
needing any HTTP interceptors or mocking functions! So even though at every yield
this library will make asynchronous calls, for testing, we can step through the
generator one step after another and make sure the yield makes the correct call.
Manages async flow for a generator. This is an alias to the co
function.
const { task, call } = require('cosed');
const fetch = require('node-fetch');
function* example() {
yield call(fetch, 'http://google.com')
return 'hi';
}
task(example);
Uses Promise.all
to execute effects in parallel. Could be an array of effects
or an object of effects.
const { task, call, all } = require('cosed');
const fetch = require('node-fetch');
function* example() {
const resp = yield all([
call(fetch, 'http://google.com'),
call(fetch, 'http://something-else.com'),
]);
const data = yield all(resp.map((r) => call([r, 'json'])));
return data;
}
task(example);
Spawns an effect without the generator waiting for that effect to finish.
const { task, spawn } = require('cosed');
const fetch = require('node-fetch');
function effect() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
console.log('ACTIVATE');
}, 5000);
});
}
function* example() {
yield spawn(effect);
console.log('COOL');
}
task(example);
// COOL
// ... five seconds later
// ACTIVATE
This will sleep
the generator for the designated amount of time.
const { task, delay } = require('cosed');
function* example() {
console.log('INIT')
yield delay(1000);
console.log('END');
}
task(example);
// INIT
// ... one second later
// END
This is what creates task
. This allows end-developers to build their own
effect middleware. When using middleware it must return a promise, something that co
understands how to handle, and
to allow other middleware to handle the effect as well, you
must return next(effect)
;
const { factory } = require('cosed');
const ERROR = 'ERROR';
const error = (msg) => ({ type: ERROR, msg });
const middleware = (next) => (effect) => {
if (effect.type === ERROR) {
return Promise.reject(effect.msg);
}
return next(effect);
};
function* example() {
yield error('SOMETHING HAPPENED');
}
const customTask = factory(middleware);
customTask(example).catch((err) => {
console.log(`ERROR: ${err}`);
});
// ERROR: SOMETHING HAPPENED
FAQs
co side effects as data
The npm package cosed receives a total of 1 weekly downloads. As such, cosed popularity was classified as not popular.
We found that cosed demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.