Skip to content

Commit

Permalink
feat: Added a express/knex example application
Browse files Browse the repository at this point in the history
  • Loading branch information
bizob2828 committed Sep 19, 2024
1 parent 3755c57 commit 5b098d1
Show file tree
Hide file tree
Showing 31 changed files with 1,231 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ This repository contains example applications and scripts that demonstrate funct
* [ESM](./esm-app) - example demonstrating how to load the agent in an [ESM](https://nodejs.org/api/esm.html) application. It also demonstrates how to register custom instrumentation for an ESM package.
* [GraphQL Dataloader](./graphql-koa-dataloader) - example using Apollo Server, koa and GraphQL dataloader
* [Kafkajs](./kafkajs) - example demonstrating [kafkajs](https://kafka.js.org/) with the Node.js agent
* [Knex](./knex) - example demonstrating knex with the Node.js agent
* [Mock Infinite Tracing Server](./mock-infinite-tracing-server) - mock gRPC server to use to locally test [infinite tracing](https://docs.newrelic.com/docs/distributed-tracing/infinite-tracing/introduction-infinite-tracing/) with a Node.js applciation
* [Nest](./nestjs) - examples demonstrating Nestjs with the Node.js agent
* [Next.js](./nextjs) - examples demonstrating Next.js with the Node.js agent
Expand Down
22 changes: 22 additions & 0 deletions knex/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)

Copyright (c) 2018, Rob McLarty (http://robmclarty.com)

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 changes: 29 additions & 0 deletions knex/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Knex/Express Example Application

This is an example app that uses the [New Relic hybrid agent](https://github.com/newrelic/newrelic-node-opentelemetry-integration) to demonstrate how to create both New Relic and OpenTelemetry spans.


## Setup
**Note**: This is used to demonstrate behavior between the New Relic Node.js agent and hybrid agent. The hybrid agent is currently only available to New Relic employees.

### Get hybrid agent

```sh
git clone [email protected]:newrelic/newrelic-node-opentelemetry-integration.git
npm install
npm link
```

```sh
npm install
cp env.sample .env
# Fill out `NEW_RELIC_LICENSE_KEY`
npm link @newrelic/opentelemetry-integration
docker compose up -d
npm run db:migrate
npm run db:seed
npm start
```

## Exploring Telemetry
More to come later...
8 changes: 8 additions & 0 deletions knex/config/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict'

const env = process.env.NODE_ENV || 'development'
const knexfile = require('../knexfile')
debugger
const knex = require('knex')(knexfile[env])

module.exports = knex
14 changes: 14 additions & 0 deletions knex/db/migrations/20180326094647_create_users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
exports.up = knex => {
return knex.schema.createTable('users', t => {
t.increments('id').primary().unsigned()
t.string('username').unique().index()
t.string('password')
t.string('email').unique().index()
t.timestamp('created_at').defaultTo(knex.fn.now())
t.timestamp('updated_at').defaultTo(knex.fn.now())
})
}

exports.down = knex => {
return knex.schema.dropTable('users')
}
15 changes: 15 additions & 0 deletions knex/db/migrations/20180326105452_create_projects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
exports.up = knex => {
return knex.schema.createTable('projects', t => {
t.increments('id').primary().unsigned()
t.integer('user_id').references('users.id').unsigned().index().onDelete('CASCADE')
t.string('name')
t.text('description')
t.timestamp('completed_at')
t.timestamp('created_at').defaultTo(knex.fn.now())
t.timestamp('updated_at').defaultTo(knex.fn.now())
})
}

exports.down = knex => {
return knex.schema.dropTable('projects')
}
19 changes: 19 additions & 0 deletions knex/db/seeds/001_users_seed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict'

const { User } = require('../../server/models')

exports.seed = knex => knex(User.tableName).del()
.then(() => [
{
username: 'admin',
password: 'password',
email: '[email protected]'
},
{
username: 'first-user',
password: 'another-password',
email: '[email protected]'
}
])
.then(newUsers => Promise.all(newUsers.map(user => User.create(user))))
.catch(err => console.log('err: ', err))
26 changes: 26 additions & 0 deletions knex/db/seeds/002_project_seed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict'

const { User, Project } = require('../../server/models')

exports.seed = knex => knex(Project.tableName).del()
.then(() => User.findAll())
.then(users => {
if (users.length <= 0) throw 'No users found'

return users[0].id
})
.then(userId => [
{
user_id: userId,
name: 'Sample Project',
description: 'This is just a sample project to create some data to look at.'
},
{
user_id: userId,
name: 'Another Project',
description: 'This is another project of sample data.',
completed_at: knex.fn.now()
}
])
.then(newProjects => Promise.all(newProjects.map(project => Project.create(project))))
.catch(err => console.log('err: ', err))
18 changes: 18 additions & 0 deletions knex/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
version: '3'

services:
db:
container_name: pg_knex
image: postgres:15
ports:
- "5436:5436"
environment:
PGPORT: 5436
POSTGRES_PASSWORD: newrelic
POSTGRES_DB: knex
healthcheck:
test: ["CMD", "pg_isready"]
interval: 1s
timeout: 10s
retries: 30

7 changes: 7 additions & 0 deletions knex/docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Knex Express Project Sample Documentation

## Usage

- [Auth](./usage/auth.md)
- [Users](./usage/users.md)
- [Projects](./usage/projects.md)
59 changes: 59 additions & 0 deletions knex/docs/usage/auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Authentication

This being a sample application, this is by no means a proper authentication
implementation and is only meant to demonstrate some very basic concepts in
the context of knex and express.

## Login

### Request

```shell
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"username":"admin", "password":"password"}' \
http://localhost:3000/login
```

### Response

```json
{
"ok": true,
"message": "Login successful",
"user": {
"id": 1,
"username": "admin",
"email": "[email protected]",
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
}
}
```

## Register

```shell
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"username":"new-user", "password":"my-password", "email":"[email protected]"}' \
http://localhost:3000/register
```

### Response

```json
{
"ok": true,
"message": "Registration successful",
"user": {
"id": 2,
"username": "new-user",
"email": "[email protected]",
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
}
}
```
145 changes: 145 additions & 0 deletions knex/docs/usage/projects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Projects

Basic CRUD for interacting with the JSON API's project resources.

## Create

### Request

```shell
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"name":"my-project", "description":"This is my description of this project."}' \
http://localhost:3000/users/1/projects
```

### Response

```json
{
"ok": true,
"message": "Project created",
"project": {
"id": 1,
"name": "my-project",
"description": "This is my description of this project.",
"completed_at": null,
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
}
}
```

## List

### Request

```shell
curl \
-X GET \
http://localhost:3000/users/1/projects
```

### Response

```json
{
"ok": true,
"message": "Projects found",
"projects": [
{
"id": 1,
"name": "my-project",
"description": "This is my description of this project.",
"completed_at": null,
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
},
{
"id": 2,
"name": "my-other-project",
"description": "This is my other project description.",
"completed_at": "2018-04-03 14:43:02.183277-04",
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
}
]
}
```

## Get

### Request

```shell
curl \
-X GET \
http://localhost:3000/projects/1
```

### Response

```json
{
"ok": true,
"message": "Project found",
"project": {
"id": 1,
"name": "my-project",
"description": "This is my description of this project.",
"completed_at": null,
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
}
}
```

## Update

### Request

```shell
curl \
-X PUT \
-H "Content-Type: application/json" \
-d '{"name":"my-new-name", "completed_at":"2018-04-03 14:43:02"}' \
http://localhost:3000/projects/1
```

### Response

```json
{
"ok": true,
"message": "Project updated",
"project": {
"id": 1,
"name": "my-new-name",
"description": "This is my description of this project.",
"completed_at": "2018-04-03 14:43:02.183277-04",
"created_at": "2018-04-03 14:43:02.183277-04",
"updated_at": "2018-04-03 14:43:02.183277-04"
}
}
```

## Delete

### Request

```shell
curl \
-X DELETE \
http://localhost:3000/projects/2
```

### Response

```json
{
"ok": true,
"message": "Project '2' deleted",
"deleteCount": 1
}
```
Loading

0 comments on commit 5b098d1

Please sign in to comment.