[MAJOR][FIRSTCOMMIT] Added basic routes, controllers, repos to kanban service (no postgres yet)
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -133,4 +133,5 @@ dist/
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
/generated/prisma
|
||||
|
||||
142
Aragon-Kanban-API.postman_collection.json
Normal file
142
Aragon-Kanban-API.postman_collection.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"info": {
|
||||
"name": "Aragon Kanban API",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||
"description": "Postman collection for Users, Boards, and Tasks API"
|
||||
},
|
||||
"item": [
|
||||
{
|
||||
"name": "Users",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get All Users",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/users", "host": ["{{baseUrl}}"], "path": ["users"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Add User",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"body": { "mode": "raw", "raw": "{\n \"user\": {\n \"id\": 1,\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}" },
|
||||
"url": { "raw": "{{baseUrl}}/users", "host": ["{{baseUrl}}"], "path": ["users"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Update User",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"body": { "mode": "raw", "raw": "{\n \"user\": {\n \"id\": 1,\n \"name\": \"Jane Doe\",\n \"email\": \"jane@example.com\"\n }\n}" },
|
||||
"url": { "raw": "{{baseUrl}}/users", "host": ["{{baseUrl}}"], "path": ["users"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Delete User",
|
||||
"request": {
|
||||
"method": "DELETE",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/users/1", "host": ["{{baseUrl}}"], "path": ["users", "1"] }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Boards",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get All Boards for User",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/boards/user/1", "host": ["{{baseUrl}}"], "path": ["boards", "user", "1"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Get Board by ID",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/boards/user/1/123", "host": ["{{baseUrl}}"], "path": ["boards", "user", "1", "123"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Add Board",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"body": { "mode": "raw", "raw": "{\n \"name\": \"Project Board\"\n}" },
|
||||
"url": { "raw": "{{baseUrl}}/boards/user/1", "host": ["{{baseUrl}}"], "path": ["boards", "user", "1"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Update Board",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"body": { "mode": "raw", "raw": "{\n \"name\": \"Updated Board Name\"\n}" },
|
||||
"url": { "raw": "{{baseUrl}}/boards/user/1/123", "host": ["{{baseUrl}}"], "path": ["boards", "user", "1", "123"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Delete Board",
|
||||
"request": {
|
||||
"method": "DELETE",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/boards/user/1/123", "host": ["{{baseUrl}}"], "path": ["boards", "user", "1", "123"] }
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Tasks",
|
||||
"item": [
|
||||
{
|
||||
"name": "Get All Tasks for Board",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/tasks/board/123", "host": ["{{baseUrl}}"], "path": ["tasks", "board", "123"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Get Task by ID",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/tasks/board/123/456", "host": ["{{baseUrl}}"], "path": ["tasks", "board", "123", "456"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Add Task",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"body": { "mode": "raw", "raw": "{\n \"title\": \"New Task\",\n \"description\": \"Task details\",\n \"status\": \"todo\"\n}" },
|
||||
"url": { "raw": "{{baseUrl}}/tasks/board/123", "host": ["{{baseUrl}}"], "path": ["tasks", "board", "123"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Update Task",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [{"key": "Content-Type", "value": "application/json"}, {"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"body": { "mode": "raw", "raw": "{\n \"title\": \"Updated Task\",\n \"description\": \"Updated details\",\n \"status\": \"done\"\n}" },
|
||||
"url": { "raw": "{{baseUrl}}/tasks/board/123/456", "host": ["{{baseUrl}}"], "path": ["tasks", "board", "123", "456"] }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Delete Task",
|
||||
"request": {
|
||||
"method": "DELETE",
|
||||
"header": [{"key": "Authorization", "value": "Bearer testtoken"}],
|
||||
"url": { "raw": "{{baseUrl}}/tasks/board/123/456", "host": ["{{baseUrl}}"], "path": ["tasks", "board", "123", "456"] }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
29
lib/constants/EnvVars.js
Normal file
29
lib/constants/EnvVars.js
Normal file
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Environments variables declared here.
|
||||
*/
|
||||
var _a, _b, _c, _d, _e, _f, _g;
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/* eslint-disable node/no-process-env */
|
||||
exports.default = {
|
||||
NodeEnv: ((_a = process.env.NODE_ENV) !== null && _a !== void 0 ? _a : ''),
|
||||
Port: ((_b = process.env.PORT) !== null && _b !== void 0 ? _b : 0),
|
||||
CookieProps: {
|
||||
Key: 'ExpressGeneratorTs',
|
||||
Secret: ((_c = process.env.COOKIE_SECRET) !== null && _c !== void 0 ? _c : ''),
|
||||
// Casing to match express cookie options
|
||||
Options: {
|
||||
httpOnly: true,
|
||||
signed: true,
|
||||
path: ((_d = process.env.COOKIE_PATH) !== null && _d !== void 0 ? _d : ''),
|
||||
maxAge: Number((_e = process.env.COOKIE_EXP) !== null && _e !== void 0 ? _e : 0),
|
||||
domain: ((_f = process.env.COOKIE_DOMAIN) !== null && _f !== void 0 ? _f : ''),
|
||||
secure: (process.env.SECURE_COOKIE === 'true'),
|
||||
},
|
||||
},
|
||||
Jwt: {
|
||||
Secret: ((_g = process.env.JWT_SECRET) !== null && _g !== void 0 ? _g : ''),
|
||||
Exp: (process.env.COOKIE_EXP && process.env.COOKIE_EXP !== '' ? process.env.COOKIE_EXP : '1h'), // exp at the same time as the cookie
|
||||
},
|
||||
};
|
||||
//# sourceMappingURL=EnvVars.js.map
|
||||
1
lib/constants/EnvVars.js.map
Normal file
1
lib/constants/EnvVars.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"EnvVars.js","sourceRoot":"","sources":["../../src/constants/EnvVars.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,wCAAwC;AAGxC,kBAAe;IACb,OAAO,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,QAAQ,mCAAI,EAAE,CAAC;IACrC,IAAI,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,IAAI,mCAAI,CAAC,CAAC;IAC7B,WAAW,EAAE;QACX,GAAG,EAAE,oBAAoB;QACzB,MAAM,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,aAAa,mCAAI,EAAE,CAAC;QACzC,yCAAyC;QACzC,OAAO,EAAE;YACP,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,WAAW,mCAAI,EAAE,CAAC;YACrC,MAAM,EAAE,MAAM,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,UAAU,mCAAI,CAAC,CAAC;YAC3C,MAAM,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,aAAa,mCAAI,EAAE,CAAC;YACzC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,MAAM,CAAC;SAC/C;KACF;IACD,GAAG,EAAE;QACH,MAAM,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,UAAU,mCAAK,EAAE,CAAC;QACvC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,qCAAqC;KACtI;CACO,CAAC"}
|
||||
327
lib/constants/HttpStatusCodes.js
Normal file
327
lib/constants/HttpStatusCodes.js
Normal file
@@ -0,0 +1,327 @@
|
||||
"use strict";
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* This file was copied from here: https://gist.github.com/scokmen/f813c904ef79022e84ab2409574d1b45
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
/**
|
||||
* Hypertext Transfer Protocol (HTTP) response status codes.
|
||||
* @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}
|
||||
*/
|
||||
var HttpStatusCodes;
|
||||
(function (HttpStatusCodes) {
|
||||
/**
|
||||
* The server has received the request headers and the client should proceed to send the request body
|
||||
* (in the case of a request for which a body needs to be sent; for example, a POST request).
|
||||
* Sending a large request body to a server after a request has been rejected for inappropriate headers would be inefficient.
|
||||
* To have a server check the request's headers, a client must send Expect: 100-continue as a header in its initial request
|
||||
* and receive a 100 Continue status code in response before sending the body. The response 417 Expectation Failed indicates the request should not be continued.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["CONTINUE"] = 100] = "CONTINUE";
|
||||
/**
|
||||
* The requester has asked the server to switch protocols and the server has agreed to do so.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["SWITCHING_PROTOCOLS"] = 101] = "SWITCHING_PROTOCOLS";
|
||||
/**
|
||||
* A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request.
|
||||
* This code indicates that the server has received and is processing the request, but no response is available yet.
|
||||
* This prevents the client from timing out and assuming the request was lost.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PROCESSING"] = 102] = "PROCESSING";
|
||||
/**
|
||||
* Standard response for successful HTTP requests.
|
||||
* The actual response will depend on the request method used.
|
||||
* In a GET request, the response will contain an entity corresponding to the requested resource.
|
||||
* In a POST request, the response will contain an entity describing or containing the result of the action.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["OK"] = 200] = "OK";
|
||||
/**
|
||||
* The request has been fulfilled, resulting in the creation of a new resource.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["CREATED"] = 201] = "CREATED";
|
||||
/**
|
||||
* The request has been accepted for processing, but the processing has not been completed.
|
||||
* The request might or might not be eventually acted upon, and may be disallowed when processing occurs.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["ACCEPTED"] = 202] = "ACCEPTED";
|
||||
/**
|
||||
* SINCE HTTP/1.1
|
||||
* The server is a transforming proxy that received a 200 OK from its origin,
|
||||
* but is returning a modified version of the origin's response.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NON_AUTHORITATIVE_INFORMATION"] = 203] = "NON_AUTHORITATIVE_INFORMATION";
|
||||
/**
|
||||
* The server successfully processed the request and is not returning any content.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NO_CONTENT"] = 204] = "NO_CONTENT";
|
||||
/**
|
||||
* The server successfully processed the request, but is not returning any content.
|
||||
* Unlike a 204 response, this response requires that the requester reset the document view.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["RESET_CONTENT"] = 205] = "RESET_CONTENT";
|
||||
/**
|
||||
* The server is delivering only part of the resource (byte serving) due to a range header sent by the client.
|
||||
* The range header is used by HTTP clients to enable resuming of interrupted downloads,
|
||||
* or split a download into multiple simultaneous streams.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PARTIAL_CONTENT"] = 206] = "PARTIAL_CONTENT";
|
||||
/**
|
||||
* The message body that follows is an XML message and can contain a number of separate response codes,
|
||||
* depending on how many sub-requests were made.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["MULTI_STATUS"] = 207] = "MULTI_STATUS";
|
||||
/**
|
||||
* The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response,
|
||||
* and are not being included again.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["ALREADY_REPORTED"] = 208] = "ALREADY_REPORTED";
|
||||
/**
|
||||
* The server has fulfilled a request for the resource,
|
||||
* and the response is a representation of the result of one or more instance-manipulations applied to the current instance.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["IM_USED"] = 226] = "IM_USED";
|
||||
/**
|
||||
* Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation).
|
||||
* For example, this code could be used to present multiple video format options,
|
||||
* to list files with different filename extensions, or to suggest word-sense disambiguation.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["MULTIPLE_CHOICES"] = 300] = "MULTIPLE_CHOICES";
|
||||
/**
|
||||
* This and all future requests should be directed to the given URI.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["MOVED_PERMANENTLY"] = 301] = "MOVED_PERMANENTLY";
|
||||
/**
|
||||
* This is an example of industry practice contradicting the standard.
|
||||
* The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect
|
||||
* (the original describing phrase was "Moved Temporarily"), but popular browsers implemented 302
|
||||
* with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307
|
||||
* to distinguish between the two behaviours. However, some Web applications and frameworks
|
||||
* use the 302 status code as if it were the 303.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["FOUND"] = 302] = "FOUND";
|
||||
/**
|
||||
* SINCE HTTP/1.1
|
||||
* The response to the request can be found under another URI using a GET method.
|
||||
* When received in response to a POST (or PUT/DELETE), the client should presume that
|
||||
* the server has received the data and should issue a redirect with a separate GET message.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["SEE_OTHER"] = 303] = "SEE_OTHER";
|
||||
/**
|
||||
* Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match.
|
||||
* In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NOT_MODIFIED"] = 304] = "NOT_MODIFIED";
|
||||
/**
|
||||
* SINCE HTTP/1.1
|
||||
* The requested resource is available only through a proxy, the address for which is provided in the response.
|
||||
* Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["USE_PROXY"] = 305] = "USE_PROXY";
|
||||
/**
|
||||
* No longer used. Originally meant "Subsequent requests should use the specified proxy."
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["SWITCH_PROXY"] = 306] = "SWITCH_PROXY";
|
||||
/**
|
||||
* SINCE HTTP/1.1
|
||||
* In this case, the request should be repeated with another URI; however, future requests should still use the original URI.
|
||||
* In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request.
|
||||
* For example, a POST request should be repeated using another POST request.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["TEMPORARY_REDIRECT"] = 307] = "TEMPORARY_REDIRECT";
|
||||
/**
|
||||
* The request and all future requests should be repeated using another URI.
|
||||
* 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change.
|
||||
* So, for example, submitting a form to a permanently redirected resource may continue smoothly.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PERMANENT_REDIRECT"] = 308] = "PERMANENT_REDIRECT";
|
||||
/**
|
||||
* The server cannot or will not process the request due to an apparent client error
|
||||
* (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing).
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["BAD_REQUEST"] = 400] = "BAD_REQUEST";
|
||||
/**
|
||||
* Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet
|
||||
* been provided. The response must include a WWW-Authenticate header field containing a challenge applicable to the
|
||||
* requested resource. See Basic access authentication and Digest access authentication. 401 semantically means
|
||||
* "unauthenticated",i.e. the user does not have the necessary credentials.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
|
||||
/**
|
||||
* Reserved for future use. The original intention was that this code might be used as part of some form of digital
|
||||
* cash or micro payment scheme, but that has not happened, and this code is not usually used.
|
||||
* Google Developers API uses this status if a particular developer has exceeded the daily limit on requests.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PAYMENT_REQUIRED"] = 402] = "PAYMENT_REQUIRED";
|
||||
/**
|
||||
* The request was valid, but the server is refusing action.
|
||||
* The user might not have the necessary permissions for a resource.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["FORBIDDEN"] = 403] = "FORBIDDEN";
|
||||
/**
|
||||
* The requested resource could not be found but may be available in the future.
|
||||
* Subsequent requests by the client are permissible.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NOT_FOUND"] = 404] = "NOT_FOUND";
|
||||
/**
|
||||
* A request method is not supported for the requested resource;
|
||||
* for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["METHOD_NOT_ALLOWED"] = 405] = "METHOD_NOT_ALLOWED";
|
||||
/**
|
||||
* The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NOT_ACCEPTABLE"] = 406] = "NOT_ACCEPTABLE";
|
||||
/**
|
||||
* The client must first authenticate itself with the proxy.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PROXY_AUTHENTICATION_REQUIRED"] = 407] = "PROXY_AUTHENTICATION_REQUIRED";
|
||||
/**
|
||||
* The server timed out waiting for the request.
|
||||
* According to HTTP specifications:
|
||||
* "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time."
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["REQUEST_TIMEOUT"] = 408] = "REQUEST_TIMEOUT";
|
||||
/**
|
||||
* Indicates that the request could not be processed because of conflict in the request,
|
||||
* such as an edit conflict between multiple simultaneous updates.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["CONFLICT"] = 409] = "CONFLICT";
|
||||
/**
|
||||
* Indicates that the resource requested is no longer available and will not be available again.
|
||||
* This should be used when a resource has been intentionally removed and the resource should be purged.
|
||||
* Upon receiving a 410 status code, the client should not request the resource in the future.
|
||||
* Clients such as search engines should remove the resource from their indices.
|
||||
* Most use cases do not require clients and search engines to purge the resource, and a "404 Not Found" may be used instead.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["GONE"] = 410] = "GONE";
|
||||
/**
|
||||
* The request did not specify the length of its content, which is required by the requested resource.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["LENGTH_REQUIRED"] = 411] = "LENGTH_REQUIRED";
|
||||
/**
|
||||
* The server does not meet one of the preconditions that the requester put on the request.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PRECONDITION_FAILED"] = 412] = "PRECONDITION_FAILED";
|
||||
/**
|
||||
* The request is larger than the server is willing or able to process. Previously called "Request Entity Too Large".
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PAYLOAD_TOO_LARGE"] = 413] = "PAYLOAD_TOO_LARGE";
|
||||
/**
|
||||
* The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request,
|
||||
* in which case it should be converted to a POST request.
|
||||
* Called "Request-URI Too Long" previously.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["URI_TOO_LONG"] = 414] = "URI_TOO_LONG";
|
||||
/**
|
||||
* The request entity has a media type which the server or resource does not support.
|
||||
* For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["UNSUPPORTED_MEDIA_TYPE"] = 415] = "UNSUPPORTED_MEDIA_TYPE";
|
||||
/**
|
||||
* The client has asked for a portion of the file (byte serving), but the server cannot supply that portion.
|
||||
* For example, if the client asked for a part of the file that lies beyond the end of the file.
|
||||
* Called "Requested Range Not Satisfiable" previously.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["RANGE_NOT_SATISFIABLE"] = 416] = "RANGE_NOT_SATISFIABLE";
|
||||
/**
|
||||
* The server cannot meet the requirements of the Expect request-header field.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["EXPECTATION_FAILED"] = 417] = "EXPECTATION_FAILED";
|
||||
/**
|
||||
* This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol,
|
||||
* and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by
|
||||
* teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including Google.com.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["I_AM_A_TEAPOT"] = 418] = "I_AM_A_TEAPOT";
|
||||
/**
|
||||
* The request was directed at a server that is not able to produce a response (for example because a connection reuse).
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["MISDIRECTED_REQUEST"] = 421] = "MISDIRECTED_REQUEST";
|
||||
/**
|
||||
* The request was well-formed but was unable to be followed due to semantic errors.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
|
||||
/**
|
||||
* The resource that is being accessed is locked.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["LOCKED"] = 423] = "LOCKED";
|
||||
/**
|
||||
* The request failed due to failure of a previous request (e.g., a PROPPATCH).
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["FAILED_DEPENDENCY"] = 424] = "FAILED_DEPENDENCY";
|
||||
/**
|
||||
* The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["UPGRADE_REQUIRED"] = 426] = "UPGRADE_REQUIRED";
|
||||
/**
|
||||
* The origin server requires the request to be conditional.
|
||||
* Intended to prevent "the 'lost update' problem, where a client
|
||||
* GETs a resource's state, modifies it, and PUTs it back to the server,
|
||||
* when meanwhile a third party has modified the state on the server, leading to a conflict."
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["PRECONDITION_REQUIRED"] = 428] = "PRECONDITION_REQUIRED";
|
||||
/**
|
||||
* The user has sent too many requests in a given amount of time. Intended for use with rate-limiting schemes.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["TOO_MANY_REQUESTS"] = 429] = "TOO_MANY_REQUESTS";
|
||||
/**
|
||||
* The server is unwilling to process the request because either an individual header field,
|
||||
* or all the header fields collectively, are too large.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["REQUEST_HEADER_FIELDS_TOO_LARGE"] = 431] = "REQUEST_HEADER_FIELDS_TOO_LARGE";
|
||||
/**
|
||||
* A server operator has received a legal demand to deny access to a resource or to a set of resources
|
||||
* that includes the requested resource. The code 451 was chosen as a reference to the novel Fahrenheit 451.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["UNAVAILABLE_FOR_LEGAL_REASONS"] = 451] = "UNAVAILABLE_FOR_LEGAL_REASONS";
|
||||
/**
|
||||
* A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
|
||||
/**
|
||||
* The server either does not recognize the request method, or it lacks the ability to fulfill the request.
|
||||
* Usually this implies future availability (e.g., a new feature of a web-service API).
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NOT_IMPLEMENTED"] = 501] = "NOT_IMPLEMENTED";
|
||||
/**
|
||||
* The server was acting as a gateway or proxy and received an invalid response from the upstream server.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["BAD_GATEWAY"] = 502] = "BAD_GATEWAY";
|
||||
/**
|
||||
* The server is currently unavailable (because it is overloaded or down for maintenance).
|
||||
* Generally, this is a temporary state.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["SERVICE_UNAVAILABLE"] = 503] = "SERVICE_UNAVAILABLE";
|
||||
/**
|
||||
* The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["GATEWAY_TIMEOUT"] = 504] = "GATEWAY_TIMEOUT";
|
||||
/**
|
||||
* The server does not support the HTTP protocol version used in the request
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["HTTP_VERSION_NOT_SUPPORTED"] = 505] = "HTTP_VERSION_NOT_SUPPORTED";
|
||||
/**
|
||||
* Transparent content negotiation for the request results in a circular reference.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["VARIANT_ALSO_NEGOTIATES"] = 506] = "VARIANT_ALSO_NEGOTIATES";
|
||||
/**
|
||||
* The server is unable to store the representation needed to complete the request.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["INSUFFICIENT_STORAGE"] = 507] = "INSUFFICIENT_STORAGE";
|
||||
/**
|
||||
* The server detected an infinite loop while processing the request.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["LOOP_DETECTED"] = 508] = "LOOP_DETECTED";
|
||||
/**
|
||||
* Further extensions to the request are required for the server to fulfill it.
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NOT_EXTENDED"] = 510] = "NOT_EXTENDED";
|
||||
/**
|
||||
* The client needs to authenticate to gain network access.
|
||||
* Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used
|
||||
* to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
|
||||
*/
|
||||
HttpStatusCodes[HttpStatusCodes["NETWORK_AUTHENTICATION_REQUIRED"] = 511] = "NETWORK_AUTHENTICATION_REQUIRED";
|
||||
})(HttpStatusCodes || (HttpStatusCodes = {}));
|
||||
exports.default = HttpStatusCodes;
|
||||
//# sourceMappingURL=HttpStatusCodes.js.map
|
||||
1
lib/constants/HttpStatusCodes.js.map
Normal file
1
lib/constants/HttpStatusCodes.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"HttpStatusCodes.js","sourceRoot":"","sources":["../../src/constants/HttpStatusCodes.ts"],"names":[],"mappings":";AAAA,4BAA4B;AAC5B;;GAEG;;AAEH;;;GAGG;AACH,IAAK,eAsXJ;AAtXD,WAAK,eAAe;IAEhB;;;;;;OAMG;IACH,+DAAc,CAAA;IAEd;;OAEG;IACH,qFAAyB,CAAA;IAEzB;;;;OAIG;IACH,mEAAgB,CAAA;IAEhB;;;;;OAKG;IACH,mDAAQ,CAAA;IAER;;OAEG;IACH,6DAAa,CAAA;IAEb;;;OAGG;IACH,+DAAc,CAAA;IAEd;;;;OAIG;IACH,yGAAmC,CAAA;IAEnC;;OAEG;IACH,mEAAgB,CAAA;IAEhB;;;OAGG;IACH,yEAAmB,CAAA;IAEnB;;;;OAIG;IACH,6EAAqB,CAAA;IAErB;;;OAGG;IACH,uEAAkB,CAAA;IAElB;;;OAGG;IACH,+EAAsB,CAAA;IAEtB;;;OAGG;IACH,6DAAa,CAAA;IAEb;;;;OAIG;IACH,+EAAsB,CAAA;IAEtB;;OAEG;IACH,iFAAuB,CAAA;IAEvB;;;;;;;OAOG;IACH,yDAAW,CAAA;IAEX;;;;;OAKG;IACH,iEAAe,CAAA;IAEf;;;OAGG;IACH,uEAAkB,CAAA;IAElB;;;;OAIG;IACH,iEAAe,CAAA;IAEf;;OAEG;IACH,uEAAkB,CAAA;IAElB;;;;;OAKG;IACH,mFAAwB,CAAA;IAExB;;;;OAIG;IACH,mFAAwB,CAAA;IAExB;;;OAGG;IACH,qEAAiB,CAAA;IAEjB;;;;;OAKG;IACH,uEAAkB,CAAA;IAElB;;;;OAIG;IACH,+EAAsB,CAAA;IAEtB;;;OAGG;IACH,iEAAe,CAAA;IAEf;;;OAGG;IACH,iEAAe,CAAA;IAEf;;;OAGG;IACH,mFAAwB,CAAA;IAExB;;OAEG;IACH,2EAAoB,CAAA;IAEpB;;OAEG;IACH,yGAAmC,CAAA;IAEnC;;;;OAIG;IACH,6EAAqB,CAAA;IAErB;;;OAGG;IACH,+DAAc,CAAA;IAEd;;;;;;OAMG;IACH,uDAAU,CAAA;IAEV;;OAEG;IACH,6EAAqB,CAAA;IAErB;;OAEG;IACH,qFAAyB,CAAA;IAEzB;;OAEG;IACH,iFAAuB,CAAA;IAEvB;;;;OAIG;IACH,uEAAkB,CAAA;IAElB;;;OAGG;IACH,2FAA4B,CAAA;IAE5B;;;;OAIG;IACH,yFAA2B,CAAA;IAE3B;;OAEG;IACH,mFAAwB,CAAA;IAExB;;;;OAIG;IACH,yEAAmB,CAAA;IAEnB;;OAEG;IACH,qFAAyB,CAAA;IAEzB;;OAEG;IACH,uFAA0B,CAAA;IAE1B;;OAEG;IACH,2DAAY,CAAA;IAEZ;;OAEG;IACH,iFAAuB,CAAA;IAEvB;;OAEG;IACH,+EAAsB,CAAA;IAEtB;;;;;OAKG;IACH,yFAA2B,CAAA;IAE3B;;OAEG;IACH,iFAAuB,CAAA;IAEvB;;;OAGG;IACH,6GAAqC,CAAA;IAErC;;;OAGG;IACH,yGAAmC,CAAA;IAEnC;;OAEG;IACH,yFAA2B,CAAA;IAE3B;;;OAGG;IACH,6EAAqB,CAAA;IAErB;;OAEG;IACH,qEAAiB,CAAA;IAEjB;;;OAGG;IACH,qFAAyB,CAAA;IAEzB;;OAEG;IACH,6EAAqB,CAAA;IAErB;;OAEG;IACH,mGAAgC,CAAA;IAEhC;;OAEG;IACH,6FAA6B,CAAA;IAE7B;;OAEG;IACH,uFAA0B,CAAA;IAE1B;;OAEG;IACH,yEAAmB,CAAA;IAEnB;;OAEG;IACH,uEAAkB,CAAA;IAElB;;;;OAIG;IACH,6GAAqC,CAAA;AACzC,CAAC,EAtXI,eAAe,KAAf,eAAe,QAsXnB;AAED,kBAAe,eAAe,CAAC"}
|
||||
10
lib/constants/misc.js
Normal file
10
lib/constants/misc.js
Normal file
@@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.NodeEnvs = void 0;
|
||||
var NodeEnvs;
|
||||
(function (NodeEnvs) {
|
||||
NodeEnvs["Dev"] = "development";
|
||||
NodeEnvs["Test"] = "test";
|
||||
NodeEnvs["Production"] = "production";
|
||||
})(NodeEnvs || (exports.NodeEnvs = NodeEnvs = {}));
|
||||
//# sourceMappingURL=misc.js.map
|
||||
1
lib/constants/misc.js.map
Normal file
1
lib/constants/misc.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"misc.js","sourceRoot":"","sources":["../../src/constants/misc.ts"],"names":[],"mappings":";;;AAAA,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,+BAAmB,CAAA;IACnB,yBAAa,CAAA;IACb,qCAAyB,CAAA;AAC3B,CAAC,EAJW,QAAQ,wBAAR,QAAQ,QAInB"}
|
||||
62
lib/controllers/board.controller.js
Normal file
62
lib/controllers/board.controller.js
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const board_repo_1 = __importDefault(require("@src/repos/board.repo"));
|
||||
class BoardController {
|
||||
constructor() {
|
||||
// Get all boards for a user
|
||||
this.getBoardsByUserId = async (req, res) => {
|
||||
if (!req.headers.authorization) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boards = await board_repo_1.default.getBoardsByUserId(userId);
|
||||
return res.json({ boards });
|
||||
};
|
||||
// Get single board by userId and boardId
|
||||
this.getBoardByUserId = async (req, res) => {
|
||||
if (!req.headers.authorization) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardId = +req.params.boardId;
|
||||
const board = await board_repo_1.default.getBoardByUserId(userId, boardId);
|
||||
return res.json({ board });
|
||||
};
|
||||
// Create board for a user
|
||||
this.createBoard = async (req, res) => {
|
||||
if (!req.body.name) {
|
||||
return res.status(400).json({ error: 'Board name required' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardData = req.body;
|
||||
const board = await board_repo_1.default.createBoard(userId, boardData);
|
||||
return res.status(201).json({ board });
|
||||
};
|
||||
// Update board for a user
|
||||
this.updateBoard = async (req, res) => {
|
||||
if (!req.body.name) {
|
||||
return res.status(400).json({ error: 'Board name required' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardId = +req.params.boardId;
|
||||
const boardData = req.body;
|
||||
const board = await board_repo_1.default.updateBoard(userId, boardId, boardData);
|
||||
return res.json({ board });
|
||||
};
|
||||
// Delete board for a user
|
||||
this.deleteBoard = async (req, res) => {
|
||||
if (!req.headers.authorization) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardId = +req.params.boardId;
|
||||
await board_repo_1.default.deleteBoard(userId, boardId);
|
||||
return res.status(204).end();
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.default = new BoardController();
|
||||
//# sourceMappingURL=board.controller.js.map
|
||||
1
lib/controllers/board.controller.js.map
Normal file
1
lib/controllers/board.controller.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"board.controller.js","sourceRoot":"","sources":["../../src/controllers/board.controller.ts"],"names":[],"mappings":";;;;;AACA,uEAA8C;AAI9C,MAAM,eAAe;IAArB;QACE,4BAA4B;QAC5B,sBAAiB,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YACxD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;YAClC,MAAM,MAAM,GAAG,MAAM,oBAAS,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACzD,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9B,CAAC,CAAC;QAEF,yCAAyC;QACzC,qBAAgB,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YACvD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;YAClC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;YACpC,MAAM,KAAK,GAAG,MAAM,oBAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAChE,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC;QAEF,0BAA0B;QAC1B,gBAAW,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YAClD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACnB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YAChE,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;YAClC,MAAM,SAAS,GAAW,GAAG,CAAC,IAAI,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,oBAAS,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YAC7D,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC,CAAC;QAEF,0BAA0B;QAC1B,gBAAW,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YAClD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACnB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;YAChE,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;YAClC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;YACpC,MAAM,SAAS,GAAW,GAAG,CAAC,IAAI,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,oBAAS,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACtE,OAAO,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC;QAEF,0BAA0B;QAC1B,gBAAW,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YAClD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;gBAC/B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;YAClC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;YACpC,MAAM,oBAAS,CAAC,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC,CAAC;IACJ,CAAC;CAAA;AAED,kBAAe,IAAI,eAAe,EAAE,CAAC"}
|
||||
64
lib/controllers/task.controller.js
Normal file
64
lib/controllers/task.controller.js
Normal file
@@ -0,0 +1,64 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const task_repo_1 = __importDefault(require("@src/repos/task.repo"));
|
||||
class TaskController {
|
||||
constructor() {
|
||||
// Get all tasks for a board
|
||||
this.getTasksByBoardId = async (req, res) => {
|
||||
if (!req.headers.authorization) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const tasks = await task_repo_1.default.getTasksByBoardId(boardId);
|
||||
return res.json({ tasks });
|
||||
};
|
||||
// Get single task by boardId and taskId
|
||||
this.getTaskByBoardId = async (req, res) => {
|
||||
if (!req.headers.authorization) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskId = +req.params.taskId;
|
||||
const task = await task_repo_1.default.getTaskByBoardId(boardId, taskId);
|
||||
return res.json({ task });
|
||||
};
|
||||
// Create task for a board
|
||||
this.createTask = async (req, res) => {
|
||||
// Dummy form validation
|
||||
if (!req.body.title) {
|
||||
return res.status(400).json({ error: 'Task title required' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskData = req.body;
|
||||
const task = await task_repo_1.default.createTask(boardId, taskData);
|
||||
return res.status(201).json({ task });
|
||||
};
|
||||
// Update task for a board
|
||||
this.updateTask = async (req, res) => {
|
||||
// Dummy form validation
|
||||
if (!req.body.title) {
|
||||
return res.status(400).json({ error: 'Task title required' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskId = +req.params.taskId;
|
||||
const taskData = req.body;
|
||||
const task = await task_repo_1.default.updateTask(boardId, taskId, taskData);
|
||||
return res.json({ task });
|
||||
};
|
||||
// Delete task for a board
|
||||
this.deleteTask = async (req, res) => {
|
||||
if (!req.headers.authorization) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskId = +req.params.taskId;
|
||||
await task_repo_1.default.deleteTask(boardId, taskId);
|
||||
return res.status(204).end();
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.default = new TaskController();
|
||||
//# sourceMappingURL=task.controller.js.map
|
||||
1
lib/controllers/task.controller.js.map
Normal file
1
lib/controllers/task.controller.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"task.controller.js","sourceRoot":"","sources":["../../src/controllers/task.controller.ts"],"names":[],"mappings":"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"}
|
||||
31
lib/controllers/user.controller.js
Normal file
31
lib/controllers/user.controller.js
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const user_repo_1 = __importDefault(require("@src/repos/user.repo"));
|
||||
class UserController {
|
||||
constructor() {
|
||||
this.getAll = async (_, res) => {
|
||||
const users = await user_repo_1.default.getAll();
|
||||
return res.status(200).json({ users });
|
||||
};
|
||||
this.add = async (req, res) => {
|
||||
const user = req.body.user;
|
||||
await user_repo_1.default.add(user);
|
||||
return res.status(201).end();
|
||||
};
|
||||
this.update = async (req, res) => {
|
||||
const user = req.body.user;
|
||||
await user_repo_1.default.update(user);
|
||||
return res.status(200).end();
|
||||
};
|
||||
this.delete = async (req, res) => {
|
||||
const id = +req.params.id;
|
||||
await user_repo_1.default.delete(id);
|
||||
return res.status(200).end();
|
||||
};
|
||||
}
|
||||
}
|
||||
exports.default = new UserController();
|
||||
//# sourceMappingURL=user.controller.js.map
|
||||
1
lib/controllers/user.controller.js.map
Normal file
1
lib/controllers/user.controller.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.controller.js","sourceRoot":"","sources":["../../src/controllers/user.controller.ts"],"names":[],"mappings":";;;;;AACA,qEAA4C;AAG5C,MAAM,cAAc;IAApB;QACS,WAAM,GAAG,KAAK,EAAE,CAAU,EAAE,GAAa,EAAE,EAAE;YAClD,MAAM,KAAK,GAAG,MAAM,mBAAQ,CAAC,MAAM,EAAE,CAAC;YACtC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC,CAAC;QAEK,QAAG,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YACjD,MAAM,IAAI,GAAU,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,MAAM,mBAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACzB,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC,CAAC;QAEK,WAAM,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YACpD,MAAM,IAAI,GAAU,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAClC,MAAM,mBAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC,CAAC;QAEK,WAAM,GAAG,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,EAAE;YACpD,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,MAAM,mBAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC,CAAC;IACJ,CAAC;CAAA;AAED,kBAAe,IAAI,cAAc,EAAE,CAAC"}
|
||||
14
lib/index.js
Normal file
14
lib/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
require("./pre-start"); // Must be the first import
|
||||
const jet_logger_1 = __importDefault(require("jet-logger"));
|
||||
const EnvVars_1 = __importDefault(require("@src/constants/EnvVars"));
|
||||
const server_1 = __importDefault(require("./server"));
|
||||
// **** Run **** //
|
||||
const SERVER_START_MSG = ('Express server started on port: ' +
|
||||
EnvVars_1.default.Port.toString());
|
||||
server_1.default.listen(EnvVars_1.default.Port, () => jet_logger_1.default.info(SERVER_START_MSG));
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
lib/index.js.map
Normal file
1
lib/index.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,uBAAqB,CAAC,2BAA2B;AACjD,4DAAgC;AAEhC,qEAA6C;AAC7C,sDAA8B;AAG9B,mBAAmB;AAEnB,MAAM,gBAAgB,GAAG,CAAC,kCAAkC;IAC1D,iBAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;AAE3B,gBAAM,CAAC,MAAM,CAAC,iBAAO,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,oBAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC"}
|
||||
48
lib/models/board.model.js
Normal file
48
lib/models/board.model.js
Normal file
@@ -0,0 +1,48 @@
|
||||
"use strict";
|
||||
// **** Variables **** //
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must be a string or an object with the appropriate board keys.';
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Create new Board.
|
||||
*/
|
||||
function new_(userId, name, description, createdAt, updatedAt, id) {
|
||||
const now = new Date().toISOString();
|
||||
return {
|
||||
id: (id !== null && id !== void 0 ? id : -1),
|
||||
userId: (userId !== null && userId !== void 0 ? userId : -1),
|
||||
name: (name !== null && name !== void 0 ? name : ''),
|
||||
description,
|
||||
createdAt: (createdAt !== null && createdAt !== void 0 ? createdAt : now),
|
||||
updatedAt: (updatedAt !== null && updatedAt !== void 0 ? updatedAt : now),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Get board instance from object.
|
||||
*/
|
||||
function from(param) {
|
||||
if (!isBoard(param)) {
|
||||
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
||||
}
|
||||
const p = param;
|
||||
return new_(p.userId, p.name, p.description, p.createdAt, p.updatedAt, p.id);
|
||||
}
|
||||
/**
|
||||
* See if the param meets criteria to be a board.
|
||||
*/
|
||||
function isBoard(arg) {
|
||||
return (!!arg &&
|
||||
typeof arg === 'object' &&
|
||||
'id' in arg &&
|
||||
'userId' in arg &&
|
||||
'name' in arg &&
|
||||
'createdAt' in arg &&
|
||||
'updatedAt' in arg);
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
new: new_,
|
||||
from,
|
||||
isBoard,
|
||||
};
|
||||
//# sourceMappingURL=board.model.js.map
|
||||
1
lib/models/board.model.js.map
Normal file
1
lib/models/board.model.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"board.model.js","sourceRoot":"","sources":["../../src/models/board.model.ts"],"names":[],"mappings":";AAAA,yBAAyB;;AAEzB,MAAM,yBAAyB,GAAG,8EAA8E,CAAC;AAajH,yBAAyB;AAEzB;;GAEG;AACH,SAAS,IAAI,CACZ,MAAe,EACf,IAAa,EACb,WAAoB,EACpB,SAAkB,EAClB,SAAkB,EAClB,EAAW;IAEX,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO;QACN,EAAE,EAAE,CAAC,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,CAAC,CAAC,CAAC;QACd,MAAM,EAAE,CAAC,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,CAAC,CAAC,CAAC;QACtB,IAAI,EAAE,CAAC,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,CAAC;QAClB,WAAW;QACX,SAAS,EAAE,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,GAAG,CAAC;QAC7B,SAAS,EAAE,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,GAAG,CAAC;KAC7B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,IAAI,CAAC,KAAa;IAC1B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,CAAC,GAAG,KAAe,CAAC;IAC1B,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,GAAY;IAC5B,OAAO,CACN,CAAC,CAAC,GAAG;QACL,OAAO,GAAG,KAAK,QAAQ;QACvB,IAAI,IAAI,GAAG;QACX,QAAQ,IAAI,GAAG;QACf,MAAM,IAAI,GAAG;QACb,WAAW,IAAI,GAAG;QAClB,WAAW,IAAI,GAAG,CAClB,CAAC;AACH,CAAC;AAED,8BAA8B;AAE9B,kBAAe;IACd,GAAG,EAAE,IAAI;IACT,IAAI;IACJ,OAAO;CACE,CAAC"}
|
||||
50
lib/models/task.model.js
Normal file
50
lib/models/task.model.js
Normal file
@@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
// **** Variables **** //
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const INVALID_CONSTRUCTOR_PARAM = 'titleOrObj arg must be a string or an object with the appropriate task keys.';
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Create new Task.
|
||||
*/
|
||||
function new_(boardId, title, status, description, createdAt, updatedAt, id) {
|
||||
const now = new Date().toISOString();
|
||||
return {
|
||||
id: (id !== null && id !== void 0 ? id : -1),
|
||||
boardId: (boardId !== null && boardId !== void 0 ? boardId : -1),
|
||||
title: (title !== null && title !== void 0 ? title : ''),
|
||||
status: (status !== null && status !== void 0 ? status : 'todo'),
|
||||
description,
|
||||
createdAt: (createdAt !== null && createdAt !== void 0 ? createdAt : now),
|
||||
updatedAt: (updatedAt !== null && updatedAt !== void 0 ? updatedAt : now),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Get task instance from object.
|
||||
*/
|
||||
function from(param) {
|
||||
if (!isTask(param)) {
|
||||
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
||||
}
|
||||
const p = param;
|
||||
return new_(p.boardId, p.title, p.status, p.description, p.createdAt, p.updatedAt, p.id);
|
||||
}
|
||||
/**
|
||||
* See if the param meets criteria to be a task.
|
||||
*/
|
||||
function isTask(arg) {
|
||||
return (!!arg &&
|
||||
typeof arg === 'object' &&
|
||||
'id' in arg &&
|
||||
'boardId' in arg &&
|
||||
'title' in arg &&
|
||||
'status' in arg &&
|
||||
'createdAt' in arg &&
|
||||
'updatedAt' in arg);
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
new: new_,
|
||||
from,
|
||||
isTask,
|
||||
};
|
||||
//# sourceMappingURL=task.model.js.map
|
||||
1
lib/models/task.model.js.map
Normal file
1
lib/models/task.model.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"task.model.js","sourceRoot":"","sources":["../../src/models/task.model.ts"],"names":[],"mappings":";AAAA,yBAAyB;;AAEzB,MAAM,yBAAyB,GAAG,8EAA8E,CAAC;AAcjH,yBAAyB;AAEzB;;GAEG;AACH,SAAS,IAAI,CACZ,OAAgB,EAChB,KAAc,EACd,MAAwC,EACxC,WAAoB,EACpB,SAAkB,EAClB,SAAkB,EAClB,EAAW;IAEX,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO;QACN,EAAE,EAAE,CAAC,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,CAAC,CAAC,CAAC;QACd,OAAO,EAAE,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,CAAC,CAAC,CAAC;QACxB,KAAK,EAAE,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC;QACpB,MAAM,EAAE,CAAC,MAAM,aAAN,MAAM,cAAN,MAAM,GAAI,MAAM,CAAC;QAC1B,WAAW;QACX,SAAS,EAAE,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,GAAG,CAAC;QAC7B,SAAS,EAAE,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,GAAG,CAAC;KAC7B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,IAAI,CAAC,KAAa;IAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,CAAC,GAAG,KAAc,CAAC;IACzB,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED;;GAEG;AACH,SAAS,MAAM,CAAC,GAAY;IAC3B,OAAO,CACN,CAAC,CAAC,GAAG;QACL,OAAO,GAAG,KAAK,QAAQ;QACvB,IAAI,IAAI,GAAG;QACX,SAAS,IAAI,GAAG;QAChB,OAAO,IAAI,GAAG;QACd,QAAQ,IAAI,GAAG;QACf,WAAW,IAAI,GAAG;QAClB,WAAW,IAAI,GAAG,CAClB,CAAC;AACH,CAAC;AAED,8BAA8B;AAE9B,kBAAe;IACd,GAAG,EAAE,IAAI;IACT,IAAI;IACJ,MAAM;CACG,CAAC"}
|
||||
54
lib/models/user.model.js
Normal file
54
lib/models/user.model.js
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
// **** Variables **** //
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UserRoles = void 0;
|
||||
const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must a string or an ' +
|
||||
'object with the appropriate user keys.';
|
||||
var UserRoles;
|
||||
(function (UserRoles) {
|
||||
UserRoles[UserRoles["Standard"] = 0] = "Standard";
|
||||
UserRoles[UserRoles["Admin"] = 1] = "Admin";
|
||||
})(UserRoles || (exports.UserRoles = UserRoles = {}));
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Create new User.
|
||||
*/
|
||||
function new_(name, email, role, pwdHash, id) {
|
||||
return {
|
||||
id: (id !== null && id !== void 0 ? id : -1),
|
||||
name: (name !== null && name !== void 0 ? name : ''),
|
||||
email: (email !== null && email !== void 0 ? email : ''),
|
||||
role: (role !== null && role !== void 0 ? role : UserRoles.Standard),
|
||||
pwdHash: (pwdHash !== null && pwdHash !== void 0 ? pwdHash : ''),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Get user instance from object.
|
||||
*/
|
||||
function from(param) {
|
||||
// Check is user
|
||||
if (!isUser(param)) {
|
||||
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
||||
}
|
||||
// Get user instance
|
||||
const p = param;
|
||||
return new_(p.name, p.email, p.role, p.pwdHash, p.id);
|
||||
}
|
||||
/**
|
||||
* See if the param meets criteria to be a user.
|
||||
*/
|
||||
function isUser(arg) {
|
||||
return (!!arg &&
|
||||
typeof arg === 'object' &&
|
||||
'id' in arg &&
|
||||
'email' in arg &&
|
||||
'name' in arg &&
|
||||
'role' in arg);
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
new: new_,
|
||||
from,
|
||||
isUser,
|
||||
};
|
||||
//# sourceMappingURL=user.model.js.map
|
||||
1
lib/models/user.model.js.map
Normal file
1
lib/models/user.model.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.model.js","sourceRoot":"","sources":["../../src/models/user.model.ts"],"names":[],"mappings":";AAAA,yBAAyB;;;AAEzB,MAAM,yBAAyB,GAAG,oCAAoC;IACpE,wCAAwC,CAAC;AAE3C,IAAY,SAGX;AAHD,WAAY,SAAS;IACnB,iDAAQ,CAAA;IACR,2CAAK,CAAA;AACP,CAAC,EAHW,SAAS,yBAAT,SAAS,QAGpB;AAqBD,yBAAyB;AAEzB;;GAEG;AACH,SAAS,IAAI,CACX,IAAa,EACb,KAAc,EACd,IAAgB,EAChB,OAAgB,EAChB,EAAW;IAEX,OAAO;QACL,EAAE,EAAE,CAAC,EAAE,aAAF,EAAE,cAAF,EAAE,GAAI,CAAC,CAAC,CAAC;QACd,IAAI,EAAE,CAAC,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,EAAE,CAAC;QAClB,KAAK,EAAE,CAAC,KAAK,aAAL,KAAK,cAAL,KAAK,GAAI,EAAE,CAAC;QACpB,IAAI,EAAE,CAAC,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,SAAS,CAAC,QAAQ,CAAC;QAClC,OAAO,EAAE,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC;KACzB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,IAAI,CAAC,KAAa;IACzB,gBAAgB;IAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,oBAAoB;IACpB,MAAM,CAAC,GAAG,KAAc,CAAC;IACzB,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,MAAM,CAAC,GAAY;IAC1B,OAAO,CACL,CAAC,CAAC,GAAG;QACL,OAAO,GAAG,KAAK,QAAQ;QACvB,IAAI,IAAI,GAAG;QACX,OAAO,IAAI,GAAG;QACd,MAAM,IAAI,GAAG;QACb,MAAM,IAAI,GAAG,CACd,CAAC;AACJ,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,GAAG,EAAE,IAAI;IACT,IAAI;IACJ,MAAM;CACE,CAAC"}
|
||||
17
lib/other/classes.js
Normal file
17
lib/other/classes.js
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Miscellaneous shared classes go here.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RouteError = void 0;
|
||||
/**
|
||||
* Error with status code and message
|
||||
*/
|
||||
class RouteError extends Error {
|
||||
constructor(status, message) {
|
||||
super(message);
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
exports.RouteError = RouteError;
|
||||
//# sourceMappingURL=classes.js.map
|
||||
1
lib/other/classes.js.map
Normal file
1
lib/other/classes.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"classes.js","sourceRoot":"","sources":["../../src/other/classes.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAKH;;GAEG;AACH,MAAa,UAAW,SAAQ,KAAK;IAEnC,YAAY,MAAuB,EAAE,OAAe;QAClD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAND,gCAMC"}
|
||||
3
lib/other/types.js
Normal file
3
lib/other/types.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
lib/other/types.js.map
Normal file
1
lib/other/types.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/other/types.ts"],"names":[],"mappings":""}
|
||||
31
lib/pre-start.js
Normal file
31
lib/pre-start.js
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Pre-start is where we want to place things that must run BEFORE the express
|
||||
* server is started. This is useful for environment variables, command-line
|
||||
* arguments, and cron-jobs.
|
||||
*/
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// NOTE: DO NOT IMPORT ANY SOURCE CODE HERE
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const dotenv_1 = __importDefault(require("dotenv"));
|
||||
const ts_command_line_args_1 = require("ts-command-line-args");
|
||||
// **** Setup **** //
|
||||
// Command line arguments
|
||||
const args = (0, ts_command_line_args_1.parse)({
|
||||
env: {
|
||||
type: String,
|
||||
defaultValue: 'development',
|
||||
alias: 'e',
|
||||
},
|
||||
});
|
||||
// Set the env file
|
||||
const result2 = dotenv_1.default.config({
|
||||
path: path_1.default.join(__dirname, `../env/${args.env}.env`),
|
||||
});
|
||||
if (result2.error) {
|
||||
throw result2.error;
|
||||
}
|
||||
//# sourceMappingURL=pre-start.js.map
|
||||
1
lib/pre-start.js.map
Normal file
1
lib/pre-start.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"pre-start.js","sourceRoot":"","sources":["../src/pre-start.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;AAEH,2CAA2C;AAC3C,gDAAwB;AACxB,oDAA4B;AAC5B,+DAA6C;AAU7C,qBAAqB;AAErB,yBAAyB;AACzB,MAAM,IAAI,GAAG,IAAA,4BAAK,EAAQ;IACxB,GAAG,EAAE;QACH,IAAI,EAAE,MAAM;QACZ,YAAY,EAAE,aAAa;QAC3B,KAAK,EAAE,GAAG;KACX;CACF,CAAC,CAAC;AAEH,mBAAmB;AACnB,MAAM,OAAO,GAAG,gBAAM,CAAC,MAAM,CAAC;IAC5B,IAAI,EAAE,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,IAAI,CAAC,GAAG,MAAM,CAAC;CACrD,CAAC,CAAC;AACH,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,MAAM,OAAO,CAAC,KAAK,CAAC;AACtB,CAAC"}
|
||||
27
lib/public/scripts/http.js
Normal file
27
lib/public/scripts/http.js
Normal file
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var Http = (() => {
|
||||
// Setup request for json
|
||||
var getOptions = (verb, data) => {
|
||||
var options = {
|
||||
dataType: 'json',
|
||||
method: verb,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
if (data) {
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
return options;
|
||||
};
|
||||
// Set Http methods
|
||||
return {
|
||||
get: (path) => fetch(path, getOptions('GET')),
|
||||
post: (path, data) => fetch(path, getOptions('POST', data)),
|
||||
put: (path, data) => fetch(path, getOptions('PUT', data)),
|
||||
delete: (path) => fetch(path, getOptions('DELETE')),
|
||||
};
|
||||
})();
|
||||
//# sourceMappingURL=http.js.map
|
||||
1
lib/public/scripts/http.js.map
Normal file
1
lib/public/scripts/http.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/public/scripts/http.js"],"names":[],"mappings":";;AAAA,IAAI,IAAI,GAAG,CAAC,GAAG,EAAE;IACf,yBAAyB;IACzB,IAAI,UAAU,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,OAAO,GAAG;YACZ,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;gBACP,QAAQ,EAAE,kBAAkB;gBAC5B,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC;QACF,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,mBAAmB;IACnB,OAAO;QACL,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3D,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;KACpD,CAAC;AACJ,CAAC,CAAC,EAAE,CAAC"}
|
||||
154
lib/public/scripts/users.js
Normal file
154
lib/public/scripts/users.js
Normal file
@@ -0,0 +1,154 @@
|
||||
"use strict";
|
||||
// ***** Start **** //
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
displayUsers();
|
||||
// ***** Fetch and display users **** //
|
||||
/**
|
||||
* Call api
|
||||
*/
|
||||
function displayUsers() {
|
||||
Http
|
||||
.get('/api/users/all')
|
||||
.then(resp => resp.json())
|
||||
.then((resp) => {
|
||||
var allUsers = resp.users;
|
||||
// Empty the anchor
|
||||
var allUsersAnchor = document.getElementById('all-users-anchor');
|
||||
allUsersAnchor.innerHTML = '';
|
||||
// Append users to anchor
|
||||
allUsers.forEach((user) => {
|
||||
allUsersAnchor.innerHTML += getUserDisplayEle(user);
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get user display element
|
||||
*/
|
||||
function getUserDisplayEle(user) {
|
||||
return (`<div class="user-display-ele">
|
||||
|
||||
<div class="normal-view">
|
||||
<div>Name: ${user.name}</div>
|
||||
<div>Email: ${user.email}</div>
|
||||
<button class="edit-user-btn" data-user-id="${user.id}" data-user-role="${user.role}">
|
||||
Edit
|
||||
</button>
|
||||
<button class="delete-user-btn" data-user-id="${user.id}">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="edit-view">
|
||||
<div>
|
||||
Name: <input class="name-edit-input" value="${user.name}">
|
||||
</div>
|
||||
<div>
|
||||
Email: <input class="email-edit-input" value="${user.email}">
|
||||
</div>
|
||||
<button class="submit-edit-btn" data-user-id="${user.id}">
|
||||
Submit
|
||||
</button>
|
||||
<button class="cancel-edit-btn" data-user-id="${user.id}">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>`);
|
||||
}
|
||||
// **** Add, Edit, and Delete Users **** //
|
||||
// Setup event listener for button click
|
||||
document.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
var ele = event.target;
|
||||
if (ele.matches('#add-user-btn')) {
|
||||
addUser();
|
||||
}
|
||||
else if (ele.matches('.edit-user-btn')) {
|
||||
showEditView(ele.parentNode.parentNode);
|
||||
}
|
||||
else if (ele.matches('.cancel-edit-btn')) {
|
||||
cancelEdit(ele.parentNode.parentNode);
|
||||
}
|
||||
else if (ele.matches('.submit-edit-btn')) {
|
||||
submitEdit(ele);
|
||||
}
|
||||
else if (ele.matches('.delete-user-btn')) {
|
||||
deleteUser(ele);
|
||||
}
|
||||
else if (ele.matches('#logout-btn')) {
|
||||
logoutUser();
|
||||
}
|
||||
}, false);
|
||||
/**
|
||||
* Add a new user.
|
||||
*/
|
||||
function addUser() {
|
||||
var nameInput = document.getElementById('name-input');
|
||||
var emailInput = document.getElementById('email-input');
|
||||
var data = {
|
||||
user: {
|
||||
id: -1,
|
||||
name: nameInput.value,
|
||||
email: emailInput.value,
|
||||
role: 0,
|
||||
},
|
||||
};
|
||||
// Call api
|
||||
Http
|
||||
.post('/api/users/add', data)
|
||||
.then(() => displayUsers());
|
||||
}
|
||||
/**
|
||||
* Show edit view.
|
||||
*/
|
||||
function showEditView(userEle) {
|
||||
var normalView = userEle.getElementsByClassName('normal-view')[0];
|
||||
var editView = userEle.getElementsByClassName('edit-view')[0];
|
||||
normalView.style.display = 'none';
|
||||
editView.style.display = 'block';
|
||||
}
|
||||
/**
|
||||
* Cancel edit.
|
||||
*/
|
||||
function cancelEdit(userEle) {
|
||||
var normalView = userEle.getElementsByClassName('normal-view')[0];
|
||||
var editView = userEle.getElementsByClassName('edit-view')[0];
|
||||
normalView.style.display = 'block';
|
||||
editView.style.display = 'none';
|
||||
}
|
||||
/**
|
||||
* Submit edit.
|
||||
*/
|
||||
function submitEdit(ele) {
|
||||
var userEle = ele.parentNode.parentNode;
|
||||
var nameInput = userEle.getElementsByClassName('name-edit-input')[0];
|
||||
var emailInput = userEle.getElementsByClassName('email-edit-input')[0];
|
||||
var id = ele.getAttribute('data-user-id');
|
||||
var role = ele.getAttribute('data-user-role');
|
||||
var data = {
|
||||
user: {
|
||||
id: Number(id),
|
||||
name: nameInput.value,
|
||||
email: emailInput.value,
|
||||
role: Number(role),
|
||||
},
|
||||
};
|
||||
Http
|
||||
.put('/api/users/update', data)
|
||||
.then(() => displayUsers());
|
||||
}
|
||||
/**
|
||||
* Delete a user
|
||||
*/
|
||||
function deleteUser(ele) {
|
||||
var id = ele.getAttribute('data-user-id');
|
||||
Http
|
||||
.delete('/api/users/delete/' + id)
|
||||
.then(() => displayUsers());
|
||||
}
|
||||
// **** Logout **** //
|
||||
function logoutUser() {
|
||||
Http
|
||||
.get('/api/auth/logout')
|
||||
.then(() => window.location.href = '/');
|
||||
}
|
||||
//# sourceMappingURL=users.js.map
|
||||
1
lib/public/scripts/users.js.map
Normal file
1
lib/public/scripts/users.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"users.js","sourceRoot":"","sources":["../../../src/public/scripts/users.js"],"names":[],"mappings":"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"}
|
||||
52
lib/repos/BoardRepo.js
Normal file
52
lib/repos/BoardRepo.js
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const MockOrm_1 = __importDefault(require("./MockOrm"));
|
||||
async function getBoardsByUserId(userId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.boards.filter((board) => board.userId === userId);
|
||||
}
|
||||
async function getBoardByUserId(userId, boardId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.boards.find((board) => board.userId === userId && board.id === boardId) || null;
|
||||
}
|
||||
async function createBoard(userId, board) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
board.id = Date.now();
|
||||
board.userId = userId;
|
||||
board.createdAt = new Date().toISOString();
|
||||
board.updatedAt = board.createdAt;
|
||||
db.boards.push(board);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
async function updateBoard(userId, boardId, boardData) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const board = db.boards.find((b) => b.userId === userId && b.id === boardId);
|
||||
if (board) {
|
||||
Object.assign(board, boardData, { updatedAt: new Date().toISOString() });
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function deleteBoard(userId, boardId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const idx = db.boards.findIndex((b) => b.userId === userId && b.id === boardId);
|
||||
if (idx !== -1) {
|
||||
db.boards.splice(idx, 1);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.default = {
|
||||
getBoardsByUserId,
|
||||
getBoardByUserId,
|
||||
createBoard,
|
||||
updateBoard,
|
||||
deleteBoard,
|
||||
};
|
||||
//# sourceMappingURL=BoardRepo.js.map
|
||||
1
lib/repos/BoardRepo.js.map
Normal file
1
lib/repos/BoardRepo.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"BoardRepo.js","sourceRoot":"","sources":["../../src/repos/BoardRepo.ts"],"names":[],"mappings":";;;;;AACA,wDAA4B;AAE5B,KAAK,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,MAAc,EAAE,OAAe;IAC9D,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC;AACnG,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,KAAa;IACvD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IAClC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC;AACd,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,OAAe,EAAE,SAA0B;IACrF,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IACrF,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACzE,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,OAAe;IACzD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IACxF,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,kBAAe;IACd,iBAAiB;IACjB,gBAAgB;IAChB,WAAW;IACX,WAAW;IACX,WAAW;CACX,CAAC"}
|
||||
27
lib/repos/MockOrm.js
Normal file
27
lib/repos/MockOrm.js
Normal file
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const jsonfile_1 = __importDefault(require("jsonfile"));
|
||||
// **** Variables **** //
|
||||
const DB_FILE_NAME = 'database.json';
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Fetch the json from the file.
|
||||
*/
|
||||
function openDb() {
|
||||
return jsonfile_1.default.readFile(__dirname + '/' + DB_FILE_NAME);
|
||||
}
|
||||
/**
|
||||
* Update the file.
|
||||
*/
|
||||
function saveDb(db) {
|
||||
return jsonfile_1.default.writeFile((__dirname + '/' + DB_FILE_NAME), db);
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
openDb,
|
||||
saveDb,
|
||||
};
|
||||
//# sourceMappingURL=MockOrm.js.map
|
||||
1
lib/repos/MockOrm.js.map
Normal file
1
lib/repos/MockOrm.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"MockOrm.js","sourceRoot":"","sources":["../../src/repos/MockOrm.ts"],"names":[],"mappings":";;;;;AAEA,wDAAgC;AAOhC,yBAAyB;AAEzB,MAAM,YAAY,GAAG,eAAe,CAAC;AAYrC,yBAAyB;AAEzB;;GAEG;AACH,SAAS,MAAM;IACb,OAAO,kBAAQ,CAAC,QAAQ,CAAC,SAAS,GAAG,GAAG,GAAG,YAAY,CAAiB,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,SAAS,MAAM,CAAC,EAAO;IACrB,OAAO,kBAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;AAClE,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,MAAM;IACN,MAAM;CACE,CAAC"}
|
||||
52
lib/repos/TaskRepo.js
Normal file
52
lib/repos/TaskRepo.js
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const MockOrm_1 = __importDefault(require("./MockOrm"));
|
||||
async function getTasksByBoardId(boardId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.tasks.filter((task) => task.boardId === boardId);
|
||||
}
|
||||
async function getTaskByBoardId(boardId, taskId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.tasks.find((task) => task.boardId === boardId && task.id === taskId) || null;
|
||||
}
|
||||
async function createTask(boardId, task) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
task.id = Date.now();
|
||||
task.boardId = boardId;
|
||||
task.createdAt = new Date().toISOString();
|
||||
task.updatedAt = task.createdAt;
|
||||
db.tasks.push(task);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
async function updateTask(boardId, taskId, taskData) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const task = db.tasks.find((t) => t.boardId === boardId && t.id === taskId);
|
||||
if (task) {
|
||||
Object.assign(task, taskData, { updatedAt: new Date().toISOString() });
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function deleteTask(boardId, taskId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const idx = db.tasks.findIndex((t) => t.boardId === boardId && t.id === taskId);
|
||||
if (idx !== -1) {
|
||||
db.tasks.splice(idx, 1);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.default = {
|
||||
getTasksByBoardId,
|
||||
getTaskByBoardId,
|
||||
createTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
};
|
||||
//# sourceMappingURL=TaskRepo.js.map
|
||||
1
lib/repos/TaskRepo.js.map
Normal file
1
lib/repos/TaskRepo.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"TaskRepo.js","sourceRoot":"","sources":["../../src/repos/TaskRepo.ts"],"names":[],"mappings":";;;;;AACA,wDAA4B;AAE5B,KAAK,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAW,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAc;IAC9D,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAW,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC;AAC/F,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,IAAW;IACrD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACvB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAChC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,MAAc,EAAE,QAAwB;IAClF,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACnF,IAAI,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACvE,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,MAAc;IACxD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACvF,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACxB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,kBAAe;IACd,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,UAAU;IACV,UAAU;CACV,CAAC"}
|
||||
52
lib/repos/board.repo.js
Normal file
52
lib/repos/board.repo.js
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const MockOrm_1 = __importDefault(require("./MockOrm"));
|
||||
async function getBoardsByUserId(userId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.boards.filter((board) => board.userId === userId);
|
||||
}
|
||||
async function getBoardByUserId(userId, boardId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.boards.find((board) => board.userId === userId && board.id === boardId) || null;
|
||||
}
|
||||
async function createBoard(userId, board) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
board.id = Date.now();
|
||||
board.userId = userId;
|
||||
board.createdAt = new Date().toISOString();
|
||||
board.updatedAt = board.createdAt;
|
||||
db.boards.push(board);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
async function updateBoard(userId, boardId, boardData) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const board = db.boards.find((b) => b.userId === userId && b.id === boardId);
|
||||
if (board) {
|
||||
Object.assign(board, boardData, { updatedAt: new Date().toISOString() });
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function deleteBoard(userId, boardId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const idx = db.boards.findIndex((b) => b.userId === userId && b.id === boardId);
|
||||
if (idx !== -1) {
|
||||
db.boards.splice(idx, 1);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.default = {
|
||||
getBoardsByUserId,
|
||||
getBoardByUserId,
|
||||
createBoard,
|
||||
updateBoard,
|
||||
deleteBoard,
|
||||
};
|
||||
//# sourceMappingURL=board.repo.js.map
|
||||
1
lib/repos/board.repo.js.map
Normal file
1
lib/repos/board.repo.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"board.repo.js","sourceRoot":"","sources":["../../src/repos/board.repo.ts"],"names":[],"mappings":";;;;;AACA,wDAA4B;AAE5B,KAAK,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AACrE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,MAAc,EAAE,OAAe;IAC9D,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC;AACnG,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,KAAa;IACvD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;IAClC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,KAAK,CAAC;AACd,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,OAAe,EAAE,SAA0B;IACrF,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IACrF,IAAI,KAAK,EAAE,CAAC;QACX,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACzE,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAc,EAAE,OAAe;IACzD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IACxF,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACzB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,kBAAe;IACd,iBAAiB;IACjB,gBAAgB;IAChB,WAAW;IACX,WAAW;IACX,WAAW;CACX,CAAC"}
|
||||
52
lib/repos/task.repo.js
Normal file
52
lib/repos/task.repo.js
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const MockOrm_1 = __importDefault(require("./MockOrm"));
|
||||
async function getTasksByBoardId(boardId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.tasks.filter((task) => task.boardId === boardId);
|
||||
}
|
||||
async function getTaskByBoardId(boardId, taskId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.tasks.find((task) => task.boardId === boardId && task.id === taskId) || null;
|
||||
}
|
||||
async function createTask(boardId, task) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
task.id = Date.now();
|
||||
task.boardId = boardId;
|
||||
task.createdAt = new Date().toISOString();
|
||||
task.updatedAt = task.createdAt;
|
||||
db.tasks.push(task);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
async function updateTask(boardId, taskId, taskData) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const task = db.tasks.find((t) => t.boardId === boardId && t.id === taskId);
|
||||
if (task) {
|
||||
Object.assign(task, taskData, { updatedAt: new Date().toISOString() });
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function deleteTask(boardId, taskId) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
const idx = db.tasks.findIndex((t) => t.boardId === boardId && t.id === taskId);
|
||||
if (idx !== -1) {
|
||||
db.tasks.splice(idx, 1);
|
||||
await MockOrm_1.default.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.default = {
|
||||
getTasksByBoardId,
|
||||
getTaskByBoardId,
|
||||
createTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
};
|
||||
//# sourceMappingURL=task.repo.js.map
|
||||
1
lib/repos/task.repo.js.map
Normal file
1
lib/repos/task.repo.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"task.repo.js","sourceRoot":"","sources":["../../src/repos/task.repo.ts"],"names":[],"mappings":";;;;;AACA,wDAA4B;AAE5B,KAAK,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAW,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,MAAc;IAC9D,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAW,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC;AAC/F,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,IAAW;IACrD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACvB,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IAChC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,MAAc,EAAE,QAAwB;IAClF,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACnF,IAAI,IAAI,EAAE,CAAC;QACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACvE,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,MAAc;IACxD,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACvF,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QAChB,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACxB,MAAM,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,kBAAe;IACd,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,UAAU;IACV,UAAU;CACV,CAAC"}
|
||||
82
lib/repos/user.repo.js
Normal file
82
lib/repos/user.repo.js
Normal file
@@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const misc_1 = require("@src/util/misc");
|
||||
const MockOrm_1 = __importDefault(require("./MockOrm"));
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Get one user.
|
||||
*/
|
||||
async function getOne(email) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
for (const user of db.users) {
|
||||
if (user.email === email) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* See if a user with the given id exists.
|
||||
*/
|
||||
async function persists(id) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
for (const user of db.users) {
|
||||
if (user.id === id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Get all users.
|
||||
*/
|
||||
async function getAll() {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
return db.users;
|
||||
}
|
||||
/**
|
||||
* Add one user.
|
||||
*/
|
||||
async function add(user) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
user.id = (0, misc_1.getRandomInt)();
|
||||
db.users.push(user);
|
||||
return MockOrm_1.default.saveDb(db);
|
||||
}
|
||||
/**
|
||||
* Update a user.
|
||||
*/
|
||||
async function update(user) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
for (let i = 0; i < db.users.length; i++) {
|
||||
if (db.users[i].id === user.id) {
|
||||
db.users[i] = user;
|
||||
return MockOrm_1.default.saveDb(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Delete one user.
|
||||
*/
|
||||
async function delete_(id) {
|
||||
const db = await MockOrm_1.default.openDb();
|
||||
for (let i = 0; i < db.users.length; i++) {
|
||||
if (db.users[i].id === id) {
|
||||
db.users.splice(i, 1);
|
||||
return MockOrm_1.default.saveDb(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
getOne,
|
||||
persists,
|
||||
getAll,
|
||||
add,
|
||||
update,
|
||||
delete: delete_,
|
||||
};
|
||||
//# sourceMappingURL=user.repo.js.map
|
||||
1
lib/repos/user.repo.js.map
Normal file
1
lib/repos/user.repo.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.repo.js","sourceRoot":"","sources":["../../src/repos/user.repo.ts"],"names":[],"mappings":";;;;;AACA,yCAA8C;AAC9C,wDAA4B;AAG5B,yBAAyB;AAEzB;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,KAAa;IACjC,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,QAAQ,CAAC,EAAU;IAChC,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,MAAM;IACnB,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,OAAO,EAAE,CAAC,KAAK,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,GAAG,CAAC,IAAW;IAC5B,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE,GAAG,IAAA,mBAAY,GAAE,CAAC;IACzB,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpB,OAAO,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,IAAW;IAC/B,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC;YAC/B,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;YACnB,OAAO,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO,CAAC,EAAU;IAC/B,MAAM,EAAE,GAAG,MAAM,iBAAG,CAAC,MAAM,EAAE,CAAC;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAC1B,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACtB,OAAO,iBAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;AACH,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,MAAM;IACN,QAAQ;IACR,MAAM;IACN,GAAG;IACH,MAAM;IACN,MAAM,EAAE,OAAO;CACP,CAAC"}
|
||||
24
lib/routes/api.js
Normal file
24
lib/routes/api.js
Normal file
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const jet_validator_1 = __importDefault(require("jet-validator"));
|
||||
const Paths_1 = __importDefault(require("./constants/Paths"));
|
||||
const user_model_1 = __importDefault(require("@src/models/user.model"));
|
||||
const user_controller_1 = __importDefault(require("@src/controllers/user.controller"));
|
||||
// **** Variables **** //
|
||||
const apiRouter = (0, express_1.Router)(), validate = (0, jet_validator_1.default)();
|
||||
// ** Add UserRouter ** //
|
||||
const userRouter = (0, express_1.Router)();
|
||||
// Get all users
|
||||
userRouter.get(Paths_1.default.Users.Get, user_controller_1.default.getAll.bind(user_controller_1.default));
|
||||
userRouter.post(Paths_1.default.Users.Add, validate(['user', user_model_1.default.isUser]), user_controller_1.default.add.bind(user_controller_1.default));
|
||||
userRouter.put(Paths_1.default.Users.Update, validate(['user', user_model_1.default.isUser]), user_controller_1.default.update.bind(user_controller_1.default));
|
||||
userRouter.delete(Paths_1.default.Users.Delete, validate(['id', 'number', 'params']), user_controller_1.default.delete.bind(user_controller_1.default));
|
||||
// Add UserRouter
|
||||
apiRouter.use(Paths_1.default.Users.Base, userRouter);
|
||||
// **** Export default **** //
|
||||
exports.default = apiRouter;
|
||||
//# sourceMappingURL=api.js.map
|
||||
1
lib/routes/api.js.map
Normal file
1
lib/routes/api.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/routes/api.ts"],"names":[],"mappings":";;;;;AAAA,qCAAiC;AACjC,kEAAyC;AAEzC,8DAAsC;AACtC,wEAA0C;AAC1C,uFAA8D;AAG9D,yBAAyB;AAEzB,MAAM,SAAS,GAAG,IAAA,gBAAM,GAAE,EACxB,QAAQ,GAAG,IAAA,uBAAY,GAAE,CAAC;AAG5B,0BAA0B;AAE1B,MAAM,UAAU,GAAG,IAAA,gBAAM,GAAE,CAAC;AAE5B,gBAAgB;AAChB,UAAU,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,GAAG,EAAE,yBAAc,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAc,CAAC,CAAC,CAAC;AAC5E,UAAU,CAAC,IAAI,CACb,eAAK,CAAC,KAAK,CAAC,GAAG,EACf,QAAQ,CAAC,CAAC,MAAM,EAAE,oBAAI,CAAC,MAAM,CAAC,CAAC,EAC/B,yBAAc,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAc,CAAC,CACxC,CAAC;AACF,UAAU,CAAC,GAAG,CACZ,eAAK,CAAC,KAAK,CAAC,MAAM,EAClB,QAAQ,CAAC,CAAC,MAAM,EAAE,oBAAI,CAAC,MAAM,CAAC,CAAC,EAC/B,yBAAc,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAc,CAAC,CAC3C,CAAC;AACF,UAAU,CAAC,MAAM,CACf,eAAK,CAAC,KAAK,CAAC,MAAM,EAClB,QAAQ,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,EACpC,yBAAc,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAc,CAAC,CAC3C,CAAC;AAEF,iBAAiB;AACjB,SAAS,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAG5C,8BAA8B;AAE9B,kBAAe,SAAS,CAAC"}
|
||||
15
lib/routes/board.route.js
Normal file
15
lib/routes/board.route.js
Normal file
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const board_controller_1 = __importDefault(require("../controllers/board.controller"));
|
||||
const router = (0, express_1.Router)();
|
||||
router.get('/user/:userId', board_controller_1.default.getBoardsByUserId);
|
||||
router.get('/user/:userId/:boardId', board_controller_1.default.getBoardByUserId);
|
||||
router.post('/user/:userId', board_controller_1.default.createBoard);
|
||||
router.put('/user/:userId/:boardId', board_controller_1.default.updateBoard);
|
||||
router.delete('/user/:userId/:boardId', board_controller_1.default.deleteBoard);
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=board.route.js.map
|
||||
1
lib/routes/board.route.js.map
Normal file
1
lib/routes/board.route.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"board.route.js","sourceRoot":"","sources":["../../src/routes/board.route.ts"],"names":[],"mappings":";;;;;AACA,qCAAiC;AACjC,uFAA8D;AAE9D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,0BAAe,CAAC,iBAAiB,CAAC,CAAC;AAC/D,MAAM,CAAC,GAAG,CAAC,wBAAwB,EAAE,0BAAe,CAAC,gBAAgB,CAAC,CAAC;AACvE,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,0BAAe,CAAC,WAAW,CAAC,CAAC;AAC1D,MAAM,CAAC,GAAG,CAAC,wBAAwB,EAAE,0BAAe,CAAC,WAAW,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,CAAC,wBAAwB,EAAE,0BAAe,CAAC,WAAW,CAAC,CAAC;AAErE,kBAAe,MAAM,CAAC"}
|
||||
30
lib/routes/constants/FullPaths.js
Normal file
30
lib/routes/constants/FullPaths.js
Normal file
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Convert paths to full paths.
|
||||
*/
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Paths_1 = __importDefault(require("./Paths"));
|
||||
/**
|
||||
* The recursive function.
|
||||
*/
|
||||
function getFullPaths(parent, baseUrl) {
|
||||
const url = (baseUrl + parent.Base), keys = Object.keys(parent), retVal = { Base: url };
|
||||
// Iterate keys
|
||||
for (const key of keys) {
|
||||
const pval = parent[key];
|
||||
if (key !== 'Base' && typeof pval === 'string') {
|
||||
retVal[key] = (url + pval);
|
||||
}
|
||||
else if (typeof pval === 'object') {
|
||||
retVal[key] = getFullPaths(pval, url);
|
||||
}
|
||||
}
|
||||
// Return
|
||||
return retVal;
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = getFullPaths(Paths_1.default, '');
|
||||
//# sourceMappingURL=FullPaths.js.map
|
||||
1
lib/routes/constants/FullPaths.js.map
Normal file
1
lib/routes/constants/FullPaths.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"FullPaths.js","sourceRoot":"","sources":["../../../src/routes/constants/FullPaths.ts"],"names":[],"mappings":";AACA;;GAEG;;;;;AAEH,oDAAwC;AAQxC;;GAEG;AACH,SAAS,YAAY,CACnB,MAAgB,EAChB,OAAe;IAEf,MAAM,GAAG,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,EACjC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAC1B,MAAM,GAAa,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IACnC,eAAe;IACf,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,IAAI,GAAG,KAAK,MAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;QAC7B,CAAC;aAAM,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IACD,SAAS;IACT,OAAO,MAAM,CAAC;AAChB,CAAC;AAGD,8BAA8B;AAE9B,kBAAe,YAAY,CAAC,eAAK,EAAE,EAAE,CAAW,CAAC"}
|
||||
17
lib/routes/constants/Paths.js
Normal file
17
lib/routes/constants/Paths.js
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Express router paths go here.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const Paths = {
|
||||
Base: '/api',
|
||||
Users: {
|
||||
Base: '/users',
|
||||
Get: '/all',
|
||||
Add: '/add',
|
||||
Update: '/update',
|
||||
Delete: '/delete/:id',
|
||||
},
|
||||
};
|
||||
exports.default = Paths;
|
||||
//# sourceMappingURL=Paths.js.map
|
||||
1
lib/routes/constants/Paths.js.map
Normal file
1
lib/routes/constants/Paths.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"Paths.js","sourceRoot":"","sources":["../../../src/routes/constants/Paths.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAKH,MAAM,KAAK,GAAG;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE;QACL,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,MAAM;QACX,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,aAAa;KACtB;CACF,CAAC;AAMF,kBAAe,KAAe,CAAC"}
|
||||
15
lib/routes/task.route.js
Normal file
15
lib/routes/task.route.js
Normal file
@@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const task_controller_1 = __importDefault(require("../controllers/task.controller"));
|
||||
const router = (0, express_1.Router)();
|
||||
router.get('/board/:boardId', task_controller_1.default.getTasksByBoardId);
|
||||
router.get('/board/:boardId/:taskId', task_controller_1.default.getTaskByBoardId);
|
||||
router.post('/board/:boardId', task_controller_1.default.createTask);
|
||||
router.put('/board/:boardId/:taskId', task_controller_1.default.updateTask);
|
||||
router.delete('/board/:boardId/:taskId', task_controller_1.default.deleteTask);
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=task.route.js.map
|
||||
1
lib/routes/task.route.js.map
Normal file
1
lib/routes/task.route.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"task.route.js","sourceRoot":"","sources":["../../src/routes/task.route.ts"],"names":[],"mappings":";;;;;AACA,qCAAiC;AACjC,qFAA4D;AAE5D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,yBAAc,CAAC,iBAAiB,CAAC,CAAC;AAChE,MAAM,CAAC,GAAG,CAAC,yBAAyB,EAAE,yBAAc,CAAC,gBAAgB,CAAC,CAAC;AACvE,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,yBAAc,CAAC,UAAU,CAAC,CAAC;AAC1D,MAAM,CAAC,GAAG,CAAC,yBAAyB,EAAE,yBAAc,CAAC,UAAU,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,CAAC,yBAAyB,EAAE,yBAAc,CAAC,UAAU,CAAC,CAAC;AAEpE,kBAAe,MAAM,CAAC"}
|
||||
3
lib/routes/types/express/misc.js
Normal file
3
lib/routes/types/express/misc.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=misc.js.map
|
||||
1
lib/routes/types/express/misc.js.map
Normal file
1
lib/routes/types/express/misc.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"misc.js","sourceRoot":"","sources":["../../../../src/routes/types/express/misc.ts"],"names":[],"mappings":""}
|
||||
3
lib/routes/types/types.js
Normal file
3
lib/routes/types/types.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=types.js.map
|
||||
1
lib/routes/types/types.js.map
Normal file
1
lib/routes/types/types.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/routes/types/types.ts"],"names":[],"mappings":""}
|
||||
14
lib/routes/user.route.js
Normal file
14
lib/routes/user.route.js
Normal file
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const user_controller_1 = __importDefault(require("../controllers/user.controller"));
|
||||
const router = (0, express_1.Router)();
|
||||
router.get('/', user_controller_1.default.getAll);
|
||||
router.post('/', user_controller_1.default.add);
|
||||
router.put('/', user_controller_1.default.update);
|
||||
router.delete('/:id', user_controller_1.default.delete);
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=user.route.js.map
|
||||
1
lib/routes/user.route.js.map
Normal file
1
lib/routes/user.route.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.route.js","sourceRoot":"","sources":["../../src/routes/user.route.ts"],"names":[],"mappings":";;;;;AAAA,qCAAiC;AACjC,qFAA4D;AAE5D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,yBAAc,CAAC,MAAM,CAAC,CAAC;AACvC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,yBAAc,CAAC,GAAG,CAAC,CAAC;AACrC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,yBAAc,CAAC,MAAM,CAAC,CAAC;AACvC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAc,CAAC,MAAM,CAAC,CAAC;AAE7C,kBAAe,MAAM,CAAC"}
|
||||
69
lib/server.js
Normal file
69
lib/server.js
Normal file
@@ -0,0 +1,69 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Setup express server.
|
||||
*/
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const cookie_parser_1 = __importDefault(require("cookie-parser"));
|
||||
const morgan_1 = __importDefault(require("morgan"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const helmet_1 = __importDefault(require("helmet"));
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const jet_logger_1 = __importDefault(require("jet-logger"));
|
||||
require("express-async-errors");
|
||||
const api_1 = __importDefault(require("@src/routes/api"));
|
||||
const Paths_1 = __importDefault(require("@src/routes/constants/Paths"));
|
||||
const EnvVars_1 = __importDefault(require("@src/constants/EnvVars"));
|
||||
const HttpStatusCodes_1 = __importDefault(require("@src/constants/HttpStatusCodes"));
|
||||
const misc_1 = require("@src/constants/misc");
|
||||
const classes_1 = require("@src/other/classes");
|
||||
// **** Variables **** //
|
||||
const app = (0, express_1.default)();
|
||||
// **** Setup **** //
|
||||
// Basic middleware
|
||||
app.use(express_1.default.json());
|
||||
app.use(express_1.default.urlencoded({ extended: true }));
|
||||
app.use((0, cookie_parser_1.default)(EnvVars_1.default.CookieProps.Secret));
|
||||
// Show routes called in console during development
|
||||
if (EnvVars_1.default.NodeEnv === misc_1.NodeEnvs.Dev) {
|
||||
app.use((0, morgan_1.default)('dev'));
|
||||
}
|
||||
// Security
|
||||
if (EnvVars_1.default.NodeEnv === misc_1.NodeEnvs.Production) {
|
||||
app.use((0, helmet_1.default)());
|
||||
}
|
||||
// Add APIs, must be after middleware
|
||||
app.use(Paths_1.default.Base, api_1.default);
|
||||
// Add error handler
|
||||
app.use((err, _, res,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
next) => {
|
||||
if (EnvVars_1.default.NodeEnv !== misc_1.NodeEnvs.Test) {
|
||||
jet_logger_1.default.err(err, true);
|
||||
}
|
||||
let status = HttpStatusCodes_1.default.BAD_REQUEST;
|
||||
if (err instanceof classes_1.RouteError) {
|
||||
status = err.status;
|
||||
}
|
||||
return res.status(status).json({ error: err.message });
|
||||
});
|
||||
// ** Front-End Content ** //
|
||||
// Set views directory (html)
|
||||
const viewsDir = path_1.default.join(__dirname, 'views');
|
||||
app.set('views', viewsDir);
|
||||
// Set static directory (js and css).
|
||||
const staticDir = path_1.default.join(__dirname, 'public');
|
||||
app.use(express_1.default.static(staticDir));
|
||||
// Nav to users pg by default
|
||||
app.get('/', (_, res) => {
|
||||
return res.redirect('/users');
|
||||
});
|
||||
// Redirect to login if not logged in.
|
||||
app.get('/users', (_, res) => {
|
||||
return res.sendFile('users.html', { root: viewsDir });
|
||||
});
|
||||
// **** Export default **** //
|
||||
exports.default = app;
|
||||
//# sourceMappingURL=server.js.map
|
||||
1
lib/server.js.map
Normal file
1
lib/server.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;AAEH,kEAAyC;AACzC,oDAA4B;AAC5B,gDAAwB;AACxB,oDAA4B;AAC5B,sDAAmE;AACnE,4DAAgC;AAEhC,gCAA8B;AAE9B,0DAAyC;AACzC,wEAAgD;AAEhD,qEAA6C;AAC7C,qFAA6D;AAE7D,8CAA+C;AAC/C,gDAAgD;AAGhD,yBAAyB;AAEzB,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AAGtB,qBAAqB;AAErB,mBAAmB;AACnB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACxB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,UAAU,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;AAC9C,GAAG,CAAC,GAAG,CAAC,IAAA,uBAAY,EAAC,iBAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AAElD,mDAAmD;AACnD,IAAI,iBAAO,CAAC,OAAO,KAAK,eAAQ,CAAC,GAAG,EAAE,CAAC;IACrC,GAAG,CAAC,GAAG,CAAC,IAAA,gBAAM,EAAC,KAAK,CAAC,CAAC,CAAC;AACzB,CAAC;AAED,WAAW;AACX,IAAI,iBAAO,CAAC,OAAO,KAAK,eAAQ,CAAC,UAAU,EAAE,CAAC;IAC5C,GAAG,CAAC,GAAG,CAAC,IAAA,gBAAM,GAAE,CAAC,CAAC;AACpB,CAAC;AAED,qCAAqC;AACrC,GAAG,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,EAAE,aAAU,CAAC,CAAC;AAEhC,oBAAoB;AACpB,GAAG,CAAC,GAAG,CAAC,CACN,GAAU,EACV,CAAU,EACV,GAAa;AACb,6DAA6D;AAC7D,IAAkB,EAClB,EAAE;IACF,IAAI,iBAAO,CAAC,OAAO,KAAK,eAAQ,CAAC,IAAI,EAAE,CAAC;QACtC,oBAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,IAAI,MAAM,GAAG,yBAAe,CAAC,WAAW,CAAC;IACzC,IAAI,GAAG,YAAY,oBAAU,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AACzD,CAAC,CAAC,CAAC;AAGH,6BAA6B;AAE7B,6BAA6B;AAC7B,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAC/C,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAE3B,qCAAqC;AACrC,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AACjD,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;AAEnC,6BAA6B;AAC7B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAU,EAAE,GAAa,EAAE,EAAE;IACzC,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,sCAAsC;AACtC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAU,EAAE,GAAa,EAAE,EAAE;IAC9C,OAAO,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC;AAGH,8BAA8B;AAE9B,kBAAe,GAAG,CAAC"}
|
||||
45
lib/services/AuthService.js
Normal file
45
lib/services/AuthService.js
Normal file
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Errors = void 0;
|
||||
const user_repo_1 = __importDefault(require("@src/repos/user.repo"));
|
||||
const PwdUtil_1 = __importDefault(require("@src/util/PwdUtil"));
|
||||
const misc_1 = require("@src/util/misc");
|
||||
const HttpStatusCodes_1 = __importDefault(require("@src/constants/HttpStatusCodes"));
|
||||
const classes_1 = require("@src/other/classes");
|
||||
// **** Variables **** //
|
||||
// Errors
|
||||
exports.Errors = {
|
||||
Unauth: 'Unauthorized',
|
||||
EmailNotFound(email) {
|
||||
return `User with email "${email}" not found`;
|
||||
},
|
||||
};
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Login a user.
|
||||
*/
|
||||
async function login(email, password) {
|
||||
var _a;
|
||||
// Fetch user
|
||||
const user = await user_repo_1.default.getOne(email);
|
||||
if (!user) {
|
||||
throw new classes_1.RouteError(HttpStatusCodes_1.default.UNAUTHORIZED, exports.Errors.EmailNotFound(email));
|
||||
}
|
||||
// Check password
|
||||
const hash = ((_a = user.pwdHash) !== null && _a !== void 0 ? _a : ''), pwdPassed = await PwdUtil_1.default.compare(password, hash);
|
||||
if (!pwdPassed) {
|
||||
// If password failed, wait 500ms this will increase security
|
||||
await (0, misc_1.tick)(500);
|
||||
throw new classes_1.RouteError(HttpStatusCodes_1.default.UNAUTHORIZED, exports.Errors.Unauth);
|
||||
}
|
||||
// Return
|
||||
return user;
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
login,
|
||||
};
|
||||
//# sourceMappingURL=AuthService.js.map
|
||||
1
lib/services/AuthService.js.map
Normal file
1
lib/services/AuthService.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["../../src/services/AuthService.ts"],"names":[],"mappings":";;;;;;AAAA,qEAA4C;AAE5C,gEAAwC;AACxC,yCAAsC;AAEtC,qFAA6D;AAC7D,gDAAgD;AAIhD,yBAAyB;AAEzB,SAAS;AACI,QAAA,MAAM,GAAG;IACpB,MAAM,EAAE,cAAc;IACtB,aAAa,CAAC,KAAa;QACzB,OAAO,oBAAoB,KAAK,aAAa,CAAC;IAChD,CAAC;CACO,CAAC;AAGX,yBAAyB;AAEzB;;GAEG;AACH,KAAK,UAAU,KAAK,CAAC,KAAa,EAAE,QAAgB;;IAClD,aAAa;IACb,MAAM,IAAI,GAAG,MAAM,mBAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,oBAAU,CAClB,yBAAe,CAAC,YAAY,EAC5B,cAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAC5B,CAAC;IACJ,CAAC;IACD,iBAAiB;IACjB,MAAM,IAAI,GAAG,CAAC,MAAA,IAAI,CAAC,OAAO,mCAAI,EAAE,CAAC,EAC/B,SAAS,GAAG,MAAM,iBAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,6DAA6D;QAC7D,MAAM,IAAA,WAAI,EAAC,GAAG,CAAC,CAAC;QAChB,MAAM,IAAI,oBAAU,CAClB,yBAAe,CAAC,YAAY,EAC5B,cAAM,CAAC,MAAM,CACd,CAAC;IACJ,CAAC;IACD,SAAS;IACT,OAAO,IAAI,CAAC;AACd,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,KAAK;CACG,CAAC"}
|
||||
54
lib/services/UserService.js
Normal file
54
lib/services/UserService.js
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.USER_NOT_FOUND_ERR = void 0;
|
||||
const user_repo_1 = __importDefault(require("@src/repos/user.repo"));
|
||||
const classes_1 = require("@src/other/classes");
|
||||
const HttpStatusCodes_1 = __importDefault(require("@src/constants/HttpStatusCodes"));
|
||||
// **** Variables **** //
|
||||
exports.USER_NOT_FOUND_ERR = 'User not found';
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Get all users.
|
||||
*/
|
||||
function getAll() {
|
||||
return user_repo_1.default.getAll();
|
||||
}
|
||||
/**
|
||||
* Add one user.
|
||||
*/
|
||||
function addOne(user) {
|
||||
return user_repo_1.default.add(user);
|
||||
}
|
||||
/**
|
||||
* Update one user.
|
||||
*/
|
||||
async function updateOne(user) {
|
||||
const persists = await user_repo_1.default.persists(user.id);
|
||||
if (!persists) {
|
||||
throw new classes_1.RouteError(HttpStatusCodes_1.default.NOT_FOUND, exports.USER_NOT_FOUND_ERR);
|
||||
}
|
||||
// Return user
|
||||
return user_repo_1.default.update(user);
|
||||
}
|
||||
/**
|
||||
* Delete a user by their id.
|
||||
*/
|
||||
async function _delete(id) {
|
||||
const persists = await user_repo_1.default.persists(id);
|
||||
if (!persists) {
|
||||
throw new classes_1.RouteError(HttpStatusCodes_1.default.NOT_FOUND, exports.USER_NOT_FOUND_ERR);
|
||||
}
|
||||
// Delete user
|
||||
return user_repo_1.default.delete(id);
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
getAll,
|
||||
addOne,
|
||||
updateOne,
|
||||
delete: _delete,
|
||||
};
|
||||
//# sourceMappingURL=UserService.js.map
|
||||
1
lib/services/UserService.js.map
Normal file
1
lib/services/UserService.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"UserService.js","sourceRoot":"","sources":["../../src/services/UserService.ts"],"names":[],"mappings":";;;;;;AAAA,qEAA4C;AAE5C,gDAAgD;AAChD,qFAA6D;AAG7D,yBAAyB;AAEZ,QAAA,kBAAkB,GAAG,gBAAgB,CAAC;AAGnD,yBAAyB;AAEzB;;GAEG;AACH,SAAS,MAAM;IACb,OAAO,mBAAQ,CAAC,MAAM,EAAE,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAS,MAAM,CAAC,IAAW;IACzB,OAAO,mBAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,SAAS,CAAC,IAAW;IAClC,MAAM,QAAQ,GAAG,MAAM,mBAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,oBAAU,CAClB,yBAAe,CAAC,SAAS,EACzB,0BAAkB,CACnB,CAAC;IACJ,CAAC;IACD,cAAc;IACd,OAAO,mBAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO,CAAC,EAAU;IAC/B,MAAM,QAAQ,GAAG,MAAM,mBAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,oBAAU,CAClB,yBAAe,CAAC,SAAS,EACzB,0BAAkB,CACnB,CAAC;IACJ,CAAC;IACD,cAAc;IACd,OAAO,mBAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC7B,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,MAAM;IACN,MAAM;IACN,SAAS;IACT,MAAM,EAAE,OAAO;CACP,CAAC"}
|
||||
34
lib/util/PwdUtil.js
Normal file
34
lib/util/PwdUtil.js
Normal file
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const bcrypt_1 = __importDefault(require("bcrypt"));
|
||||
// **** Variables **** //
|
||||
const SALT_ROUNDS = 12;
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Get a hash from the password.
|
||||
*/
|
||||
function getHash(pwd) {
|
||||
return bcrypt_1.default.hash(pwd, SALT_ROUNDS);
|
||||
}
|
||||
/**
|
||||
* Useful for testing.
|
||||
*/
|
||||
function hashSync(pwd) {
|
||||
return bcrypt_1.default.hashSync(pwd, SALT_ROUNDS);
|
||||
}
|
||||
/**
|
||||
* See if a password passes the hash.
|
||||
*/
|
||||
function compare(pwd, hash) {
|
||||
return bcrypt_1.default.compare(pwd, hash);
|
||||
}
|
||||
// **** Export Default **** //
|
||||
exports.default = {
|
||||
getHash,
|
||||
hashSync,
|
||||
compare,
|
||||
};
|
||||
//# sourceMappingURL=PwdUtil.js.map
|
||||
1
lib/util/PwdUtil.js.map
Normal file
1
lib/util/PwdUtil.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"PwdUtil.js","sourceRoot":"","sources":["../../src/util/PwdUtil.ts"],"names":[],"mappings":";;;;;AAAA,oDAA4B;AAG5B,yBAAyB;AAEzB,MAAM,WAAW,GAAG,EAAE,CAAC;AAGvB,yBAAyB;AAEzB;;GAEG;AACH,SAAS,OAAO,CAAC,GAAW;IAC1B,OAAO,gBAAM,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,gBAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,GAAW,EAAE,IAAY;IACxC,OAAO,gBAAM,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,OAAO;IACP,QAAQ;IACR,OAAO;CACC,CAAC"}
|
||||
74
lib/util/SessionUtil.js
Normal file
74
lib/util/SessionUtil.js
Normal file
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const HttpStatusCodes_1 = __importDefault(require("@src/constants/HttpStatusCodes"));
|
||||
const classes_1 = require("@src/other/classes");
|
||||
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
||||
const EnvVars_1 = __importDefault(require("../constants/EnvVars"));
|
||||
// **** Variables **** //
|
||||
// Errors
|
||||
const Errors = {
|
||||
ParamFalsey: 'Param is falsey',
|
||||
Validation: 'JSON-web-token validation failed.',
|
||||
};
|
||||
// Options
|
||||
const Options = {
|
||||
expiresIn: EnvVars_1.default.Jwt.Exp,
|
||||
};
|
||||
// **** Functions **** //
|
||||
/**
|
||||
* Get session data from request object (i.e. ISessionUser)
|
||||
*/
|
||||
function getSessionData(req) {
|
||||
const { Key } = EnvVars_1.default.CookieProps, jwt = req.signedCookies[Key];
|
||||
return _decode(jwt);
|
||||
}
|
||||
/**
|
||||
* Add a JWT to the response
|
||||
*/
|
||||
async function addSessionData(res, data) {
|
||||
if (!res || !data) {
|
||||
throw new classes_1.RouteError(HttpStatusCodes_1.default.BAD_REQUEST, Errors.ParamFalsey);
|
||||
}
|
||||
// Setup JWT
|
||||
const jwt = await _sign(data), { Key, Options } = EnvVars_1.default.CookieProps;
|
||||
// Return
|
||||
return res.cookie(Key, jwt, Options);
|
||||
}
|
||||
/**
|
||||
* Remove cookie
|
||||
*/
|
||||
function clearCookie(res) {
|
||||
const { Key, Options } = EnvVars_1.default.CookieProps;
|
||||
return res.clearCookie(Key, Options);
|
||||
}
|
||||
// **** Helper Functions **** //
|
||||
/**
|
||||
* Encrypt data and return jwt.
|
||||
*/
|
||||
function _sign(data) {
|
||||
return new Promise((res, rej) => {
|
||||
jsonwebtoken_1.default.sign(data, EnvVars_1.default.Jwt.Secret, { expiresIn: '1h' }, (err, token) => {
|
||||
return err ? rej(err) : res(token || '');
|
||||
});
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Decrypt JWT and extract client data.
|
||||
*/
|
||||
function _decode(jwt) {
|
||||
return new Promise((res, rej) => {
|
||||
jsonwebtoken_1.default.verify(jwt, EnvVars_1.default.Jwt.Secret, undefined, (err, decoded) => {
|
||||
return err ? rej(Errors.Validation) : res(decoded);
|
||||
});
|
||||
});
|
||||
}
|
||||
// **** Export default **** //
|
||||
exports.default = {
|
||||
addSessionData,
|
||||
getSessionData,
|
||||
clearCookie,
|
||||
};
|
||||
//# sourceMappingURL=SessionUtil.js.map
|
||||
1
lib/util/SessionUtil.js.map
Normal file
1
lib/util/SessionUtil.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"SessionUtil.js","sourceRoot":"","sources":["../../src/util/SessionUtil.ts"],"names":[],"mappings":";;;;;AAEA,qFAA6D;AAC7D,gDAAgD;AAChD,gEAAwC;AAExC,mEAA2C;AAG3C,yBAAyB;AAEzB,SAAS;AACT,MAAM,MAAM,GAAG;IACb,WAAW,EAAE,iBAAiB;IAC9B,UAAU,EAAE,mCAAmC;CACvC,CAAC;AAEX,UAAU;AACV,MAAM,OAAO,GAAG;IACd,SAAS,EAAE,iBAAO,CAAC,GAAG,CAAC,GAAG;CAC3B,CAAC;AAGF,yBAAyB;AAEzB;;GAEG;AACH,SAAS,cAAc,CAAI,GAAY;IACrC,MAAM,EAAE,GAAG,EAAE,GAAG,iBAAO,CAAC,WAAW,EACjC,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAC3B,GAAa,EACb,IAAqB;IAErB,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,MAAM,IAAI,oBAAU,CAAC,yBAAe,CAAC,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACxE,CAAC;IACD,YAAY;IACZ,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,EAC3B,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,iBAAO,CAAC,WAAW,CAAC;IACzC,SAAS;IACT,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,GAAa;IAChC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,iBAAO,CAAC,WAAW,CAAC;IAC7C,OAAO,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACvC,CAAC;AAGD,gCAAgC;AAEhC;;GAEG;AACH,SAAS,KAAK,CAAC,IAA8B;IAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9B,sBAAY,CAAC,IAAI,CACf,IAAI,EACJ,iBAAO,CAAC,GAAG,CAAC,MAAM,EAClB,EAAE,SAAS,EAAE,IAAI,EAAE,EACnB,CAAC,GAAiB,EAAE,KAAc,EAAE,EAAE;YACpC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAI,GAAW;IAC7B,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9B,sBAAY,CAAC,MAAM,CACjB,GAAG,EACH,iBAAO,CAAC,GAAG,CAAC,MAAM,EAClB,SAAS,EACT,CAAC,GAAiB,EAAE,OAA0C,EAAE,EAAE;YAChE,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAY,CAAC,CAAC;QAC1D,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAGD,8BAA8B;AAE9B,kBAAe;IACb,cAAc;IACd,cAAc;IACd,WAAW;CACH,CAAC"}
|
||||
24
lib/util/misc.js
Normal file
24
lib/util/misc.js
Normal file
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Miscellaneous shared functions go here.
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getRandomInt = getRandomInt;
|
||||
exports.tick = tick;
|
||||
/**
|
||||
* Get a random number between 1 and 1,000,000,000,000
|
||||
*/
|
||||
function getRandomInt() {
|
||||
return Math.floor(Math.random() * 1000000000000);
|
||||
}
|
||||
/**
|
||||
* Wait for a certain number of milliseconds.
|
||||
*/
|
||||
function tick(milliseconds) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, milliseconds);
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=misc.js.map
|
||||
1
lib/util/misc.js.map
Normal file
1
lib/util/misc.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"misc.js","sourceRoot":"","sources":["../../src/util/misc.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAMH,oCAEC;AAKD,oBAMC;AAhBD;;GAEG;AACH,SAAgB,YAAY;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,aAAiB,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,SAAgB,IAAI,CAAC,YAAoB;IACvC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,YAAY,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
||||
991
package-lock.json
generated
991
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "Seer",
|
||||
"name": "ara-kanban-service",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"build": "npx ts-node build.ts",
|
||||
"lint": "npx eslint --ext .ts src/",
|
||||
"lint:tests": "npx eslint --ext .ts spec/",
|
||||
"start": "node -r module-alias/register ./dist --env=production",
|
||||
"dev": "nodemon",
|
||||
"dev": "PORT=5000 nodemon",
|
||||
"test": "nodemon --config ./spec/nodemon.json",
|
||||
"test:no-reloading": "npx ts-node --files -r tsconfig-paths/register ./spec"
|
||||
},
|
||||
@@ -27,26 +27,32 @@
|
||||
"node": ">=8.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "^6.16.2",
|
||||
"bcrypt": "^6.0.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^16.3.1",
|
||||
"dotenv": "^16.6.1",
|
||||
"express": "^4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"helmet": "^7.0.0",
|
||||
"helmet": "^7.2.0",
|
||||
"inserturlparams": "^1.0.1",
|
||||
"jet-logger": "^1.3.1",
|
||||
"jet-validator": "^1.1.1",
|
||||
"jsonfile": "^6.1.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"module-alias": "^2.2.3",
|
||||
"morgan": "^1.10.0",
|
||||
"prisma": "^6.16.2",
|
||||
"ts-command-line-args": "^2.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^6.0.0",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/find": "^0.2.1",
|
||||
"@types/fs-extra": "^11.0.1",
|
||||
"@types/jasmine": "^4.3.5",
|
||||
"@types/jsonfile": "^6.1.1",
|
||||
"@types/jsonwebtoken": "^9.0.10",
|
||||
"@types/morgan": "^1.9.4",
|
||||
"@types/node": "^20.4.2",
|
||||
"@types/supertest": "^2.0.12",
|
||||
@@ -61,6 +67,6 @@
|
||||
"supertest": "^6.3.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.1.6"
|
||||
"typescript": "^5.9.2"
|
||||
}
|
||||
}
|
||||
|
||||
15
prisma/schema.prisma
Normal file
15
prisma/schema.prisma
Normal file
@@ -0,0 +1,15 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../generated/prisma"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import insertUrlParams from 'inserturlparams';
|
||||
|
||||
import app from '@src/server';
|
||||
|
||||
import UserRepo from '@src/repos/UserRepo';
|
||||
import User from '@src/models/User';
|
||||
import UserRepo from '@src/repos/user.repo';
|
||||
import User from '@src/models/user.model';
|
||||
import HttpStatusCodes from '@src/constants/HttpStatusCodes';
|
||||
import { USER_NOT_FOUND_ERR } from '@src/services/UserService';
|
||||
import FullPaths from '@src/routes/constants/FullPaths';
|
||||
|
||||
2
spec/types/supertest/index.d.ts
vendored
2
spec/types/supertest/index.d.ts
vendored
@@ -1,4 +1,4 @@
|
||||
import { IUser } from '@src/models/User';
|
||||
import { IUser } from '@src/models/user.model';
|
||||
import 'supertest';
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
* Environments variables declared here.
|
||||
*/
|
||||
|
||||
import { NodeEnvs } from './misc';
|
||||
|
||||
/* eslint-disable node/no-process-env */
|
||||
|
||||
|
||||
export default {
|
||||
NodeEnv: (process.env.NODE_ENV ?? ''),
|
||||
NodeEnv: (process.env.NODE_ENV as NodeEnvs ?? ''),
|
||||
Port: (process.env.PORT ?? 0),
|
||||
CookieProps: {
|
||||
Key: 'ExpressGeneratorTs',
|
||||
@@ -23,6 +25,6 @@ export default {
|
||||
},
|
||||
Jwt: {
|
||||
Secret: (process.env.JWT_SECRET ?? ''),
|
||||
Exp: (process.env.COOKIE_EXP ?? ''), // exp at the same time as the cookie
|
||||
Exp: (process.env.COOKIE_EXP && process.env.COOKIE_EXP !== '' ? process.env.COOKIE_EXP : '1h'), // exp at the same time as the cookie
|
||||
},
|
||||
} as const;
|
||||
|
||||
93
src/controllers/board.controller.ts
Normal file
93
src/controllers/board.controller.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { Request, Response } from 'express';
|
||||
import BoardRepo from '@src/repos/board.repo';
|
||||
import { IBoard } from '@src/models/board.model';
|
||||
|
||||
class BoardController {
|
||||
// Get all boards for a user
|
||||
public getBoardsByUserId = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boards = await BoardRepo.getBoardsByUserId(userId);
|
||||
return res.json({ boards });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Get single board by userId and boardId
|
||||
public getBoardByUserId = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardId = +req.params.boardId;
|
||||
const board = await BoardRepo.getBoardByUserId(userId, boardId);
|
||||
return res.json({ board });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Create board for a user
|
||||
public createBoard = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardData = req.body as IBoard;
|
||||
if (!boardData.name) {
|
||||
return res.status(400).json({ error: 'Board name required' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const board = await BoardRepo.createBoard(userId, boardData);
|
||||
return res.status(201).json({ board });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Update board for a user
|
||||
public updateBoard = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardData = req.body as IBoard;
|
||||
if (!boardData.name) {
|
||||
return res.status(400).json({ error: 'Board name required' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardId = +req.params.boardId;
|
||||
const board = await BoardRepo.updateBoard(userId, boardId, boardData);
|
||||
return res.json({ board });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Delete board for a user
|
||||
public deleteBoard = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const userId = +req.params.userId;
|
||||
const boardId = +req.params.boardId;
|
||||
await BoardRepo.deleteBoard(userId, boardId);
|
||||
return res.status(204).end();
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default new BoardController();
|
||||
95
src/controllers/task.controller.ts
Normal file
95
src/controllers/task.controller.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { Request, Response } from 'express';
|
||||
import TaskRepo from '@src/repos/task.repo';
|
||||
import { ITask } from '@src/models/task.model';
|
||||
|
||||
class TaskController {
|
||||
// Get all tasks for a board
|
||||
public getTasksByBoardId = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const tasks = await TaskRepo.getTasksByBoardId(boardId);
|
||||
return res.json({ tasks });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Get single task by boardId and taskId
|
||||
public getTaskByBoardId = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskId = +req.params.taskId;
|
||||
const task = await TaskRepo.getTaskByBoardId(boardId, taskId);
|
||||
return res.json({ task });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Create task for a board
|
||||
public createTask = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
// Dummy form validation
|
||||
const taskData = req.body as ITask;
|
||||
if (!taskData.title) {
|
||||
return res.status(400).json({ error: 'Task title required' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const task = await TaskRepo.createTask(boardId, taskData);
|
||||
return res.status(201).json({ task });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Update task for a board
|
||||
public updateTask = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
// Dummy form validation
|
||||
const taskData = req.body as ITask;
|
||||
if (!taskData.title) {
|
||||
return res.status(400).json({ error: 'Task title required' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskId = +req.params.taskId;
|
||||
const task = await TaskRepo.updateTask(boardId, taskId, taskData);
|
||||
return res.json({ task });
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
|
||||
// Delete task for a board
|
||||
public deleteTask = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const boardId = +req.params.boardId;
|
||||
const taskId = +req.params.taskId;
|
||||
await TaskRepo.deleteTask(boardId, taskId);
|
||||
return res.status(204).end();
|
||||
} catch (err) {
|
||||
return res.status(500).json({ error: 'Internal server error',
|
||||
details: String(err) });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default new TaskController();
|
||||
42
src/controllers/user.controller.ts
Normal file
42
src/controllers/user.controller.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Request, Response } from 'express';
|
||||
import UserRepo from '@src/repos/user.repo';
|
||||
import { IUser } from '@src/models/user.model';
|
||||
|
||||
class UserController {
|
||||
public getAll = async (req: Request, res: Response) => {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const users = await UserRepo.getAll();
|
||||
return res.status(200).json({ users });
|
||||
};
|
||||
|
||||
public add = async (req: Request, res: Response) => {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const user = req.body.user as IUser;
|
||||
await UserRepo.add(user);
|
||||
return res.status(201).end();
|
||||
};
|
||||
|
||||
public update = async (req: Request, res: Response) => {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const user = req.body.user as IUser;
|
||||
await UserRepo.update(user);
|
||||
return res.status(200).end();
|
||||
};
|
||||
|
||||
public delete = async (req: Request, res: Response) => {
|
||||
if (req.headers.authorization !== 'Bearer testtoken') {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
const id = +req.params.id;
|
||||
await UserRepo.delete(id);
|
||||
return res.status(200).end();
|
||||
};
|
||||
}
|
||||
|
||||
export default new UserController();
|
||||
80
src/models/board.model.ts
Normal file
80
src/models/board.model.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
// **** Variables **** //
|
||||
|
||||
const INVALID_CONSTRUCTOR_PARAM = 'nameOrObj arg must be a string or an object with the appropriate board keys.';
|
||||
|
||||
// **** Types **** //
|
||||
|
||||
export interface IBoard {
|
||||
id: number;
|
||||
userId: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// **** Functions **** //
|
||||
|
||||
/**
|
||||
* Create new Board.
|
||||
*/
|
||||
function new_(
|
||||
userId?: number,
|
||||
name?: string,
|
||||
description?: string,
|
||||
createdAt?: string,
|
||||
updatedAt?: string,
|
||||
id?: number,
|
||||
): IBoard {
|
||||
const now = new Date().toISOString();
|
||||
return {
|
||||
id: (id ?? -1),
|
||||
userId: (userId ?? -1),
|
||||
name: (name ?? ''),
|
||||
description,
|
||||
createdAt: (createdAt ?? now),
|
||||
updatedAt: (updatedAt ?? now),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get board instance from object.
|
||||
*/
|
||||
function from(param: object): IBoard {
|
||||
if (!isBoard(param)) {
|
||||
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
||||
}
|
||||
const p = param as IBoard;
|
||||
return new_(p.userId, p.name, p.description, p.createdAt, p.updatedAt, p.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the param meets criteria to be a board.
|
||||
*/
|
||||
function isBoard(arg: unknown): boolean {
|
||||
return (
|
||||
!!arg &&
|
||||
typeof arg === 'object' &&
|
||||
'id' in arg &&
|
||||
'userId' in arg &&
|
||||
'name' in arg &&
|
||||
'createdAt' in arg &&
|
||||
'updatedAt' in arg
|
||||
);
|
||||
}
|
||||
|
||||
// **** Export default **** //
|
||||
|
||||
export default {
|
||||
new: new_,
|
||||
from,
|
||||
isBoard,
|
||||
} as const;
|
||||
export interface IBoard {
|
||||
id: number;
|
||||
userId: number;
|
||||
name: string;
|
||||
description?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
85
src/models/task.model.ts
Normal file
85
src/models/task.model.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
// **** Variables **** //
|
||||
|
||||
const INVALID_CONSTRUCTOR_PARAM = 'titleOrObj arg must be a string or an object with the appropriate task keys.';
|
||||
|
||||
// **** Types **** //
|
||||
|
||||
export interface ITask {
|
||||
id: number;
|
||||
boardId: number;
|
||||
title: string;
|
||||
description?: string;
|
||||
status: 'todo' | 'in-progress' | 'done';
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
// **** Functions **** //
|
||||
|
||||
/**
|
||||
* Create new Task.
|
||||
*/
|
||||
function new_(
|
||||
boardId?: number,
|
||||
title?: string,
|
||||
status?: 'todo' | 'in-progress' | 'done',
|
||||
description?: string,
|
||||
createdAt?: string,
|
||||
updatedAt?: string,
|
||||
id?: number,
|
||||
): ITask {
|
||||
const now = new Date().toISOString();
|
||||
return {
|
||||
id: (id ?? -1),
|
||||
boardId: (boardId ?? -1),
|
||||
title: (title ?? ''),
|
||||
status: (status ?? 'todo'),
|
||||
description,
|
||||
createdAt: (createdAt ?? now),
|
||||
updatedAt: (updatedAt ?? now),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get task instance from object.
|
||||
*/
|
||||
function from(param: object): ITask {
|
||||
if (!isTask(param)) {
|
||||
throw new Error(INVALID_CONSTRUCTOR_PARAM);
|
||||
}
|
||||
const p = param as ITask;
|
||||
return new_(p.boardId, p.title, p.status, p.description, p.createdAt, p.updatedAt, p.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the param meets criteria to be a task.
|
||||
*/
|
||||
function isTask(arg: unknown): boolean {
|
||||
return (
|
||||
!!arg &&
|
||||
typeof arg === 'object' &&
|
||||
'id' in arg &&
|
||||
'boardId' in arg &&
|
||||
'title' in arg &&
|
||||
'status' in arg &&
|
||||
'createdAt' in arg &&
|
||||
'updatedAt' in arg
|
||||
);
|
||||
}
|
||||
|
||||
// **** Export default **** //
|
||||
|
||||
export default {
|
||||
new: new_,
|
||||
from,
|
||||
isTask,
|
||||
} as const;
|
||||
export interface ITask {
|
||||
id: number;
|
||||
boardId: number;
|
||||
title: string;
|
||||
description?: string;
|
||||
status: 'todo' | 'in-progress' | 'done';
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
body {
|
||||
padding: 100px;
|
||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body .users-column {
|
||||
display: inline-block;
|
||||
margin-right: 2em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
body .users-column .column-header {
|
||||
padding-bottom: 5px;
|
||||
font-weight: 700;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
|
||||
/** Add User Column **/
|
||||
|
||||
body .add-user-col input {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
body .add-user-col #add-user-btn {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
body .add-user-col #logout-btn {
|
||||
margin-top: 25px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
|
||||
/** Users Display Column **/
|
||||
|
||||
body .users-column .user-display-ele {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
body .users-column .user-display-ele button {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
body .users-column .user-display-ele .edit-view {
|
||||
display: none;
|
||||
}
|
||||
53
src/repos/BoardRepo.ts
Normal file
53
src/repos/BoardRepo.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { IBoard } from '@src/models/board.model';
|
||||
import orm from './MockOrm';
|
||||
|
||||
async function getBoardsByUserId(userId: number): Promise<IBoard[]> {
|
||||
const db = await orm.openDb();
|
||||
return db.boards.filter((board: IBoard) => board.userId === userId);
|
||||
}
|
||||
|
||||
async function getBoardByUserId(userId: number, boardId: number): Promise<IBoard | null> {
|
||||
const db = await orm.openDb();
|
||||
return db.boards.find((board: IBoard) => board.userId === userId && board.id === boardId) || null;
|
||||
}
|
||||
|
||||
async function createBoard(userId: number, board: IBoard): Promise<IBoard> {
|
||||
const db = await orm.openDb();
|
||||
board.id = Date.now();
|
||||
board.userId = userId;
|
||||
board.createdAt = new Date().toISOString();
|
||||
board.updatedAt = board.createdAt;
|
||||
db.boards.push(board);
|
||||
await orm.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
|
||||
async function updateBoard(userId: number, boardId: number, boardData: Partial<IBoard>): Promise<IBoard | null> {
|
||||
const db = await orm.openDb();
|
||||
const board = db.boards.find((b: IBoard) => b.userId === userId && b.id === boardId);
|
||||
if (board) {
|
||||
Object.assign(board, boardData, { updatedAt: new Date().toISOString() });
|
||||
await orm.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function deleteBoard(userId: number, boardId: number): Promise<boolean> {
|
||||
const db = await orm.openDb();
|
||||
const idx = db.boards.findIndex((b: IBoard) => b.userId === userId && b.id === boardId);
|
||||
if (idx !== -1) {
|
||||
db.boards.splice(idx, 1);
|
||||
await orm.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export default {
|
||||
getBoardsByUserId,
|
||||
getBoardByUserId,
|
||||
createBoard,
|
||||
updateBoard,
|
||||
deleteBoard,
|
||||
};
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
import jsonfile from 'jsonfile';
|
||||
|
||||
import { IUser } from '@src/models/User';
|
||||
import { IUser } from '@src/models/user.model';
|
||||
import { IBoard } from '@src/models/board.model';
|
||||
import { ITask } from '@src/models/task.model';
|
||||
|
||||
|
||||
// **** Variables **** //
|
||||
@@ -14,6 +16,8 @@ const DB_FILE_NAME = 'database.json';
|
||||
|
||||
interface IDb {
|
||||
users: IUser[];
|
||||
boards: IBoard[];
|
||||
tasks: ITask[];
|
||||
}
|
||||
|
||||
|
||||
|
||||
53
src/repos/TaskRepo.ts
Normal file
53
src/repos/TaskRepo.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { ITask } from '@src/models/task.model';
|
||||
import orm from './MockOrm';
|
||||
|
||||
async function getTasksByBoardId(boardId: number): Promise<ITask[]> {
|
||||
const db = await orm.openDb();
|
||||
return db.tasks.filter((task: ITask) => task.boardId === boardId);
|
||||
}
|
||||
|
||||
async function getTaskByBoardId(boardId: number, taskId: number): Promise<ITask | null> {
|
||||
const db = await orm.openDb();
|
||||
return db.tasks.find((task: ITask) => task.boardId === boardId && task.id === taskId) || null;
|
||||
}
|
||||
|
||||
async function createTask(boardId: number, task: ITask): Promise<ITask> {
|
||||
const db = await orm.openDb();
|
||||
task.id = Date.now();
|
||||
task.boardId = boardId;
|
||||
task.createdAt = new Date().toISOString();
|
||||
task.updatedAt = task.createdAt;
|
||||
db.tasks.push(task);
|
||||
await orm.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
|
||||
async function updateTask(boardId: number, taskId: number, taskData: Partial<ITask>): Promise<ITask | null> {
|
||||
const db = await orm.openDb();
|
||||
const task = db.tasks.find((t: ITask) => t.boardId === boardId && t.id === taskId);
|
||||
if (task) {
|
||||
Object.assign(task, taskData, { updatedAt: new Date().toISOString() });
|
||||
await orm.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function deleteTask(boardId: number, taskId: number): Promise<boolean> {
|
||||
const db = await orm.openDb();
|
||||
const idx = db.tasks.findIndex((t: ITask) => t.boardId === boardId && t.id === taskId);
|
||||
if (idx !== -1) {
|
||||
db.tasks.splice(idx, 1);
|
||||
await orm.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export default {
|
||||
getTasksByBoardId,
|
||||
getTaskByBoardId,
|
||||
createTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
};
|
||||
64
src/repos/board.repo.ts
Normal file
64
src/repos/board.repo.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { IBoard } from '@src/models/board.model';
|
||||
import orm from './MockOrm';
|
||||
|
||||
async function getBoardsByUserId(userId: number): Promise<IBoard[]> {
|
||||
const db = await orm.openDb();
|
||||
const boards = Array.isArray(db.boards) ? db.boards : [];
|
||||
return boards.filter((board: IBoard) => board.userId === userId);
|
||||
}
|
||||
|
||||
async function getBoardByUserId(userId: number, boardId: number):
|
||||
Promise<IBoard | null> {
|
||||
const db = await orm.openDb();
|
||||
const boards = Array.isArray(db.boards) ? db.boards : [];
|
||||
return boards.find(
|
||||
(board: IBoard) => board.userId === userId && board.id === boardId,
|
||||
) || null;
|
||||
}
|
||||
|
||||
async function createBoard(userId: number, board: IBoard): Promise<IBoard> {
|
||||
const db = await orm.openDb();
|
||||
if (!Array.isArray(db.boards)) db.boards = [];
|
||||
board.id = Date.now();
|
||||
board.userId = userId;
|
||||
board.createdAt = new Date().toISOString();
|
||||
board.updatedAt = board.createdAt;
|
||||
db.boards.push(board);
|
||||
await orm.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
|
||||
async function updateBoard(userId: number, boardId: number, boardData:
|
||||
Partial<IBoard>): Promise<IBoard | null> {
|
||||
const db = await orm.openDb();
|
||||
const boards = Array.isArray(db.boards) ? db.boards : [];
|
||||
const board = boards.find((b: IBoard) => b.userId === userId &&
|
||||
b.id === boardId);
|
||||
if (board) {
|
||||
Object.assign(board, boardData, { updatedAt: new Date().toISOString() });
|
||||
await orm.saveDb(db);
|
||||
return board;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function deleteBoard(userId: number, boardId: number): Promise<boolean> {
|
||||
const db = await orm.openDb();
|
||||
const boards = Array.isArray(db.boards) ? db.boards : [];
|
||||
const idx = boards.findIndex((b: IBoard) => b.userId === userId &&
|
||||
b.id === boardId);
|
||||
if (idx !== -1) {
|
||||
boards.splice(idx, 1);
|
||||
await orm.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export default {
|
||||
getBoardsByUserId,
|
||||
getBoardByUserId,
|
||||
createBoard,
|
||||
updateBoard,
|
||||
deleteBoard,
|
||||
};
|
||||
@@ -1 +1 @@
|
||||
{"users":[{"name":"Sean Maxwell","email":"sean.maxwell@gmail.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":1,"id":159123164363},{"name":"Gordan Freeman","email":"gordan.freeman@halflife.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":0,"id":906524522143},{"name":"John Smith","email":"jsmith@yahoo.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":0,"id":357437875835},{"id":75800032258,"name":"asdf","email":"asdfasdf","role":0}]}
|
||||
{"users":[{"name":"Sean Maxwell","email":"sean.maxwell@gmail.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":1,"id":159123164363},{"name":"Gordan Freeman","email":"gordan.freeman@halflife.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":0,"id":906524522143},{"name":"John Smith","email":"jsmith@yahoo.com","pwdHash":"$2b$12$1mE2OI9hMS/rgH9Mi0s85OM2V5gzm7aF3gJIWH1y0S1MqVBueyjsy","role":0,"id":357437875835},{"id":75800032258,"name":"asdf","email":"asdfasdf","role":0}],"boards":[{"name":"Project Board","id":1758960982352,"userId":1,"createdAt":"2025-09-27T08:16:22.352Z","updatedAt":"2025-09-27T08:16:22.352Z"}],"tasks":[{"title":"New Task","description":"Task details","status":"todo","id":1758961254717,"boardId":1758960982352,"createdAt":"2025-09-27T08:20:54.717Z","updatedAt":"2025-09-27T08:20:54.717Z"},{"title":"New Task 2","description":"Task details 2","status":"todo","id":1758961267429,"boardId":1758960982352,"createdAt":"2025-09-27T08:21:07.429Z","updatedAt":"2025-09-27T08:21:07.429Z"}]}
|
||||
|
||||
63
src/repos/task.repo.ts
Normal file
63
src/repos/task.repo.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { ITask } from '@src/models/task.model';
|
||||
import orm from './MockOrm';
|
||||
|
||||
async function getTasksByBoardId(boardId: number): Promise<ITask[]> {
|
||||
const db = await orm.openDb();
|
||||
const tasks = Array.isArray(db.tasks) ? db.tasks : [];
|
||||
return tasks.filter((task: ITask) => task.boardId === boardId);
|
||||
}
|
||||
|
||||
async function getTaskByBoardId(boardId: number, taskId: number):
|
||||
Promise<ITask | null> {
|
||||
const db = await orm.openDb();
|
||||
const tasks = Array.isArray(db.tasks) ? db.tasks : [];
|
||||
return tasks.find((task: ITask) => task.boardId === boardId &&
|
||||
task.id === taskId) || null;
|
||||
}
|
||||
|
||||
async function createTask(boardId: number, task: ITask): Promise<ITask> {
|
||||
const db = await orm.openDb();
|
||||
if (!Array.isArray(db.tasks)) db.tasks = [];
|
||||
task.id = Date.now();
|
||||
task.boardId = boardId;
|
||||
task.createdAt = new Date().toISOString();
|
||||
task.updatedAt = task.createdAt;
|
||||
db.tasks.push(task);
|
||||
await orm.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
|
||||
async function updateTask(boardId: number, taskId: number, taskData:
|
||||
Partial<ITask>): Promise<ITask | null> {
|
||||
const db = await orm.openDb();
|
||||
const tasks = Array.isArray(db.tasks) ? db.tasks : [];
|
||||
const task = tasks.find((t: ITask) => t.boardId === boardId &&
|
||||
t.id === taskId);
|
||||
if (task) {
|
||||
Object.assign(task, taskData, { updatedAt: new Date().toISOString() });
|
||||
await orm.saveDb(db);
|
||||
return task;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function deleteTask(boardId: number, taskId: number): Promise<boolean> {
|
||||
const db = await orm.openDb();
|
||||
const tasks = Array.isArray(db.tasks) ? db.tasks : [];
|
||||
const idx = tasks.findIndex((t: ITask) => t.boardId === boardId &&
|
||||
t.id === taskId);
|
||||
if (idx !== -1) {
|
||||
tasks.splice(idx, 1);
|
||||
await orm.saveDb(db);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export default {
|
||||
getTasksByBoardId,
|
||||
getTaskByBoardId,
|
||||
createTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IUser } from '@src/models/User';
|
||||
import { IUser } from '@src/models/user.model';
|
||||
import { getRandomInt } from '@src/util/misc';
|
||||
import orm from './MockOrm';
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import HttpStatusCodes from '@src/constants/HttpStatusCodes';
|
||||
|
||||
import UserService from '@src/services/UserService';
|
||||
import { IUser } from '@src/models/User';
|
||||
import { IReq, IRes } from './types/express/misc';
|
||||
|
||||
|
||||
// **** Functions **** //
|
||||
|
||||
/**
|
||||
* Get all users.
|
||||
*/
|
||||
async function getAll(_: IReq, res: IRes) {
|
||||
const users = await UserService.getAll();
|
||||
return res.status(HttpStatusCodes.OK).json({ users });
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one user.
|
||||
*/
|
||||
async function add(req: IReq<{user: IUser}>, res: IRes) {
|
||||
const { user } = req.body;
|
||||
await UserService.addOne(user);
|
||||
return res.status(HttpStatusCodes.CREATED).end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update one user.
|
||||
*/
|
||||
async function update(req: IReq<{user: IUser}>, res: IRes) {
|
||||
const { user } = req.body;
|
||||
await UserService.updateOne(user);
|
||||
return res.status(HttpStatusCodes.OK).end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete one user.
|
||||
*/
|
||||
async function delete_(req: IReq, res: IRes) {
|
||||
const id = +req.params.id;
|
||||
await UserService.delete(id);
|
||||
return res.status(HttpStatusCodes.OK).end();
|
||||
}
|
||||
|
||||
|
||||
// **** Export default **** //
|
||||
|
||||
export default {
|
||||
getAll,
|
||||
add,
|
||||
update,
|
||||
delete: delete_,
|
||||
} as const;
|
||||
@@ -1,52 +0,0 @@
|
||||
import { Router } from 'express';
|
||||
import jetValidator from 'jet-validator';
|
||||
|
||||
import Paths from './constants/Paths';
|
||||
import User from '@src/models/User';
|
||||
import UserRoutes from './UserRoutes';
|
||||
|
||||
|
||||
// **** Variables **** //
|
||||
|
||||
const apiRouter = Router(),
|
||||
validate = jetValidator();
|
||||
|
||||
|
||||
// ** Add UserRouter ** //
|
||||
|
||||
const userRouter = Router();
|
||||
|
||||
// Get all users
|
||||
userRouter.get(
|
||||
Paths.Users.Get,
|
||||
UserRoutes.getAll,
|
||||
);
|
||||
|
||||
// Add one user
|
||||
userRouter.post(
|
||||
Paths.Users.Add,
|
||||
validate(['user', User.isUser]),
|
||||
UserRoutes.add,
|
||||
);
|
||||
|
||||
// Update one user
|
||||
userRouter.put(
|
||||
Paths.Users.Update,
|
||||
validate(['user', User.isUser]),
|
||||
UserRoutes.update,
|
||||
);
|
||||
|
||||
// Delete one user
|
||||
userRouter.delete(
|
||||
Paths.Users.Delete,
|
||||
validate(['id', 'number', 'params']),
|
||||
UserRoutes.delete,
|
||||
);
|
||||
|
||||
// Add UserRouter
|
||||
apiRouter.use(Paths.Users.Base, userRouter);
|
||||
|
||||
|
||||
// **** Export default **** //
|
||||
|
||||
export default apiRouter;
|
||||
13
src/routes/board.route.ts
Normal file
13
src/routes/board.route.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
import { Router } from 'express';
|
||||
import BoardController from '../controllers/board.controller';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/user/:userId', BoardController.getBoardsByUserId);
|
||||
router.get('/user/:userId/:boardId', BoardController.getBoardByUserId);
|
||||
router.post('/user/:userId', BoardController.createBoard);
|
||||
router.put('/user/:userId/:boardId', BoardController.updateBoard);
|
||||
router.delete('/user/:userId/:boardId', BoardController.deleteBoard);
|
||||
|
||||
export default router;
|
||||
@@ -1,40 +0,0 @@
|
||||
|
||||
/**
|
||||
* Convert paths to full paths.
|
||||
*/
|
||||
|
||||
import Paths, { TPaths } from './Paths';
|
||||
|
||||
|
||||
interface IPathObj {
|
||||
Base: string;
|
||||
[key: string]: string | IPathObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* The recursive function.
|
||||
*/
|
||||
function getFullPaths(
|
||||
parent: IPathObj,
|
||||
baseUrl: string,
|
||||
): IPathObj {
|
||||
const url = (baseUrl + parent.Base),
|
||||
keys = Object.keys(parent),
|
||||
retVal: IPathObj = { Base: url };
|
||||
// Iterate keys
|
||||
for (const key of keys) {
|
||||
const pval = parent[key];
|
||||
if (key !== 'Base' && typeof pval === 'string') {
|
||||
retVal[key] = (url + pval);
|
||||
} else if (typeof pval === 'object') {
|
||||
retVal[key] = getFullPaths(pval, url);
|
||||
}
|
||||
}
|
||||
// Return
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
// **** Export default **** //
|
||||
|
||||
export default getFullPaths(Paths, '') as TPaths;
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Express router paths go here.
|
||||
*/
|
||||
|
||||
import { Immutable } from '@src/other/types';
|
||||
|
||||
|
||||
const Paths = {
|
||||
Base: '/api',
|
||||
Users: {
|
||||
Base: '/users',
|
||||
Get: '/all',
|
||||
Add: '/add',
|
||||
Update: '/update',
|
||||
Delete: '/delete/:id',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
// **** Export **** //
|
||||
|
||||
export type TPaths = Immutable<typeof Paths>;
|
||||
export default Paths as TPaths;
|
||||
12
src/routes/index.ts
Normal file
12
src/routes/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Router } from 'express';
|
||||
import boardRouter from './board.route';
|
||||
import taskRouter from './task.route';
|
||||
import userRouter from './user.route';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.use('/boards', boardRouter);
|
||||
router.use('/tasks', taskRouter);
|
||||
router.use('/users', userRouter);
|
||||
|
||||
export default router;
|
||||
13
src/routes/task.route.ts
Normal file
13
src/routes/task.route.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
import { Router } from 'express';
|
||||
import TaskController from '../controllers/task.controller';
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get('/board/:boardId', TaskController.getTasksByBoardId);
|
||||
router.get('/board/:boardId/:taskId', TaskController.getTaskByBoardId);
|
||||
router.post('/board/:boardId', TaskController.createTask);
|
||||
router.put('/board/:boardId/:taskId', TaskController.updateTask);
|
||||
router.delete('/board/:boardId/:taskId', TaskController.deleteTask);
|
||||
|
||||
export default router;
|
||||
11
src/routes/types/express/index.d.ts
vendored
11
src/routes/types/express/index.d.ts
vendored
@@ -1,11 +0,0 @@
|
||||
import 'express';
|
||||
|
||||
|
||||
// **** Declaration Merging **** //
|
||||
|
||||
declare module 'express' {
|
||||
|
||||
export interface Request {
|
||||
signedCookies: Record<string, string>;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user