accio-orm 0.1.0 → 0.1.1

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 (45) hide show
  1. package/README.md +1 -0
  2. package/dist/connection/Connection.d.ts +6 -0
  3. package/dist/connection/Connection.js +60 -11
  4. package/dist/connection/types.d.ts +2 -0
  5. package/dist/decorators/Column.d.ts +3 -2
  6. package/dist/decorators/PrimaryColumn.d.ts +1 -1
  7. package/dist/decorators/PrimaryColumn.js +3 -0
  8. package/dist/errors/AccioError.d.ts +44 -0
  9. package/dist/errors/AccioError.js +55 -0
  10. package/dist/errors/ConnectionError.d.ts +27 -0
  11. package/dist/errors/ConnectionError.js +33 -0
  12. package/dist/errors/DatabaseError.d.ts +35 -0
  13. package/dist/errors/DatabaseError.js +35 -0
  14. package/dist/errors/QueryError.d.ts +36 -0
  15. package/dist/errors/QueryError.js +36 -0
  16. package/dist/errors/ValidationError.d.ts +35 -0
  17. package/dist/errors/ValidationError.js +35 -0
  18. package/dist/errors/index.d.ts +11 -0
  19. package/dist/errors/index.js +19 -0
  20. package/dist/index.d.ts +6 -3
  21. package/dist/index.js +17 -1
  22. package/dist/logger/LogLevel.d.ts +47 -0
  23. package/dist/logger/LogLevel.js +57 -0
  24. package/dist/logger/Logger.d.ts +171 -0
  25. package/dist/logger/Logger.js +207 -0
  26. package/dist/logger/index.d.ts +8 -0
  27. package/dist/logger/index.js +14 -0
  28. package/dist/metadata/MetadataStorage.d.ts +1 -1
  29. package/dist/metadata/MetadataStorage.js +12 -11
  30. package/dist/query/QueryBuilder.d.ts +0 -5
  31. package/dist/query/QueryBuilder.js +10 -31
  32. package/dist/repository/Repository.js +12 -11
  33. package/dist/types/PostgresTypes.d.ts +74 -0
  34. package/dist/types/PostgresTypes.js +98 -0
  35. package/dist/types/index.d.ts +6 -0
  36. package/dist/types/index.js +12 -0
  37. package/dist/validation/ConnectionValidation.d.ts +27 -0
  38. package/dist/validation/ConnectionValidation.js +58 -0
  39. package/dist/validation/IdentifierValidator.d.ts +101 -0
  40. package/dist/validation/IdentifierValidator.js +127 -0
  41. package/dist/validation/QueryValidator.d.ts +61 -0
  42. package/dist/validation/QueryValidator.js +81 -0
  43. package/dist/validation/index.d.ts +9 -0
  44. package/dist/validation/index.js +15 -0
  45. package/package.json +3 -2
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Log level definitions for the Accio logger
3
+ *
4
+ * Log levels control which messages are output. Higher levels are more severe.
5
+ * Setting a log level will output all messages at the level and above.
6
+ */
7
+ /**
8
+ * Log severity levels
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const dv = connect({
13
+ * host: 'localhost',
14
+ * database: 'mydb',
15
+ * user: 'user',
16
+ * password: 'password',
17
+ * logger: {
18
+ * level: Loglevel.DEBUG // show all log messages
19
+ * }
20
+ * })
21
+ */
22
+ export declare enum LogLevel {
23
+ /**
24
+ * Debug level - most verbose, includes all query details
25
+ */
26
+ DEBUG = 0,
27
+ /**
28
+ * Info level - general informational messages
29
+ */
30
+ INFO = 1,
31
+ /**
32
+ * Warning level - warnings that don't stop execution
33
+ */
34
+ WARN = 2,
35
+ /**
36
+ * Error level - errors that cause operation failures
37
+ */
38
+ ERROR = 3,
39
+ /**
40
+ * No logging - disables all log output
41
+ */
42
+ NONE = 4
43
+ }
44
+ /**
45
+ * Human-readable names for log levels
46
+ */
47
+ export declare const LogLevelNames: Record<LogLevel, string>;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ /**
3
+ * Log level definitions for the Accio logger
4
+ *
5
+ * Log levels control which messages are output. Higher levels are more severe.
6
+ * Setting a log level will output all messages at the level and above.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.LogLevelNames = exports.LogLevel = void 0;
10
+ /**
11
+ * Log severity levels
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const dv = connect({
16
+ * host: 'localhost',
17
+ * database: 'mydb',
18
+ * user: 'user',
19
+ * password: 'password',
20
+ * logger: {
21
+ * level: Loglevel.DEBUG // show all log messages
22
+ * }
23
+ * })
24
+ */
25
+ var LogLevel;
26
+ (function (LogLevel) {
27
+ /**
28
+ * Debug level - most verbose, includes all query details
29
+ */
30
+ LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
31
+ /**
32
+ * Info level - general informational messages
33
+ */
34
+ LogLevel[LogLevel["INFO"] = 1] = "INFO";
35
+ /**
36
+ * Warning level - warnings that don't stop execution
37
+ */
38
+ LogLevel[LogLevel["WARN"] = 2] = "WARN";
39
+ /**
40
+ * Error level - errors that cause operation failures
41
+ */
42
+ LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
43
+ /**
44
+ * No logging - disables all log output
45
+ */
46
+ LogLevel[LogLevel["NONE"] = 4] = "NONE";
47
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
48
+ /**
49
+ * Human-readable names for log levels
50
+ */
51
+ exports.LogLevelNames = {
52
+ [LogLevel.DEBUG]: 'DEBUG',
53
+ [LogLevel.INFO]: 'INFO',
54
+ [LogLevel.WARN]: 'WARN',
55
+ [LogLevel.ERROR]: 'ERROR',
56
+ [LogLevel.NONE]: 'NONE'
57
+ };
@@ -0,0 +1,171 @@
1
+ import { LogLevel } from './LogLevel';
2
+ /**
3
+ * Structured log entity
4
+ */
5
+ export interface LogEntry {
6
+ /**
7
+ * Timestamp when the log entry was created
8
+ */
9
+ timestamp: Date;
10
+ /**
11
+ * Log severity level
12
+ */
13
+ level: LogLevel;
14
+ /**
15
+ * Log message
16
+ */
17
+ message: string;
18
+ /**
19
+ * Additional context information
20
+ */
21
+ context?: Record<string, unknown>;
22
+ /**
23
+ * SQL query (for query logs)
24
+ */
25
+ sql?: string;
26
+ /**
27
+ * Query parameters (for query logs)
28
+ */
29
+ params?: unknown[];
30
+ /**
31
+ * Query execution duration in milliseconds (for query logs)
32
+ */
33
+ duration?: number;
34
+ }
35
+ /**
36
+ * Logger configuration options
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const loggerConfig: LoggerConfig = {
41
+ * level: LogLevel.DEBUG,
42
+ * logQueries: true,
43
+ * logErrors: true,
44
+ * customLogger: (entry) => {
45
+ * // Send to external logging service
46
+ * winston.log(entry);
47
+ * }
48
+ * };
49
+ * ```
50
+ */
51
+ export interface LoggerConfig {
52
+ /**
53
+ * Minimum log level to output (default: INFO)
54
+ */
55
+ level: LogLevel;
56
+ /**
57
+ * Whether to log SQL queries (default: true)
58
+ */
59
+ logQueries?: boolean;
60
+ /**
61
+ * Whether to log errors (default: true)
62
+ */
63
+ logErrors?: boolean;
64
+ /**
65
+ * Custom logger function for integration with external logging services
66
+ */
67
+ customLogger?: (entry: LogEntry) => void;
68
+ }
69
+ /**
70
+ *
71
+ */
72
+ export declare class Logger {
73
+ private config;
74
+ /**
75
+ * Creates a new Logger instance
76
+ *
77
+ * @param config - Logger configuration options
78
+ */
79
+ constructor(config?: Partial<LoggerConfig>);
80
+ /**
81
+ * Check if a log level should be output
82
+ */
83
+ private shouldLog;
84
+ /**
85
+ * Format a log entry as a string for console output
86
+ */
87
+ private formatMessage;
88
+ /**
89
+ * Internal log method that handle output
90
+ */
91
+ private log;
92
+ /**
93
+ * Log a debig message
94
+ *
95
+ * @param message - The message to log
96
+ * @param context - Additional context information
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * logger.debug('Building query', { table: 'users', operation: 'SELECT' });
101
+ * ```
102
+ */
103
+ debug(message: string, context?: Record<string, unknown>): void;
104
+ /**
105
+ * Log an info message
106
+ *
107
+ * @param message - The message to log
108
+ * @param context - Additional context information
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * logger.info('Connection established', { host: 'localhost', database: 'mydb' })
113
+ * ```
114
+ */
115
+ info(message: string, context?: Record<string, unknown>): void;
116
+ /**
117
+ * Log an warning message
118
+ *
119
+ * @param message - The message to log
120
+ * @param context - Additional context information
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * logger.warn('Query slow', { duration: 5000, threshold: 1000 })
125
+ * ```
126
+ */
127
+ warn(message: string, context?: Record<string, unknown>): void;
128
+ /**
129
+ * Log an warning message
130
+ *
131
+ * @param message - The message to log
132
+ * @param error - The error object (optional)
133
+ * @param context - Additional context information
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * logger.error('Query failed', { query: 'SELECT * FROM users' })
138
+ * ```
139
+ */
140
+ error(message: string, error?: Error, context?: Record<string, unknown>): void;
141
+ /**
142
+ * Log an warning message
143
+ *
144
+ * @param message - The message to log
145
+ * @param error - The error object (optional)
146
+ * @param context - Additional context information
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * logger.error('Query failed', { query: 'SELECT * FROM users' })
151
+ * ```
152
+ */
153
+ query(sql: string, params?: unknown[], duration?: number): void;
154
+ /**
155
+ * Set the minimum log level
156
+ *
157
+ * @param level - The new log level
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * logger.setLevel(LogLevel.ERROR); // Only show errors
162
+ * ```
163
+ */
164
+ setLevel(level: LogLevel): void;
165
+ /**
166
+ * Get the current log level
167
+ *
168
+ * @returns the current log level
169
+ */
170
+ getLevel(): LogLevel;
171
+ }
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Logger = void 0;
4
+ const LogLevel_1 = require("./LogLevel");
5
+ const LogLevel_2 = require("./LogLevel");
6
+ /**
7
+ *
8
+ */
9
+ class Logger {
10
+ /**
11
+ * Creates a new Logger instance
12
+ *
13
+ * @param config - Logger configuration options
14
+ */
15
+ constructor(config = {}) {
16
+ this.config = {
17
+ level: config.level ?? LogLevel_1.LogLevel.INFO,
18
+ logQueries: config.logQueries ?? true,
19
+ logErrors: config.logErrors ?? true,
20
+ customLogger: config.customLogger
21
+ };
22
+ }
23
+ /**
24
+ * Check if a log level should be output
25
+ */
26
+ shouldLog(level) {
27
+ return level >= this.config.level;
28
+ }
29
+ /**
30
+ * Format a log entry as a string for console output
31
+ */
32
+ formatMessage(entry) {
33
+ const timestamp = entry.timestamp.toISOString();
34
+ const level = LogLevel_2.LogLevelNames[entry.level];
35
+ let message = `[${timestamp}] ${level}: ${entry.message}`;
36
+ if (entry.sql) {
37
+ message += `\n SQL: ${entry.sql}`;
38
+ }
39
+ if (entry.params && entry.params.length > 0) {
40
+ message += `\n Params: ${JSON.stringify(entry.params)}`;
41
+ }
42
+ if (entry.duration) {
43
+ message += `\n Duration: ${entry.duration}ms`;
44
+ }
45
+ if (entry.context) {
46
+ message += `\n Context: ${JSON.stringify(entry.context, null, 2)}`;
47
+ }
48
+ return message;
49
+ }
50
+ /**
51
+ * Internal log method that handle output
52
+ */
53
+ log(entry) {
54
+ if (!this.shouldLog(entry.level)) {
55
+ return;
56
+ }
57
+ if (this.config.customLogger) {
58
+ this.config.customLogger(entry);
59
+ }
60
+ else {
61
+ const message = this.formatMessage(entry);
62
+ switch (entry.level) {
63
+ case LogLevel_1.LogLevel.DEBUG:
64
+ case LogLevel_1.LogLevel.INFO:
65
+ console.log(message);
66
+ break;
67
+ case LogLevel_1.LogLevel.WARN:
68
+ console.warn(message);
69
+ break;
70
+ case LogLevel_1.LogLevel.ERROR:
71
+ console.error(message);
72
+ break;
73
+ }
74
+ }
75
+ }
76
+ /**
77
+ * Log a debig message
78
+ *
79
+ * @param message - The message to log
80
+ * @param context - Additional context information
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * logger.debug('Building query', { table: 'users', operation: 'SELECT' });
85
+ * ```
86
+ */
87
+ debug(message, context) {
88
+ this.log({
89
+ timestamp: new Date(),
90
+ level: LogLevel_1.LogLevel.DEBUG,
91
+ message,
92
+ context
93
+ });
94
+ }
95
+ /**
96
+ * Log an info message
97
+ *
98
+ * @param message - The message to log
99
+ * @param context - Additional context information
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * logger.info('Connection established', { host: 'localhost', database: 'mydb' })
104
+ * ```
105
+ */
106
+ info(message, context) {
107
+ this.log({
108
+ timestamp: new Date(),
109
+ level: LogLevel_1.LogLevel.INFO,
110
+ message,
111
+ context
112
+ });
113
+ }
114
+ /**
115
+ * Log an warning message
116
+ *
117
+ * @param message - The message to log
118
+ * @param context - Additional context information
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * logger.warn('Query slow', { duration: 5000, threshold: 1000 })
123
+ * ```
124
+ */
125
+ warn(message, context) {
126
+ this.log({
127
+ timestamp: new Date(),
128
+ level: LogLevel_1.LogLevel.WARN,
129
+ message,
130
+ context
131
+ });
132
+ }
133
+ /**
134
+ * Log an warning message
135
+ *
136
+ * @param message - The message to log
137
+ * @param error - The error object (optional)
138
+ * @param context - Additional context information
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * logger.error('Query failed', { query: 'SELECT * FROM users' })
143
+ * ```
144
+ */
145
+ error(message, error, context) {
146
+ if (!this.config.logErrors) {
147
+ return;
148
+ }
149
+ this.log({
150
+ timestamp: new Date(),
151
+ level: LogLevel_1.LogLevel.ERROR,
152
+ message,
153
+ context: {
154
+ ...context,
155
+ error: error?.message,
156
+ stack: error?.stack
157
+ }
158
+ });
159
+ }
160
+ /**
161
+ * Log an warning message
162
+ *
163
+ * @param message - The message to log
164
+ * @param error - The error object (optional)
165
+ * @param context - Additional context information
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * logger.error('Query failed', { query: 'SELECT * FROM users' })
170
+ * ```
171
+ */
172
+ query(sql, params, duration) {
173
+ if (!this.config.logQueries) {
174
+ return;
175
+ }
176
+ this.log({
177
+ timestamp: new Date(),
178
+ level: LogLevel_1.LogLevel.DEBUG,
179
+ message: 'Query Executed',
180
+ sql,
181
+ params,
182
+ duration
183
+ });
184
+ }
185
+ /**
186
+ * Set the minimum log level
187
+ *
188
+ * @param level - The new log level
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * logger.setLevel(LogLevel.ERROR); // Only show errors
193
+ * ```
194
+ */
195
+ setLevel(level) {
196
+ this.config.level = level;
197
+ }
198
+ /**
199
+ * Get the current log level
200
+ *
201
+ * @returns the current log level
202
+ */
203
+ getLevel() {
204
+ return this.config.level;
205
+ }
206
+ }
207
+ exports.Logger = Logger;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Logging system for Accio ORM
3
+ *
4
+ * Provides configurable logging with support for different log levels.
5
+ * query logging, and custom logger integration.
6
+ */
7
+ export { type LogEntry, Logger, type LoggerConfig } from './Logger';
8
+ export { LogLevel, LogLevelNames } from './LogLevel';
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ /**
3
+ * Logging system for Accio ORM
4
+ *
5
+ * Provides configurable logging with support for different log levels.
6
+ * query logging, and custom logger integration.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.LogLevelNames = exports.LogLevel = exports.Logger = void 0;
10
+ var Logger_1 = require("./Logger");
11
+ Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return Logger_1.Logger; } });
12
+ var LogLevel_1 = require("./LogLevel");
13
+ Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return LogLevel_1.LogLevel; } });
14
+ Object.defineProperty(exports, "LogLevelNames", { enumerable: true, get: function () { return LogLevel_1.LogLevelNames; } });
@@ -20,7 +20,7 @@ export declare class MetadataStorage {
20
20
  * @param entityClass
21
21
  * @returns get the table name
22
22
  */
23
- static getTableName(entityCLass: EntityConstructor): string;
23
+ static getTableName(entityClass: EntityConstructor): string;
24
24
  static getColumns(entityClass: EntityConstructor): ColumnMetadata[];
25
25
  static getPrimaryColumn(entityClass: EntityConstructor): ColumnMetadata;
26
26
  /**
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MetadataStorage = void 0;
4
4
  const Column_1 = require("@/decorators/Column");
5
5
  const Table_1 = require("@/decorators/Table");
6
+ const errors_1 = require("@/errors");
6
7
  class MetadataStorage {
7
8
  /**
8
9
  * Extract all metadata from an entity class
@@ -16,24 +17,24 @@ class MetadataStorage {
16
17
  }
17
18
  const tableName = (0, Table_1.getTableName)(entityClass);
18
19
  if (!tableName) {
19
- throw new Error(`Entity ${entityClass.name} is missing @Table decorator.
20
+ throw new errors_1.ValidationError(`Entity ${entityClass.name} is missing @Table decorator.
20
21
  Did you forget to add @Table('table_name') to the class?
21
- `);
22
+ `, 'decorator', '@Table', { entityClass: entityClass.name });
22
23
  }
23
24
  const columns = (0, Column_1.getColumns)(entityClass);
24
25
  if (columns.length === 0) {
25
- throw new Error(`Entity ${entityClass.name} has no columns defined.
26
- Did you forget to add @Column() or @PrimaryColumn() decorators?`);
26
+ throw new errors_1.ValidationError(`Entity ${entityClass.name} has no columns defined.
27
+ Did you forget to add @Column() or @PrimaryColumn() decorators?`, 'decorator', '@Column', { entityClass: entityClass.name });
27
28
  }
28
29
  const primaryColumns = columns.filter((col) => col.isPrimary);
29
30
  if (primaryColumns.length === 0) {
30
- throw new Error(`Entity ${entityClass.name} has no primary key defined.
31
- Add @PrimaryColumn() to one of your properties.`);
31
+ throw new errors_1.ValidationError(`Entity ${entityClass.name} has no primary key defined.
32
+ Add @PrimaryColumn() to one of your properties.`, 'decorator', '@PrimaryColumn', { entityClass: entityClass.name });
32
33
  }
33
34
  if (primaryColumns.length > 1) {
34
- throw new Error(`Entity ${entityClass.name} has multiple primary keys:
35
+ throw new errors_1.ValidationError(`Entity ${entityClass.name} has multiple primary keys:
35
36
  ${primaryColumns.map((c) => c.propertyKey).join(', ')}.
36
- Only one primary key is supported.`);
37
+ Only one primary key is supported.`, 'primarykey', primaryColumns.map((c) => c.propertyKey), { entityClass: entityClass.name });
37
38
  }
38
39
  const primaryColumn = primaryColumns[0];
39
40
  const metadata = {
@@ -58,8 +59,8 @@ class MetadataStorage {
58
59
  * @param entityClass
59
60
  * @returns get the table name
60
61
  */
61
- static getTableName(entityCLass) {
62
- return this.getEntityMetadata(entityCLass).tableName;
62
+ static getTableName(entityClass) {
63
+ return this.getEntityMetadata(entityClass).tableName;
63
64
  }
64
65
  static getColumns(entityClass) {
65
66
  return this.getEntityMetadata(entityClass).columns;
@@ -67,7 +68,7 @@ class MetadataStorage {
67
68
  static getPrimaryColumn(entityClass) {
68
69
  const metadata = this.getEntityMetadata(entityClass);
69
70
  if (!metadata.primaryColumn) {
70
- throw new Error(`Entity ${entityClass.name} has no primary key`);
71
+ throw new errors_1.ValidationError(`Entity ${entityClass.name} has no primary key ddefined`, 'primaryKey', undefined, { entityClass: entityClass.name });
71
72
  }
72
73
  return metadata.primaryColumn;
73
74
  }
@@ -11,11 +11,6 @@ export declare class QueryBuilder<T> {
11
11
  private orderByColumn?;
12
12
  private orderDirection;
13
13
  constructor(repository: Repository<T>, connection: Connection, metadata: EntityMetadata, initialConditions?: Partial<T>);
14
- /**
15
- * Map a database row to an entity instance
16
- * @private
17
- */
18
- private mapRowToEntity;
19
14
  /**
20
15
  * Add WHERE conditions (can be chained multiple times)
21
16
  * Multiple calls to where() are combined with AND
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QueryBuilder = void 0;
4
+ const validation_1 = require("@/validation");
4
5
  const entityMapper_1 = require("../utils/entityMapper");
5
6
  class QueryBuilder {
6
7
  constructor(repository, connection, metadata, initialConditions) {
@@ -13,21 +14,6 @@ class QueryBuilder {
13
14
  this.conditions.push(initialConditions);
14
15
  }
15
16
  }
16
- /**
17
- * Map a database row to an entity instance
18
- * @private
19
- */
20
- mapRowToEntity(row) {
21
- // Get the entity class from the repository
22
- const entityClass = this.repository.getEntityClass();
23
- const entity = new entityClass();
24
- // Map each column from the database row to the entity property
25
- this.metadata.columns.forEach((col) => {
26
- const value = row[col.columnName];
27
- entity[col.propertyKey] = value;
28
- });
29
- return entity;
30
- }
31
17
  /**
32
18
  * Add WHERE conditions (can be chained multiple times)
33
19
  * Multiple calls to where() are combined with AND
@@ -40,9 +26,7 @@ class QueryBuilder {
40
26
  * Set the maximum number of results to return
41
27
  */
42
28
  limit(value) {
43
- if (value < 0) {
44
- throw new Error('Limit must be a positive number');
45
- }
29
+ validation_1.QueryValidator.validateLimit(value);
46
30
  this.limitValue = value;
47
31
  return this;
48
32
  }
@@ -50,9 +34,7 @@ class QueryBuilder {
50
34
  * Set the number of results to skip
51
35
  */
52
36
  offset(value) {
53
- if (value < 0) {
54
- throw new Error('Offset must be a positive number');
55
- }
37
+ validation_1.QueryValidator.validateOffset(value);
56
38
  this.offsetValue = value;
57
39
  return this;
58
40
  }
@@ -60,12 +42,11 @@ class QueryBuilder {
60
42
  * Order results by a column
61
43
  */
62
44
  orderBy(column, direction = 'ASC') {
63
- // Validate that the column exists
45
+ // validate direction
46
+ validation_1.QueryValidator.validateOrderDirection(direction);
47
+ // validate that property exists in metadata
48
+ validation_1.identifierValidator.validatePropertyExists(column, this.metadata, 'ORDER BY');
64
49
  const columnMeta = this.metadata.columns.find((col) => col.propertyKey === column);
65
- if (!columnMeta) {
66
- throw new Error(`Column '${column}' does not exist on entity. ` +
67
- `Available columns: ${this.metadata.columns.map((c) => c.propertyKey).join(', ')}`);
68
- }
69
50
  this.orderByColumn = columnMeta.columnName;
70
51
  this.orderDirection = direction;
71
52
  return this;
@@ -119,13 +100,11 @@ class QueryBuilder {
119
100
  const whereClauses = [];
120
101
  this.conditions.forEach((condition) => {
121
102
  Object.entries(condition).forEach(([key, value]) => {
103
+ // validate that the property exists in metadata
104
+ validation_1.identifierValidator.validatePropertyExists(key, this.metadata, 'WHERE clause');
122
105
  // find column metadata for this property
123
106
  const column = this.metadata.columns.find((col) => col.propertyKey === key);
124
- if (!column) {
125
- throw new Error(`Property '${key}' does not exist on entity ${this.metadata.tableName}. ` +
126
- `Available properties: ${this.metadata.columns.map((c) => c.propertyKey).join(', ')}`);
127
- }
128
- // Hanfle different value types
107
+ // Handle different value types
129
108
  if (value === null) {
130
109
  whereClauses.push(`${column.columnName} IS NULL`);
131
110
  }