velocious 1.0.0

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.
Files changed (60) hide show
  1. package/.github/dependabot.yml +9 -0
  2. package/bin/velocious +14 -0
  3. package/index.cjs +11 -0
  4. package/package.json +29 -0
  5. package/peak_flow.yml +17 -0
  6. package/spec/database/connection/drivers/mysql/query-parser-spec.cjs +34 -0
  7. package/spec/dummy/config/databases.example.json +10 -0
  8. package/spec/dummy/config/databases.json +0 -0
  9. package/spec/dummy/config/databases.peakflow.json +11 -0
  10. package/spec/dummy/index.cjs +40 -0
  11. package/spec/dummy/src/models/task.cjs +4 -0
  12. package/spec/dummy/src/routes/tasks/controller.cjs +18 -0
  13. package/spec/dummy/src/routes/tasks/index.ejs +1 -0
  14. package/spec/dummy/src/routes/tasks/show.ejs +0 -0
  15. package/spec/dummy/src/routes.cjs +10 -0
  16. package/spec/http-server/client-spec.cjs +35 -0
  17. package/spec/http-server/get-spec.cjs +13 -0
  18. package/spec/support/jasmine.json +11 -0
  19. package/src/application.cjs +36 -0
  20. package/src/configuration.cjs +14 -0
  21. package/src/controller.cjs +50 -0
  22. package/src/database/connection/drivers/mysql/index.cjs +5 -0
  23. package/src/database/connection/drivers/mysql/options.cjs +7 -0
  24. package/src/database/connection/drivers/mysql/query-parser.cjs +26 -0
  25. package/src/database/connection/index.cjs +2 -0
  26. package/src/database/handler.cjs +5 -0
  27. package/src/database/index.cjs +9 -0
  28. package/src/database/pool/index.cjs +2 -0
  29. package/src/database/query/from-base.cjs +15 -0
  30. package/src/database/query/from-plain.cjs +12 -0
  31. package/src/database/query/from-table.cjs +12 -0
  32. package/src/database/query/index.cjs +59 -0
  33. package/src/database/query/join-base.cjs +15 -0
  34. package/src/database/query/join-plain.cjs +12 -0
  35. package/src/database/query/select-base.cjs +15 -0
  36. package/src/database/query/select-plain.cjs +12 -0
  37. package/src/database/query/select-table-and-column.cjs +21 -0
  38. package/src/database/query-parser/from-parser.cjs +35 -0
  39. package/src/database/query-parser/joins-parser.cjs +33 -0
  40. package/src/database/query-parser/options.cjs +20 -0
  41. package/src/database/query-parser/select-parser.cjs +42 -0
  42. package/src/database/record/index.cjs +5 -0
  43. package/src/error-logger.js +18 -0
  44. package/src/http-server/client/index.cjs +75 -0
  45. package/src/http-server/client/request-parser.cjs +92 -0
  46. package/src/http-server/client/request-runner.cjs +32 -0
  47. package/src/http-server/client/request.cjs +25 -0
  48. package/src/http-server/client/response.cjs +28 -0
  49. package/src/http-server/index.cjs +78 -0
  50. package/src/http-server/worker-handler/index.cjs +78 -0
  51. package/src/http-server/worker-handler/socket-handler.cjs +35 -0
  52. package/src/http-server/worker-handler/worker-script.cjs +4 -0
  53. package/src/http-server/worker-handler/worker-thread.cjs +49 -0
  54. package/src/logger.cjs +11 -0
  55. package/src/routes/base-route.cjs +25 -0
  56. package/src/routes/get-route.cjs +18 -0
  57. package/src/routes/index.cjs +9 -0
  58. package/src/routes/resolver.cjs +61 -0
  59. package/src/routes/resource-route.cjs +39 -0
  60. package/src/routes/root-route.cjs +4 -0
@@ -0,0 +1,35 @@
1
+ const {digs} = require("diggerize")
2
+
3
+ module.exports = class VelociousDatabaseQueryParserFromParser {
4
+ constructor({pretty, query, queryParserOptions}) {
5
+ this.pretty = pretty
6
+ this.query = query
7
+ this.queryParserOptions = queryParserOptions
8
+ }
9
+
10
+ toSql() {
11
+ const {pretty, query} = digs(this, "pretty", "query")
12
+
13
+ let sql = " FROM"
14
+
15
+ for (const fromKey in query._froms) {
16
+ const from = query._froms[fromKey]
17
+
18
+ from.setOptions(this.queryParserOptions)
19
+
20
+ if (fromKey > 0) {
21
+ sql += ","
22
+ }
23
+
24
+ if (pretty) {
25
+ sql += "\n "
26
+ } else {
27
+ sql += " "
28
+ }
29
+
30
+ sql += from.toSql()
31
+ }
32
+
33
+ return sql
34
+ }
35
+ }
@@ -0,0 +1,33 @@
1
+ const {digs} = require("diggerize")
2
+
3
+ module.exports = class VelocuiousDatabaseQueryParserJoinsParser {
4
+ constructor({pretty, query, queryParserOptions}) {
5
+ this.pretty = pretty
6
+ this.query = query
7
+ this.queryParserOptions = queryParserOptions
8
+ }
9
+
10
+ toSql() {
11
+ const {pretty, query} = digs(this, "pretty", "query")
12
+
13
+ let sql = ""
14
+
15
+ for (const joinKey in query._joins) {
16
+ const join = query._joins[joinKey]
17
+
18
+ join.setOptions(this.queryParserOptions)
19
+
20
+ if (joinKey == 0) {
21
+ if (pretty) {
22
+ sql += "\n\n"
23
+ } else {
24
+ sql += " "
25
+ }
26
+ }
27
+
28
+ sql += join.toSql()
29
+ }
30
+
31
+ return sql
32
+ }
33
+ }
@@ -0,0 +1,20 @@
1
+ const {digg} = require("diggerize")
2
+
3
+ module.exports = class VelociousDatabaseQueryParserOptions {
4
+ constructor(options) {
5
+ this.columnQuote = digg(options, "columnQuote")
6
+ this.tableQuote = digg(options, "tableQuote")
7
+ }
8
+
9
+ quoteColumnName(columnName) {
10
+ if (columnName.includes(this.columnQuote)) throw new Error(`Invalid column name: ${columnName}`)
11
+
12
+ return `${this.columnQuote}${columnName}${this.columnQuote}`
13
+ }
14
+
15
+ quoteTableName(tableName) {
16
+ if (tableName.includes(this.tableQuote)) throw new Error(`Invalid table name: ${tableName}`)
17
+
18
+ return `${this.tableQuote}${tableName}${this.tableQuote}`
19
+ }
20
+ }
@@ -0,0 +1,42 @@
1
+ const {digs} = require("diggerize")
2
+
3
+ module.exports = class VelociousDatabaseQueryParserSelectParser {
4
+ constructor({pretty, query, queryParserOptions}) {
5
+ this.pretty = pretty
6
+ this.query = query
7
+ this.queryParserOptions = queryParserOptions
8
+ }
9
+
10
+ toSql() {
11
+ const {pretty, query} = digs(this, "pretty", "query")
12
+
13
+ let sql = ""
14
+
15
+ sql += "SELECT"
16
+
17
+ if (pretty) {
18
+ sql += "\n"
19
+ } else {
20
+ sql += " "
21
+ }
22
+
23
+ for (const selectKey in query._selects) {
24
+ const selectValue = query._selects[selectKey]
25
+
26
+ selectValue.setOptions(this.queryParserOptions)
27
+
28
+ sql += selectValue.toSql()
29
+
30
+ if (selectKey + 1 < query._selects.length) {
31
+ if (pretty) {
32
+ sql += ","
33
+ sql += " "
34
+ } else {
35
+ sql += ", "
36
+ }
37
+ }
38
+ }
39
+
40
+ return sql
41
+ }
42
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = class VelociousDatabaseRecord {
2
+ static find(recordId) {
3
+ throw new Error("stub")
4
+ }
5
+ }
@@ -0,0 +1,18 @@
1
+ module.exports = function errorLogger(callback) {
2
+ return async function(...args) {
3
+ try {
4
+ await callback(...args)
5
+ } catch (error) {
6
+ console.error(`ErrorLogger: ${error.message}`)
7
+
8
+ if (error.stack) {
9
+ console.error("Stack", error.stack)
10
+ } else {
11
+ console.error("No stack")
12
+ }
13
+
14
+ // Give console some time to write out messages before crashing
15
+ setTimeout(() => { throw error })
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,75 @@
1
+ const Configuration = require("../../configuration.cjs")
2
+ const {digg} = require("diggerize")
3
+ const {EventEmitter} = require("events")
4
+ const logger = require("../../logger.cjs")
5
+ const Request = require("./request.cjs")
6
+ const RequestRunner = require("./request-runner.cjs")
7
+
8
+ module.exports = class VeoliciousHttpServerClient {
9
+ events = new EventEmitter()
10
+ state = "initial"
11
+
12
+ constructor({clientCount, configuration, onExecuteRequest}) {
13
+ if (!configuration) throw new Error("No configuration given")
14
+
15
+ this.clientCount = clientCount
16
+ this.configuration = configuration
17
+ this.onExecuteRequest = onExecuteRequest
18
+ }
19
+
20
+ executeCurrentRequest() {
21
+ logger(this, "executeCurrentRequest")
22
+
23
+ this.state = "response"
24
+
25
+ const requestRunner = new RequestRunner({
26
+ configuration: this.configuration,
27
+ request: this.currentRequest,
28
+ routes: this.routes
29
+ })
30
+
31
+ requestRunner.events.on("done", (requestRunner) => this.sendResponse(requestRunner))
32
+ requestRunner.run()
33
+ }
34
+
35
+ onWrite(data) {
36
+ if (this.state == "initial") {
37
+ this.currentRequest = new Request({
38
+ configuration: this.configuration
39
+ })
40
+ this.currentRequest.requestParser.events.on("done", () => this.executeCurrentRequest())
41
+ this.currentRequest.feed(data)
42
+ this.state = "requestStarted"
43
+ } else if (this.state == "requestStarted") {
44
+ this.currentRequest.feed(data)
45
+ } else {
46
+ throw new Error(`Unknown state: ${this.state}`)
47
+ }
48
+ }
49
+
50
+ sendResponse(requestRunner) {
51
+ const response = digg(requestRunner, "response")
52
+ const body = response.getBody()
53
+ const date = new Date()
54
+
55
+ response.addHeader("Connection", "keep-alive")
56
+ response.addHeader("Content-Length", response.body.length)
57
+ response.addHeader("Date", date.toUTCString())
58
+ response.addHeader("Server", "Velocious")
59
+
60
+ let headers = ""
61
+
62
+ headers += "HTTP/1.1 200 OK\r\n"
63
+
64
+ for (const headerKey in response.headers) {
65
+ for (const headerValue of response.headers[headerKey]) {
66
+ headers += `${headerKey}: ${headerValue}\r\n`
67
+ }
68
+ }
69
+
70
+ headers += "\r\n"
71
+
72
+ this.events.emit("output", headers)
73
+ this.events.emit("output", body)
74
+ }
75
+ }
@@ -0,0 +1,92 @@
1
+ const {EventEmitter} = require("events")
2
+ const logger = require("../../logger.cjs")
3
+
4
+ module.exports = class VelociousHttpServerClientRequestParser {
5
+ constructor({configuration}) {
6
+ if (!configuration) throw new Error("No configuration given")
7
+
8
+ this.configuration = configuration
9
+ this.data = []
10
+ this.events = new EventEmitter()
11
+ this.headers = []
12
+ this.headersByName = {}
13
+ this.state = "status"
14
+ }
15
+
16
+ addHeader(name, value) {
17
+ logger(this, "addHeader", {name, value})
18
+
19
+ this.headers.push({name, value})
20
+
21
+ const formattedName = name.toLowerCase().trim()
22
+
23
+ this.headersByName[formattedName] = value
24
+ }
25
+
26
+ feed(data) {
27
+ if (this.state == "status" || this.state == "headers") {
28
+ for (const char of data) {
29
+ this.data.push(char)
30
+
31
+ if (char == 10) {
32
+ const line = String.fromCharCode.apply(null, this.data)
33
+
34
+ this.data = []
35
+ this.parse(line)
36
+ }
37
+ }
38
+ }
39
+ }
40
+
41
+ matchAndRemove(regex) {
42
+ const match = this.data.match(regex)
43
+
44
+ if (!match) {
45
+ return null
46
+ }
47
+
48
+ this.data = this.data.replace(regex, "")
49
+
50
+ return match
51
+ }
52
+
53
+ parse(line) {
54
+ if (this.state == "status") {
55
+ this.parseStatusLine(line)
56
+ } else if (this.state == "headers") {
57
+ this.parseHeader(line)
58
+ } else {
59
+ throw new Error(`Unknown state: ${this.state}`)
60
+ }
61
+ }
62
+
63
+ parseHeader(line) {
64
+ let match
65
+
66
+ if (match = line.match(/^(.+): (.+)\r\n/)) {
67
+ const name = match[1]
68
+ const value = match[2]
69
+
70
+ this.addHeader(name, value)
71
+ } else if (line == "\r\n") {
72
+ if (this.httpMethod.toUpperCase() == "GET") {
73
+ this.state = "done"
74
+ this.events.emit("done")
75
+ } else {
76
+ throw new Error(`Unknown HTTP method: ${this.httpMethod}`)
77
+ }
78
+ }
79
+ }
80
+
81
+ parseStatusLine(line) {
82
+ const match = line.match(/^(GET|POST) (.+?) HTTP\/1\.1\r\n/)
83
+
84
+ if (!match) {
85
+ throw new Error(`Couldn't match status line from: ${line}`)
86
+ }
87
+
88
+ this.httpMethod = match[1]
89
+ this.path = match[2]
90
+ this.state = "headers"
91
+ }
92
+ }
@@ -0,0 +1,32 @@
1
+ const EventEmitter = require("events")
2
+ const logger = require("../../logger.cjs")
3
+ const Response = require("./response.cjs")
4
+ const RoutesResolver = require("../../routes/resolver.cjs")
5
+
6
+ module.exports = class VelociousHttpServerClientRequestRunner {
7
+ events = new EventEmitter()
8
+
9
+ constructor({configuration, request}) {
10
+ if (!configuration) throw new Error("No configuration given")
11
+ if (!request) throw new Error("No request given")
12
+
13
+ this.configuration = configuration
14
+ this.request = request
15
+ this.response = new Response({configuration})
16
+ }
17
+
18
+ async run() {
19
+ if (!this.request) throw new Error("No request?")
20
+
21
+ logger(this, "Run request")
22
+
23
+ const routesResolver = new RoutesResolver({
24
+ configuration: this.configuration,
25
+ request: this.request,
26
+ response: this.response
27
+ })
28
+
29
+ await routesResolver.resolve()
30
+ this.events.emit("done", this)
31
+ }
32
+ }
@@ -0,0 +1,25 @@
1
+ const {digg} = require("diggerize")
2
+ const RequestParser = require("./request-parser.cjs")
3
+
4
+ module.exports = class VelociousHttpServerClientRequest {
5
+ constructor({configuration}) {
6
+ this.configuration = configuration
7
+ this.requestParser = new RequestParser({configuration})
8
+ }
9
+
10
+ feed(data) {
11
+ this.requestParser.feed(data)
12
+ }
13
+
14
+ httpMethod() {
15
+ return digg(this, "requestParser", "httpMethod")
16
+ }
17
+
18
+ host() {
19
+ return digg(this, "requestParser", "headersByName", "host")
20
+ }
21
+
22
+ path() {
23
+ return digg(this, "requestParser", "path")
24
+ }
25
+ }
@@ -0,0 +1,28 @@
1
+ module.exports = class VelociousHttpServerClientResponse {
2
+ body = undefined
3
+ headers = {}
4
+
5
+ constructor({configuration}) {
6
+ this.configuration = configuration
7
+ }
8
+
9
+ addHeader(key, value) {
10
+ if (!(key in this.headers)) {
11
+ this.headers[key] = []
12
+ }
13
+
14
+ this.headers[key].push(value)
15
+ }
16
+
17
+ getBody() {
18
+ if (this.body) {
19
+ return this.body
20
+ }
21
+
22
+ throw new Error("No body has been set")
23
+ }
24
+
25
+ setBody(value) {
26
+ this.body = value
27
+ }
28
+ }
@@ -0,0 +1,78 @@
1
+ const logger = require("../logger.cjs")
2
+ const Net = require("net")
3
+ const WorkerHandler = require("./worker-handler/index.cjs")
4
+
5
+ module.exports = class VelociousHttpServer {
6
+ constructor({configuration, host, maxWorkers, port}) {
7
+ this.configuration = configuration
8
+ this.host = host
9
+ this.port = port
10
+ this.clientCount = 0
11
+ this.maxWorkers = maxWorkers || 16
12
+ this.workerCount = 0
13
+ this.workerHandlers = []
14
+ }
15
+
16
+ async start() {
17
+ // We need at least one worker to handle requests
18
+ if (this.workerHandlers.length == 0) {
19
+ await this.spawnWorker()
20
+ }
21
+
22
+ this.netServer = new Net.Server()
23
+ this.netServer.on("connection", (socket) => this.onConnection(socket))
24
+ this.netServer.listen(this.port, () => {
25
+ logger(this, `Velocious listening on ${this.host}:${this.port}`)
26
+ })
27
+ }
28
+
29
+ stop() {
30
+ return new Promise((resolve) => {
31
+ this.netServer?.close(() => resolve())
32
+ })
33
+ }
34
+
35
+ onConnection(socket) {
36
+ const clientCount = this.clientCount
37
+
38
+ logger(this, `New client ${clientCount}`)
39
+
40
+ this.clientCount++
41
+
42
+ const workerHandler = this.workerHandlerToUse()
43
+
44
+ logger(this, `Gave client ${clientCount} to worker ${workerHandler.workerCount}`)
45
+
46
+ workerHandler.addSocketConnection({
47
+ socket,
48
+ clientCount: this.clientCount
49
+ })
50
+ }
51
+
52
+ async spawnWorker() {
53
+ const workerCount = this.workerCount
54
+
55
+ this.workerCount++
56
+
57
+ const workerHandler = new WorkerHandler({
58
+ configuration: this.configuration,
59
+ workerCount
60
+ })
61
+
62
+ await workerHandler.start()
63
+ this.workerHandlers.push(workerHandler)
64
+ }
65
+
66
+ workerHandlerToUse() {
67
+ logger(this, `Worker handlers length: ${this.workerHandlers.length}`)
68
+
69
+ const randomWorkerNumber = parseInt(Math.random() * this.workerHandlers.length)
70
+ const workerHandler = this.workerHandlers[randomWorkerNumber]
71
+
72
+ if (!workerHandler) {
73
+ throw new Error(`No workerHandler by that number: ${randomWorkerNumber}`)
74
+ }
75
+
76
+ return workerHandler
77
+ }
78
+ }
@@ -0,0 +1,78 @@
1
+ const {digs} = require("diggerize")
2
+ const logger = require("../../logger.cjs")
3
+ const SocketHandler = require("./socket-handler.cjs")
4
+ const {Worker} = require("worker_threads")
5
+
6
+ module.exports = class VelociousHttpServerWorker {
7
+ constructor({configuration, workerCount}) {
8
+ this.configuration = configuration
9
+ this.socketHandlers = {}
10
+ this.workerCount = workerCount
11
+ }
12
+
13
+ async start() {
14
+ return new Promise((resolve) => {
15
+ const {debug, directory} = digs(this.configuration, "debug", "directory")
16
+
17
+ this.onStartCallback = resolve
18
+ this.worker = new Worker("./src/http-server/worker-handler/worker-script.cjs", {
19
+ workerData: {
20
+ debug,
21
+ directory,
22
+ workerCount: this.workerCount
23
+ }
24
+ })
25
+ this.worker.on("error", (error) => this.onWorkerError(error))
26
+ this.worker.on("exit", (code) => this.onWorkerExit(code))
27
+ this.worker.on("message", (message) => this.onWorkerMessage(message))
28
+ })
29
+ }
30
+
31
+ addSocketConnection({socket, clientCount}) {
32
+ socket.on("end", () => {
33
+ logger(this, `Removing ${clientCount} from socketHandlers`)
34
+ delete this.socketHandlers[clientCount]
35
+ })
36
+
37
+ const socketHandler = new SocketHandler({
38
+ configuration: this.configuration,
39
+ socket,
40
+ clientCount,
41
+ worker: this.worker
42
+ })
43
+
44
+ this.socketHandlers[clientCount] = socketHandler
45
+ this.worker.postMessage({command: "newClient", clientCount})
46
+ }
47
+
48
+ onWorkerError(error) {
49
+ throw new Error(`Worker error: ${error}`)
50
+ }
51
+
52
+ onWorkerExit(code) {
53
+ if (code !== 0) {
54
+ throw new Error(`Client worker stopped with exit code ${code}`)
55
+ }
56
+ }
57
+
58
+ onWorkerMessage(data) {
59
+ logger(this, `Worker message`, data)
60
+
61
+ const {command} = digs(data, "command")
62
+
63
+ if (command == "started") {
64
+ this.onStartCallback()
65
+ this.onStartCallback = null
66
+ } else if (command == "clientOutput") {
67
+ logger(this, "CLIENT OUTPUT", data)
68
+
69
+ const {clientCount, output} = digs(data, "clientCount", "output")
70
+
71
+ logger(this, "CLIENT OUTPUT", data)
72
+
73
+ this.socketHandlers[clientCount].send(output)
74
+ } else {
75
+ throw new Error(`Unknown command: ${command}`)
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,35 @@
1
+ const logger = require("../../logger.cjs")
2
+
3
+ module.exports = class VelociousHttpServerWorkerHandlerSocketHandler {
4
+ constructor({configuration, socket, clientCount, worker}) {
5
+ if (!configuration) throw new Error("No configuration given")
6
+
7
+ this.configuration = configuration
8
+ this.socket = socket
9
+ this.clientCount = clientCount
10
+ this.worker = worker
11
+
12
+ socket.on("data", (chunk) => this.onSocketData(chunk))
13
+ socket.on("end", () => this.onSocketEnd())
14
+ }
15
+
16
+ onSocketData(chunk) {
17
+ logger(this, `Socket ${this.clientCount}: ${chunk}`)
18
+
19
+ this.worker.postMessage({
20
+ command: "clientWrite",
21
+ chunk,
22
+ clientCount: this.clientCount
23
+ })
24
+ }
25
+
26
+ onSocketEnd() {
27
+ logger(this, `Socket ${this.clientCount} end`)
28
+ }
29
+
30
+ send(data) {
31
+ logger(this, "Send", data)
32
+
33
+ this.socket.write(data)
34
+ }
35
+ }
@@ -0,0 +1,4 @@
1
+ const { workerData, parentPort } = require("worker_threads")
2
+ const WorkerThread = require("./worker-thread.cjs")
3
+
4
+ new WorkerThread({parentPort, workerData})
@@ -0,0 +1,49 @@
1
+ const Client = require("../client/index.cjs")
2
+ const Configuration = require("../../configuration.cjs")
3
+ const {digg, digs} = require("diggerize")
4
+ const errorLogger = require("../../error-logger")
5
+ const logger = require("../../logger.cjs")
6
+
7
+ module.exports = class VelociousHttpServerWorkerHandlerWorkerThread {
8
+ constructor({parentPort, workerData}) {
9
+ const {debug, directory, workerCount} = digs(workerData, "debug", "directory", "workerCount")
10
+
11
+ this.clients = {}
12
+ this.configuration = new Configuration({debug, directory})
13
+ this.parentPort = parentPort
14
+ this.workerCount = workerCount
15
+
16
+ parentPort.on("message", errorLogger((data) => this.onCommand(data)))
17
+
18
+ logger(this, `Worker ${workerCount} started`)
19
+
20
+ parentPort.postMessage({command: "started"})
21
+ }
22
+
23
+ onCommand(data) {
24
+ logger(this, `Worker ${this.workerCount} received command`, data)
25
+
26
+ const {command} = data
27
+
28
+ if (command == "newClient") {
29
+ const {clientCount} = digs(data, "clientCount")
30
+ const client = new Client({
31
+ clientCount,
32
+ configuration: this.configuration
33
+ })
34
+
35
+ client.events.on("output", (output) => {
36
+ this.parentPort.postMessage({command: "clientOutput", clientCount, output})
37
+ })
38
+
39
+ this.clients[clientCount] = client
40
+ } else if (command == "clientWrite") {
41
+ const {chunk, clientCount} = digs(data, "chunk", "clientCount")
42
+ const client = digg(this.clients, clientCount)
43
+
44
+ client.onWrite(chunk)
45
+ } else {
46
+ throw new Error(`Unknown command: ${command}`)
47
+ }
48
+ }
49
+ }
package/src/logger.cjs ADDED
@@ -0,0 +1,11 @@
1
+ const {digg} = require("diggerize")
2
+
3
+ module.exports = function log(object, ...messages) {
4
+ if (!object.configuration) console.error(`No configuration on ${object.constructor.name}`)
5
+
6
+ if (object.configuration?.debug) {
7
+ const className = digg(object, "constructor", "name")
8
+
9
+ console.log(className, ...messages)
10
+ }
11
+ }