npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

neopipe

v0.1.11

Published

Pipe stuff to Neo4j

Downloads

16

Readme

neopipe

A simple(ish) tool to pipe stuff into Neo4j.

Installing

npm install -g neopipe

Changelog

0.1.9

  • Reworked streaming mode to resolve race conditions.
  • Added --stream-flush N argument, to force flushing of streamed queries every N expressions. This is required for fast-running input, such as file cat, which would otherwise hog the event loop.

0.1.8

  • Fixed race condition for large end output.
  • Started reworking grammar, among other things to support property operations with default values: FOO:1 KNOWS (weight(0)+=0.2) BAR:2

0.1.7

  • Started changelog.
  • Removed -p and -i arguments to piping and interpolated output. Replaced with -o option.
  • Added -o option to output JSON from both raw Cypher queries and from individual inserts.
  • Streamed inserts (--stream) will yield write JSON to stdout on the fly. Can be piped to jq (https://stedolan.github.io/jq/) or whatever.
  • The end query mode can now be used to make rar cypher queries, if the main expression is skipped. See examples in --help / README.

Usage

Note: This file (and --help) will be the only updated sources on how to use Neopipe. Any example video can and will be outdated.

First you need Neo4j running locally with no password. Yes, that should be fixed in the future. Yes, it should be configurable from the command line.

For now, if you don't have Neo4j, getting the required stuff up and running with Docker will look something like:

mkdir -p neo4j/data
docker run \
    --publish=7474:7474 --publish=7687:7687 \
    --volume=$PWD/neo4j/data:/data \
    --env=NEO4J_AUTH=none \
    neo4j

.. at which point a web interface should be available at http://localhost:7474/. Also any data for that specific Neo4j instance will be put in the current folder's newly created subfolder neo4j/. If you're coming back to a pre-existing forensic project directory, you'll find that you can continue where you left off. Neat and contained.

See also this thread for examples I slapped together while feverishly developing the tool: https://twitter.com/einaros/status/1029385058078076928

As for how to use neopipe yourseelf: Here's the output from neopipe -h:

Usage: neopipe [options]

Pipe stuff to Neo4j

Options:

	-V, --version                output the version number
	-s, --separator <separator>  Custom field separator for stdin interpolation. (default:  )
	-q, --quote <quote>          Custom quote char for stdin interpolation. (default: ")
	-j, --jobs <jobs>            Limit number of concurrent jobs. (default: 8)
	-o, --output <output type>   Output type:
		| none: No output
		| pipe: Pipe input to output
		| interpolated: Print completed expressions
		| json: Return JSON output from Neo4j inserts
		| (default: No output)
	-t, --testonly               Simulate insertion.
	-v, --verbose                Increase verbosity.
	-e, --end-query <query>      Raw CYPHER query to run after the sequence has finished. (default: )
	-r, --show-results           Write end query results to stdout (as JSON).
	--neohost <host>             Neo4j hostname. (default: localhost)
	--neouser <user>             Neo4j username. (default: null)
	--neopasswd <passwd>         Neo4j password. (default: null)
	--stream                     Stream insertion to Neo4j. Disable transaction logic, that is.
  --stream-flush <count>       (if --stream) Flush stream buffer every N expressions. Useful for fast-running pipes that hog the queue. 0 to disable. (default: 0)
	--shell <shell>              Shell for interpolated execution. (default: /bin/sh)
	-h, --help                   output usage information

Examples

Adding entities, properties and connections:

Add entity 'Dog' with id='Fido', set age=10:

$ neopipe 'Dog:Fido (age:10)'

Add entity 'Dog' with id='Fido Boy', set age='very old', add connection 'OWNED_BY' to Man with id='Roy':

$ neopipe 'Dog:"Fido Boy" (age:"very old") OWNED_BY Man:Roy'

Add property 'Likes dog'='yes' to existing entity Man with id='Roy':

$ neopipe 'Man:Roy ("Likes dog":yes)'

Process lines from standard input

Add Thing with id='foo' connected via 'is_not_a' to Thing with id 'baz':

$ echo foo bar baz | neopipe 'Thing:{1} is_not_a Thing:{3}'

Add the same things as above, and pass all stdin along to the next piped command:

$ echo foo bar baz | neopipe -o pipe 'Thing:{1} is_not_a Thing:{3}' | something_else.sh

Find files in a folder hierarchy, add FILE entities with the filenames as id, set a property 'size' on the FILE with the result of a shell executed command (stat) with the filename interpolated ({1}), add a connection to a HASH with id set to the result of another command (md5):

$ find node_modules -type f | neopipe 'FILE:"{1}" (size:"{!stat -f %z {1}}") HAS HASH:{!md5 -q {1}}'

Simulate adding an entity 'a' with id='az', which is the result of splitting the third entry three times with different delimiters. Show verbose output (repeat 'v' multiple times for more verbose):

$ echo 'foo bar "b-az,bax"' | neopipe -vt 'a:"{3/,:1/\-:2}"'

As above, but make the entity id a sha1 hash of the interpolated value:

$ echo 'foo bar "b-az,bax"' | neopipe -vt 'a:"{#3/,:1/\\-:2}"'

As above, but make the entity id a sha1 hash of the uppercase'd interpolated value:

$ echo 'foo bar "b-az,bax"' | neopipe -vt 'a:"{##3/,:1/\\-:2}"'

Add an entity 'a', but try to interpolate id from a missing field, so fall back to a default value 'ugh':

$ echo 'foo bar "b-az,bax"' | neopipe 'a:"{4?ugh}"'

Add an entity 'a', but try to interpolate id from a missing field, fall back to the result of 'uptime':

$ echo 'foo bar "b-az,bax"' | neopipe 'a:"{4?{!uptime}}"'

Executing raw Cypher queries:

Detach and delete all entities:

$ neopipe -e 'MATCH (n) DETACH DELETE (n)'

Use the JSON output mode, no input expression and an end query to extract existing entity relationships (based on the hamming distance example below) and parse the output with jq (https://stedolan.github.io/jq/):

$ neopipe -o json -e 'MATCH p=()-[r:LOOKS_LIKE]->() RETURN p' | jq .

Other / advanced examples:

Add entities for all images in a hierarchy, calculating perceptual hashes for each one, storing bitwise pHash as an entity property, finally run raw Cypher query to find images with low Hamming distance, based on the hashes, and create relationships between them:

$ find *.jpg | neopipe -v 'Image:"{}" (phash:{!imagehash -b "{}"})' -r -e '
MATCH (a:Image)
MATCH (b:Image)
WITH a, b, apoc.text.hammingDistance(a.phash, b.phash) AS c
WHERE id(a) < id(b) AND c <= 10
MERGE (a)-[r:LOOKS_LIKE]-(b)
SET r.distance = c
RETURN a, b, r'

Re: above example, see also https://vimeo.com/285498808/8e5eb49ffd and find the simple imagehash tool at https://gist.github.com/einaros/a9f4d0d5f0f7f69cb70b0f005fc9ae29.

License

ISC

Author

Einar Otto Stangvik (https://twitter.com/einaros)