Twine
A command line Twitter client (CLI)
Project Directory Structure
- /bin: Options parsing, Help text, Command execution
- /commands: User input, Console output, Sequence of steps
- /lib: Store/load credentials, Make API calls, Utilities
Twine in Three Steps
- Consumer API Key and Secret
- Twitter Account Token and Secret
- Specific Twitter API Call
Handling Errors
Workflow: /bin --> /commands --> /lib Errors: /lib --> /commands --> /bin
Exiting Node.js Correctly on Error
// This is an example of what NOT to do:
if (someConditionNotMet()) {
printUsageToStdout();
process.exit(1);
}
// How to properly set the exit code while letting
// the process exit gracefully
if (someConditionNotMet()) {
printUsageToStdout();
process.exitCode = 1;
}
Environment Variables
-
Consumer API Key and Secret:
- TWINE_CONSUMER_KEY
- TWINE_CONSUMER_SECRET
-
Twitter Account Token and Secret:
- TWINE_ACCOUNT_KEY
- TWINE_ACCOUNT_SECRET
Setting Environment Variables
set TWINE_CONSUMER_KEY=key
set TWINE_CONSUMER_SECRET=secret
Note:
- Standard In: process.stdin
- Standard Out: process.stdout
- Standard Error: process.stderr
process.stdin.pipe(process.stdout)
Support params both on the command line and read from stdin
- A single parameter
twine [some command] param
echo "param" | twine [some command]
- Multiple parameters
twine [some command] param1, param2
twine [some command] < param-file.txt
param-generator | twine [some command]
Examples:
param-generator | twine lookup users
- process.stdin
- split on newline
- batches of 100
- Twitter API(s)
- flatten
- JSON stringify
- process.stdout
twine lookup users user1,user2
- CLI params
- array
- batches of 100
- Twitter API(s)
- flatten
- JSON stringify
- process.stdout
Several New Stream-related Modules
- split2
- parallel-transform
- through2
- JSONStream
- from2-array
- promise-streams
Example
users.txt
user1
user2
cmd
type users.txt | twine lookup users
JQ (find out more about this)
choco install jq
Publish our command line app!
Publishing to npm
Two simple commands:
- npm login
- npm publish
However we need a scoped package: @miguelleonmarti/twine (miguelleonmarti is the scope) Why using scoped packages in npm? Due to private packages, grouping, namespacing
Executing Binaries Directly with npx
- Typical module usage:
npm install -g @miguelleonmarti/twine
twine lookup users miguelleonmarti
- With npx:
npx @miguelleonmarti/twine lookup users miguelleonmarti