@iamkirbki/database-handler-core 3.1.2 → 3.1.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../src/Database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAEhE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAEjC;;;;;;;;;;;;;;;;OAgBG;gBACS,OAAO,EAAE,gBAAgB;IAIrC;;;;;;;;;;;;OAYG;IACU,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAMhD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAsBvE;;;;;;;;;;;;;;OAcG;IACI,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK;CAGjD"}
1
+ {"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../src/Database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAEhE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAEjC;;;;;;;;;;;;;;;;OAgBG;gBACS,OAAO,EAAE,gBAAgB;IAIrC;;;;;;;;;;;;OAYG;IACU,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAKhD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAmBvE;;;;;;;;;;;;;;OAcG;IACI,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK;CAGjD"}
package/dist/Database.js CHANGED
@@ -62,7 +62,6 @@ export default class Database {
62
62
  */
63
63
  Table(name) {
64
64
  return __awaiter(this, void 0, void 0, function* () {
65
- // Validator.ValidateTableName(name);
66
65
  return yield Table.create(name, this.adapter);
67
66
  });
68
67
  }
@@ -94,14 +93,11 @@ export default class Database {
94
93
  */
95
94
  CreateTable(name, columns) {
96
95
  return __awaiter(this, void 0, void 0, function* () {
97
- // Validator.ValidateTableName(name);
98
96
  const names = Object.keys(columns || {}).map((colName) => {
99
- // Validator.ValidateColumnName(colName);
100
97
  return colName;
101
98
  });
102
99
  const colsDef = names.map(colName => {
103
100
  const colType = columns[colName];
104
- // Validator.ValidateColumnType(colType);
105
101
  return `"${colName}" ${colType}`;
106
102
  }).join(", ");
107
103
  const stmt = yield this.adapter.prepare(`CREATE TABLE IF NOT EXISTS "${name}" (${colsDef});`);
package/dist/Query.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import Table from "./Table.js";
2
- import { QueryParameters } from "./types/index.js";
2
+ import { QueryCondition } from "./types/index.js";
3
3
  import Record from "./Record.js";
4
4
  import IDatabaseAdapter from "./interfaces/IDatabaseAdapter.js";
5
5
  /**
@@ -35,7 +35,9 @@ export default class Query {
35
35
  readonly Table: Table;
36
36
  private readonly adapter;
37
37
  private query;
38
- Parameters: QueryParameters;
38
+ private _parameters;
39
+ get Parameters(): QueryCondition;
40
+ set Parameters(value: QueryCondition);
39
41
  /**
40
42
  * Creates a Query instance (usually called via db.Query() method)
41
43
  *
@@ -108,6 +110,8 @@ export default class Query {
108
110
  * ```
109
111
  */
110
112
  All<Type>(): Promise<Record<Type>[]>;
113
+ private convertParamsToObject;
114
+ private convertIdToString;
111
115
  /**
112
116
  * Execute a SELECT query and return the first matching row as a Record object
113
117
  * Returns undefined if no rows match the query
@@ -134,6 +138,6 @@ export default class Query {
134
138
  * ```
135
139
  */
136
140
  Get<Type>(): Promise<Record<Type> | undefined>;
137
- Transaction(paramList: QueryParameters[]): Promise<void>;
141
+ Transaction(paramList: QueryCondition[]): Promise<void>;
138
142
  }
139
143
  //# sourceMappingURL=Query.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../src/Query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,OAAO,OAAO,KAAK;IACxB,SAAgB,KAAK,EAAE,KAAK,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,KAAK,CAAc;IACpB,UAAU,EAAE,eAAe,CAAM;IAExC;;;;;;;;;;;;;;;;;;;;;OAqBG;gBACS,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB;IAMlE;;;;;;;;;;;;;;;;;;;;OAoBG;IACU,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC;IAKvC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACU,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IAajD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAM9C,WAAW,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAiBtE"}
1
+ {"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../src/Query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAwB,MAAM,kBAAkB,CAAC;AACxE,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,OAAO,OAAO,KAAK;IACxB,SAAgB,KAAK,EAAE,KAAK,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,WAAW,CAAsB;IAEzC,IAAW,UAAU,IAAI,cAAc,CAEtC;IAED,IAAW,UAAU,CAAC,KAAK,EAAE,cAAc,EAE1C;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;gBACS,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB;IAMlE;;;;;;;;;;;;;;;;;;;;OAoBG;IACU,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC;IAKvC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACU,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IAMjD,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,iBAAiB;IAQzB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAM9C,WAAW,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAiBrE"}
package/dist/Query.js CHANGED
@@ -38,6 +38,12 @@ import Record from "./Record.js";
38
38
  * ```
39
39
  */
40
40
  export default class Query {
41
+ get Parameters() {
42
+ return this._parameters;
43
+ }
44
+ set Parameters(value) {
45
+ this._parameters = this.convertParamsToObject(value);
46
+ }
41
47
  /**
42
48
  * Creates a Query instance (usually called via db.Query() method)
43
49
  *
@@ -62,7 +68,7 @@ export default class Query {
62
68
  */
63
69
  constructor(Table, Query, adapter) {
64
70
  this.query = "";
65
- this.Parameters = {};
71
+ this._parameters = {};
66
72
  this.Table = Table;
67
73
  this.query = Query;
68
74
  this.adapter = adapter;
@@ -123,15 +129,28 @@ export default class Query {
123
129
  All() {
124
130
  return __awaiter(this, void 0, void 0, function* () {
125
131
  const stmt = yield this.adapter.prepare(this.query);
126
- let results = yield stmt.all(this.Parameters);
127
- // This is a fix for a bug where id's passed as numbers don't match string ids in the db
128
- if (results.length === 0 && this.Parameters.id) {
129
- this.Parameters.id = this.Parameters.id.toString();
130
- results = (yield stmt.all(this.Parameters));
131
- }
132
+ const results = yield stmt.all(this.Parameters);
132
133
  return results.map(res => new Record(res, this.adapter, this.Table));
133
134
  });
134
135
  }
136
+ convertParamsToObject(params) {
137
+ const paramObject = {};
138
+ if (Array.isArray(params)) {
139
+ params.forEach(param => {
140
+ paramObject[param.column] = param.value;
141
+ });
142
+ }
143
+ else {
144
+ Object.assign(paramObject, params);
145
+ }
146
+ return this.convertIdToString(paramObject);
147
+ }
148
+ convertIdToString(params) {
149
+ if (params.id && typeof params.id === 'number') {
150
+ return Object.assign(Object.assign({}, params), { id: params.id.toString() });
151
+ }
152
+ return params;
153
+ }
135
154
  /**
136
155
  * Execute a SELECT query and return the first matching row as a Record object
137
156
  * Returns undefined if no rows match the query
package/dist/Table.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import IDatabaseAdapter from "./interfaces/IDatabaseAdapter.js";
2
- import { DefaultQueryOptions, QueryOptions, QueryParameters, ReadableTableColumnInfo, TableColumnInfo } from "./types/index.js";
2
+ import { QueryOptions, ReadableTableColumnInfo, TableColumnInfo, DefaultQueryOptions, QueryWhereParameters } from "./types/index.js";
3
3
  import Record from "./Record.js";
4
4
  /**
5
5
  * Table class for interacting with a specific database table
@@ -153,6 +153,6 @@ export default class Table {
153
153
  * ]);
154
154
  * ```
155
155
  */
156
- Insert<Type>(values: QueryParameters): Promise<Record<Type> | undefined>;
156
+ Insert<Type>(values: QueryWhereParameters): Promise<Record<Type> | undefined>;
157
157
  }
158
158
  //# sourceMappingURL=Table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../src/Table.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAChE,OAAO,EACH,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,uBAAuB,EAEvB,eAAe,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,OAAO,OAAO,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAE3C;;;;;OAKG;IACH,OAAO;IAKP;;;;;;;;OAQG;WACiB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,UAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAe3G;;;;OAIG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;;;;;;;;;OAUG;IACU,sBAAsB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAIjE;;;;;;;;;;OAUG;IACU,8BAA8B,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAWpE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMlC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,OAAO,CAAC,IAAI,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IAoB1B;;;;;;;;;;;;;;;;;;;;OAoBG;IACU,MAAM,CAAC,IAAI,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAWpC;;;;;;;;;;OAUG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAM5C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACU,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;CA0FxF"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../src/Table.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,kCAAkC,CAAC;AAChE,OAAO,EACH,YAAY,EACZ,uBAAuB,EAEvB,eAAe,EACf,mBAAmB,EAEnB,oBAAoB,EACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,OAAO,OAAO,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAE3C;;;;;OAKG;IACH,OAAO;IAKP;;;;;;;;OAQG;WACiB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,cAAc,UAAQ,GAAG,OAAO,CAAC,KAAK,CAAC;IAe3G;;;;OAIG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED;;;;;;;;;;OAUG;IACU,sBAAsB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAIjE;;;;;;;;;;OAUG;IACU,8BAA8B,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAWpE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMlC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,OAAO,CAAC,IAAI,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IAoB1B;;;;;;;;;;;;;;;;;;;;OAoBG;IACU,MAAM,CAAC,IAAI,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IAWpC;;;;;;;;;;OAUG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAM5C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACU,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;CAgG7F"}
package/dist/Table.js CHANGED
@@ -230,7 +230,7 @@ export default class Table {
230
230
  */
231
231
  Insert(values) {
232
232
  return __awaiter(this, void 0, void 0, function* () {
233
- var _a;
233
+ var _a, _b;
234
234
  const columns = Object.keys(values);
235
235
  if (columns.length === 0) {
236
236
  throw new Error("Cannot insert record with no columns");
@@ -239,8 +239,14 @@ export default class Table {
239
239
  const query = new Query(this, queryStr, this.adapter);
240
240
  query.Parameters = values;
241
241
  const result = yield query.Run();
242
+ let recordId;
242
243
  // For PostgreSQL compatibility: use 'id' from values if lastInsertRowid is undefined
243
- const recordId = (_a = result === null || result === void 0 ? void 0 : result.lastInsertRowid) !== null && _a !== void 0 ? _a : values.id;
244
+ if (Array.isArray(values)) {
245
+ recordId = (_a = result === null || result === void 0 ? void 0 : result.lastInsertRowid) !== null && _a !== void 0 ? _a : values.map(v => v.column === 'id' ? v.value : undefined);
246
+ }
247
+ else {
248
+ recordId = (_b = result === null || result === void 0 ? void 0 : result.lastInsertRowid) !== null && _b !== void 0 ? _b : values.id;
249
+ }
244
250
  if (recordId === undefined) {
245
251
  return undefined;
246
252
  }
@@ -1,5 +1,5 @@
1
1
  import IDatabaseAdapter from "../interfaces/IDatabaseAdapter.js";
2
- import { QueryParameters } from "../types/query.js";
2
+ import { QueryCondition } from "../types/query.js";
3
3
  import Table from "../Table.js";
4
4
  import Record from "../Record.js";
5
5
  export default abstract class Model<T extends object> {
@@ -10,7 +10,7 @@ export default abstract class Model<T extends object> {
10
10
  private RecordGet;
11
11
  get(): Promise<T | undefined>;
12
12
  all(): Promise<T[]>;
13
- where(QueryParameters: QueryParameters): this;
13
+ where(QueryCondition: QueryCondition): this;
14
14
  create(data: T): Promise<Record<T> | undefined>;
15
15
  update(data: T): Promise<void>;
16
16
  delete(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"Model.d.ts","sourceRoot":"","sources":["../../src/abstract/Model.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,MAAM,aAAa,CAAC;AAChC,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,KAAK,CAAC,CAAC,SAAS,MAAM;IAChD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAuB;gBAEvB,KAAK,EAAE,KAAK;WAIX,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,EAE/C,IAAI,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,CAAC,EAC7B,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,CAAC,CAAC;YAKC,SAAS;IAIV,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAK7B,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAKzB,KAAK,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;IAKvC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAI/C,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvC"}
1
+ {"version":3,"file":"Model.d.ts","sourceRoot":"","sources":["../../src/abstract/Model.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAwB,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,MAAM,aAAa,CAAC;AAChC,OAAO,MAAM,MAAM,cAAc,CAAC;AAElC,MAAM,CAAC,OAAO,CAAC,QAAQ,OAAO,KAAK,CAAC,CAAC,SAAS,MAAM;IAChD,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,WAAW,CAAsB;gBAEtB,KAAK,EAAE,KAAK;WAIX,OAAO,CAAC,CAAC,SAAS,KAAK,CAAC,MAAM,CAAC,EAE/C,IAAI,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,CAAC,EAC7B,OAAO,EAAE,gBAAgB,GAC1B,OAAO,CAAC,CAAC,CAAC;YAKC,SAAS;IAIV,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAK7B,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAKzB,KAAK,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI;IAKrC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAI/C,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvC"}
@@ -36,8 +36,8 @@ export default class Model {
36
36
  return records.map(record => record.values);
37
37
  });
38
38
  }
39
- where(QueryParameters) {
40
- this.QueryParams = QueryParameters;
39
+ where(QueryCondition) {
40
+ this.QueryParams = QueryCondition;
41
41
  return this;
42
42
  }
43
43
  create(data) {
@@ -1,4 +1,4 @@
1
- import { DefaultQueryOptions, QueryOptions, QueryParameters, Join } from "../types/index.js";
1
+ import { DefaultQueryOptions, QueryOptions, QueryCondition, Join, QueryWhereParameters } from "../types/index.js";
2
2
  import Table from "Table";
3
3
  /**
4
4
  * QueryStatementBuilder - Utility class for building SQL query strings
@@ -77,7 +77,7 @@ export default class QueryStatementBuilder {
77
77
  * // Note: The actual values will be bound separately using the Parameters object
78
78
  * ```
79
79
  */
80
- static BuildInsert(table: Table, record: QueryParameters): string;
80
+ static BuildInsert(table: Table, record: QueryWhereParameters): string;
81
81
  /**
82
82
  * Build an UPDATE SQL statement with SET clause and WHERE conditions
83
83
  *
@@ -104,7 +104,7 @@ export default class QueryStatementBuilder {
104
104
  * // "UPDATE users SET status = @status WHERE status = @status AND last_login = @last_login"
105
105
  * ```
106
106
  */
107
- static BuildUpdate(table: Table, record: QueryParameters, where: QueryParameters): string;
107
+ static BuildUpdate(table: Table, record: QueryCondition, where: QueryCondition): string;
108
108
  /**
109
109
  * Build a DELETE SQL statement with WHERE conditions
110
110
  *
@@ -125,7 +125,7 @@ export default class QueryStatementBuilder {
125
125
  * // "DELETE FROM users WHERE status = @status AND last_login = @last_login"
126
126
  * ```
127
127
  */
128
- static BuildDelete(table: Table, where: QueryParameters): string;
128
+ static BuildDelete(table: Table, where: QueryCondition): string;
129
129
  /**
130
130
  * Build a COUNT SQL statement to count rows, optionally with WHERE conditions
131
131
  *
@@ -147,7 +147,7 @@ export default class QueryStatementBuilder {
147
147
  * // "SELECT COUNT(*) as count FROM users WHERE status = @status AND age = @age"
148
148
  * ```
149
149
  */
150
- static BuildCount(table: Table, where?: QueryParameters): string;
150
+ static BuildCount(table: Table, where?: QueryCondition): string;
151
151
  /**
152
152
  * Build a WHERE clause from parameter conditions (helper method)
153
153
  *
@@ -176,7 +176,9 @@ export default class QueryStatementBuilder {
176
176
  * // ""
177
177
  * ```
178
178
  */
179
- static BuildWhere(where?: QueryParameters): string;
179
+ static BuildWhere(where?: QueryCondition): string;
180
+ private static BuildWhereWithOperators;
181
+ private static BuildWhereSimple;
180
182
  /**
181
183
  * Build a SELECT statement with JOIN operations (INNER, LEFT, RIGHT, FULL)
182
184
  *
@@ -271,7 +273,7 @@ export default class QueryStatementBuilder {
271
273
  *
272
274
  * @param table - The source table (left side of the join)
273
275
  * @param joinTable - The table being joined (right side of the join)
274
- * @param on - QueryParameters object where key is the foreign key in joinTable and value is the primary key in table
276
+ * @param on - QueryCondition object where key is the foreign key in joinTable and value is the primary key in table
275
277
  * @returns ON clause string for JOIN operations
276
278
  *
277
279
  * @example
@@ -294,7 +296,7 @@ export default class QueryStatementBuilder {
294
296
  * // "ON users.id = orders.user_id AND users.company_id = orders.company_id"
295
297
  * ```
296
298
  */
297
- static BuildJoinOnPart(table: Table, joinTable: Table, on: QueryParameters | QueryParameters[]): string;
299
+ static BuildJoinOnPart(table: Table, joinTable: Table, on: QueryWhereParameters | QueryWhereParameters[]): string;
298
300
  /**
299
301
  * Build query options clause (ORDER BY, LIMIT, OFFSET) (helper method)
300
302
  *
@@ -1 +1 @@
1
- {"version":3,"file":"QueryStatementBuilder.d.ts","sourceRoot":"","sources":["../../src/helpers/QueryStatementBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAC7F,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAAG,MAAM;IAY7F;;;;;;;;;;;;;;;;;;OAkBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,GAAG,MAAM;IAYxE;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM;IAWhG;;;;;;;;;;;;;;;;;;;OAmBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM;IASvE;;;;;;;;;;;;;;;;;;;;OAoBG;WACW,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,MAAM;IAQvE;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;WACW,UAAU,CAAC,KAAK,CAAC,EAAE,eAAe,GAAG,MAAM;IAYzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;WACW,SAAS,CACnB,SAAS,EAAE,KAAK,EAChB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY;IAYhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;WACW,aAAa,CACvB,SAAS,EAAE,KAAK,EAChB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,GACrB,MAAM;IAeT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;WACW,eAAe,CACzB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,KAAK,EAChB,EAAE,EAAE,eAAe,GAAG,eAAe,EAAE,GACxC,MAAM;IAWT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;WACW,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;CAiBjE"}
1
+ {"version":3,"file":"QueryStatementBuilder.d.ts","sourceRoot":"","sources":["../../src/helpers/QueryStatementBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,cAAc,EAAE,IAAI,EAAmB,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACnI,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACtC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY,GAAG,MAAM;IAY7F;;;;;;;;;;;;;;;;;;OAkBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,GAAG,MAAM;IAY7E;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM;IAW9F;;;;;;;;;;;;;;;;;;;OAmBG;WACW,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM;IAStE;;;;;;;;;;;;;;;;;;;;OAoBG;WACW,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,cAAc,GAAG,MAAM;IAQtE;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;WACW,UAAU,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,MAAM;IAgBxD,OAAO,CAAC,MAAM,CAAC,uBAAuB;IAStC,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAK/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;WACW,SAAS,CACnB,SAAS,EAAE,KAAK,EAChB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAAG,YAAY;IAYhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAsCG;WACW,aAAa,CACvB,SAAS,EAAE,KAAK,EAChB,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,GACrB,MAAM;IAcT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;WACW,eAAe,CACzB,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,KAAK,EAChB,EAAE,EAAE,oBAAoB,GAAG,oBAAoB,EAAE,GAClD,MAAM;IAWT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;WACW,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;CAiBjE"}
@@ -208,14 +208,30 @@ export default class QueryStatementBuilder {
208
208
  * ```
209
209
  */
210
210
  static BuildWhere(where) {
211
- if (!where || Object.keys(where).length === 0)
211
+ if (!where || (Array.isArray(where) && where.length === 0) || Object.keys(where).length === 0)
212
212
  return "";
213
+ const isSimpleObject = !Array.isArray(where) && typeof where === 'object' && where !== null;
213
214
  const queryParts = [];
214
- const whereClauses = Object.keys(where).map(col => `${col} = @${col}`);
215
215
  queryParts.push("WHERE");
216
- queryParts.push(whereClauses.join(" AND "));
216
+ if (isSimpleObject) {
217
+ queryParts.push(this.BuildWhereSimple(where));
218
+ }
219
+ else {
220
+ queryParts.push(this.BuildWhereWithOperators(where));
221
+ }
217
222
  return queryParts.join(" ");
218
223
  }
224
+ static BuildWhereWithOperators(where) {
225
+ const queryParts = where.map(condition => {
226
+ const operator = condition.operator || "=";
227
+ return `${condition.column} ${operator} @${condition.column.trim()}`;
228
+ });
229
+ return queryParts.join(" AND ");
230
+ }
231
+ static BuildWhereSimple(where) {
232
+ const queryParts = Object.keys(where).map(col => `${col} = @${col}`);
233
+ return queryParts.join(" AND ");
234
+ }
219
235
  /**
220
236
  * Build a SELECT statement with JOIN operations (INNER, LEFT, RIGHT, FULL)
221
237
  *
@@ -329,7 +345,7 @@ export default class QueryStatementBuilder {
329
345
  *
330
346
  * @param table - The source table (left side of the join)
331
347
  * @param joinTable - The table being joined (right side of the join)
332
- * @param on - QueryParameters object where key is the foreign key in joinTable and value is the primary key in table
348
+ * @param on - QueryCondition object where key is the foreign key in joinTable and value is the primary key in table
333
349
  * @returns ON clause string for JOIN operations
334
350
  *
335
351
  * @example
@@ -1,10 +1,16 @@
1
- export type QueryParameters = {
1
+ export type QueryWhereParameters = {
2
2
  [key: string]: QueryValues;
3
3
  };
4
+ export type QueryParameters = {
5
+ column: string;
6
+ operator: '=' | '!=' | '<' | '<=' | '>' | '>=' | 'LIKE' | 'IN' | 'NOT IN';
7
+ value: QueryValues;
8
+ };
9
+ export type QueryCondition = QueryWhereParameters | QueryParameters[];
4
10
  export type QueryValues = string | number | boolean | null | bigint;
5
11
  export type DefaultQueryOptions = {
6
12
  select?: string;
7
- where?: QueryParameters;
13
+ where?: QueryCondition;
8
14
  };
9
15
  export type QueryOptions = {
10
16
  orderBy?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/types/query.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAA;AAEnE,MAAM,MAAM,mBAAmB,GAAG;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;CAC3B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/types/query.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;CAC9B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC;IAC1E,KAAK,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,oBAAoB,GAAG,eAAe,EAAE,CAAC;AAEtE,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAA;AAEnE,MAAM,MAAM,mBAAmB,GAAG;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,cAAc,CAAC;CAC1B,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { QueryParameters } from "index";
1
+ import { QueryWhereParameters } from "index";
2
2
  import Table from "../Table.js";
3
3
  export type TableColumnInfo = {
4
4
  cid: number;
@@ -24,6 +24,6 @@ export type ColumnDefinition = {
24
24
  export type Join = {
25
25
  fromTable: Table;
26
26
  joinType: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
27
- on: QueryParameters | QueryParameters[];
27
+ on: QueryWhereParameters | QueryWhereParameters[];
28
28
  };
29
29
  //# sourceMappingURL=table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/types/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,MAAM,aAAa,CAAC;AAEhC,MAAM,MAAM,eAAe,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACf,SAAS,EAAE,KAAK,CAAC;IACjB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,EAAE,EAAE,eAAe,GAAG,eAAe,EAAE,CAAC;CAC3C,CAAA"}
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/types/table.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,KAAK,MAAM,aAAa,CAAC;AAEhC,MAAM,MAAM,eAAe,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IACf,SAAS,EAAE,KAAK,CAAC;IACjB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,EAAE,EAAE,oBAAoB,GAAG,oBAAoB,EAAE,CAAC;CACrD,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iamkirbki/database-handler-core",
3
- "version": "3.1.2",
3
+ "version": "3.1.4",
4
4
  "author": "iamkirbki",
5
5
  "description": "Core database abstractions and interfaces",
6
6
  "license": "ISC",
@@ -1,210 +0,0 @@
1
- import { QueryParameters, TableColumnInfo } from "../types/index.js";
2
- /**
3
- * Validator class for validating table names, column names, column types, SQL queries, and query parameters
4
- *
5
- * Provides static methods to ensure data integrity and prevent SQL injection attacks by:
6
- * - Validating table and column naming conventions
7
- * - Checking column type compatibility with SQLite standards
8
- * - Detecting SQL injection patterns in queries
9
- * - Verifying parameter types match column types
10
- * - Enforcing NOT NULL constraints
11
- *
12
- * @example
13
- * ```typescript
14
- * // Validate a table name
15
- * Validator.ValidateTableName('users'); // OK
16
- * Validator.ValidateTableName('invalid-name'); // throws Error
17
- *
18
- * // Validate a column type
19
- * Validator.ValidateColumnType('TEXT NOT NULL'); // OK
20
- * Validator.ValidateColumnType('INVALID_TYPE'); // throws Error
21
- *
22
- * // Validate a query for SQL injection
23
- * Validator.ValidateQuery('SELECT * FROM users WHERE id = @id', columnInfo); // OK
24
- * Validator.ValidateQuery('SELECT * FROM users; DROP TABLE users', columnInfo); // throws Error
25
- * ```
26
- */
27
- export default class Validator {
28
- /**
29
- * List of valid SQLite column types
30
- * Includes numeric, text, binary, date/time types and compatibility types for other SQL dialects
31
- */
32
- private static readonly validTypes;
33
- /**
34
- * List of SQL keywords that are valid in column type definitions
35
- * These keywords are stripped when validating the base column type
36
- */
37
- private static readonly sqlKeywords;
38
- /**
39
- * Validates a table name according to SQLite naming conventions
40
- *
41
- * Rules:
42
- * - Must be a non-empty string
43
- * - Cannot contain commas
44
- * - Must only contain letters, numbers, and underscores
45
- *
46
- * @param name - The table name to validate
47
- * @throws Error if the table name is invalid
48
- *
49
- * @example
50
- * ```typescript
51
- * Validator.ValidateTableName('users'); // OK
52
- * Validator.ValidateTableName('user_accounts'); // OK
53
- * Validator.ValidateTableName('users123'); // OK
54
- * Validator.ValidateTableName('invalid-name'); // throws Error
55
- * Validator.ValidateTableName(''); // throws Error
56
- * ```
57
- */
58
- static ValidateTableName(name: string): void;
59
- /**
60
- * Validates a column name according to SQLite naming conventions
61
- *
62
- * Rules:
63
- * - Must be a non-empty string
64
- * - Cannot contain commas
65
- * - Must only contain letters, numbers, and underscores
66
- *
67
- * @param name - The column name to validate
68
- * @throws Error if the column name is invalid
69
- *
70
- * @example
71
- * ```typescript
72
- * Validator.ValidateColumnName('email'); // OK
73
- * Validator.ValidateColumnName('user_id'); // OK
74
- * Validator.ValidateColumnName('created_at'); // OK
75
- * Validator.ValidateColumnName('invalid-name'); // throws Error
76
- * Validator.ValidateColumnName(''); // throws Error
77
- * ```
78
- */
79
- static ValidateColumnName(name: string): void;
80
- /**
81
- * Generic name validation for tables and columns
82
- *
83
- * Rules:
84
- * - Must be a non-empty string
85
- * - Cannot contain commas
86
- * - Must only contain letters, numbers, and underscores
87
- *
88
- * @param name - The table/column name to validate
89
- * @param type - The type, either table or column
90
- * @throws Error if the name is invalid
91
- */
92
- private static ValidateName;
93
- /**
94
- * Validates a column type definition against SQLite type standards
95
- *
96
- * Strips SQL keywords (NOT NULL, PRIMARY KEY, etc.) and length specifications
97
- * before checking if the base type is valid. Supports all SQLite types and
98
- * common types from other SQL dialects for compatibility.
99
- *
100
- * @param type - The column type definition to validate (e.g., "TEXT NOT NULL", "VARCHAR(255)")
101
- * @throws Error if the column type is invalid
102
- *
103
- * @example
104
- * ```typescript
105
- * Validator.ValidateColumnType('TEXT'); // OK
106
- * Validator.ValidateColumnType('INTEGER NOT NULL'); // OK
107
- * Validator.ValidateColumnType('VARCHAR(255)'); // OK
108
- * Validator.ValidateColumnType('TEXT PRIMARY KEY'); // OK
109
- * Validator.ValidateColumnType('INVALID_TYPE'); // throws Error
110
- * ```
111
- */
112
- static ValidateColumnType(type: string): void;
113
- /**
114
- * Validates an SQL query for security and correctness
115
- *
116
- * Security checks:
117
- * - Detects SQL injection attempts (semicolon followed by DROP, DELETE, UPDATE, INSERT, ALTER)
118
- * - Ensures all field references (@fieldName) exist in the table schema
119
- *
120
- * Correctness checks:
121
- * - Verifies all required (NOT NULL) fields are provided in INSERT queries
122
- * - Validates query is a non-empty string
123
- *
124
- * @param query - The SQL query string to validate
125
- * @param TableColumnInformation - Array of column metadata from the table schema
126
- * @throws Error if the query contains forbidden operations, references unknown fields, or missing required fields
127
- *
128
- * @example
129
- * ```typescript
130
- * const columnInfo = [
131
- * { name: 'id', type: 'INTEGER', notnull: 1 },
132
- * { name: 'name', type: 'TEXT', notnull: 1 },
133
- * { name: 'email', type: 'TEXT', notnull: 0 }
134
- * ];
135
- *
136
- * // Valid queries
137
- * Validator.ValidateQuery('SELECT * FROM users WHERE id = @id', columnInfo); // OK
138
- * Validator.ValidateQuery('INSERT INTO users (name, email) VALUES (@name, @email)', columnInfo); // OK
139
- *
140
- * // Invalid queries
141
- * Validator.ValidateQuery('SELECT * FROM users; DROP TABLE users', columnInfo); // throws Error - SQL injection
142
- * Validator.ValidateQuery('SELECT * FROM users WHERE @nonexistent = 1', columnInfo); // throws Error - unknown field
143
- * Validator.ValidateQuery('INSERT INTO users (email) VALUES (@email)', columnInfo); // throws Error - missing required field 'name'
144
- * ```
145
- */
146
- static ValidateQuery(query: string, TableColumnInformation: TableColumnInfo[]): void;
147
- /**
148
- * Validates query parameters against table schema
149
- *
150
- * Checks performed:
151
- * - Each parameter key must match a column in the table
152
- * - NOT NULL columns cannot receive null or undefined values
153
- * - Parameter types must match their corresponding column types
154
- * - All field references in the query must have corresponding parameters
155
- *
156
- * @param query - The SQL query string containing field references
157
- * @param parameters - Object mapping parameter names to values
158
- * @param TableColumnInformation - Array of column metadata from the table schema
159
- * @throws Error if parameters don't match schema, have wrong types, or violate NOT NULL constraints
160
- *
161
- * @example
162
- * ```typescript
163
- * const columnInfo = [
164
- * { name: 'id', type: 'INTEGER', notnull: 1 },
165
- * { name: 'name', type: 'TEXT', notnull: 1 },
166
- * { name: 'age', type: 'INTEGER', notnull: 0 }
167
- * ];
168
- *
169
- * const query = 'INSERT INTO users (name, age) VALUES (@name, @age)';
170
- *
171
- * // Valid parameters
172
- * Validator.ValidateQueryParameters(query, { name: 'John', age: 30 }, columnInfo); // OK
173
- * Validator.ValidateQueryParameters(query, { name: 'Jane', age: null }, columnInfo); // OK - age is nullable
174
- *
175
- * // Invalid parameters
176
- * Validator.ValidateQueryParameters(query, { name: null, age: 30 }, columnInfo); // throws Error - name is NOT NULL
177
- * Validator.ValidateQueryParameters(query, { name: 'John', age: 'thirty' }, columnInfo); // throws Error - wrong type
178
- * Validator.ValidateQueryParameters(query, { name: 'John' }, columnInfo); // throws Error - missing @age parameter
179
- * Validator.ValidateQueryParameters(query, { name: 'John', age: 30, extra: 'value' }, columnInfo); // throws Error - extra is not a column
180
- * ```
181
- */
182
- static ValidateQueryParameters(query: string, parameters: QueryParameters, TableColumnInformation: TableColumnInfo[]): void;
183
- /**
184
- * Compares a column type with a JavaScript parameter type for compatibility
185
- *
186
- * Type mappings:
187
- * - TEXT/CHAR types → string
188
- * - INTEGER/INT types → number
189
- * - REAL/FLOAT/DOUBLE types → number
190
- * - BOOLEAN types → boolean
191
- * - BLOB types → object (Buffer/Uint8Array)
192
- * - UUID → string (with format validation)
193
- *
194
- * @param columnType - The SQLite column type from the schema
195
- * @param parameterType - The JavaScript typeof value for the parameter
196
- * @returns true if the types are compatible, false otherwise
197
- *
198
- * @example
199
- * ```typescript
200
- * Validator.CompareTypes('TEXT', 'string'); // true
201
- * Validator.CompareTypes('INTEGER', 'number'); // true
202
- * Validator.CompareTypes('VARCHAR(255)', 'string'); // true
203
- * Validator.CompareTypes('REAL', 'number'); // true
204
- * Validator.CompareTypes('TEXT', 'number'); // false
205
- * Validator.CompareTypes('INTEGER', 'string'); // false
206
- * ```
207
- */
208
- static CompareTypes(columnType?: string, parameterType?: string): boolean;
209
- }
210
- //# sourceMappingURL=Validator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Validator.d.ts","sourceRoot":"","sources":["../../src/helpers/Validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,OAAO,SAAS;IAC1B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAkBhC;IAEF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAWjC;IAEF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI5C;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI7C;;;;;;;;;;;MAWE;IACF,OAAO,CAAC,MAAM,CAAC,YAAY;IAY3B;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgB7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,sBAAsB,EAAE,eAAe,EAAE,GAAG,IAAI;IA0CpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACH,MAAM,CAAC,uBAAuB,CAC1B,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,eAAe,EAC3B,sBAAsB,EAAE,eAAe,EAAE,GAC1C,IAAI;IAkCP;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO;CAoC5E"}
@@ -1,345 +0,0 @@
1
- /**
2
- * Validator class for validating table names, column names, column types, SQL queries, and query parameters
3
- *
4
- * Provides static methods to ensure data integrity and prevent SQL injection attacks by:
5
- * - Validating table and column naming conventions
6
- * - Checking column type compatibility with SQLite standards
7
- * - Detecting SQL injection patterns in queries
8
- * - Verifying parameter types match column types
9
- * - Enforcing NOT NULL constraints
10
- *
11
- * @example
12
- * ```typescript
13
- * // Validate a table name
14
- * Validator.ValidateTableName('users'); // OK
15
- * Validator.ValidateTableName('invalid-name'); // throws Error
16
- *
17
- * // Validate a column type
18
- * Validator.ValidateColumnType('TEXT NOT NULL'); // OK
19
- * Validator.ValidateColumnType('INVALID_TYPE'); // throws Error
20
- *
21
- * // Validate a query for SQL injection
22
- * Validator.ValidateQuery('SELECT * FROM users WHERE id = @id', columnInfo); // OK
23
- * Validator.ValidateQuery('SELECT * FROM users; DROP TABLE users', columnInfo); // throws Error
24
- * ```
25
- */
26
- class Validator {
27
- /**
28
- * Validates a table name according to SQLite naming conventions
29
- *
30
- * Rules:
31
- * - Must be a non-empty string
32
- * - Cannot contain commas
33
- * - Must only contain letters, numbers, and underscores
34
- *
35
- * @param name - The table name to validate
36
- * @throws Error if the table name is invalid
37
- *
38
- * @example
39
- * ```typescript
40
- * Validator.ValidateTableName('users'); // OK
41
- * Validator.ValidateTableName('user_accounts'); // OK
42
- * Validator.ValidateTableName('users123'); // OK
43
- * Validator.ValidateTableName('invalid-name'); // throws Error
44
- * Validator.ValidateTableName(''); // throws Error
45
- * ```
46
- */
47
- static ValidateTableName(name) {
48
- this.ValidateName(name, "Table");
49
- }
50
- /**
51
- * Validates a column name according to SQLite naming conventions
52
- *
53
- * Rules:
54
- * - Must be a non-empty string
55
- * - Cannot contain commas
56
- * - Must only contain letters, numbers, and underscores
57
- *
58
- * @param name - The column name to validate
59
- * @throws Error if the column name is invalid
60
- *
61
- * @example
62
- * ```typescript
63
- * Validator.ValidateColumnName('email'); // OK
64
- * Validator.ValidateColumnName('user_id'); // OK
65
- * Validator.ValidateColumnName('created_at'); // OK
66
- * Validator.ValidateColumnName('invalid-name'); // throws Error
67
- * Validator.ValidateColumnName(''); // throws Error
68
- * ```
69
- */
70
- static ValidateColumnName(name) {
71
- this.ValidateName(name, "Column");
72
- }
73
- /**
74
- * Generic name validation for tables and columns
75
- *
76
- * Rules:
77
- * - Must be a non-empty string
78
- * - Cannot contain commas
79
- * - Must only contain letters, numbers, and underscores
80
- *
81
- * @param name - The table/column name to validate
82
- * @param type - The type, either table or column
83
- * @throws Error if the name is invalid
84
- */
85
- static ValidateName(name, type) {
86
- if (!name || typeof name !== "string") {
87
- throw new Error(`${type} name must be a non-empty string.`);
88
- }
89
- if (name.includes(",")) {
90
- throw new Error(`${type} name cannot contain commas.`);
91
- }
92
- if (/[^a-zA-Z0-9_]/.test(name)) {
93
- throw new Error(`${type} name must only contain letters, numbers, and underscores.`);
94
- }
95
- }
96
- /**
97
- * Validates a column type definition against SQLite type standards
98
- *
99
- * Strips SQL keywords (NOT NULL, PRIMARY KEY, etc.) and length specifications
100
- * before checking if the base type is valid. Supports all SQLite types and
101
- * common types from other SQL dialects for compatibility.
102
- *
103
- * @param type - The column type definition to validate (e.g., "TEXT NOT NULL", "VARCHAR(255)")
104
- * @throws Error if the column type is invalid
105
- *
106
- * @example
107
- * ```typescript
108
- * Validator.ValidateColumnType('TEXT'); // OK
109
- * Validator.ValidateColumnType('INTEGER NOT NULL'); // OK
110
- * Validator.ValidateColumnType('VARCHAR(255)'); // OK
111
- * Validator.ValidateColumnType('TEXT PRIMARY KEY'); // OK
112
- * Validator.ValidateColumnType('INVALID_TYPE'); // throws Error
113
- * ```
114
- */
115
- static ValidateColumnType(type) {
116
- if (!type || typeof type !== "string") {
117
- throw new Error("Column type must be a non-empty string.");
118
- }
119
- const cleanedType = type
120
- .toUpperCase()
121
- .replace(/\([0-9 , a-zA-Z]*\)/g, "") // Remove (255), (10,2), etc.
122
- .replace(new RegExp(`\\b(${this.sqlKeywords.join("|")})\\b`, "gi"), "")
123
- .trim();
124
- if (!this.validTypes.includes(cleanedType)) {
125
- throw new Error(`Invalid column type "${type}". Valid types are: ${this.validTypes.join(", ")}.`);
126
- }
127
- }
128
- /**
129
- * Validates an SQL query for security and correctness
130
- *
131
- * Security checks:
132
- * - Detects SQL injection attempts (semicolon followed by DROP, DELETE, UPDATE, INSERT, ALTER)
133
- * - Ensures all field references (@fieldName) exist in the table schema
134
- *
135
- * Correctness checks:
136
- * - Verifies all required (NOT NULL) fields are provided in INSERT queries
137
- * - Validates query is a non-empty string
138
- *
139
- * @param query - The SQL query string to validate
140
- * @param TableColumnInformation - Array of column metadata from the table schema
141
- * @throws Error if the query contains forbidden operations, references unknown fields, or missing required fields
142
- *
143
- * @example
144
- * ```typescript
145
- * const columnInfo = [
146
- * { name: 'id', type: 'INTEGER', notnull: 1 },
147
- * { name: 'name', type: 'TEXT', notnull: 1 },
148
- * { name: 'email', type: 'TEXT', notnull: 0 }
149
- * ];
150
- *
151
- * // Valid queries
152
- * Validator.ValidateQuery('SELECT * FROM users WHERE id = @id', columnInfo); // OK
153
- * Validator.ValidateQuery('INSERT INTO users (name, email) VALUES (@name, @email)', columnInfo); // OK
154
- *
155
- * // Invalid queries
156
- * Validator.ValidateQuery('SELECT * FROM users; DROP TABLE users', columnInfo); // throws Error - SQL injection
157
- * Validator.ValidateQuery('SELECT * FROM users WHERE @nonexistent = 1', columnInfo); // throws Error - unknown field
158
- * Validator.ValidateQuery('INSERT INTO users (email) VALUES (@email)', columnInfo); // throws Error - missing required field 'name'
159
- * ```
160
- */
161
- static ValidateQuery(query, TableColumnInformation) {
162
- if (!query || typeof query !== "string" || query.trim() === "") {
163
- throw new Error("Query must be a non-empty string.");
164
- }
165
- const forbiddenPatterns = [
166
- /;\s*drop\s+table/i,
167
- /;\s*delete\s+from/i,
168
- /;\s*update\s+/i,
169
- /;\s*insert\s+into/i,
170
- /;\s*alter\s+table/i
171
- ];
172
- for (const pattern of forbiddenPatterns) {
173
- if (pattern.test(query)) {
174
- throw new Error("Query contains forbidden operations.");
175
- }
176
- }
177
- const fieldPattern = /@([a-zA-Z0-9_]+)/g;
178
- let match;
179
- let requiredFields = TableColumnInformation
180
- .filter(col => col.notnull === 1);
181
- while ((match = fieldPattern.exec(query)) !== null) {
182
- const fieldName = match[1];
183
- const found = TableColumnInformation.some(col => col.name === fieldName);
184
- if (!found) {
185
- throw new Error(`Query references unknown field "@${fieldName}".`);
186
- }
187
- requiredFields = requiredFields.filter(col => col.name != fieldName);
188
- }
189
- if (requiredFields.length > 0 && /insert\s+into/i.test(query)) {
190
- const fieldNames = requiredFields.map(col => col.name).join(", ");
191
- throw new Error(`Query is missing required fields: ${fieldNames}.`);
192
- }
193
- }
194
- /**
195
- * Validates query parameters against table schema
196
- *
197
- * Checks performed:
198
- * - Each parameter key must match a column in the table
199
- * - NOT NULL columns cannot receive null or undefined values
200
- * - Parameter types must match their corresponding column types
201
- * - All field references in the query must have corresponding parameters
202
- *
203
- * @param query - The SQL query string containing field references
204
- * @param parameters - Object mapping parameter names to values
205
- * @param TableColumnInformation - Array of column metadata from the table schema
206
- * @throws Error if parameters don't match schema, have wrong types, or violate NOT NULL constraints
207
- *
208
- * @example
209
- * ```typescript
210
- * const columnInfo = [
211
- * { name: 'id', type: 'INTEGER', notnull: 1 },
212
- * { name: 'name', type: 'TEXT', notnull: 1 },
213
- * { name: 'age', type: 'INTEGER', notnull: 0 }
214
- * ];
215
- *
216
- * const query = 'INSERT INTO users (name, age) VALUES (@name, @age)';
217
- *
218
- * // Valid parameters
219
- * Validator.ValidateQueryParameters(query, { name: 'John', age: 30 }, columnInfo); // OK
220
- * Validator.ValidateQueryParameters(query, { name: 'Jane', age: null }, columnInfo); // OK - age is nullable
221
- *
222
- * // Invalid parameters
223
- * Validator.ValidateQueryParameters(query, { name: null, age: 30 }, columnInfo); // throws Error - name is NOT NULL
224
- * Validator.ValidateQueryParameters(query, { name: 'John', age: 'thirty' }, columnInfo); // throws Error - wrong type
225
- * Validator.ValidateQueryParameters(query, { name: 'John' }, columnInfo); // throws Error - missing @age parameter
226
- * Validator.ValidateQueryParameters(query, { name: 'John', age: 30, extra: 'value' }, columnInfo); // throws Error - extra is not a column
227
- * ```
228
- */
229
- static ValidateQueryParameters(query, parameters, TableColumnInformation) {
230
- for (const [key, value] of Object.entries(parameters)) {
231
- const columnInfo = TableColumnInformation.find(col => col.name === key);
232
- if (!columnInfo) {
233
- throw new Error(`Parameter "${key}" does not match any column in the table.`);
234
- }
235
- if (columnInfo.notnull === 1 && (value === null || value === undefined)) {
236
- throw new Error(`Parameter "${key}" cannot be null or undefined for a NOT NULL column.`);
237
- }
238
- const parameterType = typeof value;
239
- const columnType = columnInfo.type;
240
- const isValidType = Validator.CompareTypes(columnType, parameterType);
241
- if (!isValidType) {
242
- throw new Error(`Parameter "${key}" has type "${parameterType}" which does not match column type "${columnType}".`);
243
- }
244
- const fieldPattern = /@([a-zA-Z0-9_]+)/g;
245
- let match;
246
- while ((match = fieldPattern.exec(query)) !== null) {
247
- const fieldName = match[1];
248
- const found = parameters[fieldName] !== undefined;
249
- if (!found) {
250
- throw new Error(`Missing parameter for column "${fieldName}".`);
251
- }
252
- }
253
- }
254
- }
255
- /**
256
- * Compares a column type with a JavaScript parameter type for compatibility
257
- *
258
- * Type mappings:
259
- * - TEXT/CHAR types → string
260
- * - INTEGER/INT types → number
261
- * - REAL/FLOAT/DOUBLE types → number
262
- * - BOOLEAN types → boolean
263
- * - BLOB types → object (Buffer/Uint8Array)
264
- * - UUID → string (with format validation)
265
- *
266
- * @param columnType - The SQLite column type from the schema
267
- * @param parameterType - The JavaScript typeof value for the parameter
268
- * @returns true if the types are compatible, false otherwise
269
- *
270
- * @example
271
- * ```typescript
272
- * Validator.CompareTypes('TEXT', 'string'); // true
273
- * Validator.CompareTypes('INTEGER', 'number'); // true
274
- * Validator.CompareTypes('VARCHAR(255)', 'string'); // true
275
- * Validator.CompareTypes('REAL', 'number'); // true
276
- * Validator.CompareTypes('TEXT', 'number'); // false
277
- * Validator.CompareTypes('INTEGER', 'string'); // false
278
- * ```
279
- */
280
- static CompareTypes(columnType, parameterType) {
281
- if (!columnType || !parameterType) {
282
- return false;
283
- }
284
- const lowerType = columnType.toLowerCase();
285
- // SQLite text types (TEXT, VARCHAR, CHAR, etc.)
286
- if (lowerType.includes('text') || lowerType.includes('char')) {
287
- return parameterType === 'string' || parameterType === 'number';
288
- }
289
- // SQLite integer and real/float types (INTEGER, INT, TINYINT, SMALLINT, REAL, FLOAT, DOUBLE etc.)
290
- if (lowerType.includes('int') || lowerType.includes('real') || lowerType.includes('float') || lowerType.includes('double')) {
291
- return parameterType === 'number';
292
- }
293
- // Boolean
294
- if (lowerType.includes('bool')) {
295
- return parameterType === 'boolean';
296
- }
297
- // BLOB types
298
- if (lowerType.includes('blob')) {
299
- return parameterType === 'object'; // Buffer or Uint8Array
300
- }
301
- // UUID with validation
302
- if (lowerType === 'uuid' && parameterType === 'string') {
303
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(parameterType);
304
- }
305
- // Default: allow any type if not explicitly restricted
306
- // This handles custom SQLite types gracefully
307
- return true;
308
- }
309
- }
310
- /**
311
- * List of valid SQLite column types
312
- * Includes numeric, text, binary, date/time types and compatibility types for other SQL dialects
313
- */
314
- Validator.validTypes = [
315
- // Numeric types
316
- "INTEGER", "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT", "UNSIGNED BIG INT",
317
- "INT2", "INT8", "NUMERIC", "DECIMAL", "BOOLEAN", "FLOAT", "DOUBLE", "DOUBLE PRECISION", "REAL",
318
- // Text types
319
- "TEXT", "CHARACTER", "CHAR", "VARCHAR", "VARYING CHARACTER", "NCHAR",
320
- "NATIVE CHARACTER", "NVARCHAR", "CLOB",
321
- // Binary types
322
- "BLOB", "BINARY", "VARBINARY",
323
- // Date/time types
324
- "DATE", "DATETIME", "TIME", "TIMESTAMP",
325
- // Other types (for compatibility with other SQL dialects)
326
- "ENUM", "SET", "YEAR", "JSON", "GEOMETRY", "POINT", "LINESTRING", "POLYGON",
327
- "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON", "GEOMETRYCOLLECTION"
328
- ];
329
- /**
330
- * List of SQL keywords that are valid in column type definitions
331
- * These keywords are stripped when validating the base column type
332
- */
333
- Validator.sqlKeywords = [
334
- "NOT",
335
- "NULL",
336
- "PRIMARY",
337
- "KEY",
338
- "AUTOINCREMENT",
339
- "UNIQUE",
340
- "CHECK",
341
- "DEFAULT",
342
- "COLLATE",
343
- "REFERENCES"
344
- ];
345
- export default Validator;