├── .gitignore ├── package.json ├── readme.md ├── index.js ├── yarn.lock └── article.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NoteToSelf", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "bin": { 10 | "notetoself": "./index.js" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "dependencies": { 16 | "chalk": "^1.1.3", 17 | "cosmicjs": "^2.39.0", 18 | "inquirer": "^3.0.6", 19 | "meteor-random": "^0.0.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Note to Self 2 | ![Note App](https://cosmicjs.com/uploads/58fb06b0-2dbb-11e7-826f-f34de0199ac5-note-to-self.png) 3 | ## Getting Started 4 | 1. Go to [Cosmic JS](https://cosmicjs.com) and create a new Bucket to store your notes. 5 | 2. Download the Note to Self repo: 6 | ``` 7 | git clone https://github.com/cosmicjs/notetoself 8 | cd notetoself 9 | yarn 10 | ``` 11 | 12 | ## Starting the app 13 | 1. Edit the config part of `index.js` to point to your Cosmic JS Bucket Slug 14 | ```javascript 15 | config.bucket = { 16 | slug: 'your-bucket-slug', // add your slug here 17 | read_key: '', // add read key if added to Cosmic JS > Your Bucket > Settings 18 | write_key: '' // add write key if added to Cosmic JS > Your Bucket > Settings 19 | } 20 | ``` 21 | 2. Install the app globally 22 | ``` 23 | npm install -g 24 | ``` 25 | 3. Now you can view / create / edit / delete notes with the following command: 26 | ``` 27 | notetoself 28 | ``` 29 | Your notes are now available to any device and any programming language through the [Cosmic JS API](https://cosmicjs.com). 30 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const chalk = require('chalk'); 3 | var inquirer = require('inquirer'); 4 | const Random = require('meteor-random'); 5 | 6 | 7 | var config = {}; 8 | config.bucket = { 9 | slug: process.env.COSMIC_BUCKET, 10 | read_key: '', 11 | write_key: '' 12 | } 13 | const Cosmic = require('cosmicjs'); 14 | 15 | const MainMenu = () => { 16 | if (!config.bucket.slug) { 17 | console.log(chalk.red('ERROR: You must start the app with COSMIC_BUCKET=your-bucket-slug environment variable before running this app.')) 18 | } 19 | inquirer.prompt( 20 | { 21 | type: 'list', 22 | name: 'mainMenu', 23 | message: 'Main Menu', 24 | choices: [ 25 | 'New Note', 26 | 'View Notes', 27 | new inquirer.Separator(), 28 | 'Exit' 29 | ] 30 | } 31 | ).then((answers)=>{ 32 | if(answers.mainMenu === "New Note"){ 33 | NewNote() 34 | } else if(answers.mainMenu === "View Notes"){ 35 | ViewNotes() 36 | } else { 37 | process.exit() 38 | } 39 | }) 40 | } 41 | 42 | MainMenu() //Creates the main menu and starts the application 43 | 44 | const NewNote = () => { 45 | if (!config.bucket.slug) { 46 | MainMenu() 47 | return 48 | } 49 | var question = { 50 | type: 'input', 51 | name: 'note_text', 52 | message: 'Note' 53 | } 54 | inquirer.prompt(question).then((answers) => { 55 | var params = { 56 | write_key: config.bucket.write_key, 57 | type_slug: 'notes', 58 | slug: Random.id().toLowerCase(), 59 | title: answers.note_text, 60 | content: '' 61 | } 62 | if(answers.note_text === ''){ 63 | console.log(chalk.red("You cannot add an empty note")) 64 | MainMenu() 65 | return; 66 | } 67 | Cosmic.addObject(config, params, (error, response) =>{ 68 | if(response.object){ 69 | console.log(chalk.green("\u2713" + " Success")) 70 | } 71 | if(error){ 72 | console.log(error) 73 | } 74 | MainMenu() 75 | }) 76 | }) 77 | } 78 | 79 | const ViewNotes = () => { 80 | if (!config.bucket.slug) { 81 | MainMenu() 82 | return 83 | } 84 | var params = { 85 | type_slug: 'notes', 86 | limit: 10, 87 | skip: 0 88 | }; 89 | 90 | Cosmic.getObjectType(config, params, (error, response)=>{ //fetches all notes 91 | var notes = [] 92 | var noteText = [chalk.yellow("Return")] 93 | if(error || response.total === undefined){ 94 | console.log(chalk.red("No notes found.")) 95 | MainMenu() 96 | return; 97 | } 98 | sortedresponse = response.objects.all.sort((a,b)=>{ 99 | return new Date(b.created) - new Date(a.created) 100 | }) 101 | const amount = response.objects.all.length 102 | sortedresponse.map((note)=>{ 103 | var newnote = { 104 | name: note.title, 105 | slug: note.slug 106 | } 107 | noteText.push(chalk.blue(note.title) + chalk.hidden('slug - '+note.slug + ' | ') ) 108 | notes.push(newnote) 109 | if(notes.length === amount){ 110 | inquirer.prompt( 111 | { 112 | type: 'list', 113 | name: 'allnotes', 114 | message: 'All Notes:', 115 | choices: noteText 116 | }).then((answers)=>{ 117 | if(answers.allnotes === "\u001b[33mReturn\u001b[39m"){ 118 | MainMenu() 119 | return; 120 | } 121 | var regexSearch = /(\w{17})/ 122 | var newvalue = answers.allnotes.match(regexSearch) 123 | Cosmic.getObject(config, {slug: newvalue[0]}, (error, response)=>{ 124 | inquirer.prompt({ 125 | type: 'expand', 126 | message: chalk.blue(response.object.title), 127 | name: 'morecontext', 128 | choices: [ 129 | { 130 | key: 'e', 131 | name: 'Edit', 132 | value: 'edit' 133 | }, 134 | { 135 | key: 'd', 136 | name: 'Delete', 137 | value: 'delete' 138 | }, 139 | { 140 | key: 'l', 141 | name: 'Leave', 142 | value: 'leave' 143 | } 144 | ]}).then((answers)=>{ 145 | if(answers.morecontext === 'edit'){ 146 | inquirer.prompt( 147 | { 148 | type: 'input', 149 | name: 'newText', 150 | message: 'New Text:' 151 | }).then((answers)=>{ 152 | var params = { 153 | write_key: config.bucket.write_key, 154 | slug: response.object.slug, 155 | type_slug: 'notes', 156 | title: answers.newText, 157 | content: '' 158 | } 159 | Cosmic.editObject(config, params, (error, response)=>{ 160 | if(response.object){ 161 | console.log(chalk.green("\u2713" + " Success")) 162 | } 163 | MainMenu() 164 | }) 165 | }) 166 | 167 | } else if(answers.morecontext === 'delete'){ 168 | var params = { 169 | write_key: config.bucket.write_key, 170 | slug: response.object.slug 171 | } 172 | Cosmic.deleteObject(config, params, (error, response)=>{ 173 | if(error){ 174 | console.log(error) 175 | } 176 | if(response.object){ 177 | console.log(chalk.green("\u2713" + " Success")) 178 | } 179 | MainMenu(); 180 | }); 181 | } else { 182 | MainMenu(); 183 | } 184 | }) 185 | }) 186 | }) 187 | } 188 | }) 189 | }) 190 | } -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | ansi-escapes@^1.1.0: 4 | version "1.4.0" 5 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 6 | 7 | ansi-regex@^2.0.0: 8 | version "2.1.1" 9 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 10 | 11 | ansi-styles@^2.2.1: 12 | version "2.2.1" 13 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 14 | 15 | chalk@^1.0.0, chalk@^1.1.3: 16 | version "1.1.3" 17 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 18 | dependencies: 19 | ansi-styles "^2.2.1" 20 | escape-string-regexp "^1.0.2" 21 | has-ansi "^2.0.0" 22 | strip-ansi "^3.0.0" 23 | supports-color "^2.0.0" 24 | 25 | cli-cursor@^2.1.0: 26 | version "2.1.0" 27 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 28 | dependencies: 29 | restore-cursor "^2.0.0" 30 | 31 | cli-width@^2.0.0: 32 | version "2.1.0" 33 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" 34 | 35 | cosmicjs@^2.39.0: 36 | version "2.39.0" 37 | resolved "https://registry.yarnpkg.com/cosmicjs/-/cosmicjs-2.39.0.tgz#8efbbd019895172cc471f456c6d2b22063d586b2" 38 | dependencies: 39 | es6-promise "^3.0.2" 40 | isomorphic-fetch "^2.2.0" 41 | lodash "^4.17.4" 42 | 43 | crypto@0.0.3: 44 | version "0.0.3" 45 | resolved "https://registry.yarnpkg.com/crypto/-/crypto-0.0.3.tgz#470a81b86be4c5ee17acc8207a1f5315ae20dbb0" 46 | 47 | encoding@^0.1.11: 48 | version "0.1.12" 49 | resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" 50 | dependencies: 51 | iconv-lite "~0.4.13" 52 | 53 | es6-promise@^3.0.2: 54 | version "3.3.1" 55 | resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613" 56 | 57 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 58 | version "1.0.5" 59 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 60 | 61 | external-editor@^2.0.1: 62 | version "2.0.1" 63 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" 64 | dependencies: 65 | tmp "^0.0.31" 66 | 67 | figures@^2.0.0: 68 | version "2.0.0" 69 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 70 | dependencies: 71 | escape-string-regexp "^1.0.5" 72 | 73 | has-ansi@^2.0.0: 74 | version "2.0.0" 75 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 76 | dependencies: 77 | ansi-regex "^2.0.0" 78 | 79 | iconv-lite@~0.4.13: 80 | version "0.4.15" 81 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" 82 | 83 | inquirer@^3.0.6: 84 | version "3.0.6" 85 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" 86 | dependencies: 87 | ansi-escapes "^1.1.0" 88 | chalk "^1.0.0" 89 | cli-cursor "^2.1.0" 90 | cli-width "^2.0.0" 91 | external-editor "^2.0.1" 92 | figures "^2.0.0" 93 | lodash "^4.3.0" 94 | mute-stream "0.0.7" 95 | run-async "^2.2.0" 96 | rx "^4.1.0" 97 | string-width "^2.0.0" 98 | strip-ansi "^3.0.0" 99 | through "^2.3.6" 100 | 101 | is-fullwidth-code-point@^2.0.0: 102 | version "2.0.0" 103 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 104 | 105 | is-promise@^2.1.0: 106 | version "2.1.0" 107 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 108 | 109 | is-stream@^1.0.1: 110 | version "1.1.0" 111 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 112 | 113 | isomorphic-fetch@^2.2.0: 114 | version "2.2.1" 115 | resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" 116 | dependencies: 117 | node-fetch "^1.0.1" 118 | whatwg-fetch ">=0.10.0" 119 | 120 | lodash@^4.17.4, lodash@^4.3.0: 121 | version "4.17.4" 122 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 123 | 124 | meteor-random@^0.0.3: 125 | version "0.0.3" 126 | resolved "https://registry.yarnpkg.com/meteor-random/-/meteor-random-0.0.3.tgz#0d1489ecdb9bcb58bb52decebfbceddf54473a68" 127 | dependencies: 128 | crypto "0.0.3" 129 | 130 | mimic-fn@^1.0.0: 131 | version "1.1.0" 132 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" 133 | 134 | mute-stream@0.0.7: 135 | version "0.0.7" 136 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" 137 | 138 | node-fetch@^1.0.1: 139 | version "1.6.3" 140 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" 141 | dependencies: 142 | encoding "^0.1.11" 143 | is-stream "^1.0.1" 144 | 145 | onetime@^2.0.0: 146 | version "2.0.1" 147 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 148 | dependencies: 149 | mimic-fn "^1.0.0" 150 | 151 | os-tmpdir@~1.0.1: 152 | version "1.0.2" 153 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 154 | 155 | restore-cursor@^2.0.0: 156 | version "2.0.0" 157 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 158 | dependencies: 159 | onetime "^2.0.0" 160 | signal-exit "^3.0.2" 161 | 162 | run-async@^2.2.0: 163 | version "2.3.0" 164 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 165 | dependencies: 166 | is-promise "^2.1.0" 167 | 168 | rx@^4.1.0: 169 | version "4.1.0" 170 | resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" 171 | 172 | signal-exit@^3.0.2: 173 | version "3.0.2" 174 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 175 | 176 | string-width@^2.0.0: 177 | version "2.0.0" 178 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" 179 | dependencies: 180 | is-fullwidth-code-point "^2.0.0" 181 | strip-ansi "^3.0.0" 182 | 183 | strip-ansi@^3.0.0: 184 | version "3.0.1" 185 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 186 | dependencies: 187 | ansi-regex "^2.0.0" 188 | 189 | supports-color@^2.0.0: 190 | version "2.0.0" 191 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 192 | 193 | through@^2.3.6: 194 | version "2.3.8" 195 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 196 | 197 | tmp@^0.0.31: 198 | version "0.0.31" 199 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" 200 | dependencies: 201 | os-tmpdir "~1.0.1" 202 | 203 | whatwg-fetch@>=0.10.0: 204 | version "2.0.3" 205 | resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" 206 | 207 | -------------------------------------------------------------------------------- /article.md: -------------------------------------------------------------------------------- 1 | Today I'm going to show you how to build a simple note taking app that can be used inside of your command line. 2 | We're going to use [Cosmic JS](https://cosmicjs.com/) which allows us to view these notes from anywhere on any device. 3 | 4 | # Setup 5 | 6 | In an empty directory start a new npm project. 7 | ```sh 8 | npm init 9 | ``` 10 | Next you'll need to add the following packages. 11 | - cosmicjs ( makes accessing your bucket end points easier ) 12 | - meteor-random ( generates a nicely formatted 16 character sequence ) 13 | - chalk ( does a good job at coloring the terminal output ) 14 | - inquirer ( a framework for the command line ) 15 | 16 | ```sh 17 | npm install --save cosmicjs meteor-random chalk inquirer 18 | ``` 19 | 20 | Now let's take a look at the package.json. If you did everything right so far it should look like this. 21 | 22 | ```json 23 | { 24 | "name": "NoteToSelf", 25 | "version": "1.0.0", 26 | "description": "", 27 | "main": "index.js", 28 | "scripts": { 29 | "test": "echo \"Error: no test specified\" && exit 1" 30 | }, 31 | "keywords": [], 32 | "author": "", 33 | "license": "ISC", 34 | "dependencies": { 35 | "chalk": "^1.1.3", 36 | "cosmicjs": "^2.39.0", 37 | "inquirer": "^3.0.6", 38 | "meteor-random": "^0.0.3" 39 | } 40 | } 41 | ``` 42 | Now let's take a second to setup our index.js file. First thing we need to do is import our packages at the top of the page 43 | ```js 44 | const chalk = require('chalk'); 45 | const inquirer = require('inquirer'); 46 | const Random = require('meteor-random'); 47 | const Cosmic = require('cosmicjs'); 48 | ``` 49 | When we have done that next we need to setup our buckets information to be used later. 50 | 51 | ```js 52 | var config = {}; 53 | config.bucket = { 54 | slug: '', 55 | read_key: '', 56 | write_key: '' 57 | } 58 | ``` 59 | You will need to fill in the above object with your buckets information. Now we need to setup the main menu 60 | this is what you'll see when you start the program. 61 | 62 | # Code Overview 63 | 64 | ```js 65 | const MainMenu = () => { 66 | inquirer.prompt( 67 | { 68 | type: 'list', 69 | name: 'mainMenu', 70 | message: 'Main Menu', 71 | choices: [ 72 | 'New Note', 73 | 'View Notes', 74 | new inquirer.Separator(), 75 | 'Exit' 76 | ] 77 | } 78 | ).then((answers)=>{ 79 | if(answers.mainMenu === "New Note"){ 80 | NewNote() 81 | } else if(answers.mainMenu === "View Notes"){ 82 | ViewNotes() 83 | } else { 84 | process.exit() 85 | } 86 | }) 87 | } 88 | MainMenu() 89 | ``` 90 | Let's break this down so i'ts easier to understand. 91 | 1. generates a cli interface with 3 options 92 | 2. after you select an option it runs through a series of if statements directing you to the next interface 93 | 94 | Now we are going to create the interface for adding a new note. Buckle in because this is where it gets slightly more confusing. 95 | 96 | ```js 97 | const NewNote = () => { 98 | var question = { 99 | type: 'input', 100 | name: 'note_text', 101 | message: 'Note' 102 | } // 1 103 | inquirer.prompt(question).then((answers) => { // 2 104 | var params = { 105 | write_key: config.bucket.write_key, 106 | type_slug: 'notes', 107 | slug: Random.id().toLowerCase(), 108 | title: answers.note_text, 109 | content: '' 110 | } // 3 111 | if(answers.note_text === ''){ 112 | console.log(chalk.red("You cannot add an empty note")) 113 | MainMenu() 114 | return; 115 | } 116 | Cosmic.addObject(config, params, (error, response) =>{ // 4 117 | if(response.object){ 118 | console.log(chalk.green("\u2713" + " Success")) 119 | } 120 | if(error){ 121 | console.log(error) 122 | } 123 | MainMenu() //5 124 | }) 125 | }) 126 | } 127 | ``` 128 | This isn't too confusing don't worry we'll walk through it together. 129 | 1. we create the question type and declare it to a variable 130 | 2. we then send it to a inquirer function to get user input for what the note text should be 131 | 3. now we create an object with all the information we'll need for cosmic js. It automatically pulls the input text from inquirer and builds a slug from the meteor random package. 132 | 4. we now use the wonder of CosmicJS and create a new object. 133 | 5. return to the main menu 134 | 135 | The next menu is a little more confusing so we're going to break it down into smaller chunks. 136 | 137 | ```js 138 | const ViewNotes = () => { 139 | var params = { 140 | type_slug: 'notes', 141 | limit: 10, 142 | skip: 0 143 | }; 144 | 145 | Cosmic.getObjectType(config, params, (error, response)=>{ //fetches all notes 146 | var notes = [] 147 | var noteText = [chalk.yellow("Return")] 148 | if(response.total === undefined){ 149 | console.log(chalk.red("No notes found.")) 150 | MainMenu() 151 | return; 152 | } 153 | sortedresponse = response.objects.all.sort((a,b)=>{ 154 | return new Date(b.created) - new Date(a.created) 155 | }) 156 | const amount = response.objects.all.length 157 | sortedresponse.map((note)=>{ 158 | var newnote = { 159 | name: note.title, 160 | slug: note.slug 161 | } 162 | noteText.push(chalk.blue(note.title) + chalk.hidden('slug - '+note.slug + ' | ') ) 163 | notes.push(newnote) 164 | if(notes.length === amount){ 165 | inquirer.prompt( 166 | { 167 | type: 'list', 168 | name: 'allnotes', 169 | message: 'All Notes:', 170 | choices: noteText 171 | }).then((answers)=>{ 172 | if(answers.allnotes === "\u001b[33mReturn\u001b[39m"){ 173 | MainMenu() 174 | return; 175 | } 176 | var regexSearch = /(\w{17})/ 177 | var newvalue = answers.allnotes.match(regexSearch) 178 | Cosmic.getObject(config, {slug: newvalue[0]}, (error, response)=>{ 179 | inquirer.prompt({ 180 | type: 'expand', 181 | message: chalk.blue(response.object.title), 182 | name: 'morecontext', 183 | choices: [ 184 | { 185 | key: 'e', 186 | name: 'Edit', 187 | value: 'edit' 188 | }, 189 | { 190 | key: 'd', 191 | name: 'Delete', 192 | value: 'delete' 193 | }, 194 | { 195 | key: 'l', 196 | name: 'Leave', 197 | value: 'leave' 198 | } 199 | ]}).then((answers)=>{ 200 | if(answers.morecontext === 'edit'){ 201 | inquirer.prompt( 202 | { 203 | type: 'input', 204 | name: 'newText', 205 | message: 'New Text:' 206 | }).then((answers)=>{ 207 | var params = { 208 | write_key: config.bucket.write_key, 209 | slug: response.object.slug, 210 | type_slug: 'notes', 211 | title: answers.newText, 212 | content: '' 213 | } 214 | Cosmic.editObject(config, params, (error, response)=>{ 215 | if(response.object){ 216 | console.log(chalk.green("\u2713" + " Success")) 217 | } 218 | MainMenu() 219 | }) 220 | }) 221 | 222 | } else if(answers.morecontext === 'delete'){ 223 | var params = { 224 | write_key: config.bucket.write_key, 225 | slug: response.object.slug 226 | } 227 | Cosmic.deleteObject(config, params, (error, response)=>{ 228 | if(error){ 229 | console.log(error) 230 | } 231 | if(response.object){ 232 | console.log(chalk.green("\u2713" + " Success")) 233 | } 234 | MainMenu(); 235 | }); 236 | } else { 237 | MainMenu(); 238 | } 239 | }) 240 | }) 241 | }) 242 | } 243 | }) 244 | }) 245 | } 246 | ``` 247 | If this seem like absolutely gibberish that's okay we can take it one piece at a time. Let's start with the top half where we 248 | get all of your notes (up to ten) and display them in a list view. 249 | 250 | ```js 251 | var params = { 252 | type_slug: 'notes', 253 | limit: 10, 254 | skip: 0 255 | }; 256 | 257 | Cosmic.getObjectType(config, params, (error, response)=>{ // 1 258 | var notes = [] 259 | var noteText = [chalk.yellow("Return")] 260 | if(response.total === undefined){ 261 | console.log(chalk.red("No notes found.")) 262 | MainMenu() 263 | return; 264 | } 265 | sortedresponse = response.objects.all.sort((a,b)=>{ 266 | return new Date(b.created) - new Date(a.created) 267 | }) // 2 268 | const amount = response.objects.all.length 269 | sortedresponse.map((note)=>{ 270 | var newnote = { 271 | name: note.title, 272 | slug: note.slug 273 | } 274 | noteText.push(chalk.blue(note.title) + chalk.hidden('slug - '+note.slug + ' | ') ) // 3 275 | notes.push(newnote) 276 | if(notes.length === amount){ 277 | inquirer.prompt( 278 | { 279 | type: 'list', 280 | name: 'allnotes', 281 | message: 'All Notes:', 282 | choices: noteText 283 | }).then((answers)=>{ 284 | if(answers.allnotes === "\u001b[33mReturn\u001b[39m"){ 285 | MainMenu() 286 | return; 287 | } 288 | var regexSearch = /(\w{17})/ 289 | var newvalue = answers.allnotes.match(regexSearch) // 4 290 | Cosmic.getObject(config, {slug: newvalue[0]}, (error, response)=>{ // 5 291 | inquirer.prompt({ // 6 292 | type: 'expand', 293 | message: chalk.blue(response.object.title), 294 | name: 'morecontext', 295 | choices: [ 296 | { 297 | key: 'e', 298 | name: 'Edit', 299 | value: 'edit' 300 | }, 301 | { 302 | key: 'd', 303 | name: 'Delete', 304 | value: 'delete' 305 | }, 306 | { 307 | key: 'l', 308 | name: 'Leave', 309 | value: 'leave' 310 | } 311 | ]}) 312 | ``` 313 | 1. We use the CosmicJS package to go ahead and grab all of the objects. 314 | 2. We take the array of objects and sort them so the most recent are on the top. 315 | 3. We create a string with two seperate parts. The first part is the text of the note styled to be blue using the chalk package. Next we take the slug of the item and pass it in but make it hidden. This is done so that we can fetch more information about this note later on in the program. 316 | 4. We take the string the user selected and match it agains a regex search that will find the slug and return it. 317 | 5. We get the objects specific information this allows us to use it better later on. 318 | 6. We generate the next prompt using the newly fetched data and place the note text in the message field. 319 | 320 | That was the basics of fetching the data and manipulating the return in a manner that we can use it correctly in this instance. 321 | Now we're going to take a look at the second half of the view function. This is where we can edit and delete our selected not from before. 322 | 323 | ```js 324 | ]}).then((answers)=>{ 325 | if(answers.morecontext === 'edit'){ 326 | inquirer.prompt( 327 | { 328 | type: 'input', 329 | name: 'newText', 330 | message: 'New Text:' 331 | }).then((answers)=>{ // 1 332 | var params = { 333 | write_key: config.bucket.write_key, 334 | slug: response.object.slug, 335 | type_slug: 'notes', 336 | title: answers.newText, 337 | content: '' 338 | } // 2 339 | Cosmic.editObject(config, params, (error, response) => { // 3 340 | if(response.object){ 341 | console.log(chalk.green("\u2713" + " Success")) 342 | } 343 | MainMenu() 344 | }) 345 | }) 346 | } else if(answers.morecontext === 'delete'){ 347 | var params = { 348 | write_key: config.bucket.write_key, 349 | slug: response.object.slug 350 | } 351 | Cosmic.deleteObject(config, params, (error, response)=>{ 352 | if(error){ 353 | console.log(error) 354 | } 355 | if(response.object){ 356 | console.log(chalk.green("\u2713" + " Success")) 357 | } 358 | MainMenu(); 359 | }); 360 | } else { 361 | MainMenu(); 362 | } 363 | }) 364 | ``` 365 | 1. Creates a prompt and asks the user for the new note text 366 | 2. Again we build an object with all the neccesarry parts you need. 367 | - we grab the slug from the earlier CosmicJS request 368 | - title is determined by what is typed in the box 369 | - content is left as a blank string on purpose 370 | 3. Once we have all the pieces this is where we put them all together and edit what the note says. 371 | 372 | # Final Steps 373 | 374 | After all of that code it wasn't too bad in the end. After reading that overview you should have a pretty rough idea of what the program is doing. If your still having problems understanding what is going on I'm just an email away. 375 | There are still a few more things that need to be done though. First things first we need to make some adjusts to the package.json file. 376 | 377 | ```json 378 | { 379 | "name": "NoteToSelf", 380 | "version": "1.0.0", 381 | "description": "", 382 | "main": "index.js", 383 | "scripts": { 384 | "test": "echo \"Error: no test specified\" && exit 1" 385 | }, 386 | + "bin": { 387 | + "notetoself": "./index.js" 388 | + }, 389 | "keywords": [], 390 | "author": "", 391 | "license": "ISC", 392 | "dependencies": { 393 | "chalk": "^1.1.3", 394 | "cosmicjs": "^2.39.0", 395 | "inquirer": "^3.0.6", 396 | "meteor-random": "^0.0.3" 397 | } 398 | } 399 | ``` 400 | This will make it so that the application is installable system wide and can be called by using 'notetoself'. All that's left to do is install the package to your system. 401 | ```sh 402 | npm install -g 403 | ``` 404 | Once this is done simply run 'notetoself' and you'll have system wide notes available anytime you want. 405 | 406 | --------------------------------------------------------------------------------