@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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @objectstack/objectql@3.0.8 build /home/runner/work/spec/spec/packages/objectql
2
+ > @objectstack/objectql@3.0.10 build /home/runner/work/spec/spec/packages/objectql
3
3
  > tsup --config ../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- CJS dist/index.js 84.46 KB
14
- CJS dist/index.js.map 171.04 KB
15
- CJS ⚡️ Build success in 184ms
16
- ESM dist/index.mjs 82.74 KB
17
- ESM dist/index.mjs.map 169.75 KB
18
- ESM ⚡️ Build success in 186ms
13
+ ESM dist/index.mjs 89.01 KB
14
+ ESM dist/index.mjs.map 182.74 KB
15
+ ESM ⚡️ Build success in 209ms
16
+ CJS dist/index.js 90.75 KB
17
+ CJS dist/index.js.map 184.04 KB
18
+ CJS ⚡️ Build success in 213ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 21175ms
21
- DTS dist/index.d.mts 71.63 KB
22
- DTS dist/index.d.ts 71.63 KB
20
+ DTS ⚡️ Build success in 22325ms
21
+ DTS dist/index.d.mts 73.43 KB
22
+ DTS dist/index.d.ts 73.43 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @objectstack/objectql
2
2
 
3
+ ## 3.0.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [d1e5d31]
8
+ - @objectstack/spec@3.0.10
9
+ - @objectstack/core@3.0.10
10
+ - @objectstack/types@3.0.10
11
+
12
+ ## 3.0.9
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [15e0df6]
17
+ - @objectstack/spec@3.0.9
18
+ - @objectstack/core@3.0.9
19
+ - @objectstack/types@3.0.9
20
+
3
21
  ## 3.0.8
4
22
 
5
23
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -4,6 +4,7 @@ import { ServiceObject, ObjectOwnership, HookContext, QueryAST, DataEngineQueryO
4
4
  import { ObjectStackManifest, InstalledPackage, ExecutionContext } from '@objectstack/spec/kernel';
5
5
  import { ObjectStackProtocol, MetadataCacheRequest, MetadataCacheResponse, BatchUpdateRequest, BatchUpdateResponse, UpdateManyDataRequest, DeleteManyDataRequest } from '@objectstack/spec/api';
6
6
  import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext, ObjectKernel } from '@objectstack/core';
7
+ import { IFeedService } from '@objectstack/spec/contracts';
7
8
 
8
9
  /**
9
10
  * XState-inspired State Machine Protocol
@@ -204,7 +205,7 @@ declare class SchemaRegistry {
204
205
  abstract: boolean;
205
206
  datasource: string;
206
207
  fields: Record<string, {
207
- type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "json" | "text" | "textarea" | "email" | "url" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
208
+ type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
208
209
  required: boolean;
209
210
  searchable: boolean;
210
211
  multiple: boolean;
@@ -840,6 +841,9 @@ declare class SchemaRegistry {
840
841
  } | undefined;
841
842
  } | undefined;
842
843
  } | undefined;
844
+ engine?: {
845
+ objectstack: string;
846
+ } | undefined;
843
847
  };
844
848
  status: "error" | "disabled" | "installed" | "installing" | "upgrading" | "uninstalling";
845
849
  enabled: boolean;
@@ -850,6 +854,14 @@ declare class SchemaRegistry {
850
854
  statusChangedAt?: string | undefined;
851
855
  errorMessage?: string | undefined;
852
856
  settings?: Record<string, unknown> | undefined;
857
+ upgradeHistory?: {
858
+ fromVersion: string;
859
+ toVersion: string;
860
+ upgradedAt: string;
861
+ status: "success" | "failed" | "rolled_back";
862
+ migrationLog?: string[] | undefined;
863
+ }[] | undefined;
864
+ registeredNamespaces?: string[] | undefined;
853
865
  } | {
854
866
  id: string;
855
867
  version: string;
@@ -1154,6 +1166,9 @@ declare class SchemaRegistry {
1154
1166
  } | undefined;
1155
1167
  } | undefined;
1156
1168
  } | undefined;
1169
+ engine?: {
1170
+ objectstack: string;
1171
+ } | undefined;
1157
1172
  };
1158
1173
  /**
1159
1174
  * Universal Unregister Method
@@ -1199,7 +1214,9 @@ declare class SchemaRegistry {
1199
1214
  declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1200
1215
  private engine;
1201
1216
  private getServicesRegistry?;
1202
- constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>);
1217
+ private getFeedService?;
1218
+ constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>, getFeedService?: () => IFeedService | undefined);
1219
+ private requireFeedService;
1203
1220
  getDiscovery(): Promise<{
1204
1221
  version: string;
1205
1222
  apiName: string;
@@ -1224,8 +1241,24 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1224
1241
  status: "degraded" | "stub" | "available" | "unavailable";
1225
1242
  route?: string | undefined;
1226
1243
  provider?: string | undefined;
1244
+ version?: string | undefined;
1227
1245
  message?: string | undefined;
1246
+ rateLimit?: {
1247
+ requestsPerMinute?: number | undefined;
1248
+ requestsPerHour?: number | undefined;
1249
+ burstLimit?: number | undefined;
1250
+ retryAfterMs?: number | undefined;
1251
+ } | undefined;
1228
1252
  }>;
1253
+ capabilities: {
1254
+ feed: boolean;
1255
+ comments: boolean;
1256
+ automation: boolean;
1257
+ cron: boolean;
1258
+ search: boolean;
1259
+ export: boolean;
1260
+ chunkedUpload: boolean;
1261
+ };
1229
1262
  }>;
1230
1263
  getMetaTypes(): Promise<{
1231
1264
  types: string[];
@@ -1276,7 +1309,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1276
1309
  label: string | undefined;
1277
1310
  required: boolean;
1278
1311
  readonly: boolean;
1279
- type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "json" | "text" | "textarea" | "email" | "url" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
1312
+ type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
1280
1313
  colSpan: number;
1281
1314
  }[];
1282
1315
  }[];
@@ -1353,6 +1386,20 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1353
1386
  success: boolean;
1354
1387
  message: string;
1355
1388
  }>;
1389
+ listFeed(request: any): Promise<any>;
1390
+ createFeedItem(request: any): Promise<any>;
1391
+ updateFeedItem(request: any): Promise<any>;
1392
+ deleteFeedItem(request: any): Promise<any>;
1393
+ addReaction(request: any): Promise<any>;
1394
+ removeReaction(request: any): Promise<any>;
1395
+ pinFeedItem(request: any): Promise<any>;
1396
+ unpinFeedItem(request: any): Promise<any>;
1397
+ starFeedItem(request: any): Promise<any>;
1398
+ unstarFeedItem(request: any): Promise<any>;
1399
+ searchFeed(request: any): Promise<any>;
1400
+ getChangelog(request: any): Promise<any>;
1401
+ feedSubscribe(request: any): Promise<any>;
1402
+ feedUnsubscribe(request: any): Promise<any>;
1356
1403
  }
1357
1404
 
1358
1405
  type HookHandler = (context: HookContext) => Promise<void> | void;
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ import { ServiceObject, ObjectOwnership, HookContext, QueryAST, DataEngineQueryO
4
4
  import { ObjectStackManifest, InstalledPackage, ExecutionContext } from '@objectstack/spec/kernel';
5
5
  import { ObjectStackProtocol, MetadataCacheRequest, MetadataCacheResponse, BatchUpdateRequest, BatchUpdateResponse, UpdateManyDataRequest, DeleteManyDataRequest } from '@objectstack/spec/api';
6
6
  import { IDataEngine, DriverInterface, Logger, Plugin, PluginContext, ObjectKernel } from '@objectstack/core';
7
+ import { IFeedService } from '@objectstack/spec/contracts';
7
8
 
8
9
  /**
9
10
  * XState-inspired State Machine Protocol
@@ -204,7 +205,7 @@ declare class SchemaRegistry {
204
205
  abstract: boolean;
205
206
  datasource: string;
206
207
  fields: Record<string, {
207
- type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "json" | "text" | "textarea" | "email" | "url" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
208
+ type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
208
209
  required: boolean;
209
210
  searchable: boolean;
210
211
  multiple: boolean;
@@ -840,6 +841,9 @@ declare class SchemaRegistry {
840
841
  } | undefined;
841
842
  } | undefined;
842
843
  } | undefined;
844
+ engine?: {
845
+ objectstack: string;
846
+ } | undefined;
843
847
  };
844
848
  status: "error" | "disabled" | "installed" | "installing" | "upgrading" | "uninstalling";
845
849
  enabled: boolean;
@@ -850,6 +854,14 @@ declare class SchemaRegistry {
850
854
  statusChangedAt?: string | undefined;
851
855
  errorMessage?: string | undefined;
852
856
  settings?: Record<string, unknown> | undefined;
857
+ upgradeHistory?: {
858
+ fromVersion: string;
859
+ toVersion: string;
860
+ upgradedAt: string;
861
+ status: "success" | "failed" | "rolled_back";
862
+ migrationLog?: string[] | undefined;
863
+ }[] | undefined;
864
+ registeredNamespaces?: string[] | undefined;
853
865
  } | {
854
866
  id: string;
855
867
  version: string;
@@ -1154,6 +1166,9 @@ declare class SchemaRegistry {
1154
1166
  } | undefined;
1155
1167
  } | undefined;
1156
1168
  } | undefined;
1169
+ engine?: {
1170
+ objectstack: string;
1171
+ } | undefined;
1157
1172
  };
1158
1173
  /**
1159
1174
  * Universal Unregister Method
@@ -1199,7 +1214,9 @@ declare class SchemaRegistry {
1199
1214
  declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1200
1215
  private engine;
1201
1216
  private getServicesRegistry?;
1202
- constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>);
1217
+ private getFeedService?;
1218
+ constructor(engine: IDataEngine, getServicesRegistry?: () => Map<string, any>, getFeedService?: () => IFeedService | undefined);
1219
+ private requireFeedService;
1203
1220
  getDiscovery(): Promise<{
1204
1221
  version: string;
1205
1222
  apiName: string;
@@ -1224,8 +1241,24 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1224
1241
  status: "degraded" | "stub" | "available" | "unavailable";
1225
1242
  route?: string | undefined;
1226
1243
  provider?: string | undefined;
1244
+ version?: string | undefined;
1227
1245
  message?: string | undefined;
1246
+ rateLimit?: {
1247
+ requestsPerMinute?: number | undefined;
1248
+ requestsPerHour?: number | undefined;
1249
+ burstLimit?: number | undefined;
1250
+ retryAfterMs?: number | undefined;
1251
+ } | undefined;
1228
1252
  }>;
1253
+ capabilities: {
1254
+ feed: boolean;
1255
+ comments: boolean;
1256
+ automation: boolean;
1257
+ cron: boolean;
1258
+ search: boolean;
1259
+ export: boolean;
1260
+ chunkedUpload: boolean;
1261
+ };
1229
1262
  }>;
1230
1263
  getMetaTypes(): Promise<{
1231
1264
  types: string[];
@@ -1276,7 +1309,7 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1276
1309
  label: string | undefined;
1277
1310
  required: boolean;
1278
1311
  readonly: boolean;
1279
- type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "json" | "text" | "textarea" | "email" | "url" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
1312
+ type: "number" | "boolean" | "tags" | "date" | "lookup" | "file" | "url" | "json" | "text" | "textarea" | "email" | "phone" | "password" | "markdown" | "html" | "richtext" | "currency" | "percent" | "datetime" | "time" | "toggle" | "select" | "multiselect" | "radio" | "checkboxes" | "master_detail" | "tree" | "image" | "avatar" | "video" | "audio" | "formula" | "summary" | "autonumber" | "location" | "address" | "code" | "color" | "rating" | "slider" | "signature" | "qrcode" | "progress" | "vector";
1280
1313
  colSpan: number;
1281
1314
  }[];
1282
1315
  }[];
@@ -1353,6 +1386,20 @@ declare class ObjectStackProtocolImplementation implements ObjectStackProtocol {
1353
1386
  success: boolean;
1354
1387
  message: string;
1355
1388
  }>;
1389
+ listFeed(request: any): Promise<any>;
1390
+ createFeedItem(request: any): Promise<any>;
1391
+ updateFeedItem(request: any): Promise<any>;
1392
+ deleteFeedItem(request: any): Promise<any>;
1393
+ addReaction(request: any): Promise<any>;
1394
+ removeReaction(request: any): Promise<any>;
1395
+ pinFeedItem(request: any): Promise<any>;
1396
+ unpinFeedItem(request: any): Promise<any>;
1397
+ starFeedItem(request: any): Promise<any>;
1398
+ unstarFeedItem(request: any): Promise<any>;
1399
+ searchFeed(request: any): Promise<any>;
1400
+ getChangelog(request: any): Promise<any>;
1401
+ feedSubscribe(request: any): Promise<any>;
1402
+ feedUnsubscribe(request: any): Promise<any>;
1356
1403
  }
1357
1404
 
1358
1405
  type HookHandler = (context: HookContext) => Promise<void> | void;
package/dist/index.js CHANGED
@@ -531,6 +531,7 @@ SchemaRegistry.namespaceRegistry = /* @__PURE__ */ new Map();
531
531
  SchemaRegistry.metadata = /* @__PURE__ */ new Map();
532
532
 
533
533
  // src/protocol.ts
534
+ var import_data2 = require("@objectstack/spec/data");
534
535
  function simpleHash(str) {
535
536
  let hash = 0;
536
537
  for (let i = 0; i < str.length; i++) {
@@ -558,9 +559,17 @@ var SERVICE_CONFIG = {
558
559
  search: { route: "/api/v1/search", plugin: "plugin-search" }
559
560
  };
560
561
  var ObjectStackProtocolImplementation = class {
561
- constructor(engine, getServicesRegistry) {
562
+ constructor(engine, getServicesRegistry, getFeedService) {
562
563
  this.engine = engine;
563
564
  this.getServicesRegistry = getServicesRegistry;
565
+ this.getFeedService = getFeedService;
566
+ }
567
+ requireFeedService() {
568
+ const svc = this.getFeedService?.();
569
+ if (!svc) {
570
+ throw new Error("Feed service not available. Install and register service-feed to enable feed operations.");
571
+ }
572
+ return svc;
564
573
  }
565
574
  async getDiscovery() {
566
575
  const registeredServices = this.getServicesRegistry ? this.getServicesRegistry() : /* @__PURE__ */ new Map();
@@ -609,16 +618,40 @@ var ObjectStackProtocolImplementation = class {
609
618
  }
610
619
  }
611
620
  }
621
+ if (registeredServices.has("feed")) {
622
+ services["feed"] = {
623
+ enabled: true,
624
+ status: "available",
625
+ route: "/api/v1/data",
626
+ provider: "service-feed"
627
+ };
628
+ } else {
629
+ services["feed"] = {
630
+ enabled: false,
631
+ status: "unavailable",
632
+ message: "Install service-feed to enable"
633
+ };
634
+ }
612
635
  const routes = {
613
636
  data: "/api/v1/data",
614
637
  metadata: "/api/v1/meta",
615
638
  ...optionalRoutes
616
639
  };
640
+ const capabilities = {
641
+ feed: registeredServices.has("feed"),
642
+ comments: registeredServices.has("feed"),
643
+ automation: registeredServices.has("automation"),
644
+ cron: registeredServices.has("job"),
645
+ search: registeredServices.has("search"),
646
+ export: registeredServices.has("automation") || registeredServices.has("queue"),
647
+ chunkedUpload: registeredServices.has("file-storage")
648
+ };
617
649
  return {
618
650
  version: "1.0",
619
651
  apiName: "ObjectStack API",
620
652
  routes,
621
- services
653
+ services,
654
+ capabilities
622
655
  };
623
656
  }
624
657
  async getMetaTypes() {
@@ -725,18 +758,18 @@ var ObjectStackProtocolImplementation = class {
725
758
  options.sort = parsed;
726
759
  delete options.orderBy;
727
760
  }
761
+ if (options.filters !== void 0 && options.filter === void 0) {
762
+ options.filter = options.filters;
763
+ }
764
+ delete options.filters;
728
765
  if (typeof options.filter === "string") {
729
766
  try {
730
767
  options.filter = JSON.parse(options.filter);
731
768
  } catch {
732
769
  }
733
770
  }
734
- if (typeof options.filters === "string") {
735
- try {
736
- options.filter = JSON.parse(options.filters);
737
- delete options.filters;
738
- } catch {
739
- }
771
+ if ((0, import_data2.isFilterAST)(options.filter)) {
772
+ options.filter = (0, import_data2.parseFilterAST)(options.filter);
740
773
  }
741
774
  if (typeof options.populate === "string") {
742
775
  options.populate = options.populate.split(",").map((s) => s.trim()).filter(Boolean);
@@ -1100,6 +1133,137 @@ var ObjectStackProtocolImplementation = class {
1100
1133
  message: "Saved to memory registry"
1101
1134
  };
1102
1135
  }
1136
+ // ==========================================
1137
+ // Feed Operations
1138
+ // ==========================================
1139
+ async listFeed(request) {
1140
+ const svc = this.requireFeedService();
1141
+ const result = await svc.listFeed({
1142
+ object: request.object,
1143
+ recordId: request.recordId,
1144
+ filter: request.type,
1145
+ limit: request.limit,
1146
+ cursor: request.cursor
1147
+ });
1148
+ return { success: true, data: result };
1149
+ }
1150
+ async createFeedItem(request) {
1151
+ const svc = this.requireFeedService();
1152
+ const item = await svc.createFeedItem({
1153
+ object: request.object,
1154
+ recordId: request.recordId,
1155
+ type: request.type,
1156
+ actor: { type: "user", id: "current_user" },
1157
+ body: request.body,
1158
+ mentions: request.mentions,
1159
+ parentId: request.parentId,
1160
+ visibility: request.visibility
1161
+ });
1162
+ return { success: true, data: item };
1163
+ }
1164
+ async updateFeedItem(request) {
1165
+ const svc = this.requireFeedService();
1166
+ const item = await svc.updateFeedItem(request.feedId, {
1167
+ body: request.body,
1168
+ mentions: request.mentions,
1169
+ visibility: request.visibility
1170
+ });
1171
+ return { success: true, data: item };
1172
+ }
1173
+ async deleteFeedItem(request) {
1174
+ const svc = this.requireFeedService();
1175
+ await svc.deleteFeedItem(request.feedId);
1176
+ return { success: true, data: { feedId: request.feedId } };
1177
+ }
1178
+ async addReaction(request) {
1179
+ const svc = this.requireFeedService();
1180
+ const reactions = await svc.addReaction(request.feedId, request.emoji, "current_user");
1181
+ return { success: true, data: { reactions } };
1182
+ }
1183
+ async removeReaction(request) {
1184
+ const svc = this.requireFeedService();
1185
+ const reactions = await svc.removeReaction(request.feedId, request.emoji, "current_user");
1186
+ return { success: true, data: { reactions } };
1187
+ }
1188
+ async pinFeedItem(request) {
1189
+ const svc = this.requireFeedService();
1190
+ const item = await svc.getFeedItem(request.feedId);
1191
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1192
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1193
+ return { success: true, data: { feedId: request.feedId, pinned: true, pinnedAt: (/* @__PURE__ */ new Date()).toISOString() } };
1194
+ }
1195
+ async unpinFeedItem(request) {
1196
+ const svc = this.requireFeedService();
1197
+ const item = await svc.getFeedItem(request.feedId);
1198
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1199
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1200
+ return { success: true, data: { feedId: request.feedId, pinned: false } };
1201
+ }
1202
+ async starFeedItem(request) {
1203
+ const svc = this.requireFeedService();
1204
+ const item = await svc.getFeedItem(request.feedId);
1205
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1206
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1207
+ return { success: true, data: { feedId: request.feedId, starred: true, starredAt: (/* @__PURE__ */ new Date()).toISOString() } };
1208
+ }
1209
+ async unstarFeedItem(request) {
1210
+ const svc = this.requireFeedService();
1211
+ const item = await svc.getFeedItem(request.feedId);
1212
+ if (!item) throw new Error(`Feed item ${request.feedId} not found`);
1213
+ await svc.updateFeedItem(request.feedId, { visibility: item.visibility });
1214
+ return { success: true, data: { feedId: request.feedId, starred: false } };
1215
+ }
1216
+ async searchFeed(request) {
1217
+ const svc = this.requireFeedService();
1218
+ const result = await svc.listFeed({
1219
+ object: request.object,
1220
+ recordId: request.recordId,
1221
+ filter: request.type,
1222
+ limit: request.limit,
1223
+ cursor: request.cursor
1224
+ });
1225
+ const queryLower = (request.query || "").toLowerCase();
1226
+ const filtered = result.items.filter(
1227
+ (item) => item.body?.toLowerCase().includes(queryLower)
1228
+ );
1229
+ return { success: true, data: { items: filtered, total: filtered.length, hasMore: false } };
1230
+ }
1231
+ async getChangelog(request) {
1232
+ const svc = this.requireFeedService();
1233
+ const result = await svc.listFeed({
1234
+ object: request.object,
1235
+ recordId: request.recordId,
1236
+ filter: "changes_only",
1237
+ limit: request.limit,
1238
+ cursor: request.cursor
1239
+ });
1240
+ const entries = result.items.map((item) => ({
1241
+ id: item.id,
1242
+ object: item.object,
1243
+ recordId: item.recordId,
1244
+ actor: item.actor,
1245
+ changes: item.changes || [],
1246
+ timestamp: item.createdAt,
1247
+ source: item.source
1248
+ }));
1249
+ return { success: true, data: { entries, total: result.total, nextCursor: result.nextCursor, hasMore: result.hasMore } };
1250
+ }
1251
+ async feedSubscribe(request) {
1252
+ const svc = this.requireFeedService();
1253
+ const subscription = await svc.subscribe({
1254
+ object: request.object,
1255
+ recordId: request.recordId,
1256
+ userId: "current_user",
1257
+ events: request.events,
1258
+ channels: request.channels
1259
+ });
1260
+ return { success: true, data: subscription };
1261
+ }
1262
+ async feedUnsubscribe(request) {
1263
+ const svc = this.requireFeedService();
1264
+ const unsubscribed = await svc.unsubscribe(request.object, request.recordId, "current_user");
1265
+ return { success: true, data: { object: request.object, recordId: request.recordId, unsubscribed } };
1266
+ }
1103
1267
  };
1104
1268
 
1105
1269
  // src/engine.ts