@dronedeploy/rocos-js-sdk 3.0.30 → 3.1.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.
Files changed (57) hide show
  1. package/cjs/api/streams/caller/CallerStreamAbstract.js +1 -2
  2. package/cjs/api/streams/caller/CallerStreamNode.js +18 -8
  3. package/cjs/api/streams/command/CommandStreamNode.js +17 -7
  4. package/cjs/api/streams/control/ControlStreamNode.js +17 -7
  5. package/cjs/api/streams/fileAccessor/FileAccessorStreamNode.js +17 -7
  6. package/cjs/api/streams/search/SearchStreamNode.js +17 -7
  7. package/cjs/api/streams/telemetry/TelemetryStream.js +1 -0
  8. package/cjs/api/streams/telemetry/TelemetryStreamConnect.d.ts +26 -0
  9. package/cjs/api/streams/telemetry/TelemetryStreamConnect.js +145 -0
  10. package/cjs/api/streams/telemetry/TelemetryStreamNode.js +18 -9
  11. package/cjs/grpc/conker_pb.grpc-client.js +17 -7
  12. package/cjs/grpc/connect/teletubby_pb.d.ts +635 -0
  13. package/cjs/grpc/connect/teletubby_pb.js +196 -0
  14. package/cjs/grpc/filagree_pb.grpc-client.js +17 -7
  15. package/cjs/grpc/pigeon_pb.grpc-client.js +17 -7
  16. package/cjs/grpc/rambo.v1_pb.grpc-client.js +17 -7
  17. package/cjs/grpc/serviette.v1_pb.grpc-client.js +17 -7
  18. package/cjs/grpc/slowlane_pb.grpc-client.js +17 -7
  19. package/cjs/grpc/teletubby_pb.grpc-client.js +17 -7
  20. package/cjs/helpers/callerMessageHelpers.js +2 -3
  21. package/cjs/helpers/flattenOneOf.js +2 -3
  22. package/cjs/helpers/generateUUID.js +1 -2
  23. package/cjs/helpers/getSha256Hex.d.ts +1 -1
  24. package/cjs/helpers/getSha256HexNode.d.ts +1 -1
  25. package/cjs/helpers/kscript/index.js +17 -7
  26. package/cjs/helpers/kscript/utils.js +1 -2
  27. package/cjs/helpers/splitRobotTopic.js +1 -2
  28. package/cjs/helpers/stringToUint8Array.js +1 -8
  29. package/cjs/helpers/websandbox/connection.d.ts +1 -1
  30. package/cjs/logger/RocosLogger.js +9 -30
  31. package/cjs/models/IRocosSDKConfig.d.ts +2 -0
  32. package/cjs/models/IStreamConfig.d.ts +3 -0
  33. package/cjs/models/asset-storage/SyncIntegrations.d.ts +1 -2
  34. package/cjs/services/CallerService.js +1 -2
  35. package/cjs/services/SpotProvisioningServiceNode.d.ts +0 -1
  36. package/cjs/services/TelemetryService.js +5 -0
  37. package/esm/api/streams/caller/CallerStreamAbstract.js +1 -2
  38. package/esm/api/streams/caller/CallerStreamNode.js +1 -1
  39. package/esm/api/streams/telemetry/TelemetryStream.js +1 -0
  40. package/esm/api/streams/telemetry/TelemetryStreamConnect.d.ts +26 -0
  41. package/esm/api/streams/telemetry/TelemetryStreamConnect.js +141 -0
  42. package/esm/api/streams/telemetry/TelemetryStreamNode.js +1 -2
  43. package/esm/grpc/connect/teletubby_pb.d.ts +635 -0
  44. package/esm/grpc/connect/teletubby_pb.js +193 -0
  45. package/esm/helpers/generateUUID.js +1 -2
  46. package/esm/helpers/getSha256Hex.d.ts +1 -1
  47. package/esm/helpers/getSha256HexNode.d.ts +1 -1
  48. package/esm/helpers/stringToUint8Array.js +1 -8
  49. package/esm/helpers/websandbox/connection.d.ts +1 -1
  50. package/esm/logger/RocosLogger.js +9 -7
  51. package/esm/models/IRocosSDKConfig.d.ts +2 -0
  52. package/esm/models/IStreamConfig.d.ts +3 -0
  53. package/esm/models/asset-storage/SyncIntegrations.d.ts +1 -2
  54. package/esm/services/CallerService.js +1 -2
  55. package/esm/services/SpotProvisioningServiceNode.d.ts +0 -1
  56. package/esm/services/TelemetryService.js +5 -0
  57. package/package.json +5 -7
@@ -9,7 +9,6 @@ const BaseStreamService_1 = require("./BaseStreamService");
9
9
  const CallerStream_1 = require("../api/streams/caller/CallerStream");
10
10
  const identifier_1 = require("../constants/identifier");
11
11
  const helpers_1 = require("../helpers");
12
- const uuid_1 = require("uuid");
13
12
  class CallerService extends BaseStreamService_1.BaseStreamService {
14
13
  constructor(config) {
15
14
  super('CallerService', config);
@@ -66,7 +65,7 @@ class CallerService extends BaseStreamService_1.BaseStreamService {
66
65
  }
67
66
  getCallerParams(params, component, topic) {
68
67
  return {
69
- uid: params.options?.uid ?? (0, uuid_1.v4)(),
68
+ uid: params.options?.uid ?? crypto.randomUUID(),
70
69
  projectId: params.projectId,
71
70
  callsign: params.callsign,
72
71
  subSystem: '',
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { IBaseService, IRocosSDKConfig, RocosError } from '../models';
3
2
  import { BaseServiceAbstract } from './BaseServiceAbstract';
4
3
  import { Timezone } from '../constants/timezones';
@@ -8,6 +8,7 @@ const BaseStreamService_1 = require("./BaseStreamService");
8
8
  const identifier_1 = require("../constants/identifier");
9
9
  const RocosStore_1 = require("../store/RocosStore");
10
10
  const TelemetryStream_1 = require("../api/streams/telemetry/TelemetryStream");
11
+ const TelemetryStreamConnect_1 = require("../api/streams/telemetry/TelemetryStreamConnect");
11
12
  const arrayUnique_1 = require("../helpers/arrayUnique");
12
13
  const flattenCallsignsLookup_1 = require("../helpers/flattenCallsignsLookup");
13
14
  const getUniqueId_1 = require("../helpers/getUniqueId");
@@ -162,6 +163,7 @@ class TelemetryService extends BaseStreamService_1.BaseStreamService {
162
163
  options: this.config.options,
163
164
  port: this.config.port,
164
165
  insecure: this.config.insecure,
166
+ transport: this.config.transport,
165
167
  });
166
168
  if (!newStream.isNew) {
167
169
  newStream.stream.statusStream$.subscribe((msg) => {
@@ -174,6 +176,9 @@ class TelemetryService extends BaseStreamService_1.BaseStreamService {
174
176
  return newStream.stream;
175
177
  }
176
178
  getStream(config) {
179
+ if (config.transport === 'connect') {
180
+ return new TelemetryStreamConnect_1.TelemetryStreamConnect(config);
181
+ }
177
182
  return new TelemetryStream_1.TelemetryStream(config);
178
183
  }
179
184
  }
@@ -6,7 +6,6 @@ import { IDENTIFIER_NAME_CALLER } from '../../../constants/identifier';
6
6
  import { RocosStore } from '../../../store/RocosStore';
7
7
  import { StreamRegister } from '../../StreamRegister';
8
8
  import { filter } from 'rxjs/operators';
9
- import { v4 as uuidv4 } from 'uuid';
10
9
  export class CallerStreamAbstract {
11
10
  constructor(config) {
12
11
  this.subscriberStatus = SubscriberStatusEnum.STOPPED;
@@ -78,7 +77,7 @@ export class CallerStreamAbstract {
78
77
  version: UIDVersion.HEADER_HASH_RAND,
79
78
  content: {
80
79
  oneofKind: 'hash',
81
- hash: uid ?? uuidv4(),
80
+ hash: uid ?? crypto.randomUUID(),
82
81
  },
83
82
  },
84
83
  payload: this.getPayload(payload),
@@ -102,7 +102,7 @@ export class CallerStreamNode extends CallerStreamAbstract {
102
102
  });
103
103
  }
104
104
  getPayload(payload) {
105
- return Buffer.from(payload);
105
+ return new TextEncoder().encode(payload);
106
106
  }
107
107
  getMetadata(projectId, callsign, subsystem) {
108
108
  const meta = new grpc.Metadata();
@@ -12,6 +12,7 @@ export class TelemetryStream extends TelemetryStreamAbstract {
12
12
  const port = config.port ? `:${config.port}` : '';
13
13
  const transport = new GrpcWebFetchTransport({
14
14
  baseUrl: `${protocol}://${this.url}${port}`,
15
+ format: config.grpcWebFormat,
15
16
  });
16
17
  this.client = new TelemetryGatewayClient(transport);
17
18
  }
@@ -0,0 +1,26 @@
1
+ import { ITelemetryStreamConfig } from '../../../models';
2
+ import { TelemetryAckStatus, TelemetryQueryRequest, TelemetryRequest } from '../../../grpc/teletubby_pb';
3
+ import { TelemetryStreamAbstract } from './TelemetryStreamAbstract';
4
+ /**
5
+ * Connect-protocol telemetry receive stream. Mirrors TelemetryStream (grpc-web) but uses
6
+ * @connectrpc/connect. Selected when config.transport === 'connect'.
7
+ *
8
+ * The shared TelemetryStreamAbstract is typed with the protobuf-ts message types, while the
9
+ * Connect client uses @bufbuild/protobuf types. Both serialise to identical protobuf wire
10
+ * bytes, so we bridge across the boundary with toBinary/fromBinary rather than hand-written
11
+ * field mapping. This keeps all reconnect/subscription/heartbeat logic shared and untouched.
12
+ */
13
+ export declare class TelemetryStreamConnect extends TelemetryStreamAbstract {
14
+ private client;
15
+ private abortController?;
16
+ constructor(config: ITelemetryStreamConfig);
17
+ protected stopInternal(): void;
18
+ protected registerReceiver(): () => void;
19
+ private onError;
20
+ private onEnd;
21
+ private getHeaders;
22
+ protected requestTelemetry(req: TelemetryRequest): Promise<void>;
23
+ protected requestTelemetryQuery(req: TelemetryQueryRequest): Promise<void>;
24
+ protected sendAcknowledgmentInternal(uid: string, status: TelemetryAckStatus, noRetry: boolean): boolean;
25
+ protected sendHeartbeat(): void;
26
+ }
@@ -0,0 +1,141 @@
1
+ import { createClient } from '@connectrpc/connect';
2
+ import { SubscriberStatusEnum } from '../../../models';
3
+ import { RegistrationMessageSchema, TelemetryGateway, TelemetryQueryRequestSchema, TelemetryRequestSchema, } from '../../../grpc/connect/teletubby_pb';
4
+ import { TelemetryMessage, TelemetryQueryRequest, TelemetryRequest, } from '../../../grpc/teletubby_pb';
5
+ import { create, fromBinary } from '@bufbuild/protobuf';
6
+ import { RocosLogger } from '../../../logger/RocosLogger';
7
+ import { TelemetryStreamAbstract } from './TelemetryStreamAbstract';
8
+ import { createConnectTransport } from '@connectrpc/connect-web';
9
+ /**
10
+ * Connect-protocol telemetry receive stream. Mirrors TelemetryStream (grpc-web) but uses
11
+ * @connectrpc/connect. Selected when config.transport === 'connect'.
12
+ *
13
+ * The shared TelemetryStreamAbstract is typed with the protobuf-ts message types, while the
14
+ * Connect client uses @bufbuild/protobuf types. Both serialise to identical protobuf wire
15
+ * bytes, so we bridge across the boundary with toBinary/fromBinary rather than hand-written
16
+ * field mapping. This keeps all reconnect/subscription/heartbeat logic shared and untouched.
17
+ */
18
+ export class TelemetryStreamConnect extends TelemetryStreamAbstract {
19
+ constructor(config) {
20
+ super(config);
21
+ this.logger = RocosLogger.getInstance(`TelemetryStreamConnect(${this.identifier})`);
22
+ const protocol = config.insecure ? 'http' : 'https';
23
+ const port = config.port ? `:${config.port}` : '';
24
+ const transport = createConnectTransport({
25
+ baseUrl: `${protocol}://${this.url}${port}`,
26
+ // Binary proto codec. The Connect default is JSON, which fails to decode real telemetry
27
+ // payloads containing control characters (verified against a live robot on dev) and is
28
+ // less efficient. Binary is required for correctness here.
29
+ useBinaryFormat: true,
30
+ });
31
+ this.client = createClient(TelemetryGateway, transport);
32
+ }
33
+ stopInternal() {
34
+ if (this.abortController) {
35
+ this.logger.info('Starting stop stream process');
36
+ this.abortController.abort();
37
+ this.abortController = undefined;
38
+ this.logger.info('Finished stop stream process');
39
+ }
40
+ }
41
+ registerReceiver() {
42
+ this.logger.info('registerReceiver');
43
+ // Reset counter
44
+ this.receivedMessagesCount = 0;
45
+ const abortController = new AbortController();
46
+ this.abortController = abortController;
47
+ void (async () => {
48
+ try {
49
+ const stream = this.client.registerReceiver(create(RegistrationMessageSchema, {}), {
50
+ headers: this.getHeaders(this.projectId),
51
+ signal: abortController.signal,
52
+ });
53
+ for await (const msg of stream) {
54
+ // Bridge connect-es message -> protobuf-ts TelemetryMessage with a direct field map.
55
+ // (Avoids a per-message re-serialize/re-parse; created/seq are int64/uint64 -> string
56
+ // for protobuf-ts's long_type_string config.)
57
+ const ptMsg = TelemetryMessage.create({
58
+ source: msg.source,
59
+ callsign: msg.callsign,
60
+ payload: msg.payload,
61
+ uid: msg.uid,
62
+ created: msg.created.toString(),
63
+ seq: msg.seq.toString(),
64
+ meta: msg.meta,
65
+ });
66
+ this.onData(ptMsg, false);
67
+ }
68
+ this.onEnd(true);
69
+ }
70
+ catch (e) {
71
+ if (abortController.signal.aborted) {
72
+ this.logger.debug('registerReceiver', 'aborted');
73
+ return;
74
+ }
75
+ void this.onError(e);
76
+ this.onEnd(false);
77
+ }
78
+ })();
79
+ this.listenMessagesAndRenew();
80
+ return () => {
81
+ abortController.abort();
82
+ };
83
+ }
84
+ async onError(e) {
85
+ this.logger.error(`Telemetry Stream Error: ${e}, SubscriberId: ${this.subscriberId}`);
86
+ this.subscriberStatus = SubscriberStatusEnum.ERROR;
87
+ this.statusStream$.next(this.subscriberStatus);
88
+ }
89
+ onEnd(ok) {
90
+ this.logger.debug('registerReceiver', 'end');
91
+ if (ok) {
92
+ this.stopInternal();
93
+ this.registerReceiver();
94
+ }
95
+ }
96
+ getHeaders(projectId) {
97
+ const result = {
98
+ // Canary marker: the istio VirtualService routes only requests carrying this header to
99
+ // the Connect-Go handler (:8083), leaving existing grpc-web traffic untouched. Harmless
100
+ // when the backend does a full cutover or is hit directly. Must match the chart's
101
+ // virtualService.routes.connect.matchHeader.
102
+ 'x-tt-connect': '1',
103
+ };
104
+ if (this.token) {
105
+ result.authorization = this.token;
106
+ }
107
+ if (projectId) {
108
+ result['r-p'] = projectId;
109
+ }
110
+ return result;
111
+ }
112
+ async requestTelemetry(req) {
113
+ this.logger.debug('Sending telemetry request');
114
+ try {
115
+ const connectReq = fromBinary(TelemetryRequestSchema, TelemetryRequest.toBinary(req));
116
+ await this.client.requestTelemetry(connectReq, { headers: this.getHeaders(this.projectId) });
117
+ }
118
+ catch (e) {
119
+ this.logger.error('error requestTelemetry ', e);
120
+ throw e;
121
+ }
122
+ }
123
+ async requestTelemetryQuery(req) {
124
+ this.logger.debug('Requesting telemetry with query');
125
+ try {
126
+ const connectReq = fromBinary(TelemetryQueryRequestSchema, TelemetryQueryRequest.toBinary(req));
127
+ await this.client.requestTelemetryQuery(connectReq, { headers: this.getHeaders(this.projectId) });
128
+ }
129
+ catch (e) {
130
+ this.logger.error('error requestTelemetryQuery ', e);
131
+ throw e;
132
+ }
133
+ }
134
+ sendAcknowledgmentInternal(uid, status, noRetry) {
135
+ this.logger.error('Error can not send Acknowledgment on connect client', { uid, status, noRetry });
136
+ return false;
137
+ }
138
+ sendHeartbeat() {
139
+ // Server-streaming Connect has no client->server channel for heartbeats.
140
+ }
141
+ }
@@ -4,7 +4,6 @@ import { ReceiverStreamMessage, } from '../../../grpc/teletubby_pb';
4
4
  import { RocosLogger } from '../../../logger/RocosLogger';
5
5
  import { TelemetryReceiverClient } from '../../../grpc/teletubby_pb.grpc-client';
6
6
  import { TelemetryStreamAbstract } from './TelemetryStreamAbstract';
7
- import { v4 as uuid4 } from 'uuid';
8
7
  export class TelemetryStreamNode extends TelemetryStreamAbstract {
9
8
  constructor(config) {
10
9
  super(config);
@@ -104,7 +103,7 @@ export class TelemetryStreamNode extends TelemetryStreamAbstract {
104
103
  getMetaData() {
105
104
  const meta = new grpc.Metadata();
106
105
  meta.add('r-p', this.projectId);
107
- meta.add('r-tid', uuid4());
106
+ meta.add('r-tid', crypto.randomUUID());
108
107
  meta.add('r-cs', 'rocos-js-sdk-agent');
109
108
  if (this.token)
110
109
  meta.add('authorization', this.token);