ofsc-utility-browser 1.0.22 → 1.0.24
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/activities/index.d.ts +1 -1
- package/dist/activities/index.js +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -2
- package/dist/metadata/activityType.d.ts +41 -0
- package/dist/metadata/activityType.js +227 -0
- package/dist/metadata/activityTypeGroup.d.ts +37 -0
- package/dist/metadata/activityTypeGroup.js +186 -0
- package/dist/metadata/index.d.ts +37 -0
- package/dist/metadata/index.js +156 -0
- package/dist/metadata/resourceTypes.d.ts +34 -0
- package/dist/metadata/resourceTypes.js +161 -0
- package/dist/ofsc-utilities-min.js +1 -1
- package/dist/ofsc-utilities-min.js.map +1 -1
- package/package.json +1 -1
- package/readme.md +9 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* @returns {Promise<any[]>} A promise which resolves to an array of activity objects.
|
|
13
13
|
* @throws {Error} If the date format is invalid or if the resources parameter is missing.
|
|
14
14
|
*/
|
|
15
|
-
export declare function getAllActivities(clientId: string, clientSecret: string, instanceUrl: string, resources: string, dateFrom: string, dateTo: string, q?: string, fields?: string, includeNonScheduled?: boolean): Promise<any[]>;
|
|
15
|
+
export declare function getAllActivities(clientId: string, clientSecret: string, instanceUrl: string, resources: string, dateFrom: string, dateTo: string, q?: string, fields?: string, includeNonScheduled?: boolean, includeChildren?: "none" | "all" | "immediate"): Promise<any[]>;
|
|
16
16
|
export declare function getActivitybyId(clientId: string, clientSecret: string, instanceUrl: string, activityId: number, token?: string): Promise<{
|
|
17
17
|
token: string;
|
|
18
18
|
data: any;
|
package/dist/activities/index.js
CHANGED
|
@@ -16,7 +16,7 @@ const isValidDate = (date) => /^\d{4}-\d{2}-\d{2}$/.test(date);
|
|
|
16
16
|
* @returns {Promise<any[]>} A promise which resolves to an array of activity objects.
|
|
17
17
|
* @throws {Error} If the date format is invalid or if the resources parameter is missing.
|
|
18
18
|
*/
|
|
19
|
-
export async function getAllActivities(clientId, clientSecret, instanceUrl, resources, dateFrom, dateTo, q, fields, includeNonScheduled = false) {
|
|
19
|
+
export async function getAllActivities(clientId, clientSecret, instanceUrl, resources, dateFrom, dateTo, q, fields, includeNonScheduled = false, includeChildren = "none") {
|
|
20
20
|
// Validate date inputs
|
|
21
21
|
if (!isValidDate(dateFrom) || !isValidDate(dateTo)) {
|
|
22
22
|
throw new Error(`❌ Invalid date format. Expected YYYY-MM-DD.`);
|
|
@@ -34,6 +34,8 @@ export async function getAllActivities(clientId, clientSecret, instanceUrl, reso
|
|
|
34
34
|
});
|
|
35
35
|
if (q)
|
|
36
36
|
params.append("q", q);
|
|
37
|
+
if (includeChildren)
|
|
38
|
+
params.append("includeChildren", includeChildren);
|
|
37
39
|
if (resources)
|
|
38
40
|
params.append("resources", resources);
|
|
39
41
|
if (fields)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as Activity from "./activities";
|
|
2
2
|
import * as DailyExtract from "./dailyExtract";
|
|
3
3
|
import * as GPS from "./gps";
|
|
4
|
+
import * as MetaData from "./metadata";
|
|
4
5
|
import * as OauthTokenService from "./oauthTokenService";
|
|
5
6
|
import * as Resources from "./resources";
|
|
6
7
|
import * as Users from "./users";
|
|
7
8
|
import * as Utilities from "./utilities";
|
|
8
|
-
export { Activity, DailyExtract, GPS, OauthTokenService, Resources, Users, Utilities };
|
|
9
|
+
export { Activity, DailyExtract, GPS, MetaData, OauthTokenService, Resources, Users, Utilities };
|
|
9
10
|
export * from "./types";
|
|
10
11
|
declare const _default: {
|
|
11
12
|
Activity: typeof Activity;
|
|
@@ -16,5 +17,6 @@ declare const _default: {
|
|
|
16
17
|
Users: typeof Users;
|
|
17
18
|
DailyExtract: typeof DailyExtract;
|
|
18
19
|
GPS: typeof GPS;
|
|
20
|
+
MetaData: typeof MetaData;
|
|
19
21
|
};
|
|
20
22
|
export default _default;
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as Activity from "./activities";
|
|
2
2
|
import * as DailyExtract from "./dailyExtract";
|
|
3
3
|
import * as GPS from "./gps";
|
|
4
|
+
import * as MetaData from "./metadata";
|
|
4
5
|
import * as OauthTokenService from "./oauthTokenService";
|
|
5
6
|
import * as Resources from "./resources";
|
|
6
7
|
import * as Users from "./users";
|
|
7
8
|
import * as Utilities from "./utilities";
|
|
8
9
|
import { downloadCSV } from "./utilities";
|
|
9
10
|
// Export grouped namespaces
|
|
10
|
-
export { Activity, DailyExtract, GPS, OauthTokenService, Resources, Users, Utilities };
|
|
11
|
+
export { Activity, DailyExtract, GPS, MetaData, OauthTokenService, Resources, Users, Utilities };
|
|
11
12
|
// Export types
|
|
12
13
|
export * from "./types";
|
|
13
14
|
// Default export (for convenience)
|
|
@@ -19,5 +20,6 @@ export default {
|
|
|
19
20
|
downloadCSV,
|
|
20
21
|
Users,
|
|
21
22
|
DailyExtract,
|
|
22
|
-
GPS
|
|
23
|
+
GPS,
|
|
24
|
+
MetaData
|
|
23
25
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches all proeprties from the OFSC instance.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} clientId - The OFSC client ID.
|
|
5
|
+
* @param {string} clientSecret - The OFSC client secret.
|
|
6
|
+
* @param {string} instanceUrl - The OFSC instance URL.
|
|
7
|
+
* @param {string} [initialToken] - The OAuth token to use. If not provided, a new token will be fetched.
|
|
8
|
+
*
|
|
9
|
+
* @returns {Promise<any[]>} A promise which resolves to an array of resource objects.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ActivityType(clientId: string, clientSecret: string, instanceUrl: string, initialToken?: string): Promise<any[]>;
|
|
12
|
+
type TimeSlot = {
|
|
13
|
+
label: string;
|
|
14
|
+
};
|
|
15
|
+
type Translation = {
|
|
16
|
+
language: string;
|
|
17
|
+
name: string;
|
|
18
|
+
languageISO: string;
|
|
19
|
+
};
|
|
20
|
+
type ActivityType = {
|
|
21
|
+
label: string;
|
|
22
|
+
name: string;
|
|
23
|
+
active: boolean;
|
|
24
|
+
groupLabel: string;
|
|
25
|
+
defaultDuration: number;
|
|
26
|
+
timeSlots?: TimeSlot[];
|
|
27
|
+
colors?: Record<string, string>;
|
|
28
|
+
features?: Record<string, boolean>;
|
|
29
|
+
translations?: Translation[];
|
|
30
|
+
};
|
|
31
|
+
type CompareError = {
|
|
32
|
+
label: string;
|
|
33
|
+
field?: string;
|
|
34
|
+
message: string;
|
|
35
|
+
env1Value?: any;
|
|
36
|
+
env2Value?: any;
|
|
37
|
+
env1Instance?: string;
|
|
38
|
+
env2Instance?: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function deepCompareActivityTypes(env1: ActivityType[], env2: ActivityType[], e1Instance: string, e2Instance: string): CompareError[];
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { fetchWithRetry } from "../utilities";
|
|
2
|
+
/**
|
|
3
|
+
* Fetches all proeprties from the OFSC instance.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} clientId - The OFSC client ID.
|
|
6
|
+
* @param {string} clientSecret - The OFSC client secret.
|
|
7
|
+
* @param {string} instanceUrl - The OFSC instance URL.
|
|
8
|
+
* @param {string} [initialToken] - The OAuth token to use. If not provided, a new token will be fetched.
|
|
9
|
+
*
|
|
10
|
+
* @returns {Promise<any[]>} A promise which resolves to an array of resource objects.
|
|
11
|
+
*/
|
|
12
|
+
export async function ActivityType(clientId, clientSecret, instanceUrl, initialToken = "") {
|
|
13
|
+
/**
|
|
14
|
+
* The number of API calls made so far.
|
|
15
|
+
* Used to determine if we should wait 10 seconds to avoid server rate limits.
|
|
16
|
+
*/
|
|
17
|
+
let apiCallCount = 0;
|
|
18
|
+
/**
|
|
19
|
+
* The number of API calls after which we should wait 10 seconds.
|
|
20
|
+
*/
|
|
21
|
+
const WAIT_AFTER_CALLS = 20;
|
|
22
|
+
/**
|
|
23
|
+
* The delay in milliseconds to wait after reaching the API call limit.
|
|
24
|
+
*/
|
|
25
|
+
const DELAY_MS = 10000; // 10 seconds
|
|
26
|
+
/**
|
|
27
|
+
* Sleeps for the given amount of milliseconds.
|
|
28
|
+
*
|
|
29
|
+
* @param {number} ms - The amount of milliseconds to sleep.
|
|
30
|
+
* @returns {Promise<void>} A promise which resolves when the sleep is over.
|
|
31
|
+
*/
|
|
32
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
33
|
+
/**
|
|
34
|
+
* Fetches resources from the OFSC instance.
|
|
35
|
+
*
|
|
36
|
+
* @param {number} offset - The offset from which to fetch resources.
|
|
37
|
+
* @param {string} token - The OAuth token to use.
|
|
38
|
+
* @returns {Promise<Response[]>} A promise which resolves to an array of resource responses.
|
|
39
|
+
*/
|
|
40
|
+
const ActivityType = async (offset, token) => {
|
|
41
|
+
apiCallCount++;
|
|
42
|
+
// Wait 10 seconds after 20 API calls to avoid server rate limits.
|
|
43
|
+
if (apiCallCount % WAIT_AFTER_CALLS === 0) {
|
|
44
|
+
console.warn(` Waiting 10 seconds after ${apiCallCount} API calls to avoid server rate limits.`);
|
|
45
|
+
await sleep(DELAY_MS);
|
|
46
|
+
}
|
|
47
|
+
const url = `https://${instanceUrl}.fs.ocs.oraclecloud.com/rest/ofscMetadata/v1/activityTypes?offset=${offset}&limit=100`;
|
|
48
|
+
const res = await fetchWithRetry(url, clientId, clientSecret, instanceUrl, token);
|
|
49
|
+
const { items, totalResults } = res.data;
|
|
50
|
+
const totalFetched = items.length;
|
|
51
|
+
console.log(`Received ${totalFetched} items (Total: ${offset + totalFetched})`);
|
|
52
|
+
if (offset + totalFetched >= totalResults) {
|
|
53
|
+
return items;
|
|
54
|
+
}
|
|
55
|
+
const nextItems = await ActivityType(offset + totalFetched, res.token);
|
|
56
|
+
return [...items, ...nextItems];
|
|
57
|
+
};
|
|
58
|
+
return ActivityType(0, initialToken);
|
|
59
|
+
}
|
|
60
|
+
export function deepCompareActivityTypes(env1, env2, e1Instance, e2Instance) {
|
|
61
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
62
|
+
const errors = [];
|
|
63
|
+
const env2Map = new Map(env2.map(e => [e.label, e]));
|
|
64
|
+
const env1Map = new Map(env1.map(e => [e.label, e]));
|
|
65
|
+
for (const a1 of env1) {
|
|
66
|
+
const a2 = env2Map.get(a1.label);
|
|
67
|
+
if (!a2) {
|
|
68
|
+
errors.push({
|
|
69
|
+
label: a1.label,
|
|
70
|
+
message: "Missing in env2",
|
|
71
|
+
env1Value: a1,
|
|
72
|
+
env1Instance: e1Instance,
|
|
73
|
+
env2Instance: e2Instance
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// ---- primitive fields ----
|
|
78
|
+
const fields = [
|
|
79
|
+
"name",
|
|
80
|
+
"active",
|
|
81
|
+
"groupLabel",
|
|
82
|
+
"defaultDuration"
|
|
83
|
+
];
|
|
84
|
+
for (const field of fields) {
|
|
85
|
+
if (a1[field] !== a2[field]) {
|
|
86
|
+
errors.push({
|
|
87
|
+
label: a1.label,
|
|
88
|
+
field: String(field),
|
|
89
|
+
message: `${field} mismatch`,
|
|
90
|
+
env1Value: a1[field],
|
|
91
|
+
env2Value: a2[field],
|
|
92
|
+
env1Instance: e1Instance,
|
|
93
|
+
env2Instance: e2Instance
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ---- timeSlots ----
|
|
98
|
+
const ts1 = (_a = a1.timeSlots) !== null && _a !== void 0 ? _a : [];
|
|
99
|
+
const ts2 = (_b = a2.timeSlots) !== null && _b !== void 0 ? _b : [];
|
|
100
|
+
const ts2Set = new Set(ts2.map(t => t.label));
|
|
101
|
+
const ts1Set = new Set(ts1.map(t => t.label));
|
|
102
|
+
for (const t of ts1) {
|
|
103
|
+
if (!ts2Set.has(t.label)) {
|
|
104
|
+
errors.push({
|
|
105
|
+
label: a1.label,
|
|
106
|
+
field: "timeSlots",
|
|
107
|
+
message: `Missing timeslot in env2 (${t.label})`,
|
|
108
|
+
env1Value: t.label,
|
|
109
|
+
env1Instance: e1Instance,
|
|
110
|
+
env2Instance: e2Instance
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (const t of ts2) {
|
|
115
|
+
if (!ts1Set.has(t.label)) {
|
|
116
|
+
errors.push({
|
|
117
|
+
label: a1.label,
|
|
118
|
+
field: "timeSlots",
|
|
119
|
+
message: `Missing timeslot in env1 (${t.label})`,
|
|
120
|
+
env2Value: t.label,
|
|
121
|
+
env1Instance: e1Instance,
|
|
122
|
+
env2Instance: e2Instance
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ---- colors ----
|
|
127
|
+
const c1 = (_c = a1.colors) !== null && _c !== void 0 ? _c : {};
|
|
128
|
+
const c2 = (_d = a2.colors) !== null && _d !== void 0 ? _d : {};
|
|
129
|
+
const allColorKeys = new Set([...Object.keys(c1), ...Object.keys(c2)]);
|
|
130
|
+
for (const key of allColorKeys) {
|
|
131
|
+
if (c1[key] !== c2[key]) {
|
|
132
|
+
errors.push({
|
|
133
|
+
label: a1.label,
|
|
134
|
+
field: `colors.${key}`,
|
|
135
|
+
message: "Color mismatch",
|
|
136
|
+
env1Value: c1[key],
|
|
137
|
+
env2Value: c2[key],
|
|
138
|
+
env1Instance: e1Instance,
|
|
139
|
+
env2Instance: e2Instance
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ---- features ----
|
|
144
|
+
const f1 = (_e = a1.features) !== null && _e !== void 0 ? _e : {};
|
|
145
|
+
const f2 = (_f = a2.features) !== null && _f !== void 0 ? _f : {};
|
|
146
|
+
const allFeatureKeys = new Set([...Object.keys(f1), ...Object.keys(f2)]);
|
|
147
|
+
for (const key of allFeatureKeys) {
|
|
148
|
+
if (f1[key] !== f2[key]) {
|
|
149
|
+
errors.push({
|
|
150
|
+
label: a1.label,
|
|
151
|
+
field: `features.${key}`,
|
|
152
|
+
message: "Feature mismatch",
|
|
153
|
+
env1Value: f1[key],
|
|
154
|
+
env2Value: f2[key],
|
|
155
|
+
env1Instance: e1Instance,
|
|
156
|
+
env2Instance: e2Instance
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ---- translations ----
|
|
161
|
+
const t1 = (_g = a1.translations) !== null && _g !== void 0 ? _g : [];
|
|
162
|
+
const t2 = (_h = a2.translations) !== null && _h !== void 0 ? _h : [];
|
|
163
|
+
const t2Map = new Map(t2.map(t => [t.languageISO, t]));
|
|
164
|
+
const t1Set = new Set(t1.map(t => t.languageISO));
|
|
165
|
+
for (const tr1 of t1) {
|
|
166
|
+
const tr2 = t2Map.get(tr1.languageISO);
|
|
167
|
+
if (!tr2) {
|
|
168
|
+
errors.push({
|
|
169
|
+
label: a1.label,
|
|
170
|
+
field: "translations",
|
|
171
|
+
message: `Missing translation in env2 (${tr1.languageISO})`,
|
|
172
|
+
env1Value: tr1,
|
|
173
|
+
env1Instance: e1Instance,
|
|
174
|
+
env2Instance: e2Instance
|
|
175
|
+
});
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (tr1.name !== tr2.name) {
|
|
179
|
+
errors.push({
|
|
180
|
+
label: a1.label,
|
|
181
|
+
field: `translations.name[${tr1.languageISO}]`,
|
|
182
|
+
message: "Translation name mismatch",
|
|
183
|
+
env1Value: tr1.name,
|
|
184
|
+
env2Value: tr2.name,
|
|
185
|
+
env1Instance: e1Instance,
|
|
186
|
+
env2Instance: e2Instance
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (tr1.language !== tr2.language) {
|
|
190
|
+
errors.push({
|
|
191
|
+
label: a1.label,
|
|
192
|
+
field: `translations.language[${tr1.languageISO}]`,
|
|
193
|
+
message: "Translation language mismatch",
|
|
194
|
+
env1Value: tr1.language,
|
|
195
|
+
env2Value: tr2.language,
|
|
196
|
+
env1Instance: e1Instance,
|
|
197
|
+
env2Instance: e2Instance
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const tr2 of t2) {
|
|
202
|
+
if (!t1Set.has(tr2.languageISO)) {
|
|
203
|
+
errors.push({
|
|
204
|
+
label: a1.label,
|
|
205
|
+
field: "translations",
|
|
206
|
+
message: `Missing translation in env1 (${tr2.languageISO})`,
|
|
207
|
+
env2Value: tr2,
|
|
208
|
+
env1Instance: e1Instance,
|
|
209
|
+
env2Instance: e2Instance
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// ---- missing in env1 ----
|
|
215
|
+
for (const a2 of env2) {
|
|
216
|
+
if (!env1Map.has(a2.label)) {
|
|
217
|
+
errors.push({
|
|
218
|
+
label: a2.label,
|
|
219
|
+
message: "Missing in env1",
|
|
220
|
+
env2Value: a2,
|
|
221
|
+
env1Instance: e1Instance,
|
|
222
|
+
env2Instance: e2Instance
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return errors;
|
|
227
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches all proeprties from the OFSC instance.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} clientId - The OFSC client ID.
|
|
5
|
+
* @param {string} clientSecret - The OFSC client secret.
|
|
6
|
+
* @param {string} instanceUrl - The OFSC instance URL.
|
|
7
|
+
* @param {string} [initialToken] - The OAuth token to use. If not provided, a new token will be fetched.
|
|
8
|
+
*
|
|
9
|
+
* @returns {Promise<any[]>} A promise which resolves to an array of resource objects.
|
|
10
|
+
*/
|
|
11
|
+
export declare function ActivityTypeGroups(clientId: string, clientSecret: string, instanceUrl: string, initialToken?: string): Promise<any[]>;
|
|
12
|
+
type ActivityType = {
|
|
13
|
+
label: string;
|
|
14
|
+
};
|
|
15
|
+
type Translation = {
|
|
16
|
+
language: string;
|
|
17
|
+
name: string;
|
|
18
|
+
languageISO: string;
|
|
19
|
+
};
|
|
20
|
+
type ActivityGroup = {
|
|
21
|
+
label: string;
|
|
22
|
+
name: string;
|
|
23
|
+
activityTypes?: ActivityType[];
|
|
24
|
+
translations?: Translation[];
|
|
25
|
+
links?: any[];
|
|
26
|
+
};
|
|
27
|
+
type CompareError = {
|
|
28
|
+
label: string;
|
|
29
|
+
field?: string;
|
|
30
|
+
message: string;
|
|
31
|
+
env1Value?: any;
|
|
32
|
+
env2Value?: any;
|
|
33
|
+
env1Instance?: string;
|
|
34
|
+
env2Instance?: string;
|
|
35
|
+
};
|
|
36
|
+
export declare function deepCompareActivityGroups(env1: ActivityGroup[], env2: ActivityGroup[], e1Instance: string, e2Instance: string): CompareError[];
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { fetchWithRetry } from "../utilities";
|
|
2
|
+
/**
|
|
3
|
+
* Fetches all proeprties from the OFSC instance.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} clientId - The OFSC client ID.
|
|
6
|
+
* @param {string} clientSecret - The OFSC client secret.
|
|
7
|
+
* @param {string} instanceUrl - The OFSC instance URL.
|
|
8
|
+
* @param {string} [initialToken] - The OAuth token to use. If not provided, a new token will be fetched.
|
|
9
|
+
*
|
|
10
|
+
* @returns {Promise<any[]>} A promise which resolves to an array of resource objects.
|
|
11
|
+
*/
|
|
12
|
+
export async function ActivityTypeGroups(clientId, clientSecret, instanceUrl, initialToken = "") {
|
|
13
|
+
/**
|
|
14
|
+
* The number of API calls made so far.
|
|
15
|
+
* Used to determine if we should wait 10 seconds to avoid server rate limits.
|
|
16
|
+
*/
|
|
17
|
+
let apiCallCount = 0;
|
|
18
|
+
/**
|
|
19
|
+
* The number of API calls after which we should wait 10 seconds.
|
|
20
|
+
*/
|
|
21
|
+
const WAIT_AFTER_CALLS = 20;
|
|
22
|
+
/**
|
|
23
|
+
* The delay in milliseconds to wait after reaching the API call limit.
|
|
24
|
+
*/
|
|
25
|
+
const DELAY_MS = 10000; // 10 seconds
|
|
26
|
+
/**
|
|
27
|
+
* Sleeps for the given amount of milliseconds.
|
|
28
|
+
*
|
|
29
|
+
* @param {number} ms - The amount of milliseconds to sleep.
|
|
30
|
+
* @returns {Promise<void>} A promise which resolves when the sleep is over.
|
|
31
|
+
*/
|
|
32
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
33
|
+
/**
|
|
34
|
+
* Fetches resources from the OFSC instance.
|
|
35
|
+
*
|
|
36
|
+
* @param {number} offset - The offset from which to fetch resources.
|
|
37
|
+
* @param {string} token - The OAuth token to use.
|
|
38
|
+
* @returns {Promise<Response[]>} A promise which resolves to an array of resource responses.
|
|
39
|
+
*/
|
|
40
|
+
const ActivityTypeGroups = async (offset, token) => {
|
|
41
|
+
apiCallCount++;
|
|
42
|
+
// Wait 10 seconds after 20 API calls to avoid server rate limits.
|
|
43
|
+
if (apiCallCount % WAIT_AFTER_CALLS === 0) {
|
|
44
|
+
console.warn(` Waiting 10 seconds after ${apiCallCount} API calls to avoid server rate limits.`);
|
|
45
|
+
await sleep(DELAY_MS);
|
|
46
|
+
}
|
|
47
|
+
const url = `https://${instanceUrl}.fs.ocs.oraclecloud.com/rest/ofscMetadata/v1/activityTypeGroups?offset=${offset}&limit=100`;
|
|
48
|
+
const res = await fetchWithRetry(url, clientId, clientSecret, instanceUrl, token);
|
|
49
|
+
const { items, totalResults } = res.data;
|
|
50
|
+
const totalFetched = items.length;
|
|
51
|
+
console.log(`Received ${totalFetched} items (Total: ${offset + totalFetched})`);
|
|
52
|
+
if (offset + totalFetched >= totalResults) {
|
|
53
|
+
return items;
|
|
54
|
+
}
|
|
55
|
+
const nextItems = await ActivityTypeGroups(offset + totalFetched, res.token);
|
|
56
|
+
return [...items, ...nextItems];
|
|
57
|
+
};
|
|
58
|
+
return ActivityTypeGroups(0, initialToken);
|
|
59
|
+
}
|
|
60
|
+
export function deepCompareActivityGroups(env1, env2, e1Instance, e2Instance) {
|
|
61
|
+
var _a, _b, _c, _d;
|
|
62
|
+
const errors = [];
|
|
63
|
+
const env2Map = new Map(env2.map(e => [e.label, e]));
|
|
64
|
+
const env1Map = new Map(env1.map(e => [e.label, e]));
|
|
65
|
+
// --- Compare env1 against env2 ---
|
|
66
|
+
for (const g1 of env1) {
|
|
67
|
+
const g2 = env2Map.get(g1.label);
|
|
68
|
+
if (!g2) {
|
|
69
|
+
errors.push({
|
|
70
|
+
label: g1.label,
|
|
71
|
+
message: "Missing in env2",
|
|
72
|
+
env1Value: g1,
|
|
73
|
+
env1Instance: e1Instance,
|
|
74
|
+
env2Instance: e2Instance
|
|
75
|
+
});
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
// ---- name ----
|
|
79
|
+
if (g1.name !== g2.name) {
|
|
80
|
+
errors.push({
|
|
81
|
+
label: g1.label,
|
|
82
|
+
field: "name",
|
|
83
|
+
message: "Name mismatch",
|
|
84
|
+
env1Value: g1.name,
|
|
85
|
+
env2Value: g2.name,
|
|
86
|
+
env1Instance: e1Instance,
|
|
87
|
+
env2Instance: e2Instance
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
// ---- activityTypes ----
|
|
91
|
+
const a1 = (_a = g1.activityTypes) !== null && _a !== void 0 ? _a : [];
|
|
92
|
+
const a2 = (_b = g2.activityTypes) !== null && _b !== void 0 ? _b : [];
|
|
93
|
+
const a2Map = new Map(a2.map(a => [a.label, a]));
|
|
94
|
+
const a1Set = new Set(a1.map(a => a.label));
|
|
95
|
+
for (const at1 of a1) {
|
|
96
|
+
if (!a2Map.has(at1.label)) {
|
|
97
|
+
errors.push({
|
|
98
|
+
label: g1.label,
|
|
99
|
+
field: "activityTypes",
|
|
100
|
+
message: `ActivityType missing in env2 (${at1.label})`,
|
|
101
|
+
env1Value: at1.label,
|
|
102
|
+
env1Instance: e1Instance,
|
|
103
|
+
env2Instance: e2Instance
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
for (const at2 of a2) {
|
|
108
|
+
if (!a1Set.has(at2.label)) {
|
|
109
|
+
errors.push({
|
|
110
|
+
label: g1.label,
|
|
111
|
+
field: "activityTypes",
|
|
112
|
+
message: `ActivityType missing in env1 (${at2.label})`,
|
|
113
|
+
env2Value: at2.label,
|
|
114
|
+
env1Instance: e1Instance,
|
|
115
|
+
env2Instance: e2Instance
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ---- translations ----
|
|
120
|
+
const t1 = (_c = g1.translations) !== null && _c !== void 0 ? _c : [];
|
|
121
|
+
const t2 = (_d = g2.translations) !== null && _d !== void 0 ? _d : [];
|
|
122
|
+
const t2Map = new Map(t2.map(t => [t.languageISO, t]));
|
|
123
|
+
const t1Set = new Set(t1.map(t => t.languageISO));
|
|
124
|
+
for (const tr1 of t1) {
|
|
125
|
+
const tr2 = t2Map.get(tr1.languageISO);
|
|
126
|
+
if (!tr2) {
|
|
127
|
+
errors.push({
|
|
128
|
+
label: g1.label,
|
|
129
|
+
field: "translations",
|
|
130
|
+
message: `Translation missing in env2 (${tr1.languageISO})`,
|
|
131
|
+
env1Value: tr1,
|
|
132
|
+
env1Instance: e1Instance,
|
|
133
|
+
env2Instance: e2Instance
|
|
134
|
+
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (tr1.name !== tr2.name) {
|
|
138
|
+
errors.push({
|
|
139
|
+
label: g1.label,
|
|
140
|
+
field: `translation.name[${tr1.languageISO}]`,
|
|
141
|
+
message: "Translation name mismatch",
|
|
142
|
+
env1Value: tr1.name,
|
|
143
|
+
env2Value: tr2.name,
|
|
144
|
+
env1Instance: e1Instance,
|
|
145
|
+
env2Instance: e2Instance
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (tr1.language !== tr2.language) {
|
|
149
|
+
errors.push({
|
|
150
|
+
label: g1.label,
|
|
151
|
+
field: `translation.language[${tr1.languageISO}]`,
|
|
152
|
+
message: "Translation language mismatch",
|
|
153
|
+
env1Value: tr1.language,
|
|
154
|
+
env2Value: tr2.language,
|
|
155
|
+
env1Instance: e1Instance,
|
|
156
|
+
env2Instance: e2Instance
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
for (const tr2 of t2) {
|
|
161
|
+
if (!t1Set.has(tr2.languageISO)) {
|
|
162
|
+
errors.push({
|
|
163
|
+
label: g1.label,
|
|
164
|
+
field: "translations",
|
|
165
|
+
message: `Translation missing in env1 (${tr2.languageISO})`,
|
|
166
|
+
env2Value: tr2,
|
|
167
|
+
env1Instance: e1Instance,
|
|
168
|
+
env2Instance: e2Instance
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// --- Missing in env1 ---
|
|
174
|
+
for (const g2 of env2) {
|
|
175
|
+
if (!env1Map.has(g2.label)) {
|
|
176
|
+
errors.push({
|
|
177
|
+
label: g2.label,
|
|
178
|
+
message: "Missing in env1",
|
|
179
|
+
env2Value: g2,
|
|
180
|
+
env1Instance: e1Instance,
|
|
181
|
+
env2Instance: e2Instance
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return errors;
|
|
186
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export * from "./activityType";
|
|
2
|
+
export * from "./activityTypeGroup";
|
|
3
|
+
export * from "./resourceTypes";
|
|
4
|
+
/**
|
|
5
|
+
* Fetches all proeprties from the OFSC instance.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} clientId - The OFSC client ID.
|
|
8
|
+
* @param {string} clientSecret - The OFSC client secret.
|
|
9
|
+
* @param {string} instanceUrl - The OFSC instance URL.
|
|
10
|
+
* @param {string} [initialToken] - The OAuth token to use. If not provided, a new token will be fetched.
|
|
11
|
+
*
|
|
12
|
+
* @returns {Promise<any[]>} A promise which resolves to an array of resource objects.
|
|
13
|
+
*/
|
|
14
|
+
export declare function AllProperties(clientId: string, clientSecret: string, instanceUrl: string, initialToken?: string): Promise<any[]>;
|
|
15
|
+
type Translation = {
|
|
16
|
+
language: string;
|
|
17
|
+
name: string;
|
|
18
|
+
languageISO: string;
|
|
19
|
+
};
|
|
20
|
+
type FieldDefinition = {
|
|
21
|
+
label: string;
|
|
22
|
+
name: string;
|
|
23
|
+
type: string;
|
|
24
|
+
entity: string;
|
|
25
|
+
gui: string;
|
|
26
|
+
translations: Translation[];
|
|
27
|
+
};
|
|
28
|
+
type CompareError = {
|
|
29
|
+
label: string;
|
|
30
|
+
field?: string;
|
|
31
|
+
message: string;
|
|
32
|
+
env1Value?: any;
|
|
33
|
+
env2Value?: any;
|
|
34
|
+
env1Instance?: string;
|
|
35
|
+
env2Instance?: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function compareProperties(propEnv1: FieldDefinition[], propEnv2: FieldDefinition[], e1Instance: string, e2Instance: string): Promise<CompareError[]>;
|