@objectstack/objectql 3.0.8 → 3.0.10

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
@@ -491,6 +491,7 @@ SchemaRegistry.namespaceRegistry = /* @__PURE__ */ new Map();
491
491
  SchemaRegistry.metadata = /* @__PURE__ */ new Map();
492
492
 
493
493
  // src/protocol.ts
494
+ import { parseFilterAST, isFilterAST } from "@objectstack/spec/data";
494
495
  function simpleHash(str) {
495
496
  let hash = 0;
496
497
  for (let i = 0; i < str.length; i++) {
@@ -518,9 +519,17 @@ var SERVICE_CONFIG = {
518
519
  search: { route: "/api/v1/search", plugin: "plugin-search" }
519
520
  };
520
521
  var ObjectStackProtocolImplementation = class {
521
- constructor(engine, getServicesRegistry) {
522
+ constructor(engine, getServicesRegistry, getFeedService) {
522
523
  this.engine = engine;
523
524
  this.getServicesRegistry = getServicesRegistry;
525
+ this.getFeedService = getFeedService;
526
+ }
527
+ requireFeedService() {
528
+ const svc = this.getFeedService?.();
529
+ if (!svc) {
530
+ throw new Error("Feed service not available. Install and register service-feed to enable feed operations.");
531
+ }
532
+ return svc;
524
533
  }
525
534
  async getDiscovery() {
526
535
  const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : /* @__PURE__ */ new Map();
@@ -569,16 +578,40 @@ var ObjectStackProtocolImplementation = class {
569
578
  }
570
579
  }
571
580
  }
581
+ if (registeredServices.has("feed")) {
582
+ services["feed"] = {
583
+ enabled: true,
584
+ status: "available",
585
+ route: "/api/v1/data",
586
+ provider: "service-feed"
587
+ };
588
+ } else {
589
+ services["feed"] = {
590
+ enabled: false,
591
+ status: "unavailable",
592
+ message: "Install service-feed to enable"
593
+ };
594
+ }
572
595
  const routes = {
573
596
  data: "/api/v1/data",
574
597
  metadata: "/api/v1/meta",
575
598
  ...optionalRoutes
576
599
  };
600
+ const capabilities = {
601
+ feed: registeredServices.has("feed"),
602
+ comments: registeredServices.has("feed"),
603
+ automation: registeredServices.has("automation"),
604
+ cron: registeredServices.has("job"),
605
+ search: registeredServices.has("search"),
606
+ export: registeredServices.has("automation") || registeredServices.has("queue"),
607
+ chunkedUpload: registeredServices.has("file-storage")
608
+ };
577
609
  return {
578
610
  version: "1.0",
579
611
  apiName: "ObjectStack API",
580
612
  routes,
581
- services
613
+ services,
614
+ capabilities
582
615
  };
583
616
  }
584
617
  async getMetaTypes() {
@@ -685,18 +718,18 @@ var ObjectStackProtocolImplementation = class {
685
718
  options.sort = parsed;
686
719
  delete options.orderBy;
687
720
  }
721
+ if (options.filters !== void 0 && options.filter === void 0) {
722
+ options.filter = options.filters;
723
+ }
724
+ delete options.filters;
688
725
  if (typeof options.filter === "string") {
689
726
  try {
690
727
  options.filter = JSON.parse(options.filter);
691
728
  } catch {
692
729
  }
693
730
  }
694
- if (typeof options.filters === "string") {
695
- try {
696
- options.filter = JSON.parse(options.filters);
697
- delete options.filters;
698
- } catch {
699
- }
731
+ if (isFilterAST(options.filter)) {
732
+ options.filter = parseFilterAST(options.filter);
700
733
  }
701
734
  if (typeof options.populate === "string") {
702
735
  options.populate = options.populate.split(",").map((s) => s.trim()).filter(Boolean);
@@ -1060,6 +1093,137 @@ var ObjectStackProtocolImplementation = class {
1060
1093
  message: "Saved to memory registry"
1061
1094
  };
1062
1095
  }
1096
+ // ==========================================
1097
+ // Feed Operations
1098
+ // ==========================================
1099
+ async listFeed(request) {
1100
+ const svc = this.requireFeedService();
1101
+ const result = await svc.listFeed({
1102
+ object: request.object,
1103
+ recordId: request.recordId,
1104
+ filter: request.type,
1105
+ limit: request.limit,
1106
+ cursor: request.cursor
1107
+ });
1108
+ return { success: true, data: result };
1109
+ }
1110
+ async createFeedItem(request) {
1111
+ const svc = this.requireFeedService();
1112
+ const item = await svc.createFeedItem({
1113
+ object: request.object,
1114
+ recordId: request.recordId,
1115
+ type: request.type,
1116
+ actor: { type: "user", id: "current_user" },
1117
+ body: request.body,
1118
+ mentions: request.mentions,
1119
+ parentId: request.parentId,
1120
+ visibility: request.visibility
1121
+ });
1122
+ return { success: true, data: item };
1123
+ }
1124
+ async updateFeedItem(request) {
1125
+ const svc = this.requireFeedService();
1126
+ const item = await svc.updateFeedItem(request.feedId, {
1127
+ body: request.body,
1128
+ mentions: request.mentions,
1129
+ visibility: request.visibility
1130
+ });
1131
+ return { success: true, data: item };
1132
+ }
1133
+ async deleteFeedItem(request) {
1134
+ const svc = this.requireFeedService();
1135
+ await svc.deleteFeedItem(request.feedId);
1136
+ return { success: true, data: { feedId: request.feedId } };
1137
+ }
1138
+ async addReaction(request) {
1139
+ const svc = this.requireFeedService();
1140
+ const reactions = await svc.addReaction(request.feedId, request.emoji, "current_user");
1141
+ return { success: true, data: { reactions } };
1142
+ }
1143
+ async removeReaction(request) {
1144
+ const svc = this.requireFeedService();
1145
+ const reactions = await svc.removeReaction(request.feedId, request.emoji, "current_user");
1146
+ return { success: true, data: { reactions } };
1147
+ }
1148
+ async pinFeedItem(request) {
1149
+ const svc = this.requireFeedService();
1150
+ const item = await svc.getFeedItem(request.feedId);
1151
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1152
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1153
+ return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: (/* @__PURE__ */ new Date()).toISOString() } };
1154
+ }
1155
+ async unpinFeedItem(request) {
1156
+ const svc = this.requireFeedService();
1157
+ const item = await svc.getFeedItem(request.feedId);
1158
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1159
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1160
+ return { success: true, data: { feedId: request.feedId, pinned: false } };
1161
+ }
1162
+ async starFeedItem(request) {
1163
+ const svc = this.requireFeedService();
1164
+ const item = await svc.getFeedItem(request.feedId);
1165
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1166
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1167
+ return { success: true, data: { feedId: request.feedId, starred: true, starredAt: (/* @__PURE__ */ new Date()).toISOString() } };
1168
+ }
1169
+ async unstarFeedItem(request) {
1170
+ const svc = this.requireFeedService();
1171
+ const item = await svc.getFeedItem(request.feedId);
1172
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1173
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1174
+ return { success: true, data: { feedId: request.feedId, starred: false } };
1175
+ }
1176
+ async searchFeed(request) {
1177
+ const svc = this.requireFeedService();
1178
+ const result = await svc.listFeed({
1179
+ object: request.object,
1180
+ recordId: request.recordId,
1181
+ filter: request.type,
1182
+ limit: request.limit,
1183
+ cursor: request.cursor
1184
+ });
1185
+ const queryLower = (request.query || "").toLowerCase();
1186
+ const filtered = result.items.filter(
1187
+ (item) => item.body?.toLowerCase().includes(queryLower)
1188
+ );
1189
+ return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };
1190
+ }
1191
+ async getChangelog(request) {
1192
+ const svc = this.requireFeedService();
1193
+ const result = await svc.listFeed({
1194
+ object: request.object,
1195
+ recordId: request.recordId,
1196
+ filter: "changes_only",
1197
+ limit: request.limit,
1198
+ cursor: request.cursor
1199
+ });
1200
+ const entries = result.items.map((item) => ({
1201
+ id: item.id,
1202
+ object: item.object,
1203
+ recordId: item.recordId,
1204
+ actor: item.actor,
1205
+ changes: item.changes || [],
1206
+ timestamp: item.createdAt,
1207
+ source: item.source
1208
+ }));
1209
+ return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };
1210
+ }
1211
+ async feedSubscribe(request) {
1212
+ const svc = this.requireFeedService();
1213
+ const subscription = await svc.subscribe({
1214
+ object: request.object,
1215
+ recordId: request.recordId,
1216
+ userId: "current_user",
1217
+ events: request.events,
1218
+ channels: request.channels
1219
+ });
1220
+ return { success: true, data: subscription };
1221
+ }
1222
+ async feedUnsubscribe(request) {
1223
+ const svc = this.requireFeedService();
1224
+ const unsubscribed = await svc.unsubscribe(request.object, request.recordId, "current_user");
1225
+ return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };
1226
+ }
1063
1227
  };
1064
1228
 
1065
1229
  // src/engine.ts