@andrewcaires/api 1.0.0 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,19 @@
1
+ /*!
2
+ * @andrewcaires/api v1.0.3
3
+ * (c) 2022 Andrew Caires
4
+ * @license: MIT
5
+ */
1
6
  /// <reference types="node" />
2
7
  import * as https from 'https';
3
8
  import * as http from 'http';
4
9
  import * as _sequelize from 'sequelize';
5
10
  import { Model, Sequelize, ModelStatic, FindOptions, Attributes } from 'sequelize';
6
11
  import * as express_serve_static_core from 'express-serve-static-core';
7
- import WebSocket from 'ws';
8
12
  import { Request, Response, NextFunction } from 'express';
9
- import { WhereOptions } from 'sequelize/types';
10
13
  import { ObjectSchema } from 'joi';
14
+ import { WhereOptions } from 'sequelize/types';
15
+ import { TypeObject } from '@andrewcaires/utils.js';
16
+ import WebSocket from 'ws';
11
17
 
12
18
  declare const initialize: () => void;
13
19
  declare const server: http.Server | https.Server;
@@ -95,9 +101,31 @@ declare class Logs extends Model {
95
101
  }
96
102
 
97
103
  declare const app: express_serve_static_core.Express;
98
-
99
104
  declare const router: express_serve_static_core.Router;
100
105
 
106
+ declare global {
107
+ namespace Express {
108
+ interface Request {
109
+ auth?: Auth;
110
+ user?: User;
111
+ }
112
+ }
113
+ }
114
+ declare const auth: (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
115
+
116
+ declare const permission: (name: string) => (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
117
+
118
+ interface UploadOptions {
119
+ count?: number;
120
+ field?: string;
121
+ path?: string;
122
+ size?: number;
123
+ types?: string[];
124
+ }
125
+ declare const upload: (options?: UploadOptions) => (req: Request, res: Response, next: NextFunction) => void;
126
+
127
+ declare const validation: (schema: ObjectSchema) => (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
128
+
101
129
  declare const uuid: {
102
130
  type: _sequelize.AbstractDataTypeConstructor;
103
131
  defaultValue: _sequelize.AbstractDataTypeConstructor;
@@ -115,8 +143,6 @@ declare const key: {
115
143
  token: Buffer | undefined;
116
144
  };
117
145
 
118
- declare const startSocket: (server: http.Server | https.Server) => WebSocket.Server;
119
-
120
146
  declare type FnRecord<M> = (records: M) => any;
121
147
  declare type FnRecords<M> = (records: Array<M>) => Array<any>;
122
148
  declare class Controller<M extends Model<M>> {
@@ -131,11 +157,11 @@ declare class Controller<M extends Model<M>> {
131
157
  }
132
158
 
133
159
  declare class Log {
134
- static write(message: string, source?: string): void;
135
- static error(message: string, source?: string): void;
136
- static info(message: string, source?: string): void;
137
- static success(message: string, source?: string): void;
138
- static warning(message: string, source?: string): void;
160
+ static write(message: string, source?: string, console?: boolean): void;
161
+ static error(message: string, source?: string, console?: boolean): void;
162
+ static info(message: string, source?: string, console?: boolean): void;
163
+ static success(message: string, source?: string, console?: boolean): void;
164
+ static warning(message: string, source?: string, console?: boolean): void;
139
165
  private static writeConsole;
140
166
  private static writeRaw;
141
167
  }
@@ -156,27 +182,19 @@ declare class Responses {
156
182
  static unauthorized(res: Response, message: string): Response<any, Record<string, any>>;
157
183
  }
158
184
 
159
- declare global {
160
- namespace Express {
161
- interface Request {
162
- auth: Auth | undefined;
163
- user: User | undefined;
164
- }
165
- }
185
+ interface TokenSign {
186
+ error?: string;
187
+ token?: string;
166
188
  }
167
- declare const auth: (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
168
-
169
- declare const permission: (name: string) => (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
170
-
171
- interface UploadOptions {
172
- count?: number;
173
- field?: string;
174
- path?: string;
175
- size?: number;
176
- types?: string[];
189
+ interface TokenVerify {
190
+ error?: string;
191
+ decode?: TypeObject<string | number | boolean>;
192
+ }
193
+ declare class Token {
194
+ static sign(payload: TypeObject<string | number>): TokenSign;
195
+ static verify(token: string): TokenVerify;
177
196
  }
178
- declare const upload: (options?: UploadOptions | undefined) => (req: Request, res: Response, next: NextFunction) => void;
179
197
 
180
- declare const validation: (schema: ObjectSchema) => (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
198
+ declare const startSocket: (server: http.Server | https.Server) => WebSocket.Server;
181
199
 
182
- export { API_AUTH_SLEEP, API_DB_DATABASE, API_DB_HOST, API_DB_LOG, API_DB_PASSWORD, API_DB_PORT, API_DB_TYPE, API_DB_USERNAME, API_HTTP_CROSS, API_HTTP_CRT, API_HTTP_HYBRID, API_HTTP_KEY, API_HTTP_PORT, API_HTTP_PUBLIC, API_TOKEN_CRT, API_TOKEN_HEADER, API_TOKEN_KEY, API_TOKEN_LIFETIME, API_UPLOAD_COUNT, API_UPLOAD_FIELD, API_UPLOAD_SIZE, API_UPLOAD_TEMP, API_WEBSOCKET_START, Auth, Controller, Group, GroupRoute, Log, Logs, Permission, Responses, Route, User, UserGroup, app, auth, crt, initialize, key, permission, router, sequelize, server, startSocket, upload, uuid, validation };
200
+ export { API_AUTH_SLEEP, API_DB_DATABASE, API_DB_HOST, API_DB_LOG, API_DB_PASSWORD, API_DB_PORT, API_DB_TYPE, API_DB_USERNAME, API_HTTP_CROSS, API_HTTP_CRT, API_HTTP_HYBRID, API_HTTP_KEY, API_HTTP_PORT, API_HTTP_PUBLIC, API_TOKEN_CRT, API_TOKEN_HEADER, API_TOKEN_KEY, API_TOKEN_LIFETIME, API_UPLOAD_COUNT, API_UPLOAD_FIELD, API_UPLOAD_SIZE, API_UPLOAD_TEMP, API_WEBSOCKET_START, Auth, Controller, Group, GroupRoute, Log, Logs, Permission, Responses, Route, Token, User, UserGroup, app, auth, crt, initialize, key, permission, router, sequelize, server, startSocket, upload, uuid, validation };
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * @andrewcaires/api v1.0.0
2
+ * @andrewcaires/api v1.0.3
3
3
  * (c) 2022 Andrew Caires
4
4
  * @license: MIT
5
5
  */
6
- import{toBool as e,forEachSeries as t,dateFormat as r,sleep as s,uniqueID as o,allowedObject as n,uuidv4 as i}from"@andrewcaires/utils.js";import{config as a}from"dotenv";import{Sequelize as d,UUID as u,UUIDV4 as c,DataTypes as l,Model as m}from"sequelize";import p from"cors";import g,{Router as v}from"express";import{existsSync as f,readFileSync as h}from"fs";import{SHA256 as y}from"crypto-js";import w from"jsonwebtoken";import I from"joi";import*as b from"http";import*as T from"https";import{Server as A}from"net";import S from"ws";import _ from"mime-types";import E from"multer";import{join as P}from"path";a();const O=parseInt(process.env.API_AUTH_SLEEP||"1000"),N=process.env.API_DB_DATABASE||"",R=process.env.API_DB_HOST||"127.0.0.1",q=process.env.API_DB_PASSWORD||"",j=parseInt(process.env.API_DB_PORT||"3306"),k=process.env.API_DB_TYPE||"",x=process.env.API_DB_USERNAME||"root",D=e(process.env.API_DB_LOG||"false"),B=process.env.API_HTTP_CRT||"",z=process.env.API_HTTP_KEY||"",G=parseInt(process.env.API_HTTP_PORT||"3000"),U=process.env.API_HTTP_PUBLIC||"",L=e(process.env.API_HTTP_CROSS||"false"),C=e(process.env.API_HTTP_HYBRID||"false"),H=process.env.API_TOKEN_CRT||"",K=process.env.API_TOKEN_KEY||"",M=process.env.API_TOKEN_HEADER||"authorization",F=parseInt(process.env.API_TOKEN_LIFETIME||"15"),W=parseInt(process.env.API_UPLOAD_COUNT||"1"),X=process.env.API_UPLOAD_FIELD||"upload",Y=parseInt(process.env.API_UPLOAD_SIZE||"2"),$=process.env.API_UPLOAD_TEMP||"./temp",J=e(process.env.API_WEBSOCKET_START||"false");function V(e,t,r,s){return new(r||(r=Promise))((function(o,n){function i(e){try{d(s.next(e))}catch(e){n(e)}}function a(e){try{d(s.throw(e))}catch(e){n(e)}}function d(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,a)}d((s=s.apply(e,t||[])).next())}))}const Z={type:u,defaultValue:c,allowNull:!1,primaryKey:!0},Q=(()=>{switch(k){case"mariadb":return new d(N,x,q,{host:R,port:j,dialect:"mariadb",logging:D,define:{timestamps:!1}});case"mysql":return new d(N,x,q,{host:R,port:j,dialect:"mysql",logging:D,define:{timestamps:!1}});case"postgres":return new d(N,x,q,{host:R,port:j,dialect:"postgres",logging:D,define:{timestamps:!1}})}throw new Error("No database selected")})();class ee extends m{}ee.init({login:l.BIGINT,logout:l.BIGINT,secret:l.STRING,timestamp:l.BIGINT,useragent:l.STRING},{sequelize:Q,modelName:"auth"});class te extends m{}te.init({name:l.STRING,description:l.TEXT,state:l.BOOLEAN},{sequelize:Q,modelName:"group"});class re extends m{}re.init({type:l.STRING,source:l.STRING,message:l.TEXT},{sequelize:Q,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class se extends m{}se.init({name:l.STRING,description:l.TEXT,state:l.BOOLEAN},{sequelize:Q,modelName:"route"});class oe extends m{}oe.init({},{sequelize:Q,modelName:"groups_routes"}),oe.removeAttribute("id");class ne extends m{}ne.init({name:l.STRING,email:l.STRING,username:l.STRING,password:l.STRING,description:l.TEXT,state:l.BOOLEAN},{sequelize:Q,modelName:"user"});class ie extends m{}ie.init({},{sequelize:Q,modelName:"users_groups"}),ie.removeAttribute("id"),ne.hasMany(ee),ee.belongsTo(ne),te.hasMany(oe),oe.belongsTo(te),se.hasMany(oe),oe.belongsTo(se),ne.hasMany(ie),ie.belongsTo(ne),te.hasMany(ie),ie.belongsTo(te);var ae;!function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(ae||(ae={}));class de{static write(e,t){de.writeRaw(ae.NONE,"",e,t)}static error(e,t){de.writeRaw(ae.ERROR,"error",e,t)}static info(e,t){de.writeRaw(ae.INFO,"info",e,t)}static success(e,t){de.writeRaw(ae.ERROR,"success",e,t)}static warning(e,t){de.writeRaw(ae.WARNING,"warning",e,t)}static writeConsole(e,t,s){const o=r(new Date,"%H:%M:%S");console.log(">",e,t+" ".repeat(10-t.length),"","|",o,"|",s)}static writeRaw(e,t,r,s){de.writeConsole(e,t,r),re.create({type:t,source:s,message:r}).catch((()=>null))}}class ue{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}const ce=e=>{if(f(e))return h(e)},le={http:ce(B),token:ce(H)},me={http:ce(z),token:ce(K)};class pe{static all(e,t){return V(this,void 0,void 0,(function*(){return yield se.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:oe,required:!0,include:[{model:te,required:!0,where:{state:!0},include:[{model:ie,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{de.error(e.message,"permission")}))}))}static get(e){return V(this,void 0,void 0,(function*(){const t=yield pe.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return V(this,void 0,void 0,(function*(){const r=yield pe.all(e,{name:t});return r&&!!r.length}))}}const ge=["id","name","email","username"],ve=(e,t,r)=>V(void 0,void 0,void 0,(function*(){const s=e.get(M)||"";if(!le.token)return ue.error(t,"Invalid Secret");if(!s||s.split(".").length<3)return ue.error(t,"Invalid token");const o=w.verify(s,le.token);if(o&&o.id&&o.secret){const s=yield ne.findOne({where:{id:o.id}}).catch((e=>{de.error(e.message,"token.check")}));if(s&&s.state){const n=yield ee.findOne({where:{logout:null,secret:o.secret,userId:s.id}}).catch((e=>{de.error(e.message,"token.check")}));if(n){const o=Date.now();if(o>n.timestamp)return ue.error(t,"Expired token");n.timestamp=o+6e4*F;const i=e.get("User-Agent");return i&&(n.useragent=i),yield n.save(),e.auth=n,e.user=s,r()}}return ue.error(t,"Access denied")}return ue.error(t,"Invalid token")})),fe=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),ue.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},he={username:I.string().min(5).required(),password:I.string().min(5).required()},ye=fe(I.object(he)),we=v();we.get("/",ve,((e,t)=>V(void 0,void 0,void 0,(function*(){const r=e.user;if(!r)return ue.unauthorized(t,"Access denied");const s=yield pe.all(r);if(s){const e=n(ge,r.toJSON()),o=s.map((e=>e.name));return ue.data(t,Object.assign(Object.assign({},e),{permissions:o}))}return ue.error(t,"Internal Server Error")})))),we.post("/login",ye,((e,t)=>V(void 0,void 0,void 0,(function*(){const{username:r,password:n}=e.body;if(!r||!n)return ue.error(t,"Invalid parameters");yield s(O);const i=yield ne.findOne({where:{username:r}}).catch((e=>{de.error(e.message,"auth.login")}));if(!i)return ue.notfound(t,"User not found");if(!i.state)return ue.error(t,"User is disabled");const a=y(n).toString();if(i.password!=a)return ue.error(t,"Invalid password");if(!me.token)return ue.error(t,"Invalid Secret");const d=i.id,u=o(),c=w.sign({id:d,secret:u},me.token,{algorithm:"RS256"});if(c){const r=Date.now(),s=r+6e4*F,o=e.get("User-Agent");if(yield ee.create({login:r,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{de.error(e.message,"auth.login")})))return ue.data(t,{token:c})}return ue.error(t,"Internal Server Error")})))),we.get("/logout",ve,((e,t)=>V(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),ue.success(t,"Disconcerted")):ue.unauthorized(t,"Access denied")}))));class Ie{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>V(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{de.error(e.message,this.log+".add")}));return r?ue.data(t,{id:r.id}):ue.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>V(this,void 0,void 0,(function*(){var o,n;e||(e={});const i=null===(o=r.query.limit)||void 0===o?void 0:o.toString();i&&(e.limit=parseInt(i));const a=null===(n=r.query.offset)||void 0===n?void 0:n.toString();a&&(e.offset=parseInt(a));const d=yield this.model.findAll(e).catch((e=>{de.error(e.message,this.log+".all")})),u=yield this.model.count().catch((e=>{de.error(e.message,this.log+".all")}));return d?ue.data(s,{count:u,records:t?t(d):d}):ue.error(s,"Internal Server Error")}))}del(){return(e,t)=>V(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{de.error(e.message,this.log+".del")})))?ue.success(t,"OK"):ue.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>V(this,void 0,void 0,(function*(){e||(e={});const{id:o}=r.params,n=yield this.model.findByPk(o,e).catch((e=>{de.error(e.message,this.log+".get")}));return n?ue.data(s,t?t(n):n.toJSON()):null===n?ue.notfound(s,"Record not found"):ue.error(s,"Internal Server Error")}))}set(){return(e,t)=>V(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{de.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return ue.success(t,"OK")}return ue.success(t,"Record not changed")}))}}const be=new Ie("groups",te),Te=be.add(),Ae=be.all(),Se=be.del(),_e=be.get(),Ee=be.set(),Pe=e=>(t,r,s)=>V(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield pe.is(o,e))?s():ue.error(r,"Unauthorized access"):ue.unauthorized(r,"Access denied")})),Oe={name:I.string().min(3).required(),description:I.string().allow(null,""),state:I.boolean().required()},Ne=fe(I.object(Oe)),Re={routes:I.array().items(I.number())},qe=fe(I.object(Re)),je={name:I.string().min(3).empty(""),description:I.string().allow(null,""),state:I.boolean().empty("")},ke=fe(I.object(je)),xe=v();xe.use(ve),xe.get("/",Pe("groups.read"),Ae),xe.post("/",Pe("groups.write"),Ne,Te),xe.route("/:id").get(Pe("groups.read"),_e).put(Pe("groups.write"),ke,Ee).delete(Pe("groups.write"),Se),xe.route("/:id/routes").get(Pe("groups.read"),qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,s=yield oe.findAll({where:{groupId:r},include:[{model:se,required:!0}]}).catch((e=>{de.error(e.message,"groups.routesAll")}));return s?ue.list(t,s.map((e=>e.route))):ue.error(t,"Internal Server Error")})))).put(Pe("groups.write"),qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield te.findByPk(r,{attributes:["id"]}).catch((e=>{de.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield oe.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield se.count({where:{id:s[r]}}),t&&(yield oe.create({groupId:e,routeId:s[r]}))}return ue.success(t,"OK")}return null===o?ue.notfound(t,"Record not found"):ue.error(t,"Internal Server Error")}))));const De=new Ie("route",se),Be=De.add(),ze=De.all(),Ge=De.del(),Ue=De.get(),Le=De.set(),Ce={name:I.string().min(5).required(),permission:I.string().required(),description:I.string().allow(null,""),state:I.boolean().required()},He=fe(I.object(Ce)),Ke={name:I.string().min(5).empty(""),permission:I.string().empty(""),description:I.string().allow(null,""),state:I.boolean().empty("")},Me=fe(I.object(Ke)),Fe=v();Fe.use(ve),Fe.get("/",Pe("routes.read"),ze),Fe.post("/",Pe("routes.write"),He,Be),Fe.route("/:id").get(Pe("routes.read"),Ue).put(Pe("routes.write"),Me,Le).delete(Pe("routes.write"),Ge);const We=new Ie("user",ne),Xe=new Ie("user.groups",ie),Ye=["id","name","email","username","description","state"],$e=We.del(),Je={name:I.string().min(5).required(),email:I.string().email().required(),username:I.string().min(5).required(),password:I.string().min(5).required(),description:I.string().allow(null,""),state:I.boolean().required()},Ve=fe(I.object(Je)),Ze={groups:I.array().items(I.number())},Qe=fe(I.object(Ze)),et={name:I.string().min(5).empty(""),email:I.string().email().empty(""),username:I.string().min(5).empty(""),password:I.string().min(5).empty(""),description:I.string().allow(null,""),state:I.boolean().empty("")},tt=fe(I.object(et)),rt=v();rt.use(ve),rt.get("/",Pe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){return We.all({attributes:Ye})(e,t)})))),rt.post("/",Pe("users.write"),Ve,((e,t)=>V(void 0,void 0,void 0,(function*(){return e.body.password=y(e.body.password).toString(),yield We.add()(e,t)})))),rt.route("/:id").get(Pe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){return We.get({attributes:Ye})(e,t)})))).put(Pe("users.write"),tt,((e,t)=>V(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=y(e.body.password).toString()),We.set()(e,t)})))).delete(Pe("users.write"),$e),rt.route("/:id/groups").get(Pe("users.read"),((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Xe.all({where:{userId:r},include:[{model:te,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Pe("users.write"),Qe,((e,t)=>V(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield ne.findByPk(r,{attributes:["id"]}).catch((e=>{de.error(e.message,"user.groups.set")}));if(o){if(yield ie.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield te.count({where:{id:s[t]}}),e&&(yield ie.create({userId:o.id,groupId:s[t]}))}return ue.success(t,"OK")}return ue.notfound(t,"Record not found")}))));const st=v();st.use("/v1/auth",we),st.use("/v1/groups",xe),st.use("/v1/routes",Fe),st.use("/v1/users",rt);const ot=g();ot.use(g.json()),ot.use(((e,t,r,s)=>e?(de.error(e.message,"express"),ue.error(r,"Internal Server Error")):s())),ot.use(g.urlencoded({extended:!0})),ot.disable("x-powered-by"),L&&ot.use(p()),ot.use("/api",st),ot.all("/api/*",((e,t)=>ue.notfound(t,"Invalid API"))),U&&(f(U)&&ot.use(g.static(U)),ot.get("*",((e,t)=>{if(!f(U))return ue.notfound(t,'File "index.html" not found');t.sendFile(U+"/index.html")})));const nt=e=>{const t=new S.Server({server:e,verifyClient:it});return t.on("connection",(e=>{e.on("message",(t=>{e.close()})),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},it=(e,t)=>t(J),at=()=>{Q.sync().then((()=>{V(void 0,void 0,void 0,(function*(){if(0==(yield ne.count())){const e=yield ne.create({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",description:"",state:!0});if(0==(yield te.count())){const r=yield te.create({name:"admin",description:"",state:!0});if(yield ie.create({userId:e.id,groupId:r.id}),0==(yield se.count())){const e=["read","write"];t(["users","groups","permission"],(s=>V(void 0,void 0,void 0,(function*(){t(e,(e=>V(void 0,void 0,void 0,(function*(){const t=s.toLowerCase()+"."+e.toLowerCase(),o=yield se.create({name:t,description:"",state:!0});yield oe.create({groupId:r.id,routeId:o.id})}))))}))))}}}})),J&&nt(dt)}))},dt=(e=>{if(!le.http||!me.http){const t=b.createServer(e);return t.listen(G,(()=>de.info(`Server started on port ${G}`))),t}const t=b.createServer(((e,t)=>{const r=80==G?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=T.createServer({key:me.http,cert:le.http},e);if(C){return new A((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(G,(()=>de.info(`Server started on port ${G}`))),r}return 443==G&&t.listen(80,(()=>de.info("Server started on port 80"))),r.listen(G,(()=>de.info(`Server started on port ${G}`))),r})(ot),ut=(e,t)=>{const r=i()+"."+t;return f(P(e,r))?ut(e,t):r},ct=e=>{const t=(null==e?void 0:e.path)||$,r=E.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>V(void 0,void 0,void 0,(function*(){return s(null,ut(t,_.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||Y),o=E({storage:r,fileFilter(t,r,s){var o;return V(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.indexOf(r.mimetype);return void 0!==t&&t<0?s(new Error("File type not allowed")):s(null,!0)}))},limits:{fileSize:s}}),n=(null==e?void 0:e.count)||W,i=(null==e?void 0:e.field)||X,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?ue.error(t,e.message):r()}))}};export{O as API_AUTH_SLEEP,N as API_DB_DATABASE,R as API_DB_HOST,D as API_DB_LOG,q as API_DB_PASSWORD,j as API_DB_PORT,k as API_DB_TYPE,x as API_DB_USERNAME,L as API_HTTP_CROSS,B as API_HTTP_CRT,C as API_HTTP_HYBRID,z as API_HTTP_KEY,G as API_HTTP_PORT,U as API_HTTP_PUBLIC,H as API_TOKEN_CRT,M as API_TOKEN_HEADER,K as API_TOKEN_KEY,F as API_TOKEN_LIFETIME,W as API_UPLOAD_COUNT,X as API_UPLOAD_FIELD,Y as API_UPLOAD_SIZE,$ as API_UPLOAD_TEMP,J as API_WEBSOCKET_START,ee as Auth,Ie as Controller,te as Group,oe as GroupRoute,de as Log,re as Logs,pe as Permission,ue as Responses,se as Route,ne as User,ie as UserGroup,ot as app,ve as auth,le as crt,at as initialize,me as key,Pe as permission,st as router,Q as sequelize,dt as server,nt as startSocket,ct as upload,Z as uuid,fe as validation};
6
+ import{toBool as e,forEachSeries as t,dateFormat as r,isUndefined as s,noop as o,sleep as n,uniqueID as i,allowedObject as d,uuidv4 as a}from"@andrewcaires/utils.js";import{config as u}from"dotenv";import{Sequelize as c,UUID as l,UUIDV4 as m,DataTypes as p,Model as g,Op as v}from"sequelize";import f from"cors";import h,{Router as y}from"express";import{existsSync as w,readFileSync as I}from"fs";import{SHA256 as b}from"crypto-js";import{sign as S,verify as T}from"jsonwebtoken";import A from"mime-types";import O from"multer";import{join as E}from"path";import _ from"joi";import*as P from"http";import*as N from"https";import{Server as R}from"net";import j from"ws";u();const q=parseInt(process.env.API_AUTH_SLEEP||"1000"),k=process.env.API_DB_DATABASE||"",D=process.env.API_DB_HOST||"127.0.0.1",x=process.env.API_DB_PASSWORD||"",B=parseInt(process.env.API_DB_PORT||"3306"),z=process.env.API_DB_TYPE||"",G=process.env.API_DB_USERNAME||"root",U=e(process.env.API_DB_LOG||"false"),C=process.env.API_HTTP_CRT||"",L=process.env.API_HTTP_KEY||"",H=parseInt(process.env.API_HTTP_PORT||"3000"),K=process.env.API_HTTP_PUBLIC||"",M=e(process.env.API_HTTP_CROSS||"false"),F=e(process.env.API_HTTP_HYBRID||"false"),W=process.env.API_TOKEN_CRT||"",X=process.env.API_TOKEN_KEY||"",Y=process.env.API_TOKEN_HEADER||"authorization",$=parseInt(process.env.API_TOKEN_LIFETIME||"15"),J=parseInt(process.env.API_UPLOAD_COUNT||"1"),V=process.env.API_UPLOAD_FIELD||"upload",Z=parseInt(process.env.API_UPLOAD_SIZE||"2"),Q=process.env.API_UPLOAD_TEMP||"./temp",ee=e(process.env.API_WEBSOCKET_START||"false");function te(e,t,r,s){return new(r||(r=Promise))((function(o,n){function i(e){try{a(s.next(e))}catch(e){n(e)}}function d(e){try{a(s.throw(e))}catch(e){n(e)}}function a(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,d)}a((s=s.apply(e,t||[])).next())}))}const re={type:l,defaultValue:m,allowNull:!1,primaryKey:!0},se=(()=>{switch(z){case"mariadb":return new c(k,G,x,{host:D,port:B,dialect:"mariadb",logging:U,define:{timestamps:!1}});case"mysql":return new c(k,G,x,{host:D,port:B,dialect:"mysql",logging:U,define:{timestamps:!1}});case"postgres":return new c(k,G,x,{host:D,port:B,dialect:"postgres",logging:U,define:{timestamps:!1}})}throw new Error("No database selected")})();class oe extends g{}oe.init({login:p.BIGINT,logout:p.BIGINT,secret:p.STRING,timestamp:p.BIGINT,useragent:p.STRING},{sequelize:se,modelName:"auth"});class ne extends g{}ne.init({name:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:se,modelName:"group"});class ie extends g{}ie.init({type:p.STRING,source:p.STRING,message:p.TEXT},{sequelize:se,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class de extends g{}de.init({name:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:se,modelName:"route"});class ae extends g{}ae.init({},{sequelize:se,modelName:"groups_routes"}),ae.removeAttribute("id");class ue extends g{}ue.init({name:p.STRING,email:p.STRING,username:p.STRING,password:p.STRING,description:p.TEXT,state:p.BOOLEAN},{sequelize:se,modelName:"user"});class ce extends g{}ce.init({},{sequelize:se,modelName:"users_groups"}),ce.removeAttribute("id"),ue.hasMany(oe),oe.belongsTo(ue),ne.hasMany(ae),ae.belongsTo(ne),de.hasMany(ae),ae.belongsTo(de),ue.hasMany(ce),ce.belongsTo(ue),ne.hasMany(ce),ce.belongsTo(ne);var le;!function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(le||(le={}));class me{static write(e,t,r){me.writeRaw(le.NONE,"",e,t,r)}static error(e,t,r){me.writeRaw(le.ERROR,"error",e,t,r)}static info(e,t,r){me.writeRaw(le.INFO,"info",e,t,r)}static success(e,t,r){me.writeRaw(le.ERROR,"success",e,t,r)}static warning(e,t,r){me.writeRaw(le.WARNING,"warning",e,t,r)}static writeConsole(e,t,s){const o=r(new Date,"%H:%M:%S");console.log(">",e,t+" ".repeat(10-t.length),"","|",o,"|",s)}static writeRaw(e,t,r,o,n){(n=!!s(n)||n)&&me.writeConsole(e,t,r),ie.create({type:t,source:o,message:r}).catch((()=>null))}}class pe{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}class ge{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>te(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{me.error(e.message,this.log+".add")}));return r?pe.data(t,{id:r.id}):pe.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>te(this,void 0,void 0,(function*(){var n,i,d,a,u;e||(e={});const c=Object.assign({},e);c.where=c.where?Object.assign({},c.where):{};const l=null===(n=r.query.limit)||void 0===n?void 0:n.toString();l&&(c.limit=parseInt(l));const m=null===(i=r.query.offset)||void 0===i?void 0:i.toString();m&&(c.offset=parseInt(m));const p=null===(d=r.query.asc)||void 0===d?void 0:d.toString();p&&(c.order=[[p,"ASC"]]);const g=null===(a=r.query.desc)||void 0===a?void 0:a.toString();g&&(c.order=[[g,"DESC"]]);const f=[],h=null===(u=r.query.search)||void 0===u?void 0:u.toString();h&&(Object.keys(this.model.getAttributes()).forEach((e=>{"password"!=e&&f.push({[e]:{[v.like]:`%${h}%`}})})),f.length&&(c.where=Object.assign(Object.assign({},c.where),{[v.or]:[...f]})));const y=yield this.model.findAll(c).catch((e=>{me.error(e.message,this.log+".all")})),w=yield this.model.count(c).catch(o);return y?pe.data(s,{count:w,records:t?t(y):y}):pe.error(s,"Internal Server Error")}))}del(){return(e,t)=>te(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{me.error(e.message,this.log+".del")})))?pe.success(t,"OK"):pe.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>te(this,void 0,void 0,(function*(){e||(e={});const o=Object.assign({},e);o.where=o.where?Object.assign({},o.where):{};const{id:n}=r.params,i=yield this.model.findByPk(n,o).catch((e=>{me.error(e.message,this.log+".get")}));return i?pe.data(s,t?t(i):i.toJSON()):null===i?pe.notfound(s,"Record not found"):pe.error(s,"Internal Server Error")}))}set(){return(e,t)=>te(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{me.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return pe.success(t,"OK")}return pe.success(t,"Record not changed")}))}}class ve{static all(e,t){return te(this,void 0,void 0,(function*(){return yield de.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:ae,required:!0,include:[{model:ne,required:!0,where:{state:!0},include:[{model:ce,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{me.error(e.message,"permission")}))}))}static get(e){return te(this,void 0,void 0,(function*(){const t=yield ve.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return te(this,void 0,void 0,(function*(){const r=yield ve.all(e,{name:t});return r&&!!r.length}))}}const fe=e=>{if(w(e))return I(e)},he={http:fe(C),token:fe(W)},ye={http:fe(L),token:fe(X)};class we{static sign(e){return ye.token?{token:S(e,ye.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static verify(e){if(!he.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:T(e,he.token)}}catch(e){return{error:"Invalid Token"}}}}const Ie=["id","name","email","username"],be=(e,t,r)=>te(void 0,void 0,void 0,(function*(){const s=e.get(Y)||"",{error:o,decode:n}=we.verify(s);if(o)return pe.error(t,o);if(n){const{id:s,secret:o}=n;if(s&&n){const n=yield ue.findOne({where:{id:s,state:!0}}).catch((e=>{me.error(e.message,"token.check")}));if(n){const s=yield oe.findOne({where:{secret:o,userId:n.id}}).catch((e=>{me.error(e.message,"token.check")}));if(s){const o=Date.now();if(o>s.timestamp)return pe.error(t,"Expired token");s.timestamp=o+6e4*$;const i=e.get("User-Agent");return i&&(s.useragent=i),yield s.save(),e.auth=s,e.user=n,r()}}return pe.error(t,"Access denied")}}return pe.error(t,"Invalid token")})),Se=e=>(t,r,s)=>te(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield ve.is(o,e))?s():pe.error(r,"Unauthorized access"):pe.unauthorized(r,"Access denied")})),Te=(e,t)=>{const r=a()+"."+t;return w(E(e,r))?Te(e,t):r},Ae=e=>{const t=(null==e?void 0:e.path)||Q,r=O.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>te(void 0,void 0,void 0,(function*(){return s(null,Te(t,A.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||Z),o=O({storage:r,fileFilter(t,r,s){var o;return te(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.indexOf(r.mimetype);return void 0!==t&&t<0?s(new Error("File type not allowed")):s(null,!0)}))},limits:{fileSize:s}}),n=(null==e?void 0:e.count)||J,i=(null==e?void 0:e.field)||V,d=o.array(i,n);return(e,t,r)=>{d(e,t,(function(e){return e?pe.error(t,e.message):r()}))}},Oe=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),pe.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},Ee={username:_.string().min(5).required(),password:_.string().min(5).required()},_e=Oe(_.object(Ee)),Pe=y();Pe.get("/",be,((e,t)=>te(void 0,void 0,void 0,(function*(){const r=e.user;if(!r)return pe.unauthorized(t,"Access denied");const s=yield ve.all(r);if(s){const e=d(Ie,r.toJSON()),o=s.map((e=>e.name));return pe.data(t,Object.assign(Object.assign({},e),{permissions:o}))}return pe.error(t,"Internal Server Error")})))),Pe.post("/login",_e,((e,t)=>te(void 0,void 0,void 0,(function*(){const{username:r,password:s}=e.body;if(!r||!s)return pe.error(t,"Invalid parameters");yield n(q);const o=yield ue.findOne({where:{username:r}}).catch((e=>{me.error(e.message,"auth.login")}));if(!o)return pe.notfound(t,"Username not found");if(!o.state)return pe.error(t,"Username is disabled");const d=b(s).toString();if(o.password!=d)return pe.error(t,"Invalid password");const a=o.id,u=i(),{error:c,token:l}=we.sign({id:a,secret:u});if(c)return pe.error(t,c);if(l){const r=Date.now(),s=r+6e4*$,o=e.get("User-Agent"),n=yield oe.create({login:r,secret:u,timestamp:s,useragent:o,userId:a}).catch((e=>{me.error(e.message,"auth.login")}));if(n)return pe.data(t,{token:l})}return pe.error(t,"Internal Server Error")})))),Pe.get("/logout",be,((e,t)=>te(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),pe.success(t,"Disconcerted")):pe.unauthorized(t,"Access denied")}))));const Ne=new ge("groups",ne),Re=new ge("groups.route",ae),je=Ne.add(),qe=Ne.all(),ke=Ne.del(),De=Ne.get(),xe=Ne.set(),Be={name:_.string().min(3).required(),description:_.string().allow(null,""),state:_.boolean().required()},ze=Oe(_.object(Be)),Ge={routes:_.array().items(_.number())},Ue=Oe(_.object(Ge)),Ce={name:_.string().min(3).empty(""),description:_.string().allow(null,""),state:_.boolean().empty("")},Le=Oe(_.object(Ce)),He=y();He.use(be),He.get("/",Se("groups.read"),qe),He.post("/",Se("groups.write"),ze,je),He.route("/:id").get(Se("groups.read"),De).put(Se("groups.write"),Le,xe).delete(Se("groups.write"),ke),He.route("/:id/routes").get(Se("groups.read"),Ue,((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Re.all({where:{groupId:r},include:[{model:de,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(Se("groups.write"),Ue,((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield ne.findByPk(r,{attributes:["id"]}).catch((e=>{me.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield ae.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield de.count({where:{id:s[r]}}),t&&(yield ae.create({groupId:e,routeId:s[r]}))}return pe.success(t,"OK")}return null===o?pe.notfound(t,"Record not found"):pe.error(t,"Internal Server Error")}))));const Ke=new ge("logs",ie),Me=y();Me.use(be),Me.get("/",Se("logs.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){const{source:r,type:s}=e.query,o=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return Ke.all({where:o,order:[["created","DESC"]]})(e,t)}))));const Fe=new ge("route",de),We=Fe.add(),Xe=Fe.all(),Ye=Fe.del(),$e=Fe.get(),Je=Fe.set(),Ve={name:_.string().min(5).required(),description:_.string().allow(null,""),state:_.boolean().required()},Ze=Oe(_.object(Ve)),Qe={name:_.string().min(5).empty(""),description:_.string().allow(null,""),state:_.boolean().empty("")},et=Oe(_.object(Qe)),tt=y();tt.use(be),tt.get("/",Se("routes.read"),Xe),tt.post("/",Se("routes.write"),Ze,We),tt.route("/:id").get(Se("routes.read"),$e).put(Se("routes.write"),et,Je).delete(Se("routes.write"),Ye);const rt=new ge("user",ue),st=new ge("user.groups",ce),ot=["id","name","email","username","description","state"],nt=rt.del(),it={name:_.string().min(5).required(),email:_.string().email().required(),username:_.string().min(5).required(),password:_.string().min(5).required(),description:_.string().allow(null,""),state:_.boolean().required()},dt=Oe(_.object(it)),at={groups:_.array().items(_.number())},ut=Oe(_.object(at)),ct={name:_.string().min(5).empty(""),email:_.string().email().empty(""),username:_.string().min(5).empty(""),password:_.string().min(5).empty(""),description:_.string().allow(null,""),state:_.boolean().empty("")},lt=Oe(_.object(ct)),mt=y();mt.use(be),mt.get("/",Se("users.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){return rt.all({attributes:ot})(e,t)})))),mt.post("/",Se("users.write"),dt,((e,t)=>te(void 0,void 0,void 0,(function*(){return e.body.password=b(e.body.password).toString(),yield rt.add()(e,t)})))),mt.route("/:id").get(Se("users.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){return rt.get({attributes:ot})(e,t)})))).put(Se("users.write"),lt,((e,t)=>te(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=b(e.body.password).toString()),rt.set()(e,t)})))).delete(Se("users.write"),nt),mt.route("/:id/groups").get(Se("users.read"),((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return st.all({where:{userId:r},include:[{model:ne,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(Se("users.write"),ut,((e,t)=>te(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield ue.findByPk(r,{attributes:["id"]}).catch((e=>{me.error(e.message,"user.groups.set")}));if(o){if(yield ce.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield ne.count({where:{id:s[t]}}),e&&(yield ce.create({userId:o.id,groupId:s[t]}))}return pe.success(t,"OK")}return pe.notfound(t,"Record not found")}))));const pt=y();pt.use("/auth",Pe),pt.use("/groups",He),pt.use("/logs",Me),pt.use("/routes",tt),pt.use("/users",mt);const gt=h();gt.use(h.json()),gt.use(((e,t,r,s)=>e?(me.error(e.message,"express"),pe.error(r,"Internal Server Error")):s())),gt.use(h.urlencoded({extended:!0})),gt.disable("x-powered-by"),M&&gt.use(f());const vt=y();gt.use("/api",vt),gt.use("/api",pt),gt.all("/api/*",((e,t)=>pe.notfound(t,"Invalid API"))),K&&(w(K)&&gt.use(h.static(K)),gt.get("*",((e,t)=>{if(!w(K))return pe.notfound(t,'File "index.html" not found');t.sendFile(K+"/index.html")})));const ft=e=>{const t=new j.Server({server:e,verifyClient:ht});return t.on("connection",(e=>{e.on("message",(t=>te(void 0,void 0,void 0,(function*(){we.verify(t.toString()),e.close()})))),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},ht=(e,t)=>t(ee),yt=()=>{se.sync().then((()=>{te(void 0,void 0,void 0,(function*(){if(0==(yield ue.count())){const e={description:"",state:!0},r=yield ue.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"},e));if(0==(yield ne.count())){const s=yield ne.create(Object.assign({name:"admin"},e));if(yield ce.create({userId:r.id,groupId:s.id}),0==(yield de.count())){const r=["read","write"],o=["users","groups","permission"];yield t(o,(o=>te(void 0,void 0,void 0,(function*(){yield t(r,(t=>te(void 0,void 0,void 0,(function*(){const r=o+"."+t,n=yield de.create(Object.assign({name:r},e));yield ae.create({groupId:s.id,routeId:n.id})}))))}))));const n=yield de.create(Object.assign({name:"logs.read"},e));yield ae.create({groupId:s.id,routeId:n.id})}}}})),ee&&ft(wt)}))},wt=(e=>{if(!he.http||!ye.http){const t=P.createServer(e);return t.listen(H,(()=>me.info(`Server started on port ${H}`))),t}const t=P.createServer(((e,t)=>{const r=80==H?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=N.createServer({key:ye.http,cert:he.http},e);if(F){return new R((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(H,(()=>me.info(`Server started on port ${H}`))),r}return 443==H&&t.listen(80,(()=>me.info("Server started on port 80"))),r.listen(H,(()=>me.info(`Server started on port ${H}`))),r})(gt);export{q as API_AUTH_SLEEP,k as API_DB_DATABASE,D as API_DB_HOST,U as API_DB_LOG,x as API_DB_PASSWORD,B as API_DB_PORT,z as API_DB_TYPE,G as API_DB_USERNAME,M as API_HTTP_CROSS,C as API_HTTP_CRT,F as API_HTTP_HYBRID,L as API_HTTP_KEY,H as API_HTTP_PORT,K as API_HTTP_PUBLIC,W as API_TOKEN_CRT,Y as API_TOKEN_HEADER,X as API_TOKEN_KEY,$ as API_TOKEN_LIFETIME,J as API_UPLOAD_COUNT,V as API_UPLOAD_FIELD,Z as API_UPLOAD_SIZE,Q as API_UPLOAD_TEMP,ee as API_WEBSOCKET_START,oe as Auth,ge as Controller,ne as Group,ae as GroupRoute,me as Log,ie as Logs,ve as Permission,pe as Responses,de as Route,we as Token,ue as User,ce as UserGroup,gt as app,be as auth,he as crt,yt as initialize,ye as key,Se as permission,vt as router,se as sequelize,wt as server,ft as startSocket,Ae as upload,re as uuid,Oe as validation};
package/dist/index.umd.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * @andrewcaires/api v1.0.0
2
+ * @andrewcaires/api v1.0.3
3
3
  * (c) 2022 Andrew Caires
4
4
  * @license: MIT
5
5
  */
6
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@andrewcaires/utils.js"),t=require("dotenv"),r=require("sequelize"),s=require("cors"),o=require("express"),n=require("fs"),i=require("crypto-js"),a=require("jsonwebtoken"),d=require("joi"),u=require("http"),l=require("https"),c=require("net"),p=require("ws"),f=require("mime-types"),m=require("multer"),g=require("path");function v(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function y(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var I=v(s),h=v(o),T=v(a),_=v(d),w=y(u),A=y(l),P=v(p),S=v(f),x=v(m);t.config();const E=parseInt(process.env.API_AUTH_SLEEP||"1000"),b=process.env.API_DB_DATABASE||"",O=process.env.API_DB_HOST||"127.0.0.1",D=process.env.API_DB_PASSWORD||"",R=parseInt(process.env.API_DB_PORT||"3306"),q=process.env.API_DB_TYPE||"",N=process.env.API_DB_USERNAME||"root",j=e.toBool(process.env.API_DB_LOG||"false"),B=process.env.API_HTTP_CRT||"",U=process.env.API_HTTP_KEY||"",k=parseInt(process.env.API_HTTP_PORT||"3000"),L=process.env.API_HTTP_PUBLIC||"",H=e.toBool(process.env.API_HTTP_CROSS||"false"),z=e.toBool(process.env.API_HTTP_HYBRID||"false"),M=process.env.API_TOKEN_CRT||"",C=process.env.API_TOKEN_KEY||"",G=process.env.API_TOKEN_HEADER||"authorization",K=parseInt(process.env.API_TOKEN_LIFETIME||"15"),F=parseInt(process.env.API_UPLOAD_COUNT||"1"),Y=process.env.API_UPLOAD_FIELD||"upload",W=parseInt(process.env.API_UPLOAD_SIZE||"2"),X=process.env.API_UPLOAD_TEMP||"./temp",V=e.toBool(process.env.API_WEBSOCKET_START||"false");function $(e,t,r,s){return new(r||(r=Promise))((function(o,n){function i(e){try{d(s.next(e))}catch(e){n(e)}}function a(e){try{d(s.throw(e))}catch(e){n(e)}}function d(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,a)}d((s=s.apply(e,t||[])).next())}))}const J={type:r.UUID,defaultValue:r.UUIDV4,allowNull:!1,primaryKey:!0},Z=(()=>{switch(q){case"mariadb":return new r.Sequelize(b,N,D,{host:O,port:R,dialect:"mariadb",logging:j,define:{timestamps:!1}});case"mysql":return new r.Sequelize(b,N,D,{host:O,port:R,dialect:"mysql",logging:j,define:{timestamps:!1}});case"postgres":return new r.Sequelize(b,N,D,{host:O,port:R,dialect:"postgres",logging:j,define:{timestamps:!1}})}throw new Error("No database selected")})();class Q extends r.Model{}Q.init({login:r.DataTypes.BIGINT,logout:r.DataTypes.BIGINT,secret:r.DataTypes.STRING,timestamp:r.DataTypes.BIGINT,useragent:r.DataTypes.STRING},{sequelize:Z,modelName:"auth"});class ee extends r.Model{}ee.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"group"});class te extends r.Model{}te.init({type:r.DataTypes.STRING,source:r.DataTypes.STRING,message:r.DataTypes.TEXT},{sequelize:Z,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class re extends r.Model{}re.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"route"});class se extends r.Model{}se.init({},{sequelize:Z,modelName:"groups_routes"}),se.removeAttribute("id");class oe extends r.Model{}oe.init({name:r.DataTypes.STRING,email:r.DataTypes.STRING,username:r.DataTypes.STRING,password:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:Z,modelName:"user"});class ne extends r.Model{}ne.init({},{sequelize:Z,modelName:"users_groups"}),ne.removeAttribute("id"),oe.hasMany(Q),Q.belongsTo(oe),ee.hasMany(se),se.belongsTo(ee),re.hasMany(se),se.belongsTo(re),oe.hasMany(ne),ne.belongsTo(oe),ee.hasMany(ne),ne.belongsTo(ee);var ie;!function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(ie||(ie={}));class ae{static write(e,t){ae.writeRaw(ie.NONE,"",e,t)}static error(e,t){ae.writeRaw(ie.ERROR,"error",e,t)}static info(e,t){ae.writeRaw(ie.INFO,"info",e,t)}static success(e,t){ae.writeRaw(ie.ERROR,"success",e,t)}static warning(e,t){ae.writeRaw(ie.WARNING,"warning",e,t)}static writeConsole(t,r,s){const o=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"","|",o,"|",s)}static writeRaw(e,t,r,s){ae.writeConsole(e,t,r),te.create({type:t,source:s,message:r}).catch((()=>null))}}class de{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}const ue=e=>{if(n.existsSync(e))return n.readFileSync(e)},le={http:ue(B),token:ue(M)},ce={http:ue(U),token:ue(C)};class pe{static all(e,t){return $(this,void 0,void 0,(function*(){return yield re.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:se,required:!0,include:[{model:ee,required:!0,where:{state:!0},include:[{model:ne,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ae.error(e.message,"permission")}))}))}static get(e){return $(this,void 0,void 0,(function*(){const t=yield pe.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return $(this,void 0,void 0,(function*(){const r=yield pe.all(e,{name:t});return r&&!!r.length}))}}const fe=["id","name","email","username"],me=(e,t,r)=>$(void 0,void 0,void 0,(function*(){const s=e.get(G)||"";if(!le.token)return de.error(t,"Invalid Secret");if(!s||s.split(".").length<3)return de.error(t,"Invalid token");const o=T.default.verify(s,le.token);if(o&&o.id&&o.secret){const s=yield oe.findOne({where:{id:o.id}}).catch((e=>{ae.error(e.message,"token.check")}));if(s&&s.state){const n=yield Q.findOne({where:{logout:null,secret:o.secret,userId:s.id}}).catch((e=>{ae.error(e.message,"token.check")}));if(n){const o=Date.now();if(o>n.timestamp)return de.error(t,"Expired token");n.timestamp=o+6e4*K;const i=e.get("User-Agent");return i&&(n.useragent=i),yield n.save(),e.auth=n,e.user=s,r()}}return de.error(t,"Access denied")}return de.error(t,"Invalid token")})),ge=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),de.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},ve={username:_.default.string().min(5).required(),password:_.default.string().min(5).required()},ye=ge(_.default.object(ve)),Ie=o.Router();Ie.get("/",me,((t,r)=>$(void 0,void 0,void 0,(function*(){const s=t.user;if(!s)return de.unauthorized(r,"Access denied");const o=yield pe.all(s);if(o){const t=e.allowedObject(fe,s.toJSON()),n=o.map((e=>e.name));return de.data(r,Object.assign(Object.assign({},t),{permissions:n}))}return de.error(r,"Internal Server Error")})))),Ie.post("/login",ye,((t,r)=>$(void 0,void 0,void 0,(function*(){const{username:s,password:o}=t.body;if(!s||!o)return de.error(r,"Invalid parameters");yield e.sleep(E);const n=yield oe.findOne({where:{username:s}}).catch((e=>{ae.error(e.message,"auth.login")}));if(!n)return de.notfound(r,"User not found");if(!n.state)return de.error(r,"User is disabled");const a=i.SHA256(o).toString();if(n.password!=a)return de.error(r,"Invalid password");if(!ce.token)return de.error(r,"Invalid Secret");const d=n.id,u=e.uniqueID(),l=T.default.sign({id:d,secret:u},ce.token,{algorithm:"RS256"});if(l){const e=Date.now(),s=e+6e4*K,o=t.get("User-Agent");if(yield Q.create({login:e,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{ae.error(e.message,"auth.login")})))return de.data(r,{token:l})}return de.error(r,"Internal Server Error")})))),Ie.get("/logout",me,((e,t)=>$(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),de.success(t,"Disconcerted")):de.unauthorized(t,"Access denied")}))));class he{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>$(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{ae.error(e.message,this.log+".add")}));return r?de.data(t,{id:r.id}):de.error(t,"Internal Server Error")}))}all(e,t){return(r,s)=>$(this,void 0,void 0,(function*(){var o,n;e||(e={});const i=null===(o=r.query.limit)||void 0===o?void 0:o.toString();i&&(e.limit=parseInt(i));const a=null===(n=r.query.offset)||void 0===n?void 0:n.toString();a&&(e.offset=parseInt(a));const d=yield this.model.findAll(e).catch((e=>{ae.error(e.message,this.log+".all")})),u=yield this.model.count().catch((e=>{ae.error(e.message,this.log+".all")}));return d?de.data(s,{count:u,records:t?t(d):d}):de.error(s,"Internal Server Error")}))}del(){return(e,t)=>$(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{ae.error(e.message,this.log+".del")})))?de.success(t,"OK"):de.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>$(this,void 0,void 0,(function*(){e||(e={});const{id:o}=r.params,n=yield this.model.findByPk(o,e).catch((e=>{ae.error(e.message,this.log+".get")}));return n?de.data(s,t?t(n):n.toJSON()):null===n?de.notfound(s,"Record not found"):de.error(s,"Internal Server Error")}))}set(){return(e,t)=>$(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{ae.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return de.success(t,"OK")}return de.success(t,"Record not changed")}))}}const Te=new he("groups",ee),_e=Te.add(),we=Te.all(),Ae=Te.del(),Pe=Te.get(),Se=Te.set(),xe=e=>(t,r,s)=>$(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield pe.is(o,e))?s():de.error(r,"Unauthorized access"):de.unauthorized(r,"Access denied")})),Ee={name:_.default.string().min(3).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},be=ge(_.default.object(Ee)),Oe={routes:_.default.array().items(_.default.number())},De=ge(_.default.object(Oe)),Re={name:_.default.string().min(3).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},qe=ge(_.default.object(Re)),Ne=o.Router();Ne.use(me),Ne.get("/",xe("groups.read"),we),Ne.post("/",xe("groups.write"),be,_e),Ne.route("/:id").get(xe("groups.read"),Pe).put(xe("groups.write"),qe,Se).delete(xe("groups.write"),Ae),Ne.route("/:id/routes").get(xe("groups.read"),De,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,s=yield se.findAll({where:{groupId:r},include:[{model:re,required:!0}]}).catch((e=>{ae.error(e.message,"groups.routesAll")}));return s?de.list(t,s.map((e=>e.route))):de.error(t,"Internal Server Error")})))).put(xe("groups.write"),De,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield ee.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield se.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield re.count({where:{id:s[r]}}),t&&(yield se.create({groupId:e,routeId:s[r]}))}return de.success(t,"OK")}return null===o?de.notfound(t,"Record not found"):de.error(t,"Internal Server Error")}))));const je=new he("route",re),Be=je.add(),Ue=je.all(),ke=je.del(),Le=je.get(),He=je.set(),ze={name:_.default.string().min(5).required(),permission:_.default.string().required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},Me=ge(_.default.object(ze)),Ce={name:_.default.string().min(5).empty(""),permission:_.default.string().empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},Ge=ge(_.default.object(Ce)),Ke=o.Router();Ke.use(me),Ke.get("/",xe("routes.read"),Ue),Ke.post("/",xe("routes.write"),Me,Be),Ke.route("/:id").get(xe("routes.read"),Le).put(xe("routes.write"),Ge,He).delete(xe("routes.write"),ke);const Fe=new he("user",oe),Ye=new he("user.groups",ne),We=["id","name","email","username","description","state"],Xe=Fe.del(),Ve={name:_.default.string().min(5).required(),email:_.default.string().email().required(),username:_.default.string().min(5).required(),password:_.default.string().min(5).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},$e=ge(_.default.object(Ve)),Je={groups:_.default.array().items(_.default.number())},Ze=ge(_.default.object(Je)),Qe={name:_.default.string().min(5).empty(""),email:_.default.string().email().empty(""),username:_.default.string().min(5).empty(""),password:_.default.string().min(5).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},et=ge(_.default.object(Qe)),tt=o.Router();tt.use(me),tt.get("/",xe("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return Fe.all({attributes:We})(e,t)})))),tt.post("/",xe("users.write"),$e,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password=i.SHA256(e.body.password).toString(),yield Fe.add()(e,t)})))),tt.route("/:id").get(xe("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return Fe.get({attributes:We})(e,t)})))).put(xe("users.write"),et,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=i.SHA256(e.body.password).toString()),Fe.set()(e,t)})))).delete(xe("users.write"),Xe),tt.route("/:id/groups").get(xe("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ye.all({where:{userId:r},include:[{model:ee,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(xe("users.write"),Ze,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield oe.findByPk(r,{attributes:["id"]}).catch((e=>{ae.error(e.message,"user.groups.set")}));if(o){if(yield ne.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield ee.count({where:{id:s[t]}}),e&&(yield ne.create({userId:o.id,groupId:s[t]}))}return de.success(t,"OK")}return de.notfound(t,"Record not found")}))));const rt=o.Router();rt.use("/v1/auth",Ie),rt.use("/v1/groups",Ne),rt.use("/v1/routes",Ke),rt.use("/v1/users",tt);const st=h.default();st.use(h.default.json()),st.use(((e,t,r,s)=>e?(ae.error(e.message,"express"),de.error(r,"Internal Server Error")):s())),st.use(h.default.urlencoded({extended:!0})),st.disable("x-powered-by"),H&&st.use(I.default()),st.use("/api",rt),st.all("/api/*",((e,t)=>de.notfound(t,"Invalid API"))),L&&(n.existsSync(L)&&st.use(h.default.static(L)),st.get("*",((e,t)=>{if(!n.existsSync(L))return de.notfound(t,'File "index.html" not found');t.sendFile(L+"/index.html")})));const ot=e=>{const t=new P.default.Server({server:e,verifyClient:nt});return t.on("connection",(e=>{e.on("message",(t=>{e.close()})),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},nt=(e,t)=>t(V),it=(e=>{if(!le.http||!ce.http){const t=w.createServer(e);return t.listen(k,(()=>ae.info(`Server started on port ${k}`))),t}const t=w.createServer(((e,t)=>{const r=80==k?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=A.createServer({key:ce.http,cert:le.http},e);if(z){return new c.Server((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(k,(()=>ae.info(`Server started on port ${k}`))),r}return 443==k&&t.listen(80,(()=>ae.info("Server started on port 80"))),r.listen(k,(()=>ae.info(`Server started on port ${k}`))),r})(st),at=(t,r)=>{const s=e.uuidv4()+"."+r;return n.existsSync(g.join(t,s))?at(t,r):s};exports.API_AUTH_SLEEP=E,exports.API_DB_DATABASE=b,exports.API_DB_HOST=O,exports.API_DB_LOG=j,exports.API_DB_PASSWORD=D,exports.API_DB_PORT=R,exports.API_DB_TYPE=q,exports.API_DB_USERNAME=N,exports.API_HTTP_CROSS=H,exports.API_HTTP_CRT=B,exports.API_HTTP_HYBRID=z,exports.API_HTTP_KEY=U,exports.API_HTTP_PORT=k,exports.API_HTTP_PUBLIC=L,exports.API_TOKEN_CRT=M,exports.API_TOKEN_HEADER=G,exports.API_TOKEN_KEY=C,exports.API_TOKEN_LIFETIME=K,exports.API_UPLOAD_COUNT=F,exports.API_UPLOAD_FIELD=Y,exports.API_UPLOAD_SIZE=W,exports.API_UPLOAD_TEMP=X,exports.API_WEBSOCKET_START=V,exports.Auth=Q,exports.Controller=he,exports.Group=ee,exports.GroupRoute=se,exports.Log=ae,exports.Logs=te,exports.Permission=pe,exports.Responses=de,exports.Route=re,exports.User=oe,exports.UserGroup=ne,exports.app=st,exports.auth=me,exports.crt=le,exports.initialize=()=>{Z.sync().then((()=>{$(void 0,void 0,void 0,(function*(){if(0==(yield oe.count())){const t=yield oe.create({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",description:"",state:!0});if(0==(yield ee.count())){const r=yield ee.create({name:"admin",description:"",state:!0});if(yield ne.create({userId:t.id,groupId:r.id}),0==(yield re.count())){const t=["read","write"],s=["users","groups","permission"];e.forEachSeries(s,(s=>$(void 0,void 0,void 0,(function*(){e.forEachSeries(t,(e=>$(void 0,void 0,void 0,(function*(){const t=s.toLowerCase()+"."+e.toLowerCase(),o=yield re.create({name:t,description:"",state:!0});yield se.create({groupId:r.id,routeId:o.id})}))))}))))}}}})),V&&ot(it)}))},exports.key=ce,exports.permission=xe,exports.router=rt,exports.sequelize=Z,exports.server=it,exports.startSocket=ot,exports.upload=e=>{const t=(null==e?void 0:e.path)||X,r=x.default.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>$(void 0,void 0,void 0,(function*(){return s(null,at(t,S.default.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||W),o=x.default({storage:r,fileFilter(t,r,s){var o;return $(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.indexOf(r.mimetype);return void 0!==t&&t<0?s(new Error("File type not allowed")):s(null,!0)}))},limits:{fileSize:s}}),n=(null==e?void 0:e.count)||F,i=(null==e?void 0:e.field)||Y,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?de.error(t,e.message):r()}))}},exports.uuid=J,exports.validation=ge;
6
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@andrewcaires/utils.js"),t=require("dotenv"),r=require("sequelize"),s=require("cors"),o=require("express"),n=require("fs"),i=require("crypto-js"),a=require("jsonwebtoken"),d=require("mime-types"),u=require("multer"),l=require("path"),c=require("joi"),p=require("http"),f=require("https"),m=require("net"),g=require("ws");function v(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function y(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var s=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,s.get?s:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var h=v(s),I=v(o),T=v(d),w=v(u),_=v(c),A=y(p),P=y(f),S=v(g);t.config();const b=parseInt(process.env.API_AUTH_SLEEP||"1000"),O=process.env.API_DB_DATABASE||"",x=process.env.API_DB_HOST||"127.0.0.1",E=process.env.API_DB_PASSWORD||"",D=parseInt(process.env.API_DB_PORT||"3306"),R=process.env.API_DB_TYPE||"",q=process.env.API_DB_USERNAME||"root",N=e.toBool(process.env.API_DB_LOG||"false"),j=process.env.API_HTTP_CRT||"",B=process.env.API_HTTP_KEY||"",k=parseInt(process.env.API_HTTP_PORT||"3000"),U=process.env.API_HTTP_PUBLIC||"",H=e.toBool(process.env.API_HTTP_CROSS||"false"),L=e.toBool(process.env.API_HTTP_HYBRID||"false"),z=process.env.API_TOKEN_CRT||"",C=process.env.API_TOKEN_KEY||"",M=process.env.API_TOKEN_HEADER||"authorization",G=parseInt(process.env.API_TOKEN_LIFETIME||"15"),K=parseInt(process.env.API_UPLOAD_COUNT||"1"),F=process.env.API_UPLOAD_FIELD||"upload",Y=parseInt(process.env.API_UPLOAD_SIZE||"2"),W=process.env.API_UPLOAD_TEMP||"./temp",X=e.toBool(process.env.API_WEBSOCKET_START||"false");function $(e,t,r,s){return new(r||(r=Promise))((function(o,n){function i(e){try{d(s.next(e))}catch(e){n(e)}}function a(e){try{d(s.throw(e))}catch(e){n(e)}}function d(e){var t;e.done?o(e.value):(t=e.value,t instanceof r?t:new r((function(e){e(t)}))).then(i,a)}d((s=s.apply(e,t||[])).next())}))}const V={type:r.UUID,defaultValue:r.UUIDV4,allowNull:!1,primaryKey:!0},J=(()=>{switch(R){case"mariadb":return new r.Sequelize(O,q,E,{host:x,port:D,dialect:"mariadb",logging:N,define:{timestamps:!1}});case"mysql":return new r.Sequelize(O,q,E,{host:x,port:D,dialect:"mysql",logging:N,define:{timestamps:!1}});case"postgres":return new r.Sequelize(O,q,E,{host:x,port:D,dialect:"postgres",logging:N,define:{timestamps:!1}})}throw new Error("No database selected")})();class Z extends r.Model{}Z.init({login:r.DataTypes.BIGINT,logout:r.DataTypes.BIGINT,secret:r.DataTypes.STRING,timestamp:r.DataTypes.BIGINT,useragent:r.DataTypes.STRING},{sequelize:J,modelName:"auth"});class Q extends r.Model{}Q.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:J,modelName:"group"});class ee extends r.Model{}ee.init({type:r.DataTypes.STRING,source:r.DataTypes.STRING,message:r.DataTypes.TEXT},{sequelize:J,modelName:"logs",timestamps:!0,createdAt:"created",updatedAt:!1});class te extends r.Model{}te.init({name:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:J,modelName:"route"});class re extends r.Model{}re.init({},{sequelize:J,modelName:"groups_routes"}),re.removeAttribute("id");class se extends r.Model{}se.init({name:r.DataTypes.STRING,email:r.DataTypes.STRING,username:r.DataTypes.STRING,password:r.DataTypes.STRING,description:r.DataTypes.TEXT,state:r.DataTypes.BOOLEAN},{sequelize:J,modelName:"user"});class oe extends r.Model{}oe.init({},{sequelize:J,modelName:"users_groups"}),oe.removeAttribute("id"),se.hasMany(Z),Z.belongsTo(se),Q.hasMany(re),re.belongsTo(Q),te.hasMany(re),re.belongsTo(te),se.hasMany(oe),oe.belongsTo(se),Q.hasMany(oe),oe.belongsTo(Q);var ne;!function(e){e.ERROR="",e.INFO="",e.NONE="",e.SUCCESS="",e.WARNING=""}(ne||(ne={}));class ie{static write(e,t,r){ie.writeRaw(ne.NONE,"",e,t,r)}static error(e,t,r){ie.writeRaw(ne.ERROR,"error",e,t,r)}static info(e,t,r){ie.writeRaw(ne.INFO,"info",e,t,r)}static success(e,t,r){ie.writeRaw(ne.ERROR,"success",e,t,r)}static warning(e,t,r){ie.writeRaw(ne.WARNING,"warning",e,t,r)}static writeConsole(t,r,s){const o=e.dateFormat(new Date,"%H:%M:%S");console.log(">",t,r+" ".repeat(10-r.length),"","|",o,"|",s)}static writeRaw(t,r,s,o,n){(n=!!e.isUndefined(n)||n)&&ie.writeConsole(t,r,s),ee.create({type:r,source:o,message:s}).catch((()=>null))}}class ae{static success(e,t){return e.status(200).json({message:t})}static data(e,t){return e.status(200).json(Object.assign({},t))}static error(e,t){return e.status(500).json({message:t})}static list(e,t){return e.status(200).json([...t])}static notfound(e,t){return e.status(404).json({message:t})}static validation(e,t,r){return e.status(400).json({message:t,details:r})}static unauthorized(e,t){return e.status(401).json({message:t})}}class de{constructor(e,t){this.log=e,this.model=t}add(){return(e,t)=>$(this,void 0,void 0,(function*(){const r=yield this.model.create(e.body).catch((e=>{ie.error(e.message,this.log+".add")}));return r?ae.data(t,{id:r.id}):ae.error(t,"Internal Server Error")}))}all(t,s){return(o,n)=>$(this,void 0,void 0,(function*(){var i,a,d,u,l;t||(t={});const c=Object.assign({},t);c.where=c.where?Object.assign({},c.where):{};const p=null===(i=o.query.limit)||void 0===i?void 0:i.toString();p&&(c.limit=parseInt(p));const f=null===(a=o.query.offset)||void 0===a?void 0:a.toString();f&&(c.offset=parseInt(f));const m=null===(d=o.query.asc)||void 0===d?void 0:d.toString();m&&(c.order=[[m,"ASC"]]);const g=null===(u=o.query.desc)||void 0===u?void 0:u.toString();g&&(c.order=[[g,"DESC"]]);const v=[],y=null===(l=o.query.search)||void 0===l?void 0:l.toString();y&&(Object.keys(this.model.getAttributes()).forEach((e=>{"password"!=e&&v.push({[e]:{[r.Op.like]:`%${y}%`}})})),v.length&&(c.where=Object.assign(Object.assign({},c.where),{[r.Op.or]:[...v]})));const h=yield this.model.findAll(c).catch((e=>{ie.error(e.message,this.log+".all")})),I=yield this.model.count(c).catch(e.noop);return h?ae.data(n,{count:I,records:s?s(h):h}):ae.error(n,"Internal Server Error")}))}del(){return(e,t)=>$(this,void 0,void 0,(function*(){const{id:r}=e.params;return(yield this.model.destroy({where:{id:r}}).catch((e=>{ie.error(e.message,this.log+".del")})))?ae.success(t,"OK"):ae.notfound(t,"Record not found")}))}get(e,t){return(r,s)=>$(this,void 0,void 0,(function*(){e||(e={});const o=Object.assign({},e);o.where=o.where?Object.assign({},o.where):{};const{id:n}=r.params,i=yield this.model.findByPk(n,o).catch((e=>{ie.error(e.message,this.log+".get")}));return i?ae.data(s,t?t(i):i.toJSON()):null===i?ae.notfound(s,"Record not found"):ae.error(s,"Internal Server Error")}))}set(){return(e,t)=>$(this,void 0,void 0,(function*(){const{id:r}=e.params,s=yield this.model.update(e.body,{where:{id:r}}).catch((e=>{ie.error(e.message,this.log+".set")}));if(s){const[e]=s;if(e)return ae.success(t,"OK")}return ae.success(t,"Record not changed")}))}}class ue{static all(e,t){return $(this,void 0,void 0,(function*(){return yield te.findAll({where:Object.assign(Object.assign({},t),{state:!0}),include:[{model:re,required:!0,include:[{model:Q,required:!0,where:{state:!0},include:[{model:oe,required:!0,where:{userId:e.id}}]}]}]}).catch((e=>{ie.error(e.message,"permission")}))}))}static get(e){return $(this,void 0,void 0,(function*(){const t=yield ue.all(e);return t?t.map((e=>e.name)):[]}))}static is(e,t){return $(this,void 0,void 0,(function*(){const r=yield ue.all(e,{name:t});return r&&!!r.length}))}}const le=e=>{if(n.existsSync(e))return n.readFileSync(e)},ce={http:le(j),token:le(z)},pe={http:le(B),token:le(C)};class fe{static sign(e){return pe.token?{token:a.sign(e,pe.token,{algorithm:"RS256"})}:{error:"Invalid Secret"}}static verify(e){if(!ce.token)return{error:"Invalid Secret"};if(!e||e.split(".").length<3)return{error:"Invalid Token"};try{return{decode:a.verify(e,ce.token)}}catch(e){return{error:"Invalid Token"}}}}const me=["id","name","email","username"],ge=(e,t,r)=>$(void 0,void 0,void 0,(function*(){const s=e.get(M)||"",{error:o,decode:n}=fe.verify(s);if(o)return ae.error(t,o);if(n){const{id:s,secret:o}=n;if(s&&n){const n=yield se.findOne({where:{id:s,state:!0}}).catch((e=>{ie.error(e.message,"token.check")}));if(n){const s=yield Z.findOne({where:{secret:o,userId:n.id}}).catch((e=>{ie.error(e.message,"token.check")}));if(s){const o=Date.now();if(o>s.timestamp)return ae.error(t,"Expired token");s.timestamp=o+6e4*G;const i=e.get("User-Agent");return i&&(s.useragent=i),yield s.save(),e.auth=s,e.user=n,r()}}return ae.error(t,"Access denied")}}return ae.error(t,"Invalid token")})),ve=e=>(t,r,s)=>$(void 0,void 0,void 0,(function*(){const o=t.user;return o?(yield ue.is(o,e))?s():ae.error(r,"Unauthorized access"):ae.unauthorized(r,"Access denied")})),ye=(t,r)=>{const s=e.uuidv4()+"."+r;return n.existsSync(l.join(t,s))?ye(t,r):s},he=e=>{const t={abortEarly:!1,allowUnknown:!0,stripUnknown:!0};return(r,s,o)=>{const{error:n,value:i}=e.validate(r.body,t);if(n){const e=n.details.map((e=>e.message)).join(", "),t=[];return n.details.forEach((e=>{var r;t.push({key:(null===(r=e.context)||void 0===r?void 0:r.key)||"",type:e.type})})),ae.validation(s,"Validation error: "+e,t)}return r.body=i,o()}},Ie={username:_.default.string().min(5).required(),password:_.default.string().min(5).required()},Te=he(_.default.object(Ie)),we=o.Router();we.get("/",ge,((t,r)=>$(void 0,void 0,void 0,(function*(){const s=t.user;if(!s)return ae.unauthorized(r,"Access denied");const o=yield ue.all(s);if(o){const t=e.allowedObject(me,s.toJSON()),n=o.map((e=>e.name));return ae.data(r,Object.assign(Object.assign({},t),{permissions:n}))}return ae.error(r,"Internal Server Error")})))),we.post("/login",Te,((t,r)=>$(void 0,void 0,void 0,(function*(){const{username:s,password:o}=t.body;if(!s||!o)return ae.error(r,"Invalid parameters");yield e.sleep(b);const n=yield se.findOne({where:{username:s}}).catch((e=>{ie.error(e.message,"auth.login")}));if(!n)return ae.notfound(r,"Username not found");if(!n.state)return ae.error(r,"Username is disabled");const a=i.SHA256(o).toString();if(n.password!=a)return ae.error(r,"Invalid password");const d=n.id,u=e.uniqueID(),{error:l,token:c}=fe.sign({id:d,secret:u});if(l)return ae.error(r,l);if(c){const e=Date.now(),s=e+6e4*G,o=t.get("User-Agent"),n=yield Z.create({login:e,secret:u,timestamp:s,useragent:o,userId:d}).catch((e=>{ie.error(e.message,"auth.login")}));if(n)return ae.data(r,{token:c})}return ae.error(r,"Internal Server Error")})))),we.get("/logout",ge,((e,t)=>$(void 0,void 0,void 0,(function*(){const r=e.auth;return r?(r.logout=Date.now(),r.timestamp=r.logout,yield r.save(),ae.success(t,"Disconcerted")):ae.unauthorized(t,"Access denied")}))));const _e=new de("groups",Q),Ae=new de("groups.route",re),Pe=_e.add(),Se=_e.all(),be=_e.del(),Oe=_e.get(),xe=_e.set(),Ee={name:_.default.string().min(3).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},De=he(_.default.object(Ee)),Re={routes:_.default.array().items(_.default.number())},qe=he(_.default.object(Re)),Ne={name:_.default.string().min(3).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},je=he(_.default.object(Ne)),Be=o.Router();Be.use(ge),Be.get("/",ve("groups.read"),Se),Be.post("/",ve("groups.write"),De,Pe),Be.route("/:id").get(ve("groups.read"),Oe).put(ve("groups.write"),je,xe).delete(ve("groups.write"),be),Be.route("/:id/routes").get(ve("groups.read"),qe,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ae.all({where:{groupId:r},include:[{model:te,required:!0}]},(e=>e.map((e=>e.route))))(e,t)})))).put(ve("groups.write"),qe,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{routes:s}=e.body,o=yield Q.findByPk(r,{attributes:["id"]}).catch((e=>{ie.error(e.message,"groups.routesSet")}));if(o){const e=o.id;if(yield re.destroy({where:{groupId:e}}),s){let t=0;for(let r=0;r<s.length;r++)t=yield te.count({where:{id:s[r]}}),t&&(yield re.create({groupId:e,routeId:s[r]}))}return ae.success(t,"OK")}return null===o?ae.notfound(t,"Record not found"):ae.error(t,"Internal Server Error")}))));const ke=new de("logs",ee),Ue=o.Router();Ue.use(ge),Ue.get("/",ve("logs.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){const{source:r,type:s}=e.query,o=r&&s?{source:r,type:s}:r?{source:r}:s?{type:s}:{};return ke.all({where:o,order:[["created","DESC"]]})(e,t)}))));const He=new de("route",te),Le=He.add(),ze=He.all(),Ce=He.del(),Me=He.get(),Ge=He.set(),Ke={name:_.default.string().min(5).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},Fe=he(_.default.object(Ke)),Ye={name:_.default.string().min(5).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},We=he(_.default.object(Ye)),Xe=o.Router();Xe.use(ge),Xe.get("/",ve("routes.read"),ze),Xe.post("/",ve("routes.write"),Fe,Le),Xe.route("/:id").get(ve("routes.read"),Me).put(ve("routes.write"),We,Ge).delete(ve("routes.write"),Ce);const $e=new de("user",se),Ve=new de("user.groups",oe),Je=["id","name","email","username","description","state"],Ze=$e.del(),Qe={name:_.default.string().min(5).required(),email:_.default.string().email().required(),username:_.default.string().min(5).required(),password:_.default.string().min(5).required(),description:_.default.string().allow(null,""),state:_.default.boolean().required()},et=he(_.default.object(Qe)),tt={groups:_.default.array().items(_.default.number())},rt=he(_.default.object(tt)),st={name:_.default.string().min(5).empty(""),email:_.default.string().email().empty(""),username:_.default.string().min(5).empty(""),password:_.default.string().min(5).empty(""),description:_.default.string().allow(null,""),state:_.default.boolean().empty("")},ot=he(_.default.object(st)),nt=o.Router();nt.use(ge),nt.get("/",ve("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return $e.all({attributes:Je})(e,t)})))),nt.post("/",ve("users.write"),et,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password=i.SHA256(e.body.password).toString(),yield $e.add()(e,t)})))),nt.route("/:id").get(ve("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){return $e.get({attributes:Je})(e,t)})))).put(ve("users.write"),ot,((e,t)=>$(void 0,void 0,void 0,(function*(){return e.body.password&&(e.body.password=i.SHA256(e.body.password).toString()),$e.set()(e,t)})))).delete(ve("users.write"),Ze),nt.route("/:id/groups").get(ve("users.read"),((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params;return Ve.all({where:{userId:r},include:[{model:Q,required:!0}]},(e=>e.map((e=>e.group))))(e,t)})))).put(ve("users.write"),rt,((e,t)=>$(void 0,void 0,void 0,(function*(){const{id:r}=e.params,{groups:s}=e.body,o=yield se.findByPk(r,{attributes:["id"]}).catch((e=>{ie.error(e.message,"user.groups.set")}));if(o){if(yield oe.destroy({where:{userId:o.id}}),s){let e=0;for(let t=0;t<s.length;t++)e=yield Q.count({where:{id:s[t]}}),e&&(yield oe.create({userId:o.id,groupId:s[t]}))}return ae.success(t,"OK")}return ae.notfound(t,"Record not found")}))));const it=o.Router();it.use("/auth",we),it.use("/groups",Be),it.use("/logs",Ue),it.use("/routes",Xe),it.use("/users",nt);const at=I.default();at.use(I.default.json()),at.use(((e,t,r,s)=>e?(ie.error(e.message,"express"),ae.error(r,"Internal Server Error")):s())),at.use(I.default.urlencoded({extended:!0})),at.disable("x-powered-by"),H&&at.use(h.default());const dt=o.Router();at.use("/api",dt),at.use("/api",it),at.all("/api/*",((e,t)=>ae.notfound(t,"Invalid API"))),U&&(n.existsSync(U)&&at.use(I.default.static(U)),at.get("*",((e,t)=>{if(!n.existsSync(U))return ae.notfound(t,'File "index.html" not found');t.sendFile(U+"/index.html")})));const ut=e=>{const t=new S.default.Server({server:e,verifyClient:lt});return t.on("connection",(e=>{e.on("message",(t=>$(void 0,void 0,void 0,(function*(){fe.verify(t.toString()),e.close()})))),setTimeout((()=>{e.close()}),2e3),e.on("close",(()=>{t.emit("close",e)}))})),t},lt=(e,t)=>t(X),ct=(e=>{if(!ce.http||!pe.http){const t=A.createServer(e);return t.listen(k,(()=>ie.info(`Server started on port ${k}`))),t}const t=A.createServer(((e,t)=>{const r=80==k?":80":"";t.writeHead(301,{Location:"https://"+e.headers.host+r+e.url}),t.end()})),r=P.createServer({key:pe.http,cert:ce.http},e);if(L){return new m.Server((e=>{e.once("data",(s=>{e.pause(),e.unshift(s),(22===s[0]?r:t).emit("connection",e),process.nextTick((()=>e.resume()))}))})).listen(k,(()=>ie.info(`Server started on port ${k}`))),r}return 443==k&&t.listen(80,(()=>ie.info("Server started on port 80"))),r.listen(k,(()=>ie.info(`Server started on port ${k}`))),r})(at);exports.API_AUTH_SLEEP=b,exports.API_DB_DATABASE=O,exports.API_DB_HOST=x,exports.API_DB_LOG=N,exports.API_DB_PASSWORD=E,exports.API_DB_PORT=D,exports.API_DB_TYPE=R,exports.API_DB_USERNAME=q,exports.API_HTTP_CROSS=H,exports.API_HTTP_CRT=j,exports.API_HTTP_HYBRID=L,exports.API_HTTP_KEY=B,exports.API_HTTP_PORT=k,exports.API_HTTP_PUBLIC=U,exports.API_TOKEN_CRT=z,exports.API_TOKEN_HEADER=M,exports.API_TOKEN_KEY=C,exports.API_TOKEN_LIFETIME=G,exports.API_UPLOAD_COUNT=K,exports.API_UPLOAD_FIELD=F,exports.API_UPLOAD_SIZE=Y,exports.API_UPLOAD_TEMP=W,exports.API_WEBSOCKET_START=X,exports.Auth=Z,exports.Controller=de,exports.Group=Q,exports.GroupRoute=re,exports.Log=ie,exports.Logs=ee,exports.Permission=ue,exports.Responses=ae,exports.Route=te,exports.Token=fe,exports.User=se,exports.UserGroup=oe,exports.app=at,exports.auth=ge,exports.crt=ce,exports.initialize=()=>{J.sync().then((()=>{$(void 0,void 0,void 0,(function*(){if(0==(yield se.count())){const t={description:"",state:!0},r=yield se.create(Object.assign({name:"Admin",email:"admin@localhost",username:"admin",password:"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"},t));if(0==(yield Q.count())){const s=yield Q.create(Object.assign({name:"admin"},t));if(yield oe.create({userId:r.id,groupId:s.id}),0==(yield te.count())){const r=["read","write"],o=["users","groups","permission"];yield e.forEachSeries(o,(o=>$(void 0,void 0,void 0,(function*(){yield e.forEachSeries(r,(e=>$(void 0,void 0,void 0,(function*(){const r=o+"."+e,n=yield te.create(Object.assign({name:r},t));yield re.create({groupId:s.id,routeId:n.id})}))))}))));const n=yield te.create(Object.assign({name:"logs.read"},t));yield re.create({groupId:s.id,routeId:n.id})}}}})),X&&ut(ct)}))},exports.key=pe,exports.permission=ve,exports.router=dt,exports.sequelize=J,exports.server=ct,exports.startSocket=ut,exports.upload=e=>{const t=(null==e?void 0:e.path)||W,r=w.default.diskStorage({destination:(e,r,s)=>s(null,t),filename:(e,r,s)=>$(void 0,void 0,void 0,(function*(){return s(null,ye(t,T.default.extension(r.mimetype)||"bin"))}))}),s=1e6*((null==e?void 0:e.size)||Y),o=w.default({storage:r,fileFilter(t,r,s){var o;return $(this,void 0,void 0,(function*(){const t=null===(o=null==e?void 0:e.types)||void 0===o?void 0:o.indexOf(r.mimetype);return void 0!==t&&t<0?s(new Error("File type not allowed")):s(null,!0)}))},limits:{fileSize:s}}),n=(null==e?void 0:e.count)||K,i=(null==e?void 0:e.field)||F,a=o.array(i,n);return(e,t,r)=>{a(e,t,(function(e){return e?ae.error(t,e.message):r()}))}},exports.uuid=V,exports.validation=he;
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@andrewcaires/api",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Simple api for small applications using express, jsonwebtoken, sequelize and websocket",
5
5
  "main": "dist/index.umd.js",
6
6
  "module": "dist/index.esm.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "scripts": {
9
9
  "serve": "ts-node src/test.ts",
10
- "build": "rollup -c build/rollup.config.js"
10
+ "build": "rollup -c build/rollup.config.js",
11
+ "dev": "ts-node-dev --respawn --transpile-only ./src/index.ts"
11
12
  },
12
13
  "repository": {
13
14
  "type": "git",
@@ -34,7 +35,7 @@
34
35
  },
35
36
  "homepage": "https://github.com/andrewcaires/npm/tree/main/api#readme",
36
37
  "dependencies": {
37
- "@andrewcaires/utils.js": "^0.1.0",
38
+ "@andrewcaires/utils.js": "^0.1.5",
38
39
  "cors": "^2.8.5",
39
40
  "crypto-js": "^4.1.1",
40
41
  "dotenv": "^16.0.1",
@@ -44,30 +45,32 @@
44
45
  "jsonwebtoken": "^8.5.1",
45
46
  "mariadb": "^3.0.0",
46
47
  "mime-types": "^2.1.35",
47
- "multer": "^1.4.4",
48
+ "multer": "^1.4.5-lts.1",
48
49
  "mysql2": "^2.3.3",
49
50
  "pg": "^8.7.3",
50
51
  "pg-hstore": "^2.3.4",
51
- "sequelize": "^6.19.1",
52
- "ws": "^8.6.0"
52
+ "sequelize": "^6.21.2",
53
+ "ws": "^8.8.0"
53
54
  },
54
55
  "devDependencies": {
55
- "@rollup/plugin-typescript": "^8.3.2",
56
+ "@rollup/plugin-commonjs": "^22.0.1",
57
+ "@rollup/plugin-typescript": "^8.3.3",
56
58
  "@types/cors": "^2.8.12",
57
59
  "@types/crypto-js": "^4.1.1",
58
60
  "@types/express": "^4.17.13",
59
61
  "@types/jsonwebtoken": "^8.5.8",
60
62
  "@types/mime-types": "^2.1.1",
61
63
  "@types/multer": "^1.4.7",
62
- "@types/node": "^17.0.34",
64
+ "@types/node": "^18.0.1",
63
65
  "@types/ws": "^8.5.3",
64
- "@typescript-eslint/eslint-plugin": "^5.24.0",
65
- "@typescript-eslint/parser": "^5.24.0",
66
- "eslint": "^8.15.0",
67
- "rollup": "^2.73.0",
68
- "rollup-plugin-dts": "^4.2.1",
66
+ "@typescript-eslint/eslint-plugin": "^5.30.4",
67
+ "@typescript-eslint/parser": "^5.30.0",
68
+ "eslint": "^8.19.0",
69
+ "rollup": "^2.75.7",
70
+ "rollup-plugin-dts": "^4.2.2",
69
71
  "rollup-plugin-terser": "^7.0.2",
70
- "ts-node": "^10.7.0",
71
- "typescript": "^4.6.4"
72
+ "ts-node": "^10.8.2",
73
+ "ts-node-dev": "^2.0.0",
74
+ "typescript": "^4.7.4"
72
75
  }
73
76
  }