Skip to content

feat(server): add MongoDB support for hit counting stuff #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ SERVER_PORT=3000
# Link to the Registry Repo for redirect handler for /register
TEMPLATE_REGISTRY_REPO_URL=https://github.com/code-server-boilerplates/template-registry

# database for storing hit counters
MONGO_URL=mongodb+srv://localhost:5432/test

# for local dev, set this to false unless needed
ENABLE_WEBHOOK_ENDPOINT=false
# GitHub API token, since we'll use webhooks for handling replied and stuff
Expand Down
9 changes: 9 additions & 0 deletions .gitpod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
image: gitpod/workspace-full

tasks:
- before: yarn install
command: yarn dev

vscode:
extensions:
- [email protected]:30b7a8787b00b019734875064c013473
3 changes: 3 additions & 0 deletions .theia/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.autoSave": "on"
}
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ hosted on Divio.
repo path for specific Code Server template, which the server usually handles it through `if-else` magic (e.g. `/railway/nodejs-yarnified` for Yarnified Node.js)
* `/heroku/slug-here` - redirects to <https://heroku.com/deploy?template=https://github.com/username/slug-here>, where `username/slug-here` (in URL-decoded form) is the GitHub repo path
for specific Code Server template, which the server usually handles it through `if-else` magic (e.g. `/heroku/electron-builder` for building Electron apps like VS Code or Theia)
* `/heartbeat` - use this endpoint to check server status (even there's an endpoint specifically for health checking services,
* `/api/heartbeat` - use this endpoint to check server status (even there's an endpoint specifically for health checking services,
there's no way to detect issues in the code through this API endpoint
unless you're using an modern IDE like VS Code or Atom or even going to every single endpoint listed above
* `/register` - redirects to `process.env.TEMPLATE_REGISTRY_REPO_URL + "/issues/new/choose"`
(by default, <https://github.com/code-server-boilerplates/template-registry/issues/new/choose>)
* `/api/webhookHandler` - Reserved for GitHub webhook handling. Will develop an code handling for tnat soon.

## Development

Expand Down
23 changes: 23 additions & 0 deletions lib/visitsModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// source file: https://github.com/ahmad-ali14/siteViews-counter/blob/master/models/visits.js

const mongoose = require('mongoose');

const schemaOptions = {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
};

const visitSchema = new mongoose.Schema({

page:{
type: String,
required: true
},
counter:{
type: Number,
required: true
}
}, schemaOptions);

const visits = mongoose.model('visits', visitSchema);

module.exports = visits;
5 changes: 3 additions & 2 deletions nodemon.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"watch": [
"server.js",
".env"
".env",
"lib/**.js"
],
"delay": "10"
"delay": 2
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"cz-conventional-changelog": "^3.3.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"mongodb": "^3.6.6",
"mongoose": "^5.12.7",
"uuid": "^8.3.2"
},
"scripts": {
Expand Down
75 changes: 64 additions & 11 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
// core server
const express = require("express");
const app = express();
require("dotenv").config();
const { v4: uuidv4 } = require('uuid');

const { v4: uuidv4 } = require("uuid");

// database logic
const mongoose = require("mongoose");
const visits = require("./lib/visitsModel");

// function for hit counter stuff
countNewVisit = function (collection, slug) {
visits
.findOneAndUpdate(
{ page: slug },
{ $inc: { counter: 1 } },
{ new: true },
)
.then((data) => {
console.log("server-log-analytics: " + data);
})
.catch((err) => {
console.log("server-errors: " + err);
});
};

const registryRepo =
process.env.TEMPLATE_REGISTRY_REPO_URL ||
Expand Down Expand Up @@ -37,21 +59,33 @@ app.post("/api/webhookHandler", (req, res) => {
});

app.get("/api/webhookHandler", (req, res) => {
res.status(405).json({ ok: false, description: "Method not supported", code: 405 })
})
res
.status(405)
.json({ ok: false, description: "Method not supported", code: 405 });
});

app.get("/heroku/:boilerplateSlug", (req, res) => {
// TODO: better handle hig counting in the future
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
console.log(
"server-log-analytics: Requested slug: " + req.params.boilerplateSlug + " | Request type: heroku.com/deploy | Request ID: " + uuidv4() + " | IP Address: " + ip);
"server-log-analytics: Requested slug: " +
req.params.boilerplateSlug +
" | Request type: heroku.com/deploy | Request ID: " +
uuidv4() +
" | IP Address: " +
ip,
);
var slugVisitName = "heroku-" + req.params.boilerplateSlug;
countNewVisit(slugVisitName);
// if it's example-project, use the starter-pack repo.
if (req.params.boilerplateSlug == "example-project") {
res.redirect(
"https://heroku.com/deploy?template=https://github.com/code-server-boilerplate/starter-pack",
);
} else if (req.params.boilerplateSlug == "deploy-code-server-upstream") {
res.redirect("https://heroku.com/deploy?template=https://github.com/cdr/deploy-code-server")
res.redirect(
"https://heroku.com/deploy?template=https://github.com/cdr/deploy-code-server",
);
} else {
res.redirect(
"https://heroku.com/deploy?template=https://github.com/code-server-boilerplate/" +
Expand All @@ -62,9 +96,17 @@ app.get("/heroku/:boilerplateSlug", (req, res) => {

app.get("/railway/:boilerplateSlug", (req, res) => {
// implement better hit counting handler here
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
const ip = req.headers["x-forwarded-for"] || req.socket.remoteAddress;
console.log(
"server-log-analytics: Requested slug: " + req.params.boilerplateSlug + " | Request type: railway.app | Request ID: " + uuidv4() + " | IP Address: " + ip);
"server-log-analytics: Requested slug: " +
req.params.boilerplateSlug +
" | Request type: railway.app | Request ID: " +
uuidv4() +
" | IP Address: " +
ip,
);
var slugVisitName = "heroku-" + req.params.boilerplateSlug;
countNewVisit(slugVisitName);
// if it's example-project, use the starter-pack repo.
if (req.params.boilerplateSlug == "example-project") {
res.redirect(
Expand Down Expand Up @@ -101,6 +143,17 @@ app.get("/bootstrapper/:boilerplateSlug", (req, res) => {
});

const port = process.env.SERVER_PORT || 8080;
app.listen(port, () => {
console.log(`server-up: Now listening at port ${port}`);
});
mongoose
.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
retryWrites: true,
})
.then(() => {
console.log(`server-log-analytics: Conncted to MongoDB`);
app.listen(port, () =>
console.log(`server-up: Now listening at port ${port}`),
);
});
Loading