@7365admin1/core 3.84.0 → 3.85.0

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/index.mjs CHANGED
@@ -60249,6 +60249,145 @@ function registerOunitechBrand() {
60249
60249
  });
60250
60250
  }
60251
60251
 
60252
+ // src/services/robot-tracking.service.ts
60253
+ import axios4 from "axios";
60254
+ async function openWithAxios(url, body) {
60255
+ const response = await axios4.post(url, body, {
60256
+ responseType: "stream",
60257
+ // No read timeout: this connection is SUPPOSED to stay open and mostly
60258
+ // silent. A request timeout here would sever a healthy stream on a quiet
60259
+ // robot. The idle watchdog is what decides a stream is dead, because it can
60260
+ // tell silence from a closed socket.
60261
+ timeout: 0,
60262
+ headers: { "Content-Type": "application/json", Accept: "text/event-stream" }
60263
+ });
60264
+ return response.data;
60265
+ }
60266
+ function startRobotTracking(options) {
60267
+ const {
60268
+ credentials,
60269
+ robotSn,
60270
+ onEvent,
60271
+ baseUrl = ROBOT_CLOUD_BASE_URL,
60272
+ idleTimeoutMs = TRACKING_IDLE_TIMEOUT_MS,
60273
+ openStream = openWithAxios,
60274
+ now = Date.now
60275
+ } = options;
60276
+ if (!baseUrl)
60277
+ throw new Error("Robot cloud: ROBOT_CLOUD_BASE_URL is not configured.");
60278
+ let stopped = false;
60279
+ let attempt = 0;
60280
+ let current = null;
60281
+ let watchdog = null;
60282
+ let retry = null;
60283
+ let lastActivityAt = now();
60284
+ let everConnected = false;
60285
+ const parser = createSseParser();
60286
+ function clearTimers() {
60287
+ if (watchdog) {
60288
+ clearInterval(watchdog);
60289
+ watchdog = null;
60290
+ }
60291
+ if (retry) {
60292
+ clearTimeout(retry);
60293
+ retry = null;
60294
+ }
60295
+ }
60296
+ function dropUpstream() {
60297
+ if (!current)
60298
+ return;
60299
+ try {
60300
+ current.destroy();
60301
+ } catch {
60302
+ }
60303
+ current = null;
60304
+ }
60305
+ function lose(reason) {
60306
+ if (stopped)
60307
+ return;
60308
+ onEvent({ type: "lost", reason, at: now() });
60309
+ dropUpstream();
60310
+ scheduleReconnect();
60311
+ }
60312
+ function scheduleReconnect() {
60313
+ if (stopped)
60314
+ return;
60315
+ clearTimers();
60316
+ const delay2 = trackingBackoffMs(attempt++);
60317
+ retry = setTimeout(connect2, delay2);
60318
+ }
60319
+ async function connect2() {
60320
+ if (stopped)
60321
+ return;
60322
+ const body = robotCloudBody(
60323
+ credentials.appid,
60324
+ credentials.secret,
60325
+ ROBOT_CLOUD_PATHS.tracking,
60326
+ { robotSn }
60327
+ );
60328
+ let stream;
60329
+ try {
60330
+ stream = await openStream(
60331
+ `${baseUrl.replace(/\/+$/, "")}${ROBOT_CLOUD_PATHS.tracking}`,
60332
+ body
60333
+ );
60334
+ } catch (error) {
60335
+ lose(error?.message ?? "Could not open the robot's tracking stream.");
60336
+ return;
60337
+ }
60338
+ if (stopped) {
60339
+ try {
60340
+ stream.destroy();
60341
+ } catch {
60342
+ }
60343
+ return;
60344
+ }
60345
+ parser.reset();
60346
+ current = stream;
60347
+ lastActivityAt = now();
60348
+ if (everConnected)
60349
+ onEvent({ type: "reconnected", at: now() });
60350
+ everConnected = true;
60351
+ attempt = 0;
60352
+ stream.on("data", (chunk) => {
60353
+ if (stopped)
60354
+ return;
60355
+ const { events, sawActivity } = parser.push(chunk.toString("utf8"));
60356
+ if (sawActivity)
60357
+ lastActivityAt = now();
60358
+ for (const event of events) {
60359
+ const pose = decodeTrackingFrame(event.data);
60360
+ if (pose)
60361
+ onEvent({ type: "pose", pose, at: now() });
60362
+ }
60363
+ });
60364
+ stream.on("error", (error) => lose(error?.message ?? "The tracking stream failed."));
60365
+ stream.on("end", () => lose("The robot cloud closed the tracking stream."));
60366
+ stream.on("close", () => {
60367
+ if (!stopped && current === stream)
60368
+ lose("The tracking stream closed.");
60369
+ });
60370
+ clearTimers();
60371
+ watchdog = setInterval(() => {
60372
+ if (stopped)
60373
+ return;
60374
+ if (now() - lastActivityAt >= idleTimeoutMs) {
60375
+ lose("The robot stopped reporting.");
60376
+ }
60377
+ }, Math.max(1e3, Math.floor(idleTimeoutMs / 3)));
60378
+ }
60379
+ void connect2();
60380
+ return {
60381
+ stop() {
60382
+ if (stopped)
60383
+ return;
60384
+ stopped = true;
60385
+ clearTimers();
60386
+ dropUpstream();
60387
+ }
60388
+ };
60389
+ }
60390
+
60252
60391
  // src/controllers/robot-fleet.controller.ts
60253
60392
  import Joi76 from "joi";
60254
60393
  import { BadRequestError as BadRequestError135, logger as logger106 } from "@7365admin1/node-server-utils";
@@ -60327,7 +60466,55 @@ function useRobotFleetController(deps) {
60327
60466
  fail(next, error);
60328
60467
  }
60329
60468
  }
60330
- return { getState, getMaps, getMapImages, getPlans, sendCommand: sendCommand2 };
60469
+ async function trackRobot(req, res, next) {
60470
+ let robot;
60471
+ let robotSn;
60472
+ try {
60473
+ robot = await entitleRobot(req, req.params.id);
60474
+ robotSn = await getFleet().resolveRobotSn(robot);
60475
+ } catch (error) {
60476
+ fail(next, error);
60477
+ return;
60478
+ }
60479
+ res.writeHead(200, {
60480
+ "Content-Type": "text/event-stream",
60481
+ "Cache-Control": "no-cache, no-transform",
60482
+ Connection: "keep-alive",
60483
+ // Nginx buffers proxied responses by default, which holds an SSE stream
60484
+ // until the buffer fills - the stream appears dead for minutes.
60485
+ "X-Accel-Buffering": "no"
60486
+ });
60487
+ res.flushHeaders?.();
60488
+ const send2 = (event) => {
60489
+ if (res.writableEnded)
60490
+ return;
60491
+ res.write(`data: ${JSON.stringify(event)}
60492
+
60493
+ `);
60494
+ };
60495
+ const handle = startRobotTracking({
60496
+ credentials: {
60497
+ appid: (robot.appKey ?? "").trim(),
60498
+ secret: (robot.appToken ?? "").trim()
60499
+ },
60500
+ robotSn,
60501
+ onEvent: send2
60502
+ });
60503
+ const keepAlive = setInterval(() => {
60504
+ if (!res.writableEnded)
60505
+ res.write(": keep-alive\n\n");
60506
+ }, 15e3);
60507
+ const close = () => {
60508
+ clearInterval(keepAlive);
60509
+ handle.stop();
60510
+ if (!res.writableEnded)
60511
+ res.end();
60512
+ };
60513
+ req.on("close", close);
60514
+ req.on("aborted", close);
60515
+ res.on("error", close);
60516
+ }
60517
+ return { getState, getMaps, getMapImages, getPlans, sendCommand: sendCommand2, trackRobot };
60331
60518
  }
60332
60519
 
60333
60520
  // src/models/patrol-question.model.ts
@@ -80953,7 +81140,7 @@ import {
80953
81140
  } from "@7365admin1/node-server-utils";
80954
81141
 
80955
81142
  // src/utils/hrmlabs-attendance.util.ts
80956
- import axios4 from "axios";
81143
+ import axios5 from "axios";
80957
81144
  import moment8 from "moment-timezone";
80958
81145
  var default_early_checkIn = 4;
80959
81146
  async function hrmLabsAuthentication({
@@ -80962,7 +81149,7 @@ async function hrmLabsAuthentication({
80962
81149
  password,
80963
81150
  domain
80964
81151
  }) {
80965
- const res = await axios4.post(
81152
+ const res = await axios5.post(
80966
81153
  authUrl,
80967
81154
  {
80968
81155
  grant_type: "password",
@@ -80992,7 +81179,7 @@ async function fetchAttendanceData({
80992
81179
  search
80993
81180
  }) {
80994
81181
  try {
80995
- const res = await axios4.post(
81182
+ const res = await axios5.post(
80996
81183
  attendanceUrl,
80997
81184
  {
80998
81185
  start: startDate,
@@ -81192,7 +81379,7 @@ async function fetchSites({ siteUrl, token }) {
81192
81379
  do {
81193
81380
  try {
81194
81381
  attempt++;
81195
- const res = await axios4.get(siteUrl, {
81382
+ const res = await axios5.get(siteUrl, {
81196
81383
  headers: { Authorization: `Bearer ${token}` },
81197
81384
  timeout: 15e3
81198
81385
  });
@@ -84840,7 +85027,7 @@ async function manpowerEvents(io) {
84840
85027
  }
84841
85028
 
84842
85029
  // src/services/reddot-payment.service.ts
84843
- import axios5 from "axios";
85030
+ import axios6 from "axios";
84844
85031
 
84845
85032
  // src/utils/payment-signature.util.ts
84846
85033
  import * as crypto9 from "crypto";
@@ -85482,7 +85669,7 @@ var useRedDotPaymentSvc = () => {
85482
85669
  );
85483
85670
  }
85484
85671
  const url = process.env.MERCHANT_PAYMENT;
85485
- const response = await axios5.post(url, dataString, { headers });
85672
+ const response = await axios6.post(url, dataString, { headers });
85486
85673
  const result = response.data;
85487
85674
  return result;
85488
85675
  } catch (error) {
@@ -85516,7 +85703,7 @@ var useRedDotPaymentSvc = () => {
85516
85703
  );
85517
85704
  }
85518
85705
  const url = process.env.MERCHANT_ENQUIRY;
85519
- const response = await axios5.post(url, dataString, { headers });
85706
+ const response = await axios6.post(url, dataString, { headers });
85520
85707
  const result = response.data;
85521
85708
  const transactionId = result.transaction_id;
85522
85709
  const amount = result.request_amount || 0;
@@ -94334,6 +94521,7 @@ export {
94334
94521
  ROBOT_CAPABILITIES,
94335
94522
  ROBOT_CLOUD_DOC_CONFIRMATIONS,
94336
94523
  ROBOT_CLOUD_PATHS,
94524
+ ROBOT_CLOUD_TIMEOUT_MS,
94337
94525
  ROBOT_MODULE,
94338
94526
  ROBOT_PERMISSIONS,
94339
94527
  ROBOT_STATUS_NAMES,
@@ -94772,6 +94960,7 @@ export {
94772
94960
  snapshotEndpoint,
94773
94961
  snapshotRefusalReason,
94774
94962
  staffMayBypass,
94963
+ startRobotTracking,
94775
94964
  startTodaysBookForSite,
94776
94965
  stringifyHidJson,
94777
94966
  stripFacialImageMetadata,