@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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +18 -0
- package/dist/index.d.mts +50 -3
- package/dist/index.d.ts +50 -3
- package/dist/index.js +172 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +172 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/protocol-discovery.test.ts +65 -5
- package/src/protocol-feed.test.ts +303 -0
- package/src/protocol.ts +205 -4
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 (
|
|
695
|
-
|
|
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
|