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