├── .DS_Store ├── .gitattributes ├── .gitignore ├── .vscode └── launch.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app.js ├── background.png ├── character.png ├── images ├── .DS_Store ├── node-icon.png └── node-snippets.gif ├── package.json ├── snippets └── snippets.json └── vsc-extension-quickstart.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.vsix 3 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to the "node-snippets" extension will be documented in this file. 3 | 4 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 5 | 6 | ## [Unreleased] 7 | - Initial release -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2025 Chris Noring 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # node-snippets 3 | 4 | This is an extension meant to give you some awesome NodeJS snippets 5 | ![alt text](images/node-snippets.gif "Using the snippet") 6 | 7 | ## NEW - generative AI commands 8 | 9 | The following commands have been added in 1.4.0: 10 | 11 | - `node-genai-response-api-app`, generates a response API app, 12 | - `node-genai-response-api-client`, generates a response API, only the client part. 13 | - `node-genai-response-api-response`, generates a response API, only the response part. 14 | - `node-genai-chat-messages`, is a list of chat messages sent to the LLM. 15 | - `node-genai-chat-app`, generates a chat app. 16 | - `node-genai-github-models`, generates a chat app that you can run in GitHub Codespaces or 17 | 18 | Try out a fun free course on Generative AI + JavaScript, it features: 19 | 20 |
21 | Generative AI For JavaScript 22 |
23 | 24 | - Lessons on fundamentals of Generative AI including RAG 25 | - It has a companion app that lets you interact with historical characters like Ada Lovelace and Leonardo Da Vinci. 26 | - It has a fun time travelling narrative. 27 | 28 |
29 | Companion app 30 |
31 | 32 | > Check it out at [Generative AI For JavaScript](https://github.com/microsoft/generative-ai-with-javascript) 33 | 34 | ## Contact 35 | 36 | If you find issues please report them on the GitHub repo. 37 | 38 | If you have any comments like feature requests or feedback on theses snippets please contact me on: 39 | 40 | - **Twitter** at [chris_noring](https://twitter.com/chris_noring). 41 | - **Linked In** at [Chris Noring](https://uk.linkedin.com/in/christoffer-noring-3257061) 42 | 43 | Remember these snippets are for all of you, so if you feel that they could be even better, don't hesitate to let me know :) 44 | 45 | /Chris 46 | 47 | ## Features 48 | 49 | A collection of NodeJS snippets 50 | 51 | The following commands are available: 52 | 53 | - `node-express`, creates an express server 54 | - `node-express-get`, creates GET route 55 | - `node-express-get-params`, creates a GET route and shows how to access parameters 56 | - `node-express-post`, creates a POST route 57 | - `node-express-post-params`, creates a POST route and shows how to access the body 58 | - `node-express-post-params-alt`, creates a POST route, shows how to access the body, works for express 4.16 and above 59 | - `node-express-put-params`, creates a PUT route, shows how to access body. 60 | - `node-express-delete-params`, creates a DELETE route, shows how to access route parameter. 61 | - `node-express-query-params`, creates a POST route, shows how to access query parameters. 62 | - `node-express-middleware-logger`, creates an example middleware 63 | - `node-express-middleware-error`, creates an error handling middleware 64 | - `node-http-server`, creates a simple HTTP server 65 | - `node-file-read-sync`, reads a file synchronously 66 | - `node-file-read-async`, reads a file asynchronously, with a callback 67 | - `node-event-emitter`, creates an event emitter, emit events and shows to subscribe to said event 68 | - `node-promise-create`, creates a Promise 69 | - `node-promise-shorthand`, creates a Promises using the static methods `resolve()` and `reject()` 70 | - `node-promise-all`, resolves a list of Promises using the `Promise.all([])` method 71 | - `node-async-await`, using async/await 72 | - `node-express-schema-validation`, adding schema validation for express, read more about the usage of schema validation with `Joi` at https://github.com/hapijs/joi 73 | - `node-regex-test-digits`, invokes the `test()` method that tests whether a string matches a regular expression on digits. 74 | - `node-regex-test-word`, invokes the `test()` method that tests whether a string matches a regular expression on word boundaries. 75 | - `node-regex-match`, invokes the method `match()` on a regular expression to find a file extension 76 | - `node-regex-match-named-group`, invokes the method `match()` on a regular expression and place it in a group called `exteension`. 77 | - `node-http-quark`, creates a HTTP app using the framework [quarkhttp](https://www.npmjs.com/package/quarkhttp), 78 | - `node-http-quark-get`, adds a GET route to your [quarkhttp](https://www.npmjs.com/package/quarkhttp) app 79 | - `node-http-quark-post`, adds a POST route to your [quarkhttp](https://www.npmjs.com/package/quarkhttp) app 80 | - `node-http-quark-put`, adds a PUT route to your [quarkhttp](https://www.npmjs.com/package/quarkhttp) app 81 | - `node-http-quark-middleware`, adds a middleware to your [quarkhttp](https://www.npmjs.com/package/quarkhttp) app 82 | - `node-jest-suite`, adds a test suite 83 | - `node-jest-test`, adds a test 84 | - `node-jest-test-expect`, adds a test with an expect 85 | - `node-jest-expect`, adds an expect, using `toBe()` 86 | - `node-jest-expect-to-equal`, adds expect, using `toEqual()` 87 | - `node-jest-test-expect-to-equal`, adds a test with an expect, using `toEqual()` 88 | - `node-jest-expect-to-throw`, adds an expect, using `toThrow()` 89 | - `node-jest-test-expect-to-throw`, adds a test with an expect, using `toThrow()`, 90 | - `node-jest-test-beforeAll`, adds a `beforeAll()`, this method runs before all tests 91 | - `node-jest-test-afterAll`, adds a `afterAll()`, this method runs after all tests 92 | - `node-supertest-init`, adds the initial imports for supertest and the app you are about to test. I assume the app you are about to test looks something like this: 93 | 94 | ```javascript 95 | // app.js 96 | const express = require('express') 97 | const app = express(); 98 | // your route definitions 99 | module.exports = app; 100 | ``` 101 | 102 | and that your file structure looks like this: 103 | 104 | ```bash 105 | -| app.js // this is where the web app goes 106 | -| __tests__/ 107 | ---| app.js // this where the tests goes 108 | ``` 109 | 110 | - `node-supertest-beforeall`, configures supertest to use the app instance, this is a needed step to initialize supertest 111 | - `node-supertest-aftereall`, ensures the web app closes down after the test run, this is a needed step. 112 | - `node-supertest-testget`, an example of supertest testing a GET route 113 | - `node-supertest-testgetwithparam`, an example of supertest testing a GET route with a route parameter 114 | - `node-supertest-testpost`, an example of supertest testing a POST route with a payload 115 | 116 | - `node-genai-response-api-app`, generates a response API app, 117 | - `node-genai-response-api-client`, generates a response API, only the client part. 118 | - `node-genai-response-api-response`, generates a response API, only the response part. 119 | - `node-genai-chat-messages`, is a list of chat messages sent to the LLM. 120 | - `node-genai-chat-app`, generates a chat app. 121 | - `node-genai-github-models`, generates a chat app that you can run in GitHub Codespaces or locally if you create a personal access token. 122 | 123 | ## Release Notes 124 | 125 | This is the release notes. 126 | 127 | ### 1.4.0 128 | 129 | Adding generative Gen AI snippets. 130 | 131 | ### 1.3.3 132 | 133 | Fix issues with interpolation 134 | 135 | ### 1.3.2 136 | 137 | Adding typescript support. Thank you to @DrQubit for the suggestion 138 | 139 | ### 1.2.1 140 | 141 | Adding supertest so you can easily test your API. Assumes using Express as web framework. 142 | 143 | ### 1.1.0 144 | 145 | Adding Jest snippets and snippets for a micro HTTP framework, quarkhttp (can be installed from NPM) 146 | 147 | ### 0.0.5 148 | 149 | correcting the docs 150 | 151 | ### 0.0.4 152 | 153 | adding schema validation with the lib `Joi` 154 | 155 | ### 0.0.3 156 | 157 | added promises and async 158 | 159 | ### 0.0.2 160 | 161 | added repo and icon 162 | 163 | ### 0.0.1 164 | 165 | some initial commands for express library but also things like `http`, file access and using `event-emitter` 166 | 167 | ## Publisher 168 | 169 | Chris Noring 170 | @chris_noring 171 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/app.js -------------------------------------------------------------------------------- /background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/background.png -------------------------------------------------------------------------------- /character.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/character.png -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/images/.DS_Store -------------------------------------------------------------------------------- /images/node-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/images/node-icon.png -------------------------------------------------------------------------------- /images/node-snippets.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/softchris/node-snippets/8b2cb2ddb6696de5e1e9c682f90cc8042a1c131f/images/node-snippets.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-snippets", 3 | "displayName": "node-snippets", 4 | "description": "snippets for node + libraries", 5 | "version": "1.4.0", 6 | "publisher": "chris-noring", 7 | "engines": { 8 | "vscode": "^1.29.0" 9 | }, 10 | "categories": [ 11 | "Snippets" 12 | ], 13 | "contributes": { 14 | "snippets": [ 15 | { 16 | "language": "javascript", 17 | "path": "./snippets/snippets.json" 18 | }, 19 | { 20 | "language": "typescript", 21 | "path": "./snippets/snippets.json" 22 | }, 23 | { 24 | "language": "javascriptreact", 25 | "path": "./snippets/snippets.json" 26 | }, 27 | { 28 | "language": "typescriptreact", 29 | "path": "./snippets/snippets.json" 30 | } 31 | ] 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/softchris/node-snippets.git" 36 | }, 37 | "homepage": "https://github.com/softchris/node-snippets/blob/master/README.md", 38 | "icon": "images/node-icon.png" 39 | } 40 | -------------------------------------------------------------------------------- /snippets/snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "genai-chat-codespaces" : { 3 | "prefix": "node-genai-github-models", 4 | "body": [ 5 | "/*", 6 | " - GitHub Models are LLM models that are completely free, great for local development and testing. Remember to run this code from a Codespaces instance of change key to a personal access token", 7 | " - Check out https://github.com/microsoft/generative-ai-with-javascript, for a fun free course on how to use GenAi, it has time traveling :)", 8 | "*/", 9 | "", 10 | "import { OpenAI } from 'openai';", 11 | "", 12 | "const messages = [", 13 | " {", 14 | " \"role\": \"system\",", 15 | " \"content\": \"You are a helpful chat bot\"", 16 | " }", 17 | "{", 18 | " \"role\": \"user\",", 19 | " \"content\": \"users prompt here\"", 20 | "}", 21 | "];", 22 | "", 23 | "const openai = new OpenAI({", 24 | " baseURL: 'https://models.inference.ai.azure.com',", 25 | " apiKey: process.env.GITHUB_TOKEN,", 26 | "});", 27 | "const completion = await openai.chat.completions.create({", 28 | " model: 'gpt-4o-mini',", 29 | " messages: messages,", 30 | "});", 31 | "", 32 | "console.log(`Response: ${completion.choices[0]?.message?.content}`);" 33 | ] 34 | }, 35 | "genai-response-api-app" : { 36 | "prefix": "node-genai-response-api-app", 37 | "body": [ 38 | "/*", 39 | " - Check out official docs at: https://github.com/openai/openai-node", 40 | " - Check out https://github.com/microsoft/generative-ai-with-javascript, for a fun free course on how to use GenAi, it has time traveling :)", 41 | "*/", 42 | "", 43 | "import OpenAI from 'openai';", 44 | "", 45 | "const client = new OpenAI({", 46 | " apiKey: process.env['OPENAI_API_KEY'], // This is the default and can be omitted", 47 | "});", 48 | "", 49 | "const response = await client.responses.create({", 50 | " model: 'gpt-4o',", 51 | " instructions: 'You are a coding assistant that talks like a pirate',", 52 | " input: 'Are semicolons optional in JavaScript?',", 53 | "});", 54 | "", 55 | "console.log(response.output_text);" 56 | ] 57 | }, 58 | "genai-response-api-client" : { 59 | "prefix": "node-genai-response-api-client", 60 | "body": [ 61 | "/*", 62 | " - Check out official docs at: https://github.com/openai/openai-node", 63 | " - Check out https://github.com/microsoft/generative-ai-with-javascript, for a fun free course on how to use GenAi, it has time traveling :)", 64 | "*/", 65 | "", 66 | "import OpenAI from 'openai';", 67 | "", 68 | "const client = new OpenAI({", 69 | " apiKey: process.env['OPENAI_API_KEY'], // This is the default and can be omitted", 70 | "});" 71 | ], 72 | "description": "Generates a new instance of GenAi" 73 | }, 74 | "genai-response-api-response" : { 75 | "prefix": "node-genai-response-api-response", 76 | "body": [ 77 | "/*", 78 | " - Check out official docs at: https://github.com/openai/openai-node", 79 | " - Check out https://github.com/microsoft/generative-ai-with-javascript, for a fun free course on how to use GenAi, it has time traveling :)", 80 | "*/", 81 | "", 82 | "const response = await client.responses.create({", 83 | " model: 'gpt-4o',", 84 | " instructions: 'You are a coding assistant that talks like a pirate',", 85 | " input: 'Are semicolons optional in JavaScript?',", 86 | "});", 87 | "", 88 | "console.log(response.output_text);" 89 | ] 90 | }, 91 | "genai-chat-messages": { 92 | "prefix": "node-genai-chat-messages", 93 | "body": [ 94 | "/*", 95 | " system/developer are instructions to the LLM", 96 | " user is what the user says", 97 | "*/", 98 | "", 99 | "[", 100 | "{ role: 'developer', content: 'Speak like Sherlock Homes' }, // this is what was called system before", 101 | "{ role: 'user', content: 'Are semicolons optional in JavaScript?' }", 102 | "]" 103 | ] 104 | }, 105 | "genai-chat-app" : { 106 | "prefix": "node-genai-chat-app", 107 | "body": [ 108 | "/*", 109 | " Check out official docs at: https://github.com/openai/openai-node", 110 | " Check out https://github.com/microsoft/generative-ai-with-javascript, for a fun free course on how to use GenAi, it has time traveling :)", 111 | "*/", 112 | "", 113 | "import OpenAI from 'openai';", 114 | 115 | "const client = new OpenAI({", 116 | " apiKey: process.env['OPENAI_API_KEY'], // This is the default and can be omitted", 117 | "});", 118 | "", 119 | "const completion = await client.chat.completions.create({", 120 | " model: 'gpt-4o',", 121 | " messages: [", 122 | " { role: 'developer', content: 'Speak like Sherlock Homes' }, // this is what was called system before", 123 | " { role: 'user', content: 'Are semicolons optional in JavaScript?' },", 124 | "],", 125 | "});", 126 | "", 127 | "console.log(completion.choices[0].message.content);" 128 | ] 129 | }, 130 | "http-quark": { 131 | "prefix": "node-http-quark", 132 | "body": [ 133 | "const quark = require('quarkhttp');", 134 | "const app = quark();", 135 | "app.get('/', (req, res) => res.send('hello world'))", 136 | "app.listen(3000, () => {", 137 | " console.log('Server running on 3000');", 138 | "})" 139 | ], 140 | "description": "a micro HTTP framework, creates an app with a route" 141 | }, 142 | "http-quark-get": { 143 | "prefix": "node-http-quark-get", 144 | "body": [ 145 | "app.get('/products', (req, res) => res.json([{ id: 1, name: 'a product' }]))" 146 | ], 147 | "description": "a micro HTTP framework, adds a GET route" 148 | }, 149 | "http-quark-post": { 150 | "prefix": "node-http-quark-post", 151 | "body": [ 152 | "app.post('/products', (req,res) => {", 153 | " console.info('body', req.body)", 154 | " res.json(req.body);", 155 | "})" 156 | ], 157 | "description": "a micro HTTP framework, adds a POST route" 158 | }, 159 | "http-quark-put": { 160 | "prefix": "node-http-quark-put", 161 | "body": [ 162 | "app.put('/products', (req,res) => {", 163 | " console.info('body', req.body)", 164 | " res.json(req.body);", 165 | "})" 166 | ], 167 | "description": "a micro HTTP framework, adds a PUT route" 168 | }, 169 | "http-quark-middleware": { 170 | "prefix": "node-http-quark-middleware", 171 | "body": [ 172 | "app.get('/orders', (req, res, next) => {", 173 | " if (req.headers['authorization'] === 'abc123') {", 174 | " next()", 175 | " } else {", 176 | " res.statusCode = 401;", 177 | " res.send('Not allowed')", 178 | " }", 179 | "}, (req, res) => {", 180 | " res.send('Protected route');", 181 | "})" 182 | ], 183 | "description": "a micro HTTP framework, adds a middleware" 184 | }, 185 | "jest-suite": { 186 | "prefix": "node-jest-suite", 187 | "body": ["describe('$1', () => {", " ", "})"] 188 | }, 189 | "jest-test": { 190 | "prefix": "node-jest-test", 191 | "body": ["test('$1', () => {$2})"] 192 | }, 193 | "jest-test-expect": { 194 | "prefix": "node-jest-test-expect", 195 | "body": ["test('$2', () => {", " expect(1).toBe(2)", "})"] 196 | }, 197 | "jest-expect": { 198 | "prefix": "node-jest-expect", 199 | "body": [" expect(1).toBe(2)"] 200 | }, 201 | "jest-expect-to-equal": { 202 | "prefix": "node-jest-expect-to-equal", 203 | "body": ["let obj = { a: '1' }", "expect(obj).toEqual({ a: '1' })"] 204 | }, 205 | "jest-test-expect-to-equal": { 206 | "prefix": "node-jest-test-expect-to-equal", 207 | "body": [ 208 | "test('$2', () => {", 209 | " let obj = { a: '1' }", 210 | " expect(obj).toEqual({ a: '1' })", 211 | "})" 212 | ] 213 | }, 214 | "jest-expect-to-throw": { 215 | "prefix": "node-jest-expect-to-throw", 216 | "body": [ 217 | "const thisThrows = () => throw new Error('error message')", 218 | "expect(thisThrows).toThrow('error message')" 219 | ] 220 | }, 221 | "jest-test-expect-to-throw": { 222 | "prefix": "node-jest-test-expect-to-throw", 223 | "body": [ 224 | "test('$2', () => {", 225 | " const thisThrows = () => throw new Error('error message')", 226 | " expect(thisThrows).toThrow('error message')", 227 | "})" 228 | ] 229 | }, 230 | "jest-test-beforeAll": { 231 | "prefix": "node-jest-test-beforeAll", 232 | "body": [" beforeAll(() => {", " ", " })"] 233 | }, 234 | "jest-test-afterAll": { 235 | "prefix": "node-jest-test-afterAll", 236 | "body": [" afterAll(() => {", " ", " })"] 237 | }, 238 | "regex-test-digits": { 239 | "prefix": "node-regex-test-digits", 240 | "body": ["const isMatch = /\\d+/.test('abc123')"], 241 | "description": "test if string contains digits, returns true/false" 242 | }, 243 | "regex-test-word": { 244 | "prefix": "node-regex-test-word", 245 | "body": ["const isMatch = /\\w+/.test('abc123')"], 246 | "description": "test if string contains a word boundary, returns true/false" 247 | }, 248 | "regex-test-match": { 249 | "prefix": "node-regex-match", 250 | "body": ["const [, extension] = 'file.txt'.match(/\\.(\\w+)/)"], 251 | "description": "matches a file extension" 252 | }, 253 | "regex-test-match-named-group": { 254 | "prefix": "node-regex-match-named-group", 255 | "body": [ 256 | "const { groups: { extension } } = 'file.txt'.match(/\\.(?\\w+)/)" 257 | ], 258 | "description": "matches a file extension, " 259 | }, 260 | "express server": { 261 | "prefix": "node-express", 262 | "body": [ 263 | "const express = require('express')", 264 | "const app = express()", 265 | "const port = 3000", 266 | "", 267 | "app.get('/', (req, res) => res.send('Hello World!'))", 268 | "app.listen(port, () => console.log(`Example app listening on port \\${port\\}!`))" 269 | ], 270 | "description": "Creates an express server" 271 | }, 272 | "express GET": { 273 | "prefix": "node-express-get", 274 | "body": [ 275 | "app.get('/', (req, res) => {", 276 | " res.send('GET request to the homepage')", 277 | "})" 278 | ], 279 | "description": "Creates a GET route" 280 | }, 281 | "express GET params": { 282 | "prefix": "node-express-get-params", 283 | "body": [ 284 | "app.get('/books/:bookId', (req, res) => {", 285 | " res.send(req.params.bookId)", 286 | "})" 287 | ], 288 | "description": "Creates a GET route and shows how to access params" 289 | }, 290 | "express POST": { 291 | "prefix": "node-express-post", 292 | "body": [ 293 | "app.post('/', function (req, res) {", 294 | " res.send('POST request to the homepage')", 295 | "})" 296 | ], 297 | "description": "Creates a POST route" 298 | }, 299 | "express POST params": { 300 | "prefix": "node-express-post-params", 301 | "body": [ 302 | "const bodyParser = require('body-parser');", 303 | "app.use(bodyParser.json());", 304 | "", 305 | "app.post('/update', function(req, res) {", 306 | " const { name, description } = req.body;", 307 | " res.send(`Name \\${name\\}, desc \\${description\\}`);", 308 | "});" 309 | ], 310 | "description": "Creates a POST route that can read from the body" 311 | }, 312 | "express PUT params": { 313 | "prefix": "node-express-put-params", 314 | "body": [ 315 | "const bodyParser = require('body-parser');", 316 | "app.use(bodyParser.json());", 317 | "", 318 | "app.put('/products', function(req, res) {", 319 | " const { id, name, description } = req.body;", 320 | " res.send(`Name \\${id\\} \\${name\\}, desc \\${description\\}`);", 321 | "});" 322 | ], 323 | "description": "Creates a POST route that can read from the body" 324 | }, 325 | "express DELETE params": { 326 | "prefix": "node-express-delete-params", 327 | "body": [ 328 | "const bodyParser = require('body-parser');", 329 | "app.use(bodyParser.json());", 330 | "", 331 | "app.delete('/products/:id', function(req, res) {", 332 | " const { id } = req.params;", 333 | " res.send(`Delete record with id \\${id\\}`);", 334 | "});" 335 | ], 336 | "description": "Creates a POST route that can read from the body" 337 | }, 338 | "express QUERY params": { 339 | "prefix": "node-express-query-params", 340 | "body": [ 341 | "const bodyParser = require('body-parser');", 342 | "app.use(bodyParser.json());", 343 | "", 344 | "// for routes looking like this `/products?page=1&pageSize=50`", 345 | "app.get('/products', function(req, res) {", 346 | " const page = req.query.page;", 347 | " const pageSize = req.query.pageSize;", 348 | " res.send(`Filter with parameters \\${page\\} and \\${pageSize\\});`", 349 | "});" 350 | ], 351 | "description": "Creates a POST route that can read from the body" 352 | }, 353 | "express POST params version >=4.16": { 354 | "prefix": "node-express-post-params-alt", 355 | "body": [ 356 | "app.use(express.json())", 357 | "app.listen(8080)", 358 | "", 359 | "app.post('/test', (req, res) => {", 360 | " res.json({ body: req.body })", 361 | "});" 362 | ], 363 | "description": "Creates a POST route that can read from the body, works for 4.16 version of express and above" 364 | }, 365 | "express middleware": { 366 | "prefix": "node-express-middleware-logger", 367 | "body": [ 368 | "const logger = function (req, res, next) {", 369 | " console.log('logging')", 370 | " next()", 371 | "}", 372 | "", 373 | "app.use(logger)", 374 | "", 375 | "app.get('/', (req, res) => {", 376 | " res.send('Hello World!')", 377 | "})" 378 | ], 379 | "description": "Creates a middleware" 380 | }, 381 | "express middleware error": { 382 | "prefix": "node-express-middleware-error", 383 | "body": [ 384 | "app.use(function (err, req, res, next) {", 385 | " console.error(err.stack)", 386 | " res.status(500).send('Something broke!')", 387 | "});" 388 | ], 389 | "description": "Creates a error middleware" 390 | }, 391 | "http server": { 392 | "prefix": "node-http-server", 393 | "body": [ 394 | "const http = require('http');", 395 | "http.createServer(function (request, response) {", 396 | " response.writeHead(200, {'Content-Type': 'text/plain'});", 397 | " response.end('Hello World');", 398 | "}).listen(8081);", 399 | "", 400 | "console.log('Server running at http://127.0.0.1:8081/');" 401 | ], 402 | "description": "Creates a simple HTTP server" 403 | }, 404 | "file read sync": { 405 | "prefix": "node-file-read-sync", 406 | "body": [ 407 | "const fs = require('fs');", 408 | "const data = fs.readFileSync('file.txt');" 409 | ], 410 | "description": "Reads a file synchronously" 411 | }, 412 | "file read async": { 413 | "prefix": "node-file-read-async", 414 | "body": [ 415 | "const fs = require('fs');", 416 | "fs.readFile('input.txt', function (err, data) {", 417 | " if (err) return console.error(err);", 418 | " console.log(data.toString());", 419 | "});" 420 | ], 421 | "description": "Reads a file asynchronously" 422 | }, 423 | "event emitter": { 424 | "prefix": "node-event-emitter", 425 | "body": [ 426 | "const events = require('events');", 427 | "const eventEmitter = new events.EventEmitter();", 428 | "eventEmitter.emit('my_event');", 429 | "eventEmitter.on('my_event', () => {", 430 | " console.log('data received successfully.');", 431 | "});" 432 | ], 433 | "description": "Event emitter, shows emitting event and subscribing to it" 434 | }, 435 | "Promise creation": { 436 | "prefix": "node-promise-create", 437 | "body": [ 438 | "new Promise((resolve, reject) => {", 439 | " let condition = false;", 440 | " if(condition) {", 441 | " resolve('data')", 442 | " } else {", 443 | " reject('error')", 444 | "}", 445 | "})" 446 | ], 447 | "description": "creates a Promise by instantiating it" 448 | }, 449 | "Promise shorthand": { 450 | "prefix": "node-promise-shorthand", 451 | "body": [ 452 | "const promiseThatWillResolve = Promise.resolve('data');", 453 | "const promiseThatWillReject = Promise.reject('error');" 454 | ], 455 | "description": "uses the static resolve/reject, good for unit tests" 456 | }, 457 | "Promise all": { 458 | "prefix": "node-promise-all", 459 | "body": [ 460 | "const getData = () => Promise.resolve('data');", 461 | "const getMoreData = () => Promise.resolve('more data');", 462 | "", 463 | "Promise.all(", 464 | " getData(),", 465 | " getMoreData()", 466 | ").then(result => {", 467 | " const [data, moreData] = result;", 468 | "})" 469 | ], 470 | "description": "uses the static all(), allows us to have a list of Promises finish at the same time" 471 | }, 472 | "Async/await": { 473 | "prefix": "node-async-await", 474 | "body": [ 475 | "async function getData() {", 476 | " return Promise.resolve('data');", 477 | "}", 478 | "", 479 | "async function getMoreData(data) {", 480 | " return Promise.resolve(data + 'more data');", 481 | "}", 482 | "", 483 | "async function getAll() {", 484 | " const data = await getData();", 485 | " const moreData = await getMoreData(data);", 486 | " return `All the data: \\${data\\}, \\${moreData\\}`;", 487 | "}", 488 | "", 489 | "getAll().then((all) => {", 490 | " console.log('all the data')", 491 | "})" 492 | ], 493 | "description": "demonstrates async/await" 494 | }, 495 | "Joi schema validation": { 496 | "prefix": "node-express-schema-validation", 497 | "body": [ 498 | "const Joi = require('joi');", 499 | "const loginSchema = Joi.object().keys({", 500 | " username: Joi.string()", 501 | " .min(3)", 502 | " .max(10)", 503 | " .required(),", 504 | " password: Joi.string().regex(/^[a-zA-Z0-9]{3,30}$/)", 505 | "});", 506 | "", 507 | "app.post('/login', function(req, res) {", 508 | " const valid = Joi.validate(req.body, loginSchema).error === null;", 509 | " if (!valid) {", 510 | " res.status(422).json({", 511 | " status: 'error',", 512 | " message: 'Invalid request data',", 513 | " data: req.body", 514 | " });", 515 | " } else {", 516 | " // happy days - login user", 517 | " res.send(`ok`);", 518 | " }", 519 | "});" 520 | ], 521 | "description": "showcases the lib Joi and how you can use it to validate incoming requests" 522 | }, 523 | "supertest-init": { 524 | "prefix": "node-supertest-init", 525 | "body": [ 526 | "const supertest = require('supertest')", 527 | "const app = require('../app');", 528 | "const server = app.listen(3000, () => {", 529 | " console.log('listening at port 3000')", 530 | "})", 531 | "let request;" 532 | ], 533 | "description": "Sets up supertest by importing supertest and the app you mean to test. Additionally starts the app" 534 | }, 535 | "supertest-beforeall": { 536 | "prefix": "node-supertest-beforeall", 537 | "body": ["beforeAll(() => {", " request = supertest(app)", "})"], 538 | "description": "Configures supertest to use the app, this is needed" 539 | }, 540 | "supertest-afterall": { 541 | "prefix": "node-supertest-aftereall", 542 | "body": [ 543 | "afterAll(async(close) => {", 544 | " server.close(() => {", 545 | " close()", 546 | " console.log('server closed');", 547 | " })", 548 | "})" 549 | ], 550 | "description": "Ensures the web app closes down after the test run, this is needed" 551 | }, 552 | "supertest-testGET": { 553 | "prefix": "node-supertest-testget", 554 | "body": [ 555 | "test('testing a GET route', async () => {", 556 | " let products = [", 557 | " {", 558 | " id: 1,", 559 | " name: 'book'", 560 | " },", 561 | " {", 562 | " id: 2,", 563 | " name: 'book2'", 564 | " }", 565 | " ];", 566 | "", 567 | " const res = await request.get('/products');", 568 | " expect(res.status).toBe(200);", 569 | " expect(res.body).toEqual(products);", 570 | "})" 571 | ], 572 | "description": "An example of supertest testing a GET route" 573 | }, 574 | "supertest-testGETWithParam": { 575 | "prefix": "node-supertest-testgetwithparam", 576 | "body": [ 577 | "test('testing a GET route with router param', async () => {", 578 | " let product = {", 579 | " id: 1,", 580 | " name: 'book'", 581 | " };", 582 | " const res = await request.get('/products/1');", 583 | " expect(res.status).toBe(200);", 584 | " expect(res.body).toEqual(product);", 585 | "});" 586 | ], 587 | "description": "An example of supertest testing a GET route with a route parameter" 588 | }, 589 | "supertest-testPOSTWithParam": { 590 | "prefix": "node-supertest-testpost", 591 | "body": [ 592 | "test('testing a POST route with a payload', async () => {", 593 | " let product = {", 594 | " name: 'book3'", 595 | " };", 596 | " const res = await request", 597 | " .post('/products')", 598 | " .send(product);", 599 | " expect(res.status).toBe(200);", 600 | " expect(res.body).toEqual({ id: 3, ...product});", 601 | "", 602 | " const newRes = await request.get('/products');", 603 | " let products = [", 604 | " {", 605 | " id: 1,", 606 | " name: 'book'", 607 | " },", 608 | " {", 609 | " id: 2,", 610 | " name: 'book2'", 611 | " },", 612 | " {", 613 | " id: 3,", 614 | " name: 'book3',", 615 | " }", 616 | " ];", 617 | " expect(newRes.body).toEqual(products);", 618 | "});" 619 | ], 620 | "description": "An example of supertest testing a POST route with a payload" 621 | } 622 | } 623 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | * This folder contains all of the files necessary for your extension. 5 | * `package.json` - this is the manifest file that defines the location of the snippet file 6 | and specifies the language of the snippets. 7 | * `snippets/snippets.json` - the file containing all snippets. 8 | 9 | ## Get up and running straight away 10 | * Press `F5` to open a new window with your extension loaded. 11 | * Create a new file with a file name suffix matching your language. 12 | * Verify that your snippets are proposed on intellisense. 13 | 14 | ## Make changes 15 | * You can relaunch the extension from the debug toolbar after making changes to the files listed above. 16 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 17 | 18 | ## Install your extension 19 | * To start using your extension with Visual Studio Code copy it into the `/.vscode/extensions` folder and restart Code. 20 | * To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. 21 | --------------------------------------------------------------------------------