@managemint-solutions/sdk 0.39.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +75 -3
  2. package/dist/client.d.ts +3 -0
  3. package/dist/client.js +5 -0
  4. package/dist/index.d.ts +4 -1
  5. package/dist/index.js +14 -1
  6. package/dist/leave/dto.d.ts +4 -0
  7. package/dist/leave/dto.js +24 -0
  8. package/dist/leave/leave-entitlements.d.ts +10 -3
  9. package/dist/leave/leave-entitlements.js +26 -6
  10. package/dist/leave/leave-requests.d.ts +2 -3
  11. package/dist/leave/leave-requests.js +2 -1
  12. package/dist/leave/leave-types.d.ts +2 -3
  13. package/dist/leave/leave-types.js +3 -0
  14. package/dist/leave/working-days.d.ts +4 -0
  15. package/dist/leave/working-days.js +13 -5
  16. package/dist/permissions/dto.d.ts +4 -0
  17. package/dist/permissions/dto.js +20 -0
  18. package/dist/service-client/index.d.ts +13 -0
  19. package/dist/service-client/index.js +22 -0
  20. package/dist/timesheets/dto.d.ts +42 -0
  21. package/dist/timesheets/dto.js +211 -0
  22. package/dist/timesheets/index.d.ts +4 -0
  23. package/dist/timesheets/index.js +27 -0
  24. package/dist/timesheets/timesheet-entries.d.ts +54 -0
  25. package/dist/timesheets/timesheet-entries.js +141 -0
  26. package/dist/timesheets/timesheets.d.ts +67 -0
  27. package/dist/timesheets/timesheets.js +201 -0
  28. package/dist/timesheets/weeks.d.ts +7 -0
  29. package/dist/timesheets/weeks.js +26 -0
  30. package/dist/transforms.d.ts +13 -0
  31. package/dist/transforms.js +24 -1
  32. package/dist/users/dto.d.ts +1 -0
  33. package/dist/users/dto.js +7 -0
  34. package/dist/users/index.d.ts +8 -1
  35. package/dist/users/index.js +17 -2
  36. package/dist/validators.d.ts +10 -0
  37. package/dist/validators.js +21 -1
  38. package/package.json +2 -2
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimesheetsResource = void 0;
4
+ const enum_1 = require("@managemint-solutions/entities/audit-trail/enum");
5
+ const enum_2 = require("@managemint-solutions/entities/timesheets/enum");
6
+ const audit_1 = require("../audit");
7
+ const errors_1 = require("../errors");
8
+ const working_days_1 = require("../leave/working-days");
9
+ const transforms_1 = require("../transforms");
10
+ const timesheet_entries_1 = require("./timesheet-entries");
11
+ const weeks_1 = require("./weeks");
12
+ const TIMESHEET_SELECT = `
13
+ mms_id,
14
+ created_at,
15
+ created_by:user_profiles!created_by (*),
16
+ updated_at,
17
+ last_updated_by:user_profiles!last_updated_by (*),
18
+ user:user_profiles!user_id (*),
19
+ week_start,
20
+ status,
21
+ submitted_at,
22
+ reviewed_by:user_profiles!reviewed_by (*),
23
+ reviewed_at,
24
+ review_note
25
+ `;
26
+ class TimesheetsResource {
27
+ supabase;
28
+ auth;
29
+ table;
30
+ constructor(supabase, auth, audit) {
31
+ this.supabase = supabase;
32
+ this.auth = auth;
33
+ this.table = (0, audit_1.auditedTable)(supabase, auth, audit, {
34
+ table: 'timesheets',
35
+ entityType: enum_1.AuditTrailEntityType.TIMESHEETS,
36
+ });
37
+ }
38
+ async list(query, options = {}) {
39
+ const page = query.page;
40
+ const pageSize = query.page_size;
41
+ const offset = (page - 1) * pageSize;
42
+ let timesheetsQuery = this.supabase
43
+ .from('timesheets')
44
+ .select(TIMESHEET_SELECT, { count: 'estimated' })
45
+ .eq('organization_id', this.auth.organization_id)
46
+ .order('week_start', { ascending: false })
47
+ .order('created_at', { ascending: false })
48
+ .range(offset, offset + pageSize - 1);
49
+ if (options.userIds) {
50
+ timesheetsQuery = timesheetsQuery.in('user_id', options.userIds);
51
+ }
52
+ if (query.user_id) {
53
+ timesheetsQuery = timesheetsQuery.eq('user_id', query.user_id);
54
+ }
55
+ if (query.status) {
56
+ timesheetsQuery = timesheetsQuery.eq('status', query.status);
57
+ }
58
+ if (query.week_start) {
59
+ timesheetsQuery = timesheetsQuery.eq('week_start', query.week_start);
60
+ }
61
+ const { data, error, count } = await timesheetsQuery;
62
+ if (error)
63
+ throw (0, errors_1.mapPostgrestError)(error);
64
+ const rows = await this.withTotals((data ?? []));
65
+ return (0, transforms_1.toMmsList)(rows, page, pageSize, count);
66
+ }
67
+ /** The week with its entries, by date then start time. */
68
+ async getById(timesheetId) {
69
+ const summary = await this.summaryById(timesheetId);
70
+ const { data, error } = await this.supabase
71
+ .from('timesheet_entries')
72
+ .select(timesheet_entries_1.TIMESHEET_ENTRY_SELECT)
73
+ .eq('organization_id', this.auth.organization_id)
74
+ .eq('timesheet_id', timesheetId)
75
+ .order('date')
76
+ .order('start_time');
77
+ if (error)
78
+ throw (0, errors_1.mapPostgrestError)(error);
79
+ return { ...summary, entries: (data ?? []).map(timesheet_entries_1.withClockTimes) };
80
+ }
81
+ /**
82
+ * The week of `userId` starting on `weekStart`, or null when no entry has opened it yet. One
83
+ * row per user and Monday (the table's unique key), so there is at most one.
84
+ */
85
+ async findFor(userId, weekStart) {
86
+ const { data, error } = await this.supabase
87
+ .from('timesheets')
88
+ .select('mms_id, status, week_start')
89
+ .eq('organization_id', this.auth.organization_id)
90
+ .eq('user_id', userId)
91
+ .eq('week_start', weekStart)
92
+ .maybeSingle();
93
+ if (error)
94
+ throw (0, errors_1.mapPostgrestError)(error);
95
+ return data;
96
+ }
97
+ /** Opens a week as a draft. A second opener of the same week hits the unique key - the SDK's 409. */
98
+ async create(input) {
99
+ const row = await this.table.insert({
100
+ user_id: input.user_id,
101
+ week_start: input.week_start,
102
+ status: enum_2.TimesheetStatus.DRAFT,
103
+ organization_id: this.auth.organization_id,
104
+ created_by: this.auth.mms_id,
105
+ created_at: new Date().toISOString(),
106
+ });
107
+ return this.summaryById(row.mms_id);
108
+ }
109
+ /**
110
+ * Sends a draft or rejected week for review, clearing the previous decision. Resolves to null
111
+ * when the week was no longer in either state - submitted twice from two tabs, say.
112
+ */
113
+ async submit(timesheetId) {
114
+ const now = new Date().toISOString();
115
+ const row = await this.table.updateWhere(timesheetId, (query) => query.in('status', [enum_2.TimesheetStatus.DRAFT, enum_2.TimesheetStatus.REJECTED]), {
116
+ status: enum_2.TimesheetStatus.SUBMITTED,
117
+ submitted_at: now,
118
+ reviewed_by: null,
119
+ reviewed_at: null,
120
+ review_note: null,
121
+ last_updated_by: this.auth.mms_id,
122
+ updated_at: now,
123
+ });
124
+ return row ? this.summaryById(timesheetId) : null;
125
+ }
126
+ /**
127
+ * Approves or rejects a submitted week. Resolves to null when the week was no longer
128
+ * submitted - another reviewer got there first - so the caller can say so instead of
129
+ * overwriting their decision.
130
+ */
131
+ async review(timesheetId, input) {
132
+ const now = new Date().toISOString();
133
+ const row = await this.table.updateWhere(timesheetId, (query) => query.eq('status', enum_2.TimesheetStatus.SUBMITTED), {
134
+ status: input.status,
135
+ reviewed_by: input.reviewed_by,
136
+ reviewed_at: now,
137
+ review_note: input.review_note,
138
+ last_updated_by: this.auth.mms_id,
139
+ updated_at: now,
140
+ });
141
+ return row ? this.summaryById(timesheetId) : null;
142
+ }
143
+ /**
144
+ * The ids of `userIds`' approved weeks that could hold an entry dated `dateFrom`..`dateTo` -
145
+ * the weeks starting from the Monday of `dateFrom` up to `dateTo`. The report keeps only the
146
+ * entries of these weeks.
147
+ */
148
+ async approvedIds(userIds, dateFrom, dateTo) {
149
+ if (userIds.length === 0)
150
+ return new Set();
151
+ const rows = await (0, transforms_1.allRows)((from, to) => this.supabase
152
+ .from('timesheets')
153
+ .select('mms_id')
154
+ .eq('organization_id', this.auth.organization_id)
155
+ .in('user_id', userIds)
156
+ .eq('status', enum_2.TimesheetStatus.APPROVED)
157
+ .gte('week_start', (0, weeks_1.weekStartOf)(dateFrom))
158
+ .lte('week_start', dateTo)
159
+ .order('mms_id')
160
+ .range(from, to));
161
+ return new Set(rows.map((row) => row.mms_id));
162
+ }
163
+ async summaryById(timesheetId) {
164
+ const { data, error } = await this.supabase
165
+ .from('timesheets')
166
+ .select(TIMESHEET_SELECT)
167
+ .eq('mms_id', timesheetId)
168
+ .eq('organization_id', this.auth.organization_id)
169
+ .single();
170
+ if (error)
171
+ throw (0, errors_1.mapPostgrestError)(error);
172
+ const [row] = await this.withTotals([data]);
173
+ return row;
174
+ }
175
+ /**
176
+ * Adds `week_end` and the totals to each row from one query over the entries of these weeks.
177
+ * Nothing is stored: a total is always what the entries add up to.
178
+ */
179
+ async withTotals(rows) {
180
+ if (rows.length === 0)
181
+ return [];
182
+ const timesheetIds = rows.map((row) => row.mms_id);
183
+ const entries = await (0, transforms_1.allRows)((from, to) => this.supabase
184
+ .from('timesheet_entries')
185
+ .select('timesheet_id, duration_minutes')
186
+ .eq('organization_id', this.auth.organization_id)
187
+ .in('timesheet_id', timesheetIds)
188
+ .order('mms_id')
189
+ .range(from, to));
190
+ return rows.map((row) => {
191
+ const mine = entries.filter((entry) => entry.timesheet_id === row.mms_id);
192
+ return {
193
+ ...row,
194
+ week_end: (0, working_days_1.shiftDays)(row.week_start, 6),
195
+ total_minutes: mine.reduce((total, entry) => total + Number(entry.duration_minutes), 0),
196
+ entry_count: mine.length,
197
+ };
198
+ });
199
+ }
200
+ }
201
+ exports.TimesheetsResource = TimesheetsResource;
@@ -0,0 +1,7 @@
1
+ /** The Monday of the week containing `isoDate` (a Sunday belongs to the week before it). */
2
+ export declare const weekStartOf: (isoDate: string) => string;
3
+ /**
4
+ * The minutes from `start` to `end` on one day; `end` may be `24:00` for midnight. Zero or
5
+ * negative when the end is not after the start - the caller rejects that, so it is not clamped.
6
+ */
7
+ export declare const minutesBetween: (start: string, end: string) => number;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.minutesBetween = exports.weekStartOf = void 0;
4
+ const working_days_1 = require("../leave/working-days");
5
+ // The calendar arithmetic behind timesheets: which Monday-to-Sunday week a date belongs to, and
6
+ // how long an entry is. Pure functions over `YYYY-MM-DD` and `HH:MM` strings - the columns are
7
+ // `date` and `time`, so nothing here depends on the caller's clock zone.
8
+ /** The Monday of the week containing `isoDate` (a Sunday belongs to the week before it). */
9
+ const weekStartOf = (isoDate) => {
10
+ const date = (0, working_days_1.parseIsoDate)(isoDate);
11
+ // getUTCDay: 0 = Sunday .. 6 = Saturday; Monday is 0 days back, Sunday 6.
12
+ const daysSinceMonday = (date.getUTCDay() + 6) % 7;
13
+ date.setUTCDate(date.getUTCDate() - daysSinceMonday);
14
+ return (0, working_days_1.toIsoDate)(date);
15
+ };
16
+ exports.weekStartOf = weekStartOf;
17
+ const toMinutes = (clockTime) => {
18
+ const [hours, minutes] = clockTime.split(':').map(Number);
19
+ return hours * 60 + minutes;
20
+ };
21
+ /**
22
+ * The minutes from `start` to `end` on one day; `end` may be `24:00` for midnight. Zero or
23
+ * negative when the end is not after the start - the caller rejects that, so it is not clamped.
24
+ */
25
+ const minutesBetween = (start, end) => toMinutes(end) - toMinutes(start);
26
+ exports.minutesBetween = minutesBetween;
@@ -1,3 +1,4 @@
1
+ import type { PostgrestError } from '@supabase/supabase-js';
1
2
  import type { MmsList } from '@managemint-solutions/entities/common';
2
3
  /**
3
4
  * The `client_id` / `project_id` list filters accept either a plain UUID v7 or the base64-JSON
@@ -55,3 +56,15 @@ export declare const restoredPatch: (by: string) => {
55
56
  restored_at: string;
56
57
  restored_by: string;
57
58
  };
59
+ /** The most rows one PostgREST response carries (Supabase's `max-rows`); past it a result is cut short silently. */
60
+ export declare const ROW_CAP = 1000;
61
+ /**
62
+ * Every row of a query that may outgrow one response, fetched in pages of `ROW_CAP`. `build`
63
+ * returns the query for one page's `.range(from, to)`; the walk stops at the first short page.
64
+ * The callers are the unpaged reads a job or a rollup makes - a rollover pass, a report, the
65
+ * per-page totals - never a list the api pages itself.
66
+ */
67
+ export declare const allRows: <T>(build: (from: number, to: number) => PromiseLike<{
68
+ data: unknown;
69
+ error: PostgrestError | null;
70
+ }>) => Promise<T[]>;
@@ -2,7 +2,8 @@
2
2
  // Small conversions shared by the DTOs' `@Transform`s, the resources' write payloads, their
3
3
  // select strings and their list results.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.restoredPatch = exports.deletedPatch = exports.unarchivedPatch = exports.archivedPatch = exports.toMmsList = exports.USER_PROFILE_EMBED = exports.toDateInput = exports.orIlike = exports.ilikeContains = exports.parseEntityIdFilter = void 0;
5
+ exports.allRows = exports.ROW_CAP = exports.restoredPatch = exports.deletedPatch = exports.unarchivedPatch = exports.archivedPatch = exports.toMmsList = exports.USER_PROFILE_EMBED = exports.toDateInput = exports.orIlike = exports.ilikeContains = exports.parseEntityIdFilter = void 0;
6
+ const errors_1 = require("./errors");
6
7
  // v7, to match the `mms_id` columns these filters compare against - `public.uuidv7()` is the
7
8
  // default on every table. This is the gate in front of `@IsUUID('7')`, so a stricter version
8
9
  // here would null the id out before validation ever saw it, and a looser one would let a value
@@ -110,3 +111,25 @@ const restoredPatch = (by) => ({
110
111
  restored_by: by,
111
112
  });
112
113
  exports.restoredPatch = restoredPatch;
114
+ /** The most rows one PostgREST response carries (Supabase's `max-rows`); past it a result is cut short silently. */
115
+ exports.ROW_CAP = 1000;
116
+ /**
117
+ * Every row of a query that may outgrow one response, fetched in pages of `ROW_CAP`. `build`
118
+ * returns the query for one page's `.range(from, to)`; the walk stops at the first short page.
119
+ * The callers are the unpaged reads a job or a rollup makes - a rollover pass, a report, the
120
+ * per-page totals - never a list the api pages itself.
121
+ */
122
+ const allRows = async (build) => {
123
+ const rows = [];
124
+ for (let offset = 0;; offset += exports.ROW_CAP) {
125
+ const { data, error } = await build(offset, offset + exports.ROW_CAP - 1);
126
+ if (error)
127
+ throw (0, errors_1.mapPostgrestError)(error);
128
+ const page = (data ?? []);
129
+ rows.push(...page);
130
+ if (page.length < exports.ROW_CAP)
131
+ break;
132
+ }
133
+ return rows;
134
+ };
135
+ exports.allRows = allRows;
@@ -38,6 +38,7 @@ export declare class UpdateUserDto implements UpdateUserDtoType {
38
38
  readonly end_date?: string | null;
39
39
  readonly job_title?: string | null;
40
40
  readonly manager_id?: string | null;
41
+ readonly secondary_manager_id?: string | null;
41
42
  readonly social_facebook?: string | null;
42
43
  readonly social_linkedin?: string | null;
43
44
  readonly social_twitter?: string | null;
package/dist/users/dto.js CHANGED
@@ -137,6 +137,7 @@ class UpdateUserDto {
137
137
  end_date;
138
138
  job_title;
139
139
  manager_id;
140
+ secondary_manager_id;
140
141
  social_facebook;
141
142
  social_linkedin;
142
143
  social_twitter;
@@ -209,6 +210,12 @@ __decorate([
209
210
  (0, class_validator_1.IsUUID)('4', { message: 'Invalid manager ID format' }),
210
211
  __metadata("design:type", Object)
211
212
  ], UpdateUserDto.prototype, "manager_id", void 0);
213
+ __decorate([
214
+ (0, class_validator_1.IsOptional)(),
215
+ (0, validators_1.IsNullable)(),
216
+ (0, class_validator_1.IsUUID)('4', { message: 'Invalid secondary manager ID format' }),
217
+ __metadata("design:type", Object)
218
+ ], UpdateUserDto.prototype, "secondary_manager_id", void 0);
212
219
  __decorate([
213
220
  (0, class_validator_1.IsOptional)(),
214
221
  (0, validators_1.EmptyToNull)(),
@@ -9,6 +9,7 @@ export * from './paths';
9
9
  export type UserRow = Record<string, unknown> & {
10
10
  mms_id: string;
11
11
  manager_id: string | null;
12
+ secondary_manager_id: string | null;
12
13
  created_by: string | null;
13
14
  last_updated_by: string | null;
14
15
  };
@@ -26,8 +27,14 @@ export declare class UsersResource {
26
27
  * client - it needs no service role.
27
28
  */
28
29
  identityById(userId?: string | null): Promise<UserIdentity | null>;
29
- /** The users who report to `managerId` - the direct reports a leave approver may act on. */
30
+ /**
31
+ * The users who report to `managerId` - everyone naming them as primary or secondary
32
+ * manager, the direct reports a leave or timesheet approver may act on. One level, and
33
+ * `active` is not consulted: a deactivated report's history stays visible to their manager.
34
+ */
30
35
  idsManagedBy(managerId: string): Promise<string[]>;
36
+ /** The ids of every active member - who the leave rollover grants a new period to. */
37
+ activeIds(): Promise<string[]>;
31
38
  /** Seats in use. Counts rows rather than fetching them. */
32
39
  activeCount(): Promise<number>;
33
40
  isActive(userId: string): Promise<boolean>;
@@ -92,13 +92,28 @@ class UsersResource {
92
92
  throw (0, errors_1.mapPostgrestError)(error);
93
93
  return data;
94
94
  }
95
- /** The users who report to `managerId` - the direct reports a leave approver may act on. */
95
+ /**
96
+ * The users who report to `managerId` - everyone naming them as primary or secondary
97
+ * manager, the direct reports a leave or timesheet approver may act on. One level, and
98
+ * `active` is not consulted: a deactivated report's history stays visible to their manager.
99
+ */
96
100
  async idsManagedBy(managerId) {
97
101
  const { data, error } = await this.supabase
98
102
  .from('users')
99
103
  .select('mms_id')
100
104
  .eq('organization_id', this.auth.organization_id)
101
- .eq('manager_id', managerId);
105
+ .or(`manager_id.eq.${managerId},secondary_manager_id.eq.${managerId}`);
106
+ if (error)
107
+ throw (0, errors_1.mapPostgrestError)(error);
108
+ return (data ?? []).map((row) => row.mms_id);
109
+ }
110
+ /** The ids of every active member - who the leave rollover grants a new period to. */
111
+ async activeIds() {
112
+ const { data, error } = await this.supabase
113
+ .from('users')
114
+ .select('mms_id')
115
+ .eq('organization_id', this.auth.organization_id)
116
+ .eq('active', true);
102
117
  if (error)
103
118
  throw (0, errors_1.mapPostgrestError)(error);
104
119
  return (data ?? []).map((row) => row.mms_id);
@@ -7,6 +7,16 @@ export declare const isCalendarDate: (value: unknown) => value is string;
7
7
  * conversion. Stricter on purpose than the `@IsDateString` the timestamp columns use.
8
8
  */
9
9
  export declare const IsCalendarDate: (options?: ValidationOptions) => PropertyDecorator;
10
+ /** A wall-clock `HH:MM`; `24:00` as well when `allowEndOfDay` - a shift that ends at midnight. */
11
+ export declare const isClockTime: (value: unknown, allowEndOfDay?: boolean) => value is string;
12
+ /**
13
+ * Clock times, `HH:MM` and nothing more, for the timesheet columns that are `time`: a start is
14
+ * `00:00`..`23:59`, and an end may also be `24:00` (`allowEndOfDay`) so a shift can finish at
15
+ * midnight without crossing it. Seconds are never sent - the SDK trims them off on read.
16
+ */
17
+ export declare const IsClockTime: ({ allowEndOfDay, ...options }?: ValidationOptions & {
18
+ allowEndOfDay?: boolean;
19
+ }) => PropertyDecorator;
10
20
  export declare function IsNullable(validationOptions?: ValidationOptions): PropertyDecorator;
11
21
  /**
12
22
  * An empty string from a cleared form field means "none". It becomes null before validation,
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
7
  };
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.IsCalendarDate = exports.isCalendarDate = void 0;
9
+ exports.IsClockTime = exports.isClockTime = exports.IsCalendarDate = exports.isCalendarDate = void 0;
10
10
  exports.IsNullable = IsNullable;
11
11
  exports.EmptyToNull = EmptyToNull;
12
12
  const class_validator_1 = require("class-validator");
@@ -36,6 +36,26 @@ CalendarDateConstraint = __decorate([
36
36
  */
37
37
  const IsCalendarDate = (options) => (0, class_validator_1.Validate)(CalendarDateConstraint, options);
38
38
  exports.IsCalendarDate = IsCalendarDate;
39
+ const CLOCK_TIME = /^([01]\d|2[0-3]):[0-5]\d$/;
40
+ /** A wall-clock `HH:MM`; `24:00` as well when `allowEndOfDay` - a shift that ends at midnight. */
41
+ const isClockTime = (value, allowEndOfDay = false) => typeof value === 'string' && (CLOCK_TIME.test(value) || (allowEndOfDay && value === '24:00'));
42
+ exports.isClockTime = isClockTime;
43
+ let ClockTimeConstraint = class ClockTimeConstraint {
44
+ validate(value, args) {
45
+ const [allowEndOfDay] = args.constraints;
46
+ return (0, exports.isClockTime)(value, allowEndOfDay);
47
+ }
48
+ };
49
+ ClockTimeConstraint = __decorate([
50
+ (0, class_validator_1.ValidatorConstraint)({ name: 'isClockTime' })
51
+ ], ClockTimeConstraint);
52
+ /**
53
+ * Clock times, `HH:MM` and nothing more, for the timesheet columns that are `time`: a start is
54
+ * `00:00`..`23:59`, and an end may also be `24:00` (`allowEndOfDay`) so a shift can finish at
55
+ * midnight without crossing it. Seconds are never sent - the SDK trims them off on read.
56
+ */
57
+ const IsClockTime = ({ allowEndOfDay = false, ...options } = {}) => (0, class_validator_1.Validate)(ClockTimeConstraint, [allowEndOfDay], options);
58
+ exports.IsClockTime = IsClockTime;
39
59
  function IsNullable(validationOptions) {
40
60
  return (0, class_validator_1.ValidateIf)((_object, value) => value !== null, validationOptions);
41
61
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managemint-solutions/sdk",
3
- "version": "0.39.0",
3
+ "version": "0.40.0",
4
4
  "description": "Typed Supabase data-access SDK for ManageMint Solutions",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Scott Bebington <scottbebington@gmail.com>",
@@ -51,7 +51,7 @@
51
51
  "testEnvironment": "node"
52
52
  },
53
53
  "dependencies": {
54
- "@managemint-solutions/entities": "^1.22.0"
54
+ "@managemint-solutions/entities": "^1.23.0"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@nestjs/common": "^11.0.0",