@arcaelas/dynamite 1.0.29 → 3.1.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.
- package/README.md +13 -13
- package/{src → build/cjs}/@types/index.d.ts +26 -1
- package/build/cjs/@types/index.js.map +1 -0
- package/{src → build/cjs}/core/client.d.ts +22 -19
- package/build/cjs/core/client.js +384 -0
- package/build/cjs/core/client.js.map +1 -0
- package/build/cjs/core/decorator.d.ts +50 -0
- package/build/cjs/core/decorator.js +52 -0
- package/build/cjs/core/decorator.js.map +1 -0
- package/build/cjs/core/table.d.ts +73 -0
- package/build/cjs/core/table.js +953 -0
- package/build/cjs/core/table.js.map +1 -0
- package/build/cjs/decorators/hooks.d.ts +35 -0
- package/build/cjs/decorators/hooks.js +50 -0
- package/build/cjs/decorators/hooks.js.map +1 -0
- package/build/cjs/decorators/indexes.d.ts +20 -0
- package/build/cjs/decorators/indexes.js +45 -0
- package/build/cjs/decorators/indexes.js.map +1 -0
- package/{src → build/cjs}/decorators/relations.d.ts +8 -7
- package/{src → build/cjs}/decorators/relations.js +9 -8
- package/build/cjs/decorators/relations.js.map +1 -0
- package/build/cjs/decorators/timestamps.d.ts +20 -0
- package/build/cjs/decorators/timestamps.js +34 -0
- package/build/cjs/decorators/timestamps.js.map +1 -0
- package/build/cjs/decorators/transforms.d.ts +41 -0
- package/build/cjs/decorators/transforms.js +98 -0
- package/build/cjs/decorators/transforms.js.map +1 -0
- package/{src → build/cjs}/index.d.ts +7 -3
- package/{src → build/cjs}/index.js +15 -6
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/package.json +1 -0
- package/build/cjs/test/basic.d.ts +1 -0
- package/build/cjs/test/basic.js +248 -0
- package/build/cjs/test/basic.js.map +1 -0
- package/build/cjs/test/bulk.d.ts +1 -0
- package/build/cjs/test/bulk.js +108 -0
- package/build/cjs/test/bulk.js.map +1 -0
- package/build/cjs/test/contracts.d.ts +1 -0
- package/build/cjs/test/contracts.js +343 -0
- package/build/cjs/test/contracts.js.map +1 -0
- package/build/cjs/test/filters.d.ts +1 -0
- package/build/cjs/test/filters.js +190 -0
- package/build/cjs/test/filters.js.map +1 -0
- package/build/cjs/test/hooks.d.ts +1 -0
- package/build/cjs/test/hooks.js +191 -0
- package/build/cjs/test/hooks.js.map +1 -0
- package/build/cjs/test/index.js +38 -0
- package/build/cjs/test/index.js.map +1 -0
- package/build/cjs/test/query_scan.d.ts +1 -0
- package/build/cjs/test/query_scan.js +195 -0
- package/build/cjs/test/query_scan.js.map +1 -0
- package/build/cjs/test/relations.d.ts +1 -0
- package/build/cjs/test/relations.js +246 -0
- package/build/cjs/test/relations.js.map +1 -0
- package/build/cjs/test/transactions.d.ts +1 -0
- package/build/cjs/test/transactions.js +145 -0
- package/build/cjs/test/transactions.js.map +1 -0
- package/{src → build/cjs}/utils/relations.js +1 -8
- package/build/cjs/utils/relations.js.map +1 -0
- package/build/cjs/utils/ulid.d.ts +10 -0
- package/build/cjs/utils/ulid.js +55 -0
- package/build/cjs/utils/ulid.js.map +1 -0
- package/build/esm/@types/index.d.ts +213 -0
- package/build/esm/@types/index.js +8 -0
- package/build/esm/@types/index.js.map +1 -0
- package/build/esm/core/client.d.ts +96 -0
- package/build/esm/core/client.js +375 -0
- package/build/esm/core/client.js.map +1 -0
- package/build/esm/core/decorator.d.ts +50 -0
- package/build/esm/core/decorator.js +47 -0
- package/build/esm/core/decorator.js.map +1 -0
- package/build/esm/core/table.d.ts +73 -0
- package/build/esm/core/table.js +950 -0
- package/build/esm/core/table.js.map +1 -0
- package/build/esm/decorators/hooks.d.ts +35 -0
- package/build/esm/decorators/hooks.js +47 -0
- package/build/esm/decorators/hooks.js.map +1 -0
- package/build/esm/decorators/indexes.d.ts +20 -0
- package/build/esm/decorators/indexes.js +42 -0
- package/build/esm/decorators/indexes.js.map +1 -0
- package/build/esm/decorators/relations.d.ts +75 -0
- package/build/esm/decorators/relations.js +112 -0
- package/build/esm/decorators/relations.js.map +1 -0
- package/build/esm/decorators/timestamps.d.ts +20 -0
- package/build/esm/decorators/timestamps.js +31 -0
- package/build/esm/decorators/timestamps.js.map +1 -0
- package/build/esm/decorators/transforms.d.ts +41 -0
- package/build/esm/decorators/transforms.js +92 -0
- package/build/esm/decorators/transforms.js.map +1 -0
- package/build/esm/index.d.ts +19 -0
- package/build/esm/index.js +26 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/package.json +1 -0
- package/build/esm/test/basic.d.ts +1 -0
- package/build/esm/test/basic.js +245 -0
- package/build/esm/test/basic.js.map +1 -0
- package/build/esm/test/bulk.d.ts +1 -0
- package/build/esm/test/bulk.js +105 -0
- package/build/esm/test/bulk.js.map +1 -0
- package/build/esm/test/contracts.d.ts +1 -0
- package/build/esm/test/contracts.js +340 -0
- package/build/esm/test/contracts.js.map +1 -0
- package/build/esm/test/filters.d.ts +1 -0
- package/build/esm/test/filters.js +187 -0
- package/build/esm/test/filters.js.map +1 -0
- package/build/esm/test/hooks.d.ts +1 -0
- package/build/esm/test/hooks.js +188 -0
- package/build/esm/test/hooks.js.map +1 -0
- package/build/esm/test/index.d.ts +1 -0
- package/build/esm/test/index.js +33 -0
- package/build/esm/test/index.js.map +1 -0
- package/build/esm/test/query_scan.d.ts +1 -0
- package/build/esm/test/query_scan.js +192 -0
- package/build/esm/test/query_scan.js.map +1 -0
- package/build/esm/test/relations.d.ts +1 -0
- package/build/esm/test/relations.js +243 -0
- package/build/esm/test/relations.js.map +1 -0
- package/build/esm/test/transactions.d.ts +1 -0
- package/build/esm/test/transactions.js +142 -0
- package/build/esm/test/transactions.js.map +1 -0
- package/build/esm/utils/relations.d.ts +42 -0
- package/build/esm/utils/relations.js +207 -0
- package/build/esm/utils/relations.js.map +1 -0
- package/build/esm/utils/ulid.d.ts +10 -0
- package/build/esm/utils/ulid.js +52 -0
- package/build/esm/utils/ulid.js.map +1 -0
- package/package.json +31 -9
- package/src/core/client.js +0 -296
- package/src/core/decorator.d.ts +0 -29
- package/src/core/decorator.js +0 -103
- package/src/core/table.d.ts +0 -81
- package/src/core/table.js +0 -892
- package/src/decorators/indexes.d.ts +0 -38
- package/src/decorators/indexes.js +0 -59
- package/src/decorators/timestamps.d.ts +0 -54
- package/src/decorators/timestamps.js +0 -72
- package/src/decorators/transforms.d.ts +0 -99
- package/src/decorators/transforms.js +0 -166
- package/src/index.test.js +0 -37
- /package/{src → build/cjs}/@types/index.js +0 -0
- /package/{src/index.test.d.ts → build/cjs/test/index.d.ts} +0 -0
- /package/{src → build/cjs}/utils/relations.d.ts +0 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Dynamite, Table, PrimaryKey, Default, NotNull, Name, HasMany, BelongsTo, ManyToMany, } from "../index.js";
|
|
11
|
+
// -- 4 niveles: Org -> Dept -> Employee -> Task --
|
|
12
|
+
let Org = class Org extends Table {
|
|
13
|
+
};
|
|
14
|
+
__decorate([
|
|
15
|
+
PrimaryKey(),
|
|
16
|
+
__metadata("design:type", Object)
|
|
17
|
+
], Org.prototype, "id", void 0);
|
|
18
|
+
__decorate([
|
|
19
|
+
NotNull(),
|
|
20
|
+
__metadata("design:type", String)
|
|
21
|
+
], Org.prototype, "name", void 0);
|
|
22
|
+
__decorate([
|
|
23
|
+
HasMany(() => Dept, 'org_id', 'id'),
|
|
24
|
+
__metadata("design:type", Object)
|
|
25
|
+
], Org.prototype, "departments", void 0);
|
|
26
|
+
Org = __decorate([
|
|
27
|
+
Name('test_rel_orgs')
|
|
28
|
+
], Org);
|
|
29
|
+
let Dept = class Dept extends Table {
|
|
30
|
+
};
|
|
31
|
+
__decorate([
|
|
32
|
+
PrimaryKey(),
|
|
33
|
+
__metadata("design:type", Object)
|
|
34
|
+
], Dept.prototype, "id", void 0);
|
|
35
|
+
__decorate([
|
|
36
|
+
NotNull(),
|
|
37
|
+
__metadata("design:type", String)
|
|
38
|
+
], Dept.prototype, "name", void 0);
|
|
39
|
+
__decorate([
|
|
40
|
+
Default(''),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], Dept.prototype, "org_id", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
BelongsTo(() => Org, 'id', 'org_id'),
|
|
45
|
+
__metadata("design:type", Object)
|
|
46
|
+
], Dept.prototype, "org", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
HasMany(() => Employee, 'dept_id', 'id'),
|
|
49
|
+
__metadata("design:type", Object)
|
|
50
|
+
], Dept.prototype, "employees", void 0);
|
|
51
|
+
Dept = __decorate([
|
|
52
|
+
Name('test_rel_depts')
|
|
53
|
+
], Dept);
|
|
54
|
+
let Employee = class Employee extends Table {
|
|
55
|
+
};
|
|
56
|
+
__decorate([
|
|
57
|
+
PrimaryKey(),
|
|
58
|
+
__metadata("design:type", Object)
|
|
59
|
+
], Employee.prototype, "id", void 0);
|
|
60
|
+
__decorate([
|
|
61
|
+
NotNull(),
|
|
62
|
+
__metadata("design:type", String)
|
|
63
|
+
], Employee.prototype, "name", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
Default(''),
|
|
66
|
+
__metadata("design:type", String)
|
|
67
|
+
], Employee.prototype, "dept_id", void 0);
|
|
68
|
+
__decorate([
|
|
69
|
+
BelongsTo(() => Dept, 'id', 'dept_id'),
|
|
70
|
+
__metadata("design:type", Object)
|
|
71
|
+
], Employee.prototype, "department", void 0);
|
|
72
|
+
__decorate([
|
|
73
|
+
HasMany(() => EmpTask, 'employee_id', 'id'),
|
|
74
|
+
__metadata("design:type", Object)
|
|
75
|
+
], Employee.prototype, "tasks", void 0);
|
|
76
|
+
__decorate([
|
|
77
|
+
ManyToMany(() => Project, 'test_rel_emp_projects', 'employee_id', 'project_id'),
|
|
78
|
+
__metadata("design:type", Object)
|
|
79
|
+
], Employee.prototype, "projects", void 0);
|
|
80
|
+
Employee = __decorate([
|
|
81
|
+
Name('test_rel_employees')
|
|
82
|
+
], Employee);
|
|
83
|
+
let EmpTask = class EmpTask extends Table {
|
|
84
|
+
};
|
|
85
|
+
__decorate([
|
|
86
|
+
PrimaryKey(),
|
|
87
|
+
__metadata("design:type", Object)
|
|
88
|
+
], EmpTask.prototype, "id", void 0);
|
|
89
|
+
__decorate([
|
|
90
|
+
NotNull(),
|
|
91
|
+
__metadata("design:type", String)
|
|
92
|
+
], EmpTask.prototype, "title", void 0);
|
|
93
|
+
__decorate([
|
|
94
|
+
Default(''),
|
|
95
|
+
__metadata("design:type", String)
|
|
96
|
+
], EmpTask.prototype, "employee_id", void 0);
|
|
97
|
+
__decorate([
|
|
98
|
+
BelongsTo(() => Employee, 'id', 'employee_id'),
|
|
99
|
+
__metadata("design:type", Object)
|
|
100
|
+
], EmpTask.prototype, "employee", void 0);
|
|
101
|
+
EmpTask = __decorate([
|
|
102
|
+
Name('test_rel_tasks')
|
|
103
|
+
], EmpTask);
|
|
104
|
+
let Project = class Project extends Table {
|
|
105
|
+
};
|
|
106
|
+
__decorate([
|
|
107
|
+
PrimaryKey(),
|
|
108
|
+
__metadata("design:type", Object)
|
|
109
|
+
], Project.prototype, "id", void 0);
|
|
110
|
+
__decorate([
|
|
111
|
+
NotNull(),
|
|
112
|
+
__metadata("design:type", String)
|
|
113
|
+
], Project.prototype, "name", void 0);
|
|
114
|
+
__decorate([
|
|
115
|
+
ManyToMany(() => Employee, 'test_rel_emp_projects', 'project_id', 'employee_id'),
|
|
116
|
+
__metadata("design:type", Object)
|
|
117
|
+
], Project.prototype, "members", void 0);
|
|
118
|
+
Project = __decorate([
|
|
119
|
+
Name('test_rel_projects')
|
|
120
|
+
], Project);
|
|
121
|
+
let passed = 0;
|
|
122
|
+
let failed = 0;
|
|
123
|
+
function assert(label, condition, detail) {
|
|
124
|
+
if (condition) {
|
|
125
|
+
console.log(` OK ${label}`);
|
|
126
|
+
passed++;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.error(` FAIL ${label}${detail ? ` -- ${detail}` : ''}`);
|
|
130
|
+
failed++;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export default async function relations() {
|
|
134
|
+
console.log('\n=== RELATIONS ===\n');
|
|
135
|
+
const dynamite = new Dynamite({
|
|
136
|
+
tables: [Org, Dept, Employee, EmpTask, Project],
|
|
137
|
+
region: 'local',
|
|
138
|
+
endpoint: 'http://localhost:8000',
|
|
139
|
+
credentials: { accessKeyId: 'local', secretAccessKey: 'local' },
|
|
140
|
+
});
|
|
141
|
+
await dynamite.connect();
|
|
142
|
+
await dynamite.sync();
|
|
143
|
+
// -- Seed data --
|
|
144
|
+
const org = await Org.create({ name: 'Acme Corp' });
|
|
145
|
+
const eng = await Dept.create({ name: 'Engineering', org_id: org.id });
|
|
146
|
+
const sales = await Dept.create({ name: 'Sales', org_id: org.id });
|
|
147
|
+
const e1 = await Employee.create({ name: 'Alice', dept_id: eng.id });
|
|
148
|
+
const e2 = await Employee.create({ name: 'Bob', dept_id: eng.id });
|
|
149
|
+
const e3 = await Employee.create({ name: 'Charlie', dept_id: sales.id });
|
|
150
|
+
await EmpTask.create({ title: 'Build API', employee_id: e1.id });
|
|
151
|
+
await EmpTask.create({ title: 'Write tests', employee_id: e1.id });
|
|
152
|
+
await EmpTask.create({ title: 'Code review', employee_id: e2.id });
|
|
153
|
+
await EmpTask.create({ title: 'Close deal', employee_id: e3.id });
|
|
154
|
+
const p1 = await Project.create({ name: 'Project Alpha' });
|
|
155
|
+
const p2 = await Project.create({ name: 'Project Beta' });
|
|
156
|
+
// -- HasMany --
|
|
157
|
+
console.log('-- HasMany --');
|
|
158
|
+
const org_with_depts = await Org.where({ id: org.id }, { include: { departments: true } });
|
|
159
|
+
assert('Org -> departments', org_with_depts[0]?.departments?.length === 2);
|
|
160
|
+
const eng_with_emps = await Dept.where({ id: eng.id }, { include: { employees: true } });
|
|
161
|
+
assert('Dept -> employees', eng_with_emps[0]?.employees?.length === 2);
|
|
162
|
+
// -- BelongsTo --
|
|
163
|
+
console.log('\n-- BelongsTo --');
|
|
164
|
+
const dept_with_org = await Dept.where({ id: eng.id }, { include: { org: true } });
|
|
165
|
+
assert('Dept -> org', dept_with_org[0]?.org?.name === 'Acme Corp');
|
|
166
|
+
const emp_with_dept = await Employee.where({ id: e1.id }, { include: { department: true } });
|
|
167
|
+
assert('Employee -> department', emp_with_dept[0]?.department?.name === 'Engineering');
|
|
168
|
+
// -- HasMany con opciones (limit) --
|
|
169
|
+
console.log('\n-- HasMany con opciones --');
|
|
170
|
+
const e1_tasks_limited = await Employee.where({ id: e1.id }, {
|
|
171
|
+
include: { tasks: { limit: 1 } }
|
|
172
|
+
});
|
|
173
|
+
assert('HasMany con limit:1', e1_tasks_limited[0]?.tasks?.length === 1);
|
|
174
|
+
// -- Include recursivo 2 niveles: Org -> Dept -> Employee --
|
|
175
|
+
console.log('\n-- Include recursivo 2 niveles --');
|
|
176
|
+
const org_2lvl = await Org.where({ id: org.id }, {
|
|
177
|
+
include: {
|
|
178
|
+
departments: {
|
|
179
|
+
include: { employees: true }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
const all_emps = org_2lvl[0]?.departments?.flatMap((d) => d.employees || []);
|
|
184
|
+
assert('Org -> Dept -> Employee (2 niveles)', all_emps?.length === 3);
|
|
185
|
+
// -- Include recursivo 3 niveles: Org -> Dept -> Employee -> Task --
|
|
186
|
+
console.log('\n-- Include recursivo 3 niveles --');
|
|
187
|
+
const org_3lvl = await Org.where({ id: org.id }, {
|
|
188
|
+
include: {
|
|
189
|
+
departments: {
|
|
190
|
+
include: {
|
|
191
|
+
employees: {
|
|
192
|
+
include: { tasks: true }
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
const eng_dept = org_3lvl[0]?.departments?.find((d) => d.name === 'Engineering');
|
|
199
|
+
const alice = eng_dept?.employees?.find((e) => e.name === 'Alice');
|
|
200
|
+
assert('3 niveles: Alice tiene 2 tasks', alice?.tasks?.length === 2);
|
|
201
|
+
const bob = eng_dept?.employees?.find((e) => e.name === 'Bob');
|
|
202
|
+
assert('3 niveles: Bob tiene 1 task', bob?.tasks?.length === 1);
|
|
203
|
+
const sales_dept = org_3lvl[0]?.departments?.find((d) => d.name === 'Sales');
|
|
204
|
+
const charlie = sales_dept?.employees?.find((e) => e.name === 'Charlie');
|
|
205
|
+
assert('3 niveles: Charlie tiene 1 task', charlie?.tasks?.length === 1);
|
|
206
|
+
// -- ManyToMany: attach --
|
|
207
|
+
console.log('\n-- ManyToMany --');
|
|
208
|
+
await e1.attach(Project, p1.id);
|
|
209
|
+
await e1.attach(Project, p2.id);
|
|
210
|
+
await e2.attach(Project, p1.id);
|
|
211
|
+
const e1_projects = await Employee.where({ id: e1.id }, { include: { projects: true } });
|
|
212
|
+
assert('attach: Alice tiene 2 projects', e1_projects[0]?.projects?.length === 2);
|
|
213
|
+
const p1_members = await Project.where({ id: p1.id }, { include: { members: true } });
|
|
214
|
+
assert('attach: Project Alpha tiene 2 members', p1_members[0]?.members?.length === 2);
|
|
215
|
+
// -- ManyToMany: detach --
|
|
216
|
+
await e1.detach(Project, p2.id);
|
|
217
|
+
const e1_after_detach = await Employee.where({ id: e1.id }, { include: { projects: true } });
|
|
218
|
+
assert('detach: Alice tiene 1 project', e1_after_detach[0]?.projects?.length === 1);
|
|
219
|
+
// -- ManyToMany: sync --
|
|
220
|
+
await e1.sync(Project, [p2.id]);
|
|
221
|
+
const e1_after_sync = await Employee.where({ id: e1.id }, { include: { projects: true } });
|
|
222
|
+
assert('sync: Alice solo tiene Project Beta', e1_after_sync[0]?.projects?.length === 1);
|
|
223
|
+
assert('sync: es Project Beta', e1_after_sync[0]?.projects?.[0]?.name === 'Project Beta');
|
|
224
|
+
// -- Include recursivo 3 niveles + ManyToMany --
|
|
225
|
+
console.log('\n-- Recursivo + ManyToMany --');
|
|
226
|
+
const org_full = await Org.where({ id: org.id }, {
|
|
227
|
+
include: {
|
|
228
|
+
departments: {
|
|
229
|
+
include: {
|
|
230
|
+
employees: {
|
|
231
|
+
include: { tasks: true, projects: true }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
const eng_full = org_full[0]?.departments?.find((d) => d.name === 'Engineering');
|
|
238
|
+
const alice_full = eng_full?.employees?.find((e) => e.name === 'Alice');
|
|
239
|
+
assert('full tree: Alice tasks + projects', alice_full?.tasks?.length === 2 && alice_full?.projects?.length === 1);
|
|
240
|
+
console.log(`\n Relations: ${passed} passed, ${failed} failed`);
|
|
241
|
+
return failed;
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=relations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relations.js","sourceRoot":"","sources":["../../../src/test/relations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function transactions(): Promise<number>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Dynamite, Table, PrimaryKey, Default, NotNull, CreatedAt, Name, } from "../index.js";
|
|
11
|
+
let Account = class Account extends Table {
|
|
12
|
+
};
|
|
13
|
+
__decorate([
|
|
14
|
+
PrimaryKey(),
|
|
15
|
+
__metadata("design:type", Object)
|
|
16
|
+
], Account.prototype, "id", void 0);
|
|
17
|
+
__decorate([
|
|
18
|
+
NotNull(),
|
|
19
|
+
__metadata("design:type", String)
|
|
20
|
+
], Account.prototype, "name", void 0);
|
|
21
|
+
__decorate([
|
|
22
|
+
Default(() => 0),
|
|
23
|
+
__metadata("design:type", Object)
|
|
24
|
+
], Account.prototype, "balance", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
CreatedAt(),
|
|
27
|
+
__metadata("design:type", Object)
|
|
28
|
+
], Account.prototype, "created_at", void 0);
|
|
29
|
+
Account = __decorate([
|
|
30
|
+
Name('test_tx_accounts')
|
|
31
|
+
], Account);
|
|
32
|
+
let TxLog = class TxLog extends Table {
|
|
33
|
+
};
|
|
34
|
+
__decorate([
|
|
35
|
+
PrimaryKey(),
|
|
36
|
+
__metadata("design:type", Object)
|
|
37
|
+
], TxLog.prototype, "id", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
Default(''),
|
|
40
|
+
__metadata("design:type", String)
|
|
41
|
+
], TxLog.prototype, "account_id", void 0);
|
|
42
|
+
__decorate([
|
|
43
|
+
Default(''),
|
|
44
|
+
__metadata("design:type", String)
|
|
45
|
+
], TxLog.prototype, "action", void 0);
|
|
46
|
+
__decorate([
|
|
47
|
+
Default(() => 0),
|
|
48
|
+
__metadata("design:type", Object)
|
|
49
|
+
], TxLog.prototype, "amount", void 0);
|
|
50
|
+
TxLog = __decorate([
|
|
51
|
+
Name('test_tx_logs')
|
|
52
|
+
], TxLog);
|
|
53
|
+
let passed = 0;
|
|
54
|
+
let failed = 0;
|
|
55
|
+
function assert(label, condition, detail) {
|
|
56
|
+
if (condition) {
|
|
57
|
+
console.log(` OK ${label}`);
|
|
58
|
+
passed++;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.error(` FAIL ${label}${detail ? ` -- ${detail}` : ''}`);
|
|
62
|
+
failed++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export default async function transactions() {
|
|
66
|
+
console.log('\n=== TRANSACTIONS ===\n');
|
|
67
|
+
const dynamite = new Dynamite({
|
|
68
|
+
tables: [Account, TxLog],
|
|
69
|
+
region: 'local',
|
|
70
|
+
endpoint: 'http://localhost:8000',
|
|
71
|
+
credentials: { accessKeyId: 'local', secretAccessKey: 'local' },
|
|
72
|
+
});
|
|
73
|
+
await dynamite.connect();
|
|
74
|
+
await dynamite.sync();
|
|
75
|
+
// -- Multi-create en tx --
|
|
76
|
+
console.log('-- Multi-create --');
|
|
77
|
+
let a1, a2;
|
|
78
|
+
await dynamite.tx(async (tx) => {
|
|
79
|
+
a1 = await Account.create({ name: 'Alice', balance: 1000 }, { tx });
|
|
80
|
+
a2 = await Account.create({ name: 'Bob', balance: 500 }, { tx });
|
|
81
|
+
});
|
|
82
|
+
assert('tx multi-create: ambos persistidos', a1.__isPersisted && a2.__isPersisted);
|
|
83
|
+
const alice = await Account.first({ id: a1.id });
|
|
84
|
+
const bob = await Account.first({ id: a2.id });
|
|
85
|
+
assert('tx multi-create: Alice en DB', alice?.name === 'Alice' && alice?.balance === 1000);
|
|
86
|
+
assert('tx multi-create: Bob en DB', bob?.name === 'Bob' && bob?.balance === 500);
|
|
87
|
+
// -- Create + increment en tx --
|
|
88
|
+
console.log('\n-- Create + increment --');
|
|
89
|
+
let log1;
|
|
90
|
+
await dynamite.tx(async (tx) => {
|
|
91
|
+
log1 = await TxLog.create({ account_id: a1.id, action: 'deposit', amount: 200 }, { tx });
|
|
92
|
+
await Account.increment('balance', 200, { id: a1.id }, { tx });
|
|
93
|
+
});
|
|
94
|
+
const alice_after = await Account.first({ id: a1.id });
|
|
95
|
+
assert('tx increment: balance +200', alice_after?.balance === 1200);
|
|
96
|
+
assert('tx increment: log creado', log1.__isPersisted === true);
|
|
97
|
+
const log_check = await TxLog.first({ id: log1.id });
|
|
98
|
+
assert('tx increment: log en DB', log_check?.action === 'deposit');
|
|
99
|
+
// -- Transferencia atomica (decrement + increment + log) --
|
|
100
|
+
console.log('\n-- Transferencia atomica --');
|
|
101
|
+
await dynamite.tx(async (tx) => {
|
|
102
|
+
await Account.decrement('balance', 300, { id: a1.id }, { tx });
|
|
103
|
+
await Account.increment('balance', 300, { id: a2.id }, { tx });
|
|
104
|
+
await TxLog.create({ account_id: a1.id, action: 'transfer_out', amount: 300 }, { tx });
|
|
105
|
+
await TxLog.create({ account_id: a2.id, action: 'transfer_in', amount: 300 }, { tx });
|
|
106
|
+
});
|
|
107
|
+
const alice_transfer = await Account.first({ id: a1.id });
|
|
108
|
+
const bob_transfer = await Account.first({ id: a2.id });
|
|
109
|
+
assert('transferencia: Alice 1200-300=900', alice_transfer?.balance === 900);
|
|
110
|
+
assert('transferencia: Bob 500+300=800', bob_transfer?.balance === 800);
|
|
111
|
+
// -- Tx fallida: nada se persiste --
|
|
112
|
+
console.log('\n-- Tx fallida --');
|
|
113
|
+
const alice_before_fail = alice_transfer.balance;
|
|
114
|
+
let failed_account;
|
|
115
|
+
try {
|
|
116
|
+
await dynamite.tx(async (tx) => {
|
|
117
|
+
failed_account = await Account.create({ name: 'Ghost' }, { tx });
|
|
118
|
+
await Account.increment('balance', 99999, { id: a1.id }, { tx });
|
|
119
|
+
throw new Error('Simulated failure');
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
catch { }
|
|
123
|
+
assert('tx fallida: instancia no persistida', failed_account.__isPersisted === false);
|
|
124
|
+
const alice_after_fail = await Account.first({ id: a1.id });
|
|
125
|
+
assert('tx fallida: balance intacto', alice_after_fail?.balance === alice_before_fail);
|
|
126
|
+
const ghost = await Account.where({ name: 'Ghost' });
|
|
127
|
+
assert('tx fallida: Ghost no existe', ghost.length === 0);
|
|
128
|
+
// -- Tx con multiples operaciones (>25, auto-chunk) --
|
|
129
|
+
console.log('\n-- Auto-chunk (30 creates) --');
|
|
130
|
+
const ids = [];
|
|
131
|
+
await dynamite.tx(async (tx) => {
|
|
132
|
+
for (let i = 0; i < 30; i++) {
|
|
133
|
+
const acc = await Account.create({ name: `Bulk_${i}`, balance: i }, { tx });
|
|
134
|
+
ids.push(acc.id);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
const bulk_check = await Account.where({ name: { $include: 'Bulk_' } });
|
|
138
|
+
assert('auto-chunk: 30 registros creados', bulk_check.length === 30);
|
|
139
|
+
console.log(`\n Transactions: ${passed} passed, ${failed} failed`);
|
|
140
|
+
return failed;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=transactions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.js","sourceRoot":"","sources":["../../../src/test/transactions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file relations.ts
|
|
3
|
+
* @description Sistema de carga de relaciones con batch loading
|
|
4
|
+
* @autor Miguel Alejandro
|
|
5
|
+
* @fecha 2025-01-28
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @description Opciones para include de relaciones
|
|
9
|
+
*/
|
|
10
|
+
interface IncludeOptions {
|
|
11
|
+
where?: Record<string, any>;
|
|
12
|
+
attributes?: string[];
|
|
13
|
+
limit?: number;
|
|
14
|
+
offset?: number;
|
|
15
|
+
skip?: number;
|
|
16
|
+
order?: 'asc' | 'desc';
|
|
17
|
+
include?: Record<string, IncludeOptions | boolean>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @description Procesa includes recursivamente para cargar relaciones con caché
|
|
21
|
+
* @param items Array de instancias a poblar
|
|
22
|
+
* @param include Objeto con relaciones a incluir
|
|
23
|
+
* @param TableClass Clase de la tabla actual
|
|
24
|
+
* @param depth Profundidad actual (máximo 5 para prevenir deep nesting)
|
|
25
|
+
* @param queryCache Caché de queries para evitar duplicados (opcional)
|
|
26
|
+
* @returns Items con relaciones pobladas
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* // Uso interno en Table.where()
|
|
30
|
+
* await processIncludes(users, {
|
|
31
|
+
* posts: {
|
|
32
|
+
* where: { published: true },
|
|
33
|
+
* limit: 5,
|
|
34
|
+
* include: {
|
|
35
|
+
* comments: true
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* }, User);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare const processIncludes: (items: any[], include: Record<string, IncludeOptions | boolean>, TableClass: any, depth?: number, queryCache?: Map<string, Map<string, any>>) => Promise<any[]>;
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file relations.ts
|
|
3
|
+
* @description Sistema de carga de relaciones con batch loading
|
|
4
|
+
* @autor Miguel Alejandro
|
|
5
|
+
* @fecha 2025-01-28
|
|
6
|
+
*/
|
|
7
|
+
import { ScanCommand } from "@aws-sdk/client-dynamodb";
|
|
8
|
+
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
|
|
9
|
+
import { requireClient } from "../core/client.js";
|
|
10
|
+
import { SCHEMA } from "../core/decorator.js";
|
|
11
|
+
/**
|
|
12
|
+
* @description Batch load para HasMany/HasOne
|
|
13
|
+
* Obtiene items relacionados donde foreignKey IN parent_ids
|
|
14
|
+
*/
|
|
15
|
+
const batchLoadHasMany = async (items, relation, options = {}) => {
|
|
16
|
+
const parent_ids = items.map(i => i[relation.localKey]).filter(Boolean);
|
|
17
|
+
if (!parent_ids.length)
|
|
18
|
+
return new Map();
|
|
19
|
+
// Obtener clase del modelo relacionado
|
|
20
|
+
const RelatedModel = relation.model();
|
|
21
|
+
// Construir filtros combinados
|
|
22
|
+
const filters = {
|
|
23
|
+
[relation.foreignKey]: { $in: parent_ids },
|
|
24
|
+
...options.where
|
|
25
|
+
};
|
|
26
|
+
// Query con todas las opciones aplicadas
|
|
27
|
+
const related = await RelatedModel.where(filters, {
|
|
28
|
+
attributes: options.attributes,
|
|
29
|
+
order: options.order?.toUpperCase(),
|
|
30
|
+
limit: undefined, // Se aplica después de agrupar
|
|
31
|
+
offset: undefined,
|
|
32
|
+
});
|
|
33
|
+
// Agrupar por foreignKey
|
|
34
|
+
const grouped = new Map();
|
|
35
|
+
for (const item of related) {
|
|
36
|
+
const key = String(item[relation.foreignKey]);
|
|
37
|
+
if (!grouped.has(key))
|
|
38
|
+
grouped.set(key, []);
|
|
39
|
+
grouped.get(key).push(item);
|
|
40
|
+
}
|
|
41
|
+
// Aplicar limit por grupo
|
|
42
|
+
if (options.limit) {
|
|
43
|
+
const offset = options.skip ?? options.offset ?? 0;
|
|
44
|
+
for (const [key, groupItems] of grouped) {
|
|
45
|
+
grouped.set(key, groupItems.slice(offset, offset + options.limit));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return grouped;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* @description Batch load para BelongsTo
|
|
52
|
+
* Obtiene items donde id IN local_keys
|
|
53
|
+
*/
|
|
54
|
+
const batchLoadBelongsTo = async (items, relation, options = {}) => {
|
|
55
|
+
const local_keys = items.map(i => i[relation.localKey]).filter(Boolean);
|
|
56
|
+
if (!local_keys.length)
|
|
57
|
+
return new Map();
|
|
58
|
+
const RelatedModel = relation.model();
|
|
59
|
+
// Query con opciones aplicadas
|
|
60
|
+
const related = await RelatedModel.where({ [relation.foreignKey]: { $in: local_keys } }, { attributes: options.attributes });
|
|
61
|
+
const result = new Map();
|
|
62
|
+
for (const item of related) {
|
|
63
|
+
result.set(String(item[relation.foreignKey]), item);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* @description Batch load para ManyToMany
|
|
69
|
+
* Obtiene items relacionados usando tabla pivot
|
|
70
|
+
*/
|
|
71
|
+
const batchLoadManyToMany = async (items, relation, options = {}) => {
|
|
72
|
+
const parent_ids = items.map(i => i[relation.localKey]).filter(Boolean);
|
|
73
|
+
if (!parent_ids.length)
|
|
74
|
+
return new Map();
|
|
75
|
+
const client = requireClient();
|
|
76
|
+
// [1] Query pivot table usando OR chain (DynamoDB no soporta IN nativo)
|
|
77
|
+
const or_conditions = parent_ids.map((_, i) => `#fk = :id${i}`).join(' OR ');
|
|
78
|
+
const pivot_result = await client.send(new ScanCommand({
|
|
79
|
+
TableName: relation.pivotTable,
|
|
80
|
+
FilterExpression: parent_ids.length > 0 ? `(${or_conditions})` : undefined,
|
|
81
|
+
ExpressionAttributeNames: { '#fk': relation.foreignKey },
|
|
82
|
+
ExpressionAttributeValues: marshall(parent_ids.reduce((acc, id, i) => ({ ...acc, [`:id${i}`]: id }), {}))
|
|
83
|
+
}));
|
|
84
|
+
const pivot_rows = (pivot_result.Items ?? []).map(item => unmarshall(item));
|
|
85
|
+
if (pivot_rows.length === 0)
|
|
86
|
+
return new Map();
|
|
87
|
+
// [2] Extract unique related IDs
|
|
88
|
+
const related_ids = [...new Set(pivot_rows.map(row => row[relation.relatedKey]))];
|
|
89
|
+
// [3] Batch load related models con opciones aplicadas
|
|
90
|
+
const RelatedModel = relation.model();
|
|
91
|
+
// Construir filtros combinados
|
|
92
|
+
const filters = {
|
|
93
|
+
[relation.relatedPK]: { $in: related_ids },
|
|
94
|
+
...options.where
|
|
95
|
+
};
|
|
96
|
+
const related_items = await RelatedModel.where(filters, {
|
|
97
|
+
attributes: options.attributes,
|
|
98
|
+
order: options.order?.toUpperCase(),
|
|
99
|
+
});
|
|
100
|
+
// [5] Map related items by ID
|
|
101
|
+
const related_map = new Map(related_items.map((item) => [String(item[relation.relatedPK]), item]));
|
|
102
|
+
// [6] Group by parent ID using pivot as bridge
|
|
103
|
+
const grouped = new Map();
|
|
104
|
+
for (const pivot of pivot_rows) {
|
|
105
|
+
const parent_id = String(pivot[relation.foreignKey]);
|
|
106
|
+
const related_id = String(pivot[relation.relatedKey]);
|
|
107
|
+
const related_item = related_map.get(related_id);
|
|
108
|
+
if (related_item) {
|
|
109
|
+
if (!grouped.has(parent_id))
|
|
110
|
+
grouped.set(parent_id, []);
|
|
111
|
+
grouped.get(parent_id).push(related_item);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// [7] Apply limit per group
|
|
115
|
+
if (options.limit) {
|
|
116
|
+
const offset = options.skip ?? options.offset ?? 0;
|
|
117
|
+
for (const [key, items_arr] of grouped) {
|
|
118
|
+
grouped.set(key, items_arr.slice(offset, offset + options.limit));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return grouped;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* @description Procesa includes recursivamente para cargar relaciones con caché
|
|
125
|
+
* @param items Array de instancias a poblar
|
|
126
|
+
* @param include Objeto con relaciones a incluir
|
|
127
|
+
* @param TableClass Clase de la tabla actual
|
|
128
|
+
* @param depth Profundidad actual (máximo 5 para prevenir deep nesting)
|
|
129
|
+
* @param queryCache Caché de queries para evitar duplicados (opcional)
|
|
130
|
+
* @returns Items con relaciones pobladas
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* // Uso interno en Table.where()
|
|
134
|
+
* await processIncludes(users, {
|
|
135
|
+
* posts: {
|
|
136
|
+
* where: { published: true },
|
|
137
|
+
* limit: 5,
|
|
138
|
+
* include: {
|
|
139
|
+
* comments: true
|
|
140
|
+
* }
|
|
141
|
+
* }
|
|
142
|
+
* }, User);
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export const processIncludes = async (items, include, TableClass, depth = 0, queryCache = new Map()) => {
|
|
146
|
+
// Límite reducido de 10 a 5 para mejor performance
|
|
147
|
+
if (!include || depth > 5 || !items.length)
|
|
148
|
+
return items;
|
|
149
|
+
const schema = TableClass[SCHEMA];
|
|
150
|
+
if (!schema)
|
|
151
|
+
return items;
|
|
152
|
+
const promises = Object.entries(include)
|
|
153
|
+
.filter(([key]) => Object.prototype.hasOwnProperty.call(schema.columns, key))
|
|
154
|
+
.map(async ([relation_key, options]) => {
|
|
155
|
+
const column = schema.columns[relation_key];
|
|
156
|
+
if (!column?.store?.relation)
|
|
157
|
+
return;
|
|
158
|
+
const relation = column.store.relation;
|
|
159
|
+
const opts = typeof options === 'boolean' ? {} : options;
|
|
160
|
+
// Generar clave de caché basada en tipo de relación y IDs de padres
|
|
161
|
+
const parent_ids = items.map(i => i[relation.localKey]).filter(Boolean);
|
|
162
|
+
const cache_key = `${relation.type}:${relation.model().name}:${JSON.stringify(parent_ids.sort())}:${JSON.stringify(opts.where || {})}`;
|
|
163
|
+
// Batch load según tipo con caché
|
|
164
|
+
let data;
|
|
165
|
+
// Verificar caché primero
|
|
166
|
+
if (queryCache.has(cache_key)) {
|
|
167
|
+
data = queryCache.get(cache_key);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
if (relation.type === 'HasMany') {
|
|
171
|
+
data = await batchLoadHasMany(items, relation, opts);
|
|
172
|
+
}
|
|
173
|
+
else if (relation.type === 'HasOne') {
|
|
174
|
+
const hasMany = await batchLoadHasMany(items, relation, { ...opts, limit: 1 });
|
|
175
|
+
data = new Map();
|
|
176
|
+
for (const [k, v] of hasMany) {
|
|
177
|
+
data.set(k, v[0] ?? null);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else if (relation.type === 'ManyToMany') {
|
|
181
|
+
data = await batchLoadManyToMany(items, relation, opts);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// BelongsTo
|
|
185
|
+
data = await batchLoadBelongsTo(items, relation, opts);
|
|
186
|
+
}
|
|
187
|
+
// Guardar en caché
|
|
188
|
+
queryCache.set(cache_key, data);
|
|
189
|
+
}
|
|
190
|
+
for (const item of items) {
|
|
191
|
+
const key = String(item[relation.localKey]);
|
|
192
|
+
item[relation_key] = (relation.type === 'HasMany' || relation.type === 'ManyToMany')
|
|
193
|
+
? data.get(key) ?? []
|
|
194
|
+
: data.get(key) ?? null;
|
|
195
|
+
}
|
|
196
|
+
// Recursión para includes anidados con caché propagado
|
|
197
|
+
if (opts.include && data.size) {
|
|
198
|
+
const all_related = Array.from(data.values()).flat().filter(Boolean);
|
|
199
|
+
if (all_related.length) {
|
|
200
|
+
await processIncludes(all_related, opts.include, relation.model(), depth + 1, queryCache);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
await Promise.all(promises);
|
|
205
|
+
return items;
|
|
206
|
+
};
|
|
207
|
+
//# sourceMappingURL=relations.js.map
|