stabilize-orm 1.1.3 → 1.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.
- package/README.md +209 -155
- package/bun.lock +61 -0
- package/cache.ts +88 -17
- package/cli/stabilize-cli.ts +300 -432
- package/client.ts +153 -170
- package/decorators.ts +70 -4
- package/dist/cli/stabilize-cli.js +3093 -86
- package/dist/index.js +3023 -26
- package/index.ts +90 -51
- package/logger.ts +76 -75
- package/migrations.ts +157 -65
- package/package.json +5 -2
- package/query-builder.ts +103 -13
- package/repository.ts +447 -287
- package/types.ts +58 -29
package/bun.lock
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
"": {
|
|
5
5
|
"name": "stabilize",
|
|
6
6
|
"dependencies": {
|
|
7
|
+
"@types/pg": "^8.15.5",
|
|
7
8
|
"@types/uuid": "^11.0.0",
|
|
8
9
|
"commander": "^12.1.0",
|
|
9
10
|
"figlet": "^1.9.3",
|
|
10
11
|
"glob": "^11.0.0",
|
|
11
12
|
"ioredis": "^5.4.1",
|
|
13
|
+
"mysql2": "^3.15.2",
|
|
14
|
+
"pg": "^8.16.3",
|
|
12
15
|
"reflect-metadata": "^0.2.2",
|
|
13
16
|
"uuid": "^13.0.0",
|
|
14
17
|
},
|
|
@@ -207,6 +210,10 @@
|
|
|
207
210
|
|
|
208
211
|
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
|
|
209
212
|
|
|
213
|
+
"@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="],
|
|
214
|
+
|
|
215
|
+
"@types/pg": ["@types/pg@8.15.5", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ=="],
|
|
216
|
+
|
|
210
217
|
"@types/uuid": ["@types/uuid@11.0.0", "", { "dependencies": { "uuid": "*" } }, "sha512-HVyk8nj2m+jcFRNazzqyVKiZezyhDKrGUA3jlEcg/nZ6Ms+qHwocba1Y/AaVaznJTAM9xpdFSh+ptbNrhOGvZA=="],
|
|
211
218
|
|
|
212
219
|
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/type-utils": "8.46.1", "@typescript-eslint/utils": "8.46.1", "@typescript-eslint/visitor-keys": "8.46.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ=="],
|
|
@@ -259,6 +266,8 @@
|
|
|
259
266
|
|
|
260
267
|
"assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
|
|
261
268
|
|
|
269
|
+
"aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="],
|
|
270
|
+
|
|
262
271
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
|
263
272
|
|
|
264
273
|
"brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
|
|
@@ -353,6 +362,8 @@
|
|
|
353
362
|
|
|
354
363
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
355
364
|
|
|
365
|
+
"generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="],
|
|
366
|
+
|
|
356
367
|
"glob": ["glob@11.0.3", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA=="],
|
|
357
368
|
|
|
358
369
|
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
|
@@ -365,6 +376,8 @@
|
|
|
365
376
|
|
|
366
377
|
"html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="],
|
|
367
378
|
|
|
379
|
+
"iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="],
|
|
380
|
+
|
|
368
381
|
"ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
|
369
382
|
|
|
370
383
|
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
|
@@ -381,6 +394,8 @@
|
|
|
381
394
|
|
|
382
395
|
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
|
383
396
|
|
|
397
|
+
"is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="],
|
|
398
|
+
|
|
384
399
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
385
400
|
|
|
386
401
|
"istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
|
|
@@ -413,10 +428,14 @@
|
|
|
413
428
|
|
|
414
429
|
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
|
415
430
|
|
|
431
|
+
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
|
432
|
+
|
|
416
433
|
"loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
|
|
417
434
|
|
|
418
435
|
"lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="],
|
|
419
436
|
|
|
437
|
+
"lru.min": ["lru.min@1.1.2", "", {}, "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg=="],
|
|
438
|
+
|
|
420
439
|
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
|
|
421
440
|
|
|
422
441
|
"magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="],
|
|
@@ -433,6 +452,10 @@
|
|
|
433
452
|
|
|
434
453
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
435
454
|
|
|
455
|
+
"mysql2": ["mysql2@3.15.2", "", { "dependencies": { "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.7.0", "long": "^5.2.1", "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" } }, "sha512-kFm5+jbwR5mC+lo+3Cy46eHiykWSpUtTLOH3GE+AR7GeLq8PgfJcvpMiyVWk9/O53DjQsqm6a3VOOfq7gYWFRg=="],
|
|
456
|
+
|
|
457
|
+
"named-placeholders": ["named-placeholders@1.1.3", "", { "dependencies": { "lru-cache": "^7.14.1" } }, "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w=="],
|
|
458
|
+
|
|
436
459
|
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
437
460
|
|
|
438
461
|
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
|
@@ -457,12 +480,36 @@
|
|
|
457
480
|
|
|
458
481
|
"pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
|
|
459
482
|
|
|
483
|
+
"pg": ["pg@8.16.3", "", { "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", "pg-protocol": "^1.10.3", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.7" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw=="],
|
|
484
|
+
|
|
485
|
+
"pg-cloudflare": ["pg-cloudflare@1.2.7", "", {}, "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg=="],
|
|
486
|
+
|
|
487
|
+
"pg-connection-string": ["pg-connection-string@2.9.1", "", {}, "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="],
|
|
488
|
+
|
|
489
|
+
"pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="],
|
|
490
|
+
|
|
491
|
+
"pg-pool": ["pg-pool@3.10.1", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg=="],
|
|
492
|
+
|
|
493
|
+
"pg-protocol": ["pg-protocol@1.10.3", "", {}, "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="],
|
|
494
|
+
|
|
495
|
+
"pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
|
496
|
+
|
|
497
|
+
"pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="],
|
|
498
|
+
|
|
460
499
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
|
461
500
|
|
|
462
501
|
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
|
463
502
|
|
|
464
503
|
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
|
465
504
|
|
|
505
|
+
"postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="],
|
|
506
|
+
|
|
507
|
+
"postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="],
|
|
508
|
+
|
|
509
|
+
"postgres-date": ["postgres-date@1.0.7", "", {}, "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="],
|
|
510
|
+
|
|
511
|
+
"postgres-interval": ["postgres-interval@1.2.0", "", { "dependencies": { "xtend": "^4.0.0" } }, "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ=="],
|
|
512
|
+
|
|
466
513
|
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
|
467
514
|
|
|
468
515
|
"prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="],
|
|
@@ -485,8 +532,12 @@
|
|
|
485
532
|
|
|
486
533
|
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
|
487
534
|
|
|
535
|
+
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
|
536
|
+
|
|
488
537
|
"semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
|
|
489
538
|
|
|
539
|
+
"seq-queue": ["seq-queue@0.0.5", "", {}, "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="],
|
|
540
|
+
|
|
490
541
|
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
|
491
542
|
|
|
492
543
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
@@ -497,6 +548,10 @@
|
|
|
497
548
|
|
|
498
549
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
499
550
|
|
|
551
|
+
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
|
552
|
+
|
|
553
|
+
"sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="],
|
|
554
|
+
|
|
500
555
|
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
|
501
556
|
|
|
502
557
|
"standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="],
|
|
@@ -535,6 +590,8 @@
|
|
|
535
590
|
|
|
536
591
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
537
592
|
|
|
593
|
+
"undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
|
|
594
|
+
|
|
538
595
|
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
|
539
596
|
|
|
540
597
|
"uuid": ["uuid@13.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="],
|
|
@@ -555,6 +612,8 @@
|
|
|
555
612
|
|
|
556
613
|
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
|
557
614
|
|
|
615
|
+
"xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
|
|
616
|
+
|
|
558
617
|
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
|
559
618
|
|
|
560
619
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
|
@@ -571,6 +630,8 @@
|
|
|
571
630
|
|
|
572
631
|
"glob/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="],
|
|
573
632
|
|
|
633
|
+
"named-placeholders/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
|
|
634
|
+
|
|
574
635
|
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
|
575
636
|
|
|
576
637
|
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
package/cache.ts
CHANGED
|
@@ -1,37 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file cache.ts
|
|
3
|
+
* @description Provides a Redis-backed caching layer for the ORM.
|
|
4
|
+
* @author ElectronSz
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import Redis from "ioredis";
|
|
2
8
|
import { type CacheConfig, type CacheStats } from "./types";
|
|
3
9
|
import { ConsoleLogger, type Logger } from "./logger";
|
|
4
10
|
|
|
11
|
+
/**
|
|
12
|
+
* A caching client that uses Redis to store and retrieve query results.
|
|
13
|
+
* It supports cache-aside and write-through strategies and keeps track of basic stats.
|
|
14
|
+
*/
|
|
5
15
|
export class Cache {
|
|
6
16
|
private redis: Redis | null = null;
|
|
7
|
-
private ttl: number;
|
|
8
|
-
private prefix: string;
|
|
9
|
-
private strategy: "cache-aside" | "write-through";
|
|
10
17
|
private logger: Logger;
|
|
11
18
|
private hits: number = 0;
|
|
12
19
|
private misses: number = 0;
|
|
13
20
|
|
|
21
|
+
/** The configuration object the cache was initialized with. */
|
|
22
|
+
public readonly config: CacheConfig;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Creates an instance of the Cache client.
|
|
26
|
+
* @param config The configuration for the cache, including Redis URL and TTL.
|
|
27
|
+
* @param logger A logger instance for logging messages.
|
|
28
|
+
*/
|
|
14
29
|
constructor(config: CacheConfig, logger: Logger = new ConsoleLogger()) {
|
|
15
|
-
this.
|
|
16
|
-
this.prefix = config.cachePrefix || "cache:";
|
|
17
|
-
this.strategy = config.strategy || "cache-aside";
|
|
30
|
+
this.config = config;
|
|
18
31
|
this.logger = logger;
|
|
19
32
|
|
|
20
|
-
if (config.enabled && config.redisUrl) {
|
|
21
|
-
this.redis = new Redis(config.redisUrl, { lazyConnect: true });
|
|
33
|
+
if (this.config.enabled && this.config.redisUrl) {
|
|
34
|
+
this.redis = new Redis(this.config.redisUrl, { lazyConnect: true });
|
|
22
35
|
this.redis.on("error", (error) => this.logger.logError(error));
|
|
23
36
|
}
|
|
24
37
|
}
|
|
25
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Gets the caching strategy being used.
|
|
41
|
+
* @returns The caching strategy, either 'cache-aside' or 'write-through'.
|
|
42
|
+
*/
|
|
26
43
|
getStrategy() {
|
|
27
|
-
return this.strategy;
|
|
44
|
+
return this.config.strategy || "cache-aside";
|
|
28
45
|
}
|
|
29
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Retrieves an item from the cache.
|
|
49
|
+
* @template T The expected type of the cached item.
|
|
50
|
+
* @param key The key of the item to retrieve.
|
|
51
|
+
* @returns A promise that resolves to the cached item or `null` if not found.
|
|
52
|
+
* @example
|
|
53
|
+
* ```
|
|
54
|
+
* const user = await cache.get<User>('user:1');
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
30
57
|
async get<T>(key: string): Promise<T | null> {
|
|
31
58
|
if (!this.redis) return null;
|
|
32
59
|
|
|
33
60
|
try {
|
|
34
|
-
const data = await this.redis.get(this.
|
|
61
|
+
const data = await this.redis.get(this.config.cachePrefix + key);
|
|
35
62
|
if (data) {
|
|
36
63
|
this.hits++;
|
|
37
64
|
this.logger.logDebug(`Cache hit for key: ${key}`);
|
|
@@ -46,24 +73,46 @@ export class Cache {
|
|
|
46
73
|
}
|
|
47
74
|
}
|
|
48
75
|
|
|
49
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Stores an item in the cache.
|
|
78
|
+
* @template T The type of the item being stored.
|
|
79
|
+
* @param key The key to store the item under.
|
|
80
|
+
* @param value The value to store.
|
|
81
|
+
* @param ttl Optional: The time-to-live for this specific item in seconds. Defaults to the global TTL.
|
|
82
|
+
* @returns A promise that resolves when the item is set.
|
|
83
|
+
* @example
|
|
84
|
+
* ```
|
|
85
|
+
* await cache.set('user:1', user, 3600); // Cache for 1 hour
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
|
|
50
89
|
if (!this.redis) return;
|
|
51
90
|
|
|
52
91
|
try {
|
|
53
|
-
|
|
92
|
+
const effectiveTtl = ttl ?? this.config.ttl;
|
|
93
|
+
await this.redis.set(this.config.cachePrefix + key, JSON.stringify(value), "EX", effectiveTtl);
|
|
54
94
|
this.logger.logDebug(`Cache set for key: ${key}`);
|
|
55
95
|
} catch (error) {
|
|
56
96
|
this.logger.logError(error as Error);
|
|
57
97
|
}
|
|
58
98
|
}
|
|
59
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Removes one or more items from the cache by their exact keys.
|
|
102
|
+
* @param keys An array of keys to invalidate.
|
|
103
|
+
* @returns A promise that resolves when the keys are invalidated.
|
|
104
|
+
* @example
|
|
105
|
+
* ```
|
|
106
|
+
* await cache.invalidate(['user:1', 'all_users']);
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
60
109
|
async invalidate(keys: string[]): Promise<void> {
|
|
61
110
|
if (!this.redis) return;
|
|
62
111
|
|
|
63
112
|
try {
|
|
64
113
|
const pipeline = this.redis.pipeline();
|
|
65
114
|
for (const key of keys) {
|
|
66
|
-
pipeline.del(this.
|
|
115
|
+
pipeline.del(this.config.cachePrefix + key);
|
|
67
116
|
this.logger.logDebug(`Cache invalidated for key: ${key}`);
|
|
68
117
|
}
|
|
69
118
|
await pipeline.exec();
|
|
@@ -72,28 +121,46 @@ export class Cache {
|
|
|
72
121
|
}
|
|
73
122
|
}
|
|
74
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Invalidates all keys matching a given pattern.
|
|
126
|
+
* @param pattern The pattern to match against (e.g., 'user:*').
|
|
127
|
+
* @returns A promise that resolves when the operation is complete.
|
|
128
|
+
* @example
|
|
129
|
+
* ```
|
|
130
|
+
* await cache.invalidatePattern('user:*'); // Invalidates all user-related cache
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
75
133
|
async invalidatePattern(pattern: string): Promise<void> {
|
|
76
134
|
if (!this.redis) return;
|
|
77
135
|
|
|
78
136
|
try {
|
|
79
|
-
const keys = await this.redis.keys(this.
|
|
137
|
+
const keys = await this.redis.keys(this.config.cachePrefix + pattern);
|
|
80
138
|
if (keys.length > 0) {
|
|
81
139
|
const pipeline = this.redis.pipeline();
|
|
82
140
|
for (const key of keys) {
|
|
83
141
|
pipeline.del(key);
|
|
84
|
-
this.logger.logDebug(`Cache invalidated for pattern: ${pattern}`);
|
|
85
142
|
}
|
|
86
143
|
await pipeline.exec();
|
|
144
|
+
this.logger.logDebug(`Cache invalidated for pattern: ${pattern} (${keys.length} keys)`);
|
|
87
145
|
}
|
|
88
146
|
} catch (error) {
|
|
89
147
|
this.logger.logError(error as Error);
|
|
90
148
|
}
|
|
91
149
|
}
|
|
92
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Retrieves statistics about the cache, including hits, misses, and total key count.
|
|
153
|
+
* @returns A promise that resolves to a `CacheStats` object.
|
|
154
|
+
* @example
|
|
155
|
+
* ```
|
|
156
|
+
* const stats = await cache.getStats();
|
|
157
|
+
* console.log(`Cache Hits: ${stats.hits}, Misses: ${stats.misses}`);
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
93
160
|
async getStats(): Promise<CacheStats> {
|
|
94
161
|
if (!this.redis) return { hits: 0, misses: 0, keys: 0 };
|
|
95
162
|
try {
|
|
96
|
-
const keys = await this.redis.keys(this.
|
|
163
|
+
const keys = await this.redis.keys(this.config.cachePrefix + "*");
|
|
97
164
|
return { hits: this.hits, misses: this.misses, keys: keys.length };
|
|
98
165
|
} catch (error) {
|
|
99
166
|
this.logger.logError(error as Error);
|
|
@@ -101,10 +168,14 @@ export class Cache {
|
|
|
101
168
|
}
|
|
102
169
|
}
|
|
103
170
|
|
|
171
|
+
/**
|
|
172
|
+
* Disconnects the Redis client gracefully.
|
|
173
|
+
* @returns A promise that resolves when the client has disconnected.
|
|
174
|
+
*/
|
|
104
175
|
async disconnect(): Promise<void> {
|
|
105
176
|
if (this.redis) {
|
|
106
177
|
await this.redis.quit();
|
|
107
178
|
this.logger.logInfo("Redis connection closed");
|
|
108
179
|
}
|
|
109
180
|
}
|
|
110
|
-
}
|
|
181
|
+
}
|