velocious 1.0.4 → 1.0.5

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/index.mjs CHANGED
@@ -1,19 +1 @@
1
- import Application from "./src/application.mjs"
2
- import Cli from "./src/cli/index.mjs"
3
- import Configuration from "./src/configuration.mjs"
4
- import Controller from "./src/controller.mjs"
5
- import Database from "./src/database/index.mjs"
6
- import HttpServer from "./src/http-server/index.mjs"
7
- import Routes from "./src/routes/index.mjs"
8
- import Spec from "./src/spec/index.mjs"
9
-
10
- export {
11
- Application,
12
- Cli,
13
- Configuration,
14
- Controller,
15
- Database,
16
- HttpServer,
17
- Routes,
18
- Spec
19
- }
1
+ export {}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "velocious": "bin/velocious.mjs"
4
4
  },
5
5
  "name": "velocious",
6
- "version": "1.0.4",
6
+ "version": "1.0.5",
7
7
  "main": "index.mjs",
8
8
  "scripts": {
9
9
  "test": "jasmine",
@@ -32,6 +32,7 @@
32
32
  "escape-string-regexp": "^1.0.5",
33
33
  "incorporator": "^1.0.2",
34
34
  "inflection": "^3.0.0",
35
+ "sql-escape-string": "^1.1.0",
35
36
  "sql.js": "^1.12.0",
36
37
  "strftime": "^0.10.2"
37
38
  }
@@ -1,4 +1,5 @@
1
- import Database from "../../../../../src/database/index.mjs"
1
+ import DatabaseHandler from "../../../../../src/database/handler.mjs"
2
+ import DatabaseQuery from "../../../../../src/database/query/index.mjs"
2
3
  import MysqlQueryParser from "../../../../../src/database/drivers/mysql/query-parser.mjs"
3
4
 
4
5
  import FromTable from "../../../../../src/database/query/from-table.mjs"
@@ -10,8 +11,8 @@ const mysqlDriver = new MysqlDriverClass()
10
11
 
11
12
  describe("database - connection - drivers - mysql - query parser", () => {
12
13
  it("generates sql with selects, joins and orders", () => {
13
- const handler = new Database.Handler()
14
- const query = new Database.Query({driver: mysqlDriver, handler})
14
+ const handler = new DatabaseHandler()
15
+ const query = new DatabaseQuery({driver: mysqlDriver, handler})
15
16
  .select(["tasks.id", "tasks.name"])
16
17
  .from("tasks")
17
18
  .joins("LEFT JOIN projects ON projects.id = tasks.project_id")
@@ -22,8 +23,8 @@ describe("database - connection - drivers - mysql - query parser", () => {
22
23
  })
23
24
 
24
25
  it("generates sql with selects, joins and orders", () => {
25
- const handler = new Database.Handler()
26
- const query = new Database.Query({driver: mysqlDriver, handler})
26
+ const handler = new DatabaseHandler()
27
+ const query = new DatabaseQuery({driver: mysqlDriver, handler})
27
28
  .select([
28
29
  new SelectTableAndColumn({tableName: "tasks", columnName: "id"}),
29
30
  new SelectTableAndColumn({tableName: "tasks", columnName: "name"})
@@ -1,13 +1,12 @@
1
- import Database from "../../../../src/database/index.mjs"
1
+ import DatabaseDriversMysql from "../../../../src/database/drivers/mysql/index.mjs"
2
2
  import configuration from "../../../dummy/src/config/configuration.mjs"
3
3
  import {digg} from "diggerize"
4
4
 
5
5
  const mysqlConfig = digg(configuration, "database", "default", "master")
6
- const Mysql = Database.Drivers.Mysql
7
6
 
8
7
  describe("Database - Drivers - Mysql - Connection", () => {
9
8
  it("connects", async () => {
10
- const mysql = new Mysql(mysqlConfig)
9
+ const mysql = new DatabaseDriversMysql(mysqlConfig)
11
10
 
12
11
  await mysql.connect()
13
12
 
@@ -1,4 +1,4 @@
1
- import Database from "../../../../src/database/index.mjs"
1
+ import DatabaseRecord from "../../../../src/database/record/index.mjs"
2
2
 
3
- export default class Task extends Database.Record {
3
+ export default class Task extends DatabaseRecord {
4
4
  }
@@ -1,8 +1,23 @@
1
+ import Query from "../query/index.mjs"
2
+ import Handler from "../handler.mjs"
3
+
1
4
  export default class VelociousDatabaseDriversBase {
2
5
  constructor(args) {
3
6
  this._args = args
4
7
  }
5
8
 
9
+ async createTable(...args) {
10
+ const sql = this.createTableSql(...args)
11
+
12
+ await this.query(sql)
13
+ }
14
+
15
+ async delete(...args) {
16
+ const sql = this.deleteSql(...args)
17
+
18
+ await this.query(sql)
19
+ }
20
+
6
21
  getArgs() {
7
22
  return this._args
8
23
  }
@@ -11,7 +26,33 @@ export default class VelociousDatabaseDriversBase {
11
26
  return this.idSeq
12
27
  }
13
28
 
29
+ async insert(...args) {
30
+ const sql = this.insertSql(...args)
31
+
32
+ await this.query(sql)
33
+ }
34
+
35
+ async select(tableName) {
36
+ const handler = new Handler()
37
+ const query = new Query({
38
+ driver: this,
39
+ handler
40
+ })
41
+
42
+ const sql = query
43
+ .from(tableName)
44
+ .toSql()
45
+
46
+ return await this.query(sql)
47
+ }
48
+
14
49
  setIdSeq(id) {
15
50
  this.idSeq = id
16
51
  }
52
+
53
+ async update(...args) {
54
+ const sql = this.updateSql(...args)
55
+
56
+ await this.query(sql)
57
+ }
17
58
  }
@@ -0,0 +1,36 @@
1
+ import Base from "../base.mjs"
2
+ import CreateTable from "../sqlite/sql/create-table.mjs"
3
+ import Delete from "../sqlite/sql/delete.mjs"
4
+ import Insert from "../sqlite/sql/insert.mjs"
5
+ import QueryParser from "../sqlite/query-parser.mjs"
6
+ import Table from "./table"
7
+ import Update from "../sqlite/sql/update.mjs"
8
+
9
+ export default class VelociousDatabaseDriversSqliteBase extends Base {
10
+ createTableSql(tableData) {
11
+ const createArgs = Object.assign({tableData, driver: this})
12
+ const createTable = new CreateTable(createArgs)
13
+
14
+ return createTable.toSql()
15
+ }
16
+
17
+ deleteSql = ({tableName, conditions}) => new Delete({conditions, driver: this, tableName}).toSql()
18
+ insertSql = ({tableName, data}) => new Insert({driver: this, tableName, data}).toSql()
19
+
20
+ async getTables() {
21
+ const result = await this.query("SELECT name FROM sqlite_master WHERE type = 'table'")
22
+ const tables = []
23
+
24
+ for (const row of result) {
25
+ const table = new Table(row)
26
+
27
+ tables.push(table)
28
+ }
29
+
30
+ return tables
31
+ }
32
+
33
+ queryToSql = (query) => new QueryParser({query}).toSql()
34
+ quoteColumn = (string) => `\`${string}\``
35
+ updateSql = ({conditions, data, tableName}) => new Update({conditions, data, driver: this, tableName}).toSql()
36
+ }
@@ -1,17 +1,13 @@
1
- import Base from "../base.mjs"
2
- import CreateTable from "../sqlite/sql/create-table.mjs"
3
- import Delete from "../sqlite/sql/delete.mjs"
1
+ import Base from "./base"
4
2
  import {digg} from "diggerize"
5
- import Insert from "../sqlite/sql/insert.mjs"
3
+ import escapeString from "sql-string-escape"
6
4
  import Options from "../sqlite/options.mjs"
7
- import query from "./query.mjs"
8
- import QueryParser from "../sqlite/query-parser.mjs"
5
+ import query from "./query"
9
6
  import * as SQLite from "expo-sqlite"
10
- import Update from "../sqlite/sql/update.mjs"
11
7
 
12
- export default class VelociousDatabaseDriversSqliteNative extends Base{
8
+ export default class VelociousDatabaseDriversSqliteNative extends Base {
13
9
  async connect() {
14
- const connection = await SQLite.openDatabaseAsync(digg(this.connectArgs(), "name"))
10
+ const connection = await SQLite.openDatabaseAsync(digg(this.getArgs(), "name"))
15
11
 
16
12
  this.connection = connection
17
13
  }
@@ -39,54 +35,20 @@ export default class VelociousDatabaseDriversSqliteNative extends Base{
39
35
  this.connection = undefined
40
36
  }
41
37
 
42
- createTableSql(tableData) {
43
- const createArgs = Object.assign({tableData, driver: this})
44
- const createTable = new CreateTable(createArgs)
45
-
46
- return createTable.toSql()
47
- }
48
-
49
- async query(sql) {
50
- return await query(this.connection, sql)
51
- }
52
-
53
- queryToSql(query) {
54
- return new QueryParser({query}).toSql()
55
- }
38
+ query = async (sql) => await query(this.connection, sql)
56
39
 
57
40
  quote(string) {
58
- if (!this.connection) throw new Error("Can't escape before connected")
41
+ const type = typeof string
59
42
 
60
- return this.connection.escape(string)
61
- }
43
+ if (type == "number") return string
44
+ if (type != "string") string = `${string}`
62
45
 
63
- quoteColumn(string) {
64
- return `\`${string}\``
65
- }
66
-
67
- deleteSql({tableName, conditions}) {
68
- const deleteInstruction = new Delete({conditions, driver: this, tableName})
69
-
70
- return deleteInstruction.toSql()
71
- }
72
-
73
- insertSql({tableName, data}) {
74
- const insert = new Insert({driver: this, tableName, data})
75
-
76
- return insert.toSql()
46
+ return escapeString(string)
77
47
  }
78
48
 
79
49
  options() {
80
- if (!this._options) {
81
- this._options = new Options({driver: this})
82
- }
50
+ if (!this._options) this._options = new Options({driver: this})
83
51
 
84
52
  return this._options
85
53
  }
86
-
87
- updateSql({conditions, data, tableName}) {
88
- const update = new Update({conditions, data, driver: this, tableName})
89
-
90
- return update.toSql()
91
- }
92
54
  }
@@ -1,16 +1,11 @@
1
- import Base from "../base.mjs"
2
- import CreateTable from "../sqlite/sql/create-table.mjs"
3
- import Delete from "../sqlite/sql/delete.mjs"
1
+ import Base from "./base.mjs"
4
2
  import {digg} from "diggerize"
5
- import Insert from "../sqlite/sql/insert.mjs"
6
3
  import Options from "../sqlite/options.mjs"
7
4
  import query from "./query"
8
- import QueryParser from "../sqlite/query-parser.mjs"
9
- import Update from "../sqlite/sql/update.mjs"
10
5
 
11
6
  import initSqlJs from "sql.js"
12
7
 
13
- export default class VelociousDatabaseDriversSqliteWeb extends Base{
8
+ export default class VelociousDatabaseDriversSqliteWeb extends Base {
14
9
  async connect() {
15
10
  const SQL = await initSqlJs({
16
11
  // Required to load the wasm binary asynchronously. Of course, you can host it wherever you want you can omit locateFile completely when running in Node.
@@ -32,15 +27,7 @@ export default class VelociousDatabaseDriversSqliteWeb extends Base{
32
27
  this.connection = undefined
33
28
  }
34
29
 
35
- createTableSql(tableData) {
36
- const createArgs = Object.assign({tableData, driver: this})
37
- const createTable = new CreateTable(createArgs)
38
-
39
- return createTable.toSql()
40
- }
41
-
42
30
  query = async (sql) => await query(this.connection, sql)
43
- queryToSql = (query) => new QueryParser({query}).toSql()
44
31
 
45
32
  quote(string) {
46
33
  if (!this.connection) throw new Error("Can't escape before connected")
@@ -48,10 +35,6 @@ export default class VelociousDatabaseDriversSqliteWeb extends Base{
48
35
  return this.connection.escape(string)
49
36
  }
50
37
 
51
- quoteColumn = (string) => `\`${string}\``
52
- deleteSql = ({tableName, conditions}) => new Delete({conditions, driver: this, tableName}).toSql()
53
- insertSql = ({tableName, data}) => new Insert({driver: this, tableName, data}).toSql()
54
-
55
38
  options() {
56
39
  if (!this._options) {
57
40
  this._options = new Options({driver: this})
@@ -59,6 +42,4 @@ export default class VelociousDatabaseDriversSqliteWeb extends Base{
59
42
 
60
43
  return this._options
61
44
  }
62
-
63
- updateSql = ({conditions, data, tableName}) => new Update({conditions, data, driver: this, tableName}).toSql()
64
45
  }
@@ -0,0 +1,9 @@
1
+ import {digg} from "diggerize"
2
+
3
+ export default class VelociousDatabaseDriversSqliteTable {
4
+ constructor(row) {
5
+ this.row = row
6
+ }
7
+
8
+ getName = () => digg(this, "row", "name")
9
+ }
@@ -1,5 +1,6 @@
1
1
  import Configuration from "../configuration.mjs"
2
2
  import * as inflection from "inflection"
3
+ import Migrator from "./migrator"
3
4
 
4
5
  export default class VelociousDatabaseMigrateFromRequireContext {
5
6
  constructor(configuration) {
@@ -7,6 +8,10 @@ export default class VelociousDatabaseMigrateFromRequireContext {
7
8
  }
8
9
 
9
10
  async execute(requireContext) {
11
+ const migrator = new Migrator({configuration: this.configuration})
12
+
13
+ await migrator.prepare()
14
+
10
15
  const files = requireContext.keys()
11
16
  .map((file) => {
12
17
  const match = file.match(/^\.\/(\d{14})-(.+)\.mjs$/)
@@ -27,7 +32,9 @@ export default class VelociousDatabaseMigrateFromRequireContext {
27
32
  .sort((migration1, migration2) => migration1.date - migration2.date)
28
33
 
29
34
  for (const migration of files) {
30
- await this.runMigrationFile(migration, requireContext)
35
+ if (!migrator.hasRunMigrationVersion(migration.date)) {
36
+ await this.runMigrationFile(migration, requireContext)
37
+ }
31
38
  }
32
39
  }
33
40
 
@@ -35,7 +42,7 @@ export default class VelociousDatabaseMigrateFromRequireContext {
35
42
  if (!this.configuration) throw new Error("No configuration set")
36
43
  if (!this.configuration.isDatabasePoolInitialized()) await this.configuration.initializeDatabasePool()
37
44
 
38
- await this.configuration.getDatabasePool().withConnection(async () => {
45
+ await this.configuration.getDatabasePool().withConnection(async (db) => {
39
46
  const MigrationClass = requireContext(migration.file).default
40
47
  const migrationInstance = new MigrationClass({
41
48
  configuration: this.configuration
@@ -48,6 +55,8 @@ export default class VelociousDatabaseMigrateFromRequireContext {
48
55
  } else {
49
56
  throw new Error(`'change' or 'up' didn't exist on migration: ${migration.file}`)
50
57
  }
58
+
59
+ await db.insert({tableName: "schema_migrations", data: {version: migration.date}})
51
60
  })
52
61
  }
53
62
  }
@@ -0,0 +1,73 @@
1
+ import {digg} from "diggerize"
2
+ import TableData from "./table-data/index"
3
+
4
+ export default class VelociousDatabaseMigrator {
5
+ constructor({configuration}) {
6
+ this.configuration = configuration
7
+ }
8
+
9
+ async prepare() {
10
+ const exists = await this.migrationsTableExist()
11
+
12
+ if (!exists) await this.createMigrationsTable()
13
+
14
+ await this.loadMigrationsVersions()
15
+ }
16
+
17
+ async createMigrationsTable() {
18
+ const schemaMigrationsTable = new TableData("schema_migrations", {ifNotExists: true})
19
+
20
+ schemaMigrationsTable.string("version", {null: false, primaryKey: true})
21
+
22
+ await this.configuration.getDatabasePool().withConnection(async (db) => {
23
+ const createSchemaMigrationsTableSql = db.createTableSql(schemaMigrationsTable)
24
+
25
+ await db.query(createSchemaMigrationsTableSql)
26
+ })
27
+ }
28
+
29
+ hasRunMigrationVersion(version) {
30
+ if (!this.migrationsVersions) {
31
+ throw new Error("Migrations versions hasn't been loaded yet")
32
+ }
33
+
34
+ if (version in this.migrationsVersions) {
35
+ return true
36
+ }
37
+
38
+ return false
39
+ }
40
+
41
+ async loadMigrationsVersions() {
42
+ const db = this.configuration.getDatabasePool()
43
+
44
+ this.migrationsVersions = {}
45
+
46
+ await db.withConnection(async () => {
47
+ const rows = await db.select("schema_migrations")
48
+
49
+ for (const row of rows) {
50
+ const version = digg(row, "version")
51
+
52
+ this.migrationsVersions[version] = true
53
+ }
54
+ })
55
+ }
56
+
57
+ async migrationsTableExist() {
58
+ let exists = false
59
+
60
+ await this.configuration.getDatabasePool().withConnection(async (db) => {
61
+ const tables = await db.getTables()
62
+
63
+ for (const table of tables) {
64
+ if (table.getName() == "schema_migrations") {
65
+ exists = true
66
+ break
67
+ }
68
+ }
69
+ })
70
+
71
+ return exists
72
+ }
73
+ }
@@ -58,7 +58,7 @@ export default class VelociousDatabasePoolAsyncTrackedMultiConnection extends Ba
58
58
 
59
59
  await this.asyncLocalStorage.run(id, async () => {
60
60
  try {
61
- await callback()
61
+ await callback(connection)
62
62
  } finally {
63
63
  this.checkin(connection)
64
64
  }
@@ -34,7 +34,20 @@ class VelociousDatabasePoolBase {
34
34
  }
35
35
  }
36
36
 
37
- const forwardMethods = ["createTableSql", "deleteSql", "insertSql", "query", "quote", "updateSql"]
37
+ const forwardMethods = [
38
+ "createTable",
39
+ "createTableSql",
40
+ "delete",
41
+ "deleteSql",
42
+ "getTables",
43
+ "insert",
44
+ "insertSql",
45
+ "query",
46
+ "quote",
47
+ "select",
48
+ "update",
49
+ "updateSql"
50
+ ]
38
51
 
39
52
  for (const forwardMethod of forwardMethods) {
40
53
  VelociousDatabasePoolBase.prototype[forwardMethod] = function(...args) {
@@ -27,7 +27,7 @@ export default class VelociousDatabasePoolSingleMultiUser extends BasePool {
27
27
 
28
28
  async withConnection(callback) {
29
29
  await this.checkout() // Ensure a connection is present
30
- await callback()
30
+ await callback(this.connection)
31
31
  }
32
32
 
33
33
  getCurrentConnection() {
@@ -1,5 +1,9 @@
1
1
  export default class VelociousDatabaseQueryInsertBase {
2
2
  constructor({driver, tableName, data}) {
3
+ if (!driver) throw new Error("No driver given to insert base")
4
+ if (!tableName) throw new Error(`Invalid table name given to insert base: ${tableName}`)
5
+ if (!data) throw new Error("No data given to insert base")
6
+
3
7
  this.data = data
4
8
  this.driver = driver
5
9
  this.tableName = tableName
@@ -11,13 +11,13 @@ export default class VelociousDatabaseQueryParserOptions {
11
11
  }
12
12
 
13
13
  quoteColumnName(columnName) {
14
- if (columnName.includes(this.columnQuote)) throw new Error(`Invalid column name: ${columnName}`)
14
+ if (!columnName || columnName.includes(this.columnQuote)) throw new Error(`Invalid column name: ${columnName}`)
15
15
 
16
16
  return `${this.columnQuote}${columnName}${this.columnQuote}`
17
17
  }
18
18
 
19
19
  quoteTableName(tableName) {
20
- if (tableName.includes(this.tableQuote)) throw new Error(`Invalid table name: ${tableName}`)
20
+ if (!tableName || tableName.includes(this.tableQuote)) throw new Error(`Invalid table name: ${tableName}`)
21
21
 
22
22
  return `${this.tableQuote}${tableName}${this.tableQuote}`
23
23
  }
@@ -1,5 +0,0 @@
1
- import Mysql from "../drivers/mysql/index.mjs"
2
-
3
- export default {
4
- Mysql
5
- }
@@ -1,15 +0,0 @@
1
- import Drivers from "./drivers/index.mjs"
2
- import Handler from "./handler.mjs"
3
- import Migration from "./migration/index.mjs"
4
- import Migrator from "./migrator/index.mjs"
5
- import Query from "./query/index.mjs"
6
- import Record from "./record/index.mjs"
7
-
8
- export default {
9
- Drivers,
10
- Handler,
11
- Migration,
12
- Migrator,
13
- Query,
14
- Record
15
- }
@@ -1,15 +0,0 @@
1
- export default class VelociousDatabaseMigrator {
2
- constructor({path}) {
3
- if (!path) throw new Error("No 'path' given")
4
-
5
- this.path = path
6
- }
7
-
8
- migrateUp() {
9
- throw new Error("stub")
10
- }
11
-
12
- migrateDown() {
13
- throw new Error("stub")
14
- }
15
- }