├── .gitignore ├── README.md ├── src ├── model │ ├── provDtl.js │ ├── provMap.js │ └── cityMap.js ├── routes │ └── api-router.js ├── app.js ├── controllers │ └── controller.js └── helpers │ └── route-helpers.js ├── package.json └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.env 3 | .vercel 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repo currently not updated again and going off from the distribution. New update of this repo is continue to new repo [WhatGeo](https://github.com/Z4nR/WhatGeo) thanks for your attention. 2 | -------------------------------------------------------------------------------- /src/model/provDtl.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const provgeo = require("./provMap"); 3 | const { Schema } = mongoose; 4 | 5 | const ProvDtlSchema = new Schema({ 6 | _id: String, 7 | prov_id: Number, 8 | provCapital: String, 9 | }); 10 | 11 | const provdtl = mongoose.model("provdtl", ProvDtlSchema, "ProvDetail"); 12 | module.exports = provdtl; 13 | -------------------------------------------------------------------------------- /src/model/provMap.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const ProvSchema = new Schema({ 5 | _id: Number, 6 | provFeature: { 7 | type: { 8 | type: String, 9 | required: true, 10 | }, 11 | }, 12 | island: String, 13 | }); 14 | 15 | const provgeo = mongoose.model("provlatlong", ProvSchema, "ProvLatLong"); 16 | module.exports = provgeo; 17 | -------------------------------------------------------------------------------- /src/model/cityMap.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { Schema } = mongoose; 3 | 4 | const CitySchema = new Schema({ 5 | _id: Number, 6 | prov_id: Number, 7 | cityFeature: { 8 | type: { 9 | type: String, 10 | required: true, 11 | }, 12 | }, 13 | island: String, 14 | }); 15 | 16 | const citygeo = mongoose.model("citylatlong", CitySchema, "CityLatLong"); 17 | module.exports = citygeo; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "10.geobackend", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "node src/app.js", 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "server": "nodemon src/app.js" 10 | }, 11 | "keywords": [ 12 | "geoapi" 13 | ], 14 | "author": "Z4nR", 15 | "license": "ISC", 16 | "dependencies": { 17 | "body-parser": "^1.20.1", 18 | "cors": "^2.8.5", 19 | "dotenv": "^14.3.2", 20 | "express": "^4.18.2", 21 | "express-promise-router": "^4.1.1", 22 | "joi": "^17.9.2", 23 | "mongoose": "^6.7.2", 24 | "nodemon": "^2.0.20" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Zulham aka ZAN 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/routes/api-router.js: -------------------------------------------------------------------------------- 1 | const { 2 | getProvMap, 3 | getProvByIsland, 4 | getProvDetail, 5 | getCityByProv, 6 | getProvMapPage, 7 | getProvOnIslandPage, 8 | getCityByProvPage, 9 | } = require("../controllers/controller"); 10 | const { 11 | validatePage, 12 | schema, 13 | validateProvId, 14 | validateIsland, 15 | validateIslandPage, 16 | validateProvPage, 17 | } = require("../helpers/route-helpers"); 18 | const router = require("express-promise-router")(); 19 | 20 | //TotalPage 21 | router.route("/get-prov-page").get(getProvMapPage); 22 | router 23 | .route("/get-prov-onIsland-page") 24 | .get(validateIsland(schema.island, "island"), getProvOnIslandPage); //query ?island={String} 25 | router 26 | .route("/get-city-prov-page") 27 | .get(validateProvId(schema.prov_id, "prov_id"), getCityByProvPage); //query ?prov_id={Int} 28 | 29 | //Province 30 | router 31 | .route("/get-province-all") 32 | .get(validatePage(schema.page, "page"), getProvMap); //query ?page={Int} 33 | router 34 | .route("/get-prov-detail") 35 | .get(validateProvId(schema.prov_id, "prov_id"), getProvDetail); 36 | router 37 | .route("/get-prov-onIsland") 38 | .get( 39 | validateIslandPage(schema.islandPage, "island", "page"), 40 | getProvByIsland 41 | ); //query ?island={String}&page={Int} 42 | 43 | //City 44 | router 45 | .route("/get-city-prov") 46 | .get(validateProvPage(schema.provPage, "prov_id", "page"), getCityByProv); //query ?prov_id={Int}&page={Int} 47 | 48 | module.exports = router; 49 | -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | const express = require("express"), 2 | mongoose = require("mongoose"), 3 | route = require("./routes/api-router"), 4 | app = express(), 5 | bodyParser = require("body-parser"), 6 | cors = require("cors"); 7 | 8 | require("dotenv").config(); 9 | 10 | const env = process.env.NODE_ENV; 11 | 12 | //Handling Console.log 13 | if (env !== "development") { 14 | console.log = function () {}; 15 | } 16 | 17 | //Async Await 18 | mongoose.Promise = global.Promise; 19 | 20 | //Middleware 21 | app.use( 22 | cors({ 23 | origin: "*", 24 | methods: ["GET"], 25 | }) 26 | ); 27 | app.use(bodyParser.json()); 28 | 29 | //Router 30 | app.use("/v1", route); 31 | 32 | //Catch 404 Error 33 | app.use((req, res, next) => { 34 | const err = new Error("Not Found, Try Again"); 35 | err.status = 404; 36 | next(err); 37 | }); 38 | 39 | //Error Handler Function 40 | app.use((err, req, res, next) => { 41 | const error = app.get("env") === "development" ? err : {}; 42 | const status = err.status || 500; 43 | 44 | res.status(status).json({ 45 | error: { 46 | message: error.message, 47 | }, 48 | }); 49 | 50 | console.log(err); 51 | }); 52 | 53 | //Connect DB 54 | const mongo = mongoose.connect(process.env.DB_CONNECTION, { 55 | useUnifiedTopology: true, 56 | useNewUrlParser: true, 57 | }); 58 | 59 | mongo 60 | .then(() => { 61 | console.log("DB Running"); 62 | }) 63 | .catch((err) => { 64 | console.log(err); 65 | }); 66 | 67 | //Listen to port 68 | const port = process.env.PORT || 3000; 69 | app.listen(port, () => { 70 | console.log("Running"); 71 | console.log(port); 72 | }); 73 | -------------------------------------------------------------------------------- /src/controllers/controller.js: -------------------------------------------------------------------------------- 1 | const citygeo = require("../model/cityMap"); 2 | const provDtl = require("../model/provDtl"); 3 | const provgeo = require("../model/provMap"); 4 | 5 | let pageNumber = 1; 6 | const provLimit = 3; 7 | const cityLimit = 8; 8 | 9 | module.exports = { 10 | getProvMapPage: async (req, res, next) => { 11 | const provLength = await provgeo.count(); 12 | 13 | res.status(200).json({ 14 | totalPage: Math.ceil(provLength / Number.parseInt(provLimit)), 15 | }); 16 | }, 17 | 18 | getProvMap: async (req, res, next) => { 19 | const page = req.value.query; 20 | if (!Number.isNaN(page) && page > 0) { 21 | pageNumber = page; 22 | } 23 | 24 | const prov = await provgeo 25 | .find() 26 | .skip((pageNumber - 1) * provLimit) 27 | .limit(provLimit) 28 | .sort({ _id: 1 }); 29 | 30 | if (page <= 0) { 31 | res.status(404).json({ 32 | msg: "Nomor page tidak terdeteksi, silahkan mulai dengan query ?page=1", 33 | }); 34 | } else { 35 | res.status(200).json(prov); 36 | } 37 | }, 38 | 39 | getProvOnIslandPage: async (req, res, next) => { 40 | const island = req.value.query; 41 | const provOnIslandLength = await provgeo.find({ island }).count(); 42 | 43 | res.status(200).json({ 44 | totalPage: Math.ceil(provOnIslandLength / Number.parseInt(provLimit)), 45 | }); 46 | }, 47 | 48 | getProvByIsland: async (req, res, next) => { 49 | const { island } = req.value.query; 50 | 51 | const { page } = req.value.query; 52 | if (!Number.isNaN(page) && page > 0) { 53 | pageNumber = page; 54 | } 55 | 56 | const provIsland = await provgeo 57 | .find({ island }) 58 | .skip((pageNumber - 1) * provLimit) 59 | .limit(provLimit) 60 | .sort({ _id: 1 }); 61 | 62 | if (page <= 0) { 63 | res.status(404).json({ 64 | msg: "Nomor page tidak terdeteksi, silahkan mulai dengan query ?page=1", 65 | }); 66 | } else { 67 | res.status(200).json(provIsland); 68 | } 69 | }, 70 | 71 | getProvDetail: async (req, res, next) => { 72 | const prov_id = req.value.query; 73 | const detailProv = await provDtl.find({ _id: prov_id }); 74 | console.log(detailProv); 75 | res.status(200).json(detailProv); 76 | }, 77 | 78 | getCityByProvPage: async (req, res, next) => { 79 | const prov_id = req.value.query; 80 | const cityByProvLength = await citygeo.find({ prov_id }).count(); 81 | 82 | res.status(200).json({ 83 | totalPage: Math.ceil(cityByProvLength / Number.parseInt(cityLimit)), 84 | }); 85 | }, 86 | 87 | getCityByProv: async (req, res, next) => { 88 | const { prov_id } = req.value.query; 89 | 90 | const { page } = req.value.query; 91 | if (!Number.isNaN(page) && page > 0) { 92 | pageNumber = page; 93 | } 94 | 95 | const cityProv = await citygeo 96 | .find({ prov_id }) 97 | .skip((pageNumber - 1) * cityLimit) 98 | .limit(cityLimit) 99 | .sort({ _id: 1 }); 100 | 101 | if (page <= 0) { 102 | res.status(404).json({ 103 | msg: "Nomor page tidak terdeteksi, silahkan mulai dengan query ?page=1", 104 | }); 105 | } else { 106 | res.status(200).json(cityProv); 107 | } 108 | }, 109 | }; 110 | -------------------------------------------------------------------------------- /src/helpers/route-helpers.js: -------------------------------------------------------------------------------- 1 | const Joi = require("joi"); 2 | 3 | module.exports = { 4 | validatePage: (schema, page) => { 5 | return (req, res, next) => { 6 | console.log(req.query); 7 | 8 | const pageNumber = Number.parseInt(req["query"][page]); 9 | 10 | const result = schema.validate(pageNumber); 11 | 12 | console.log(result); 13 | 14 | if (result.error) { 15 | return res.status(400).json(result.error); 16 | } else { 17 | if (!req.value) { 18 | req.value = {}; 19 | } 20 | 21 | if (!req.value["query"]) { 22 | req.value["query"] = {}; 23 | } 24 | 25 | req.value["query"] = result.value; 26 | 27 | next(); 28 | } 29 | }; 30 | }, 31 | 32 | validateProvId: (schema, prov_id) => { 33 | return (req, res, next) => { 34 | console.log(req.query); 35 | 36 | const provId = Number.parseInt(req["query"][prov_id]); 37 | 38 | const result = schema.validate(provId); 39 | 40 | console.log(result); 41 | 42 | if (result.error) { 43 | return res.status(400).json(result.error); 44 | } else { 45 | if (!req.value) { 46 | req.value = {}; 47 | } 48 | 49 | if (!req.value["query"]) { 50 | req.value["query"] = {}; 51 | } 52 | 53 | req.value["query"] = result.value; 54 | 55 | next(); 56 | } 57 | }; 58 | }, 59 | 60 | validateIsland: (schema, island) => { 61 | return (req, res, next) => { 62 | console.log(req.query); 63 | 64 | const islandName = req["query"][island]; 65 | 66 | const result = schema.validate(islandName); 67 | 68 | console.log(result); 69 | 70 | if (result.error) { 71 | return res.status(400).json(result.error); 72 | } else { 73 | if (!req.value) { 74 | req.value = {}; 75 | } 76 | 77 | if (!req.value["query"]) { 78 | req.value["query"] = {}; 79 | } 80 | 81 | req.value["query"] = result.value; 82 | 83 | next(); 84 | } 85 | }; 86 | }, 87 | 88 | validateIslandPage: (schema, island, page) => { 89 | return (req, res, next) => { 90 | console.log(req.query); 91 | 92 | const pageNumber = Number.parseInt(req["query"][page]); 93 | const islandName = req["query"][island]; 94 | 95 | const result = schema.validate({ island: islandName, page: pageNumber }); 96 | 97 | console.log(result); 98 | 99 | if (result.error) { 100 | return res.status(400).json(result.error); 101 | } else { 102 | if (!req.value) { 103 | req.value = {}; 104 | } 105 | 106 | if (!req.value["query"]) { 107 | req.value["query"] = {}; 108 | } 109 | 110 | req.value["query"][island] = result.value.island; 111 | req.value["query"][page] = result.value.page; 112 | 113 | next(); 114 | } 115 | }; 116 | }, 117 | 118 | validateProvPage: (schema, prov_id, page) => { 119 | return (req, res, next) => { 120 | console.log(req.query); 121 | 122 | const pageNumber = Number.parseInt(req["query"][page]); 123 | const provId = Number.parseInt(req["query"][prov_id]); 124 | 125 | const result = schema.validate({ prov_id: provId, page: pageNumber }); 126 | 127 | console.log(result); 128 | 129 | if (result.error) { 130 | return res.status(400).json(result.error); 131 | } else { 132 | if (!req.value) { 133 | req.value = {}; 134 | } 135 | 136 | if (!req.value["query"]) { 137 | req.value["query"] = {}; 138 | } 139 | 140 | req.value["query"][prov_id] = result.value.prov_id; 141 | req.value["query"][page] = result.value.page; 142 | 143 | next(); 144 | } 145 | }; 146 | }, 147 | 148 | schema: { 149 | page: Joi.number().integer().required(), 150 | island: Joi.string().required(), 151 | prov_id: Joi.number().integer().required(), 152 | islandPage: Joi.object().keys({ 153 | page: Joi.number().integer().required(), 154 | island: Joi.string().required(), 155 | }), 156 | provPage: Joi.object().keys({ 157 | page: Joi.number().integer().required(), 158 | prov_id: Joi.number().integer().required(), 159 | }), 160 | }, 161 | }; 162 | --------------------------------------------------------------------------------