@typeb-digital/nucleus-sdk 0.1.1 → 0.2.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/cjs/index.cjs +291 -2
- package/dist/cjs/index.d.cts +285 -4
- package/dist/cjs/index.d.cts.map +1 -1
- package/dist/es/index.d.ts +285 -4
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +291 -2
- package/package.json +1 -1
package/dist/es/index.js
CHANGED
|
@@ -366,7 +366,6 @@ function transformDepartment(raw) {
|
|
|
366
366
|
const out = {};
|
|
367
367
|
if ('id' in r) out['id'] = r['id'];
|
|
368
368
|
if ('name' in r) out['name'] = str(r['name']);
|
|
369
|
-
if ('titles' in r) out['titles'] = Array.isArray(r['titles']) ? r['titles'] : [];
|
|
370
369
|
if ('sort_order' in r) out['sortOrder'] = num(r['sort_order']) ?? 0;
|
|
371
370
|
return out;
|
|
372
371
|
}
|
|
@@ -413,6 +412,30 @@ function transformJurisdiction(raw) {
|
|
|
413
412
|
if ('country' in r) out['country'] = str(r['country']);
|
|
414
413
|
return out;
|
|
415
414
|
}
|
|
415
|
+
function transformJobLevel(raw) {
|
|
416
|
+
if (!raw || typeof raw !== 'object') return {};
|
|
417
|
+
const r = raw;
|
|
418
|
+
const out = {};
|
|
419
|
+
if ('id' in r) out['id'] = r['id'];
|
|
420
|
+
if ('name' in r) out['name'] = str(r['name']);
|
|
421
|
+
if ('code' in r) out['code'] = str(r['code']);
|
|
422
|
+
if ('department_id' in r) out['departmentId'] = str(r['department_id']);
|
|
423
|
+
if ('sort_order' in r) out['sortOrder'] = num(r['sort_order']) ?? 0;
|
|
424
|
+
return out;
|
|
425
|
+
}
|
|
426
|
+
function transformSalaryBand(raw) {
|
|
427
|
+
if (!raw || typeof raw !== 'object') return {};
|
|
428
|
+
const r = raw;
|
|
429
|
+
const out = {};
|
|
430
|
+
if ('id' in r) out['id'] = r['id'];
|
|
431
|
+
if ('job_level_id' in r) out['jobLevelId'] = str(r['job_level_id']);
|
|
432
|
+
if ('jurisdiction_id' in r) out['jurisdictionId'] = str(r['jurisdiction_id']);
|
|
433
|
+
if ('currency_code' in r) out['currencyCode'] = str(r['currency_code']);
|
|
434
|
+
if ('min_salary' in r) out['minSalary'] = num(r['min_salary']);
|
|
435
|
+
if ('max_salary' in r) out['maxSalary'] = num(r['max_salary']);
|
|
436
|
+
if ('target_salary' in r) out['targetSalary'] = num(r['target_salary']);
|
|
437
|
+
return out;
|
|
438
|
+
}
|
|
416
439
|
function transformLeaveType(raw) {
|
|
417
440
|
if (!raw || typeof raw !== 'object') return {};
|
|
418
441
|
const r = raw;
|
|
@@ -564,6 +587,7 @@ class EmployeesAccessor {
|
|
|
564
587
|
if (params?.employmentStatus) query['employmentStatus'] = params.employmentStatus;
|
|
565
588
|
if (params?.page) query['page'] = params.page;
|
|
566
589
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
590
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
567
591
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
568
592
|
const result = await this.transport.getList('/api/v1/data/employees', query);
|
|
569
593
|
if ('error' in result) return result;
|
|
@@ -583,6 +607,14 @@ class EmployeesAccessor {
|
|
|
583
607
|
}
|
|
584
608
|
}
|
|
585
609
|
|
|
610
|
+
function transformMember(raw) {
|
|
611
|
+
return {
|
|
612
|
+
id: raw['id'],
|
|
613
|
+
projectId: raw['project_id'],
|
|
614
|
+
employeeId: raw['employee_id'],
|
|
615
|
+
role: raw['role'] ?? null
|
|
616
|
+
};
|
|
617
|
+
}
|
|
586
618
|
class ProjectsAccessor {
|
|
587
619
|
constructor(transport){
|
|
588
620
|
this.transport = transport;
|
|
@@ -591,9 +623,11 @@ class ProjectsAccessor {
|
|
|
591
623
|
const query = {};
|
|
592
624
|
if (params?.search) query['search'] = params.search;
|
|
593
625
|
if (params?.status) query['status'] = params.status;
|
|
626
|
+
if (params?.stage) query['stage'] = params.stage;
|
|
594
627
|
if (params?.clientId) query['clientId'] = params.clientId;
|
|
595
628
|
if (params?.page) query['page'] = params.page;
|
|
596
629
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
630
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
597
631
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
598
632
|
const result = await this.transport.getList('/api/v1/data/projects', query);
|
|
599
633
|
if ('error' in result) return result;
|
|
@@ -632,6 +666,33 @@ class ProjectsAccessor {
|
|
|
632
666
|
data: null
|
|
633
667
|
};
|
|
634
668
|
}
|
|
669
|
+
// ─── Team membership (the projects `team` bucket) ──────────────────────────
|
|
670
|
+
// Membership is the project↔employee join. Reads need `projects` read on `team`;
|
|
671
|
+
// add/remove need `projects` update on `team` (re-adding restores a soft-deleted row).
|
|
672
|
+
membersBase(projectId) {
|
|
673
|
+
return `/api/v1/data/project-memberships/projects/${projectId}/members`;
|
|
674
|
+
}
|
|
675
|
+
/** List a project's team members. Requires `projects` read on the `team` bucket. */ async listMembers(projectId) {
|
|
676
|
+
const result = await this.transport.get(this.membersBase(projectId));
|
|
677
|
+
if ('error' in result) return result;
|
|
678
|
+
return {
|
|
679
|
+
data: (result.data ?? []).map((r)=>transformMember(r))
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
/** Add a team member. Requires `projects` update on the `team` bucket. */ async addMember(projectId, data) {
|
|
683
|
+
const result = await this.transport.post(this.membersBase(projectId), toSnakeBody(data));
|
|
684
|
+
if ('error' in result) return result;
|
|
685
|
+
return {
|
|
686
|
+
data: transformMember(result.data)
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
/** Remove a team member. Requires `projects` update on the `team` bucket. */ async removeMember(projectId, employeeId) {
|
|
690
|
+
const result = await this.transport.del(`${this.membersBase(projectId)}/${employeeId}`);
|
|
691
|
+
if ('error' in result) return result;
|
|
692
|
+
return {
|
|
693
|
+
data: null
|
|
694
|
+
};
|
|
695
|
+
}
|
|
635
696
|
}
|
|
636
697
|
|
|
637
698
|
class ClientsAccessor {
|
|
@@ -645,6 +706,7 @@ class ClientsAccessor {
|
|
|
645
706
|
if (params?.country) query['country'] = params.country;
|
|
646
707
|
if (params?.page) query['page'] = params.page;
|
|
647
708
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
709
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
648
710
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
649
711
|
const result = await this.transport.getList('/api/v1/data/clients', query);
|
|
650
712
|
if ('error' in result) return result;
|
|
@@ -694,6 +756,7 @@ class PartnersAccessor {
|
|
|
694
756
|
if (params?.search) query['search'] = params.search;
|
|
695
757
|
if (params?.page) query['page'] = params.page;
|
|
696
758
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
759
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
697
760
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
698
761
|
const result = await this.transport.getList('/api/v1/data/partners', query);
|
|
699
762
|
if ('error' in result) return result;
|
|
@@ -743,6 +806,7 @@ class DepartmentsAccessor {
|
|
|
743
806
|
if (params?.search) query['search'] = params.search;
|
|
744
807
|
if (params?.page) query['page'] = params.page;
|
|
745
808
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
809
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
746
810
|
const result = await this.transport.getList('/api/v1/data/departments', query);
|
|
747
811
|
if ('error' in result) return result;
|
|
748
812
|
return {
|
|
@@ -788,6 +852,7 @@ class ProjectTypesAccessor {
|
|
|
788
852
|
const query = {};
|
|
789
853
|
if (params?.page) query['page'] = params.page;
|
|
790
854
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
855
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
791
856
|
const result = await this.transport.getList('/api/v1/data/project-types', query);
|
|
792
857
|
if ('error' in result) return result;
|
|
793
858
|
return {
|
|
@@ -833,6 +898,7 @@ class CurrenciesAccessor {
|
|
|
833
898
|
const query = {};
|
|
834
899
|
if (params?.page) query['page'] = params.page;
|
|
835
900
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
901
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
836
902
|
const result = await this.transport.getList('/api/v1/data/currencies', query);
|
|
837
903
|
if ('error' in result) return result;
|
|
838
904
|
return {
|
|
@@ -882,6 +948,7 @@ class GenericRatesAccessor {
|
|
|
882
948
|
if (params?.department) query['department'] = params.department;
|
|
883
949
|
if (params?.page) query['page'] = params.page;
|
|
884
950
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
951
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
885
952
|
const result = await this.transport.getList('/api/v1/data/generic-rates', query);
|
|
886
953
|
if ('error' in result) return result;
|
|
887
954
|
return {
|
|
@@ -928,6 +995,7 @@ class JurisdictionsAccessor {
|
|
|
928
995
|
if (params?.search) query['search'] = params.search;
|
|
929
996
|
if (params?.page) query['page'] = params.page;
|
|
930
997
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
998
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
931
999
|
const result = await this.transport.getList('/api/v1/data/jurisdictions', query);
|
|
932
1000
|
if ('error' in result) return result;
|
|
933
1001
|
return {
|
|
@@ -965,6 +1033,105 @@ class JurisdictionsAccessor {
|
|
|
965
1033
|
}
|
|
966
1034
|
}
|
|
967
1035
|
|
|
1036
|
+
/** JobLevelsAccessor — the company's career-ladder rungs (WS7). */ class JobLevelsAccessor {
|
|
1037
|
+
constructor(transport){
|
|
1038
|
+
this.transport = transport;
|
|
1039
|
+
}
|
|
1040
|
+
async list(params) {
|
|
1041
|
+
const query = {};
|
|
1042
|
+
if (params?.search) query['search'] = params.search;
|
|
1043
|
+
if (params?.departmentId) query['departmentId'] = params.departmentId;
|
|
1044
|
+
if (params?.page) query['page'] = params.page;
|
|
1045
|
+
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1046
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1047
|
+
const result = await this.transport.getList('/api/v1/data/job-levels', query);
|
|
1048
|
+
if ('error' in result) return result;
|
|
1049
|
+
return {
|
|
1050
|
+
data: result.data.map((r)=>transformJobLevel(r)),
|
|
1051
|
+
meta: result.meta
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
async getById(id) {
|
|
1055
|
+
const result = await this.transport.get(`/api/v1/data/job-levels/${id}`);
|
|
1056
|
+
if ('error' in result) return result;
|
|
1057
|
+
return {
|
|
1058
|
+
data: transformJobLevel(result.data)
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
/** Create a job level. Requires `job-levels.create` scope. */ async create(data) {
|
|
1062
|
+
const result = await this.transport.post('/api/v1/data/job-levels', toSnakeBody(data));
|
|
1063
|
+
if ('error' in result) return result;
|
|
1064
|
+
return {
|
|
1065
|
+
data: transformJobLevel(result.data)
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
/** Update a job level. Requires `job-levels.update` scope. */ async update(id, data) {
|
|
1069
|
+
const result = await this.transport.put(`/api/v1/data/job-levels/${id}`, toSnakeBody(data));
|
|
1070
|
+
if ('error' in result) return result;
|
|
1071
|
+
return {
|
|
1072
|
+
data: transformJobLevel(result.data)
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
/** Soft-delete a job level. Requires `job-levels.delete` scope. */ async delete(id) {
|
|
1076
|
+
const result = await this.transport.del(`/api/v1/data/job-levels/${id}`);
|
|
1077
|
+
if ('error' in result) return result;
|
|
1078
|
+
return {
|
|
1079
|
+
data: null
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
/**
|
|
1085
|
+
* SalaryBandsAccessor — per-jurisdiction pay ranges for a job level (WS7).
|
|
1086
|
+
* The `financials` bucket (min/max/target) is flagged sensitive server-side.
|
|
1087
|
+
*/ class SalaryBandsAccessor {
|
|
1088
|
+
constructor(transport){
|
|
1089
|
+
this.transport = transport;
|
|
1090
|
+
}
|
|
1091
|
+
async list(params) {
|
|
1092
|
+
const query = {};
|
|
1093
|
+
if (params?.jobLevelId) query['jobLevelId'] = params.jobLevelId;
|
|
1094
|
+
if (params?.jurisdictionId) query['jurisdictionId'] = params.jurisdictionId;
|
|
1095
|
+
if (params?.page) query['page'] = params.page;
|
|
1096
|
+
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1097
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1098
|
+
const result = await this.transport.getList('/api/v1/data/salary-bands', query);
|
|
1099
|
+
if ('error' in result) return result;
|
|
1100
|
+
return {
|
|
1101
|
+
data: result.data.map((r)=>transformSalaryBand(r)),
|
|
1102
|
+
meta: result.meta
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
async getById(id) {
|
|
1106
|
+
const result = await this.transport.get(`/api/v1/data/salary-bands/${id}`);
|
|
1107
|
+
if ('error' in result) return result;
|
|
1108
|
+
return {
|
|
1109
|
+
data: transformSalaryBand(result.data)
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
/** Create a salary band. Requires `salary-bands.create` scope. */ async create(data) {
|
|
1113
|
+
const result = await this.transport.post('/api/v1/data/salary-bands', toSnakeBody(data));
|
|
1114
|
+
if ('error' in result) return result;
|
|
1115
|
+
return {
|
|
1116
|
+
data: transformSalaryBand(result.data)
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
/** Update a salary band. Requires `salary-bands.update` scope. */ async update(id, data) {
|
|
1120
|
+
const result = await this.transport.put(`/api/v1/data/salary-bands/${id}`, toSnakeBody(data));
|
|
1121
|
+
if ('error' in result) return result;
|
|
1122
|
+
return {
|
|
1123
|
+
data: transformSalaryBand(result.data)
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
/** Soft-delete a salary band. Requires `salary-bands.delete` scope. */ async delete(id) {
|
|
1127
|
+
const result = await this.transport.del(`/api/v1/data/salary-bands/${id}`);
|
|
1128
|
+
if ('error' in result) return result;
|
|
1129
|
+
return {
|
|
1130
|
+
data: null
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
|
|
968
1135
|
class LeaveTypesAccessor {
|
|
969
1136
|
constructor(transport){
|
|
970
1137
|
this.transport = transport;
|
|
@@ -974,6 +1141,7 @@ class LeaveTypesAccessor {
|
|
|
974
1141
|
if (params?.search) query['search'] = params.search;
|
|
975
1142
|
if (params?.page) query['page'] = params.page;
|
|
976
1143
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1144
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
977
1145
|
const result = await this.transport.getList('/api/v1/data/leave-types', query);
|
|
978
1146
|
if ('error' in result) return result;
|
|
979
1147
|
return {
|
|
@@ -1022,6 +1190,7 @@ class LeavesAccessor {
|
|
|
1022
1190
|
if (params?.status) query['status'] = params.status;
|
|
1023
1191
|
if (params?.page) query['page'] = params.page;
|
|
1024
1192
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1193
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1025
1194
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
1026
1195
|
const result = await this.transport.getList('/api/v1/data/leaves', query);
|
|
1027
1196
|
if ('error' in result) return result;
|
|
@@ -1073,6 +1242,7 @@ class LeaveBalancesAccessor {
|
|
|
1073
1242
|
if (params?.year) query['year'] = params.year;
|
|
1074
1243
|
if (params?.page) query['page'] = params.page;
|
|
1075
1244
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1245
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1076
1246
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
1077
1247
|
const result = await this.transport.getList('/api/v1/data/leave-balances', query);
|
|
1078
1248
|
if ('error' in result) return result;
|
|
@@ -1123,6 +1293,7 @@ class PoliciesAccessor {
|
|
|
1123
1293
|
if (params?.category) query['category'] = params.category;
|
|
1124
1294
|
if (params?.page) query['page'] = params.page;
|
|
1125
1295
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1296
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1126
1297
|
const result = await this.transport.getList('/api/v1/data/policies', query);
|
|
1127
1298
|
if ('error' in result) return result;
|
|
1128
1299
|
return {
|
|
@@ -1170,6 +1341,7 @@ class PolicyAcknowledgementsAccessor {
|
|
|
1170
1341
|
if (params?.employeeId) query['employeeId'] = params.employeeId;
|
|
1171
1342
|
if (params?.page) query['page'] = params.page;
|
|
1172
1343
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1344
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1173
1345
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
1174
1346
|
const result = await this.transport.getList('/api/v1/data/policy-acknowledgements', query);
|
|
1175
1347
|
if ('error' in result) return result;
|
|
@@ -1218,8 +1390,10 @@ class CalendarEventsAccessor {
|
|
|
1218
1390
|
const query = {};
|
|
1219
1391
|
if (params?.search) query['search'] = params.search;
|
|
1220
1392
|
if (params?.type) query['type'] = params.type;
|
|
1393
|
+
if (params?.jurisdictionId) query['jurisdictionId'] = params.jurisdictionId;
|
|
1221
1394
|
if (params?.page) query['page'] = params.page;
|
|
1222
1395
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1396
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1223
1397
|
const result = await this.transport.getList('/api/v1/data/calendar-events', query);
|
|
1224
1398
|
if ('error' in result) return result;
|
|
1225
1399
|
return {
|
|
@@ -1267,6 +1441,7 @@ class TimesheetsAccessor {
|
|
|
1267
1441
|
if (params?.projectId) query['projectId'] = params.projectId;
|
|
1268
1442
|
if (params?.page) query['page'] = params.page;
|
|
1269
1443
|
if (params?.pageSize) query['pageSize'] = params.pageSize;
|
|
1444
|
+
if (params?.updatedSince) query['updatedSince'] = params.updatedSince;
|
|
1270
1445
|
if (params?.expand?.length) query['expand'] = params.expand.join(',');
|
|
1271
1446
|
const result = await this.transport.getList('/api/v1/data/timesheets', query);
|
|
1272
1447
|
if ('error' in result) return result;
|
|
@@ -1291,6 +1466,23 @@ class TimesheetsAccessor {
|
|
|
1291
1466
|
data: transformTimesheet(result.data)
|
|
1292
1467
|
};
|
|
1293
1468
|
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Bulk-create timesheet entries (partial accept). Requires `timesheets.create` scope.
|
|
1471
|
+
* Returns `{ created, rejected }` — every valid item is inserted; invalid items come back
|
|
1472
|
+
* with their input index + reason.
|
|
1473
|
+
*/ async bulkCreate(items) {
|
|
1474
|
+
const result = await this.transport.post('/api/v1/data/timesheets/bulk', {
|
|
1475
|
+
items: items.map((i)=>toSnakeBody(i))
|
|
1476
|
+
});
|
|
1477
|
+
if ('error' in result) return result;
|
|
1478
|
+
const data = result.data;
|
|
1479
|
+
return {
|
|
1480
|
+
data: {
|
|
1481
|
+
created: data.created.map((r)=>transformTimesheet(r)),
|
|
1482
|
+
rejected: data.rejected
|
|
1483
|
+
}
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1294
1486
|
/** Update a timesheet entry. Requires `timesheets.update` scope. */ async update(id, data) {
|
|
1295
1487
|
const result = await this.transport.put(`/api/v1/data/timesheets/${id}`, toSnakeBody(data));
|
|
1296
1488
|
if ('error' in result) return result;
|
|
@@ -1307,6 +1499,98 @@ class TimesheetsAccessor {
|
|
|
1307
1499
|
}
|
|
1308
1500
|
}
|
|
1309
1501
|
|
|
1502
|
+
/**
|
|
1503
|
+
* CalendarAccessor — read workspace users' Google Calendar events (WS3).
|
|
1504
|
+
* Requires the app's `calendar:read` scope. Not part of the bucket/CRUD scope system.
|
|
1505
|
+
*/ class CalendarAccessor {
|
|
1506
|
+
constructor(transport){
|
|
1507
|
+
this.transport = transport;
|
|
1508
|
+
}
|
|
1509
|
+
async listEvents(params) {
|
|
1510
|
+
const result = await this.transport.get('/api/v1/data/calendar/events', {
|
|
1511
|
+
employeeId: params.employeeId,
|
|
1512
|
+
timeMin: params.timeMin,
|
|
1513
|
+
timeMax: params.timeMax,
|
|
1514
|
+
q: params.q
|
|
1515
|
+
});
|
|
1516
|
+
if ('error' in result) return result;
|
|
1517
|
+
return {
|
|
1518
|
+
data: result.data
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* EmailAccessor — send Nucleus-mediated email (WS5). Requires the app's `email:send` scope.
|
|
1525
|
+
* In test mode the message is marked `[SANDBOX]` and external recipients are suppressed.
|
|
1526
|
+
*/ class EmailAccessor {
|
|
1527
|
+
constructor(transport){
|
|
1528
|
+
this.transport = transport;
|
|
1529
|
+
}
|
|
1530
|
+
async send(input) {
|
|
1531
|
+
const result = await this.transport.post('/api/v1/data/comms/send', input);
|
|
1532
|
+
if ('error' in result) return result;
|
|
1533
|
+
return {
|
|
1534
|
+
data: result.data
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
function transform(raw) {
|
|
1540
|
+
return {
|
|
1541
|
+
id: raw['id'],
|
|
1542
|
+
employeeId: raw['employee_id'],
|
|
1543
|
+
hourlyCostRate: raw['hourly_cost_rate'] ?? null,
|
|
1544
|
+
monthlyCostRate: raw['monthly_cost_rate'] ?? null,
|
|
1545
|
+
hourlyBillableRate: raw['hourly_billable_rate'] ?? null,
|
|
1546
|
+
monthlyBillableRate: raw['monthly_billable_rate'] ?? null,
|
|
1547
|
+
salary: raw['salary'] ?? null,
|
|
1548
|
+
currencyCode: raw['currency_code'],
|
|
1549
|
+
effectiveFrom: raw['effective_from'],
|
|
1550
|
+
effectiveTo: raw['effective_to'] ?? null
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
/**
|
|
1554
|
+
* EmployeeCompensationAccessor — read/write an employee's effective-dated compensation (WS6).
|
|
1555
|
+
* Gated server-side by the `employee-compensation` scope (buckets: `core`, `rates`, `salary`).
|
|
1556
|
+
* `create` closes the prior open record and opens a new one (Nucleus = single comp authority).
|
|
1557
|
+
*/ class EmployeeCompensationAccessor {
|
|
1558
|
+
constructor(transport){
|
|
1559
|
+
this.transport = transport;
|
|
1560
|
+
}
|
|
1561
|
+
base(employeeId) {
|
|
1562
|
+
return `/api/v1/data/employee-compensation/employees/${employeeId}/compensation`;
|
|
1563
|
+
}
|
|
1564
|
+
/** Full history, newest first. */ async list(employeeId) {
|
|
1565
|
+
const result = await this.transport.get(this.base(employeeId));
|
|
1566
|
+
if ('error' in result) return result;
|
|
1567
|
+
return {
|
|
1568
|
+
data: (result.data ?? []).map((r)=>transform(r))
|
|
1569
|
+
};
|
|
1570
|
+
}
|
|
1571
|
+
/** The current (open) record, or null. */ async current(employeeId) {
|
|
1572
|
+
const result = await this.transport.get(`${this.base(employeeId)}/current`);
|
|
1573
|
+
if ('error' in result) return result;
|
|
1574
|
+
return {
|
|
1575
|
+
data: result.data ? transform(result.data) : null
|
|
1576
|
+
};
|
|
1577
|
+
}
|
|
1578
|
+
/** Add a new effective-dated record (closes the prior open one). */ async create(employeeId, data) {
|
|
1579
|
+
const result = await this.transport.post(this.base(employeeId), toSnakeBody(data));
|
|
1580
|
+
if ('error' in result) return result;
|
|
1581
|
+
return {
|
|
1582
|
+
data: transform(result.data)
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
/** Soft-delete a compensation record. */ async delete(employeeId, id) {
|
|
1586
|
+
const result = await this.transport.del(`${this.base(employeeId)}/${id}`);
|
|
1587
|
+
if ('error' in result) return result;
|
|
1588
|
+
return {
|
|
1589
|
+
data: null
|
|
1590
|
+
};
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1310
1594
|
/**
|
|
1311
1595
|
* AppsAccessor — wraps the self-service app info endpoint (§3.8, §6).
|
|
1312
1596
|
* Calls GET /api/v1/platform/apps/me with the app token.
|
|
@@ -1461,6 +1745,8 @@ class AuthAccessor {
|
|
|
1461
1745
|
this.currencies = new CurrenciesAccessor(transport);
|
|
1462
1746
|
this.genericRates = new GenericRatesAccessor(transport);
|
|
1463
1747
|
this.jurisdictions = new JurisdictionsAccessor(transport);
|
|
1748
|
+
this.jobLevels = new JobLevelsAccessor(transport);
|
|
1749
|
+
this.salaryBands = new SalaryBandsAccessor(transport);
|
|
1464
1750
|
this.leaveTypes = new LeaveTypesAccessor(transport);
|
|
1465
1751
|
this.leaves = new LeavesAccessor(transport);
|
|
1466
1752
|
this.leaveBalances = new LeaveBalancesAccessor(transport);
|
|
@@ -1468,6 +1754,9 @@ class AuthAccessor {
|
|
|
1468
1754
|
this.policyAcknowledgements = new PolicyAcknowledgementsAccessor(transport);
|
|
1469
1755
|
this.calendarEvents = new CalendarEventsAccessor(transport);
|
|
1470
1756
|
this.timesheets = new TimesheetsAccessor(transport);
|
|
1757
|
+
this.calendar = new CalendarAccessor(transport);
|
|
1758
|
+
this.email = new EmailAccessor(transport);
|
|
1759
|
+
this.employeeCompensation = new EmployeeCompensationAccessor(transport);
|
|
1471
1760
|
this.apps = new AppsAccessor(transport);
|
|
1472
1761
|
this.files = new FilesAccessor(transport);
|
|
1473
1762
|
this.auth = new AuthAccessor(config.baseUrl);
|
|
@@ -1477,7 +1766,7 @@ class AuthAccessor {
|
|
|
1477
1766
|
/**
|
|
1478
1767
|
* Nucleus SDK — Type System
|
|
1479
1768
|
*
|
|
1480
|
-
* Bucket types are transcribed from docs/
|
|
1769
|
+
* Bucket types are transcribed from docs/ARCHITECTURE.md §7 (Bucket Definitions).
|
|
1481
1770
|
* Each bucket type contains only that bucket's fields.
|
|
1482
1771
|
* The scope-to-type inference intersects selected bucket types at compile time.
|
|
1483
1772
|
*/ // ─── Utility types ────────────────────────────────────────────────────────────
|