masterrecord 0.3.5 ā 0.3.7
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/Cache/QueryCache.js +175 -0
- package/Cache/RedisQueryCache.js +155 -0
- package/QueryLanguage/queryMethods.js +72 -25
- package/context.js +51 -0
- package/package.json +1 -1
- package/readme.md +295 -4
- package/test/cacheIntegration.test.js +319 -0
- package/test/multiContextCache.test.js +230 -0
- package/test/multiContextCacheSimple.test.js +185 -0
- package/test/queryCache.test.js +148 -0
- package/examples/jsonArrayTransformer.js +0 -215
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Real-World Example: Storing JavaScript Arrays as JSON Strings
|
|
3
|
-
*
|
|
4
|
-
* This example demonstrates how to use field transformers to store
|
|
5
|
-
* JavaScript arrays in database string columns, solving the common
|
|
6
|
-
* problem of "Type validation blocking array-to-JSON transformation"
|
|
7
|
-
*
|
|
8
|
-
* BEFORE (using raw SQL - not ideal):
|
|
9
|
-
* - Some fields saved through ORM
|
|
10
|
-
* - Array fields saved via raw SQL to bypass validation
|
|
11
|
-
* - Inconsistent, error-prone, loses ORM benefits
|
|
12
|
-
*
|
|
13
|
-
* AFTER (using transformers - production-ready):
|
|
14
|
-
* - All fields saved through ORM consistently
|
|
15
|
-
* - Arrays automatically transformed to/from JSON
|
|
16
|
-
* - Type-safe, maintainable, elegant
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const masterrecord = require('masterrecord');
|
|
20
|
-
|
|
21
|
-
// ============================================================================
|
|
22
|
-
// 1. Define Entity with Transformers
|
|
23
|
-
// ============================================================================
|
|
24
|
-
|
|
25
|
-
class User {
|
|
26
|
-
constructor() {
|
|
27
|
-
// Regular fields - no transformation needed
|
|
28
|
-
this.id = { type: "integer", primary: true, auto: true };
|
|
29
|
-
this.name = { type: "string" };
|
|
30
|
-
this.email = { type: "string" };
|
|
31
|
-
this.role = { type: "string" };
|
|
32
|
-
|
|
33
|
-
// š„ ARRAY FIELDS WITH TRANSFORMERS
|
|
34
|
-
// These fields store arrays as JSON strings in the database
|
|
35
|
-
this.certified_models = {
|
|
36
|
-
type: "string", // Database column type
|
|
37
|
-
nullable: true,
|
|
38
|
-
transform: {
|
|
39
|
-
// Transform JavaScript array ā JSON string for database
|
|
40
|
-
toDatabase: (value) => {
|
|
41
|
-
if (value === null || value === undefined) return null;
|
|
42
|
-
if (Array.isArray(value)) return JSON.stringify(value);
|
|
43
|
-
// Already a string (maybe from edit scenario)
|
|
44
|
-
return value;
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
// Transform JSON string ā JavaScript array from database
|
|
48
|
-
fromDatabase: (value) => {
|
|
49
|
-
if (!value) return [];
|
|
50
|
-
if (Array.isArray(value)) return value; // Already parsed
|
|
51
|
-
try {
|
|
52
|
-
return JSON.parse(value);
|
|
53
|
-
} catch {
|
|
54
|
-
console.warn(`Failed to parse certified_models: ${value}`);
|
|
55
|
-
return [];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
this.certified_agent_types = {
|
|
62
|
-
type: "string",
|
|
63
|
-
nullable: true,
|
|
64
|
-
transform: {
|
|
65
|
-
toDatabase: (value) => {
|
|
66
|
-
if (value === null || value === undefined) return null;
|
|
67
|
-
if (Array.isArray(value)) return JSON.stringify(value);
|
|
68
|
-
return value;
|
|
69
|
-
},
|
|
70
|
-
fromDatabase: (value) => {
|
|
71
|
-
if (!value) return [];
|
|
72
|
-
if (Array.isArray(value)) return value;
|
|
73
|
-
try {
|
|
74
|
-
return JSON.parse(value);
|
|
75
|
-
} catch {
|
|
76
|
-
console.warn(`Failed to parse certified_agent_types: ${value}`);
|
|
77
|
-
return [];
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
// Regular numeric field
|
|
84
|
-
this.calibration_score = { type: "integer", nullable: true };
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ============================================================================
|
|
89
|
-
// 2. Create Context
|
|
90
|
-
// ============================================================================
|
|
91
|
-
|
|
92
|
-
class AppContext extends masterrecord.context {
|
|
93
|
-
constructor(config) {
|
|
94
|
-
super(config);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
onConfig(db) {
|
|
98
|
-
this.User = this.dbset(User, "User");
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ============================================================================
|
|
103
|
-
// 3. Usage Example - Creating a User with Arrays
|
|
104
|
-
// ============================================================================
|
|
105
|
-
|
|
106
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
107
|
-
console.log("ā JSON Array Transformer - Real-World Example ā");
|
|
108
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
|
|
109
|
-
|
|
110
|
-
console.log("š Scenario: User certification management system");
|
|
111
|
-
console.log(" - Users can be certified for multiple AI models");
|
|
112
|
-
console.log(" - Users can handle multiple agent types");
|
|
113
|
-
console.log(" - Arrays stored as JSON strings in database\n");
|
|
114
|
-
|
|
115
|
-
// Simulated context (in real app, this would connect to actual database)
|
|
116
|
-
console.log("1ļøā£ Creating new user with array fields");
|
|
117
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
118
|
-
|
|
119
|
-
const user = new User();
|
|
120
|
-
user.name = "Alex Rich";
|
|
121
|
-
user.email = "alex@example.com";
|
|
122
|
-
user.role = "calibrator";
|
|
123
|
-
|
|
124
|
-
// ⨠Arrays assigned naturally - NO raw SQL needed!
|
|
125
|
-
user.certified_models = [1, 2, 5, 8]; // Array of model IDs
|
|
126
|
-
user.certified_agent_types = [10, 20, 30]; // Array of agent type IDs
|
|
127
|
-
user.calibration_score = 95;
|
|
128
|
-
|
|
129
|
-
console.log(` Name: ${user.name}`);
|
|
130
|
-
console.log(` Certified Models (array): [${user.certified_models.join(', ')}]`);
|
|
131
|
-
console.log(` Certified Agent Types (array): [${user.certified_agent_types.join(', ')}]`);
|
|
132
|
-
console.log(` Calibration Score: ${user.calibration_score}\n`);
|
|
133
|
-
|
|
134
|
-
// When saved, transformers automatically convert:
|
|
135
|
-
// [1, 2, 5, 8] ā "[1,2,5,8]" (stored in DB)
|
|
136
|
-
console.log("2ļøā£ What happens when saving");
|
|
137
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
138
|
-
console.log(" User provides: [1, 2, 5, 8]");
|
|
139
|
-
console.log(" ā");
|
|
140
|
-
console.log(" Transformer (toDatabase): [1, 2, 5, 8] ā '[1,2,5,8]'");
|
|
141
|
-
console.log(" ā");
|
|
142
|
-
console.log(" Type Validation: string '[1,2,5,8]' ā matches type: 'string'");
|
|
143
|
-
console.log(" ā");
|
|
144
|
-
console.log(" Database Stores: '[1,2,5,8]' (as string column)\n");
|
|
145
|
-
|
|
146
|
-
// Standard save - no raw SQL required!
|
|
147
|
-
// context.User.add(user);
|
|
148
|
-
// context.saveChanges();
|
|
149
|
-
|
|
150
|
-
console.log("3ļøā£ What happens when loading");
|
|
151
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
152
|
-
console.log(" Database Returns: '[1,2,5,8]' (string)");
|
|
153
|
-
console.log(" ā");
|
|
154
|
-
console.log(" Transformer (fromDatabase): '[1,2,5,8]' ā [1, 2, 5, 8]");
|
|
155
|
-
console.log(" ā");
|
|
156
|
-
console.log(" Application Receives: [1, 2, 5, 8] (JavaScript array)");
|
|
157
|
-
console.log(" ā");
|
|
158
|
-
console.log(" Code: user.certified_models.includes(2) ā true ā\n");
|
|
159
|
-
|
|
160
|
-
// When loaded from DB, transformers automatically convert back:
|
|
161
|
-
// "[1,2,5,8]" ā [1, 2, 5, 8] (JavaScript array)
|
|
162
|
-
// const users = context.User.where(u => u.id == $$, userId).toList();
|
|
163
|
-
// console.log(users[0].certified_models); // [1, 2, 5, 8]
|
|
164
|
-
|
|
165
|
-
console.log("4ļøā£ Updating existing user");
|
|
166
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
167
|
-
console.log(" const user = context.User.where(u => u.id == $$, 14).single();");
|
|
168
|
-
console.log(" user.certified_models = [1, 2, 5, 8, 12]; // Add model 12");
|
|
169
|
-
console.log(" context.saveChanges(); // ā Works perfectly!\n");
|
|
170
|
-
|
|
171
|
-
console.log("5ļøā£ Benefits over raw SQL approach");
|
|
172
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
173
|
-
console.log(" ā
Consistent ORM usage (no raw SQL needed)");
|
|
174
|
-
console.log(" ā
Automatic transformation (transparent to application code)");
|
|
175
|
-
console.log(" ā
Type-safe (validation happens after transformation)");
|
|
176
|
-
console.log(" ā
Maintainable (transformation logic in one place)");
|
|
177
|
-
console.log(" ā
Testable (transformers are pure functions)");
|
|
178
|
-
console.log(" ā
Works with all ORM features (tracking, relationships, etc.)\n");
|
|
179
|
-
|
|
180
|
-
console.log("6ļøā£ Common Patterns");
|
|
181
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
182
|
-
|
|
183
|
-
console.log("\n Pattern A: Simple Arrays");
|
|
184
|
-
console.log(" āāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
185
|
-
console.log(" certified_models: [1, 2, 3] ā '[1,2,3]'");
|
|
186
|
-
|
|
187
|
-
console.log("\n Pattern B: String Arrays");
|
|
188
|
-
console.log(" āāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
189
|
-
console.log(" tags: ['urgent', 'review'] ā '[\"urgent\",\"review\"]'");
|
|
190
|
-
|
|
191
|
-
console.log("\n Pattern C: Complex Objects");
|
|
192
|
-
console.log(" āāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
193
|
-
console.log(" metadata: {key: 'value'} ā '{\"key\":\"value\"}'");
|
|
194
|
-
console.log(" transform: { toDatabase: JSON.stringify, fromDatabase: JSON.parse }");
|
|
195
|
-
|
|
196
|
-
console.log("\n Pattern D: Defaults for Null");
|
|
197
|
-
console.log(" āāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
198
|
-
console.log(" fromDatabase: (v) => v ? JSON.parse(v) : []");
|
|
199
|
-
|
|
200
|
-
console.log("\n\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
201
|
-
console.log("ā Summary ā");
|
|
202
|
-
console.log("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
|
|
203
|
-
|
|
204
|
-
console.log("⨠PROBLEM SOLVED!");
|
|
205
|
-
console.log("\nBefore: Had to use raw SQL to bypass type validation");
|
|
206
|
-
console.log(" const sql = `UPDATE User SET certified_models = ? WHERE id = ?`;");
|
|
207
|
-
console.log(" context.User.raw(sql, [jsonString, userId]);");
|
|
208
|
-
console.log("\nAfter: Use ORM naturally with automatic transformation");
|
|
209
|
-
console.log(" user.certified_models = [1, 2, 3];");
|
|
210
|
-
console.log(" context.saveChanges();");
|
|
211
|
-
|
|
212
|
-
console.log("\nšÆ Use Case: This example solves the exact problem from the");
|
|
213
|
-
console.log(" BookBag calibration system where arrays needed to bypass ORM.\n");
|
|
214
|
-
|
|
215
|
-
console.log("š See readme.md 'Field Transformers' section for full documentation.\n");
|