@typeb-digital/nucleus-sdk 0.0.6 → 0.1.1

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/es/index.js CHANGED
@@ -66,6 +66,44 @@ class NucleusTransport {
66
66
  return makeErrorResult('NETWORK_ERROR', String(err));
67
67
  }
68
68
  }
69
+ async put(path, body) {
70
+ try {
71
+ const envelope = await $fetch(`${this.baseUrl}${path}`, {
72
+ method: 'PUT',
73
+ headers: this.headers,
74
+ body: JSON.stringify(body)
75
+ });
76
+ if (!envelope.success) return makeErrorResult('FORBIDDEN', envelope.error);
77
+ return {
78
+ data: envelope.data
79
+ };
80
+ } catch (err) {
81
+ if (err instanceof FetchError) {
82
+ const errBody = err.data;
83
+ return makeErrorResult(statusToCode(err.status ?? 0, errBody?.error), err.message);
84
+ }
85
+ return makeErrorResult('NETWORK_ERROR', String(err));
86
+ }
87
+ }
88
+ async patch(path, body) {
89
+ try {
90
+ const envelope = await $fetch(`${this.baseUrl}${path}`, {
91
+ method: 'PATCH',
92
+ headers: this.headers,
93
+ body: JSON.stringify(body)
94
+ });
95
+ if (!envelope.success) return makeErrorResult('FORBIDDEN', envelope.error);
96
+ return {
97
+ data: envelope.data
98
+ };
99
+ } catch (err) {
100
+ if (err instanceof FetchError) {
101
+ const errBody = err.data;
102
+ return makeErrorResult(statusToCode(err.status ?? 0, errBody?.error), err.message);
103
+ }
104
+ return makeErrorResult('NETWORK_ERROR', String(err));
105
+ }
106
+ }
69
107
  async del(path, query) {
70
108
  try {
71
109
  const params = query ? Object.fromEntries(Object.entries(query).filter(([, v])=>v !== undefined)) : undefined;
@@ -122,7 +160,20 @@ class NucleusTransport {
122
160
  /**
123
161
  * Transform utilities — map snake_case Prisma API responses to camelCase SDK types.
124
162
  * Each function accepts `unknown` so it works regardless of which buckets were active.
125
- */ function str(v) {
163
+ */ /**
164
+ * Serialize a camelCase mutation input to the snake_case body the API expects.
165
+ * Shallow is sufficient — write bodies are flat. `undefined` keys are dropped;
166
+ * `null` is preserved (explicit clear).
167
+ */ function toSnakeBody(input) {
168
+ const out = {};
169
+ for (const [key, value] of Object.entries(input)){
170
+ if (value === undefined) continue;
171
+ const snake = key.replace(/[A-Z]/g, (m)=>`_${m.toLowerCase()}`);
172
+ out[snake] = value;
173
+ }
174
+ return out;
175
+ }
176
+ function str(v) {
126
177
  return typeof v === 'string' ? v : null;
127
178
  }
128
179
  function num(v) {
@@ -155,6 +206,7 @@ function transformCompensation(raw) {
155
206
  hourlyBillableRate: num(r['hourly_billable_rate']),
156
207
  monthlyCostRate: num(r['monthly_cost_rate']),
157
208
  monthlyBillableRate: num(r['monthly_billable_rate']),
209
+ salary: num(r['salary']),
158
210
  currencyCode: str(r['currency_code']) ?? 'USD',
159
211
  effectiveFrom: str(r['effective_from']) ?? ''
160
212
  };
@@ -166,6 +218,7 @@ function transformCompensationHistoryEntry(raw) {
166
218
  hourlyBillableRate: num(r['hourly_billable_rate']),
167
219
  monthlyCostRate: num(r['monthly_cost_rate']),
168
220
  monthlyBillableRate: num(r['monthly_billable_rate']),
221
+ salary: num(r['salary']),
169
222
  currencyCode: str(r['currency_code']) ?? 'USD',
170
223
  effectiveFrom: str(r['effective_from']) ?? '',
171
224
  effectiveTo: str(r['effective_to'])
@@ -185,6 +238,7 @@ function transformEmployee(raw) {
185
238
  if ('job_title' in r) out['jobTitle'] = str(r['job_title']);
186
239
  if ('department' in r) out['department'] = str(r['department']);
187
240
  if ('employment_status' in r) out['employmentStatus'] = str(r['employment_status']);
241
+ if ('employment_type' in r) out['employmentType'] = str(r['employment_type']);
188
242
  if ('is_external' in r) out['isExternal'] = bool(r['is_external']);
189
243
  // employment
190
244
  if ('start_date' in r) out['startDate'] = str(r['start_date']);
@@ -245,6 +299,11 @@ function transformProject(raw) {
245
299
  return entry;
246
300
  });
247
301
  }
302
+ // financials
303
+ if ('contract_value' in r) out['contractValue'] = num(r['contract_value']);
304
+ if ('budget' in r) out['budget'] = num(r['budget']);
305
+ if ('margin_target' in r) out['marginTarget'] = num(r['margin_target']);
306
+ if ('financials_currency' in r) out['financialsCurrency'] = str(r['financials_currency']);
248
307
  // integrations
249
308
  if ('source' in r) out['source'] = str(r['source']);
250
309
  if ('clockify_project_id' in r) out['clockifyProjectId'] = str(r['clockify_project_id']);
@@ -344,6 +403,155 @@ function transformGenericRate(raw) {
344
403
  if ('billable_rate' in r) out['billableRate'] = num(r['billable_rate']);
345
404
  return out;
346
405
  }
406
+ function transformJurisdiction(raw) {
407
+ if (!raw || typeof raw !== 'object') return {};
408
+ const r = raw;
409
+ const out = {};
410
+ if ('id' in r) out['id'] = r['id'];
411
+ if ('name' in r) out['name'] = str(r['name']);
412
+ if ('code' in r) out['code'] = str(r['code']);
413
+ if ('country' in r) out['country'] = str(r['country']);
414
+ return out;
415
+ }
416
+ function transformLeaveType(raw) {
417
+ if (!raw || typeof raw !== 'object') return {};
418
+ const r = raw;
419
+ const out = {};
420
+ if ('id' in r) out['id'] = r['id'];
421
+ if ('name' in r) out['name'] = str(r['name']);
422
+ if ('description' in r) out['description'] = str(r['description']);
423
+ if ('color' in r) out['color'] = str(r['color']);
424
+ if ('sort_order' in r) out['sortOrder'] = num(r['sort_order']) ?? 0;
425
+ return out;
426
+ }
427
+ function transformLeave(raw) {
428
+ if (!raw || typeof raw !== 'object') return {};
429
+ const r = raw;
430
+ const out = {};
431
+ // core
432
+ if ('id' in r) out['id'] = r['id'];
433
+ if ('employee_id' in r) out['employeeId'] = str(r['employee_id']);
434
+ if ('leave_type_id' in r) out['leaveTypeId'] = str(r['leave_type_id']);
435
+ if ('start_date' in r) out['startDate'] = str(r['start_date']);
436
+ if ('end_date' in r) out['endDate'] = str(r['end_date']);
437
+ if ('days' in r) out['days'] = num(r['days']);
438
+ if ('status' in r) out['status'] = str(r['status']);
439
+ if ('source' in r) out['source'] = str(r['source']);
440
+ // details
441
+ if ('reason' in r) out['reason'] = str(r['reason']);
442
+ // expand: employee / leaveType
443
+ if ('employee' in r) {
444
+ out['employee'] = r['employee'] ? transformEmployee(r['employee']) : null;
445
+ }
446
+ if ('leave_type' in r || 'leaveType' in r) {
447
+ const lt = r['leave_type'] ?? r['leaveType'];
448
+ out['leaveType'] = lt ? transformLeaveType(lt) : null;
449
+ }
450
+ return out;
451
+ }
452
+ function transformLeaveBalance(raw) {
453
+ if (!raw || typeof raw !== 'object') return {};
454
+ const r = raw;
455
+ const out = {};
456
+ // core
457
+ if ('id' in r) out['id'] = r['id'];
458
+ if ('employee_id' in r) out['employeeId'] = str(r['employee_id']);
459
+ if ('leave_type_id' in r) out['leaveTypeId'] = str(r['leave_type_id']);
460
+ if ('year' in r) out['year'] = num(r['year']);
461
+ if ('balance_days' in r) out['balanceDays'] = num(r['balance_days']);
462
+ // expand: employee / leaveType
463
+ if ('employee' in r) {
464
+ out['employee'] = r['employee'] ? transformEmployee(r['employee']) : null;
465
+ }
466
+ if ('leave_type' in r || 'leaveType' in r) {
467
+ const lt = r['leave_type'] ?? r['leaveType'];
468
+ out['leaveType'] = lt ? transformLeaveType(lt) : null;
469
+ }
470
+ return out;
471
+ }
472
+ function transformPolicy(raw) {
473
+ if (!raw || typeof raw !== 'object') return {};
474
+ const r = raw;
475
+ const out = {};
476
+ // core
477
+ if ('id' in r) out['id'] = r['id'];
478
+ if ('title' in r) out['title'] = str(r['title']);
479
+ if ('code' in r) out['code'] = str(r['code']);
480
+ if ('category' in r) out['category'] = str(r['category']);
481
+ if ('description' in r) out['description'] = str(r['description']);
482
+ if ('current_version' in r) out['currentVersion'] = num(r['current_version']) ?? 1;
483
+ if ('requires_acknowledgement' in r) {
484
+ out['requiresAcknowledgement'] = bool(r['requires_acknowledgement']);
485
+ }
486
+ if ('is_published' in r) out['isPublished'] = bool(r['is_published']);
487
+ // content
488
+ if ('body' in r) out['body'] = str(r['body']);
489
+ if ('file_key' in r) out['fileKey'] = str(r['file_key']);
490
+ return out;
491
+ }
492
+ function transformPolicyAcknowledgement(raw) {
493
+ if (!raw || typeof raw !== 'object') return {};
494
+ const r = raw;
495
+ const out = {};
496
+ // core
497
+ if ('id' in r) out['id'] = r['id'];
498
+ if ('policy_id' in r) out['policyId'] = str(r['policy_id']);
499
+ if ('employee_id' in r) out['employeeId'] = str(r['employee_id']);
500
+ if ('version' in r) out['version'] = num(r['version']);
501
+ if ('acknowledged_at' in r) out['acknowledgedAt'] = str(r['acknowledged_at']);
502
+ // expand: employee / policy
503
+ if ('employee' in r) {
504
+ out['employee'] = r['employee'] ? transformEmployee(r['employee']) : null;
505
+ }
506
+ if ('policy' in r) {
507
+ out['policy'] = r['policy'] ? transformPolicy(r['policy']) : null;
508
+ }
509
+ return out;
510
+ }
511
+ function transformCalendarEvent(raw) {
512
+ if (!raw || typeof raw !== 'object') return {};
513
+ const r = raw;
514
+ const out = {};
515
+ if ('id' in r) out['id'] = r['id'];
516
+ if ('title' in r) out['title'] = str(r['title']);
517
+ if ('description' in r) out['description'] = str(r['description']);
518
+ if ('start_date' in r) out['startDate'] = str(r['start_date']);
519
+ if ('end_date' in r) out['endDate'] = str(r['end_date']);
520
+ if ('all_day' in r) out['allDay'] = bool(r['all_day']);
521
+ if ('type' in r) out['type'] = str(r['type']);
522
+ if ('location' in r) out['location'] = str(r['location']);
523
+ if ('color' in r) out['color'] = str(r['color']);
524
+ if ('is_published' in r) out['isPublished'] = bool(r['is_published']);
525
+ return out;
526
+ }
527
+ function transformTimesheet(raw) {
528
+ if (!raw || typeof raw !== 'object') return {};
529
+ const r = raw;
530
+ const out = {};
531
+ // core
532
+ if ('id' in r) out['id'] = r['id'];
533
+ if ('employee_id' in r) out['employeeId'] = str(r['employee_id']);
534
+ if ('project_id' in r) out['projectId'] = str(r['project_id']);
535
+ if ('start_time' in r) out['startTime'] = str(r['start_time']);
536
+ if ('end_time' in r) out['endTime'] = str(r['end_time']);
537
+ if ('duration_minutes' in r) out['durationMinutes'] = num(r['duration_minutes']);
538
+ if ('billable' in r) out['billable'] = bool(r['billable']);
539
+ // details
540
+ if ('description' in r) out['description'] = str(r['description']);
541
+ if ('activity_name' in r) out['activityName'] = str(r['activity_name']);
542
+ // integrations
543
+ if ('source' in r) out['source'] = str(r['source']);
544
+ if ('kimai_id' in r) out['kimaiId'] = str(r['kimai_id']);
545
+ if ('kimai_activity_id' in r) out['kimaiActivityId'] = str(r['kimai_activity_id']);
546
+ // expand: employee / project
547
+ if ('employee' in r) {
548
+ out['employee'] = r['employee'] ? transformEmployee(r['employee']) : null;
549
+ }
550
+ if ('project' in r) {
551
+ out['project'] = r['project'] ? transformProject(r['project']) : null;
552
+ }
553
+ return out;
554
+ }
347
555
 
348
556
  class EmployeesAccessor {
349
557
  constructor(transport){
@@ -403,6 +611,27 @@ class ProjectsAccessor {
403
611
  data: transformProject(result.data)
404
612
  };
405
613
  }
614
+ /** Create a project. Requires `projects.create` scope. */ async create(data) {
615
+ const result = await this.transport.post('/api/v1/data/projects', toSnakeBody(data));
616
+ if ('error' in result) return result;
617
+ return {
618
+ data: transformProject(result.data)
619
+ };
620
+ }
621
+ /** Update a project. Requires `projects.update` scope. */ async update(id, data) {
622
+ const result = await this.transport.put(`/api/v1/data/projects/${id}`, toSnakeBody(data));
623
+ if ('error' in result) return result;
624
+ return {
625
+ data: transformProject(result.data)
626
+ };
627
+ }
628
+ /** Soft-delete a project. Requires `projects.delete` scope. */ async delete(id) {
629
+ const result = await this.transport.del(`/api/v1/data/projects/${id}`);
630
+ if ('error' in result) return result;
631
+ return {
632
+ data: null
633
+ };
634
+ }
406
635
  }
407
636
 
408
637
  class ClientsAccessor {
@@ -433,6 +662,27 @@ class ClientsAccessor {
433
662
  data: transformClient(result.data)
434
663
  };
435
664
  }
665
+ /** Create a client. Requires `clients.create` scope. */ async create(data) {
666
+ const result = await this.transport.post('/api/v1/data/clients', toSnakeBody(data));
667
+ if ('error' in result) return result;
668
+ return {
669
+ data: transformClient(result.data)
670
+ };
671
+ }
672
+ /** Update a client. Requires `clients.update` scope. */ async update(id, data) {
673
+ const result = await this.transport.put(`/api/v1/data/clients/${id}`, toSnakeBody(data));
674
+ if ('error' in result) return result;
675
+ return {
676
+ data: transformClient(result.data)
677
+ };
678
+ }
679
+ /** Soft-delete a client. Requires `clients.delete` scope. */ async delete(id) {
680
+ const result = await this.transport.del(`/api/v1/data/clients/${id}`);
681
+ if ('error' in result) return result;
682
+ return {
683
+ data: null
684
+ };
685
+ }
436
686
  }
437
687
 
438
688
  class PartnersAccessor {
@@ -461,6 +711,27 @@ class PartnersAccessor {
461
711
  data: transformPartner(result.data)
462
712
  };
463
713
  }
714
+ /** Create a partner. Requires `partners.create` scope. */ async create(data) {
715
+ const result = await this.transport.post('/api/v1/data/partners', toSnakeBody(data));
716
+ if ('error' in result) return result;
717
+ return {
718
+ data: transformPartner(result.data)
719
+ };
720
+ }
721
+ /** Update a partner. Requires `partners.update` scope. */ async update(id, data) {
722
+ const result = await this.transport.put(`/api/v1/data/partners/${id}`, toSnakeBody(data));
723
+ if ('error' in result) return result;
724
+ return {
725
+ data: transformPartner(result.data)
726
+ };
727
+ }
728
+ /** Soft-delete a partner. Requires `partners.delete` scope. */ async delete(id) {
729
+ const result = await this.transport.del(`/api/v1/data/partners/${id}`);
730
+ if ('error' in result) return result;
731
+ return {
732
+ data: null
733
+ };
734
+ }
464
735
  }
465
736
 
466
737
  class DepartmentsAccessor {
@@ -486,6 +757,27 @@ class DepartmentsAccessor {
486
757
  data: transformDepartment(result.data)
487
758
  };
488
759
  }
760
+ /** Create a department. Requires `departments.create` scope. */ async create(data) {
761
+ const result = await this.transport.post('/api/v1/data/departments', toSnakeBody(data));
762
+ if ('error' in result) return result;
763
+ return {
764
+ data: transformDepartment(result.data)
765
+ };
766
+ }
767
+ /** Update a department. Requires `departments.update` scope. */ async update(id, data) {
768
+ const result = await this.transport.put(`/api/v1/data/departments/${id}`, toSnakeBody(data));
769
+ if ('error' in result) return result;
770
+ return {
771
+ data: transformDepartment(result.data)
772
+ };
773
+ }
774
+ /** Soft-delete a department. Requires `departments.delete` scope. */ async delete(id) {
775
+ const result = await this.transport.del(`/api/v1/data/departments/${id}`);
776
+ if ('error' in result) return result;
777
+ return {
778
+ data: null
779
+ };
780
+ }
489
781
  }
490
782
 
491
783
  class ProjectTypesAccessor {
@@ -510,6 +802,27 @@ class ProjectTypesAccessor {
510
802
  data: transformProjectType(result.data)
511
803
  };
512
804
  }
805
+ /** Create a project type. Requires `projectTypes.create` scope. */ async create(data) {
806
+ const result = await this.transport.post('/api/v1/data/project-types', toSnakeBody(data));
807
+ if ('error' in result) return result;
808
+ return {
809
+ data: transformProjectType(result.data)
810
+ };
811
+ }
812
+ /** Update a project type. Requires `projectTypes.update` scope. */ async update(id, data) {
813
+ const result = await this.transport.put(`/api/v1/data/project-types/${id}`, toSnakeBody(data));
814
+ if ('error' in result) return result;
815
+ return {
816
+ data: transformProjectType(result.data)
817
+ };
818
+ }
819
+ /** Soft-delete a project type. Requires `projectTypes.delete` scope. */ async delete(id) {
820
+ const result = await this.transport.del(`/api/v1/data/project-types/${id}`);
821
+ if ('error' in result) return result;
822
+ return {
823
+ data: null
824
+ };
825
+ }
513
826
  }
514
827
 
515
828
  class CurrenciesAccessor {
@@ -534,6 +847,30 @@ class CurrenciesAccessor {
534
847
  data: transformCurrency(result.data)
535
848
  };
536
849
  }
850
+ /** Create a currency. Requires `currencies.create` scope. */ async create(data) {
851
+ const result = await this.transport.post('/api/v1/data/currencies', toSnakeBody(data));
852
+ if ('error' in result) return result;
853
+ return {
854
+ data: transformCurrency(result.data)
855
+ };
856
+ }
857
+ /**
858
+ * Update a currency (keyed by its ISO code; `code` itself is immutable).
859
+ * Requires `currencies.update` scope.
860
+ */ async update(code, data) {
861
+ const result = await this.transport.put(`/api/v1/data/currencies/${code}`, toSnakeBody(data));
862
+ if ('error' in result) return result;
863
+ return {
864
+ data: transformCurrency(result.data)
865
+ };
866
+ }
867
+ /** Soft-delete a currency (keyed by its ISO code). Requires `currencies.delete` scope. */ async delete(code) {
868
+ const result = await this.transport.del(`/api/v1/data/currencies/${code}`);
869
+ if ('error' in result) return result;
870
+ return {
871
+ data: null
872
+ };
873
+ }
537
874
  }
538
875
 
539
876
  class GenericRatesAccessor {
@@ -559,6 +896,415 @@ class GenericRatesAccessor {
559
896
  data: transformGenericRate(result.data)
560
897
  };
561
898
  }
899
+ /** Create a generic rate. Requires `genericRates.create` scope. */ async create(data) {
900
+ const result = await this.transport.post('/api/v1/data/generic-rates', toSnakeBody(data));
901
+ if ('error' in result) return result;
902
+ return {
903
+ data: transformGenericRate(result.data)
904
+ };
905
+ }
906
+ /** Update a generic rate. Requires `genericRates.update` scope. */ async update(id, data) {
907
+ const result = await this.transport.put(`/api/v1/data/generic-rates/${id}`, toSnakeBody(data));
908
+ if ('error' in result) return result;
909
+ return {
910
+ data: transformGenericRate(result.data)
911
+ };
912
+ }
913
+ /** Soft-delete a generic rate. Requires `genericRates.delete` scope. */ async delete(id) {
914
+ const result = await this.transport.del(`/api/v1/data/generic-rates/${id}`);
915
+ if ('error' in result) return result;
916
+ return {
917
+ data: null
918
+ };
919
+ }
920
+ }
921
+
922
+ class JurisdictionsAccessor {
923
+ constructor(transport){
924
+ this.transport = transport;
925
+ }
926
+ async list(params) {
927
+ const query = {};
928
+ if (params?.search) query['search'] = params.search;
929
+ if (params?.page) query['page'] = params.page;
930
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
931
+ const result = await this.transport.getList('/api/v1/data/jurisdictions', query);
932
+ if ('error' in result) return result;
933
+ return {
934
+ data: result.data.map((r)=>transformJurisdiction(r)),
935
+ meta: result.meta
936
+ };
937
+ }
938
+ async getById(id) {
939
+ const result = await this.transport.get(`/api/v1/data/jurisdictions/${id}`);
940
+ if ('error' in result) return result;
941
+ return {
942
+ data: transformJurisdiction(result.data)
943
+ };
944
+ }
945
+ /** Create a jurisdiction. Requires `jurisdictions.create` scope. */ async create(data) {
946
+ const result = await this.transport.post('/api/v1/data/jurisdictions', toSnakeBody(data));
947
+ if ('error' in result) return result;
948
+ return {
949
+ data: transformJurisdiction(result.data)
950
+ };
951
+ }
952
+ /** Update a jurisdiction. Requires `jurisdictions.update` scope. */ async update(id, data) {
953
+ const result = await this.transport.put(`/api/v1/data/jurisdictions/${id}`, toSnakeBody(data));
954
+ if ('error' in result) return result;
955
+ return {
956
+ data: transformJurisdiction(result.data)
957
+ };
958
+ }
959
+ /** Soft-delete a jurisdiction. Requires `jurisdictions.delete` scope. */ async delete(id) {
960
+ const result = await this.transport.del(`/api/v1/data/jurisdictions/${id}`);
961
+ if ('error' in result) return result;
962
+ return {
963
+ data: null
964
+ };
965
+ }
966
+ }
967
+
968
+ class LeaveTypesAccessor {
969
+ constructor(transport){
970
+ this.transport = transport;
971
+ }
972
+ async list(params) {
973
+ const query = {};
974
+ if (params?.search) query['search'] = params.search;
975
+ if (params?.page) query['page'] = params.page;
976
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
977
+ const result = await this.transport.getList('/api/v1/data/leave-types', query);
978
+ if ('error' in result) return result;
979
+ return {
980
+ data: result.data.map((r)=>transformLeaveType(r)),
981
+ meta: result.meta
982
+ };
983
+ }
984
+ async getById(id) {
985
+ const result = await this.transport.get(`/api/v1/data/leave-types/${id}`);
986
+ if ('error' in result) return result;
987
+ return {
988
+ data: transformLeaveType(result.data)
989
+ };
990
+ }
991
+ /** Create a leave type. Requires `leaveTypes.create` scope. */ async create(data) {
992
+ const result = await this.transport.post('/api/v1/data/leave-types', toSnakeBody(data));
993
+ if ('error' in result) return result;
994
+ return {
995
+ data: transformLeaveType(result.data)
996
+ };
997
+ }
998
+ /** Update a leave type. Requires `leaveTypes.update` scope. */ async update(id, data) {
999
+ const result = await this.transport.put(`/api/v1/data/leave-types/${id}`, toSnakeBody(data));
1000
+ if ('error' in result) return result;
1001
+ return {
1002
+ data: transformLeaveType(result.data)
1003
+ };
1004
+ }
1005
+ /** Soft-delete a leave type. Requires `leaveTypes.delete` scope. */ async delete(id) {
1006
+ const result = await this.transport.del(`/api/v1/data/leave-types/${id}`);
1007
+ if ('error' in result) return result;
1008
+ return {
1009
+ data: null
1010
+ };
1011
+ }
1012
+ }
1013
+
1014
+ class LeavesAccessor {
1015
+ constructor(transport){
1016
+ this.transport = transport;
1017
+ }
1018
+ async list(params) {
1019
+ const query = {};
1020
+ if (params?.employeeId) query['employeeId'] = params.employeeId;
1021
+ if (params?.leaveTypeId) query['leaveTypeId'] = params.leaveTypeId;
1022
+ if (params?.status) query['status'] = params.status;
1023
+ if (params?.page) query['page'] = params.page;
1024
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
1025
+ if (params?.expand?.length) query['expand'] = params.expand.join(',');
1026
+ const result = await this.transport.getList('/api/v1/data/leaves', query);
1027
+ if ('error' in result) return result;
1028
+ return {
1029
+ data: result.data.map((r)=>transformLeave(r)),
1030
+ meta: result.meta
1031
+ };
1032
+ }
1033
+ async getById(id, options) {
1034
+ const query = {};
1035
+ if (options?.expand?.length) query['expand'] = options.expand.join(',');
1036
+ const result = await this.transport.get(`/api/v1/data/leaves/${id}`, query);
1037
+ if ('error' in result) return result;
1038
+ return {
1039
+ data: transformLeave(result.data)
1040
+ };
1041
+ }
1042
+ /** Create a leave record. Requires `leaves.create` scope. */ async create(data) {
1043
+ const result = await this.transport.post('/api/v1/data/leaves', toSnakeBody(data));
1044
+ if ('error' in result) return result;
1045
+ return {
1046
+ data: transformLeave(result.data)
1047
+ };
1048
+ }
1049
+ /** Update a leave record. Requires `leaves.update` scope. */ async update(id, data) {
1050
+ const result = await this.transport.put(`/api/v1/data/leaves/${id}`, toSnakeBody(data));
1051
+ if ('error' in result) return result;
1052
+ return {
1053
+ data: transformLeave(result.data)
1054
+ };
1055
+ }
1056
+ /** Soft-delete a leave record. Requires `leaves.delete` scope. */ async delete(id) {
1057
+ const result = await this.transport.del(`/api/v1/data/leaves/${id}`);
1058
+ if ('error' in result) return result;
1059
+ return {
1060
+ data: null
1061
+ };
1062
+ }
1063
+ }
1064
+
1065
+ class LeaveBalancesAccessor {
1066
+ constructor(transport){
1067
+ this.transport = transport;
1068
+ }
1069
+ async list(params) {
1070
+ const query = {};
1071
+ if (params?.employeeId) query['employeeId'] = params.employeeId;
1072
+ if (params?.leaveTypeId) query['leaveTypeId'] = params.leaveTypeId;
1073
+ if (params?.year) query['year'] = params.year;
1074
+ if (params?.page) query['page'] = params.page;
1075
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
1076
+ if (params?.expand?.length) query['expand'] = params.expand.join(',');
1077
+ const result = await this.transport.getList('/api/v1/data/leave-balances', query);
1078
+ if ('error' in result) return result;
1079
+ return {
1080
+ data: result.data.map((r)=>transformLeaveBalance(r)),
1081
+ meta: result.meta
1082
+ };
1083
+ }
1084
+ async getById(id, options) {
1085
+ const query = {};
1086
+ if (options?.expand?.length) query['expand'] = options.expand.join(',');
1087
+ const result = await this.transport.get(`/api/v1/data/leave-balances/${id}`, query);
1088
+ if ('error' in result) return result;
1089
+ return {
1090
+ data: transformLeaveBalance(result.data)
1091
+ };
1092
+ }
1093
+ /** Create a leave balance. Requires `leaveBalances.create` scope. */ async create(data) {
1094
+ const result = await this.transport.post('/api/v1/data/leave-balances', toSnakeBody(data));
1095
+ if ('error' in result) return result;
1096
+ return {
1097
+ data: transformLeaveBalance(result.data)
1098
+ };
1099
+ }
1100
+ /** Update a leave balance. Requires `leaveBalances.update` scope. */ async update(id, data) {
1101
+ const result = await this.transport.put(`/api/v1/data/leave-balances/${id}`, toSnakeBody(data));
1102
+ if ('error' in result) return result;
1103
+ return {
1104
+ data: transformLeaveBalance(result.data)
1105
+ };
1106
+ }
1107
+ /** Soft-delete a leave balance. Requires `leaveBalances.delete` scope. */ async delete(id) {
1108
+ const result = await this.transport.del(`/api/v1/data/leave-balances/${id}`);
1109
+ if ('error' in result) return result;
1110
+ return {
1111
+ data: null
1112
+ };
1113
+ }
1114
+ }
1115
+
1116
+ class PoliciesAccessor {
1117
+ constructor(transport){
1118
+ this.transport = transport;
1119
+ }
1120
+ async list(params) {
1121
+ const query = {};
1122
+ if (params?.search) query['search'] = params.search;
1123
+ if (params?.category) query['category'] = params.category;
1124
+ if (params?.page) query['page'] = params.page;
1125
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
1126
+ const result = await this.transport.getList('/api/v1/data/policies', query);
1127
+ if ('error' in result) return result;
1128
+ return {
1129
+ data: result.data.map((r)=>transformPolicy(r)),
1130
+ meta: result.meta
1131
+ };
1132
+ }
1133
+ async getById(id) {
1134
+ const result = await this.transport.get(`/api/v1/data/policies/${id}`);
1135
+ if ('error' in result) return result;
1136
+ return {
1137
+ data: transformPolicy(result.data)
1138
+ };
1139
+ }
1140
+ /** Create a policy. Requires `policies.create` scope. */ async create(data) {
1141
+ const result = await this.transport.post('/api/v1/data/policies', toSnakeBody(data));
1142
+ if ('error' in result) return result;
1143
+ return {
1144
+ data: transformPolicy(result.data)
1145
+ };
1146
+ }
1147
+ /** Update a policy. Requires `policies.update` scope. */ async update(id, data) {
1148
+ const result = await this.transport.put(`/api/v1/data/policies/${id}`, toSnakeBody(data));
1149
+ if ('error' in result) return result;
1150
+ return {
1151
+ data: transformPolicy(result.data)
1152
+ };
1153
+ }
1154
+ /** Soft-delete a policy. Requires `policies.delete` scope. */ async delete(id) {
1155
+ const result = await this.transport.del(`/api/v1/data/policies/${id}`);
1156
+ if ('error' in result) return result;
1157
+ return {
1158
+ data: null
1159
+ };
1160
+ }
1161
+ }
1162
+
1163
+ class PolicyAcknowledgementsAccessor {
1164
+ constructor(transport){
1165
+ this.transport = transport;
1166
+ }
1167
+ async list(params) {
1168
+ const query = {};
1169
+ if (params?.policyId) query['policyId'] = params.policyId;
1170
+ if (params?.employeeId) query['employeeId'] = params.employeeId;
1171
+ if (params?.page) query['page'] = params.page;
1172
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
1173
+ if (params?.expand?.length) query['expand'] = params.expand.join(',');
1174
+ const result = await this.transport.getList('/api/v1/data/policy-acknowledgements', query);
1175
+ if ('error' in result) return result;
1176
+ return {
1177
+ data: result.data.map((r)=>transformPolicyAcknowledgement(r)),
1178
+ meta: result.meta
1179
+ };
1180
+ }
1181
+ async getById(id, options) {
1182
+ const query = {};
1183
+ if (options?.expand?.length) query['expand'] = options.expand.join(',');
1184
+ const result = await this.transport.get(`/api/v1/data/policy-acknowledgements/${id}`, query);
1185
+ if ('error' in result) return result;
1186
+ return {
1187
+ data: transformPolicyAcknowledgement(result.data)
1188
+ };
1189
+ }
1190
+ /** Create a policy acknowledgement. Requires `policyAcknowledgements.create` scope. */ async create(data) {
1191
+ const result = await this.transport.post('/api/v1/data/policy-acknowledgements', toSnakeBody(data));
1192
+ if ('error' in result) return result;
1193
+ return {
1194
+ data: transformPolicyAcknowledgement(result.data)
1195
+ };
1196
+ }
1197
+ /** Update a policy acknowledgement. Requires `policyAcknowledgements.update` scope. */ async update(id, data) {
1198
+ const result = await this.transport.put(`/api/v1/data/policy-acknowledgements/${id}`, toSnakeBody(data));
1199
+ if ('error' in result) return result;
1200
+ return {
1201
+ data: transformPolicyAcknowledgement(result.data)
1202
+ };
1203
+ }
1204
+ /** Soft-delete a policy acknowledgement. Requires `policyAcknowledgements.delete` scope. */ async delete(id) {
1205
+ const result = await this.transport.del(`/api/v1/data/policy-acknowledgements/${id}`);
1206
+ if ('error' in result) return result;
1207
+ return {
1208
+ data: null
1209
+ };
1210
+ }
1211
+ }
1212
+
1213
+ class CalendarEventsAccessor {
1214
+ constructor(transport){
1215
+ this.transport = transport;
1216
+ }
1217
+ async list(params) {
1218
+ const query = {};
1219
+ if (params?.search) query['search'] = params.search;
1220
+ if (params?.type) query['type'] = params.type;
1221
+ if (params?.page) query['page'] = params.page;
1222
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
1223
+ const result = await this.transport.getList('/api/v1/data/calendar-events', query);
1224
+ if ('error' in result) return result;
1225
+ return {
1226
+ data: result.data.map((r)=>transformCalendarEvent(r)),
1227
+ meta: result.meta
1228
+ };
1229
+ }
1230
+ async getById(id) {
1231
+ const result = await this.transport.get(`/api/v1/data/calendar-events/${id}`);
1232
+ if ('error' in result) return result;
1233
+ return {
1234
+ data: transformCalendarEvent(result.data)
1235
+ };
1236
+ }
1237
+ /** Create a calendar event. Requires `calendarEvents.create` scope. */ async create(data) {
1238
+ const result = await this.transport.post('/api/v1/data/calendar-events', toSnakeBody(data));
1239
+ if ('error' in result) return result;
1240
+ return {
1241
+ data: transformCalendarEvent(result.data)
1242
+ };
1243
+ }
1244
+ /** Update a calendar event. Requires `calendarEvents.update` scope. */ async update(id, data) {
1245
+ const result = await this.transport.put(`/api/v1/data/calendar-events/${id}`, toSnakeBody(data));
1246
+ if ('error' in result) return result;
1247
+ return {
1248
+ data: transformCalendarEvent(result.data)
1249
+ };
1250
+ }
1251
+ /** Soft-delete a calendar event. Requires `calendarEvents.delete` scope. */ async delete(id) {
1252
+ const result = await this.transport.del(`/api/v1/data/calendar-events/${id}`);
1253
+ if ('error' in result) return result;
1254
+ return {
1255
+ data: null
1256
+ };
1257
+ }
1258
+ }
1259
+
1260
+ class TimesheetsAccessor {
1261
+ constructor(transport){
1262
+ this.transport = transport;
1263
+ }
1264
+ async list(params) {
1265
+ const query = {};
1266
+ if (params?.employeeId) query['employeeId'] = params.employeeId;
1267
+ if (params?.projectId) query['projectId'] = params.projectId;
1268
+ if (params?.page) query['page'] = params.page;
1269
+ if (params?.pageSize) query['pageSize'] = params.pageSize;
1270
+ if (params?.expand?.length) query['expand'] = params.expand.join(',');
1271
+ const result = await this.transport.getList('/api/v1/data/timesheets', query);
1272
+ if ('error' in result) return result;
1273
+ return {
1274
+ data: result.data.map((r)=>transformTimesheet(r)),
1275
+ meta: result.meta
1276
+ };
1277
+ }
1278
+ async getById(id, options) {
1279
+ const query = {};
1280
+ if (options?.expand?.length) query['expand'] = options.expand.join(',');
1281
+ const result = await this.transport.get(`/api/v1/data/timesheets/${id}`, query);
1282
+ if ('error' in result) return result;
1283
+ return {
1284
+ data: transformTimesheet(result.data)
1285
+ };
1286
+ }
1287
+ /** Create a timesheet entry. Requires `timesheets.create` scope. */ async create(data) {
1288
+ const result = await this.transport.post('/api/v1/data/timesheets', toSnakeBody(data));
1289
+ if ('error' in result) return result;
1290
+ return {
1291
+ data: transformTimesheet(result.data)
1292
+ };
1293
+ }
1294
+ /** Update a timesheet entry. Requires `timesheets.update` scope. */ async update(id, data) {
1295
+ const result = await this.transport.put(`/api/v1/data/timesheets/${id}`, toSnakeBody(data));
1296
+ if ('error' in result) return result;
1297
+ return {
1298
+ data: transformTimesheet(result.data)
1299
+ };
1300
+ }
1301
+ /** Soft-delete a timesheet entry. Requires `timesheets.delete` scope. */ async delete(id) {
1302
+ const result = await this.transport.del(`/api/v1/data/timesheets/${id}`);
1303
+ if ('error' in result) return result;
1304
+ return {
1305
+ data: null
1306
+ };
1307
+ }
562
1308
  }
563
1309
 
564
1310
  /**
@@ -693,9 +1439,9 @@ class AuthAccessor {
693
1439
  * export const nucleus = new NucleusClient({
694
1440
  * token: process.env.NUCLEUS_TOKEN!,
695
1441
  * scopes: {
696
- * employees: ['identity', 'employment'],
697
- * projects: ['core'],
698
- * clients: ['identity'],
1442
+ * employees: { read: ['identity', 'employment'], update: ['contact'] },
1443
+ * projects: { read: ['core'] },
1444
+ * leaves: { read: ['core'], create: ['core'], delete: true },
699
1445
  * },
700
1446
  * });
701
1447
  * ```
@@ -714,6 +1460,14 @@ class AuthAccessor {
714
1460
  this.projectTypes = new ProjectTypesAccessor(transport);
715
1461
  this.currencies = new CurrenciesAccessor(transport);
716
1462
  this.genericRates = new GenericRatesAccessor(transport);
1463
+ this.jurisdictions = new JurisdictionsAccessor(transport);
1464
+ this.leaveTypes = new LeaveTypesAccessor(transport);
1465
+ this.leaves = new LeavesAccessor(transport);
1466
+ this.leaveBalances = new LeaveBalancesAccessor(transport);
1467
+ this.policies = new PoliciesAccessor(transport);
1468
+ this.policyAcknowledgements = new PolicyAcknowledgementsAccessor(transport);
1469
+ this.calendarEvents = new CalendarEventsAccessor(transport);
1470
+ this.timesheets = new TimesheetsAccessor(transport);
717
1471
  this.apps = new AppsAccessor(transport);
718
1472
  this.files = new FilesAccessor(transport);
719
1473
  this.auth = new AuthAccessor(config.baseUrl);