@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 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.registerPackageManifest(
7
- new URL("./manifest.json", import.meta.url)
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
13
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
14
- if (decorator = decorators[i])
15
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
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
- let EventAsset = class extends SmrtObject {
20
- tenantId = null;
21
- eventId = "";
22
- assetId = "";
23
- relationship = "attachment";
24
- sortOrder = 0;
25
- constructor(options = {}) {
26
- super(options);
27
- if (options.eventId) this.eventId = options.eventId;
28
- if (options.assetId) this.assetId = options.assetId;
29
- if (options.relationship) this.relationship = options.relationship;
30
- if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
31
- if (options.tenantId !== void 0) this.tenantId = options.tenantId;
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
- tenantId({ nullable: true })
36
- ], EventAsset.prototype, "tenantId", 2);
37
- __decorateClass$6([
38
- foreignKey("Event", { required: true })
39
- ], EventAsset.prototype, "eventId", 2);
40
- __decorateClass$6([
41
- crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })
42
- ], EventAsset.prototype, "assetId", 2);
43
- __decorateClass$6([
44
- field({ required: true })
45
- ], EventAsset.prototype, "relationship", 2);
46
- __decorateClass$6([
47
- field()
48
- ], EventAsset.prototype, "sortOrder", 2);
49
- EventAsset = __decorateClass$6([
50
- TenantScoped({ mode: "optional" }),
51
- smrt({
52
- tableName: "event_assets",
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, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
64
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
65
- if (decorator = decorators[i])
66
- result = decorator(result) || result;
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
- let EventAssetCollection = class extends SmrtJunction {
71
- leftField = "eventId";
72
- rightField = "assetId";
73
- eventCollectionPromise = null;
74
- async getEventCollection() {
75
- if (!this.eventCollectionPromise) {
76
- const { EventCollection: EventCollection2 } = await Promise.resolve().then(() => EventCollection$1);
77
- this.eventCollectionPromise = EventCollection2.create({ db: this.db });
78
- }
79
- return this.eventCollectionPromise;
80
- }
81
- async getAssets(eventId, relationship) {
82
- return getOwnedAssetsFromCollection(
83
- await this.getEventCollection(),
84
- eventId,
85
- relationship
86
- );
87
- }
88
- async addAsset(eventId, asset, relationship = "attachment", sortOrder = 0) {
89
- await addOwnedAssetFromCollection(
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
- smrt({
111
- api: false,
112
- mcp: false,
113
- cli: false
114
- })
115
- ], EventAssetCollection);
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
126
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
127
- if (decorator = decorators[i])
128
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
129
- if (kind && result) __defProp$4(target, key, result);
130
- return result;
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
- let Event = class extends SmrtHierarchical {
133
- tenantId = null;
134
- name = "";
135
- seriesId = "";
136
- typeId = "";
137
- placeId = "";
138
- // FK to Place (from @happyvertical/smrt-places)
139
- description = "";
140
- startDate = null;
141
- endDate = null;
142
- status = "scheduled";
143
- round = null;
144
- // Sequence/round number in series
145
- metadata = "";
146
- // JSON metadata (stored as text)
147
- externalId = "";
148
- // External system identifier
149
- source = "";
150
- // Source system
151
- // Timestamps
152
- createdAt = /* @__PURE__ */ new Date();
153
- updatedAt = /* @__PURE__ */ new Date();
154
- constructor(options = {}) {
155
- super(options);
156
- if (options.seriesId !== void 0) this.seriesId = options.seriesId;
157
- if (options.parentId !== void 0)
158
- this.parentId = options.parentId ?? null;
159
- if (options.typeId) this.typeId = options.typeId;
160
- if (options.placeId !== void 0) this.placeId = options.placeId;
161
- if (options.description !== void 0)
162
- this.description = options.description;
163
- if (options.startDate !== void 0)
164
- this.startDate = options.startDate || null;
165
- if (options.endDate !== void 0) this.endDate = options.endDate || null;
166
- if (options.status !== void 0) this.status = options.status;
167
- if (options.round !== void 0) this.round = options.round;
168
- if (options.externalId !== void 0) this.externalId = options.externalId;
169
- if (options.source !== void 0) this.source = options.source;
170
- if (options.metadata !== void 0) {
171
- if (typeof options.metadata === "string") {
172
- this.metadata = options.metadata;
173
- } else {
174
- this.metadata = JSON.stringify(options.metadata);
175
- }
176
- }
177
- if (options.createdAt) this.createdAt = options.createdAt;
178
- if (options.updatedAt) this.updatedAt = options.updatedAt;
179
- }
180
- /**
181
- * Get metadata as parsed object
182
- *
183
- * @returns Parsed metadata object or empty object
184
- */
185
- getMetadata() {
186
- if (!this.metadata) return {};
187
- try {
188
- return JSON.parse(this.metadata);
189
- } catch {
190
- return {};
191
- }
192
- }
193
- /**
194
- * Set metadata from object
195
- *
196
- * @param data - Metadata object to store
197
- */
198
- setMetadata(data) {
199
- this.metadata = JSON.stringify(data);
200
- }
201
- /**
202
- * Update metadata by merging with existing values
203
- *
204
- * @param updates - Partial metadata to merge
205
- */
206
- updateMetadata(updates) {
207
- const current = this.getMetadata();
208
- this.setMetadata({ ...current, ...updates });
209
- }
210
- /**
211
- * Update event status
212
- *
213
- * @param newStatus - New status to set
214
- */
215
- async updateStatus(newStatus) {
216
- this.status = newStatus;
217
- this.updatedAt = /* @__PURE__ */ new Date();
218
- await this.save();
219
- }
220
- /**
221
- * Get the series for this event
222
- *
223
- * @returns EventSeries instance or null
224
- */
225
- async getSeries() {
226
- if (!this.seriesId) return null;
227
- const { EventSeriesCollection: EventSeriesCollection2 } = await Promise.resolve().then(() => EventSeriesCollection$1);
228
- const collection = await EventSeriesCollection2.create(this.options);
229
- return await collection.get({ id: this.seriesId });
230
- }
231
- /**
232
- * Get the event type
233
- *
234
- * @returns EventType instance or null
235
- */
236
- async getType() {
237
- if (!this.typeId) return null;
238
- const { EventTypeCollection: EventTypeCollection2 } = await Promise.resolve().then(() => EventTypeCollection$1);
239
- const collection = await EventTypeCollection2.create(this.options);
240
- return await collection.get({ id: this.typeId });
241
- }
242
- /**
243
- * Get the place for this event
244
- *
245
- * @returns Place instance or null
246
- */
247
- async getPlace() {
248
- if (!this.placeId) return null;
249
- try {
250
- const { PlaceCollection } = await import("@happyvertical/smrt-places");
251
- const collection = await PlaceCollection.create(this.options);
252
- return await collection.get({ id: this.placeId });
253
- } catch {
254
- return null;
255
- }
256
- }
257
- // Hierarchy traversal (getParent / getChildren / getAncestors /
258
- // getDescendants / getHierarchy / moveTo) provided by SmrtHierarchical.
259
- /**
260
- * Get the root event (top-level ancestor) of this event's hierarchy.
261
- *
262
- * @returns Root event instance `this` when already root
263
- */
264
- async getRootEvent() {
265
- const ancestors = await this.getAncestors();
266
- return ancestors.length > 0 ? ancestors[0] : this;
267
- }
268
- /**
269
- * Get all participants for this event
270
- *
271
- * @returns Array of EventParticipant instances
272
- */
273
- async getParticipants() {
274
- const { EventParticipantCollection: EventParticipantCollection2 } = await Promise.resolve().then(() => EventParticipantCollection$1);
275
- const collection = await EventParticipantCollection2.create(this.options);
276
- return await collection.list({ where: { eventId: this.id } });
277
- }
278
- async getEventAssetCollection() {
279
- const { EventAssetCollection: EventAssetCollection2 } = await Promise.resolve().then(() => EventAssetCollection$1);
280
- return EventAssetCollection2.create({ db: this.db });
281
- }
282
- async getAssets(relationship) {
283
- if (!this.id) {
284
- return [];
285
- }
286
- const eventAssets = await this.getEventAssetCollection();
287
- const linkedAssets = await eventAssets.byLeft(
288
- this.id,
289
- relationship ? { relationship } : {}
290
- );
291
- return resolveOwnedAssetsById(
292
- this.db,
293
- linkedAssets.map((link) => link.assetId),
294
- this.tenantId
295
- );
296
- }
297
- async addAsset(asset, relationship = "attachment", sortOrder = 0) {
298
- if (!this.id || !asset.id) {
299
- throw new Error("Cannot associate unsaved event or asset");
300
- }
301
- assertValidOwnedAssetRelationship(relationship);
302
- assertValidOwnedAssetSortOrder(sortOrder);
303
- const eventAssets = await this.getEventAssetCollection();
304
- await eventAssets.attach(this.id, asset.id, {
305
- relationship,
306
- sortOrder,
307
- tenantId: this.tenantId
308
- });
309
- }
310
- async removeAsset(assetId, relationship) {
311
- if (!this.id) {
312
- return;
313
- }
314
- const eventAssets = await this.getEventAssetCollection();
315
- await eventAssets.detach(
316
- this.id,
317
- assetId,
318
- relationship ? { relationship } : {}
319
- );
320
- }
321
- /**
322
- * Check if event is currently in progress
323
- *
324
- * @returns True if current time is between start and end
325
- */
326
- isInProgress() {
327
- if (this.status !== "in_progress") return false;
328
- const now = /* @__PURE__ */ new Date();
329
- if (this.startDate && now < this.startDate) return false;
330
- if (this.endDate && now > this.endDate) return false;
331
- return true;
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
- __decorateClass$4([
343
- tenantId({ nullable: true })
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
584
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
585
- if (decorator = decorators[i])
586
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
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
- let EventParticipant = class extends SmrtObject {
591
- tenantId = null;
592
- eventId = "";
593
- profileId = "";
594
- // FK to Profile (from @happyvertical/smrt-profiles)
595
- role = "";
596
- // Participant role (ParticipantRole or custom)
597
- placement = null;
598
- // Numeric position/placement
599
- groupId = "";
600
- // Optional grouping (e.g., team ID for individual players)
601
- metadata = "";
602
- // JSON metadata (stored as text)
603
- externalId = "";
604
- // External system identifier
605
- source = "";
606
- // Source system
607
- // Timestamps
608
- createdAt = /* @__PURE__ */ new Date();
609
- updatedAt = /* @__PURE__ */ new Date();
610
- constructor(options = {}) {
611
- super(options);
612
- if (options.eventId) this.eventId = options.eventId;
613
- if (options.profileId) this.profileId = options.profileId;
614
- if (options.role !== void 0) this.role = options.role;
615
- if (options.placement !== void 0) this.placement = options.placement;
616
- if (options.groupId !== void 0) this.groupId = options.groupId;
617
- if (options.externalId !== void 0) this.externalId = options.externalId;
618
- if (options.source !== void 0) this.source = options.source;
619
- if (options.metadata !== void 0) {
620
- if (typeof options.metadata === "string") {
621
- this.metadata = options.metadata;
622
- } else {
623
- this.metadata = JSON.stringify(options.metadata);
624
- }
625
- }
626
- if (options.createdAt) this.createdAt = options.createdAt;
627
- if (options.updatedAt) this.updatedAt = options.updatedAt;
628
- }
629
- /**
630
- * Get metadata as parsed object
631
- *
632
- * @returns Parsed metadata object or empty object
633
- */
634
- getMetadata() {
635
- if (!this.metadata) return {};
636
- try {
637
- return JSON.parse(this.metadata);
638
- } catch {
639
- return {};
640
- }
641
- }
642
- /**
643
- * Set metadata from object
644
- *
645
- * @param data - Metadata object to store
646
- */
647
- setMetadata(data) {
648
- this.metadata = JSON.stringify(data);
649
- }
650
- /**
651
- * Update metadata by merging with existing values
652
- *
653
- * @param updates - Partial metadata to merge
654
- */
655
- updateMetadata(updates) {
656
- const current = this.getMetadata();
657
- this.setMetadata({ ...current, ...updates });
658
- }
659
- /**
660
- * Get the event for this participant
661
- *
662
- * @returns Event instance or null
663
- */
664
- async getEvent() {
665
- if (!this.eventId) return null;
666
- const { EventCollection: EventCollection2 } = await Promise.resolve().then(() => EventCollection$1);
667
- const collection = await EventCollection2.create(this.options);
668
- return await collection.get({ id: this.eventId });
669
- }
670
- /**
671
- * Get the profile for this participant
672
- *
673
- * @returns Profile instance or null
674
- */
675
- async getProfile() {
676
- if (!this.profileId) return null;
677
- try {
678
- const { ProfileCollection } = await import("@happyvertical/smrt-profiles");
679
- const collection = await ProfileCollection.create(this.options);
680
- return await collection.get({ id: this.profileId });
681
- } catch {
682
- return null;
683
- }
684
- }
685
- /**
686
- * Get group participants (others with same groupId)
687
- *
688
- * @returns Array of EventParticipant instances
689
- */
690
- async getGroupParticipants() {
691
- if (!this.groupId) return [];
692
- const { EventParticipantCollection: EventParticipantCollection2 } = await Promise.resolve().then(() => EventParticipantCollection$1);
693
- const collection = await EventParticipantCollection2.create(this.options);
694
- const participants = await collection.list({
695
- where: { eventId: this.eventId, groupId: this.groupId }
696
- });
697
- return participants.filter((p) => p.id !== this.id);
698
- }
699
- /**
700
- * Check if this is a home participant (placement = 0)
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
- tenantId({ nullable: true })
718
- ], EventParticipant.prototype, "tenantId", 2);
719
- __decorateClass$3([
720
- foreignKey("Event")
721
- ], EventParticipant.prototype, "eventId", 2);
722
- __decorateClass$3([
723
- crossPackageRef("@happyvertical/smrt-profiles:Profile")
724
- ], EventParticipant.prototype, "profileId", 2);
725
- EventParticipant = __decorateClass$3([
726
- TenantScoped({ mode: "optional" }),
727
- smrt({
728
- // Junction table - uses event_id + profile_id + role as natural key
729
- // instead of slug-based conflict columns
730
- conflictColumns: ["event_id", "profile_id", "role"],
731
- api: { include: ["list", "get", "create", "update", "delete"] },
732
- mcp: { include: ["list", "get", "create", "update"] },
733
- cli: true
734
- })
735
- ], EventParticipant);
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, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
741
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
742
- if (decorator = decorators[i])
743
- result = decorator(result) || result;
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
- let EventParticipantCollection = class extends SmrtJunction {
748
- leftField = "eventId";
749
- rightField = "profileId";
750
- // EventParticipant has no sortOrder column; `placement` is domain ordering
751
- // (0=home, 1=away) and must not be auto-assigned by setLinks.
752
- sortField = null;
753
- positionField = null;
754
- // ============================================
755
- // Domain helpers
756
- // ============================================
757
- /**
758
- * Get participants ordered by placement (nulls last).
759
- */
760
- async getByPlacement(eventId) {
761
- const participants = await this.byLeft(eventId);
762
- return participants.sort((a, b) => {
763
- if (a.placement === null && b.placement === null) return 0;
764
- if (a.placement === null) return 1;
765
- if (b.placement === null) return -1;
766
- return a.placement - b.placement;
767
- });
768
- }
769
- /**
770
- * Get participants by group within an event.
771
- */
772
- async getByGroup(eventId, groupId) {
773
- return this.byLeft(eventId, { groupId });
774
- }
775
- /**
776
- * Get the home participant(s) — placement = 0.
777
- */
778
- async getHome(eventId) {
779
- return this.byLeft(eventId, { placement: 0 });
780
- }
781
- /**
782
- * Get the away participant(s) — placement = 1.
783
- */
784
- async getAway(eventId) {
785
- return this.byLeft(eventId, { placement: 1 });
786
- }
787
- /**
788
- * Search participants with optional filters.
789
- */
790
- async search(filters) {
791
- let participants = await this.list({});
792
- if (filters.eventId) {
793
- participants = participants.filter((p) => p.eventId === filters.eventId);
794
- }
795
- if (filters.profileId) {
796
- participants = participants.filter(
797
- (p) => p.profileId === filters.profileId
798
- );
799
- }
800
- if (filters.role) {
801
- participants = participants.filter((p) => p.role === filters.role);
802
- }
803
- if (filters.groupId) {
804
- participants = participants.filter((p) => p.groupId === filters.groupId);
805
- }
806
- return participants;
807
- }
808
- /**
809
- * Get participation statistics for a profile, optionally filtered by event type.
810
- */
811
- async getParticipantStats(profileId, eventTypeId) {
812
- const participants = await this.byRight(profileId);
813
- let filteredParticipants = participants;
814
- if (eventTypeId) {
815
- filteredParticipants = [];
816
- for (const participant of participants) {
817
- const event = await participant.getEvent();
818
- if (event && event.typeId === eventTypeId) {
819
- filteredParticipants.push(participant);
820
- }
821
- }
822
- }
823
- const byRole = {};
824
- const byPlacement = {};
825
- for (const participant of filteredParticipants) {
826
- byRole[participant.role] = (byRole[participant.role] || 0) + 1;
827
- if (participant.placement !== null) {
828
- byPlacement[participant.placement] = (byPlacement[participant.placement] || 0) + 1;
829
- }
830
- }
831
- return {
832
- totalEvents: filteredParticipants.length,
833
- byRole,
834
- byPlacement
835
- };
836
- }
837
- // ============================================
838
- // Tenant helpers
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
- smrt()
870
- ], EventParticipantCollection);
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
881
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
882
- if (decorator = decorators[i])
883
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
884
- if (kind && result) __defProp$1(target, key, result);
885
- return result;
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
- let EventSeries = class extends SmrtObject {
888
- tenantId = null;
889
- name = "";
890
- typeId = "";
891
- organizerId = "";
892
- // FK to Profile (from @happyvertical/smrt-profiles)
893
- description = "";
894
- startDate = null;
895
- endDate = null;
896
- recurrence = "";
897
- // JSON recurrence pattern (stored as text)
898
- metadata = "";
899
- // JSON metadata (stored as text)
900
- externalId = "";
901
- // External system identifier
902
- source = "";
903
- // Source system (e.g., 'ticketmaster', 'espn')
904
- // Timestamps
905
- createdAt = /* @__PURE__ */ new Date();
906
- updatedAt = /* @__PURE__ */ new Date();
907
- constructor(options = {}) {
908
- super(options);
909
- if (options.typeId) this.typeId = options.typeId;
910
- if (options.organizerId) this.organizerId = options.organizerId;
911
- if (options.description !== void 0)
912
- this.description = options.description;
913
- if (options.startDate !== void 0)
914
- this.startDate = options.startDate || null;
915
- if (options.endDate !== void 0) this.endDate = options.endDate || null;
916
- if (options.externalId !== void 0) this.externalId = options.externalId;
917
- if (options.source !== void 0) this.source = options.source;
918
- if (options.recurrence !== void 0) {
919
- if (typeof options.recurrence === "string") {
920
- this.recurrence = options.recurrence;
921
- } else {
922
- this.recurrence = JSON.stringify(options.recurrence);
923
- }
924
- }
925
- if (options.metadata !== void 0) {
926
- if (typeof options.metadata === "string") {
927
- this.metadata = options.metadata;
928
- } else {
929
- this.metadata = JSON.stringify(options.metadata);
930
- }
931
- }
932
- if (options.createdAt) this.createdAt = options.createdAt;
933
- if (options.updatedAt) this.updatedAt = options.updatedAt;
934
- }
935
- /**
936
- * Get recurrence pattern as parsed object
937
- *
938
- * @returns Parsed recurrence pattern or null
939
- */
940
- getRecurrence() {
941
- if (!this.recurrence) return null;
942
- try {
943
- return JSON.parse(this.recurrence);
944
- } catch {
945
- return null;
946
- }
947
- }
948
- /**
949
- * Set recurrence pattern from object
950
- *
951
- * @param pattern - Recurrence pattern to store
952
- */
953
- setRecurrence(pattern) {
954
- this.recurrence = JSON.stringify(pattern);
955
- }
956
- /**
957
- * Get metadata as parsed object
958
- *
959
- * @returns Parsed metadata object or empty object
960
- */
961
- getMetadata() {
962
- if (!this.metadata) return {};
963
- try {
964
- return JSON.parse(this.metadata);
965
- } catch {
966
- return {};
967
- }
968
- }
969
- /**
970
- * Set metadata from object
971
- *
972
- * @param data - Metadata object to store
973
- */
974
- setMetadata(data) {
975
- this.metadata = JSON.stringify(data);
976
- }
977
- /**
978
- * Update metadata by merging with existing values
979
- *
980
- * @param updates - Partial metadata to merge
981
- */
982
- updateMetadata(updates) {
983
- const current = this.getMetadata();
984
- this.setMetadata({ ...current, ...updates });
985
- }
986
- /**
987
- * Get the event type for this series
988
- *
989
- * @returns EventType instance or null
990
- */
991
- async getType() {
992
- if (!this.typeId) return null;
993
- const { EventTypeCollection: EventTypeCollection2 } = await Promise.resolve().then(() => EventTypeCollection$1);
994
- const collection = await EventTypeCollection2.create(this.options);
995
- return await collection.get({ id: this.typeId });
996
- }
997
- /**
998
- * Get the organizer profile for this series
999
- *
1000
- * @returns Profile instance or null
1001
- */
1002
- async getOrganizer() {
1003
- if (!this.organizerId) return null;
1004
- try {
1005
- const { ProfileCollection } = await import("@happyvertical/smrt-profiles");
1006
- const collection = await ProfileCollection.create(this.options);
1007
- return await collection.get({ id: this.organizerId });
1008
- } catch {
1009
- return null;
1010
- }
1011
- }
1012
- /**
1013
- * Get all events in this series
1014
- *
1015
- * @returns Array of Event instances
1016
- */
1017
- async getEvents() {
1018
- const { EventCollection: EventCollection2 } = await Promise.resolve().then(() => EventCollection$1);
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
- __decorateClass$1([
1035
- tenantId({ nullable: true })
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
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
1183
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
1184
- if (decorator = decorators[i])
1185
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
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
- let EventType = class extends SmrtObject {
1190
- tenantId = null;
1191
- name = "";
1192
- description = "";
1193
- // Optional description
1194
- schema = "";
1195
- // JSON schema for event metadata (stored as text)
1196
- participantSchema = "";
1197
- // JSON schema for participant metadata (stored as text)
1198
- // Timestamps
1199
- createdAt = /* @__PURE__ */ new Date();
1200
- updatedAt = /* @__PURE__ */ new Date();
1201
- constructor(options = {}) {
1202
- super(options);
1203
- if (options.name) this.name = options.name;
1204
- if (options.description !== void 0)
1205
- this.description = options.description;
1206
- if (options.schema !== void 0) {
1207
- if (typeof options.schema === "string") {
1208
- this.schema = options.schema;
1209
- } else {
1210
- this.schema = JSON.stringify(options.schema);
1211
- }
1212
- }
1213
- if (options.participantSchema !== void 0) {
1214
- if (typeof options.participantSchema === "string") {
1215
- this.participantSchema = options.participantSchema;
1216
- } else {
1217
- this.participantSchema = JSON.stringify(options.participantSchema);
1218
- }
1219
- }
1220
- if (options.createdAt) this.createdAt = options.createdAt;
1221
- if (options.updatedAt) this.updatedAt = options.updatedAt;
1222
- }
1223
- /**
1224
- * Get schema as parsed object
1225
- *
1226
- * @returns Parsed schema object or empty object if no schema
1227
- */
1228
- getSchema() {
1229
- if (!this.schema) return {};
1230
- try {
1231
- return JSON.parse(this.schema);
1232
- } catch {
1233
- return {};
1234
- }
1235
- }
1236
- /**
1237
- * Set schema from object
1238
- *
1239
- * @param data - Schema object to store
1240
- */
1241
- setSchema(data) {
1242
- this.schema = JSON.stringify(data);
1243
- }
1244
- /**
1245
- * Get participant schema as parsed object
1246
- *
1247
- * @returns Parsed participant schema object or empty object
1248
- */
1249
- getParticipantSchema() {
1250
- if (!this.participantSchema) return {};
1251
- try {
1252
- return JSON.parse(this.participantSchema);
1253
- } catch {
1254
- return {};
1255
- }
1256
- }
1257
- /**
1258
- * Set participant schema from object
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
- tenantId({ nullable: true })
1277
- ], EventType.prototype, "tenantId", 2);
1278
- __decorateClass([
1279
- field({ required: true })
1280
- ], EventType.prototype, "name", 2);
1281
- EventType = __decorateClass([
1282
- TenantScoped({ mode: "optional" }),
1283
- smrt({
1284
- tableStrategy: "sti",
1285
- api: { include: ["list", "get", "create", "update", "delete"] },
1286
- mcp: { include: ["list", "get", "create"] },
1287
- cli: true
1288
- })
1289
- ], EventType);
1290
- class EventTypeCollection extends SmrtCollection {
1291
- static _itemClass = EventType;
1292
- /**
1293
- * Get or create an event type by slug
1294
- *
1295
- * @param slug - EventType slug (e.g., 'basketball-game', 'concert')
1296
- * @param name - Optional display name (defaults to capitalized slug)
1297
- * @returns EventType instance
1298
- */
1299
- async getOrCreate(slug, name) {
1300
- const existing = await this.get({ slug });
1301
- if (existing) {
1302
- return existing;
1303
- }
1304
- const displayName = name || slug.replace(/-/g, " ").replace(/\b\w/g, (l) => l.toUpperCase());
1305
- return await this.create({
1306
- slug,
1307
- name: displayName
1308
- });
1309
- }
1310
- /**
1311
- * Get an event type by slug
1312
- *
1313
- * @param slug - EventType slug to search for
1314
- * @returns EventType instance or null if not found
1315
- */
1316
- async getBySlug(slug) {
1317
- return await this.get({ slug });
1318
- }
1319
- /**
1320
- * Initialize default event types
1321
- *
1322
- * Creates common event types if they don't exist:
1323
- * - Sports: game, period, goal, assist, penalty
1324
- * - Entertainment: concert, performance, song
1325
- * - Professional: conference, session, presentation, workshop
1326
- * - Community: meeting, agenda-item, motion, vote
1327
- *
1328
- * @returns Array of created/existing event types
1329
- */
1330
- async initializeDefaults() {
1331
- const defaults = [
1332
- // Sports
1333
- { slug: "game", name: "Game" },
1334
- { slug: "match", name: "Match" },
1335
- { slug: "period", name: "Period" },
1336
- { slug: "quarter", name: "Quarter" },
1337
- { slug: "inning", name: "Inning" },
1338
- { slug: "goal", name: "Goal" },
1339
- { slug: "assist", name: "Assist" },
1340
- { slug: "penalty", name: "Penalty" },
1341
- { slug: "substitution", name: "Substitution" },
1342
- // Entertainment
1343
- { slug: "concert", name: "Concert" },
1344
- { slug: "performance", name: "Performance" },
1345
- { slug: "set", name: "Set" },
1346
- { slug: "song", name: "Song" },
1347
- { slug: "theater", name: "Theater" },
1348
- { slug: "show", name: "Show" },
1349
- // Professional
1350
- { slug: "conference", name: "Conference" },
1351
- { slug: "session", name: "Session" },
1352
- { slug: "presentation", name: "Presentation" },
1353
- { slug: "workshop", name: "Workshop" },
1354
- { slug: "seminar", name: "Seminar" },
1355
- { slug: "keynote", name: "Keynote" },
1356
- { slug: "panel", name: "Panel" },
1357
- // Community
1358
- { slug: "meeting", name: "Meeting" },
1359
- { slug: "town-hall", name: "Town Hall" },
1360
- { slug: "agenda-item", name: "Agenda Item" },
1361
- { slug: "motion", name: "Motion" },
1362
- { slug: "amendment", name: "Amendment" },
1363
- { slug: "vote", name: "Vote" },
1364
- { slug: "discussion", name: "Discussion" },
1365
- // General
1366
- { slug: "event", name: "Event" },
1367
- { slug: "activity", name: "Activity" },
1368
- { slug: "action", name: "Action" }
1369
- ];
1370
- const types = [];
1371
- for (const def of defaults) {
1372
- const type = await this.getOrCreate(def.slug, def.name);
1373
- types.push(type);
1374
- }
1375
- return types;
1376
- }
1377
- // ============================================
1378
- // Tenant Helper Methods
1379
- // ============================================
1380
- /**
1381
- * Find all event types for a specific tenant
1382
- *
1383
- * @param tenantId - Tenant ID to filter by
1384
- * @returns Array of EventType instances for the tenant
1385
- */
1386
- async findByTenant(tenantId2) {
1387
- return this.list({ where: { tenantId: tenantId2 } });
1388
- }
1389
- /**
1390
- * Find all global event types (no tenant association).
1391
- *
1392
- * Routes through the shared tenant-global helper so it does not throw under
1393
- * an active tenant context (an explicit `tenant_id IS NULL` filter would be
1394
- * flagged as an isolation violation). (#1600)
1395
- *
1396
- * @returns Array of EventType instances with no tenant
1397
- */
1398
- async findGlobal() {
1399
- return queryGlobal(this);
1400
- }
1401
- /**
1402
- * Find event types for a tenant including global types.
1403
- *
1404
- * Fails closed if an active tenant context requests a different tenant's
1405
- * rows; the admin/system path keeps the cross-tenant capability. (#1600)
1406
- *
1407
- * @param tenantId - Tenant ID to filter by
1408
- * @returns Array of EventType instances for the tenant and global types
1409
- */
1410
- async findWithGlobals(tenantId2) {
1411
- return queryWithGlobals(
1412
- this,
1413
- tenantId2,
1414
- "EventType.findWithGlobals"
1415
- );
1416
- }
1417
- }
1418
- const EventTypeCollection$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1419
- __proto__: null,
1420
- EventTypeCollection
1421
- }, Symbol.toStringTag, { value: "Module" }));
1422
- export {
1423
- EVENTS_MODULE_META,
1424
- EVENTS_UI_SLOTS,
1425
- Event,
1426
- EventAsset,
1427
- EventAssetCollection,
1428
- EventCollection,
1429
- EventParticipant,
1430
- EventParticipantCollection,
1431
- EventSeries,
1432
- EventSeriesCollection,
1433
- EventType,
1434
- EventTypeCollection,
1435
- calculateDuration,
1436
- calculateNextOccurrence,
1437
- checkSchedulingConflict,
1438
- formatDuration,
1439
- formatEventDateRange,
1440
- generateEventSlug,
1441
- getEventStatusFromDates,
1442
- isEventNow,
1443
- parseRecurrencePattern,
1444
- sortEventsByDate,
1445
- validateEventStatus
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
- //# sourceMappingURL=index.js.map
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