@happyvertical/smrt-events 0.37.2 → 0.37.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/dist/index.js +1299 -1407
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +2 -2
- package/dist/playground.js +39 -44
- package/dist/playground.js.map +1 -1
- package/dist/smrt-knowledge.json +11 -11
- package/dist/types.js +0 -2
- package/dist/ui.js +31 -27
- package/dist/ui.js.map +1 -1
- package/dist/utils.js +74 -105
- package/dist/utils.js.map +1 -1
- package/package.json +22 -22
- package/dist/types.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,1447 +1,1339 @@
|
|
|
1
|
-
import { ObjectRegistry, foreignKey, crossPackageRef, field, smrt, SmrtObject, SmrtJunction, SmrtHierarchical, SmrtCollection } from "@happyvertical/smrt-core";
|
|
2
|
-
import { getOwnedAssetsFromCollection, addOwnedAssetFromCollection, removeOwnedAssetFromCollection, resolveOwnedAssetsById, assertValidOwnedAssetRelationship, assertValidOwnedAssetSortOrder } from "@happyvertical/smrt-assets";
|
|
3
|
-
import { tenantId, TenantScoped, queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
|
|
4
1
|
import { EVENTS_MODULE_META, EVENTS_UI_SLOTS } from "./ui.js";
|
|
5
2
|
import { calculateDuration, calculateNextOccurrence, checkSchedulingConflict, formatDuration, formatEventDateRange, generateEventSlug, getEventStatusFromDates, isEventNow, parseRecurrencePattern, sortEventsByDate, validateEventStatus } from "./utils.js";
|
|
6
|
-
ObjectRegistry
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { ObjectRegistry, SmrtCollection, SmrtHierarchical, SmrtJunction, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
4
|
+
import { addOwnedAssetFromCollection, assertValidOwnedAssetRelationship, assertValidOwnedAssetSortOrder, getOwnedAssetsFromCollection, removeOwnedAssetFromCollection, resolveOwnedAssetsById } from "@happyvertical/smrt-assets";
|
|
5
|
+
import { TenantScoped, queryGlobal, queryWithGlobals, tenantId } from "@happyvertical/smrt-tenancy";
|
|
6
|
+
//#region \0rolldown/runtime.js
|
|
7
|
+
var __defProp$7 = Object.defineProperty;
|
|
8
|
+
var __exportAll = (all, no_symbols) => {
|
|
9
|
+
let target = {};
|
|
10
|
+
for (var name in all) __defProp$7(target, name, {
|
|
11
|
+
get: all[name],
|
|
12
|
+
enumerable: true
|
|
13
|
+
});
|
|
14
|
+
if (!no_symbols) __defProp$7(target, Symbol.toStringTag, { value: "Module" });
|
|
15
|
+
return target;
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/__smrt-register__.ts
|
|
19
|
+
ObjectRegistry.registerPackageManifest(new URL("./manifest.json", "" + import.meta.url));
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/models/EventAsset.ts
|
|
9
22
|
var __defProp$6 = Object.defineProperty;
|
|
10
23
|
var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
|
|
11
24
|
var __decorateClass$6 = (decorators, target, key, kind) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (kind && result) __defProp$6(target, key, result);
|
|
17
|
-
return result;
|
|
25
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
|
|
26
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
27
|
+
if (kind && result) __defProp$6(target, key, result);
|
|
28
|
+
return result;
|
|
18
29
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
var EventAsset = class extends SmrtObject {
|
|
31
|
+
tenantId = null;
|
|
32
|
+
eventId = "";
|
|
33
|
+
assetId = "";
|
|
34
|
+
relationship = "attachment";
|
|
35
|
+
sortOrder = 0;
|
|
36
|
+
constructor(options = {}) {
|
|
37
|
+
super(options);
|
|
38
|
+
if (options.eventId) this.eventId = options.eventId;
|
|
39
|
+
if (options.assetId) this.assetId = options.assetId;
|
|
40
|
+
if (options.relationship) this.relationship = options.relationship;
|
|
41
|
+
if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
|
|
42
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
43
|
+
}
|
|
33
44
|
};
|
|
34
|
-
__decorateClass$6([
|
|
35
|
-
|
|
36
|
-
], EventAsset.prototype, "
|
|
37
|
-
__decorateClass$6([
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
],
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
EventAsset
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
conflictColumns: ["event_id", "asset_id", "relationship"],
|
|
54
|
-
api: false,
|
|
55
|
-
mcp: false,
|
|
56
|
-
cli: false
|
|
57
|
-
})
|
|
58
|
-
], EventAsset);
|
|
45
|
+
__decorateClass$6([tenantId({ nullable: true })], EventAsset.prototype, "tenantId", 2);
|
|
46
|
+
__decorateClass$6([foreignKey("Event", { required: true })], EventAsset.prototype, "eventId", 2);
|
|
47
|
+
__decorateClass$6([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], EventAsset.prototype, "assetId", 2);
|
|
48
|
+
__decorateClass$6([field({ required: true })], EventAsset.prototype, "relationship", 2);
|
|
49
|
+
__decorateClass$6([field()], EventAsset.prototype, "sortOrder", 2);
|
|
50
|
+
EventAsset = __decorateClass$6([TenantScoped({ mode: "optional" }), smrt({
|
|
51
|
+
tableName: "event_assets",
|
|
52
|
+
conflictColumns: [
|
|
53
|
+
"event_id",
|
|
54
|
+
"asset_id",
|
|
55
|
+
"relationship"
|
|
56
|
+
],
|
|
57
|
+
api: false,
|
|
58
|
+
mcp: false,
|
|
59
|
+
cli: false
|
|
60
|
+
})], EventAsset);
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/collections/EventAssetCollection.ts
|
|
63
|
+
var EventAssetCollection_exports = /* @__PURE__ */ __exportAll({ EventAssetCollection: () => EventAssetCollection });
|
|
59
64
|
var __defProp$5 = Object.defineProperty;
|
|
60
65
|
var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
|
|
61
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {
|
|
66
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$5(obj, key, {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
configurable: true,
|
|
69
|
+
writable: true,
|
|
70
|
+
value
|
|
71
|
+
}) : obj[key] = value;
|
|
62
72
|
var __decorateClass$5 = (decorators, target, key, kind) => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return result;
|
|
73
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
|
|
74
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
75
|
+
if (kind && result) __defProp$5(target, key, result);
|
|
76
|
+
return result;
|
|
68
77
|
};
|
|
69
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, key + "", value);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
await this.getEventCollection(),
|
|
91
|
-
"Event",
|
|
92
|
-
eventId,
|
|
93
|
-
asset,
|
|
94
|
-
relationship,
|
|
95
|
-
sortOrder
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
async removeAsset(eventId, assetId, relationship) {
|
|
99
|
-
await removeOwnedAssetFromCollection(
|
|
100
|
-
await this.getEventCollection(),
|
|
101
|
-
"Event",
|
|
102
|
-
eventId,
|
|
103
|
-
assetId,
|
|
104
|
-
relationship
|
|
105
|
-
);
|
|
106
|
-
}
|
|
78
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
79
|
+
var EventAssetCollection = class extends SmrtJunction {
|
|
80
|
+
leftField = "eventId";
|
|
81
|
+
rightField = "assetId";
|
|
82
|
+
eventCollectionPromise = null;
|
|
83
|
+
async getEventCollection() {
|
|
84
|
+
if (!this.eventCollectionPromise) {
|
|
85
|
+
const { EventCollection } = await Promise.resolve().then(() => EventCollection_exports);
|
|
86
|
+
this.eventCollectionPromise = EventCollection.create({ db: this.db });
|
|
87
|
+
}
|
|
88
|
+
return this.eventCollectionPromise;
|
|
89
|
+
}
|
|
90
|
+
async getAssets(eventId, relationship) {
|
|
91
|
+
return getOwnedAssetsFromCollection(await this.getEventCollection(), eventId, relationship);
|
|
92
|
+
}
|
|
93
|
+
async addAsset(eventId, asset, relationship = "attachment", sortOrder = 0) {
|
|
94
|
+
await addOwnedAssetFromCollection(await this.getEventCollection(), "Event", eventId, asset, relationship, sortOrder);
|
|
95
|
+
}
|
|
96
|
+
async removeAsset(eventId, assetId, relationship) {
|
|
97
|
+
await removeOwnedAssetFromCollection(await this.getEventCollection(), "Event", eventId, assetId, relationship);
|
|
98
|
+
}
|
|
107
99
|
};
|
|
108
100
|
__publicField$1(EventAssetCollection, "_itemClass", EventAsset);
|
|
109
|
-
EventAssetCollection = __decorateClass$5([
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const EventAssetCollection$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
117
|
-
__proto__: null,
|
|
118
|
-
get EventAssetCollection() {
|
|
119
|
-
return EventAssetCollection;
|
|
120
|
-
}
|
|
121
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
101
|
+
EventAssetCollection = __decorateClass$5([smrt({
|
|
102
|
+
api: false,
|
|
103
|
+
mcp: false,
|
|
104
|
+
cli: false
|
|
105
|
+
})], EventAssetCollection);
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/models/Event.ts
|
|
122
108
|
var __defProp$4 = Object.defineProperty;
|
|
123
109
|
var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
|
|
124
110
|
var __decorateClass$4 = (decorators, target, key, kind) => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
111
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
|
|
112
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
113
|
+
if (kind && result) __defProp$4(target, key, result);
|
|
114
|
+
return result;
|
|
115
|
+
};
|
|
116
|
+
var Event = class extends SmrtHierarchical {
|
|
117
|
+
tenantId = null;
|
|
118
|
+
name = "";
|
|
119
|
+
seriesId = "";
|
|
120
|
+
typeId = "";
|
|
121
|
+
placeId = "";
|
|
122
|
+
description = "";
|
|
123
|
+
startDate = null;
|
|
124
|
+
endDate = null;
|
|
125
|
+
status = "scheduled";
|
|
126
|
+
round = null;
|
|
127
|
+
metadata = "";
|
|
128
|
+
externalId = "";
|
|
129
|
+
source = "";
|
|
130
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
131
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
132
|
+
constructor(options = {}) {
|
|
133
|
+
super(options);
|
|
134
|
+
if (options.seriesId !== void 0) this.seriesId = options.seriesId;
|
|
135
|
+
if (options.parentId !== void 0) this.parentId = options.parentId ?? null;
|
|
136
|
+
if (options.typeId) this.typeId = options.typeId;
|
|
137
|
+
if (options.placeId !== void 0) this.placeId = options.placeId;
|
|
138
|
+
if (options.description !== void 0) this.description = options.description;
|
|
139
|
+
if (options.startDate !== void 0) this.startDate = options.startDate || null;
|
|
140
|
+
if (options.endDate !== void 0) this.endDate = options.endDate || null;
|
|
141
|
+
if (options.status !== void 0) this.status = options.status;
|
|
142
|
+
if (options.round !== void 0) this.round = options.round;
|
|
143
|
+
if (options.externalId !== void 0) this.externalId = options.externalId;
|
|
144
|
+
if (options.source !== void 0) this.source = options.source;
|
|
145
|
+
if (options.metadata !== void 0) if (typeof options.metadata === "string") this.metadata = options.metadata;
|
|
146
|
+
else this.metadata = JSON.stringify(options.metadata);
|
|
147
|
+
if (options.createdAt) this.createdAt = options.createdAt;
|
|
148
|
+
if (options.updatedAt) this.updatedAt = options.updatedAt;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get metadata as parsed object
|
|
152
|
+
*
|
|
153
|
+
* @returns Parsed metadata object or empty object
|
|
154
|
+
*/
|
|
155
|
+
getMetadata() {
|
|
156
|
+
if (!this.metadata) return {};
|
|
157
|
+
try {
|
|
158
|
+
return JSON.parse(this.metadata);
|
|
159
|
+
} catch {
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Set metadata from object
|
|
165
|
+
*
|
|
166
|
+
* @param data - Metadata object to store
|
|
167
|
+
*/
|
|
168
|
+
setMetadata(data) {
|
|
169
|
+
this.metadata = JSON.stringify(data);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Update metadata by merging with existing values
|
|
173
|
+
*
|
|
174
|
+
* @param updates - Partial metadata to merge
|
|
175
|
+
*/
|
|
176
|
+
updateMetadata(updates) {
|
|
177
|
+
const current = this.getMetadata();
|
|
178
|
+
this.setMetadata({
|
|
179
|
+
...current,
|
|
180
|
+
...updates
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Update event status
|
|
185
|
+
*
|
|
186
|
+
* @param newStatus - New status to set
|
|
187
|
+
*/
|
|
188
|
+
async updateStatus(newStatus) {
|
|
189
|
+
this.status = newStatus;
|
|
190
|
+
this.updatedAt = /* @__PURE__ */ new Date();
|
|
191
|
+
await this.save();
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get the series for this event
|
|
195
|
+
*
|
|
196
|
+
* @returns EventSeries instance or null
|
|
197
|
+
*/
|
|
198
|
+
async getSeries() {
|
|
199
|
+
if (!this.seriesId) return null;
|
|
200
|
+
const { EventSeriesCollection } = await Promise.resolve().then(() => EventSeriesCollection_exports);
|
|
201
|
+
return await (await EventSeriesCollection.create(this.options)).get({ id: this.seriesId });
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get the event type
|
|
205
|
+
*
|
|
206
|
+
* @returns EventType instance or null
|
|
207
|
+
*/
|
|
208
|
+
async getType() {
|
|
209
|
+
if (!this.typeId) return null;
|
|
210
|
+
const { EventTypeCollection } = await Promise.resolve().then(() => EventTypeCollection_exports);
|
|
211
|
+
return await (await EventTypeCollection.create(this.options)).get({ id: this.typeId });
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get the place for this event
|
|
215
|
+
*
|
|
216
|
+
* @returns Place instance or null
|
|
217
|
+
*/
|
|
218
|
+
async getPlace() {
|
|
219
|
+
if (!this.placeId) return null;
|
|
220
|
+
try {
|
|
221
|
+
const { PlaceCollection } = await import("@happyvertical/smrt-places");
|
|
222
|
+
return await (await PlaceCollection.create(this.options)).get({ id: this.placeId });
|
|
223
|
+
} catch {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get the root event (top-level ancestor) of this event's hierarchy.
|
|
229
|
+
*
|
|
230
|
+
* @returns Root event instance — `this` when already root
|
|
231
|
+
*/
|
|
232
|
+
async getRootEvent() {
|
|
233
|
+
const ancestors = await this.getAncestors();
|
|
234
|
+
return ancestors.length > 0 ? ancestors[0] : this;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Get all participants for this event
|
|
238
|
+
*
|
|
239
|
+
* @returns Array of EventParticipant instances
|
|
240
|
+
*/
|
|
241
|
+
async getParticipants() {
|
|
242
|
+
const { EventParticipantCollection } = await Promise.resolve().then(() => EventParticipantCollection_exports);
|
|
243
|
+
return await (await EventParticipantCollection.create(this.options)).list({ where: { eventId: this.id } });
|
|
244
|
+
}
|
|
245
|
+
async getEventAssetCollection() {
|
|
246
|
+
const { EventAssetCollection } = await Promise.resolve().then(() => EventAssetCollection_exports);
|
|
247
|
+
return EventAssetCollection.create({ db: this.db });
|
|
248
|
+
}
|
|
249
|
+
async getAssets(relationship) {
|
|
250
|
+
if (!this.id) return [];
|
|
251
|
+
const linkedAssets = await (await this.getEventAssetCollection()).byLeft(this.id, relationship ? { relationship } : {});
|
|
252
|
+
return resolveOwnedAssetsById(this.db, linkedAssets.map((link) => link.assetId), this.tenantId);
|
|
253
|
+
}
|
|
254
|
+
async addAsset(asset, relationship = "attachment", sortOrder = 0) {
|
|
255
|
+
if (!this.id || !asset.id) throw new Error("Cannot associate unsaved event or asset");
|
|
256
|
+
assertValidOwnedAssetRelationship(relationship);
|
|
257
|
+
assertValidOwnedAssetSortOrder(sortOrder);
|
|
258
|
+
await (await this.getEventAssetCollection()).attach(this.id, asset.id, {
|
|
259
|
+
relationship,
|
|
260
|
+
sortOrder,
|
|
261
|
+
tenantId: this.tenantId
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
async removeAsset(assetId, relationship) {
|
|
265
|
+
if (!this.id) return;
|
|
266
|
+
await (await this.getEventAssetCollection()).detach(this.id, assetId, relationship ? { relationship } : {});
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Check if event is currently in progress
|
|
270
|
+
*
|
|
271
|
+
* @returns True if current time is between start and end
|
|
272
|
+
*/
|
|
273
|
+
isInProgress() {
|
|
274
|
+
if (this.status !== "in_progress") return false;
|
|
275
|
+
const now = /* @__PURE__ */ new Date();
|
|
276
|
+
if (this.startDate && now < this.startDate) return false;
|
|
277
|
+
if (this.endDate && now > this.endDate) return false;
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Check if event is a root event (no parent)
|
|
282
|
+
*
|
|
283
|
+
* @returns True if parentId is null/empty
|
|
284
|
+
*/
|
|
285
|
+
isRoot() {
|
|
286
|
+
return !this.parentId;
|
|
287
|
+
}
|
|
131
288
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
* Check if event is a root event (no parent)
|
|
335
|
-
*
|
|
336
|
-
* @returns True if parentId is null/empty
|
|
337
|
-
*/
|
|
338
|
-
isRoot() {
|
|
339
|
-
return !this.parentId;
|
|
340
|
-
}
|
|
289
|
+
__decorateClass$4([tenantId({ nullable: true })], Event.prototype, "tenantId", 2);
|
|
290
|
+
__decorateClass$4([foreignKey("EventSeries")], Event.prototype, "seriesId", 2);
|
|
291
|
+
__decorateClass$4([foreignKey("EventType")], Event.prototype, "typeId", 2);
|
|
292
|
+
__decorateClass$4([crossPackageRef("@happyvertical/smrt-places:Place")], Event.prototype, "placeId", 2);
|
|
293
|
+
Event = __decorateClass$4([TenantScoped({ mode: "optional" }), smrt({
|
|
294
|
+
tableStrategy: "sti",
|
|
295
|
+
api: { include: [
|
|
296
|
+
"list",
|
|
297
|
+
"get",
|
|
298
|
+
"create",
|
|
299
|
+
"update",
|
|
300
|
+
"delete"
|
|
301
|
+
] },
|
|
302
|
+
mcp: { include: [
|
|
303
|
+
"list",
|
|
304
|
+
"get",
|
|
305
|
+
"create",
|
|
306
|
+
"update"
|
|
307
|
+
] },
|
|
308
|
+
cli: true
|
|
309
|
+
})], Event);
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region src/collections/EventCollection.ts
|
|
312
|
+
var EventCollection_exports = /* @__PURE__ */ __exportAll({ EventCollection: () => EventCollection });
|
|
313
|
+
var EventCollection = class extends SmrtCollection {
|
|
314
|
+
static _itemClass = Event;
|
|
315
|
+
/**
|
|
316
|
+
* Get events by series
|
|
317
|
+
*
|
|
318
|
+
* @param seriesId - EventSeries ID
|
|
319
|
+
* @returns Array of Event instances
|
|
320
|
+
*/
|
|
321
|
+
async getBySeriesId(seriesId) {
|
|
322
|
+
return await this.list({ where: { seriesId } });
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Get events at a specific place
|
|
326
|
+
*
|
|
327
|
+
* @param placeId - Place ID
|
|
328
|
+
* @returns Array of Event instances
|
|
329
|
+
*/
|
|
330
|
+
async getByPlace(placeId) {
|
|
331
|
+
return await this.list({ where: { placeId } });
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Get events by date range
|
|
335
|
+
*
|
|
336
|
+
* @param startDate - Start of date range
|
|
337
|
+
* @param endDate - End of date range
|
|
338
|
+
* @returns Array of Event instances
|
|
339
|
+
*/
|
|
340
|
+
async getByDateRange(startDate, endDate) {
|
|
341
|
+
return (await this.list({})).filter((event) => {
|
|
342
|
+
if (!event.startDate) return false;
|
|
343
|
+
return event.startDate >= startDate && event.startDate <= endDate;
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Get upcoming events
|
|
348
|
+
*
|
|
349
|
+
* @param limit - Maximum number of events to return
|
|
350
|
+
* @returns Array of Event instances starting in the future
|
|
351
|
+
*/
|
|
352
|
+
async getUpcoming(limit) {
|
|
353
|
+
const allEvents = await this.list({});
|
|
354
|
+
const now = /* @__PURE__ */ new Date();
|
|
355
|
+
const upcoming = allEvents.filter((event) => event.startDate && event.startDate > now).sort((a, b) => {
|
|
356
|
+
if (!a.startDate || !b.startDate) return 0;
|
|
357
|
+
return a.startDate.getTime() - b.startDate.getTime();
|
|
358
|
+
});
|
|
359
|
+
return limit ? upcoming.slice(0, limit) : upcoming;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Get events by status
|
|
363
|
+
*
|
|
364
|
+
* @param status - Event status to filter by
|
|
365
|
+
* @returns Array of Event instances
|
|
366
|
+
*/
|
|
367
|
+
async getByStatus(status) {
|
|
368
|
+
return await this.list({ where: { status } });
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Get events by type
|
|
372
|
+
*
|
|
373
|
+
* @param typeId - EventType ID
|
|
374
|
+
* @returns Array of Event instances
|
|
375
|
+
*/
|
|
376
|
+
async getByType(typeId) {
|
|
377
|
+
return await this.list({ where: { typeId } });
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Get root events (no parent)
|
|
381
|
+
*
|
|
382
|
+
* @returns Array of Event instances with no parent
|
|
383
|
+
*/
|
|
384
|
+
async getRootEvents() {
|
|
385
|
+
return (await this.list({})).filter((event) => !event.parentId);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Get children of a parent event
|
|
389
|
+
*
|
|
390
|
+
* @param parentId - Parent event ID
|
|
391
|
+
* @returns Array of child Event instances
|
|
392
|
+
*/
|
|
393
|
+
async getByParent(parentId) {
|
|
394
|
+
return await this.list({ where: { parentId } });
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Get full event tree (hierarchy)
|
|
398
|
+
*
|
|
399
|
+
* @param eventId - Root event ID
|
|
400
|
+
* @returns Object with root event and nested children
|
|
401
|
+
*/
|
|
402
|
+
async getEventTree(eventId) {
|
|
403
|
+
const event = await this.get({ id: eventId });
|
|
404
|
+
if (!event) return null;
|
|
405
|
+
return await event.getHierarchy().then((h) => h.current);
|
|
406
|
+
}
|
|
407
|
+
async getAssets(eventId, relationship) {
|
|
408
|
+
return getOwnedAssetsFromCollection(this, eventId, relationship);
|
|
409
|
+
}
|
|
410
|
+
async addAsset(eventId, asset, relationship = "attachment", sortOrder = 0) {
|
|
411
|
+
await addOwnedAssetFromCollection(this, "Event", eventId, asset, relationship, sortOrder);
|
|
412
|
+
}
|
|
413
|
+
async removeAsset(eventId, assetId, relationship) {
|
|
414
|
+
await removeOwnedAssetFromCollection(this, "Event", eventId, assetId, relationship);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Search events with filters
|
|
418
|
+
*
|
|
419
|
+
* @param query - Search query for name/description
|
|
420
|
+
* @param filters - Additional filter criteria
|
|
421
|
+
* @returns Array of matching Event instances
|
|
422
|
+
*/
|
|
423
|
+
async search(query, filters) {
|
|
424
|
+
let events = await this.list({});
|
|
425
|
+
if (query) {
|
|
426
|
+
const lowerQuery = query.toLowerCase();
|
|
427
|
+
events = events.filter((e) => e.name?.toLowerCase().includes(lowerQuery) || e.description?.toLowerCase().includes(lowerQuery));
|
|
428
|
+
}
|
|
429
|
+
if (filters) {
|
|
430
|
+
if (filters.typeId) events = events.filter((e) => e.typeId === filters.typeId);
|
|
431
|
+
if (filters.seriesId) events = events.filter((e) => e.seriesId === filters.seriesId);
|
|
432
|
+
if (filters.placeId) events = events.filter((e) => e.placeId === filters.placeId);
|
|
433
|
+
if (filters.status) if (Array.isArray(filters.status)) events = events.filter((e) => filters.status?.includes(e.status));
|
|
434
|
+
else events = events.filter((e) => e.status === filters.status);
|
|
435
|
+
if (filters.startDate) {
|
|
436
|
+
const startDate = filters.startDate;
|
|
437
|
+
events = events.filter((e) => e.startDate && e.startDate >= startDate);
|
|
438
|
+
}
|
|
439
|
+
if (filters.endDate) {
|
|
440
|
+
const endDate = filters.endDate;
|
|
441
|
+
events = events.filter((e) => e.startDate && e.startDate <= endDate);
|
|
442
|
+
}
|
|
443
|
+
if (filters.organizerId) events = events.filter(async (e) => {
|
|
444
|
+
const series = await e.getSeries();
|
|
445
|
+
return series && series.organizerId === filters.organizerId;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
return events;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Get events in progress
|
|
452
|
+
*
|
|
453
|
+
* @returns Array of Event instances currently in progress
|
|
454
|
+
*/
|
|
455
|
+
async getInProgress() {
|
|
456
|
+
return (await this.getByStatus("in_progress")).filter((event) => event.isInProgress());
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Find all events for a specific tenant
|
|
460
|
+
*
|
|
461
|
+
* @param tenantId - Tenant ID to filter by
|
|
462
|
+
* @returns Array of Event instances for the tenant
|
|
463
|
+
*/
|
|
464
|
+
async findByTenant(tenantId) {
|
|
465
|
+
return this.list({ where: { tenantId } });
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Find all global events (no tenant association).
|
|
469
|
+
*
|
|
470
|
+
* Routes through the shared tenant-global helper so it does not throw under
|
|
471
|
+
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
472
|
+
* flagged as an isolation violation). (#1600)
|
|
473
|
+
*
|
|
474
|
+
* @returns Array of Event instances with no tenant
|
|
475
|
+
*/
|
|
476
|
+
async findGlobal() {
|
|
477
|
+
return queryGlobal(this);
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Find events for a tenant including global events.
|
|
481
|
+
*
|
|
482
|
+
* Fails closed if an active tenant context requests a different tenant's
|
|
483
|
+
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
484
|
+
*
|
|
485
|
+
* @param tenantId - Tenant ID to filter by
|
|
486
|
+
* @returns Array of Event instances for the tenant and global events
|
|
487
|
+
*/
|
|
488
|
+
async findWithGlobals(tenantId) {
|
|
489
|
+
return queryWithGlobals(this, tenantId, "Event.findWithGlobals");
|
|
490
|
+
}
|
|
341
491
|
};
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
], Event.prototype, "tenantId", 2);
|
|
345
|
-
__decorateClass$4([
|
|
346
|
-
foreignKey("EventSeries")
|
|
347
|
-
], Event.prototype, "seriesId", 2);
|
|
348
|
-
__decorateClass$4([
|
|
349
|
-
foreignKey("EventType")
|
|
350
|
-
], Event.prototype, "typeId", 2);
|
|
351
|
-
__decorateClass$4([
|
|
352
|
-
crossPackageRef("@happyvertical/smrt-places:Place")
|
|
353
|
-
], Event.prototype, "placeId", 2);
|
|
354
|
-
Event = __decorateClass$4([
|
|
355
|
-
TenantScoped({ mode: "optional" }),
|
|
356
|
-
smrt({
|
|
357
|
-
tableStrategy: "sti",
|
|
358
|
-
api: { include: ["list", "get", "create", "update", "delete"] },
|
|
359
|
-
mcp: { include: ["list", "get", "create", "update"] },
|
|
360
|
-
cli: true
|
|
361
|
-
})
|
|
362
|
-
], Event);
|
|
363
|
-
class EventCollection extends SmrtCollection {
|
|
364
|
-
static _itemClass = Event;
|
|
365
|
-
/**
|
|
366
|
-
* Get events by series
|
|
367
|
-
*
|
|
368
|
-
* @param seriesId - EventSeries ID
|
|
369
|
-
* @returns Array of Event instances
|
|
370
|
-
*/
|
|
371
|
-
async getBySeriesId(seriesId) {
|
|
372
|
-
return await this.list({ where: { seriesId } });
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Get events at a specific place
|
|
376
|
-
*
|
|
377
|
-
* @param placeId - Place ID
|
|
378
|
-
* @returns Array of Event instances
|
|
379
|
-
*/
|
|
380
|
-
async getByPlace(placeId) {
|
|
381
|
-
return await this.list({ where: { placeId } });
|
|
382
|
-
}
|
|
383
|
-
/**
|
|
384
|
-
* Get events by date range
|
|
385
|
-
*
|
|
386
|
-
* @param startDate - Start of date range
|
|
387
|
-
* @param endDate - End of date range
|
|
388
|
-
* @returns Array of Event instances
|
|
389
|
-
*/
|
|
390
|
-
async getByDateRange(startDate, endDate) {
|
|
391
|
-
const allEvents = await this.list({});
|
|
392
|
-
return allEvents.filter((event) => {
|
|
393
|
-
if (!event.startDate) return false;
|
|
394
|
-
return event.startDate >= startDate && event.startDate <= endDate;
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Get upcoming events
|
|
399
|
-
*
|
|
400
|
-
* @param limit - Maximum number of events to return
|
|
401
|
-
* @returns Array of Event instances starting in the future
|
|
402
|
-
*/
|
|
403
|
-
async getUpcoming(limit) {
|
|
404
|
-
const allEvents = await this.list({});
|
|
405
|
-
const now = /* @__PURE__ */ new Date();
|
|
406
|
-
const upcoming = allEvents.filter((event) => event.startDate && event.startDate > now).sort((a, b) => {
|
|
407
|
-
if (!a.startDate || !b.startDate) return 0;
|
|
408
|
-
return a.startDate.getTime() - b.startDate.getTime();
|
|
409
|
-
});
|
|
410
|
-
return limit ? upcoming.slice(0, limit) : upcoming;
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* Get events by status
|
|
414
|
-
*
|
|
415
|
-
* @param status - Event status to filter by
|
|
416
|
-
* @returns Array of Event instances
|
|
417
|
-
*/
|
|
418
|
-
async getByStatus(status) {
|
|
419
|
-
return await this.list({ where: { status } });
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Get events by type
|
|
423
|
-
*
|
|
424
|
-
* @param typeId - EventType ID
|
|
425
|
-
* @returns Array of Event instances
|
|
426
|
-
*/
|
|
427
|
-
async getByType(typeId) {
|
|
428
|
-
return await this.list({ where: { typeId } });
|
|
429
|
-
}
|
|
430
|
-
/**
|
|
431
|
-
* Get root events (no parent)
|
|
432
|
-
*
|
|
433
|
-
* @returns Array of Event instances with no parent
|
|
434
|
-
*/
|
|
435
|
-
async getRootEvents() {
|
|
436
|
-
const allEvents = await this.list({});
|
|
437
|
-
return allEvents.filter((event) => !event.parentId);
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* Get children of a parent event
|
|
441
|
-
*
|
|
442
|
-
* @param parentId - Parent event ID
|
|
443
|
-
* @returns Array of child Event instances
|
|
444
|
-
*/
|
|
445
|
-
async getByParent(parentId) {
|
|
446
|
-
return await this.list({ where: { parentId } });
|
|
447
|
-
}
|
|
448
|
-
/**
|
|
449
|
-
* Get full event tree (hierarchy)
|
|
450
|
-
*
|
|
451
|
-
* @param eventId - Root event ID
|
|
452
|
-
* @returns Object with root event and nested children
|
|
453
|
-
*/
|
|
454
|
-
async getEventTree(eventId) {
|
|
455
|
-
const event = await this.get({ id: eventId });
|
|
456
|
-
if (!event) return null;
|
|
457
|
-
return await event.getHierarchy().then((h) => h.current);
|
|
458
|
-
}
|
|
459
|
-
async getAssets(eventId, relationship) {
|
|
460
|
-
return getOwnedAssetsFromCollection(this, eventId, relationship);
|
|
461
|
-
}
|
|
462
|
-
async addAsset(eventId, asset, relationship = "attachment", sortOrder = 0) {
|
|
463
|
-
await addOwnedAssetFromCollection(
|
|
464
|
-
this,
|
|
465
|
-
"Event",
|
|
466
|
-
eventId,
|
|
467
|
-
asset,
|
|
468
|
-
relationship,
|
|
469
|
-
sortOrder
|
|
470
|
-
);
|
|
471
|
-
}
|
|
472
|
-
async removeAsset(eventId, assetId, relationship) {
|
|
473
|
-
await removeOwnedAssetFromCollection(
|
|
474
|
-
this,
|
|
475
|
-
"Event",
|
|
476
|
-
eventId,
|
|
477
|
-
assetId,
|
|
478
|
-
relationship
|
|
479
|
-
);
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Search events with filters
|
|
483
|
-
*
|
|
484
|
-
* @param query - Search query for name/description
|
|
485
|
-
* @param filters - Additional filter criteria
|
|
486
|
-
* @returns Array of matching Event instances
|
|
487
|
-
*/
|
|
488
|
-
async search(query, filters) {
|
|
489
|
-
let events = await this.list({});
|
|
490
|
-
if (query) {
|
|
491
|
-
const lowerQuery = query.toLowerCase();
|
|
492
|
-
events = events.filter(
|
|
493
|
-
(e) => e.name?.toLowerCase().includes(lowerQuery) || e.description?.toLowerCase().includes(lowerQuery)
|
|
494
|
-
);
|
|
495
|
-
}
|
|
496
|
-
if (filters) {
|
|
497
|
-
if (filters.typeId) {
|
|
498
|
-
events = events.filter((e) => e.typeId === filters.typeId);
|
|
499
|
-
}
|
|
500
|
-
if (filters.seriesId) {
|
|
501
|
-
events = events.filter((e) => e.seriesId === filters.seriesId);
|
|
502
|
-
}
|
|
503
|
-
if (filters.placeId) {
|
|
504
|
-
events = events.filter((e) => e.placeId === filters.placeId);
|
|
505
|
-
}
|
|
506
|
-
if (filters.status) {
|
|
507
|
-
if (Array.isArray(filters.status)) {
|
|
508
|
-
events = events.filter((e) => filters.status?.includes(e.status));
|
|
509
|
-
} else {
|
|
510
|
-
events = events.filter((e) => e.status === filters.status);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
if (filters.startDate) {
|
|
514
|
-
const startDate = filters.startDate;
|
|
515
|
-
events = events.filter((e) => e.startDate && e.startDate >= startDate);
|
|
516
|
-
}
|
|
517
|
-
if (filters.endDate) {
|
|
518
|
-
const endDate = filters.endDate;
|
|
519
|
-
events = events.filter((e) => e.startDate && e.startDate <= endDate);
|
|
520
|
-
}
|
|
521
|
-
if (filters.organizerId) {
|
|
522
|
-
events = events.filter(async (e) => {
|
|
523
|
-
const series = await e.getSeries();
|
|
524
|
-
return series && series.organizerId === filters.organizerId;
|
|
525
|
-
});
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
return events;
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* Get events in progress
|
|
532
|
-
*
|
|
533
|
-
* @returns Array of Event instances currently in progress
|
|
534
|
-
*/
|
|
535
|
-
async getInProgress() {
|
|
536
|
-
const inProgressEvents = await this.getByStatus("in_progress");
|
|
537
|
-
return inProgressEvents.filter((event) => event.isInProgress());
|
|
538
|
-
}
|
|
539
|
-
// ============================================
|
|
540
|
-
// Tenant Helper Methods
|
|
541
|
-
// ============================================
|
|
542
|
-
/**
|
|
543
|
-
* Find all events for a specific tenant
|
|
544
|
-
*
|
|
545
|
-
* @param tenantId - Tenant ID to filter by
|
|
546
|
-
* @returns Array of Event instances for the tenant
|
|
547
|
-
*/
|
|
548
|
-
async findByTenant(tenantId2) {
|
|
549
|
-
return this.list({ where: { tenantId: tenantId2 } });
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Find all global events (no tenant association).
|
|
553
|
-
*
|
|
554
|
-
* Routes through the shared tenant-global helper so it does not throw under
|
|
555
|
-
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
556
|
-
* flagged as an isolation violation). (#1600)
|
|
557
|
-
*
|
|
558
|
-
* @returns Array of Event instances with no tenant
|
|
559
|
-
*/
|
|
560
|
-
async findGlobal() {
|
|
561
|
-
return queryGlobal(this);
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Find events for a tenant including global events.
|
|
565
|
-
*
|
|
566
|
-
* Fails closed if an active tenant context requests a different tenant's
|
|
567
|
-
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
568
|
-
*
|
|
569
|
-
* @param tenantId - Tenant ID to filter by
|
|
570
|
-
* @returns Array of Event instances for the tenant and global events
|
|
571
|
-
*/
|
|
572
|
-
async findWithGlobals(tenantId2) {
|
|
573
|
-
return queryWithGlobals(this, tenantId2, "Event.findWithGlobals");
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
const EventCollection$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
577
|
-
__proto__: null,
|
|
578
|
-
EventCollection
|
|
579
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
492
|
+
//#endregion
|
|
493
|
+
//#region src/models/EventParticipant.ts
|
|
580
494
|
var __defProp$3 = Object.defineProperty;
|
|
581
495
|
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
582
496
|
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
if (kind && result) __defProp$3(target, key, result);
|
|
588
|
-
return result;
|
|
497
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
498
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
499
|
+
if (kind && result) __defProp$3(target, key, result);
|
|
500
|
+
return result;
|
|
589
501
|
};
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
* @returns True if placement is 0
|
|
703
|
-
*/
|
|
704
|
-
isHome() {
|
|
705
|
-
return this.placement === 0;
|
|
706
|
-
}
|
|
707
|
-
/**
|
|
708
|
-
* Check if this is an away participant (placement = 1)
|
|
709
|
-
*
|
|
710
|
-
* @returns True if placement is 1
|
|
711
|
-
*/
|
|
712
|
-
isAway() {
|
|
713
|
-
return this.placement === 1;
|
|
714
|
-
}
|
|
502
|
+
var EventParticipant = class extends SmrtObject {
|
|
503
|
+
tenantId = null;
|
|
504
|
+
eventId = "";
|
|
505
|
+
profileId = "";
|
|
506
|
+
role = "";
|
|
507
|
+
placement = null;
|
|
508
|
+
groupId = "";
|
|
509
|
+
metadata = "";
|
|
510
|
+
externalId = "";
|
|
511
|
+
source = "";
|
|
512
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
513
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
514
|
+
constructor(options = {}) {
|
|
515
|
+
super(options);
|
|
516
|
+
if (options.eventId) this.eventId = options.eventId;
|
|
517
|
+
if (options.profileId) this.profileId = options.profileId;
|
|
518
|
+
if (options.role !== void 0) this.role = options.role;
|
|
519
|
+
if (options.placement !== void 0) this.placement = options.placement;
|
|
520
|
+
if (options.groupId !== void 0) this.groupId = options.groupId;
|
|
521
|
+
if (options.externalId !== void 0) this.externalId = options.externalId;
|
|
522
|
+
if (options.source !== void 0) this.source = options.source;
|
|
523
|
+
if (options.metadata !== void 0) if (typeof options.metadata === "string") this.metadata = options.metadata;
|
|
524
|
+
else this.metadata = JSON.stringify(options.metadata);
|
|
525
|
+
if (options.createdAt) this.createdAt = options.createdAt;
|
|
526
|
+
if (options.updatedAt) this.updatedAt = options.updatedAt;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Get metadata as parsed object
|
|
530
|
+
*
|
|
531
|
+
* @returns Parsed metadata object or empty object
|
|
532
|
+
*/
|
|
533
|
+
getMetadata() {
|
|
534
|
+
if (!this.metadata) return {};
|
|
535
|
+
try {
|
|
536
|
+
return JSON.parse(this.metadata);
|
|
537
|
+
} catch {
|
|
538
|
+
return {};
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Set metadata from object
|
|
543
|
+
*
|
|
544
|
+
* @param data - Metadata object to store
|
|
545
|
+
*/
|
|
546
|
+
setMetadata(data) {
|
|
547
|
+
this.metadata = JSON.stringify(data);
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Update metadata by merging with existing values
|
|
551
|
+
*
|
|
552
|
+
* @param updates - Partial metadata to merge
|
|
553
|
+
*/
|
|
554
|
+
updateMetadata(updates) {
|
|
555
|
+
const current = this.getMetadata();
|
|
556
|
+
this.setMetadata({
|
|
557
|
+
...current,
|
|
558
|
+
...updates
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Get the event for this participant
|
|
563
|
+
*
|
|
564
|
+
* @returns Event instance or null
|
|
565
|
+
*/
|
|
566
|
+
async getEvent() {
|
|
567
|
+
if (!this.eventId) return null;
|
|
568
|
+
const { EventCollection } = await Promise.resolve().then(() => EventCollection_exports);
|
|
569
|
+
return await (await EventCollection.create(this.options)).get({ id: this.eventId });
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Get the profile for this participant
|
|
573
|
+
*
|
|
574
|
+
* @returns Profile instance or null
|
|
575
|
+
*/
|
|
576
|
+
async getProfile() {
|
|
577
|
+
if (!this.profileId) return null;
|
|
578
|
+
try {
|
|
579
|
+
const { ProfileCollection } = await import("@happyvertical/smrt-profiles");
|
|
580
|
+
return await (await ProfileCollection.create(this.options)).get({ id: this.profileId });
|
|
581
|
+
} catch {
|
|
582
|
+
return null;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Get group participants (others with same groupId)
|
|
587
|
+
*
|
|
588
|
+
* @returns Array of EventParticipant instances
|
|
589
|
+
*/
|
|
590
|
+
async getGroupParticipants() {
|
|
591
|
+
if (!this.groupId) return [];
|
|
592
|
+
const { EventParticipantCollection } = await Promise.resolve().then(() => EventParticipantCollection_exports);
|
|
593
|
+
return (await (await EventParticipantCollection.create(this.options)).list({ where: {
|
|
594
|
+
eventId: this.eventId,
|
|
595
|
+
groupId: this.groupId
|
|
596
|
+
} })).filter((p) => p.id !== this.id);
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Check if this is a home participant (placement = 0)
|
|
600
|
+
*
|
|
601
|
+
* @returns True if placement is 0
|
|
602
|
+
*/
|
|
603
|
+
isHome() {
|
|
604
|
+
return this.placement === 0;
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Check if this is an away participant (placement = 1)
|
|
608
|
+
*
|
|
609
|
+
* @returns True if placement is 1
|
|
610
|
+
*/
|
|
611
|
+
isAway() {
|
|
612
|
+
return this.placement === 1;
|
|
613
|
+
}
|
|
715
614
|
};
|
|
716
|
-
__decorateClass$3([
|
|
717
|
-
|
|
718
|
-
], EventParticipant.prototype, "
|
|
719
|
-
__decorateClass$3([
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
],
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
615
|
+
__decorateClass$3([tenantId({ nullable: true })], EventParticipant.prototype, "tenantId", 2);
|
|
616
|
+
__decorateClass$3([foreignKey("Event")], EventParticipant.prototype, "eventId", 2);
|
|
617
|
+
__decorateClass$3([crossPackageRef("@happyvertical/smrt-profiles:Profile")], EventParticipant.prototype, "profileId", 2);
|
|
618
|
+
EventParticipant = __decorateClass$3([TenantScoped({ mode: "optional" }), smrt({
|
|
619
|
+
conflictColumns: [
|
|
620
|
+
"event_id",
|
|
621
|
+
"profile_id",
|
|
622
|
+
"role"
|
|
623
|
+
],
|
|
624
|
+
api: { include: [
|
|
625
|
+
"list",
|
|
626
|
+
"get",
|
|
627
|
+
"create",
|
|
628
|
+
"update",
|
|
629
|
+
"delete"
|
|
630
|
+
] },
|
|
631
|
+
mcp: { include: [
|
|
632
|
+
"list",
|
|
633
|
+
"get",
|
|
634
|
+
"create",
|
|
635
|
+
"update"
|
|
636
|
+
] },
|
|
637
|
+
cli: true
|
|
638
|
+
})], EventParticipant);
|
|
639
|
+
//#endregion
|
|
640
|
+
//#region src/collections/EventParticipantCollection.ts
|
|
641
|
+
var EventParticipantCollection_exports = /* @__PURE__ */ __exportAll({ EventParticipantCollection: () => EventParticipantCollection });
|
|
736
642
|
var __defProp$2 = Object.defineProperty;
|
|
737
643
|
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
738
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
|
|
644
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
|
|
645
|
+
enumerable: true,
|
|
646
|
+
configurable: true,
|
|
647
|
+
writable: true,
|
|
648
|
+
value
|
|
649
|
+
}) : obj[key] = value;
|
|
739
650
|
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
return result;
|
|
651
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
652
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
653
|
+
if (kind && result) __defProp$2(target, key, result);
|
|
654
|
+
return result;
|
|
745
655
|
};
|
|
746
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, key + "", value);
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
// ============================================
|
|
840
|
-
async findByTenant(tenantId2) {
|
|
841
|
-
return this.list({ where: { tenantId: tenantId2 } });
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
* Find all global participants (no tenant association).
|
|
845
|
-
*
|
|
846
|
-
* Routes through the shared tenant-global helper so it does not throw under
|
|
847
|
-
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
848
|
-
* flagged as an isolation violation). (#1600)
|
|
849
|
-
*/
|
|
850
|
-
async findGlobal() {
|
|
851
|
-
return queryGlobal(this);
|
|
852
|
-
}
|
|
853
|
-
/**
|
|
854
|
-
* Find participants for a tenant plus all global participants.
|
|
855
|
-
*
|
|
856
|
-
* Fails closed if an active tenant context requests a different tenant's
|
|
857
|
-
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
858
|
-
*/
|
|
859
|
-
async findWithGlobals(tenantId2) {
|
|
860
|
-
return queryWithGlobals(
|
|
861
|
-
this,
|
|
862
|
-
tenantId2,
|
|
863
|
-
"EventParticipant.findWithGlobals"
|
|
864
|
-
);
|
|
865
|
-
}
|
|
656
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
657
|
+
var EventParticipantCollection = class extends SmrtJunction {
|
|
658
|
+
leftField = "eventId";
|
|
659
|
+
rightField = "profileId";
|
|
660
|
+
sortField = null;
|
|
661
|
+
positionField = null;
|
|
662
|
+
/**
|
|
663
|
+
* Get participants ordered by placement (nulls last).
|
|
664
|
+
*/
|
|
665
|
+
async getByPlacement(eventId) {
|
|
666
|
+
return (await this.byLeft(eventId)).sort((a, b) => {
|
|
667
|
+
if (a.placement === null && b.placement === null) return 0;
|
|
668
|
+
if (a.placement === null) return 1;
|
|
669
|
+
if (b.placement === null) return -1;
|
|
670
|
+
return a.placement - b.placement;
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Get participants by group within an event.
|
|
675
|
+
*/
|
|
676
|
+
async getByGroup(eventId, groupId) {
|
|
677
|
+
return this.byLeft(eventId, { groupId });
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Get the home participant(s) — placement = 0.
|
|
681
|
+
*/
|
|
682
|
+
async getHome(eventId) {
|
|
683
|
+
return this.byLeft(eventId, { placement: 0 });
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Get the away participant(s) — placement = 1.
|
|
687
|
+
*/
|
|
688
|
+
async getAway(eventId) {
|
|
689
|
+
return this.byLeft(eventId, { placement: 1 });
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Search participants with optional filters.
|
|
693
|
+
*/
|
|
694
|
+
async search(filters) {
|
|
695
|
+
let participants = await this.list({});
|
|
696
|
+
if (filters.eventId) participants = participants.filter((p) => p.eventId === filters.eventId);
|
|
697
|
+
if (filters.profileId) participants = participants.filter((p) => p.profileId === filters.profileId);
|
|
698
|
+
if (filters.role) participants = participants.filter((p) => p.role === filters.role);
|
|
699
|
+
if (filters.groupId) participants = participants.filter((p) => p.groupId === filters.groupId);
|
|
700
|
+
return participants;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Get participation statistics for a profile, optionally filtered by event type.
|
|
704
|
+
*/
|
|
705
|
+
async getParticipantStats(profileId, eventTypeId) {
|
|
706
|
+
const participants = await this.byRight(profileId);
|
|
707
|
+
let filteredParticipants = participants;
|
|
708
|
+
if (eventTypeId) {
|
|
709
|
+
filteredParticipants = [];
|
|
710
|
+
for (const participant of participants) {
|
|
711
|
+
const event = await participant.getEvent();
|
|
712
|
+
if (event && event.typeId === eventTypeId) filteredParticipants.push(participant);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
const byRole = {};
|
|
716
|
+
const byPlacement = {};
|
|
717
|
+
for (const participant of filteredParticipants) {
|
|
718
|
+
byRole[participant.role] = (byRole[participant.role] || 0) + 1;
|
|
719
|
+
if (participant.placement !== null) byPlacement[participant.placement] = (byPlacement[participant.placement] || 0) + 1;
|
|
720
|
+
}
|
|
721
|
+
return {
|
|
722
|
+
totalEvents: filteredParticipants.length,
|
|
723
|
+
byRole,
|
|
724
|
+
byPlacement
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
async findByTenant(tenantId) {
|
|
728
|
+
return this.list({ where: { tenantId } });
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Find all global participants (no tenant association).
|
|
732
|
+
*
|
|
733
|
+
* Routes through the shared tenant-global helper so it does not throw under
|
|
734
|
+
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
735
|
+
* flagged as an isolation violation). (#1600)
|
|
736
|
+
*/
|
|
737
|
+
async findGlobal() {
|
|
738
|
+
return queryGlobal(this);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Find participants for a tenant plus all global participants.
|
|
742
|
+
*
|
|
743
|
+
* Fails closed if an active tenant context requests a different tenant's
|
|
744
|
+
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
745
|
+
*/
|
|
746
|
+
async findWithGlobals(tenantId) {
|
|
747
|
+
return queryWithGlobals(this, tenantId, "EventParticipant.findWithGlobals");
|
|
748
|
+
}
|
|
866
749
|
};
|
|
867
750
|
__publicField(EventParticipantCollection, "_itemClass", EventParticipant);
|
|
868
|
-
EventParticipantCollection = __decorateClass$2([
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
const EventParticipantCollection$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
872
|
-
__proto__: null,
|
|
873
|
-
get EventParticipantCollection() {
|
|
874
|
-
return EventParticipantCollection;
|
|
875
|
-
}
|
|
876
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
751
|
+
EventParticipantCollection = __decorateClass$2([smrt()], EventParticipantCollection);
|
|
752
|
+
//#endregion
|
|
753
|
+
//#region src/models/EventSeries.ts
|
|
877
754
|
var __defProp$1 = Object.defineProperty;
|
|
878
755
|
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
879
756
|
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
757
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
758
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
759
|
+
if (kind && result) __defProp$1(target, key, result);
|
|
760
|
+
return result;
|
|
761
|
+
};
|
|
762
|
+
var EventSeries = class extends SmrtObject {
|
|
763
|
+
tenantId = null;
|
|
764
|
+
name = "";
|
|
765
|
+
typeId = "";
|
|
766
|
+
organizerId = "";
|
|
767
|
+
description = "";
|
|
768
|
+
startDate = null;
|
|
769
|
+
endDate = null;
|
|
770
|
+
recurrence = "";
|
|
771
|
+
metadata = "";
|
|
772
|
+
externalId = "";
|
|
773
|
+
source = "";
|
|
774
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
775
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
776
|
+
constructor(options = {}) {
|
|
777
|
+
super(options);
|
|
778
|
+
if (options.typeId) this.typeId = options.typeId;
|
|
779
|
+
if (options.organizerId) this.organizerId = options.organizerId;
|
|
780
|
+
if (options.description !== void 0) this.description = options.description;
|
|
781
|
+
if (options.startDate !== void 0) this.startDate = options.startDate || null;
|
|
782
|
+
if (options.endDate !== void 0) this.endDate = options.endDate || null;
|
|
783
|
+
if (options.externalId !== void 0) this.externalId = options.externalId;
|
|
784
|
+
if (options.source !== void 0) this.source = options.source;
|
|
785
|
+
if (options.recurrence !== void 0) if (typeof options.recurrence === "string") this.recurrence = options.recurrence;
|
|
786
|
+
else this.recurrence = JSON.stringify(options.recurrence);
|
|
787
|
+
if (options.metadata !== void 0) if (typeof options.metadata === "string") this.metadata = options.metadata;
|
|
788
|
+
else this.metadata = JSON.stringify(options.metadata);
|
|
789
|
+
if (options.createdAt) this.createdAt = options.createdAt;
|
|
790
|
+
if (options.updatedAt) this.updatedAt = options.updatedAt;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Get recurrence pattern as parsed object
|
|
794
|
+
*
|
|
795
|
+
* @returns Parsed recurrence pattern or null
|
|
796
|
+
*/
|
|
797
|
+
getRecurrence() {
|
|
798
|
+
if (!this.recurrence) return null;
|
|
799
|
+
try {
|
|
800
|
+
return JSON.parse(this.recurrence);
|
|
801
|
+
} catch {
|
|
802
|
+
return null;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Set recurrence pattern from object
|
|
807
|
+
*
|
|
808
|
+
* @param pattern - Recurrence pattern to store
|
|
809
|
+
*/
|
|
810
|
+
setRecurrence(pattern) {
|
|
811
|
+
this.recurrence = JSON.stringify(pattern);
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Get metadata as parsed object
|
|
815
|
+
*
|
|
816
|
+
* @returns Parsed metadata object or empty object
|
|
817
|
+
*/
|
|
818
|
+
getMetadata() {
|
|
819
|
+
if (!this.metadata) return {};
|
|
820
|
+
try {
|
|
821
|
+
return JSON.parse(this.metadata);
|
|
822
|
+
} catch {
|
|
823
|
+
return {};
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Set metadata from object
|
|
828
|
+
*
|
|
829
|
+
* @param data - Metadata object to store
|
|
830
|
+
*/
|
|
831
|
+
setMetadata(data) {
|
|
832
|
+
this.metadata = JSON.stringify(data);
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* Update metadata by merging with existing values
|
|
836
|
+
*
|
|
837
|
+
* @param updates - Partial metadata to merge
|
|
838
|
+
*/
|
|
839
|
+
updateMetadata(updates) {
|
|
840
|
+
const current = this.getMetadata();
|
|
841
|
+
this.setMetadata({
|
|
842
|
+
...current,
|
|
843
|
+
...updates
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Get the event type for this series
|
|
848
|
+
*
|
|
849
|
+
* @returns EventType instance or null
|
|
850
|
+
*/
|
|
851
|
+
async getType() {
|
|
852
|
+
if (!this.typeId) return null;
|
|
853
|
+
const { EventTypeCollection } = await Promise.resolve().then(() => EventTypeCollection_exports);
|
|
854
|
+
return await (await EventTypeCollection.create(this.options)).get({ id: this.typeId });
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Get the organizer profile for this series
|
|
858
|
+
*
|
|
859
|
+
* @returns Profile instance or null
|
|
860
|
+
*/
|
|
861
|
+
async getOrganizer() {
|
|
862
|
+
if (!this.organizerId) return null;
|
|
863
|
+
try {
|
|
864
|
+
const { ProfileCollection } = await import("@happyvertical/smrt-profiles");
|
|
865
|
+
return await (await ProfileCollection.create(this.options)).get({ id: this.organizerId });
|
|
866
|
+
} catch {
|
|
867
|
+
return null;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Get all events in this series
|
|
872
|
+
*
|
|
873
|
+
* @returns Array of Event instances
|
|
874
|
+
*/
|
|
875
|
+
async getEvents() {
|
|
876
|
+
const { EventCollection } = await Promise.resolve().then(() => EventCollection_exports);
|
|
877
|
+
return await (await EventCollection.create(this.options)).list({ where: { seriesId: this.id } });
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Check if series is currently active
|
|
881
|
+
*
|
|
882
|
+
* @returns True if current date is between start and end
|
|
883
|
+
*/
|
|
884
|
+
isActive() {
|
|
885
|
+
const now = /* @__PURE__ */ new Date();
|
|
886
|
+
if (this.startDate && now < this.startDate) return false;
|
|
887
|
+
if (this.endDate && now > this.endDate) return false;
|
|
888
|
+
return true;
|
|
889
|
+
}
|
|
886
890
|
};
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
const collection = await EventCollection2.create(this.options);
|
|
1020
|
-
return await collection.list({ where: { seriesId: this.id } });
|
|
1021
|
-
}
|
|
1022
|
-
/**
|
|
1023
|
-
* Check if series is currently active
|
|
1024
|
-
*
|
|
1025
|
-
* @returns True if current date is between start and end
|
|
1026
|
-
*/
|
|
1027
|
-
isActive() {
|
|
1028
|
-
const now = /* @__PURE__ */ new Date();
|
|
1029
|
-
if (this.startDate && now < this.startDate) return false;
|
|
1030
|
-
if (this.endDate && now > this.endDate) return false;
|
|
1031
|
-
return true;
|
|
1032
|
-
}
|
|
891
|
+
__decorateClass$1([tenantId({ nullable: true })], EventSeries.prototype, "tenantId", 2);
|
|
892
|
+
__decorateClass$1([foreignKey("EventType")], EventSeries.prototype, "typeId", 2);
|
|
893
|
+
__decorateClass$1([crossPackageRef("@happyvertical/smrt-profiles:Profile")], EventSeries.prototype, "organizerId", 2);
|
|
894
|
+
EventSeries = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt({
|
|
895
|
+
tableStrategy: "sti",
|
|
896
|
+
api: { include: [
|
|
897
|
+
"list",
|
|
898
|
+
"get",
|
|
899
|
+
"create",
|
|
900
|
+
"update",
|
|
901
|
+
"delete"
|
|
902
|
+
] },
|
|
903
|
+
mcp: { include: [
|
|
904
|
+
"list",
|
|
905
|
+
"get",
|
|
906
|
+
"create",
|
|
907
|
+
"update"
|
|
908
|
+
] },
|
|
909
|
+
cli: true
|
|
910
|
+
})], EventSeries);
|
|
911
|
+
//#endregion
|
|
912
|
+
//#region src/collections/EventSeriesCollection.ts
|
|
913
|
+
var EventSeriesCollection_exports = /* @__PURE__ */ __exportAll({ EventSeriesCollection: () => EventSeriesCollection });
|
|
914
|
+
var EventSeriesCollection = class extends SmrtCollection {
|
|
915
|
+
static _itemClass = EventSeries;
|
|
916
|
+
/**
|
|
917
|
+
* Get series by organizer
|
|
918
|
+
*
|
|
919
|
+
* @param organizerId - Profile ID of the organizer
|
|
920
|
+
* @returns Array of EventSeries instances
|
|
921
|
+
*/
|
|
922
|
+
async getByOrganizer(organizerId) {
|
|
923
|
+
return await this.list({ where: { organizerId } });
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Get currently active series
|
|
927
|
+
*
|
|
928
|
+
* @returns Array of EventSeries instances active today
|
|
929
|
+
*/
|
|
930
|
+
async getActive() {
|
|
931
|
+
const allSeries = await this.list({});
|
|
932
|
+
const now = /* @__PURE__ */ new Date();
|
|
933
|
+
return allSeries.filter((series) => {
|
|
934
|
+
if (series.startDate && now < series.startDate) return false;
|
|
935
|
+
if (series.endDate && now > series.endDate) return false;
|
|
936
|
+
return true;
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Get upcoming series
|
|
941
|
+
*
|
|
942
|
+
* @param limit - Maximum number of series to return
|
|
943
|
+
* @returns Array of EventSeries instances starting in the future
|
|
944
|
+
*/
|
|
945
|
+
async getUpcoming(limit) {
|
|
946
|
+
const allSeries = await this.list({});
|
|
947
|
+
const now = /* @__PURE__ */ new Date();
|
|
948
|
+
const upcoming = allSeries.filter((series) => series.startDate && series.startDate > now).sort((a, b) => {
|
|
949
|
+
if (!a.startDate || !b.startDate) return 0;
|
|
950
|
+
return a.startDate.getTime() - b.startDate.getTime();
|
|
951
|
+
});
|
|
952
|
+
return limit ? upcoming.slice(0, limit) : upcoming;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Get series by type
|
|
956
|
+
*
|
|
957
|
+
* @param typeId - EventType ID
|
|
958
|
+
* @returns Array of EventSeries instances
|
|
959
|
+
*/
|
|
960
|
+
async getByType(typeId) {
|
|
961
|
+
return await this.list({ where: { typeId } });
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Search series with filters
|
|
965
|
+
*
|
|
966
|
+
* @param query - Search query for name/description
|
|
967
|
+
* @param filters - Additional filter criteria
|
|
968
|
+
* @returns Array of matching EventSeries instances
|
|
969
|
+
*/
|
|
970
|
+
async search(query, filters) {
|
|
971
|
+
let series = await this.list({});
|
|
972
|
+
if (query) {
|
|
973
|
+
const lowerQuery = query.toLowerCase();
|
|
974
|
+
series = series.filter((s) => s.name?.toLowerCase().includes(lowerQuery) || s.description?.toLowerCase().includes(lowerQuery));
|
|
975
|
+
}
|
|
976
|
+
if (filters) {
|
|
977
|
+
if (filters.typeId) series = series.filter((s) => s.typeId === filters.typeId);
|
|
978
|
+
if (filters.organizerId) series = series.filter((s) => s.organizerId === filters.organizerId);
|
|
979
|
+
if (filters.startDate) {
|
|
980
|
+
const startDate = filters.startDate;
|
|
981
|
+
series = series.filter((s) => s.startDate && s.startDate >= startDate);
|
|
982
|
+
}
|
|
983
|
+
if (filters.endDate) {
|
|
984
|
+
const endDate = filters.endDate;
|
|
985
|
+
series = series.filter((s) => s.endDate && s.endDate <= endDate);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
return series;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Find all event series for a specific tenant
|
|
992
|
+
*
|
|
993
|
+
* @param tenantId - Tenant ID to filter by
|
|
994
|
+
* @returns Array of EventSeries instances for the tenant
|
|
995
|
+
*/
|
|
996
|
+
async findByTenant(tenantId) {
|
|
997
|
+
return this.list({ where: { tenantId } });
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Find all global event series (no tenant association).
|
|
1001
|
+
*
|
|
1002
|
+
* Routes through the shared tenant-global helper so it does not throw under
|
|
1003
|
+
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
1004
|
+
* flagged as an isolation violation). (#1600)
|
|
1005
|
+
*
|
|
1006
|
+
* @returns Array of EventSeries instances with no tenant
|
|
1007
|
+
*/
|
|
1008
|
+
async findGlobal() {
|
|
1009
|
+
return queryGlobal(this);
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Find event series for a tenant including global series.
|
|
1013
|
+
*
|
|
1014
|
+
* Fails closed if an active tenant context requests a different tenant's
|
|
1015
|
+
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
1016
|
+
*
|
|
1017
|
+
* @param tenantId - Tenant ID to filter by
|
|
1018
|
+
* @returns Array of EventSeries instances for the tenant and global series
|
|
1019
|
+
*/
|
|
1020
|
+
async findWithGlobals(tenantId) {
|
|
1021
|
+
return queryWithGlobals(this, tenantId, "EventSeries.findWithGlobals");
|
|
1022
|
+
}
|
|
1033
1023
|
};
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
], EventSeries.prototype, "tenantId", 2);
|
|
1037
|
-
__decorateClass$1([
|
|
1038
|
-
foreignKey("EventType")
|
|
1039
|
-
], EventSeries.prototype, "typeId", 2);
|
|
1040
|
-
__decorateClass$1([
|
|
1041
|
-
crossPackageRef("@happyvertical/smrt-profiles:Profile")
|
|
1042
|
-
], EventSeries.prototype, "organizerId", 2);
|
|
1043
|
-
EventSeries = __decorateClass$1([
|
|
1044
|
-
TenantScoped({ mode: "optional" }),
|
|
1045
|
-
smrt({
|
|
1046
|
-
tableStrategy: "sti",
|
|
1047
|
-
api: { include: ["list", "get", "create", "update", "delete"] },
|
|
1048
|
-
mcp: { include: ["list", "get", "create", "update"] },
|
|
1049
|
-
cli: true
|
|
1050
|
-
})
|
|
1051
|
-
], EventSeries);
|
|
1052
|
-
class EventSeriesCollection extends SmrtCollection {
|
|
1053
|
-
static _itemClass = EventSeries;
|
|
1054
|
-
/**
|
|
1055
|
-
* Get series by organizer
|
|
1056
|
-
*
|
|
1057
|
-
* @param organizerId - Profile ID of the organizer
|
|
1058
|
-
* @returns Array of EventSeries instances
|
|
1059
|
-
*/
|
|
1060
|
-
async getByOrganizer(organizerId) {
|
|
1061
|
-
return await this.list({ where: { organizerId } });
|
|
1062
|
-
}
|
|
1063
|
-
/**
|
|
1064
|
-
* Get currently active series
|
|
1065
|
-
*
|
|
1066
|
-
* @returns Array of EventSeries instances active today
|
|
1067
|
-
*/
|
|
1068
|
-
async getActive() {
|
|
1069
|
-
const allSeries = await this.list({});
|
|
1070
|
-
const now = /* @__PURE__ */ new Date();
|
|
1071
|
-
return allSeries.filter((series) => {
|
|
1072
|
-
if (series.startDate && now < series.startDate) return false;
|
|
1073
|
-
if (series.endDate && now > series.endDate) return false;
|
|
1074
|
-
return true;
|
|
1075
|
-
});
|
|
1076
|
-
}
|
|
1077
|
-
/**
|
|
1078
|
-
* Get upcoming series
|
|
1079
|
-
*
|
|
1080
|
-
* @param limit - Maximum number of series to return
|
|
1081
|
-
* @returns Array of EventSeries instances starting in the future
|
|
1082
|
-
*/
|
|
1083
|
-
async getUpcoming(limit) {
|
|
1084
|
-
const allSeries = await this.list({});
|
|
1085
|
-
const now = /* @__PURE__ */ new Date();
|
|
1086
|
-
const upcoming = allSeries.filter((series) => series.startDate && series.startDate > now).sort((a, b) => {
|
|
1087
|
-
if (!a.startDate || !b.startDate) return 0;
|
|
1088
|
-
return a.startDate.getTime() - b.startDate.getTime();
|
|
1089
|
-
});
|
|
1090
|
-
return limit ? upcoming.slice(0, limit) : upcoming;
|
|
1091
|
-
}
|
|
1092
|
-
/**
|
|
1093
|
-
* Get series by type
|
|
1094
|
-
*
|
|
1095
|
-
* @param typeId - EventType ID
|
|
1096
|
-
* @returns Array of EventSeries instances
|
|
1097
|
-
*/
|
|
1098
|
-
async getByType(typeId) {
|
|
1099
|
-
return await this.list({ where: { typeId } });
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
* Search series with filters
|
|
1103
|
-
*
|
|
1104
|
-
* @param query - Search query for name/description
|
|
1105
|
-
* @param filters - Additional filter criteria
|
|
1106
|
-
* @returns Array of matching EventSeries instances
|
|
1107
|
-
*/
|
|
1108
|
-
async search(query, filters) {
|
|
1109
|
-
let series = await this.list({});
|
|
1110
|
-
if (query) {
|
|
1111
|
-
const lowerQuery = query.toLowerCase();
|
|
1112
|
-
series = series.filter(
|
|
1113
|
-
(s) => s.name?.toLowerCase().includes(lowerQuery) || s.description?.toLowerCase().includes(lowerQuery)
|
|
1114
|
-
);
|
|
1115
|
-
}
|
|
1116
|
-
if (filters) {
|
|
1117
|
-
if (filters.typeId) {
|
|
1118
|
-
series = series.filter((s) => s.typeId === filters.typeId);
|
|
1119
|
-
}
|
|
1120
|
-
if (filters.organizerId) {
|
|
1121
|
-
series = series.filter((s) => s.organizerId === filters.organizerId);
|
|
1122
|
-
}
|
|
1123
|
-
if (filters.startDate) {
|
|
1124
|
-
const startDate = filters.startDate;
|
|
1125
|
-
series = series.filter((s) => s.startDate && s.startDate >= startDate);
|
|
1126
|
-
}
|
|
1127
|
-
if (filters.endDate) {
|
|
1128
|
-
const endDate = filters.endDate;
|
|
1129
|
-
series = series.filter((s) => s.endDate && s.endDate <= endDate);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
return series;
|
|
1133
|
-
}
|
|
1134
|
-
// ============================================
|
|
1135
|
-
// Tenant Helper Methods
|
|
1136
|
-
// ============================================
|
|
1137
|
-
/**
|
|
1138
|
-
* Find all event series for a specific tenant
|
|
1139
|
-
*
|
|
1140
|
-
* @param tenantId - Tenant ID to filter by
|
|
1141
|
-
* @returns Array of EventSeries instances for the tenant
|
|
1142
|
-
*/
|
|
1143
|
-
async findByTenant(tenantId2) {
|
|
1144
|
-
return this.list({ where: { tenantId: tenantId2 } });
|
|
1145
|
-
}
|
|
1146
|
-
/**
|
|
1147
|
-
* Find all global event series (no tenant association).
|
|
1148
|
-
*
|
|
1149
|
-
* Routes through the shared tenant-global helper so it does not throw under
|
|
1150
|
-
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
1151
|
-
* flagged as an isolation violation). (#1600)
|
|
1152
|
-
*
|
|
1153
|
-
* @returns Array of EventSeries instances with no tenant
|
|
1154
|
-
*/
|
|
1155
|
-
async findGlobal() {
|
|
1156
|
-
return queryGlobal(this);
|
|
1157
|
-
}
|
|
1158
|
-
/**
|
|
1159
|
-
* Find event series for a tenant including global series.
|
|
1160
|
-
*
|
|
1161
|
-
* Fails closed if an active tenant context requests a different tenant's
|
|
1162
|
-
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
1163
|
-
*
|
|
1164
|
-
* @param tenantId - Tenant ID to filter by
|
|
1165
|
-
* @returns Array of EventSeries instances for the tenant and global series
|
|
1166
|
-
*/
|
|
1167
|
-
async findWithGlobals(tenantId2) {
|
|
1168
|
-
return queryWithGlobals(
|
|
1169
|
-
this,
|
|
1170
|
-
tenantId2,
|
|
1171
|
-
"EventSeries.findWithGlobals"
|
|
1172
|
-
);
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
const EventSeriesCollection$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1176
|
-
__proto__: null,
|
|
1177
|
-
EventSeriesCollection
|
|
1178
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
1024
|
+
//#endregion
|
|
1025
|
+
//#region src/models/EventType.ts
|
|
1179
1026
|
var __defProp = Object.defineProperty;
|
|
1180
1027
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1181
1028
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
if (kind && result) __defProp(target, key, result);
|
|
1187
|
-
return result;
|
|
1029
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
1030
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
1031
|
+
if (kind && result) __defProp(target, key, result);
|
|
1032
|
+
return result;
|
|
1188
1033
|
};
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
*
|
|
1260
|
-
* @param data - Participant schema object to store
|
|
1261
|
-
*/
|
|
1262
|
-
setParticipantSchema(data) {
|
|
1263
|
-
this.participantSchema = JSON.stringify(data);
|
|
1264
|
-
}
|
|
1265
|
-
/**
|
|
1266
|
-
* Convenience method for slug-based lookup
|
|
1267
|
-
*
|
|
1268
|
-
* @param slug - The slug to search for
|
|
1269
|
-
* @returns EventType instance or null if not found
|
|
1270
|
-
*/
|
|
1271
|
-
static async getBySlug(_slug) {
|
|
1272
|
-
return null;
|
|
1273
|
-
}
|
|
1034
|
+
var EventType = class extends SmrtObject {
|
|
1035
|
+
tenantId = null;
|
|
1036
|
+
name = "";
|
|
1037
|
+
description = "";
|
|
1038
|
+
schema = "";
|
|
1039
|
+
participantSchema = "";
|
|
1040
|
+
createdAt = /* @__PURE__ */ new Date();
|
|
1041
|
+
updatedAt = /* @__PURE__ */ new Date();
|
|
1042
|
+
constructor(options = {}) {
|
|
1043
|
+
super(options);
|
|
1044
|
+
if (options.name) this.name = options.name;
|
|
1045
|
+
if (options.description !== void 0) this.description = options.description;
|
|
1046
|
+
if (options.schema !== void 0) if (typeof options.schema === "string") this.schema = options.schema;
|
|
1047
|
+
else this.schema = JSON.stringify(options.schema);
|
|
1048
|
+
if (options.participantSchema !== void 0) if (typeof options.participantSchema === "string") this.participantSchema = options.participantSchema;
|
|
1049
|
+
else this.participantSchema = JSON.stringify(options.participantSchema);
|
|
1050
|
+
if (options.createdAt) this.createdAt = options.createdAt;
|
|
1051
|
+
if (options.updatedAt) this.updatedAt = options.updatedAt;
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Get schema as parsed object
|
|
1055
|
+
*
|
|
1056
|
+
* @returns Parsed schema object or empty object if no schema
|
|
1057
|
+
*/
|
|
1058
|
+
getSchema() {
|
|
1059
|
+
if (!this.schema) return {};
|
|
1060
|
+
try {
|
|
1061
|
+
return JSON.parse(this.schema);
|
|
1062
|
+
} catch {
|
|
1063
|
+
return {};
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Set schema from object
|
|
1068
|
+
*
|
|
1069
|
+
* @param data - Schema object to store
|
|
1070
|
+
*/
|
|
1071
|
+
setSchema(data) {
|
|
1072
|
+
this.schema = JSON.stringify(data);
|
|
1073
|
+
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Get participant schema as parsed object
|
|
1076
|
+
*
|
|
1077
|
+
* @returns Parsed participant schema object or empty object
|
|
1078
|
+
*/
|
|
1079
|
+
getParticipantSchema() {
|
|
1080
|
+
if (!this.participantSchema) return {};
|
|
1081
|
+
try {
|
|
1082
|
+
return JSON.parse(this.participantSchema);
|
|
1083
|
+
} catch {
|
|
1084
|
+
return {};
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Set participant schema from object
|
|
1089
|
+
*
|
|
1090
|
+
* @param data - Participant schema object to store
|
|
1091
|
+
*/
|
|
1092
|
+
setParticipantSchema(data) {
|
|
1093
|
+
this.participantSchema = JSON.stringify(data);
|
|
1094
|
+
}
|
|
1095
|
+
/**
|
|
1096
|
+
* Convenience method for slug-based lookup
|
|
1097
|
+
*
|
|
1098
|
+
* @param slug - The slug to search for
|
|
1099
|
+
* @returns EventType instance or null if not found
|
|
1100
|
+
*/
|
|
1101
|
+
static async getBySlug(_slug) {
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1274
1104
|
};
|
|
1275
|
-
__decorateClass([
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1105
|
+
__decorateClass([tenantId({ nullable: true })], EventType.prototype, "tenantId", 2);
|
|
1106
|
+
__decorateClass([field({ required: true })], EventType.prototype, "name", 2);
|
|
1107
|
+
EventType = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
1108
|
+
tableStrategy: "sti",
|
|
1109
|
+
api: { include: [
|
|
1110
|
+
"list",
|
|
1111
|
+
"get",
|
|
1112
|
+
"create",
|
|
1113
|
+
"update",
|
|
1114
|
+
"delete"
|
|
1115
|
+
] },
|
|
1116
|
+
mcp: { include: [
|
|
1117
|
+
"list",
|
|
1118
|
+
"get",
|
|
1119
|
+
"create"
|
|
1120
|
+
] },
|
|
1121
|
+
cli: true
|
|
1122
|
+
})], EventType);
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/collections/EventTypeCollection.ts
|
|
1125
|
+
var EventTypeCollection_exports = /* @__PURE__ */ __exportAll({ EventTypeCollection: () => EventTypeCollection });
|
|
1126
|
+
var EventTypeCollection = class extends SmrtCollection {
|
|
1127
|
+
static _itemClass = EventType;
|
|
1128
|
+
/**
|
|
1129
|
+
* Get or create an event type by slug
|
|
1130
|
+
*
|
|
1131
|
+
* @param slug - EventType slug (e.g., 'basketball-game', 'concert')
|
|
1132
|
+
* @param name - Optional display name (defaults to capitalized slug)
|
|
1133
|
+
* @returns EventType instance
|
|
1134
|
+
*/
|
|
1135
|
+
async getOrCreate(slug, name) {
|
|
1136
|
+
const existing = await this.get({ slug });
|
|
1137
|
+
if (existing) return existing;
|
|
1138
|
+
const displayName = name || slug.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
|
|
1139
|
+
return await this.create({
|
|
1140
|
+
slug,
|
|
1141
|
+
name: displayName
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Get an event type by slug
|
|
1146
|
+
*
|
|
1147
|
+
* @param slug - EventType slug to search for
|
|
1148
|
+
* @returns EventType instance or null if not found
|
|
1149
|
+
*/
|
|
1150
|
+
async getBySlug(slug) {
|
|
1151
|
+
return await this.get({ slug });
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Initialize default event types
|
|
1155
|
+
*
|
|
1156
|
+
* Creates common event types if they don't exist:
|
|
1157
|
+
* - Sports: game, period, goal, assist, penalty
|
|
1158
|
+
* - Entertainment: concert, performance, song
|
|
1159
|
+
* - Professional: conference, session, presentation, workshop
|
|
1160
|
+
* - Community: meeting, agenda-item, motion, vote
|
|
1161
|
+
*
|
|
1162
|
+
* @returns Array of created/existing event types
|
|
1163
|
+
*/
|
|
1164
|
+
async initializeDefaults() {
|
|
1165
|
+
const defaults = [
|
|
1166
|
+
{
|
|
1167
|
+
slug: "game",
|
|
1168
|
+
name: "Game"
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
slug: "match",
|
|
1172
|
+
name: "Match"
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
slug: "period",
|
|
1176
|
+
name: "Period"
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
slug: "quarter",
|
|
1180
|
+
name: "Quarter"
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
slug: "inning",
|
|
1184
|
+
name: "Inning"
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
slug: "goal",
|
|
1188
|
+
name: "Goal"
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
slug: "assist",
|
|
1192
|
+
name: "Assist"
|
|
1193
|
+
},
|
|
1194
|
+
{
|
|
1195
|
+
slug: "penalty",
|
|
1196
|
+
name: "Penalty"
|
|
1197
|
+
},
|
|
1198
|
+
{
|
|
1199
|
+
slug: "substitution",
|
|
1200
|
+
name: "Substitution"
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
slug: "concert",
|
|
1204
|
+
name: "Concert"
|
|
1205
|
+
},
|
|
1206
|
+
{
|
|
1207
|
+
slug: "performance",
|
|
1208
|
+
name: "Performance"
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
slug: "set",
|
|
1212
|
+
name: "Set"
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
slug: "song",
|
|
1216
|
+
name: "Song"
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
slug: "theater",
|
|
1220
|
+
name: "Theater"
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
slug: "show",
|
|
1224
|
+
name: "Show"
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
slug: "conference",
|
|
1228
|
+
name: "Conference"
|
|
1229
|
+
},
|
|
1230
|
+
{
|
|
1231
|
+
slug: "session",
|
|
1232
|
+
name: "Session"
|
|
1233
|
+
},
|
|
1234
|
+
{
|
|
1235
|
+
slug: "presentation",
|
|
1236
|
+
name: "Presentation"
|
|
1237
|
+
},
|
|
1238
|
+
{
|
|
1239
|
+
slug: "workshop",
|
|
1240
|
+
name: "Workshop"
|
|
1241
|
+
},
|
|
1242
|
+
{
|
|
1243
|
+
slug: "seminar",
|
|
1244
|
+
name: "Seminar"
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
slug: "keynote",
|
|
1248
|
+
name: "Keynote"
|
|
1249
|
+
},
|
|
1250
|
+
{
|
|
1251
|
+
slug: "panel",
|
|
1252
|
+
name: "Panel"
|
|
1253
|
+
},
|
|
1254
|
+
{
|
|
1255
|
+
slug: "meeting",
|
|
1256
|
+
name: "Meeting"
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
slug: "town-hall",
|
|
1260
|
+
name: "Town Hall"
|
|
1261
|
+
},
|
|
1262
|
+
{
|
|
1263
|
+
slug: "agenda-item",
|
|
1264
|
+
name: "Agenda Item"
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
slug: "motion",
|
|
1268
|
+
name: "Motion"
|
|
1269
|
+
},
|
|
1270
|
+
{
|
|
1271
|
+
slug: "amendment",
|
|
1272
|
+
name: "Amendment"
|
|
1273
|
+
},
|
|
1274
|
+
{
|
|
1275
|
+
slug: "vote",
|
|
1276
|
+
name: "Vote"
|
|
1277
|
+
},
|
|
1278
|
+
{
|
|
1279
|
+
slug: "discussion",
|
|
1280
|
+
name: "Discussion"
|
|
1281
|
+
},
|
|
1282
|
+
{
|
|
1283
|
+
slug: "event",
|
|
1284
|
+
name: "Event"
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
slug: "activity",
|
|
1288
|
+
name: "Activity"
|
|
1289
|
+
},
|
|
1290
|
+
{
|
|
1291
|
+
slug: "action",
|
|
1292
|
+
name: "Action"
|
|
1293
|
+
}
|
|
1294
|
+
];
|
|
1295
|
+
const types = [];
|
|
1296
|
+
for (const def of defaults) {
|
|
1297
|
+
const type = await this.getOrCreate(def.slug, def.name);
|
|
1298
|
+
types.push(type);
|
|
1299
|
+
}
|
|
1300
|
+
return types;
|
|
1301
|
+
}
|
|
1302
|
+
/**
|
|
1303
|
+
* Find all event types for a specific tenant
|
|
1304
|
+
*
|
|
1305
|
+
* @param tenantId - Tenant ID to filter by
|
|
1306
|
+
* @returns Array of EventType instances for the tenant
|
|
1307
|
+
*/
|
|
1308
|
+
async findByTenant(tenantId) {
|
|
1309
|
+
return this.list({ where: { tenantId } });
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Find all global event types (no tenant association).
|
|
1313
|
+
*
|
|
1314
|
+
* Routes through the shared tenant-global helper so it does not throw under
|
|
1315
|
+
* an active tenant context (an explicit `tenant_id IS NULL` filter would be
|
|
1316
|
+
* flagged as an isolation violation). (#1600)
|
|
1317
|
+
*
|
|
1318
|
+
* @returns Array of EventType instances with no tenant
|
|
1319
|
+
*/
|
|
1320
|
+
async findGlobal() {
|
|
1321
|
+
return queryGlobal(this);
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Find event types for a tenant including global types.
|
|
1325
|
+
*
|
|
1326
|
+
* Fails closed if an active tenant context requests a different tenant's
|
|
1327
|
+
* rows; the admin/system path keeps the cross-tenant capability. (#1600)
|
|
1328
|
+
*
|
|
1329
|
+
* @param tenantId - Tenant ID to filter by
|
|
1330
|
+
* @returns Array of EventType instances for the tenant and global types
|
|
1331
|
+
*/
|
|
1332
|
+
async findWithGlobals(tenantId) {
|
|
1333
|
+
return queryWithGlobals(this, tenantId, "EventType.findWithGlobals");
|
|
1334
|
+
}
|
|
1446
1335
|
};
|
|
1447
|
-
//#
|
|
1336
|
+
//#endregion
|
|
1337
|
+
export { EVENTS_MODULE_META, EVENTS_UI_SLOTS, Event, EventAsset, EventAssetCollection, EventCollection, EventParticipant, EventParticipantCollection, EventSeries, EventSeriesCollection, EventType, EventTypeCollection, calculateDuration, calculateNextOccurrence, checkSchedulingConflict, formatDuration, formatEventDateRange, generateEventSlug, getEventStatusFromDates, isEventNow, parseRecurrencePattern, sortEventsByDate, validateEventStatus };
|
|
1338
|
+
|
|
1339
|
+
//# sourceMappingURL=index.js.map
|