@m481/mp-sdk-ng 0.1.0-dev.20251024165513

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.
@@ -0,0 +1,889 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, inject, Directive, NgModule } from '@angular/core';
3
+ import { HttpClient, HttpErrorResponse, HttpParams, provideHttpClient, HTTP_INTERCEPTORS, withInterceptorsFromDi } from '@angular/common/http';
4
+ import { throwError, from, catchError as catchError$1, map, switchMap, tap } from 'rxjs';
5
+ import { catchError } from 'rxjs/operators';
6
+ import { AES, enc } from 'crypto-js';
7
+ import * as i2 from '@angular/router';
8
+ import 'cross-fetch/polyfill';
9
+ import PocketBase, { ClientResponseError } from 'pocketbase';
10
+
11
+ class BaseModel {
12
+ id;
13
+ created;
14
+ updated;
15
+ }
16
+
17
+ class CalendarShiftModel extends BaseModel {
18
+ shiftId;
19
+ startAt;
20
+ endAt;
21
+ }
22
+
23
+ class EventModel extends BaseModel {
24
+ message;
25
+ scope;
26
+ objectId;
27
+ userId;
28
+ }
29
+
30
+ class MissionModel extends BaseModel {
31
+ name;
32
+ isRegular;
33
+ color;
34
+ hours; // [ [11, 13], [17, 19] ] -
35
+ teamId;
36
+ team;
37
+ isEnabled;
38
+ }
39
+
40
+ var RecurrenceType;
41
+ (function (RecurrenceType) {
42
+ RecurrenceType[RecurrenceType["DAILY"] = 0] = "DAILY";
43
+ RecurrenceType[RecurrenceType["WEEKLY"] = 1] = "WEEKLY";
44
+ RecurrenceType[RecurrenceType["MONTHLY"] = 2] = "MONTHLY";
45
+ })(RecurrenceType || (RecurrenceType = {}));
46
+ class ShiftModel extends BaseModel {
47
+ missionId;
48
+ missionHourIndex;
49
+ teamId;
50
+ assignedUsersIds;
51
+ mission;
52
+ repeatData;
53
+ isEnabled;
54
+ }
55
+
56
+ class UserModel extends BaseModel {
57
+ email;
58
+ verified;
59
+ name;
60
+ teamsAdmin;
61
+ teamsMember;
62
+ password;
63
+ avatar;
64
+ avatarUrl;
65
+ isEnabled;
66
+ }
67
+
68
+ class TeamModel extends BaseModel {
69
+ name;
70
+ isEnabled;
71
+ }
72
+
73
+ var LogLevel;
74
+ (function (LogLevel) {
75
+ LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
76
+ LogLevel[LogLevel["WARN"] = 1] = "WARN";
77
+ LogLevel[LogLevel["INFO"] = 2] = "INFO";
78
+ LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
79
+ })(LogLevel || (LogLevel = {}));
80
+ class LoggerService {
81
+ log = window.console;
82
+ LOG_FNS = [this.log.log, this.log.warn, this.log.error];
83
+ MSG_PREFIXES = [["[", "]"], ["[", "] WARN: "], ["[", "] ERROR: "]];
84
+ get(prefix, level) {
85
+ const logLevel = level || LogLevel.INFO;
86
+ if (logLevel >= LogLevel.INFO) {
87
+ this.LOG_FNS[0].call(this.log, "[" + prefix + "] Logger created");
88
+ }
89
+ const loggerFns = this.LOG_FNS.map((logTemplFn, i) => {
90
+ return logTemplFn.bind(this.log, this.MSG_PREFIXES[i][0] + prefix + this.MSG_PREFIXES[i][1]);
91
+ });
92
+ return {
93
+ d: (...args) => {
94
+ if (logLevel === LogLevel.DEBUG) {
95
+ loggerFns[0].apply(this.log, [...args]);
96
+ }
97
+ },
98
+ w: (...args) => {
99
+ if (logLevel >= LogLevel.WARN) {
100
+ loggerFns[1].apply(this.log, [...args]);
101
+ }
102
+ },
103
+ e: (...args) => {
104
+ if (logLevel >= LogLevel.ERROR) {
105
+ loggerFns[2].apply(this.log, [...args]);
106
+ }
107
+ }
108
+ };
109
+ }
110
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
111
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, providedIn: "root" });
112
+ }
113
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: LoggerService, decorators: [{
114
+ type: Injectable,
115
+ args: [{ providedIn: "root" }]
116
+ }] });
117
+
118
+ class Configuration {
119
+ baseUrl;
120
+ secret;
121
+ isProduction;
122
+ constructor(params) {
123
+ this.baseUrl = params.baseUrl || "";
124
+ this.secret = params.secret;
125
+ this.isProduction = params.isProduction || false;
126
+ }
127
+ }
128
+
129
+ class BasePlain {
130
+ log;
131
+ config = inject(Configuration);
132
+ constructor(logLevel) {
133
+ const logger = inject(LoggerService);
134
+ this.log = logger.get(this.constructor.name, logLevel || this.config.isProduction ? LogLevel.ERROR : LogLevel.DEBUG);
135
+ }
136
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BasePlain, deps: [{ token: LogLevel }], target: i0.ɵɵFactoryTarget.Directive });
137
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BasePlain, isStandalone: true, ngImport: i0 });
138
+ }
139
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BasePlain, decorators: [{
140
+ type: Directive
141
+ }], ctorParameters: () => [{ type: LogLevel }] });
142
+
143
+ class UtilsService extends BasePlain {
144
+ cfg;
145
+ constructor(cfg) {
146
+ super();
147
+ this.cfg = cfg;
148
+ }
149
+ encryptText(text) {
150
+ let data = text;
151
+ if (this.cfg.secret) {
152
+ data = AES.encrypt(text, this.cfg.secret).toString();
153
+ }
154
+ return data;
155
+ }
156
+ decryptText(data) {
157
+ let text = data;
158
+ if (text) {
159
+ if (this.cfg.secret) {
160
+ const bytes = AES.decrypt(data.toString(), this.cfg.secret);
161
+ const decrypted = bytes.toString(enc.Utf8);
162
+ if (decrypted) {
163
+ text = decrypted;
164
+ }
165
+ else {
166
+ this.log.d("error decrypting", data);
167
+ }
168
+ }
169
+ }
170
+ return text;
171
+ }
172
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UtilsService, deps: [{ token: Configuration }], target: i0.ɵɵFactoryTarget.Injectable });
173
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UtilsService });
174
+ }
175
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: UtilsService, decorators: [{
176
+ type: Injectable
177
+ }], ctorParameters: () => [{ type: Configuration }] });
178
+
179
+ class AuthStoreService {
180
+ utilsSrv;
181
+ KEY_TOKEN = "mp_sdk:token";
182
+ token = "";
183
+ constructor(utilsSrv) {
184
+ this.utilsSrv = utilsSrv;
185
+ }
186
+ setToken(token) {
187
+ this.token = this.utilsSrv.encryptText(token);
188
+ sessionStorage.setItem(this.KEY_TOKEN, this.token);
189
+ }
190
+ getToken() {
191
+ const data = sessionStorage.getItem(this.KEY_TOKEN);
192
+ return !!data ? this.utilsSrv.decryptText(data) : null;
193
+ }
194
+ clearToken() {
195
+ this.token = null;
196
+ sessionStorage.removeItem(this.KEY_TOKEN);
197
+ }
198
+ isStoredToken() {
199
+ return this.getToken() !== null;
200
+ }
201
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthStoreService, deps: [{ token: UtilsService }], target: i0.ɵɵFactoryTarget.Injectable });
202
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthStoreService });
203
+ }
204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthStoreService, decorators: [{
205
+ type: Injectable
206
+ }], ctorParameters: () => [{ type: UtilsService }] });
207
+
208
+ class AuthInterceptor extends BasePlain {
209
+ authStore;
210
+ router;
211
+ // URLs that don't require authentication
212
+ excludedUrls = [
213
+ '/auth/login',
214
+ '/auth/register',
215
+ '/public',
216
+ '/health'
217
+ ];
218
+ constructor(authStore, router) {
219
+ super(LogLevel.DEBUG);
220
+ this.authStore = authStore;
221
+ this.router = router;
222
+ }
223
+ intercept(req, next) {
224
+ // Check if the URL should be excluded
225
+ if (this.shouldExcludeUrl(req.url)) {
226
+ return next.handle(req);
227
+ }
228
+ // Get token from AuthStore service
229
+ const authToken = this.authStore.getToken();
230
+ this.log.d("intercepting", req.url, authToken);
231
+ let ret;
232
+ if (authToken) {
233
+ // Clone the request and add authorization header
234
+ const authReq = req.clone({
235
+ setHeaders: {
236
+ Authorization: authToken
237
+ }
238
+ });
239
+ // Continue with modified request and handle errors
240
+ ret = next.handle(authReq).pipe(catchError((error) => this.handleAuthError(error)));
241
+ }
242
+ else {
243
+ // If no token, continue with original request
244
+ ret = next.handle(req);
245
+ }
246
+ return ret;
247
+ }
248
+ shouldExcludeUrl(url) {
249
+ return this.excludedUrls.some(excludedUrl => url.includes(excludedUrl));
250
+ }
251
+ handleAuthError(error) {
252
+ if (error.status === 401) {
253
+ // Invalid or expired token
254
+ this.log.w('Invalid or expired authentication token');
255
+ this.authStore.clearToken();
256
+ // Redirect to login
257
+ this.router.navigate(['/login']);
258
+ }
259
+ else if (error.status === 403) {
260
+ // Insufficient permissions
261
+ this.log.w('Insufficient permissions to access the resource');
262
+ }
263
+ // Propagate error for component handling
264
+ return throwError(() => error);
265
+ }
266
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthInterceptor, deps: [{ token: AuthStoreService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
267
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthInterceptor });
268
+ }
269
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthInterceptor, decorators: [{
270
+ type: Injectable
271
+ }], ctorParameters: () => [{ type: AuthStoreService }, { type: i2.Router }] });
272
+
273
+ ;
274
+ class BaseSdk extends BasePlain {
275
+ authStore = inject(AuthStoreService);
276
+ http = inject(HttpClient);
277
+ doGet(endpoint, params) {
278
+ return this.http.get(this.config.baseUrl + endpoint, {
279
+ params,
280
+ });
281
+ }
282
+ doGetList(endpoint, params) {
283
+ return this.http.get(this.config.baseUrl + endpoint, {
284
+ params,
285
+ });
286
+ }
287
+ getAuthHeader() {
288
+ return {
289
+ headers: {
290
+ "Authorization": this.authStore.getToken(),
291
+ }
292
+ };
293
+ }
294
+ handleError(error) {
295
+ this.log.e("Error", error);
296
+ }
297
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseSdk, deps: null, target: i0.ɵɵFactoryTarget.Directive });
298
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseSdk, isStandalone: true, usesInheritance: true, ngImport: i0 });
299
+ }
300
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseSdk, decorators: [{
301
+ type: Directive
302
+ }] });
303
+
304
+ class BasePocket extends BaseSdk {
305
+ connection;
306
+ connect() {
307
+ if (!this.connection) {
308
+ this.connection = new PocketBase(this.config.baseUrl);
309
+ }
310
+ }
311
+ getList(entity, options) {
312
+ this.connect();
313
+ this.log.d("getList --- entity", entity, this.authStore.getToken());
314
+ return from(this.connection.collection(entity).getList(1, 20, this.buildOptions(options))).pipe(catchError$1(err => this.handleError(err)), map(d => (d ? {
315
+ page: d.page,
316
+ pageSize: d.perPage,
317
+ pagesTotal: d.totalPages,
318
+ items: d.items,
319
+ total: d.totalItems
320
+ } : null)));
321
+ }
322
+ getOne(entity, id, options) {
323
+ this.connect();
324
+ this.log.d("fetchOne", entity, this.authStore.getToken());
325
+ return from(this.connection.collection(entity).getOne(id, this.buildOptions(options))).pipe(catchError$1(err => this.handleError(err)));
326
+ }
327
+ save(entity, data) {
328
+ this.connect();
329
+ this.log.d("save", entity, data?.id, this.authStore.getToken());
330
+ const target = this.connection.collection(entity);
331
+ let promise;
332
+ if (data.id) {
333
+ promise = target.update(data.id, data, this.getAuthHeader());
334
+ }
335
+ else {
336
+ promise = target.create(data, this.getAuthHeader());
337
+ }
338
+ return from(promise).pipe(catchError$1(err => this.handleError(err)));
339
+ }
340
+ remove(entity, id) {
341
+ this.connect();
342
+ this.log.d("remove", entity, this.authStore.getToken());
343
+ return from(this.connection.collection(entity).delete(id, this.getAuthHeader())).pipe(catchError$1(err => this.handleError(err)));
344
+ }
345
+ handleError(error) {
346
+ if (error instanceof ClientResponseError) {
347
+ this.log.w("Http error", error.status);
348
+ throw new HttpErrorResponse({
349
+ error: error.originalError,
350
+ status: error.status,
351
+ url: error.url
352
+ });
353
+ }
354
+ else {
355
+ this.log.w("Error response unknown", error);
356
+ throw error;
357
+ }
358
+ }
359
+ buildOptions(options) {
360
+ return options
361
+ ? { ...options, ...this.getAuthHeader() }
362
+ : this.getAuthHeader();
363
+ }
364
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BasePocket, deps: null, target: i0.ɵɵFactoryTarget.Directive });
365
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BasePocket, isStandalone: true, usesInheritance: true, ngImport: i0 });
366
+ }
367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BasePocket, decorators: [{
368
+ type: Directive
369
+ }] });
370
+
371
+ class SdkConfig {
372
+ static Entities = {
373
+ AUTH: "users",
374
+ USERS: "users",
375
+ EVENTS: "events",
376
+ MISSIONS: "missions",
377
+ SHIFTS: "shifts",
378
+ CALENDAR_SHIFTS: "calendar_shifts",
379
+ TEAMS: "teams"
380
+ };
381
+ static Endpoints = {
382
+ TEAMS: "/api/collections/teams/records"
383
+ };
384
+ static ModelKeys = {
385
+ CREATE_AT: "created",
386
+ UPDATE_AT: "updated"
387
+ };
388
+ }
389
+
390
+ class AuthService extends BasePocket {
391
+ constructor() {
392
+ super();
393
+ }
394
+ login(user, pass) {
395
+ this.connect();
396
+ return from(this.connection.collection(SdkConfig.Entities.AUTH).authWithPassword(user, pass)).pipe(catchError$1(err => this.handleError(err)), map(data => {
397
+ this.log.d("login ok", data);
398
+ this.authStore.setToken(data.token);
399
+ return data.record;
400
+ }));
401
+ }
402
+ logout() {
403
+ this.authStore.clearToken();
404
+ }
405
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
406
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthService });
407
+ }
408
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AuthService, decorators: [{
409
+ type: Injectable
410
+ }], ctorParameters: () => [] });
411
+
412
+ class BaseResource extends BasePocket {
413
+ fetchList() {
414
+ return this.getList(this.Entity, this.Options);
415
+ }
416
+ fetchOne(id) {
417
+ return this.getOne(this.Entity, id);
418
+ }
419
+ create(data) {
420
+ return this.save(this.Entity, data);
421
+ }
422
+ update(id, data) {
423
+ return this.save(this.Entity, { id, ...data });
424
+ }
425
+ delete(id) {
426
+ return this.remove(this.Entity, id);
427
+ }
428
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseResource, deps: null, target: i0.ɵɵFactoryTarget.Directive });
429
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.14", type: BaseResource, isStandalone: true, usesInheritance: true, ngImport: i0 });
430
+ }
431
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: BaseResource, decorators: [{
432
+ type: Directive
433
+ }] });
434
+
435
+ class MissionsService extends BaseResource {
436
+ Options = {
437
+ filter: "isEnabled = true"
438
+ };
439
+ Entity = SdkConfig.Entities.MISSIONS;
440
+ constructor() {
441
+ super();
442
+ }
443
+ getArchived() {
444
+ return this.getList(SdkConfig.Entities.MISSIONS, {
445
+ filter: "isEnabled = false"
446
+ });
447
+ }
448
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MissionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
449
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MissionsService });
450
+ }
451
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MissionsService, decorators: [{
452
+ type: Injectable
453
+ }], ctorParameters: () => [] });
454
+
455
+ class ShiftsService extends BaseResource {
456
+ Options = {
457
+ filter: "isEnabled = true"
458
+ };
459
+ Entity = SdkConfig.Entities.SHIFTS;
460
+ constructor() {
461
+ super();
462
+ }
463
+ create(data) {
464
+ const repeat = data.repeatData;
465
+ if (!repeat) {
466
+ return throwError(() => new Error('No repeat data provided'));
467
+ }
468
+ // Generate CalendarShifts based on repeat configuration
469
+ const calendarShifts = this.generateCalendarShifts(repeat);
470
+ // Create the main Shift first
471
+ return super.create(data).pipe(switchMap(createdShift => {
472
+ // Assign the shiftId to all generated CalendarShifts
473
+ const shiftsToCreate = calendarShifts.map(cs => ({
474
+ shiftId: createdShift.id,
475
+ startAt: cs.startAt,
476
+ endAt: cs.endAt
477
+ }));
478
+ // Create all CalendarShifts in batch
479
+ return this.createCalendarShiftsBatch(shiftsToCreate).pipe(
480
+ // If successful, return the created shift
481
+ switchMap(() => from([createdShift])),
482
+ // If CalendarShift creation fails, rollback
483
+ catchError$1(error => {
484
+ this.log.e('Error creating calendar shifts, rolling back...', error);
485
+ return this.delete(createdShift.id).pipe(switchMap(() => throwError(() => new Error('Failed to create calendar shifts. Shift has been rolled back.'))));
486
+ }));
487
+ }), catchError$1(error => {
488
+ this.log.e('Error creating shift', error);
489
+ return throwError(() => error);
490
+ }));
491
+ }
492
+ delete(id) {
493
+ this.connect();
494
+ // First, fetch all CalendarShifts associated with this Shift
495
+ return this.getCalendarShiftsByShiftId(id).pipe(switchMap(calendarShifts => {
496
+ // Store the IDs for potential rollback
497
+ const calendarShiftIds = calendarShifts.map(cs => cs.id);
498
+ // Delete all CalendarShifts first
499
+ return this.deleteCalendarShiftsBatch(calendarShiftIds).pipe(switchMap(() => {
500
+ // After successful CalendarShift deletion, delete the main Shift
501
+ return super.delete(id).pipe(catchError$1(error => {
502
+ // If Shift deletion fails, try to restore CalendarShifts
503
+ this.log.e('Error deleting shift, attempting rollback...', error);
504
+ return this.restoreCalendarShifts(calendarShifts).pipe(switchMap(() => throwError(() => new Error('Failed to delete shift. CalendarShifts have been restored.'))));
505
+ }));
506
+ }), catchError$1(error => {
507
+ // If CalendarShift deletion fails, propagate the error
508
+ this.log.e('Error deleting calendar shifts', error);
509
+ return throwError(() => new Error('Failed to delete calendar shifts.'));
510
+ }));
511
+ }), catchError$1(error => {
512
+ this.log.e('Error fetching calendar shifts for deletion', error);
513
+ return throwError(() => error);
514
+ }));
515
+ }
516
+ /**
517
+ * Generates CalendarShifts based on repeat configuration
518
+ */
519
+ generateCalendarShifts(repeat) {
520
+ const shifts = [];
521
+ const startDate = new Date(repeat.initDate);
522
+ let currentDate = new Date(startDate);
523
+ let occurrenceCount = 0;
524
+ // Determine the end date
525
+ const endDate = repeat.finalizeDate
526
+ ? new Date(repeat.finalizeDate)
527
+ : this.calculateEndDateByOccurrences(startDate, repeat);
528
+ while (currentDate <= endDate) {
529
+ // Check if we've reached the maximum number of occurrences
530
+ if (repeat.occurrences && occurrenceCount >= repeat.occurrences) {
531
+ break;
532
+ }
533
+ // Add shift based on recurrence type
534
+ if (this.shouldAddShift(currentDate, repeat)) {
535
+ const shift = new CalendarShiftModel();
536
+ shift.startAt = currentDate.getTime();
537
+ // Assume each shift lasts until end of day (you can adjust this)
538
+ const endDateTime = new Date(currentDate);
539
+ endDateTime.setHours(23, 59, 59, 999);
540
+ shift.endAt = endDateTime.getTime();
541
+ shifts.push(shift);
542
+ occurrenceCount++;
543
+ }
544
+ // Move to next period
545
+ currentDate = this.getNextDate(currentDate, repeat);
546
+ }
547
+ return shifts;
548
+ }
549
+ /**
550
+ * Determines if a shift should be added on the current date
551
+ */
552
+ shouldAddShift(date, repeat) {
553
+ switch (repeat.type) {
554
+ case RecurrenceType.DAILY:
555
+ return true;
556
+ case RecurrenceType.WEEKLY:
557
+ if (repeat.daysOfWeek && repeat.daysOfWeek.length > 0) {
558
+ const dayOfWeek = date.getDay();
559
+ return repeat.daysOfWeek.includes(dayOfWeek);
560
+ }
561
+ return true;
562
+ case RecurrenceType.MONTHLY:
563
+ if (repeat.dayOfMonth) {
564
+ return date.getDate() === repeat.dayOfMonth;
565
+ }
566
+ return true;
567
+ default:
568
+ return false;
569
+ }
570
+ }
571
+ /**
572
+ * Calculates the next date based on recurrence type
573
+ */
574
+ getNextDate(currentDate, repeat) {
575
+ const nextDate = new Date(currentDate);
576
+ switch (repeat.type) {
577
+ case RecurrenceType.DAILY:
578
+ nextDate.setDate(nextDate.getDate() + repeat.interval);
579
+ break;
580
+ case RecurrenceType.WEEKLY:
581
+ nextDate.setDate(nextDate.getDate() + (7 * repeat.interval));
582
+ break;
583
+ case RecurrenceType.MONTHLY:
584
+ nextDate.setMonth(nextDate.getMonth() + repeat.interval);
585
+ break;
586
+ }
587
+ return nextDate;
588
+ }
589
+ /**
590
+ * Calculates the end date based on number of occurrences
591
+ */
592
+ calculateEndDateByOccurrences(startDate, repeat) {
593
+ if (!repeat.occurrences) {
594
+ // If no occurrences defined, set a reasonable limit (e.g., 1 year)
595
+ const defaultEnd = new Date(startDate);
596
+ defaultEnd.setFullYear(defaultEnd.getFullYear() + 1);
597
+ return defaultEnd;
598
+ }
599
+ let estimatedEnd = new Date(startDate);
600
+ switch (repeat.type) {
601
+ case RecurrenceType.DAILY:
602
+ estimatedEnd.setDate(estimatedEnd.getDate() + (repeat.occurrences * repeat.interval));
603
+ break;
604
+ case RecurrenceType.WEEKLY:
605
+ estimatedEnd.setDate(estimatedEnd.getDate() + (repeat.occurrences * 7 * repeat.interval));
606
+ break;
607
+ case RecurrenceType.MONTHLY:
608
+ estimatedEnd.setMonth(estimatedEnd.getMonth() + (repeat.occurrences * repeat.interval));
609
+ break;
610
+ }
611
+ return estimatedEnd;
612
+ }
613
+ /**
614
+ * Fetches all CalendarShifts associated with a specific Shift ID
615
+ */
616
+ getCalendarShiftsByShiftId(shiftId) {
617
+ this.log.d('Fetching calendar shifts for shift', shiftId);
618
+ const filter = `shiftId = "${shiftId}"`;
619
+ return from(this.connection.collection(SdkConfig.Entities.CALENDAR_SHIFTS)
620
+ .getFullList({ filter, ...this.getAuthHeader() })).pipe(catchError$1(err => this.handleError(err)));
621
+ }
622
+ /**
623
+ * Deletes multiple CalendarShifts in batch
624
+ */
625
+ deleteCalendarShiftsBatch(calendarShiftIds) {
626
+ if (calendarShiftIds.length === 0) {
627
+ return from([true]);
628
+ }
629
+ this.log.d('Deleting calendar shifts batch', calendarShiftIds.length);
630
+ // PocketBase batch ops could be disabled,
631
+ // so we create a manual transaction using Promise.all
632
+ const promises = calendarShiftIds.map(id => this.connection.collection(SdkConfig.Entities.CALENDAR_SHIFTS)
633
+ .delete(id, this.getAuthHeader()));
634
+ return from(Promise.all(promises)).pipe(switchMap(() => from([true])), catchError$1(err => this.handleError(err)));
635
+ }
636
+ /**
637
+ * Restores CalendarShifts in case of rollback
638
+ */
639
+ restoreCalendarShifts(calendarShifts) {
640
+ if (calendarShifts.length === 0) {
641
+ return from([true]);
642
+ }
643
+ this.log.d('Restoring calendar shifts', calendarShifts.length);
644
+ // Recreate the CalendarShifts with their original data
645
+ const promises = calendarShifts.map(cs => this.connection.collection(SdkConfig.Entities.CALENDAR_SHIFTS)
646
+ .create({
647
+ shiftId: cs.shiftId,
648
+ startAt: cs.startAt,
649
+ endAt: cs.endAt
650
+ }, this.getAuthHeader()));
651
+ return from(Promise.all(promises)).pipe(switchMap(() => from([true])), catchError$1(err => {
652
+ this.log.e('Failed to restore calendar shifts during rollback', err);
653
+ return this.handleError(err);
654
+ }));
655
+ }
656
+ /**
657
+ * Creates multiple CalendarShifts
658
+ * TODO move to backend?
659
+ */
660
+ createCalendarShiftsBatch(shifts) {
661
+ this.connect();
662
+ if (shifts.length === 0) {
663
+ return from([]);
664
+ }
665
+ this.log.d('Creating calendar shifts batch', shifts.length);
666
+ // PocketBase batch ops could be disabled,
667
+ // so we create a manual transaction using Promise.all
668
+ const promises = shifts.map(shift => this.connection.collection(SdkConfig.Entities.CALENDAR_SHIFTS)
669
+ .create(shift, this.getAuthHeader()));
670
+ return from(Promise.all(promises)).pipe(catchError$1(err => this.handleError(err)));
671
+ }
672
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ShiftsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
673
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ShiftsService });
674
+ }
675
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ShiftsService, decorators: [{
676
+ type: Injectable
677
+ }], ctorParameters: () => [] });
678
+
679
+ class CrewService extends BaseResource {
680
+ Options = {
681
+ filter: "isEnabled = true"
682
+ };
683
+ Entity = SdkConfig.Entities.USERS;
684
+ constructor() {
685
+ super();
686
+ }
687
+ create(data) {
688
+ throw new Error("Method not supported.");
689
+ }
690
+ update(id, data) {
691
+ throw new Error("Method not supported.");
692
+ }
693
+ delete(id) {
694
+ throw new Error("Method not supported.");
695
+ }
696
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CrewService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
697
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CrewService });
698
+ }
699
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: CrewService, decorators: [{
700
+ type: Injectable
701
+ }], ctorParameters: () => [] });
702
+
703
+ class TeamsService extends BaseResource {
704
+ Options = {
705
+ filter: "isEnabled = true",
706
+ fields: "id,name,isEnabled"
707
+ };
708
+ Entity = SdkConfig.Entities.TEAMS;
709
+ constructor() {
710
+ super();
711
+ }
712
+ // Unsupported methods
713
+ /**
714
+ * @
715
+ */
716
+ fetchOne(id) {
717
+ throw new Error("Method not supported.");
718
+ }
719
+ create(data) {
720
+ throw new Error("Method not supported.");
721
+ }
722
+ update(id, data) {
723
+ throw new Error("Method not supported.");
724
+ }
725
+ delete(id) {
726
+ throw new Error("Method not supported.");
727
+ }
728
+ // Alternative methods using Angular Http
729
+ getTeams() {
730
+ const params = new HttpParams({
731
+ fromObject: this.Options
732
+ });
733
+ return this.doGetList(SdkConfig.Endpoints.TEAMS, params)
734
+ .pipe(tap(d => this.log.d("teams!!", d)));
735
+ }
736
+ fetchTeams() {
737
+ return this.getList(SdkConfig.Entities.TEAMS, this.Options);
738
+ }
739
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TeamsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
740
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TeamsService });
741
+ }
742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: TeamsService, decorators: [{
743
+ type: Injectable
744
+ }], ctorParameters: () => [] });
745
+
746
+ class MpSdkService extends BasePlain {
747
+ missionsSrv;
748
+ shiftsSrv;
749
+ staffSrv;
750
+ teamsSrv;
751
+ authSrv = inject(AuthService);
752
+ authStoreSrv = inject(AuthStoreService);
753
+ constructor(missionsSrv, shiftsSrv, staffSrv, teamsSrv) {
754
+ super();
755
+ this.missionsSrv = missionsSrv;
756
+ this.shiftsSrv = shiftsSrv;
757
+ this.staffSrv = staffSrv;
758
+ this.teamsSrv = teamsSrv;
759
+ }
760
+ // Auth
761
+ login(user, pass) {
762
+ return this.authSrv.login(user, pass);
763
+ }
764
+ logout() {
765
+ this.authSrv.logout();
766
+ }
767
+ isLoggedIn() {
768
+ return this.authStoreSrv.isStoredToken();
769
+ }
770
+ // Missions
771
+ getMissions() {
772
+ return this.missionsSrv.fetchList();
773
+ }
774
+ getArchivedMissions() {
775
+ return this.missionsSrv.getArchived();
776
+ }
777
+ getMissionById(id) {
778
+ return this.missionsSrv.fetchOne(id);
779
+ }
780
+ saveMission(m) {
781
+ return !m.id
782
+ ? this.missionsSrv.create(m)
783
+ : this.missionsSrv.update(m.id, m);
784
+ }
785
+ deleteMission(id) {
786
+ return this.missionsSrv.delete(id);
787
+ }
788
+ // Shifts
789
+ getShifts() {
790
+ return this.shiftsSrv.fetchList();
791
+ }
792
+ getShiftById(id) {
793
+ return this.shiftsSrv.fetchOne(id);
794
+ }
795
+ saveShift(m) {
796
+ return !m.id
797
+ ? this.shiftsSrv.create(m)
798
+ : this.shiftsSrv.update(m.id, m);
799
+ }
800
+ deleteShift(id) {
801
+ return this.shiftsSrv.delete(id);
802
+ }
803
+ // Staff
804
+ getStaffUsers() {
805
+ return this.staffSrv.fetchList();
806
+ }
807
+ getStaffUser(id) {
808
+ return this.staffSrv.fetchOne(id);
809
+ }
810
+ getStaffTeams() {
811
+ return this.teamsSrv.fetchList();
812
+ }
813
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MpSdkService, deps: [{ token: MissionsService }, { token: ShiftsService }, { token: CrewService }, { token: TeamsService }], target: i0.ɵɵFactoryTarget.Injectable });
814
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MpSdkService });
815
+ }
816
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MpSdkService, decorators: [{
817
+ type: Injectable
818
+ }], ctorParameters: () => [{ type: MissionsService }, { type: ShiftsService }, { type: CrewService }, { type: TeamsService }] });
819
+
820
+ const defaultConfig = () => {
821
+ return new Configuration({
822
+ baseUrl: "http://localhost:3000/api/",
823
+ secret: "lwjhvkjdfhglk",
824
+ isProduction: false
825
+ });
826
+ };
827
+ class MpSdkModule {
828
+ static forRoot(configurationFactory) {
829
+ return {
830
+ ngModule: MpSdkModule,
831
+ providers: [{
832
+ provide: Configuration,
833
+ useFactory: configurationFactory || defaultConfig
834
+ }],
835
+ };
836
+ }
837
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MpSdkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
838
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.14", ngImport: i0, type: MpSdkModule });
839
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MpSdkModule, providers: [
840
+ provideHttpClient(withInterceptorsFromDi()),
841
+ {
842
+ provide: HTTP_INTERCEPTORS,
843
+ useClass: AuthInterceptor,
844
+ multi: true
845
+ },
846
+ LoggerService,
847
+ UtilsService,
848
+ AuthStoreService,
849
+ AuthService,
850
+ MissionsService,
851
+ ShiftsService,
852
+ TeamsService,
853
+ CrewService,
854
+ MpSdkService
855
+ ] });
856
+ }
857
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: MpSdkModule, decorators: [{
858
+ type: NgModule,
859
+ args: [{
860
+ providers: [
861
+ provideHttpClient(withInterceptorsFromDi()),
862
+ {
863
+ provide: HTTP_INTERCEPTORS,
864
+ useClass: AuthInterceptor,
865
+ multi: true
866
+ },
867
+ LoggerService,
868
+ UtilsService,
869
+ AuthStoreService,
870
+ AuthService,
871
+ MissionsService,
872
+ ShiftsService,
873
+ TeamsService,
874
+ CrewService,
875
+ MpSdkService
876
+ ]
877
+ }]
878
+ }] });
879
+
880
+ /*
881
+ * Public API Surface of lib
882
+ */
883
+
884
+ /**
885
+ * Generated bundle index. Do not edit.
886
+ */
887
+
888
+ export { AuthStoreService, CalendarShiftModel, Configuration, EventModel, MissionModel, MpSdkModule, MpSdkService, RecurrenceType, ShiftModel, TeamModel, UserModel };
889
+ //# sourceMappingURL=m481-mp-sdk-ng.mjs.map