@rws-framework/db 3.9.0 → 3.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/models/core/RWSModel.d.ts +1 -1
- package/dist/models/core/RWSModel.js +33 -29
- package/dist/models/interfaces/IModel.d.ts +1 -1
- package/dist/models/utils/FindUtils.js +70 -131
- package/package.json +1 -1
- package/src/models/core/RWSModel.ts +13 -15
- package/src/models/interfaces/IModel.ts +1 -1
- package/src/models/utils/FindUtils.ts +84 -150
- package/LOADING_CONTEXT_FIX.md +0 -139
- package/LOADING_CONTEXT_IMPLEMENTATION.md +0 -122
- package/dist/models/utils/LoadingContext.d.ts +0 -56
- package/dist/models/utils/LoadingContext.js +0 -119
- package/dist/models/utils/LoadingContext.test.d.ts +0 -5
- package/dist/models/utils/LoadingContext.test.js +0 -51
- package/dist/models/utils/index.d.ts +0 -7
- package/dist/models/utils/index.js +0 -17
- package/src/models/utils/LoadingContext.ts +0 -140
- package/src/models/utils/index.ts +0 -7
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* LoadingContext - Prevents circular references during model loading by tracking
|
|
4
|
-
* the chain of models currently being loaded per execution context
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.LoadingContext = void 0;
|
|
8
|
-
class LoadingContext {
|
|
9
|
-
static executionContexts = new WeakMap();
|
|
10
|
-
static defaultMaxDepth = 10;
|
|
11
|
-
/**
|
|
12
|
-
* Get or create execution context identifier
|
|
13
|
-
*/
|
|
14
|
-
static getExecutionContext() {
|
|
15
|
-
// Use a simple object as execution context identifier
|
|
16
|
-
// In a real-world scenario, this could be tied to request context
|
|
17
|
-
if (!globalThis.__currentExecutionContext) {
|
|
18
|
-
globalThis.__currentExecutionContext = {};
|
|
19
|
-
}
|
|
20
|
-
return globalThis.__currentExecutionContext;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Create a new execution context for an operation
|
|
24
|
-
*/
|
|
25
|
-
static withNewExecutionContext(fn) {
|
|
26
|
-
const previousContext = globalThis.__currentExecutionContext;
|
|
27
|
-
try {
|
|
28
|
-
globalThis.__currentExecutionContext = {};
|
|
29
|
-
return fn();
|
|
30
|
-
}
|
|
31
|
-
finally {
|
|
32
|
-
globalThis.__currentExecutionContext = previousContext;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Get the loading stack for current execution context
|
|
37
|
-
*/
|
|
38
|
-
static getLoadingStackInternal() {
|
|
39
|
-
const context = this.getExecutionContext();
|
|
40
|
-
if (!this.executionContexts.has(context)) {
|
|
41
|
-
this.executionContexts.set(context, new Set());
|
|
42
|
-
}
|
|
43
|
-
return this.executionContexts.get(context);
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Check if a model with specific ID is currently being loaded
|
|
47
|
-
*/
|
|
48
|
-
static isLoading(modelType, id) {
|
|
49
|
-
const key = this.createKey(modelType, id);
|
|
50
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
51
|
-
return loadingStack.has(key);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Mark a model as currently being loaded
|
|
55
|
-
*/
|
|
56
|
-
static startLoading(modelType, id) {
|
|
57
|
-
const key = this.createKey(modelType, id);
|
|
58
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
59
|
-
// Check for maximum depth to prevent infinite chains
|
|
60
|
-
if (loadingStack.size >= this.defaultMaxDepth) {
|
|
61
|
-
const stackArray = Array.from(loadingStack);
|
|
62
|
-
throw new Error(`Maximum loading depth (${this.defaultMaxDepth}) exceeded. ` +
|
|
63
|
-
`Possible circular reference detected. Loading stack: ${stackArray.join(' -> ')} -> ${key}`);
|
|
64
|
-
}
|
|
65
|
-
loadingStack.add(key);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Mark a model as finished loading
|
|
69
|
-
*/
|
|
70
|
-
static finishLoading(modelType, id) {
|
|
71
|
-
const key = this.createKey(modelType, id);
|
|
72
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
73
|
-
loadingStack.delete(key);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Get current loading stack for debugging
|
|
77
|
-
*/
|
|
78
|
-
static getLoadingStack() {
|
|
79
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
80
|
-
return Array.from(loadingStack);
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Clear the entire loading stack for current context
|
|
84
|
-
*/
|
|
85
|
-
static clearStack() {
|
|
86
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
87
|
-
loadingStack.clear();
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Set default maximum loading depth
|
|
91
|
-
*/
|
|
92
|
-
static setDefaultMaxDepth(depth) {
|
|
93
|
-
this.defaultMaxDepth = depth;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Create a unique key for model type and ID
|
|
97
|
-
*/
|
|
98
|
-
static createKey(modelType, id) {
|
|
99
|
-
return `${modelType}:${id}`;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Execute a function with loading context protection
|
|
103
|
-
* Automatically manages start/finish loading calls
|
|
104
|
-
*/
|
|
105
|
-
static async withLoadingContext(modelType, id, fn) {
|
|
106
|
-
if (this.isLoading(modelType, id)) {
|
|
107
|
-
// If already loading, return null to break the cycle
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
this.startLoading(modelType, id);
|
|
111
|
-
try {
|
|
112
|
-
return await fn();
|
|
113
|
-
}
|
|
114
|
-
finally {
|
|
115
|
-
this.finishLoading(modelType, id);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
exports.LoadingContext = LoadingContext;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.testLoadingContext = testLoadingContext;
|
|
4
|
-
const LoadingContext_1 = require("./LoadingContext");
|
|
5
|
-
/**
|
|
6
|
-
* Simple test to verify LoadingContext functionality
|
|
7
|
-
*/
|
|
8
|
-
async function testLoadingContext() {
|
|
9
|
-
console.log('Testing LoadingContext...');
|
|
10
|
-
// Test 1: Basic loading detection
|
|
11
|
-
console.log('Test 1: Basic loading detection');
|
|
12
|
-
console.log('Is User:1 loading?', LoadingContext_1.LoadingContext.isLoading('User', 1)); // Should be false
|
|
13
|
-
LoadingContext_1.LoadingContext.startLoading('User', 1);
|
|
14
|
-
console.log('Is User:1 loading?', LoadingContext_1.LoadingContext.isLoading('User', 1)); // Should be true
|
|
15
|
-
LoadingContext_1.LoadingContext.finishLoading('User', 1);
|
|
16
|
-
console.log('Is User:1 loading?', LoadingContext_1.LoadingContext.isLoading('User', 1)); // Should be false
|
|
17
|
-
// Test 2: Circular reference detection
|
|
18
|
-
console.log('\nTest 2: Circular reference detection');
|
|
19
|
-
try {
|
|
20
|
-
await LoadingContext_1.LoadingContext.withLoadingContext('User', 1, async () => {
|
|
21
|
-
console.log('Loading User:1...');
|
|
22
|
-
// Simulate trying to load the same model again (circular reference)
|
|
23
|
-
const result = await LoadingContext_1.LoadingContext.withLoadingContext('User', 1, async () => {
|
|
24
|
-
console.log('This should not execute - circular reference detected');
|
|
25
|
-
return 'should not reach here';
|
|
26
|
-
});
|
|
27
|
-
console.log('Circular reference result:', result); // Should be null
|
|
28
|
-
return 'User loaded successfully';
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
catch (error) {
|
|
32
|
-
console.error('Error in circular reference test:', error);
|
|
33
|
-
}
|
|
34
|
-
// Test 3: Maximum depth protection
|
|
35
|
-
console.log('\nTest 3: Maximum depth protection');
|
|
36
|
-
LoadingContext_1.LoadingContext.setMaxDepth(3);
|
|
37
|
-
try {
|
|
38
|
-
LoadingContext_1.LoadingContext.startLoading('Model1', 1);
|
|
39
|
-
LoadingContext_1.LoadingContext.startLoading('Model2', 2);
|
|
40
|
-
LoadingContext_1.LoadingContext.startLoading('Model3', 3);
|
|
41
|
-
// This should throw an error
|
|
42
|
-
LoadingContext_1.LoadingContext.startLoading('Model4', 4);
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
console.log('Expected error caught:', error.message);
|
|
46
|
-
}
|
|
47
|
-
finally {
|
|
48
|
-
LoadingContext_1.LoadingContext.clearStack();
|
|
49
|
-
}
|
|
50
|
-
console.log('LoadingContext tests completed!');
|
|
51
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { FindUtils } from './FindUtils';
|
|
2
|
-
export { HydrateUtils } from './HydrateUtils';
|
|
3
|
-
export { LoadingContext } from './LoadingContext';
|
|
4
|
-
export { ModelUtils } from './ModelUtils';
|
|
5
|
-
export { PaginationUtils } from './PaginationUtils';
|
|
6
|
-
export { RelationUtils } from './RelationUtils';
|
|
7
|
-
export { TimeSeriesUtils } from './TimeSeriesUtils';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TimeSeriesUtils = exports.RelationUtils = exports.PaginationUtils = exports.ModelUtils = exports.LoadingContext = exports.HydrateUtils = exports.FindUtils = void 0;
|
|
4
|
-
var FindUtils_1 = require("./FindUtils");
|
|
5
|
-
Object.defineProperty(exports, "FindUtils", { enumerable: true, get: function () { return FindUtils_1.FindUtils; } });
|
|
6
|
-
var HydrateUtils_1 = require("./HydrateUtils");
|
|
7
|
-
Object.defineProperty(exports, "HydrateUtils", { enumerable: true, get: function () { return HydrateUtils_1.HydrateUtils; } });
|
|
8
|
-
var LoadingContext_1 = require("./LoadingContext");
|
|
9
|
-
Object.defineProperty(exports, "LoadingContext", { enumerable: true, get: function () { return LoadingContext_1.LoadingContext; } });
|
|
10
|
-
var ModelUtils_1 = require("./ModelUtils");
|
|
11
|
-
Object.defineProperty(exports, "ModelUtils", { enumerable: true, get: function () { return ModelUtils_1.ModelUtils; } });
|
|
12
|
-
var PaginationUtils_1 = require("./PaginationUtils");
|
|
13
|
-
Object.defineProperty(exports, "PaginationUtils", { enumerable: true, get: function () { return PaginationUtils_1.PaginationUtils; } });
|
|
14
|
-
var RelationUtils_1 = require("./RelationUtils");
|
|
15
|
-
Object.defineProperty(exports, "RelationUtils", { enumerable: true, get: function () { return RelationUtils_1.RelationUtils; } });
|
|
16
|
-
var TimeSeriesUtils_1 = require("./TimeSeriesUtils");
|
|
17
|
-
Object.defineProperty(exports, "TimeSeriesUtils", { enumerable: true, get: function () { return TimeSeriesUtils_1.TimeSeriesUtils; } });
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LoadingContext - Prevents circular references during model loading by tracking
|
|
3
|
-
* the chain of models currently being loaded per execution context
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Extend the global object type to include our execution context
|
|
7
|
-
declare global {
|
|
8
|
-
var __currentExecutionContext: object | undefined;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export class LoadingContext {
|
|
12
|
-
private static executionContexts = new WeakMap<object, Set<string>>();
|
|
13
|
-
private static defaultMaxDepth: number = 10;
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Get or create execution context identifier
|
|
17
|
-
*/
|
|
18
|
-
private static getExecutionContext(): object {
|
|
19
|
-
// Use a simple object as execution context identifier
|
|
20
|
-
// In a real-world scenario, this could be tied to request context
|
|
21
|
-
if (!globalThis.__currentExecutionContext) {
|
|
22
|
-
globalThis.__currentExecutionContext = {};
|
|
23
|
-
}
|
|
24
|
-
return globalThis.__currentExecutionContext;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Create a new execution context for an operation
|
|
29
|
-
*/
|
|
30
|
-
static withNewExecutionContext<T>(fn: () => Promise<T>): Promise<T> {
|
|
31
|
-
const previousContext = globalThis.__currentExecutionContext;
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
globalThis.__currentExecutionContext = {};
|
|
35
|
-
return fn();
|
|
36
|
-
} finally {
|
|
37
|
-
globalThis.__currentExecutionContext = previousContext;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get the loading stack for current execution context
|
|
43
|
-
*/
|
|
44
|
-
private static getLoadingStackInternal(): Set<string> {
|
|
45
|
-
const context = this.getExecutionContext();
|
|
46
|
-
if (!this.executionContexts.has(context)) {
|
|
47
|
-
this.executionContexts.set(context, new Set<string>());
|
|
48
|
-
}
|
|
49
|
-
return this.executionContexts.get(context)!;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Check if a model with specific ID is currently being loaded
|
|
54
|
-
*/
|
|
55
|
-
static isLoading(modelType: string, id: string | number): boolean {
|
|
56
|
-
const key = this.createKey(modelType, id);
|
|
57
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
58
|
-
return loadingStack.has(key);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Mark a model as currently being loaded
|
|
63
|
-
*/
|
|
64
|
-
static startLoading(modelType: string, id: string | number): void {
|
|
65
|
-
const key = this.createKey(modelType, id);
|
|
66
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
67
|
-
|
|
68
|
-
// Check for maximum depth to prevent infinite chains
|
|
69
|
-
if (loadingStack.size >= this.defaultMaxDepth) {
|
|
70
|
-
const stackArray = Array.from(loadingStack);
|
|
71
|
-
throw new Error(
|
|
72
|
-
`Maximum loading depth (${this.defaultMaxDepth}) exceeded. ` +
|
|
73
|
-
`Possible circular reference detected. Loading stack: ${stackArray.join(' -> ')} -> ${key}`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
loadingStack.add(key);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Mark a model as finished loading
|
|
82
|
-
*/
|
|
83
|
-
static finishLoading(modelType: string, id: string | number): void {
|
|
84
|
-
const key = this.createKey(modelType, id);
|
|
85
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
86
|
-
loadingStack.delete(key);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Get current loading stack for debugging
|
|
91
|
-
*/
|
|
92
|
-
static getLoadingStack(): string[] {
|
|
93
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
94
|
-
return Array.from(loadingStack);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Clear the entire loading stack for current context
|
|
99
|
-
*/
|
|
100
|
-
static clearStack(): void {
|
|
101
|
-
const loadingStack = this.getLoadingStackInternal();
|
|
102
|
-
loadingStack.clear();
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Set default maximum loading depth
|
|
107
|
-
*/
|
|
108
|
-
static setDefaultMaxDepth(depth: number): void {
|
|
109
|
-
this.defaultMaxDepth = depth;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Create a unique key for model type and ID
|
|
114
|
-
*/
|
|
115
|
-
private static createKey(modelType: string, id: string | number): string {
|
|
116
|
-
return `${modelType}:${id}`;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Execute a function with loading context protection
|
|
121
|
-
* Automatically manages start/finish loading calls
|
|
122
|
-
*/
|
|
123
|
-
static async withLoadingContext<T>(
|
|
124
|
-
modelType: string,
|
|
125
|
-
id: string | number,
|
|
126
|
-
fn: () => Promise<T>
|
|
127
|
-
): Promise<T> {
|
|
128
|
-
if (this.isLoading(modelType, id)) {
|
|
129
|
-
// If already loading, return null to break the cycle
|
|
130
|
-
return null as T;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
this.startLoading(modelType, id);
|
|
134
|
-
try {
|
|
135
|
-
return await fn();
|
|
136
|
-
} finally {
|
|
137
|
-
this.finishLoading(modelType, id);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { FindUtils } from './FindUtils';
|
|
2
|
-
export { HydrateUtils } from './HydrateUtils';
|
|
3
|
-
export { LoadingContext } from './LoadingContext';
|
|
4
|
-
export { ModelUtils } from './ModelUtils';
|
|
5
|
-
export { PaginationUtils } from './PaginationUtils';
|
|
6
|
-
export { RelationUtils } from './RelationUtils';
|
|
7
|
-
export { TimeSeriesUtils } from './TimeSeriesUtils';
|