@ductape/sdk 0.0.4-v42 → 0.0.4-v43

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 (76) hide show
  1. package/dist/apps/services/app.service.d.ts +10 -0
  2. package/dist/apps/services/app.service.js +22 -0
  3. package/dist/apps/services/app.service.js.map +1 -1
  4. package/dist/database/adapters/base.adapter.d.ts +176 -0
  5. package/dist/database/adapters/base.adapter.js +31 -0
  6. package/dist/database/adapters/base.adapter.js.map +1 -0
  7. package/dist/database/adapters/dynamodb.adapter.d.ts +83 -0
  8. package/dist/database/adapters/dynamodb.adapter.js +1237 -0
  9. package/dist/database/adapters/dynamodb.adapter.js.map +1 -0
  10. package/dist/database/adapters/mongodb.adapter.d.ts +70 -0
  11. package/dist/database/adapters/mongodb.adapter.js +717 -0
  12. package/dist/database/adapters/mongodb.adapter.js.map +1 -0
  13. package/dist/database/adapters/mysql.adapter.d.ts +141 -0
  14. package/dist/database/adapters/mysql.adapter.js +1221 -0
  15. package/dist/database/adapters/mysql.adapter.js.map +1 -0
  16. package/dist/database/adapters/postgresql.adapter.d.ts +142 -0
  17. package/dist/database/adapters/postgresql.adapter.js +1288 -0
  18. package/dist/database/adapters/postgresql.adapter.js.map +1 -0
  19. package/dist/database/database.service.d.ts +190 -0
  20. package/dist/database/database.service.js +552 -0
  21. package/dist/database/database.service.js.map +1 -0
  22. package/dist/database/index.d.ts +18 -0
  23. package/dist/database/index.js +98 -0
  24. package/dist/database/index.js.map +1 -0
  25. package/dist/database/types/aggregation.types.d.ts +202 -0
  26. package/dist/database/types/aggregation.types.js +21 -0
  27. package/dist/database/types/aggregation.types.js.map +1 -0
  28. package/dist/database/types/connection.types.d.ts +132 -0
  29. package/dist/database/types/connection.types.js +6 -0
  30. package/dist/database/types/connection.types.js.map +1 -0
  31. package/dist/database/types/database.types.d.ts +173 -0
  32. package/dist/database/types/database.types.js +73 -0
  33. package/dist/database/types/database.types.js.map +1 -0
  34. package/dist/database/types/index.d.ts +12 -0
  35. package/dist/database/types/index.js +37 -0
  36. package/dist/database/types/index.js.map +1 -0
  37. package/dist/database/types/index.types.d.ts +220 -0
  38. package/dist/database/types/index.types.js +27 -0
  39. package/dist/database/types/index.types.js.map +1 -0
  40. package/dist/database/types/migration.types.d.ts +205 -0
  41. package/dist/database/types/migration.types.js +44 -0
  42. package/dist/database/types/migration.types.js.map +1 -0
  43. package/dist/database/types/query.types.d.ts +274 -0
  44. package/dist/database/types/query.types.js +57 -0
  45. package/dist/database/types/query.types.js.map +1 -0
  46. package/dist/database/types/result.types.d.ts +218 -0
  47. package/dist/database/types/result.types.js +6 -0
  48. package/dist/database/types/result.types.js.map +1 -0
  49. package/dist/database/types/schema.types.d.ts +190 -0
  50. package/dist/database/types/schema.types.js +69 -0
  51. package/dist/database/types/schema.types.js.map +1 -0
  52. package/dist/database/utils/helpers.d.ts +66 -0
  53. package/dist/database/utils/helpers.js +501 -0
  54. package/dist/database/utils/helpers.js.map +1 -0
  55. package/dist/database/utils/migration.utils.d.ts +151 -0
  56. package/dist/database/utils/migration.utils.js +476 -0
  57. package/dist/database/utils/migration.utils.js.map +1 -0
  58. package/dist/database/utils/transaction.d.ts +64 -0
  59. package/dist/database/utils/transaction.js +130 -0
  60. package/dist/database/utils/transaction.js.map +1 -0
  61. package/dist/database/validators/connection.validator.d.ts +20 -0
  62. package/dist/database/validators/connection.validator.js +267 -0
  63. package/dist/database/validators/connection.validator.js.map +1 -0
  64. package/dist/database/validators/query.validator.d.ts +31 -0
  65. package/dist/database/validators/query.validator.js +305 -0
  66. package/dist/database/validators/query.validator.js.map +1 -0
  67. package/dist/database/validators/schema.validator.d.ts +31 -0
  68. package/dist/database/validators/schema.validator.js +334 -0
  69. package/dist/database/validators/schema.validator.js.map +1 -0
  70. package/dist/index.d.ts +25 -4
  71. package/dist/index.js +36 -4
  72. package/dist/index.js.map +1 -1
  73. package/dist/processor/services/processor.service.js +10 -8
  74. package/dist/processor/services/processor.service.js.map +1 -1
  75. package/dist/types/processor.types.d.ts +2 -2
  76. package/package.json +3 -1
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ /**
3
+ * Query Validator
4
+ * Validates query options and data
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.validateQueryOptions = validateQueryOptions;
8
+ exports.validateInsertData = validateInsertData;
9
+ exports.validateUpdateData = validateUpdateData;
10
+ exports.assertValidQueryOptions = assertValidQueryOptions;
11
+ exports.assertValidInsertData = assertValidInsertData;
12
+ exports.assertValidUpdateData = assertValidUpdateData;
13
+ const query_types_1 = require("../types/query.types");
14
+ const schema_types_1 = require("../types/schema.types");
15
+ /**
16
+ * Validate query options
17
+ */
18
+ function validateQueryOptions(options) {
19
+ const errors = [];
20
+ if (!options) {
21
+ return { valid: true, errors: [] };
22
+ }
23
+ // Validate limit
24
+ if (options.limit !== undefined) {
25
+ if (typeof options.limit !== 'number') {
26
+ errors.push('limit must be a number');
27
+ }
28
+ else if (options.limit < 1) {
29
+ errors.push('limit must be a positive number');
30
+ }
31
+ else if (!Number.isInteger(options.limit)) {
32
+ errors.push('limit must be an integer');
33
+ }
34
+ }
35
+ // Validate offset
36
+ if (options.offset !== undefined) {
37
+ if (typeof options.offset !== 'number') {
38
+ errors.push('offset must be a number');
39
+ }
40
+ else if (options.offset < 0) {
41
+ errors.push('offset must be a non-negative number');
42
+ }
43
+ else if (!Number.isInteger(options.offset)) {
44
+ errors.push('offset must be an integer');
45
+ }
46
+ }
47
+ // Validate orderBy
48
+ if (options.orderBy) {
49
+ const orderByArray = Array.isArray(options.orderBy) ? options.orderBy : [options.orderBy];
50
+ orderByArray.forEach((orderBy, index) => {
51
+ if (!orderBy.column || typeof orderBy.column !== 'string') {
52
+ errors.push(`orderBy[${index}]: column is required and must be a string`);
53
+ }
54
+ if (orderBy.order !== query_types_1.SortOrder.ASC && orderBy.order !== query_types_1.SortOrder.DESC) {
55
+ errors.push(`orderBy[${index}]: order must be "${query_types_1.SortOrder.ASC}" or "${query_types_1.SortOrder.DESC}"`);
56
+ }
57
+ });
58
+ }
59
+ // Validate select
60
+ if (options.select) {
61
+ if (!Array.isArray(options.select)) {
62
+ errors.push('select must be an array');
63
+ }
64
+ else if (options.select.length === 0) {
65
+ errors.push('select array cannot be empty');
66
+ }
67
+ else {
68
+ options.select.forEach((field, index) => {
69
+ if (typeof field !== 'string' || field.length === 0) {
70
+ errors.push(`select[${index}] must be a non-empty string`);
71
+ }
72
+ });
73
+ }
74
+ }
75
+ // Validate groupBy
76
+ if (options.groupBy) {
77
+ if (!Array.isArray(options.groupBy)) {
78
+ errors.push('groupBy must be an array');
79
+ }
80
+ else if (options.groupBy.length === 0) {
81
+ errors.push('groupBy array cannot be empty');
82
+ }
83
+ else {
84
+ options.groupBy.forEach((field, index) => {
85
+ if (typeof field !== 'string' || field.length === 0) {
86
+ errors.push(`groupBy[${index}] must be a non-empty string`);
87
+ }
88
+ });
89
+ }
90
+ }
91
+ // Validate distinct
92
+ if (options.distinct !== undefined && typeof options.distinct !== 'boolean') {
93
+ errors.push('distinct must be a boolean');
94
+ }
95
+ return {
96
+ valid: errors.length === 0,
97
+ errors,
98
+ };
99
+ }
100
+ /**
101
+ * Validate insert data against column definitions
102
+ */
103
+ function validateInsertData(data, columns) {
104
+ const errors = [];
105
+ if (!data) {
106
+ errors.push('Insert data is required');
107
+ return { valid: false, errors };
108
+ }
109
+ const records = Array.isArray(data) ? data : [data];
110
+ if (records.length === 0) {
111
+ errors.push('Insert data cannot be empty');
112
+ return { valid: false, errors };
113
+ }
114
+ records.forEach((record, index) => {
115
+ validateSingleInsertRecord(record, columns, `Record ${index}`, errors);
116
+ });
117
+ return {
118
+ valid: errors.length === 0,
119
+ errors,
120
+ };
121
+ }
122
+ /**
123
+ * Validate a single insert record
124
+ */
125
+ function validateSingleInsertRecord(record, columns, prefix, errors) {
126
+ if (!record || typeof record !== 'object') {
127
+ errors.push(`${prefix} must be an object`);
128
+ return;
129
+ }
130
+ const columnMap = new Map(columns.map((c) => [c.name, c]));
131
+ const providedFields = Object.keys(record);
132
+ // Check for required fields (non-nullable, no default, no auto-increment)
133
+ columns.forEach((column) => {
134
+ const isRequired = !column.nullable && column.defaultValue === undefined && !column.autoIncrement && !column.primaryKey;
135
+ if (isRequired && !providedFields.includes(column.name)) {
136
+ errors.push(`${prefix}: required field "${column.name}" is missing`);
137
+ }
138
+ });
139
+ // Validate each provided field
140
+ Object.entries(record).forEach(([field, value]) => {
141
+ const column = columnMap.get(field);
142
+ if (!column) {
143
+ errors.push(`${prefix}: field "${field}" does not exist in table schema`);
144
+ return;
145
+ }
146
+ // Validate value type
147
+ validateFieldValue(value, column, `${prefix}.${field}`, errors);
148
+ });
149
+ }
150
+ /**
151
+ * Validate update data against column definitions
152
+ */
153
+ function validateUpdateData(data, columns) {
154
+ const errors = [];
155
+ if (!data || typeof data !== 'object') {
156
+ errors.push('Update data must be an object');
157
+ return { valid: false, errors };
158
+ }
159
+ if (Object.keys(data).length === 0) {
160
+ errors.push('Update data cannot be empty');
161
+ return { valid: false, errors };
162
+ }
163
+ const columnMap = new Map(columns.map((c) => [c.name, c]));
164
+ Object.entries(data).forEach(([field, value]) => {
165
+ const column = columnMap.get(field);
166
+ if (!column) {
167
+ errors.push(`Field "${field}" does not exist in table schema`);
168
+ return;
169
+ }
170
+ // Cannot update primary key
171
+ if (column.primaryKey) {
172
+ errors.push(`Cannot update primary key field "${field}"`);
173
+ return;
174
+ }
175
+ // Cannot update auto-increment fields
176
+ if (column.autoIncrement) {
177
+ errors.push(`Cannot update auto-increment field "${field}"`);
178
+ return;
179
+ }
180
+ // Validate value type
181
+ validateFieldValue(value, column, field, errors);
182
+ });
183
+ return {
184
+ valid: errors.length === 0,
185
+ errors,
186
+ };
187
+ }
188
+ /**
189
+ * Validate a field value against its column definition
190
+ */
191
+ function validateFieldValue(value, column, prefix, errors) {
192
+ // Null values
193
+ if (value === null || value === undefined) {
194
+ if (!column.nullable) {
195
+ errors.push(`${prefix}: null value not allowed for non-nullable column`);
196
+ }
197
+ return;
198
+ }
199
+ // Type-specific validation
200
+ switch (column.type) {
201
+ case schema_types_1.ColumnType.STRING:
202
+ case schema_types_1.ColumnType.VARCHAR:
203
+ case schema_types_1.ColumnType.CHAR:
204
+ case schema_types_1.ColumnType.TEXT:
205
+ if (typeof value !== 'string') {
206
+ errors.push(`${prefix}: expected string, got ${typeof value}`);
207
+ }
208
+ else if (column.length && value.length > column.length) {
209
+ errors.push(`${prefix}: string length ${value.length} exceeds maximum ${column.length}`);
210
+ }
211
+ break;
212
+ case schema_types_1.ColumnType.INTEGER:
213
+ case schema_types_1.ColumnType.BIGINT:
214
+ case schema_types_1.ColumnType.SMALLINT:
215
+ if (typeof value !== 'number') {
216
+ errors.push(`${prefix}: expected number, got ${typeof value}`);
217
+ }
218
+ else if (!Number.isInteger(value)) {
219
+ errors.push(`${prefix}: expected integer, got decimal`);
220
+ }
221
+ break;
222
+ case schema_types_1.ColumnType.DECIMAL:
223
+ case schema_types_1.ColumnType.NUMERIC:
224
+ case schema_types_1.ColumnType.FLOAT:
225
+ case schema_types_1.ColumnType.DOUBLE:
226
+ case schema_types_1.ColumnType.REAL:
227
+ if (typeof value !== 'number') {
228
+ errors.push(`${prefix}: expected number, got ${typeof value}`);
229
+ }
230
+ break;
231
+ case schema_types_1.ColumnType.BOOLEAN:
232
+ if (typeof value !== 'boolean') {
233
+ errors.push(`${prefix}: expected boolean, got ${typeof value}`);
234
+ }
235
+ break;
236
+ case schema_types_1.ColumnType.DATE:
237
+ case schema_types_1.ColumnType.DATETIME:
238
+ case schema_types_1.ColumnType.TIMESTAMP:
239
+ case schema_types_1.ColumnType.TIME:
240
+ if (!(value instanceof Date) && typeof value !== 'string') {
241
+ errors.push(`${prefix}: expected Date or string, got ${typeof value}`);
242
+ }
243
+ break;
244
+ case schema_types_1.ColumnType.JSON:
245
+ case schema_types_1.ColumnType.JSONB:
246
+ case schema_types_1.ColumnType.OBJECT:
247
+ // Any value is valid for JSON (will be serialized)
248
+ break;
249
+ case schema_types_1.ColumnType.UUID:
250
+ if (typeof value !== 'string') {
251
+ errors.push(`${prefix}: expected string UUID, got ${typeof value}`);
252
+ }
253
+ else if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) {
254
+ errors.push(`${prefix}: invalid UUID format`);
255
+ }
256
+ break;
257
+ case schema_types_1.ColumnType.ENUM:
258
+ if (typeof value !== 'string') {
259
+ errors.push(`${prefix}: expected string for ENUM type, got ${typeof value}`);
260
+ }
261
+ else if (column.enumValues && !column.enumValues.includes(value)) {
262
+ errors.push(`${prefix}: value "${value}" not in allowed enum values: ${column.enumValues.join(', ')}`);
263
+ }
264
+ break;
265
+ case schema_types_1.ColumnType.BLOB:
266
+ case schema_types_1.ColumnType.BINARY:
267
+ if (!Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
268
+ errors.push(`${prefix}: expected Buffer or Uint8Array, got ${typeof value}`);
269
+ }
270
+ break;
271
+ case schema_types_1.ColumnType.ARRAY:
272
+ if (!Array.isArray(value)) {
273
+ errors.push(`${prefix}: expected array, got ${typeof value}`);
274
+ }
275
+ break;
276
+ }
277
+ }
278
+ /**
279
+ * Throw an error if query options validation fails
280
+ */
281
+ function assertValidQueryOptions(options) {
282
+ const result = validateQueryOptions(options);
283
+ if (!result.valid) {
284
+ throw new Error(`Invalid query options:\n${result.errors.join('\n')}`);
285
+ }
286
+ }
287
+ /**
288
+ * Throw an error if insert data validation fails
289
+ */
290
+ function assertValidInsertData(data, columns) {
291
+ const result = validateInsertData(data, columns);
292
+ if (!result.valid) {
293
+ throw new Error(`Invalid insert data:\n${result.errors.join('\n')}`);
294
+ }
295
+ }
296
+ /**
297
+ * Throw an error if update data validation fails
298
+ */
299
+ function assertValidUpdateData(data, columns) {
300
+ const result = validateUpdateData(data, columns);
301
+ if (!result.valid) {
302
+ throw new Error(`Invalid update data:\n${result.errors.join('\n')}`);
303
+ }
304
+ }
305
+ //# sourceMappingURL=query.validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.validator.js","sourceRoot":"","sources":["../../../src/database/validators/query.validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Schema Validator
3
+ * Validates table schemas, column definitions, indexes, and constraints
4
+ */
5
+ import { ITableSchema, IColumnDefinition } from '../types/schema.types';
6
+ import { IIndexDefinition } from '../types/index.types';
7
+ import { IValidationResult } from './connection.validator';
8
+ /**
9
+ * Validate a table schema
10
+ */
11
+ export declare function validateTableSchema(schema: ITableSchema): IValidationResult;
12
+ /**
13
+ * Validate column definition
14
+ */
15
+ export declare function validateColumnDefinition(column: IColumnDefinition, prefix: string, errors: string[]): void;
16
+ /**
17
+ * Validate index definition
18
+ */
19
+ export declare function validateIndexDefinition(index: IIndexDefinition, columns: IColumnDefinition[], prefix: string, errors: string[]): void;
20
+ /**
21
+ * Throw an error if schema validation fails
22
+ */
23
+ export declare function assertValidTableSchema(schema: ITableSchema): void;
24
+ /**
25
+ * Throw an error if column validation fails
26
+ */
27
+ export declare function assertValidColumn(column: IColumnDefinition): void;
28
+ /**
29
+ * Throw an error if index validation fails
30
+ */
31
+ export declare function assertValidIndex(index: IIndexDefinition, columns: IColumnDefinition[]): void;
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ /**
3
+ * Schema Validator
4
+ * Validates table schemas, column definitions, indexes, and constraints
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.validateTableSchema = validateTableSchema;
8
+ exports.validateColumnDefinition = validateColumnDefinition;
9
+ exports.validateIndexDefinition = validateIndexDefinition;
10
+ exports.assertValidTableSchema = assertValidTableSchema;
11
+ exports.assertValidColumn = assertValidColumn;
12
+ exports.assertValidIndex = assertValidIndex;
13
+ const schema_types_1 = require("../types/schema.types");
14
+ /**
15
+ * Validate a table schema
16
+ */
17
+ function validateTableSchema(schema) {
18
+ const errors = [];
19
+ // Validate table name
20
+ if (!schema.name || typeof schema.name !== 'string') {
21
+ errors.push('Table name is required and must be a string');
22
+ }
23
+ else {
24
+ validateTableName(schema.name, errors);
25
+ }
26
+ // Validate columns
27
+ if (!schema.columns || !Array.isArray(schema.columns)) {
28
+ errors.push('Columns array is required');
29
+ }
30
+ else {
31
+ if (schema.columns.length === 0) {
32
+ errors.push('At least one column is required');
33
+ }
34
+ // Validate each column
35
+ schema.columns.forEach((column, index) => {
36
+ validateColumnDefinition(column, `Column ${index}`, errors);
37
+ });
38
+ // Check for duplicate column names
39
+ const columnNames = schema.columns.map((c) => c.name);
40
+ const duplicates = columnNames.filter((name, index) => columnNames.indexOf(name) !== index);
41
+ if (duplicates.length > 0) {
42
+ errors.push(`Duplicate column names found: ${duplicates.join(', ')}`);
43
+ }
44
+ // Ensure at least one primary key exists
45
+ const hasPrimaryKey = schema.columns.some((c) => c.primaryKey);
46
+ if (!hasPrimaryKey) {
47
+ errors.push('At least one column must be marked as primary key');
48
+ }
49
+ }
50
+ // Validate indexes if present
51
+ if (schema.indexes) {
52
+ if (!Array.isArray(schema.indexes)) {
53
+ errors.push('Indexes must be an array');
54
+ }
55
+ else {
56
+ schema.indexes.forEach((index, i) => {
57
+ validateIndexDefinition(index, schema.columns || [], `Index ${i}`, errors);
58
+ });
59
+ }
60
+ }
61
+ return {
62
+ valid: errors.length === 0,
63
+ errors,
64
+ };
65
+ }
66
+ /**
67
+ * Validate table name
68
+ */
69
+ function validateTableName(name, errors) {
70
+ // Check length
71
+ if (name.length === 0) {
72
+ errors.push('Table name cannot be empty');
73
+ return;
74
+ }
75
+ if (name.length > 64) {
76
+ errors.push('Table name cannot exceed 64 characters');
77
+ }
78
+ // Check format (alphanumeric and underscores, must start with letter or underscore)
79
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
80
+ errors.push('Table name must start with a letter or underscore and contain only letters, numbers, and underscores');
81
+ }
82
+ // Check for reserved keywords (common SQL reserved words)
83
+ const reservedKeywords = [
84
+ 'select',
85
+ 'insert',
86
+ 'update',
87
+ 'delete',
88
+ 'drop',
89
+ 'create',
90
+ 'alter',
91
+ 'table',
92
+ 'index',
93
+ 'view',
94
+ 'user',
95
+ 'database',
96
+ 'schema',
97
+ 'order',
98
+ 'group',
99
+ 'where',
100
+ 'from',
101
+ 'join',
102
+ 'union',
103
+ ];
104
+ if (reservedKeywords.includes(name.toLowerCase())) {
105
+ errors.push(`Table name "${name}" is a reserved SQL keyword`);
106
+ }
107
+ }
108
+ /**
109
+ * Validate column name
110
+ */
111
+ function validateColumnName(name, prefix, errors) {
112
+ // Check length
113
+ if (name.length === 0) {
114
+ errors.push(`${prefix}: column name cannot be empty`);
115
+ return;
116
+ }
117
+ if (name.length > 64) {
118
+ errors.push(`${prefix}: column name cannot exceed 64 characters`);
119
+ }
120
+ // Check format
121
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
122
+ errors.push(`${prefix}: column name must start with a letter or underscore and contain only letters, numbers, and underscores`);
123
+ }
124
+ // Check for reserved keywords
125
+ const reservedKeywords = [
126
+ 'select',
127
+ 'insert',
128
+ 'update',
129
+ 'delete',
130
+ 'from',
131
+ 'where',
132
+ 'order',
133
+ 'group',
134
+ 'by',
135
+ 'having',
136
+ 'limit',
137
+ 'offset',
138
+ 'union',
139
+ 'join',
140
+ 'on',
141
+ 'as',
142
+ 'and',
143
+ 'or',
144
+ 'not',
145
+ 'null',
146
+ 'true',
147
+ 'false',
148
+ ];
149
+ if (reservedKeywords.includes(name.toLowerCase())) {
150
+ errors.push(`${prefix}: column name "${name}" is a reserved SQL keyword`);
151
+ }
152
+ }
153
+ /**
154
+ * Validate column definition
155
+ */
156
+ function validateColumnDefinition(column, prefix, errors) {
157
+ // Validate column name
158
+ if (!column.name || typeof column.name !== 'string') {
159
+ errors.push(`${prefix}: name is required and must be a string`);
160
+ }
161
+ else {
162
+ validateColumnName(column.name, prefix, errors);
163
+ }
164
+ // Validate column type
165
+ if (!column.type) {
166
+ errors.push(`${prefix}: type is required`);
167
+ }
168
+ else if (!Object.values(schema_types_1.ColumnType).includes(column.type)) {
169
+ errors.push(`${prefix}: invalid column type "${column.type}"`);
170
+ }
171
+ // Validate type-specific constraints
172
+ validateColumnTypeConstraints(column, prefix, errors);
173
+ // Validate nullable
174
+ if (column.nullable !== undefined && typeof column.nullable !== 'boolean') {
175
+ errors.push(`${prefix}: nullable must be a boolean`);
176
+ }
177
+ // Validate primaryKey
178
+ if (column.primaryKey !== undefined && typeof column.primaryKey !== 'boolean') {
179
+ errors.push(`${prefix}: primaryKey must be a boolean`);
180
+ }
181
+ // Validate unique
182
+ if (column.unique !== undefined && typeof column.unique !== 'boolean') {
183
+ errors.push(`${prefix}: unique must be a boolean`);
184
+ }
185
+ // Validate autoIncrement
186
+ if (column.autoIncrement !== undefined) {
187
+ if (typeof column.autoIncrement !== 'boolean') {
188
+ errors.push(`${prefix}: autoIncrement must be a boolean`);
189
+ }
190
+ // Auto-increment only valid for integer types
191
+ if (column.autoIncrement && column.type !== schema_types_1.ColumnType.INTEGER && column.type !== schema_types_1.ColumnType.BIGINT) {
192
+ errors.push(`${prefix}: autoIncrement is only valid for INTEGER and BIGINT types`);
193
+ }
194
+ }
195
+ // Primary key constraints
196
+ if (column.primaryKey) {
197
+ if (column.nullable) {
198
+ errors.push(`${prefix}: primary key columns cannot be nullable`);
199
+ }
200
+ }
201
+ // Validate comment
202
+ if (column.comment !== undefined && typeof column.comment !== 'string') {
203
+ errors.push(`${prefix}: comment must be a string`);
204
+ }
205
+ }
206
+ /**
207
+ * Validate column type-specific constraints
208
+ */
209
+ function validateColumnTypeConstraints(column, prefix, errors) {
210
+ switch (column.type) {
211
+ case schema_types_1.ColumnType.STRING:
212
+ case schema_types_1.ColumnType.VARCHAR:
213
+ if (column.length !== undefined) {
214
+ if (typeof column.length !== 'number' || column.length < 1) {
215
+ errors.push(`${prefix}: length must be a positive number for STRING/VARCHAR types`);
216
+ }
217
+ if (column.length > 65535) {
218
+ errors.push(`${prefix}: length cannot exceed 65535 for STRING/VARCHAR types`);
219
+ }
220
+ }
221
+ break;
222
+ case schema_types_1.ColumnType.DECIMAL:
223
+ if (column.precision !== undefined) {
224
+ if (typeof column.precision !== 'number' || column.precision < 1 || column.precision > 65) {
225
+ errors.push(`${prefix}: precision must be a number between 1 and 65 for DECIMAL type`);
226
+ }
227
+ }
228
+ if (column.scale !== undefined) {
229
+ if (typeof column.scale !== 'number' || column.scale < 0 || column.scale > 30) {
230
+ errors.push(`${prefix}: scale must be a number between 0 and 30 for DECIMAL type`);
231
+ }
232
+ if (column.precision !== undefined && column.scale > column.precision) {
233
+ errors.push(`${prefix}: scale cannot be greater than precision for DECIMAL type`);
234
+ }
235
+ }
236
+ break;
237
+ case schema_types_1.ColumnType.ENUM:
238
+ if (!column.enumValues || !Array.isArray(column.enumValues) || column.enumValues.length === 0) {
239
+ errors.push(`${prefix}: enumValues array is required for ENUM type`);
240
+ }
241
+ else {
242
+ // Validate enum values
243
+ column.enumValues.forEach((value, i) => {
244
+ if (typeof value !== 'string') {
245
+ errors.push(`${prefix}: enumValues[${i}] must be a string`);
246
+ }
247
+ });
248
+ // Check for duplicates
249
+ const duplicates = column.enumValues.filter((value, index) => column.enumValues.indexOf(value) !== index);
250
+ if (duplicates.length > 0) {
251
+ errors.push(`${prefix}: duplicate enum values found: ${duplicates.join(', ')}`);
252
+ }
253
+ }
254
+ break;
255
+ }
256
+ }
257
+ /**
258
+ * Validate index definition
259
+ */
260
+ function validateIndexDefinition(index, columns, prefix, errors) {
261
+ // Validate index name
262
+ if (!index.name || typeof index.name !== 'string') {
263
+ errors.push(`${prefix}: name is required and must be a string`);
264
+ }
265
+ else {
266
+ validateIndexName(index.name, prefix, errors);
267
+ }
268
+ // Validate columns
269
+ if (!index.columns || !Array.isArray(index.columns)) {
270
+ errors.push(`${prefix}: columns array is required`);
271
+ }
272
+ else {
273
+ if (index.columns.length === 0) {
274
+ errors.push(`${prefix}: at least one column is required`);
275
+ }
276
+ // Validate each column exists in table
277
+ const columnNames = columns.map((c) => c.name);
278
+ index.columns.forEach((indexCol) => {
279
+ const colName = typeof indexCol === 'string' ? indexCol : indexCol.name;
280
+ if (!columnNames.includes(colName)) {
281
+ errors.push(`${prefix}: column "${colName}" does not exist in table`);
282
+ }
283
+ });
284
+ }
285
+ // Validate unique flag
286
+ if (index.unique !== undefined && typeof index.unique !== 'boolean') {
287
+ errors.push(`${prefix}: unique must be a boolean`);
288
+ }
289
+ }
290
+ /**
291
+ * Validate index name
292
+ */
293
+ function validateIndexName(name, prefix, errors) {
294
+ if (name.length === 0) {
295
+ errors.push(`${prefix}: index name cannot be empty`);
296
+ return;
297
+ }
298
+ if (name.length > 64) {
299
+ errors.push(`${prefix}: index name cannot exceed 64 characters`);
300
+ }
301
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
302
+ errors.push(`${prefix}: index name must start with a letter or underscore and contain only letters, numbers, and underscores`);
303
+ }
304
+ }
305
+ /**
306
+ * Throw an error if schema validation fails
307
+ */
308
+ function assertValidTableSchema(schema) {
309
+ const result = validateTableSchema(schema);
310
+ if (!result.valid) {
311
+ throw new Error(`Invalid table schema:\n${result.errors.join('\n')}`);
312
+ }
313
+ }
314
+ /**
315
+ * Throw an error if column validation fails
316
+ */
317
+ function assertValidColumn(column) {
318
+ const errors = [];
319
+ validateColumnDefinition(column, 'Column', errors);
320
+ if (errors.length > 0) {
321
+ throw new Error(`Invalid column definition:\n${errors.join('\n')}`);
322
+ }
323
+ }
324
+ /**
325
+ * Throw an error if index validation fails
326
+ */
327
+ function assertValidIndex(index, columns) {
328
+ const errors = [];
329
+ validateIndexDefinition(index, columns, 'Index', errors);
330
+ if (errors.length > 0) {
331
+ throw new Error(`Invalid index definition:\n${errors.join('\n')}`);
332
+ }
333
+ }
334
+ //# sourceMappingURL=schema.validator.js.map