@vsaas/loopback-datasource-juggler 10.0.0

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 (63) hide show
  1. package/LICENSE +25 -0
  2. package/NOTICE +23 -0
  3. package/README.md +74 -0
  4. package/dist/_virtual/_rolldown/runtime.js +4 -0
  5. package/dist/index.js +26 -0
  6. package/dist/lib/browser.depd.js +13 -0
  7. package/dist/lib/case-utils.js +21 -0
  8. package/dist/lib/connectors/kv-memory.js +158 -0
  9. package/dist/lib/connectors/memory.js +810 -0
  10. package/dist/lib/connectors/transient.js +126 -0
  11. package/dist/lib/dao.js +2445 -0
  12. package/dist/lib/datasource.js +2215 -0
  13. package/dist/lib/date-string.js +87 -0
  14. package/dist/lib/geo.js +244 -0
  15. package/dist/lib/globalize.js +33 -0
  16. package/dist/lib/hooks.js +79 -0
  17. package/dist/lib/id-utils.js +66 -0
  18. package/dist/lib/include.js +795 -0
  19. package/dist/lib/include_utils.js +104 -0
  20. package/dist/lib/introspection.js +37 -0
  21. package/dist/lib/jutil.js +65 -0
  22. package/dist/lib/kvao/delete-all.js +57 -0
  23. package/dist/lib/kvao/delete.js +43 -0
  24. package/dist/lib/kvao/expire.js +35 -0
  25. package/dist/lib/kvao/get.js +34 -0
  26. package/dist/lib/kvao/index.js +28 -0
  27. package/dist/lib/kvao/iterate-keys.js +38 -0
  28. package/dist/lib/kvao/keys.js +55 -0
  29. package/dist/lib/kvao/set.js +39 -0
  30. package/dist/lib/kvao/ttl.js +35 -0
  31. package/dist/lib/list.js +101 -0
  32. package/dist/lib/mixins.js +58 -0
  33. package/dist/lib/model-builder.js +608 -0
  34. package/dist/lib/model-definition.js +231 -0
  35. package/dist/lib/model-utils.js +368 -0
  36. package/dist/lib/model.js +586 -0
  37. package/dist/lib/observer.js +235 -0
  38. package/dist/lib/relation-definition.js +2604 -0
  39. package/dist/lib/relations.js +587 -0
  40. package/dist/lib/scope.js +392 -0
  41. package/dist/lib/transaction.js +183 -0
  42. package/dist/lib/types.js +58 -0
  43. package/dist/lib/utils.js +625 -0
  44. package/dist/lib/validations.js +742 -0
  45. package/dist/package.js +93 -0
  46. package/package.json +85 -0
  47. package/types/common.d.ts +28 -0
  48. package/types/connector.d.ts +52 -0
  49. package/types/datasource.d.ts +324 -0
  50. package/types/date-string.d.ts +21 -0
  51. package/types/inclusion-mixin.d.ts +44 -0
  52. package/types/index.d.ts +36 -0
  53. package/types/kv-model.d.ts +201 -0
  54. package/types/model.d.ts +368 -0
  55. package/types/observer-mixin.d.ts +174 -0
  56. package/types/persisted-model.d.ts +505 -0
  57. package/types/query.d.ts +108 -0
  58. package/types/relation-mixin.d.ts +577 -0
  59. package/types/relation.d.ts +301 -0
  60. package/types/scope.d.ts +92 -0
  61. package/types/transaction-mixin.d.ts +47 -0
  62. package/types/types.d.ts +65 -0
  63. package/types/validation-mixin.d.ts +287 -0
package/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) IBM Corp. 2011,2017. All Rights Reserved.
2
+ Node module: loopback-datasource-juggler
3
+ This project is licensed under the MIT License, full text below.
4
+
5
+ --------
6
+
7
+ MIT license
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in
17
+ all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ THE SOFTWARE.
package/NOTICE ADDED
@@ -0,0 +1,23 @@
1
+ This product includes software developed at https://github.com/1602/jugglingdb
2
+ under the following MIT license.
3
+
4
+ Copyright (C) 2011 by Anatoliy Chakkaev <mail [åt] anatoliy [døt] in>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
+
package/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # @vsaas/loopback-datasource-juggler
2
+
3
+ `@vsaas/loopback-datasource-juggler` is a fork of `loopback-datasource-juggler` focused on keeping LoopBack 3 style data access working while reducing maintenance overhead.
4
+
5
+ The goal of this fork is practical compatibility for the common upstream use cases, not byte-for-byte preservation of the original package. The internals were intentionally simplified and modernized:
6
+
7
+ - TypeScript source with build output in `dist/`
8
+ - English-only messages
9
+ - no i18n catalogs or `strong-globalize`
10
+ - several legacy dependencies removed or replaced
11
+ - modern tooling with `tsdown`, `vitest`, and `oxlint`
12
+ - callback-compatible public APIs that continue to work with `Promise` and `async/await`
13
+
14
+ ## Installation
15
+
16
+ ```sh
17
+ npm install @vsaas/loopback-datasource-juggler
18
+ ```
19
+
20
+ If you are also using the related connector forks, pair it with packages such as `@vsaas/loopback-connector` and `@vsaas/loopback-connector-mongodb`.
21
+
22
+ ## Quick start
23
+
24
+ ```js
25
+ const juggler = require('@vsaas/loopback-datasource-juggler');
26
+
27
+ const ds = new juggler.DataSource('memory');
28
+
29
+ const Product = ds.createModel('Product', {
30
+ name: String,
31
+ price: Number,
32
+ });
33
+
34
+ async function main() {
35
+ await Product.create({ name: 'Notebook', price: 20 });
36
+ const products = await Product.find();
37
+ console.log(products);
38
+ }
39
+
40
+ main().catch(console.error);
41
+ ```
42
+
43
+ ## Scope
44
+
45
+ This package still provides the same main building blocks that existing juggler users expect:
46
+
47
+ - datasource and connector abstraction
48
+ - model definition and inheritance
49
+ - relations and inclusion
50
+ - scopes and query normalization
51
+ - validations and hooks
52
+ - transactions and id generation helpers
53
+
54
+ If you are migrating an existing codebase, the intent is that the public API should feel familiar even though the implementation is leaner.
55
+
56
+ ## Notes for Fork Users
57
+
58
+ - This is a maintained fork, not the upstream package.
59
+ - Messages are English-only by design.
60
+ - Legacy internals were removed where they were easy to replace without changing the public API.
61
+ - The test entrypoint is `vitest`, while the large legacy suite still runs underneath for compatibility.
62
+
63
+ ## Development
64
+
65
+ ```bash
66
+ npm run build
67
+ npm run typecheck
68
+ npm run lint
69
+ npm test
70
+ ```
71
+
72
+ ## License
73
+
74
+ MIT. See [LICENSE](./LICENSE).
@@ -0,0 +1,4 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
3
+ //#endregion
4
+ exports.__commonJSMin = __commonJSMin;
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ const require_lib_globalize = require("./lib/globalize.js");
3
+ const require_lib_geo = require("./lib/geo.js");
4
+ const require_lib_validations = require("./lib/validations.js");
5
+ const require_lib_model = require("./lib/model.js");
6
+ const require_lib_model_builder = require("./lib/model-builder.js");
7
+ const require_lib_kvao_index = require("./lib/kvao/index.js");
8
+ const require_lib_datasource = require("./lib/datasource.js");
9
+ const require_package$1 = require("./package.js");
10
+ //#region src/index.ts
11
+ require_lib_globalize.SetRootDir(__dirname);
12
+ exports.ModelBuilder = exports.LDL = require_lib_model_builder.ModelBuilder;
13
+ exports.DataSource = exports.Schema = require_lib_datasource.DataSource;
14
+ exports.ModelBaseClass = require_lib_model;
15
+ exports.GeoPoint = require_lib_geo.GeoPoint;
16
+ exports.ValidationError = require_lib_validations.ValidationError;
17
+ Object.defineProperty(exports, "version", { get: function() {
18
+ return require_package$1.default.version;
19
+ } });
20
+ const commonTest = "../test/common_test";
21
+ Object.defineProperty(exports, "test", { get: function() {
22
+ return require(commonTest);
23
+ } });
24
+ exports.Transaction = require("@vsaas/loopback-connector").Transaction;
25
+ exports.KeyValueAccessObject = require_lib_kvao_index;
26
+ //#endregion
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ //#region src/lib/browser.depd.ts
3
+ module.exports = function depd(namespace) {
4
+ const warned = {};
5
+ return function deprecate(message) {
6
+ if (warned[message]) return;
7
+ warned[message] = true;
8
+ if (process.noDeprecation) return;
9
+ else if (process.traceDeprecation) console.trace(namespace, "deprecated", message);
10
+ else console.warn(namespace, "deprecated", message);
11
+ };
12
+ };
13
+ //#endregion
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ //#region src/lib/case-utils.ts
3
+ var require_case_utils = /* @__PURE__ */ require("../_virtual/_rolldown/runtime.js").__commonJSMin(((exports, module) => {
4
+ function splitWords(value) {
5
+ return String(value).replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z0-9]+)/g, "$1 $2").replace(/[^A-Za-z0-9]+/g, " ").trim().split(/\s+/).filter(Boolean);
6
+ }
7
+ function pascalCase(value) {
8
+ return splitWords(value).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
9
+ }
10
+ function camelCase(value) {
11
+ const normalized = pascalCase(value);
12
+ if (!normalized) return "";
13
+ return normalized.charAt(0).toLowerCase() + normalized.slice(1);
14
+ }
15
+ module.exports = {
16
+ camelCase,
17
+ pascalCase
18
+ };
19
+ }));
20
+ //#endregion
21
+ module.exports = require_case_utils();
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ //#region src/lib/connectors/kv-memory.ts
3
+ const g = require("../globalize.js")();
4
+ const Connector = require("@vsaas/loopback-connector").Connector;
5
+ const debug = require("debug")("loopback:connector:kv-memory");
6
+ const minimatch = require("minimatch");
7
+ const util = require("util");
8
+ exports.initialize = function initializeDataSource(dataSource, cb) {
9
+ const settings = dataSource.settings;
10
+ dataSource.connector = new KeyValueMemoryConnector(settings, dataSource);
11
+ if (cb) process.nextTick(cb);
12
+ };
13
+ function KeyValueMemoryConnector(settings, dataSource) {
14
+ Connector.call(this, "kv-memory", settings);
15
+ debug("Connector settings", settings);
16
+ this.dataSource = dataSource;
17
+ this.DataAccessObject = dataSource.juggler.KeyValueAccessObject;
18
+ this._store = Object.create(null);
19
+ this._setupRegularCleanup();
20
+ }
21
+ util.inherits(KeyValueMemoryConnector, Connector);
22
+ KeyValueMemoryConnector.prototype._setupRegularCleanup = function() {
23
+ this._cleanupTimer = setInterval(() => {
24
+ if (this && this._removeExpiredItems) this._removeExpiredItems();
25
+ else clearInterval(this._cleanupTimer);
26
+ }, 1e3);
27
+ this._cleanupTimer.unref();
28
+ };
29
+ KeyValueMemoryConnector._removeExpiredItems = function() {
30
+ debug("Running scheduled cleanup of expired items.");
31
+ for (const modelName in this._store) {
32
+ const modelStore = this._store[modelName];
33
+ for (const key in modelStore) if (modelStore[key].isExpired()) {
34
+ debug("Removing expired key", key);
35
+ delete modelStore[key];
36
+ }
37
+ }
38
+ };
39
+ KeyValueMemoryConnector.prototype._getStoreForModel = function(modelName) {
40
+ if (!(modelName in this._store)) this._store[modelName] = Object.create(null);
41
+ return this._store[modelName];
42
+ };
43
+ KeyValueMemoryConnector.prototype._removeIfExpired = function(modelName, key) {
44
+ const store = this._getStoreForModel(modelName);
45
+ let item = store[key];
46
+ if (item && item.isExpired()) {
47
+ debug("Removing expired key", key);
48
+ delete store[key];
49
+ item = void 0;
50
+ return true;
51
+ }
52
+ return false;
53
+ };
54
+ KeyValueMemoryConnector.prototype.get = function(modelName, key, options, callback) {
55
+ this._removeIfExpired(modelName, key);
56
+ const item = this._getStoreForModel(modelName)[key];
57
+ let value = item ? item.value : null;
58
+ debug("GET %j %j -> %s", modelName, key, value);
59
+ if (typeof value === "string" && value.startsWith("buffer:")) value = Buffer.from(value.slice(7), "base64");
60
+ else if (typeof value === "string" && value.startsWith("date:")) value = new Date(value.slice(5));
61
+ else if (value != null) value = JSON.parse(value);
62
+ process.nextTick(function() {
63
+ callback(null, value);
64
+ });
65
+ };
66
+ KeyValueMemoryConnector.prototype.set = function(modelName, key, value, options, callback) {
67
+ const store = this._getStoreForModel(modelName);
68
+ if (Buffer.isBuffer(value)) value = "buffer:" + value.toString("base64");
69
+ else if (value instanceof Date) value = "date:" + value.toISOString();
70
+ else value = JSON.stringify(value);
71
+ debug("SET %j %j %s %j", modelName, key, value, options);
72
+ store[key] = new StoreItem(value, options && options.ttl);
73
+ process.nextTick(callback);
74
+ };
75
+ KeyValueMemoryConnector.prototype.expire = function(modelName, key, ttl, options, callback) {
76
+ this._removeIfExpired(modelName, key);
77
+ const store = this._getStoreForModel(modelName);
78
+ if (!(key in store)) return process.nextTick(function() {
79
+ const err = new Error(g.f("Cannot expire unknown key %j", key));
80
+ err.statusCode = 404;
81
+ callback(err);
82
+ });
83
+ debug("EXPIRE %j %j %s", modelName, key, ttl || "(never)");
84
+ store[key].setTtl(ttl);
85
+ process.nextTick(callback);
86
+ };
87
+ KeyValueMemoryConnector.prototype.ttl = function(modelName, key, options, callback) {
88
+ this._removeIfExpired(modelName, key);
89
+ const store = this._getStoreForModel(modelName);
90
+ if (!(key in store)) return process.nextTick(function() {
91
+ const err = new Error(g.f("Cannot get TTL for unknown key %j", key));
92
+ err.statusCode = 404;
93
+ callback(err);
94
+ });
95
+ const ttl = store[key].getTtl();
96
+ debug("TTL %j %j -> %s", modelName, key, ttl);
97
+ process.nextTick(function() {
98
+ callback(null, ttl);
99
+ });
100
+ };
101
+ KeyValueMemoryConnector.prototype.iterateKeys = function(modelName, filter, _options, _callback) {
102
+ const store = this._getStoreForModel(modelName);
103
+ const self = this;
104
+ const checkFilter = createMatcher(filter.match);
105
+ const keys = Object.keys(store).filter(function(key) {
106
+ return !self._removeIfExpired(modelName, key) && checkFilter(key);
107
+ });
108
+ debug("ITERATE KEYS %j -> %s keys", modelName, keys.length);
109
+ let ix = 0;
110
+ return { next: function(cb) {
111
+ const value = ix < keys.length ? keys[ix++] : void 0;
112
+ setImmediate(function() {
113
+ cb(null, value);
114
+ });
115
+ } };
116
+ };
117
+ function createMatcher(pattern) {
118
+ if (!pattern) return function matchAll() {
119
+ return true;
120
+ };
121
+ return minimatch.filter(pattern, {
122
+ nobrace: true,
123
+ noglobstar: true,
124
+ dot: true,
125
+ noext: true,
126
+ nocomment: true
127
+ });
128
+ }
129
+ KeyValueMemoryConnector.prototype.disconnect = function(callback) {
130
+ if (this._cleanupTimer) clearInterval(this._cleanupTimer);
131
+ this._cleanupTimer = null;
132
+ process.nextTick(callback);
133
+ };
134
+ KeyValueMemoryConnector.prototype.delete = function(modelName, key, options, callback) {
135
+ const store = this._getStoreForModel(modelName);
136
+ delete store[key];
137
+ callback();
138
+ };
139
+ KeyValueMemoryConnector.prototype.deleteAll = function(modelName, options, callback) {
140
+ const modelStore = this._getStoreForModel(modelName);
141
+ for (const key in modelStore) delete modelStore[key];
142
+ callback();
143
+ };
144
+ function StoreItem(value, ttl) {
145
+ this.value = value;
146
+ this.setTtl(ttl);
147
+ }
148
+ StoreItem.prototype.isExpired = function() {
149
+ return this.expires && this.expires <= Date.now();
150
+ };
151
+ StoreItem.prototype.setTtl = function(ttl) {
152
+ if (ttl) this.expires = Date.now() + ttl;
153
+ else this.expires = void 0;
154
+ };
155
+ StoreItem.prototype.getTtl = function() {
156
+ return !this.expires ? void 0 : this.expires - Date.now();
157
+ };
158
+ //#endregion