-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
197 lines (180 loc) · 5.74 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
'use strict'
const { isEqual, isEmpty, some, sortBy } = require('lodash/fp')
const Table = require('./src/table')
/**
* @typicalname db
* @class TinyJsDb
* @classdesc Main tiny-js-db database controller
* @param {object} [opts] - Database configurations
* @param {boolean} [opts.autoGenerateIds=true] - Set if ids will be generated automatically
* @description
* Creates a new database instance and provide functions to manage the database.
* @example
* const TinyJsDb = require('tiny-js-db')
* const db = new TinyJsDb()
*/
class TinyJsDb {
constructor (opts = {}) {
this._autoGenerateIds = opts.autoGenerateIds || true
this._tables = new Map()
this._relationships = []
}
get autoGenerateIds () {
return this._autoGenerateIds
}
set autoGenerateIds (value) {
throw new Error(
'the autoGenerateIds configuration can be set only during initialization'
)
}
/**
* Return all tables name from the database
*
* @return {string[]} array of strings containing the tables name
* @example
* const tables = db.tables
* console.log(tables)
* // ['cars','countries']
*/
get tables () {
return [...this._tables.keys()]
}
/**
* Return the relationships from the database
*
* @return { Array[]} array of tables instance pairs for each relationship on database
* @example
* const relationships = db.relationships
* console.log(relationships)
* // [
* // [ table1, table2 ],
* // [ table1, table3 ]
* // ]
*/
get relationships () {
return [...this._relationships]
}
/**
* Creates a new table on database
*
* @param {string} name - name of the table
* @return {object} table instance
* @example
* db.createTable('cars')
* // if you want the new table instance
* const cars = db.createTable('cars')
*/
createTable (name) {
if (this.tableExists(name)) {
throw new Error(`The table <${name}> already exists`)
}
const newTable = new Table(this, name)
this._tables.set(name, newTable)
return newTable
}
/**
* Return a table instance
*
* @param {string|object} table - An string containing the table name or an instance of a Table
* @return {object} table instance
* @example
* const cars db.getTable('cars')
*/
getTable (table) {
const tableName = typeof table === 'object' ? table.name : table
const tableRef = this._tables.get(tableName)
if (!tableRef) {
throw new Error(`Table ${tableName} does not exist`)
}
return tableRef
}
/**
* Check if a table exists in the database
*
* @param {string} name - An string containing the table name
* @return {boolean} true if the table exists and false if not
* @example
* if(db.tableExists('cars')){}
*/
tableExists (name) {
return this._tables.has(name)
}
/**
* Create a relationship between two tables
* - The order of the tables are not important
* - If you try to create a relationship that already exists, an error will throw
*
* @param {string|object} tableA - An string containing the table name or an instance of a Table
* @param {string|object} tableB - An string containing the table name or an instance of a Table
* @return {object} The created relationship
* @example
* db.createRelationship('cars', 'countries')
* // or
* db.createRelationship(cars, 'countries')
* // or
* db.createRelationship(cars, countries)
* // or
* const newRelation = db.createRelationship(cars, countries)
*/
createRelationship (tableA, tableB) {
const tableARef = this.getTable(tableA)
const tableBRef = this.getTable(tableB)
const newRelationship = sortBy('name', [tableARef, tableBRef])
this._checkRelationshipDuplication(newRelationship)
this._relationships.push(newRelationship)
return newRelationship
}
_checkRelationshipDuplication (relationship) {
if (some(isEqual(relationship), this._relationships)) {
throw new Error(
`A relationship between tables <${relationship[0].name}> and <${relationship[1].name}> already exists`
)
}
}
/**
* Get a relationship
* - The order of the tables are not important
*
* @param {string|object} tableA - An string containing the table name or an instance of a Table
* @param {string|object} tableB - An string containing the table name or an instance of a Table
* @return {object} The relationship
* @example
* const relation = db.getRelationship('cars', 'countries')
* // or
* const relation = db.getRelationship('countries', 'cars')
* // or
* const relation = db.getRelationship(cars, 'countries')
* // or
* const relation = db.getRelationship(cars, countries)
*/
getRelationship (tableA, tableB) {
const tableARef = this.getTable(tableA)
const tableBRef = this.getTable(tableB)
const relationship = sortBy('name', [tableARef, tableBRef])
return this._relationships.find(
it =>
it[0].name === relationship[0].name &&
it[1].name === relationship[1].name
)
}
/**
* Check if a relationship between two tables exist
* - The order of the tables are not important
*
* @param {string|object} tableA - An string containing the table name or an instance of a Table
* @param {string|object} tableB - An string containing the table name or an instance of a Table
* @return {boolean} true if the relationship exists and false if not
* @example
* if(db.relationshipExists('cars','countries')){}
* // or
* if(db.relationshipExists('countries', 'cars')){}
* // or
* if(db.relationshipExists(cars,'countries')){}
* // or
* if(db.relationshipExists(cars,countries)){}
*/
relationshipExists (tableA, tableB) {
return !isEmpty(this.getRelationship(tableA, tableB))
}
}
module.exports = TinyJsDb