@objectstack/client 3.0.8 → 3.0.9

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.js CHANGED
@@ -614,12 +614,80 @@ var ObjectStackClient = class {
614
614
  const res = await this.fetch(`${this.baseUrl}${route}/files/${fileId}/url`);
615
615
  const data = await res.json();
616
616
  return data.url;
617
+ },
618
+ /**
619
+ * Get a presigned URL for direct-to-cloud upload
620
+ */
621
+ getPresignedUrl: async (req) => {
622
+ const route = this.getRoute("storage");
623
+ const res = await this.fetch(`${this.baseUrl}${route}/upload/presigned`, {
624
+ method: "POST",
625
+ body: JSON.stringify(req)
626
+ });
627
+ return res.json();
628
+ },
629
+ /**
630
+ * Initiate a chunked (multipart) upload session
631
+ */
632
+ initChunkedUpload: async (req) => {
633
+ const route = this.getRoute("storage");
634
+ const res = await this.fetch(`${this.baseUrl}${route}/upload/chunked`, {
635
+ method: "POST",
636
+ body: JSON.stringify(req)
637
+ });
638
+ return res.json();
639
+ },
640
+ /**
641
+ * Upload a single chunk/part of a multipart upload
642
+ */
643
+ uploadPart: async (uploadId, chunkIndex, resumeToken, data) => {
644
+ const route = this.getRoute("storage");
645
+ const res = await this.fetch(`${this.baseUrl}${route}/upload/chunked/${uploadId}/chunk/${chunkIndex}`, {
646
+ method: "PUT",
647
+ headers: { "x-resume-token": resumeToken },
648
+ body: data
649
+ });
650
+ return res.json();
651
+ },
652
+ /**
653
+ * Complete a chunked upload by assembling all parts
654
+ */
655
+ completeChunkedUpload: async (req) => {
656
+ const route = this.getRoute("storage");
657
+ const res = await this.fetch(`${this.baseUrl}${route}/upload/chunked/${req.uploadId}/complete`, {
658
+ method: "POST",
659
+ body: JSON.stringify(req)
660
+ });
661
+ return res.json();
662
+ },
663
+ /**
664
+ * Resume an interrupted chunked upload.
665
+ * Fetches current progress, then uploads remaining chunks and completes.
666
+ */
667
+ resumeUpload: async (uploadId, file, chunkSize, resumeToken) => {
668
+ const route = this.getRoute("storage");
669
+ const progressRes = await this.fetch(`${this.baseUrl}${route}/upload/chunked/${uploadId}/progress`);
670
+ const progress = await progressRes.json();
671
+ const { totalChunks, uploadedChunks } = progress.data;
672
+ const parts = [];
673
+ const fileBuffer = file instanceof ArrayBuffer ? file : await file.arrayBuffer();
674
+ for (let i = uploadedChunks; i < totalChunks; i++) {
675
+ const start = i * chunkSize;
676
+ const end = Math.min(start + chunkSize, fileBuffer.byteLength);
677
+ const chunk = new Blob([fileBuffer.slice(start, end)]);
678
+ const chunkRes = await this.storage.uploadPart(uploadId, i, resumeToken, chunk);
679
+ parts.push({ chunkIndex: i, eTag: chunkRes.data.eTag });
680
+ }
681
+ return this.storage.completeChunkedUpload({ uploadId, parts });
617
682
  }
618
683
  };
619
684
  /**
620
685
  * Automation Services
621
686
  */
622
687
  this.automation = {
688
+ /**
689
+ * Trigger a named automation flow (legacy endpoint)
690
+ */
623
691
  trigger: async (triggerName, payload) => {
624
692
  const route = this.getRoute("automation");
625
693
  const res = await this.fetch(`${this.baseUrl}${route}/trigger/${triggerName}`, {
@@ -627,6 +695,90 @@ var ObjectStackClient = class {
627
695
  body: JSON.stringify(payload)
628
696
  });
629
697
  return res.json();
698
+ },
699
+ /**
700
+ * List all registered automation flows
701
+ */
702
+ list: async () => {
703
+ const route = this.getRoute("automation");
704
+ const res = await this.fetch(`${this.baseUrl}${route}`);
705
+ return this.unwrapResponse(res);
706
+ },
707
+ /**
708
+ * Get a flow definition by name
709
+ */
710
+ get: async (name) => {
711
+ const route = this.getRoute("automation");
712
+ const res = await this.fetch(`${this.baseUrl}${route}/${name}`);
713
+ return this.unwrapResponse(res);
714
+ },
715
+ /**
716
+ * Create (register) a new flow
717
+ */
718
+ create: async (name, definition) => {
719
+ const route = this.getRoute("automation");
720
+ const res = await this.fetch(`${this.baseUrl}${route}`, {
721
+ method: "POST",
722
+ body: JSON.stringify({ name, ...definition })
723
+ });
724
+ return this.unwrapResponse(res);
725
+ },
726
+ /**
727
+ * Update an existing flow
728
+ */
729
+ update: async (name, definition) => {
730
+ const route = this.getRoute("automation");
731
+ const res = await this.fetch(`${this.baseUrl}${route}/${name}`, {
732
+ method: "PUT",
733
+ body: JSON.stringify({ definition })
734
+ });
735
+ return this.unwrapResponse(res);
736
+ },
737
+ /**
738
+ * Delete (unregister) a flow
739
+ */
740
+ delete: async (name) => {
741
+ const route = this.getRoute("automation");
742
+ const res = await this.fetch(`${this.baseUrl}${route}/${name}`, {
743
+ method: "DELETE"
744
+ });
745
+ return this.unwrapResponse(res);
746
+ },
747
+ /**
748
+ * Enable or disable a flow
749
+ */
750
+ toggle: async (name, enabled) => {
751
+ const route = this.getRoute("automation");
752
+ const res = await this.fetch(`${this.baseUrl}${route}/${name}/toggle`, {
753
+ method: "POST",
754
+ body: JSON.stringify({ enabled })
755
+ });
756
+ return this.unwrapResponse(res);
757
+ },
758
+ /**
759
+ * Execution run history
760
+ */
761
+ runs: {
762
+ /**
763
+ * List execution runs for a flow
764
+ */
765
+ list: async (flowName, options) => {
766
+ const route = this.getRoute("automation");
767
+ const params = new URLSearchParams();
768
+ if (options?.limit) params.set("limit", String(options.limit));
769
+ if (options?.cursor) params.set("cursor", options.cursor);
770
+ const qs = params.toString();
771
+ const res = await this.fetch(`${this.baseUrl}${route}/${flowName}/runs${qs ? `?${qs}` : ""}`);
772
+ return this.unwrapResponse(res);
773
+ },
774
+ /**
775
+ * Get a single execution run
776
+ */
777
+ get: async (flowName, runId) => {
778
+ const route = this.getRoute("automation");
779
+ const res = await this.fetch(`${this.baseUrl}${route}/${flowName}/runs/${runId}`);
780
+ return this.unwrapResponse(res);
781
+ }
630
782
  }
631
783
  };
632
784
  /**
@@ -1007,6 +1159,174 @@ var ObjectStackClient = class {
1007
1159
  return this.unwrapResponse(res);
1008
1160
  }
1009
1161
  };
1162
+ /**
1163
+ * Feed / Chatter Services
1164
+ *
1165
+ * Provides access to the activity timeline (comments, field changes, tasks),
1166
+ * emoji reactions, pin/star, search, changelog, and record subscriptions.
1167
+ * Base path: /api/data/{object}/{recordId}/feed
1168
+ */
1169
+ this.feed = {
1170
+ /**
1171
+ * List feed items for a record
1172
+ */
1173
+ list: async (object, recordId, options) => {
1174
+ const route = this.getRoute("feed");
1175
+ const params = new URLSearchParams();
1176
+ if (options?.type) params.set("type", options.type);
1177
+ if (options?.limit) params.set("limit", String(options.limit));
1178
+ if (options?.cursor) params.set("cursor", options.cursor);
1179
+ const qs = params.toString();
1180
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed${qs ? `?${qs}` : ""}`);
1181
+ return this.unwrapResponse(res);
1182
+ },
1183
+ /**
1184
+ * Create a new feed item (comment, note, task, etc.)
1185
+ */
1186
+ create: async (object, recordId, data) => {
1187
+ const route = this.getRoute("feed");
1188
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed`, {
1189
+ method: "POST",
1190
+ body: JSON.stringify(data)
1191
+ });
1192
+ return this.unwrapResponse(res);
1193
+ },
1194
+ /**
1195
+ * Update an existing feed item
1196
+ */
1197
+ update: async (object, recordId, feedId, data) => {
1198
+ const route = this.getRoute("feed");
1199
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}`, {
1200
+ method: "PUT",
1201
+ body: JSON.stringify(data)
1202
+ });
1203
+ return this.unwrapResponse(res);
1204
+ },
1205
+ /**
1206
+ * Delete a feed item
1207
+ */
1208
+ delete: async (object, recordId, feedId) => {
1209
+ const route = this.getRoute("feed");
1210
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}`, {
1211
+ method: "DELETE"
1212
+ });
1213
+ return this.unwrapResponse(res);
1214
+ },
1215
+ /**
1216
+ * Add an emoji reaction to a feed item
1217
+ */
1218
+ addReaction: async (object, recordId, feedId, emoji) => {
1219
+ const route = this.getRoute("feed");
1220
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}/reactions`, {
1221
+ method: "POST",
1222
+ body: JSON.stringify({ emoji })
1223
+ });
1224
+ return this.unwrapResponse(res);
1225
+ },
1226
+ /**
1227
+ * Remove an emoji reaction from a feed item
1228
+ */
1229
+ removeReaction: async (object, recordId, feedId, emoji) => {
1230
+ const route = this.getRoute("feed");
1231
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}/reactions/${encodeURIComponent(emoji)}`, {
1232
+ method: "DELETE"
1233
+ });
1234
+ return this.unwrapResponse(res);
1235
+ },
1236
+ /**
1237
+ * Pin a feed item to the top of the timeline
1238
+ */
1239
+ pin: async (object, recordId, feedId) => {
1240
+ const route = this.getRoute("feed");
1241
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}/pin`, {
1242
+ method: "POST"
1243
+ });
1244
+ return this.unwrapResponse(res);
1245
+ },
1246
+ /**
1247
+ * Unpin a feed item
1248
+ */
1249
+ unpin: async (object, recordId, feedId) => {
1250
+ const route = this.getRoute("feed");
1251
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}/pin`, {
1252
+ method: "DELETE"
1253
+ });
1254
+ return this.unwrapResponse(res);
1255
+ },
1256
+ /**
1257
+ * Star (bookmark) a feed item
1258
+ */
1259
+ star: async (object, recordId, feedId) => {
1260
+ const route = this.getRoute("feed");
1261
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}/star`, {
1262
+ method: "POST"
1263
+ });
1264
+ return this.unwrapResponse(res);
1265
+ },
1266
+ /**
1267
+ * Unstar a feed item
1268
+ */
1269
+ unstar: async (object, recordId, feedId) => {
1270
+ const route = this.getRoute("feed");
1271
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/${encodeURIComponent(feedId)}/star`, {
1272
+ method: "DELETE"
1273
+ });
1274
+ return this.unwrapResponse(res);
1275
+ },
1276
+ /**
1277
+ * Search feed items
1278
+ */
1279
+ search: async (object, recordId, query, options) => {
1280
+ const route = this.getRoute("feed");
1281
+ const params = new URLSearchParams();
1282
+ params.set("query", query);
1283
+ if (options?.type) params.set("type", options.type);
1284
+ if (options?.actorId) params.set("actorId", options.actorId);
1285
+ if (options?.dateFrom) params.set("dateFrom", options.dateFrom);
1286
+ if (options?.dateTo) params.set("dateTo", options.dateTo);
1287
+ if (options?.limit) params.set("limit", String(options.limit));
1288
+ if (options?.cursor) params.set("cursor", options.cursor);
1289
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/feed/search?${params.toString()}`);
1290
+ return this.unwrapResponse(res);
1291
+ },
1292
+ /**
1293
+ * Get field-level changelog for a record
1294
+ */
1295
+ getChangelog: async (object, recordId, options) => {
1296
+ const route = this.getRoute("feed");
1297
+ const params = new URLSearchParams();
1298
+ if (options?.field) params.set("field", options.field);
1299
+ if (options?.actorId) params.set("actorId", options.actorId);
1300
+ if (options?.dateFrom) params.set("dateFrom", options.dateFrom);
1301
+ if (options?.dateTo) params.set("dateTo", options.dateTo);
1302
+ if (options?.limit) params.set("limit", String(options.limit));
1303
+ if (options?.cursor) params.set("cursor", options.cursor);
1304
+ const qs = params.toString();
1305
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/changelog${qs ? `?${qs}` : ""}`);
1306
+ return this.unwrapResponse(res);
1307
+ },
1308
+ /**
1309
+ * Subscribe to record notifications
1310
+ */
1311
+ subscribe: async (object, recordId, options) => {
1312
+ const route = this.getRoute("feed");
1313
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/subscribe`, {
1314
+ method: "POST",
1315
+ body: JSON.stringify(options || {})
1316
+ });
1317
+ return this.unwrapResponse(res);
1318
+ },
1319
+ /**
1320
+ * Unsubscribe from record notifications
1321
+ */
1322
+ unsubscribe: async (object, recordId) => {
1323
+ const route = this.getRoute("feed");
1324
+ const res = await this.fetch(`${this.baseUrl}${route}/${encodeURIComponent(object)}/${encodeURIComponent(recordId)}/subscribe`, {
1325
+ method: "DELETE"
1326
+ });
1327
+ return this.unwrapResponse(res);
1328
+ }
1329
+ };
1010
1330
  /**
1011
1331
  * Data Operations
1012
1332
  */
@@ -1198,6 +1518,14 @@ var ObjectStackClient = class {
1198
1518
  throw e;
1199
1519
  }
1200
1520
  }
1521
+ /**
1522
+ * Well-known capability flags discovered from the server.
1523
+ * Returns undefined if the client has not yet connected or the server
1524
+ * did not include capabilities in its discovery response.
1525
+ */
1526
+ get capabilities() {
1527
+ return this.discoveryInfo?.capabilities;
1528
+ }
1201
1529
  /**
1202
1530
  * Private Helpers
1203
1531
  */
@@ -1287,7 +1615,8 @@ var ObjectStackClient = class {
1287
1615
  views: "/api/v1/ui/views",
1288
1616
  notifications: "/api/v1/notifications",
1289
1617
  ai: "/api/v1/ai",
1290
- i18n: "/api/v1/i18n"
1618
+ i18n: "/api/v1/i18n",
1619
+ feed: "/api/v1/data"
1291
1620
  };
1292
1621
  return routeMap[type] || `/api/v1/${type}`;
1293
1622
  }