├── .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 | 
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 |

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 |

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 |
--------------------------------------------------------------------------------