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,9 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: npm
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ time: "01:00"
8
+ timezone: Europe/Copenhagen
9
+ open-pull-requests-limit: 99
package/bin/velocious ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/node
2
+
3
+ console.log("Hello", process.argv)
4
+
5
+ const args = process.argv.slice(2)
6
+
7
+ console.log(args)
8
+
9
+ if (args[0] == "g" && args[1] == "migration") {
10
+ const migrationName = args[2]
11
+ const date = new Date()
12
+
13
+ console.log({ migrationName, date })
14
+ }
package/index.cjs ADDED
@@ -0,0 +1,11 @@
1
+ const Application = require("./src/application.cjs")
2
+ const Controller = require("./src/controller.cjs")
3
+ const Database = require("./src/database/index.cjs")
4
+ const HttpServer = require("./src/http-server/index.cjs")
5
+
6
+ module.exports = {
7
+ Application,
8
+ Controller,
9
+ Database,
10
+ HttpServer
11
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "velocious",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "test": "jasmine"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/kaspernj/velocious.git"
11
+ },
12
+ "author": "k@spernj.org",
13
+ "license": "ISC",
14
+ "bugs": {
15
+ "url": "https://github.com/kaspernj/velocious/issues"
16
+ },
17
+ "homepage": "https://github.com/kaspernj/velocious#readme",
18
+ "description": "",
19
+ "devDependencies": {
20
+ "jasmine": "^4.0.2",
21
+ "node-fetch": "^2.6.1"
22
+ },
23
+ "dependencies": {
24
+ "diggerize": "^1.0.3",
25
+ "ejs": "^3.1.6",
26
+ "escape-string-regexp": "^1.0.5",
27
+ "inflection": "^1.13.2"
28
+ }
29
+ }
package/peak_flow.yml ADDED
@@ -0,0 +1,17 @@
1
+ before_script:
2
+ - cp spec/dummy/config/databases.peakflow.json spec/dummy/config/databases.json
3
+ - npm install
4
+ - wait-for-it mysql:3306
5
+ services:
6
+ mysql:
7
+ environment:
8
+ MYSQL_USER: peakflow
9
+ MYSQL_PASSWORD: password
10
+ MYSQL_ROOT_PASSWORD: password
11
+ MYSQL_DATABASE: velocious_test
12
+ image: mysql:8.0.22
13
+ expose:
14
+ - 3306
15
+ mem_limit: 2048m
16
+ script:
17
+ - npm test
@@ -0,0 +1,34 @@
1
+ const {Database: {Handler, Query}} = require("../../../../../index.cjs")
2
+ const MysqlQueryParser = require("../../../../../src/database/connection/drivers/mysql/query-parser.cjs")
3
+
4
+ const FromTable = require("../../../../../src/database/query/from-table.cjs")
5
+ const SelectTableAndColumn = require("../../../../../src/database/query/select-table-and-column.cjs")
6
+
7
+ describe("database - connection - drivers - mysql - query parser", () => {
8
+ it("generates sql with selects, joins and orders", () => {
9
+ const handler = new Handler()
10
+ const query = new Query({handler})
11
+ .select(["tasks.id", "tasks.name"])
12
+ .from("tasks")
13
+ .joins("LEFT JOIN projects ON projects.id = tasks.project_id")
14
+
15
+ const sql = new MysqlQueryParser({query}).toSql()
16
+
17
+ expect(sql).toEqual("SELECT tasks.id, tasks.name FROM tasks LEFT JOIN projects ON projects.id = tasks.project_id")
18
+ })
19
+
20
+ it("generates sql with selects, joins and orders", () => {
21
+ const handler = new Handler()
22
+ const query = new Query({handler})
23
+ .select([
24
+ new SelectTableAndColumn({tableName: "tasks", columnName: "id"}),
25
+ new SelectTableAndColumn({tableName: "tasks", columnName: "name"})
26
+ ])
27
+ .from(new FromTable({tableName: "tasks"}))
28
+ .joins("LEFT JOIN projects ON projects.id = tasks.project_id")
29
+
30
+ const sql = new MysqlQueryParser({query}).toSql()
31
+
32
+ expect(sql).toEqual("SELECT `tasks`.`id`, `tasks`.`name` FROM `tasks` LEFT JOIN projects ON projects.id = tasks.project_id")
33
+ })
34
+ })
@@ -0,0 +1,10 @@
1
+ {
2
+ "default": {
3
+ "master": {
4
+ "type": "mysql",
5
+ "host": "mysql",
6
+ "username": "username",
7
+ "password": "password"
8
+ }
9
+ }
10
+ }
File without changes
@@ -0,0 +1,11 @@
1
+ {
2
+ "default": {
3
+ "master": {
4
+ "type": "mysql",
5
+ "host": "mysql",
6
+ "username": "peakflow",
7
+ "password": "password",
8
+ "database": "velocious_test"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,40 @@
1
+ const {Application} = require("../../index.cjs")
2
+
3
+ module.exports = class Dummy {
4
+ static async run(callback) {
5
+ const dummy = new Dummy()
6
+
7
+ await dummy.run(callback)
8
+ }
9
+
10
+ async run(callback) {
11
+ await this.start()
12
+
13
+ try {
14
+ await callback()
15
+ } finally {
16
+ this.stop()
17
+ }
18
+ }
19
+
20
+ async start() {
21
+ this.application = new Application({
22
+ databases: {
23
+ default: {
24
+ host: "mysql",
25
+ username: "user",
26
+ password: ""
27
+ }
28
+ },
29
+ debug: false,
30
+ directory: __dirname,
31
+ httpServer: {port: 3006}
32
+ })
33
+
34
+ await this.application.start()
35
+ }
36
+
37
+ stop() {
38
+ this.application.stop()
39
+ }
40
+ }
@@ -0,0 +1,4 @@
1
+ const Record = require("../../../../src/database/record/index.cjs")
2
+
3
+ module.exports = class Task extends Record {
4
+ }
@@ -0,0 +1,18 @@
1
+ const Controller = require("../../../../../src/controller.cjs")
2
+ const {digg} = require("diggerize")
3
+ const Task = require("../../models/task.cjs")
4
+
5
+ module.exports = class TasksController extends Controller {
6
+ index() {
7
+ this.viewParams.numbers = [1, 2, 3, 4, 5]
8
+ this.render()
9
+ }
10
+
11
+ async show() {
12
+ const taskId = digg(params, "id")
13
+ const task = await Task.find(taskId)
14
+
15
+ this.viewParams.task = task
16
+ this.render()
17
+ }
18
+ }
@@ -0,0 +1 @@
1
+ <%= numbers.join(", ") %>
File without changes
@@ -0,0 +1,10 @@
1
+ const Routes = require("../../../src/routes/index.cjs")
2
+ const routes = new Routes()
3
+
4
+ routes.draw((route) => {
5
+ route.resources("tasks", (route) => {
6
+ route.get("users")
7
+ })
8
+ })
9
+
10
+ module.exports = {routes}
@@ -0,0 +1,35 @@
1
+ const Client = require("../../src/http-server/client/index.cjs")
2
+ const Configuration = require("../../src/configuration.cjs")
3
+ const {digg} = require("diggerize")
4
+ const path = require("path")
5
+
6
+ describe("http server - client", () => {
7
+ it("spawns a request for each that it is fed", () => {
8
+ const dummyDirectory = path.join(__dirname, "../dummy")
9
+ const configuration = new Configuration({
10
+ directory: dummyDirectory
11
+ })
12
+ const client = new Client({
13
+ clientCount: 0,
14
+ configuration
15
+ })
16
+
17
+ const strings = [
18
+ "GET /tasks",
19
+ " HTTP/1.1",
20
+ "\r\n",
21
+ "Host: www.example.com\r\n",
22
+ "\r\n"
23
+ ]
24
+
25
+ for (const string of strings) {
26
+ client.onWrite(Buffer.from(string, "utf-8"))
27
+ }
28
+
29
+ const currentRequest = digg(client, "currentRequest")
30
+
31
+ expect(currentRequest.httpMethod()).toBe("GET")
32
+ expect(currentRequest.host()).toBe("www.example.com")
33
+ expect(currentRequest.path()).toBe("/tasks")
34
+ })
35
+ })
@@ -0,0 +1,13 @@
1
+ const fetch = require("node-fetch")
2
+ const Dummy = require("../dummy/index.cjs")
3
+
4
+ describe("HttpServer", () => {
5
+ it("handles get requests", async () => {
6
+ await Dummy.run(async () => {
7
+ const response = await fetch("http://localhost:3006/tasks")
8
+ const text = await response.text()
9
+
10
+ expect(text).toEqual("1, 2, 3, 4, 5\n")
11
+ })
12
+ })
13
+ })
@@ -0,0 +1,11 @@
1
+ {
2
+ "spec_dir": "spec",
3
+ "spec_files": [
4
+ "**/*[sS]pec.cjs"
5
+ ],
6
+ "helpers": [
7
+ "helpers/**/*.cjs"
8
+ ],
9
+ "stopSpecOnExpectationFailure": false,
10
+ "random": false
11
+ }
@@ -0,0 +1,36 @@
1
+ const {digs} = require("diggerize")
2
+ const Configuration = require("./configuration.cjs")
3
+ const logger = require("./logger.cjs")
4
+ const HttpServer = require("./http-server/index.cjs")
5
+
6
+ module.exports = class VelociousApplication {
7
+ constructor({debug, directory, httpServer}) {
8
+ this.configuration = new Configuration({debug, directory})
9
+ this.httpServerConfiguration = httpServer ?? {}
10
+ }
11
+
12
+ async run(callback) {
13
+ await this.start()
14
+
15
+ try {
16
+ await callback()
17
+ } finally {
18
+ this.stop()
19
+ }
20
+ }
21
+
22
+ async start() {
23
+ const {configuration, httpServerConfiguration} = digs(this, "configuration", "httpServerConfiguration")
24
+ const port = httpServerConfiguration.port || 3006
25
+
26
+ logger(this, `Starting server on port ${port}`)
27
+
28
+ this.httpServer = new HttpServer({configuration, port})
29
+
30
+ await this.httpServer.start()
31
+ }
32
+
33
+ stop() {
34
+ this.httpServer.stop()
35
+ }
36
+ }
@@ -0,0 +1,14 @@
1
+ const Routes = require("./routes/index.cjs")
2
+
3
+ module.exports = class VelociousConfiguration {
4
+ constructor({debug, directory}) {
5
+ if (!directory) throw new Error("No directory given")
6
+
7
+ // Every client need to make their own routes because they probably can't be shared across different worker threads
8
+ const {routes} = require(`${directory}/src/routes.cjs`)
9
+
10
+ this.debug = debug
11
+ this.directory = directory
12
+ this.routes = routes
13
+ }
14
+ }
@@ -0,0 +1,50 @@
1
+ const {digg, digs} = require("diggerize")
2
+ const ejs = require("ejs")
3
+
4
+ module.exports = class VelociousController {
5
+ constructor({configuration, params, request, response}) {
6
+ if (!configuration) throw new Error("No configuration given")
7
+ if (!params) throw new Error("No params given")
8
+ if (!request) throw new Error("No request given")
9
+ if (!response) throw new Error("No response given")
10
+
11
+ this._configuration = configuration
12
+ this._params = params
13
+ this._request = request
14
+ this._response = response
15
+ this.viewParams = {}
16
+ }
17
+
18
+ render() {
19
+ return new Promise((resolve, reject) => {
20
+ const actionName = digg(this, "_params", "action")
21
+ const controllerName = digg(this, "_params", "controller")
22
+ const directory = digg(this, "_configuration", "directory")
23
+ const viewPath = `${directory}/src/routes/${controllerName}/${actionName}.ejs`
24
+ const {viewParams} = digs(this, "viewParams")
25
+
26
+ ejs.renderFile(viewPath, viewParams, {}, (err, str) => {
27
+ if (err) {
28
+ reject(err)
29
+ } else {
30
+ this._response.addHeader("Content-Type", "text/html")
31
+ this._response.setBody(str)
32
+
33
+ resolve()
34
+ }
35
+ })
36
+ })
37
+ }
38
+
39
+ renderText() {
40
+ throw new Error("renderText stub")
41
+ }
42
+
43
+ request() {
44
+ return this._request
45
+ }
46
+
47
+ response() {
48
+ return this._response
49
+ }
50
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = class VelociousDatabaseConnectionDriversMysql {
2
+ constructor(args) {
3
+ this.args = args
4
+ }
5
+ }
@@ -0,0 +1,7 @@
1
+ const QueryParserOptions = require("../../../query-parser/options.cjs")
2
+ const queryParserOptions = new QueryParserOptions({
3
+ columnQuote: "`",
4
+ tableQuote: "`"
5
+ })
6
+
7
+ module.exports = queryParserOptions
@@ -0,0 +1,26 @@
1
+ const {digs} = require("diggerize")
2
+ const FromParser = require("../../../query-parser/from-parser.cjs")
3
+ const JoinsParser = require("../../../query-parser/joins-parser.cjs")
4
+ const queryParserOptions = require("./options.cjs")
5
+ const SelectParser = require("../../../query-parser/select-parser.cjs")
6
+
7
+ module.exports = class VelociousDatabaseConnectionDriversMysqlQueryParser {
8
+ constructor({pretty, query}) {
9
+ if (!query) throw new Error("No query given")
10
+
11
+ this.pretty = pretty
12
+ this.query = query
13
+ }
14
+
15
+ toSql() {
16
+ const {pretty, query} = digs(this, "pretty", "query")
17
+
18
+ let sql = ""
19
+
20
+ sql += new SelectParser({pretty, query, queryParserOptions}).toSql()
21
+ sql += new FromParser({pretty, query, queryParserOptions}).toSql()
22
+ sql += new JoinsParser({pretty, query, queryParserOptions}).toSql()
23
+
24
+ return sql
25
+ }
26
+ }
@@ -0,0 +1,2 @@
1
+ module.exports = class VelociousDatabaseConnection {
2
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = class VelociousDatabaseHandler {
2
+ constructor() {
3
+ console.log("stub")
4
+ }
5
+ }
@@ -0,0 +1,9 @@
1
+ const Handler = require("./handler.cjs")
2
+ const Query = require("./query/index.cjs")
3
+ const Record = require("./record/index.cjs")
4
+
5
+ module.exports = {
6
+ Handler,
7
+ Query,
8
+ Record
9
+ }
@@ -0,0 +1,2 @@
1
+ module.exports = class VelociousDatabasePool {
2
+ }
@@ -0,0 +1,15 @@
1
+ module.exports = class VelociousDatabaseQueryFromBase {
2
+ getOptions() {
3
+ if (!this._options) throw new Error("Options hasn't been set")
4
+
5
+ return this._options
6
+ }
7
+
8
+ setOptions(options) {
9
+ this._options = options
10
+ }
11
+
12
+ toSql() {
13
+ throw new Error("'toSql' wasn't implemented")
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ const FromBase = require("./from-base.cjs")
2
+
3
+ module.exports = class VelociousDatabaseQueryFromPlain extends FromBase {
4
+ constructor({plain}) {
5
+ super()
6
+ this.plain = plain
7
+ }
8
+
9
+ toSql() {
10
+ return this.plain
11
+ }
12
+ }
@@ -0,0 +1,12 @@
1
+ const FromBase = require("./from-base.cjs")
2
+
3
+ module.exports = class VelociousDatabaseQueryFromTable extends FromBase {
4
+ constructor({tableName}) {
5
+ super()
6
+ this.tableName = tableName
7
+ }
8
+
9
+ toSql() {
10
+ return this.getOptions().quoteTableName(this.tableName)
11
+ }
12
+ }
@@ -0,0 +1,59 @@
1
+ const FromPlain = require("./from-plain.cjs")
2
+ const JoinPlain = require("./join-plain.cjs")
3
+ const SelectPlain = require("./select-plain.cjs")
4
+
5
+ module.exports = class VelociousDatabaseQuery {
6
+ constructor({handler}) {
7
+ if (!handler) throw new Error("No handler given")
8
+
9
+ this._froms = []
10
+ this._joins = []
11
+ this._orders = []
12
+ this._selects = []
13
+ }
14
+
15
+ getOptions() {
16
+ if (!this._options) throw new Error("Options not set")
17
+ return this._options
18
+ }
19
+
20
+ from(from) {
21
+ if (typeof from == "string") from = new FromPlain({plain: from})
22
+
23
+ this._froms.push(from)
24
+ return this
25
+ }
26
+
27
+ joins(join) {
28
+ if (typeof join == "string") join = new JoinPlain({plain: join})
29
+
30
+ this._joins.push(join)
31
+ return this
32
+ }
33
+
34
+ order(order) {
35
+ if (typeof order == "string") order = new OrderPlain({plain: order})
36
+
37
+ this._orders.push(order)
38
+ return this
39
+ }
40
+
41
+ select(select) {
42
+ if (Array.isArray(select)) {
43
+ for (const selectInArray of select) {
44
+ this.select(selectInArray)
45
+ }
46
+
47
+ return this
48
+ }
49
+
50
+ if (typeof select == "string") select = new SelectPlain({plain: select})
51
+
52
+ this._selects.push(select)
53
+ return this
54
+ }
55
+
56
+ toSql() {
57
+ throw new Error("stub")
58
+ }
59
+ }
@@ -0,0 +1,15 @@
1
+ module.exports = class VelociousDatabaseQueryJoinBase {
2
+ getOptions() {
3
+ if (!this._options) throw new Error("Options hasn't been set")
4
+
5
+ return this._options
6
+ }
7
+
8
+ setOptions(options) {
9
+ this._options = options
10
+ }
11
+
12
+ toSql() {
13
+ throw new Error("'toSql' wasn't implemented")
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ const JoinBase = require("./join-base.cjs")
2
+
3
+ module.exports = class VelociousDatabaseQueryJoinPlain extends JoinBase {
4
+ constructor({plain}) {
5
+ super()
6
+ this.plain = plain
7
+ }
8
+
9
+ toSql() {
10
+ return this.plain
11
+ }
12
+ }
@@ -0,0 +1,15 @@
1
+ module.exports = class VelociousDatabaseQuerySelectBase {
2
+ getOptions() {
3
+ if (!this._options) throw new Error("Options hasn't been set")
4
+
5
+ return this._options
6
+ }
7
+
8
+ setOptions(options) {
9
+ this._options = options
10
+ }
11
+
12
+ toSql() {
13
+ throw new Error("'toSql' wasn't implemented")
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ const SelectBase = require("./select-base.cjs")
2
+
3
+ module.exports = class VelociousDatabaseQuerySelectPlain extends SelectBase {
4
+ constructor({plain}) {
5
+ super()
6
+ this.plain = plain
7
+ }
8
+
9
+ toSql() {
10
+ return this.plain
11
+ }
12
+ }
@@ -0,0 +1,21 @@
1
+ const SelectBase = require("./select-base.cjs")
2
+
3
+ module.exports = class VelociousDatabaseQuerySelectTableAndColumn extends SelectBase {
4
+ constructor({tableName, columnName}) {
5
+ super()
6
+ this.columnName = columnName
7
+ this.tableName = tableName
8
+ }
9
+
10
+ getColumnName() {
11
+ return this.columnName
12
+ }
13
+
14
+ getTableName() {
15
+ return this.tableName
16
+ }
17
+
18
+ toSql() {
19
+ return `${this.getOptions().quoteTableName(this.tableName)}.${this.getOptions().quoteColumnName(this.columnName)}`
20
+ }
21
+ }