@dreamtree-org/korm-js 1.0.44 → 1.0.46

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 (2) hide show
  1. package/README.md +261 -114
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -156,7 +156,7 @@ POST /api/Users/crud
156
156
  "action": "list",
157
157
  "where": { "is_active": true },
158
158
  "select": ["id", "username", "email", "first_name", "last_name"],
159
- "sort": [["created_at", "desc"]],
159
+ "orderBy": { "column": "created_at", "direction": "desc" },
160
160
  "limit": 10
161
161
  }
162
162
 
@@ -165,7 +165,7 @@ POST /api/Users/crud
165
165
  {
166
166
  "action": "list",
167
167
  "select": ["id", "username", "email"],
168
- "sort": [["created_at", "desc"]],
168
+ "orderBy": { "column": "created_at", "direction": "desc" },
169
169
  "limit": 10,
170
170
  "offset": 20
171
171
  }
@@ -175,13 +175,16 @@ POST /api/Users/crud
175
175
  {
176
176
  "action": "list",
177
177
  "where": {
178
- "first_name": { "like": "%John%" },
179
- "email": { "like": "%@example.com" },
180
- "age": { ">=": 18, "<=": 65 },
178
+ "first_name": "%John%",
179
+ "email": "%@example.com",
180
+ "age": "><18,65",
181
181
  "is_active": true
182
182
  },
183
183
  "select": ["id", "username", "email", "first_name", "last_name"],
184
- "sort": [["created_at", "desc"], ["last_name", "asc"]],
184
+ "orderBy": [
185
+ { "column": "created_at", "direction": "desc" },
186
+ { "column": "last_name", "direction": "asc" }
187
+ ],
185
188
  "limit": 10
186
189
  }
187
190
 
@@ -315,7 +318,7 @@ POST /api/Users/crud
315
318
  "action": "count",
316
319
  "where": {
317
320
  "is_active": true,
318
- "created_at": { ">=": "2024-01-01" }
321
+ "created_at": ">=2024-01-01"
319
322
  }
320
323
  }
321
324
 
@@ -386,7 +389,7 @@ POST /api/Users/crud
386
389
  },
387
390
  "conflict": ["username"],
388
391
  "where": {
389
- "created_at": { "<": "2024-01-01" }
392
+ "created_at": "<2024-01-01"
390
393
  }
391
394
  }
392
395
 
@@ -411,11 +414,11 @@ POST /api/Users/crud
411
414
  {
412
415
  "action": "list",
413
416
  "where": {
414
- "age": { ">=": 18, "<=": 65 },
415
- "email": { "like": "%@example.com" },
416
- "first_name": { "in": ["John", "Jane", "Bob"] },
417
+ "age": "><18,65",
418
+ "email": "%@example.com",
419
+ "first_name": "[]John,Jane,Bob",
417
420
  "is_active": true,
418
- "created_at": { ">=": "2024-01-01", "<=": "2024-12-31" }
421
+ "created_at": "><2024-01-01,2024-12-31"
419
422
  }
420
423
  }
421
424
 
@@ -440,7 +443,7 @@ POST /api/Users/crud
440
443
  "action": "list",
441
444
  "where": {
442
445
  "status": "active",
443
- "Or:name": "like:%john%"
446
+ "Or:name": "%john%"
444
447
  }
445
448
  }
446
449
  // Generated SQL: WHERE status = 'active' OR name LIKE '%john%'
@@ -463,7 +466,7 @@ POST /api/Users/crud
463
466
  "action": "list",
464
467
  "where": {
465
468
  "status": "active",
466
- "age": { ">=": 18 },
469
+ "age": ">=18",
467
470
  "Or:role": "admin",
468
471
  "Or:role": "super_admin"
469
472
  }
@@ -476,8 +479,8 @@ POST /api/Users/crud
476
479
  "action": "list",
477
480
  "where": {
478
481
  "department": "sales",
479
- "Or:email": { "like": "%@company.com" },
480
- "Or:created_at": { ">=": "2024-01-01" }
482
+ "Or:email": "%@company.com",
483
+ "Or:created_at": ">=2024-01-01"
481
484
  }
482
485
  }
483
486
  // Generated SQL: WHERE department = 'sales' OR email LIKE '%@company.com' OR created_at >= '2024-01-01'
@@ -527,7 +530,7 @@ POST /api/Users/crud
527
530
  {
528
531
  "action": "list",
529
532
  "where": [
530
- { "is_active": true, "age": { ">=": 18 } },
533
+ { "is_active": true, "age": ">=18" },
531
534
  { "Or:status": "verified" },
532
535
  { "Or:role": "admin" }
533
536
  ]
@@ -541,7 +544,7 @@ POST /api/Users/crud
541
544
  "where": [
542
545
  { "department": "engineering" },
543
546
  { "Or:department": "product" },
544
- { "created_at": { ">=": "2024-01-01" } }
547
+ { "created_at": ">=2024-01-01" }
545
548
  ]
546
549
  }
547
550
  // Generated SQL: WHERE department = 'engineering' OR department = 'product' AND created_at >= '2024-01-01'
@@ -549,79 +552,133 @@ POST /api/Users/crud
549
552
 
550
553
  ### Where Operators Reference
551
554
 
552
- | Operator | Description | Example |
553
- |----------|-------------|---------|
554
- | `=` (default) | Equals | `"status": "active"` |
555
- | `>=` | Greater than or equal | `"age": { ">=": 18 }` |
556
- | `<=` | Less than or equal | `"age": { "<=": 65 }` |
557
- | `>` | Greater than | `"price": { ">": 100 }` |
558
- | `<` | Less than | `"price": { "<": 500 }` |
559
- | `!=` | Not equal | `"status": { "!=": "deleted" }` |
560
- | `like` | Pattern matching | `"name": { "like": "%john%" }` |
561
- | `in` | Value in list | `"status": ["active", "pending"]` |
562
- | `notIn` | Value not in list | `"role": { "notIn": ["banned", "suspended"] }` |
563
- | `between` | Range (inclusive) | `"age": { "between": [18, 65] }` |
564
- | `notBetween` | Outside range | `"score": { "notBetween": [0, 50] }` |
565
- | `null` | IS NULL check | `"deleted_at": null` |
566
- | `Or:column` | OR condition prefix | `"Or:name": "John"` |
567
-
568
- ### Sorting
555
+ | Operator | Description | Syntax | Example |
556
+ |----------|-------------|--------|---------|
557
+ | `=` (default) | Equals | `value` | `"status": "active"` |
558
+ | `>=` | Greater than or equal | `>=value` | `"age": ">=18"` |
559
+ | `<=` | Less than or equal | `<=value` | `"age": "<=65"` |
560
+ | `>` | Greater than | `>value` | `"price": ">100"` |
561
+ | `<` | Less than | `<value` | `"price": "<500"` |
562
+ | `!=` | Not equal | `!value` | `"status": "!deleted"` |
563
+ | `like` | Pattern matching (auto) | `%value%` | `"name": "%john%"` |
564
+ | `in` | Value in list | `[]val1,val2` | `"status": "[]active,pending"` |
565
+ | `notIn` | Value not in list | `![]val1,val2` | `"role": "![]banned,suspended"` |
566
+ | `between` | Range (inclusive) | `><min,max` | `"age": "><18,65"` |
567
+ | `notBetween` | Outside range | `<>min,max` | `"score": "<>0,50"` |
568
+ | `null` | IS NULL check | `null` | `"deleted_at": null` |
569
+ | `Or:column` | OR condition prefix | `Or:column` | `"Or:name": "John"` |
570
+
571
+ **Examples:**
572
+
573
+ ```javascript
574
+ // Complex query with string-based operators
575
+ POST /api/Users/crud
576
+ {
577
+ "action": "list",
578
+ "where": {
579
+ "age": ">=18",
580
+ "status": "!deleted",
581
+ "name": "%john%",
582
+ "role": "[]admin,moderator,editor",
583
+ "score": "><50,100"
584
+ }
585
+ }
586
+ // SQL: WHERE age >= 18 AND status != 'deleted' AND name LIKE '%john%'
587
+ // AND role IN ('admin', 'moderator', 'editor') AND score BETWEEN 50 AND 100
588
+ ```
589
+
590
+ ### Sorting (orderBy)
569
591
 
570
592
  ```javascript
571
- // Single sort
593
+ // Single sort with object
594
+ POST /api/Users/crud
595
+ {
596
+ "action": "list",
597
+ "orderBy": { "column": "created_at", "direction": "desc" }
598
+ }
599
+
600
+ // Single sort with string (default: ascending)
572
601
  POST /api/Users/crud
573
602
  {
574
603
  "action": "list",
575
- "sort": [["created_at", "desc"]]
604
+ "orderBy": "created_at"
576
605
  }
577
606
 
578
- // Multiple sorts
607
+ // Multiple sorts with array of objects
579
608
  POST /api/Users/crud
580
609
  {
581
610
  "action": "list",
582
- "sort": [
583
- ["is_active", "desc"],
584
- ["created_at", "desc"],
585
- ["last_name", "asc"]
611
+ "orderBy": [
612
+ { "column": "is_active", "direction": "desc" },
613
+ { "column": "created_at", "direction": "desc" },
614
+ { "column": "last_name", "direction": "asc" }
586
615
  ]
587
616
  }
617
+
618
+ // Multiple sorts with array of strings (all ascending)
619
+ POST /api/Users/crud
620
+ {
621
+ "action": "list",
622
+ "orderBy": ["is_active", "created_at", "last_name"]
623
+ }
588
624
  ```
589
625
 
590
626
  ### Joins
591
627
 
592
628
  ```javascript
593
- // Inner join
629
+ // Inner join (using innerJoin parameter)
594
630
  POST /api/Users/crud
595
631
  {
596
632
  "action": "list",
597
- "select": ["users.id", "users.username", "profiles.bio"],
598
- "join": [
599
- {
600
- "table": "user_profiles",
601
- "as": "profiles",
602
- "on": "users.id = profiles.user_id",
603
- "type": "inner"
604
- }
605
- ],
633
+ "select": ["users.id", "users.username", "user_profiles.bio"],
634
+ "innerJoin": {
635
+ "table": "user_profiles",
636
+ "on": "users.id = user_profiles.user_id"
637
+ },
606
638
  "where": { "users.is_active": true }
607
639
  }
608
640
 
609
- // Left join
641
+ // Left join (using leftJoin parameter)
610
642
  POST /api/Users/crud
611
643
  {
612
644
  "action": "list",
613
- "select": ["users.*", "profiles.bio"],
614
- "join": [
615
- {
616
- "table": "user_profiles",
617
- "as": "profiles",
618
- "on": "users.id = profiles.user_id",
619
- "type": "left"
620
- }
645
+ "select": ["users.*", "user_profiles.bio"],
646
+ "leftJoin": {
647
+ "table": "user_profiles",
648
+ "on": "users.id = user_profiles.user_id"
649
+ }
650
+ }
651
+
652
+ // Multiple joins (array format)
653
+ POST /api/Users/crud
654
+ {
655
+ "action": "list",
656
+ "select": ["users.*", "profiles.bio", "roles.name"],
657
+ "leftJoin": [
658
+ { "table": "user_profiles", "on": "users.id = user_profiles.user_id" },
659
+ { "table": "roles", "on": "users.role_id = roles.id" }
621
660
  ]
622
661
  }
662
+
663
+ // Join with explicit columns
664
+ POST /api/Users/crud
665
+ {
666
+ "action": "list",
667
+ "innerJoin": {
668
+ "table": "orders",
669
+ "first": "users.id",
670
+ "operator": "=",
671
+ "second": "orders.user_id"
672
+ }
673
+ }
623
674
  ```
624
675
 
676
+ **Available join types:**
677
+ - `join` - Regular join
678
+ - `innerJoin` - Inner join
679
+ - `leftJoin` - Left join
680
+ - `rightJoin` - Right join
681
+
625
682
  ## Relational Support with hasRelations
626
683
 
627
684
  ### Understanding hasRelations Structure
@@ -881,6 +938,9 @@ Create a model file at `models/Users.model.js`:
881
938
 
882
939
  ```javascript
883
940
  class Users {
941
+ // Soft delete support (property, not method)
942
+ hasSoftDelete = true;
943
+
884
944
  // Validation hook - runs before any action
885
945
  async validate({ model, action, request, context, db, utils, controller }) {
886
946
  if (action === 'create' || action === 'update') {
@@ -897,61 +957,91 @@ class Users {
897
957
  }
898
958
  }
899
959
 
900
- // Before hook - runs before the action executes
960
+ // Before hooks - run before the action executes
961
+ // Method naming: before{Action} (e.g., beforeCreate, beforeUpdate, beforeList, beforeDelete)
901
962
  async beforeCreate({ model, action, request, context, db, utils, controller }) {
902
- // Add timestamps
963
+ // Modify request data before insert
903
964
  request.data.created_at = new Date();
904
965
  request.data.updated_at = new Date();
905
966
  return request.data;
906
967
  }
907
968
 
908
969
  async beforeUpdate({ model, action, request, context, db, utils, controller }) {
909
- // Update timestamp
970
+ // Modify request data before update
910
971
  request.data.updated_at = new Date();
911
972
  return request.data;
912
973
  }
913
974
 
914
- // After hook - runs after the action executes
975
+ async beforeDelete({ model, action, request, context, db, utils, controller }) {
976
+ // Logic before delete (works with both hard and soft delete)
977
+ console.log('Deleting user:', request.where);
978
+ }
979
+
980
+ // After hooks - run after the action executes
981
+ // Method naming: after{Action} (e.g., afterCreate, afterUpdate, afterList, afterDelete)
915
982
  async afterCreate({ model, action, data, request, context, db, utils, controller }) {
916
- // Log creation
983
+ // data contains the result of the action
917
984
  console.log('User created:', data);
918
- // Send welcome email, etc.
985
+ // Send welcome email, trigger notifications, etc.
919
986
  return data;
920
987
  }
921
988
 
922
989
  async afterUpdate({ model, action, data, request, context, db, utils, controller }) {
923
- // Log update
924
990
  console.log('User updated:', data);
925
991
  return data;
926
992
  }
927
993
 
928
- // Custom action hook
929
- async onCustomAction({ model, action, request, context, db, utils, controller }) {
930
- // Handle custom actions like 'activate', 'deactivate', etc.
931
- if (action === 'activate') {
932
- return await db('users')
933
- .where(request.where)
934
- .update({ is_active: true, updated_at: new Date() });
935
- }
936
- throw new Error(`Unknown custom action: ${action}`);
994
+ async afterList({ model, action, data, request, context, db, utils, controller }) {
995
+ // Modify list results before returning
996
+ return data;
937
997
  }
938
998
 
939
- // Soft delete support
940
- hasSoftDelete = true;
999
+ // Custom action hooks
1000
+ // Method naming: on{Action}Action (e.g., onActivateAction, onDeactivateAction)
1001
+ async onActivateAction({ model, action, request, context, db, utils, controller }) {
1002
+ return await db('users')
1003
+ .where(request.where)
1004
+ .update({ is_active: true, updated_at: new Date() });
1005
+ }
1006
+
1007
+ async onDeactivateAction({ model, action, request, context, db, utils, controller }) {
1008
+ return await db('users')
1009
+ .where(request.where)
1010
+ .update({ is_active: false, updated_at: new Date() });
1011
+ }
941
1012
  }
942
1013
 
943
1014
  module.exports = Users;
944
1015
  ```
945
1016
 
1017
+ ### Hook Arguments Reference
1018
+
1019
+ | Argument | Description |
1020
+ |----------|-------------|
1021
+ | `model` | Model definition object with table, columns, relations |
1022
+ | `action` | Current action being performed (create, update, delete, etc.) |
1023
+ | `request` | The request object containing where, data, etc. |
1024
+ | `context` | Custom context passed from the controller |
1025
+ | `db` | Knex database instance for direct queries |
1026
+ | `utils` | Utility functions |
1027
+ | `controller` | ControllerWrapper instance |
1028
+ | `data` | (After hooks only) Result of the action |
1029
+
946
1030
  ### Using Custom Actions
947
1031
 
948
1032
  ```javascript
949
- // Call custom action
1033
+ // Call custom action - triggers on{Action}Action hook
950
1034
  POST /api/Users/crud
951
1035
  {
952
1036
  "action": "activate",
953
1037
  "where": { "id": 1 }
954
1038
  }
1039
+
1040
+ POST /api/Users/crud
1041
+ {
1042
+ "action": "deactivate",
1043
+ "where": { "id": 1 }
1044
+ }
955
1045
  ```
956
1046
 
957
1047
  ## Data Validation
@@ -1109,49 +1199,67 @@ POST /api/Users/crud
1109
1199
  ### KORM Instance Methods
1110
1200
 
1111
1201
  ```javascript
1202
+ const { initializeKORM } = require('@dreamtree-org/korm-js');
1203
+
1112
1204
  const korm = initializeKORM({
1113
- db: db,
1114
- dbClient: 'mysql' // or 'pg', 'sqlite'
1205
+ db: db, // Knex database instance
1206
+ dbClient: 'mysql', // 'mysql', 'mysql2', 'pg', 'postgresql', 'sqlite', 'sqlite3'
1207
+ schema: null, // Optional: initial schema object
1208
+ resolverPath: null // Optional: path to models directory (default: process.cwd())
1115
1209
  });
1116
1210
 
1117
- // Process any CRUD request
1118
- const result = await korm.processRequest(requestBody, modelName);
1211
+ // Process any CRUD request (automatically handles other_requests if present)
1212
+ const result = await korm.processRequest(requestBody, modelName, context);
1119
1213
 
1120
- // Process request with nested requests
1121
- const result = await korm.processRequestWithOthers(requestBody, modelName);
1214
+ // Process request with nested requests (legacy - now same as processRequest)
1215
+ const result = await korm.processRequestWithOthers(requestBody, modelName, context);
1122
1216
 
1123
1217
  // Set schema manually
1124
1218
  korm.setSchema(schemaObject);
1125
1219
 
1126
- // Sync database with schema
1220
+ // Sync database with schema (creates/updates tables)
1127
1221
  await korm.syncDatabase();
1128
1222
 
1129
1223
  // Generate schema from existing database
1130
1224
  const schema = await korm.generateSchema();
1131
- ```
1132
-
1133
- ### ControllerWrapper Static Methods
1134
1225
 
1135
- ```javascript
1136
- const { ControllerWrapper } = require('@dreamtree-org/korm-js');
1137
-
1138
- // Load model class
1139
- const ModelClass = ControllerWrapper.loadModelClass('Users');
1226
+ // Load model class from models/{ModelName}.model.js
1227
+ const ModelClass = korm.loadModelClass('Users');
1140
1228
 
1141
1229
  // Get model instance
1142
- const modelInstance = ControllerWrapper.getModelInstance(model);
1143
-
1144
- // Generate schema
1145
- const schema = await ControllerWrapper.generateSchema();
1230
+ const modelInstance = korm.getModelInstance(modelDef);
1146
1231
  ```
1147
1232
 
1233
+ ### ProcessRequest Options
1234
+
1235
+ | Parameter | Type | Description |
1236
+ |-----------|------|-------------|
1237
+ | `action` | string | Action to perform (list, show, create, update, delete, count, replace, upsert, sync) |
1238
+ | `where` | object/array | Filter conditions |
1239
+ | `data` | object/array | Data for create/update operations |
1240
+ | `select` | array/string | Columns to select |
1241
+ | `orderBy` | object/array/string | Sorting configuration |
1242
+ | `limit` | number | Maximum records to return |
1243
+ | `offset` | number | Records to skip |
1244
+ | `page` | number | Page number (alternative to offset) |
1245
+ | `with` | array | Related models to eager load |
1246
+ | `groupBy` | array/string | Group by columns |
1247
+ | `having` | object | Having conditions |
1248
+ | `distinct` | boolean/array/string | Distinct results |
1249
+ | `join` | object/array | Join configuration |
1250
+ | `leftJoin` | object/array | Left join configuration |
1251
+ | `rightJoin` | object/array | Right join configuration |
1252
+ | `innerJoin` | object/array | Inner join configuration |
1253
+ | `conflict` | array | Conflict columns for upsert |
1254
+ | `other_requests` | object | Nested requests for related models |
1255
+
1148
1256
  ### ProcessRequest Actions Summary
1149
1257
 
1150
1258
  | Action | Description | Required Fields |
1151
1259
  |--------|-------------|----------------|
1152
- | `create` | Create new record | `data` |
1153
- | `list` | Get multiple records | None (optional: `where`, `select`, `sort`, `limit`, `offset`) |
1260
+ | `list` | Get multiple records | None (optional: `where`, `select`, `orderBy`, `limit`, `offset`) |
1154
1261
  | `show` | Get single record | `where` |
1262
+ | `create` | Create new record | `data` |
1155
1263
  | `update` | Update record(s) | `where`, `data` |
1156
1264
  | `delete` | Delete record(s) | `where` |
1157
1265
  | `count` | Count records | None (optional: `where`) |
@@ -1163,19 +1271,58 @@ const schema = await ControllerWrapper.generateSchema();
1163
1271
 
1164
1272
  | Rule | Description | Example |
1165
1273
  |------|-------------|---------|
1166
- | `required` | Field is required | `username: 'required'` |
1167
- | `type:string` | Field must be string | `name: 'type:string'` |
1168
- | `type:number` | Field must be number | `age: 'type:number'` |
1169
- | `type:boolean` | Field must be boolean | `is_active: 'type:boolean'` |
1170
- | `minLen:n` | Minimum length | `username: 'minLen:3'` |
1171
- | `maxLen:n` | Maximum length | `email: 'maxLen:255'` |
1172
- | `min:n` | Minimum value | `age: 'min:0'` |
1173
- | `max:n` | Maximum value | `age: 'max:150'` |
1174
- | `in:val1,val2` | Value must be in list | `status: 'in:active,inactive'` |
1175
- | `regex:name` | Custom regex pattern | `email: 'regex:email'` |
1176
- | `call:name` | Custom callback function | `field: 'call:myValidator'` |
1177
- | `exists:table,column` | Value must exist in table | `user_id: 'exists:users,id'` |
1178
- | `default:value` | Default value if not provided | `status: 'default:active'` |
1274
+ | `required` | Field is required | `'required'` |
1275
+ | `type:string` | Field must be string | `'type:string'` |
1276
+ | `type:number` | Field must be number | `'type:number'` |
1277
+ | `type:boolean` | Field must be boolean | `'type:boolean'` |
1278
+ | `type:array` | Field must be array | `'type:array'` |
1279
+ | `type:object` | Field must be object | `'type:object'` |
1280
+ | `type:longText` | Field must be string > 255 chars | `'type:longText'` |
1281
+ | `minLen:n` | Minimum string/array length | `'minLen:3'` |
1282
+ | `maxLen:n` | Maximum string/array length | `'maxLen:255'` |
1283
+ | `min:n` | Minimum numeric value | `'min:0'` |
1284
+ | `max:n` | Maximum numeric value | `'max:150'` |
1285
+ | `in:val1,val2` | Value must be in list | `'in:active,inactive,pending'` |
1286
+ | `regex:name` | Custom regex pattern (define in options) | `'regex:email'` |
1287
+ | `call:name` | Custom callback function (define in options) | `'call:myValidator'` |
1288
+ | `exists:table,column` | Value must exist in database table | `'exists:users,id'` |
1289
+ | `default:value` | Default value if not provided | `'default:active'` |
1290
+
1291
+ **Rule Chaining:** Combine multiple rules with `|` pipe character:
1292
+ ```javascript
1293
+ {
1294
+ username: 'required|type:string|minLen:3|maxLen:50',
1295
+ email: 'required|type:string|regex:email',
1296
+ age: 'type:number|min:0|max:150',
1297
+ status: 'in:active,inactive|default:active'
1298
+ }
1299
+ ```
1300
+
1301
+ ### Library Exports
1302
+
1303
+ ```javascript
1304
+ const {
1305
+ initializeKORM, // Initialize KORM with database connection
1306
+ helperUtility, // Utility functions (file operations, string manipulation)
1307
+ emitter, // Event emitter instance
1308
+ validate, // Validation function
1309
+ lib, // Additional utilities
1310
+ LibClasses // Library classes (Emitter)
1311
+ } = require('@dreamtree-org/korm-js');
1312
+
1313
+ // lib contains:
1314
+ // - createValidationMiddleware(rules, options) - Express middleware
1315
+ // - validateEmail(email) - Email validation
1316
+ // - validatePassword(password) - Password strength validation
1317
+ // - validatePhone(phone) - Phone number validation
1318
+ // - validatePAN(pan) - PAN validation (India)
1319
+ // - validateAadhaar(aadhaar) - Aadhaar validation (India)
1320
+
1321
+ // helperUtility.file contains:
1322
+ // - readJSON(path) - Read JSON file
1323
+ // - writeJSON(path, data) - Write JSON file
1324
+ // - createDirectory(path) - Create directory
1325
+ ```
1179
1326
 
1180
1327
  ## Database Support
1181
1328
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreamtree-org/korm-js",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "Knowledge Object-Relational Mapping - A powerful, modular ORM system for Node.js with dynamic database operations, complex queries, relationships, and nested requests",
5
5
  "author": {
6
6
  "name": "Partha Preetham Krishna",