@restoai/resto-datacli 0.2.0 → 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/cli.js CHANGED
File without changes
@@ -11,7 +11,17 @@ const DEFAULT_AUTH_GATEWAY_PLAT = "cli";
11
11
  const LOGIN_FOR_TOKEN_PATH = "/loginApi/loginForToken";
12
12
  const PHONE_CAPTCHA_PATH = "/vulcan/captcha/phoneCaptcha";
13
13
  const PROFILE_INFO_PATH = "/vulcan/profile/getInfo";
14
+ const ORGANIZATION_VIEW_PATH = "/vulcan/employee/queryOrgView";
14
15
  const REPORT_SHOP_ORG_TYPE_LIST = [7];
16
+ const ORGANIZATION_ID_FIELDS = [
17
+ "organizationId",
18
+ "orgId",
19
+ "corporationOrgId",
20
+ "brandId",
21
+ "orgShopId",
22
+ "franchiseeOrgId",
23
+ "orgFranchiseeId"
24
+ ];
15
25
  const PHONE_CAPTCHA_TYPE_VERIFY_CODE = "1";
16
26
  const PHONE_CAPTCHA_STEP_LOGIN = "1";
17
27
  const DEFAULT_PHONE_AREA_CODE = "86";
@@ -129,19 +139,40 @@ function buildReportContext(profile, options) {
129
139
  };
130
140
  return Object.keys(reportContext).length > 0 ? reportContext : undefined;
131
141
  }
132
- function extractProfileReportContext(payload) {
142
+ function extractProfileIdentity(payload) {
133
143
  const data = asRecord(asRecord(payload)?.data) ?? asRecord(payload);
134
144
  const employeeCode = firstString(data?.employeeCode, data?.code, data?.loginId, data?.principalUid);
145
+ const employeeId = firstString(data?.employeeId, data?.id, data?.userId);
135
146
  const organizationId = firstString(data?.organizationId, data?.orgId);
136
- const organizationType = firstString(data?.organizationType, data?.orgType, data?.type);
147
+ const organizationType = firstString(data?.organizationType, data?.orgType);
148
+ return { employeeCode, employeeId, organizationId, organizationType };
149
+ }
150
+ function extractProfileReportContext(payload, resolvedOrganizationType) {
151
+ const identity = extractProfileIdentity(payload);
152
+ const organizationType = resolvedOrganizationType ?? identity.organizationType;
137
153
  const reportContext = {
138
- ...(employeeCode ? { employeeCode } : {}),
139
- ...(organizationId ? { organizationId } : {}),
154
+ ...(identity.employeeCode ? { employeeCode: identity.employeeCode } : {}),
155
+ ...(identity.organizationId ? { organizationId: identity.organizationId } : {}),
140
156
  ...(organizationType ? { organizationType } : {}),
141
- ...(organizationId ? { orgTypeList: REPORT_SHOP_ORG_TYPE_LIST } : {})
157
+ ...(identity.organizationId ? { orgTypeList: REPORT_SHOP_ORG_TYPE_LIST } : {})
142
158
  };
143
159
  return Object.keys(reportContext).length > 0 ? reportContext : undefined;
144
160
  }
161
+ function resolveOrganizationType(payload, organizationId) {
162
+ const data = asRecord(asRecord(payload)?.data) ?? asRecord(payload);
163
+ const matchingTypes = new Set();
164
+ for (const record of collectRecords(data)) {
165
+ const matchesOrganization = ORGANIZATION_ID_FIELDS.some((fieldName) => firstString(record[fieldName]) === organizationId);
166
+ if (!matchesOrganization) {
167
+ continue;
168
+ }
169
+ const organizationType = firstString(record.orgType, record.organizationType);
170
+ if (organizationType) {
171
+ matchingTypes.add(organizationType);
172
+ }
173
+ }
174
+ return matchingTypes.size === 1 ? [...matchingTypes][0] : undefined;
175
+ }
145
176
  function extractLoginProfile(payload, fallbackCorporationId) {
146
177
  const records = collectRecords(payload);
147
178
  const token = records.reduce((current, record) => current ?? firstString(record.token, record.accessToken, record.access_token), undefined);
@@ -154,7 +185,34 @@ function withReportContext(profile, options) {
154
185
  const reportContext = buildReportContext(profile, options);
155
186
  return reportContext ? { ...profile, reportContext } : profile;
156
187
  }
157
- async function fetchProfileReportContext(profile, fetchImpl) {
188
+ async function fetchOrganizationType(profile, fetchImpl, employeeId, organizationId) {
189
+ const response = await fetchImpl(authGatewayUrl(profile.baseUrl, ORGANIZATION_VIEW_PATH, profile.plat), {
190
+ method: "POST",
191
+ headers: {
192
+ Accept: "application/json",
193
+ "Content-Type": "application/json",
194
+ "Corporation-Id": profile.corporationId,
195
+ "Vulcan-Token": profile.token,
196
+ "Language-Code": profile.languageCode,
197
+ "Accept-Timezone": profile.timezone
198
+ },
199
+ body: JSON.stringify({ id: employeeId, corporationId: profile.corporationId })
200
+ });
201
+ if (!response.ok) {
202
+ throw new Error(`Organization context request failed: ${response.status} ${response.statusText}`.trim());
203
+ }
204
+ const payload = await response.json();
205
+ const code = firstString(asRecord(payload)?.code);
206
+ if (code && code !== "000") {
207
+ throw new Error(extractLoginError(payload) ?? `Organization context request failed with code ${code}.`);
208
+ }
209
+ const organizationType = resolveOrganizationType(payload, organizationId);
210
+ if (!organizationType) {
211
+ throw new Error("Current organization type could not be resolved from the organization view.");
212
+ }
213
+ return organizationType;
214
+ }
215
+ async function fetchProfileReportContext(profile, fetchImpl, organizationTypeOverride) {
158
216
  const response = await fetchImpl(authGatewayUrl(profile.baseUrl, PROFILE_INFO_PATH, profile.plat), {
159
217
  method: "GET",
160
218
  headers: {
@@ -166,30 +224,33 @@ async function fetchProfileReportContext(profile, fetchImpl) {
166
224
  }
167
225
  });
168
226
  if (!response.ok) {
169
- return undefined;
227
+ throw new Error(`Profile request failed: ${response.status} ${response.statusText}`.trim());
170
228
  }
171
229
  const payload = await response.json();
172
230
  const code = firstString(asRecord(payload)?.code);
173
231
  if (code && code !== "000") {
174
- return undefined;
232
+ throw new Error(extractLoginError(payload) ?? `Profile request failed with code ${code}.`);
233
+ }
234
+ const identity = extractProfileIdentity(payload);
235
+ let organizationType = organizationTypeOverride ?? identity.organizationType;
236
+ if (!organizationType && identity.organizationId) {
237
+ if (!identity.employeeId) {
238
+ throw new Error("Profile did not contain an employee id for organization resolution.");
239
+ }
240
+ organizationType = await fetchOrganizationType(profile, fetchImpl, identity.employeeId, identity.organizationId);
175
241
  }
176
- return extractProfileReportContext(payload);
242
+ return extractProfileReportContext(payload, organizationType);
177
243
  }
178
244
  async function hydrateReportContext(profile, options, fetchImpl) {
179
245
  const initialProfile = withReportContext(profile, options);
180
246
  if (hasCompleteReportContext(initialProfile.reportContext)) {
181
247
  return initialProfile;
182
248
  }
183
- try {
184
- const profileReportContext = await fetchProfileReportContext(profile, fetchImpl);
185
- const hydratedProfile = profileReportContext
186
- ? { ...profile, reportContext: { ...(profile.reportContext ?? {}), ...profileReportContext } }
187
- : profile;
188
- return withReportContext(hydratedProfile, options);
189
- }
190
- catch {
191
- return initialProfile;
192
- }
249
+ const profileReportContext = await fetchProfileReportContext(profile, fetchImpl, options.organizationType);
250
+ const hydratedProfile = profileReportContext
251
+ ? { ...profile, reportContext: { ...(profile.reportContext ?? {}), ...profileReportContext } }
252
+ : profile;
253
+ return withReportContext(hydratedProfile, options);
193
254
  }
194
255
  async function loginWithPassword(options, fetchImpl) {
195
256
  if (!options.baseUrl) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@restoai/resto-datacli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "resto": "dist/cli.js"