Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Plant the "zeed" for your next Typescript project and let it grow with this useful lib, providing basic functionalities handy in most projects.
Get started like this:
npm i zeed
Powerful logging for browser and terminal.
import { Logger } from "zeed"
const log = Logger("demo")
log("Hello World")
log.info("Info")
log.warn("Warning")
log.error("Error")
Sample output on a terminal:
Sample output in Safari:
By default, the most appropriate log handlers are activated. By default, a colorful output is applied for better orientation. Each line has trace info to allow direct jumps back into the code where the log has been issued. Logs can easily be filtered by level.
By default logs are muted! Show the logs by applying filters. On the browser enter this an the web inspector console:
localStorage.zeed = "*"
On node set an environment variable like this
ZEED=* node myapp.js
Instead of the *
more advanced filters can be applied compatible to the well known debug syntax. Instead of ZEED
variable you may also use DEBUG
. Please note that ZEED
will supersede DEBUG
.
Filtering by level is possible by setting ZEED_LEVEL
, LEVEL
or DEBUG_LEVEL
to set the filter e.g. ZEED_LEVEL=info
to hide debug logs.
To also write logs to a file you may set ZEED_LOG
to the file path. All levels will be written to the file, no matter what other filtering has been chosen.
It is also possible to set (Logger.setHandlers([handlers])
) or add (Logger.registerHandler(handler)
) new log handlers. You can choose from:
LoggerConsoleHandler(opt)
: Plain basic output via console
(default) - (muted by default)LoggerBrowserHandler(opt)
: Colorful log entries - (muted by default)LoggerNodeHandler(opt)
: Colorful logging for node.js - (muted by default)LoggerFileHandler(path, opt)
: Write to fileopt
are general options like level
for the log level or filter
for custom filtering (see below). But it can also hold individual settings specific for a log handler.
Examples for custom loggers are breadcrumb tracking in Sentry.io or showing notifications to users on errors in a UI.
You can use Logger
in submodules and Zeed will make sure all logging goes through the same handlers, no matter what bundler is used. With Logger.setLock(true)
any further changes to handlers, factories and log levels can be forbidden, to ensure no conflicting settings with submodules. You should set up the Logging very early in your main project before loading submodules.
Loggers can be extended. const newLog = log.extend("demo")
will append :demo
to the current namespace.
Zeed tries to identify the origin in the source code of the log being issued. To get appropriate results in Node environments consider using the Source Map option:
node --enable-source-maps myapp.js
Alternative logging solutions: debug, tslog, consola, pino or winston to name just a few.
Wait for an event via on
or addEventListener
, useful in unit tests.
await waitOn(emitter, "action", 1000) // 1000 is optional timeout in ms
Wait for milliseconds.
await sleep(1000) // wait 1s
Throw an error after timeout of 1 second.
await timeout(asynFn, 1000)
If a value is not yet a Promise, wrap it to become one.
await promisify(returnValue)
Get a random unique ID of fixed length of 22 chars (these are 16 bytes = 128 bit, encoded in Base62). According to Nano ID Collision Calculator: "~597 billion years needed, in order to have a 1% probability of at least one collision."
const id1 = uuid() // base62 encoded => 22 chars
const id2 = uuidB32() // base32 encoded => 26 chars
Get an incremental unique ID for current process with named groups, great for debugging.
uname("something") // => 'something-0'
uname("other") // => 'other-0'
uname("something") // => 'something-1'
Sortable unique ID inspired by go-uuid. 6 bytes encode time and 10 bytes are random. String is Base62 encoded. Date can be extracted from the ID.
const shortSortableId = suid() // = '000iMi10bt6YK8buKlYPsd'
suidDate(shortSortableId) // = 2021-07-03T22:42:40.727Z
shortSortableId < suid() // = true
Overview of available IDs:
uuid
uuidB32
suid
quid
: Quick ID great for UI purposes of patter id-1
, id-2
, ...uuidv4
: The classic UID like a7755f8d-ef6f-45e9-8db3-d29347a4a2a1
Typed and async emitter:
interface MyEvents {
inc(count: number): number
}
let counter = 0
const e = new Emitter() < MyEvents > e.on("inc", async (count) => counter + 1)
await e.emit("inc", 1) // counter === 1
It is also possible to alternatively use a Proxy called .call
that makes nice dynamic function calls of the events:
await e.call.inc(1)
We can also alternatively declare the listeners this way:
e.onCall({
async inc(count: number): number {
return counter + 1
},
})
You can also use a global emitter that will be available even over module boundaries:
declare global {
interface ZeedGlobalEmitter {
test(x: string): void
}
}
getGlobalEmitter().emit("test", "Hello World") // or
getGlobalEmitter().call.test("Hello World")
Communicating to servers or other remote parts through messages as if they were methods on a local object in a type safe way:
let m = useMessageHub({ cannel }).send<MyMessages>()
m.echo({ hello: "world" })
But there is much more basic infrastructure for communication available in
zeed
. More details at src/common/msg/README.md
A conflict free sorting algorithm with minimal data changes. Just extend an object from SortableItem
, which will provide an additional property of type number called sort_weight
.
interface Row extends SortedItem {
id: string
title: string
}
let rows: Row[] = []
const getSortedRows = () => sortedItems(rows)
Use startSortWeight
, endSortWeight
and moveSortWeight
to get initial values for new entries or manipulate existing ones.
Essays:
The implementation in Zeed is pretty straight forward, but there are also more sophisticated approaches available as alternatives:
- Implementing Fractional Indexing
- fractional-indexing - npm module
Integration of the base-x code to support encoding and decoding to any alphabet, but especially base2, base16 (hex), base32, base62, base64. Human-readable yet efficient encoding of binary data.
const sample = new UInt8Array([1, 2, 3])
const { encode, decode } = useBase(62)
decode(encode(sample)) === sample // = true
Handle complex objects.
deepEqual({ a: { b: 1 } }, { a: { b: 2 } }) // false
deepMerge({ a: { b: 1 } }, { c: 3, a: { d: 4 } }) // {a:{b:1, d:4}, c:4}
useDisposer
will simplify cleaning up objects. You just need to track
a function or and object with dispose
method to be called for cleanup. This can also be nested. A simple example is a timer:
const disposableTimer = () => {
const timout = setTimeout(() => console.log('hello world')), 1000)
return () => clearTimeout(timeout)
}
let disposer = useDisposer()
const obj = disposableTimer()
disposer.track(obj)
// or
const untrackTimer = disposer.track(disposableTimer())
// then later one of these
disposer.untrack(obj) // dispose single object
untrackTimer() // dispose single object by return value of .track
disposer.dispose() // will dispose all tracked elements
You can also untrack
single entries. Entries are untracked LIFO. Disposers can also return a Promise and therefore await
async disposals.
The disposer itself is also a call to dispose i.e. for convenience you can add it to objects and provide dispose
easily like this:
class DisposeExample {
// the trick is to assign to member `dispose`, will be both
// the destructor and the registration point for disposables
dispose = useDisposer()
constructor() {
this.dispose.track(disposableTimer())
}
}
let obj = new DisposeExample()
// ...
obj.dispose()
Related projects:
Recommended other collections of common JS utils:
Code integrated from other sources:
FAQs
🌱 Simple foundation library
The npm package zeed receives a total of 897 weekly downloads. As such, zeed popularity was classified as not popular.
We found that zeed demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.