@lacrous/omnicloud 0.2.27 → 0.2.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lacrous/omnicloud",
3
- "version": "0.2.27",
3
+ "version": "0.2.28",
4
4
  "description": "SDK and core building blocks for OmniCloud — self-hosted cloud storage powered by your Telegram account.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,9 +48,9 @@
48
48
  "prisma": "^6.2.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@omnicloud/core": "0.2.27",
52
- "@omnicloud/shared": "0.2.27",
53
- "@omnicloud/telegram": "0.2.27",
51
+ "@omnicloud/core": "0.2.28",
52
+ "@omnicloud/shared": "0.2.28",
53
+ "@omnicloud/telegram": "0.2.28",
54
54
  "@types/node": "^22.10.0",
55
55
  "esbuild": "0.25.12",
56
56
  "tsup": "^8.3.0",
package/server/index.js CHANGED
@@ -617,10 +617,10 @@ var StorageEngine = class {
617
617
  }
618
618
  }
619
619
  /** Read-only search for stored objects with this content hash and size. */
620
- async findByCaption(sha256, size) {
620
+ async findByCaption(caption, size) {
621
621
  if (!this.provider.findByCaption) return null;
622
622
  try {
623
- return await this.provider.findByCaption(sha256, size);
623
+ return await this.provider.findByCaption(caption, size);
624
624
  } catch (error) {
625
625
  throw mapProviderError("Storage lookup failed", error);
626
626
  }
@@ -1105,6 +1105,9 @@ function uploadRequestFingerprint(input) {
1105
1105
  function contentSha256(input) {
1106
1106
  return input.spooled?.sha256 ?? sha256Hex(input.data ?? Buffer.alloc(0));
1107
1107
  }
1108
+ function uploadCaption(sha256, operationId) {
1109
+ return `${sha256}:${operationId}`;
1110
+ }
1108
1111
  function contentSize(input) {
1109
1112
  return input.spooled?.size ?? input.data?.byteLength ?? 0;
1110
1113
  }
@@ -1180,6 +1183,7 @@ var FileService = class {
1180
1183
  }
1181
1184
  try {
1182
1185
  const record = await this.performUpload(userId, input, {
1186
+ caption: uploadCaption(contentSha256(input), op.operationId),
1183
1187
  onStored: async (stored) => {
1184
1188
  await operations.update(op.id, { telegramMessageId: Number(stored.messageId) });
1185
1189
  await operations.claim(op.id, "UPLOADING", "COMMITTING");
@@ -1211,7 +1215,7 @@ var FileService = class {
1211
1215
  );
1212
1216
  }
1213
1217
  const engine = await this.engineFor(userId);
1214
- const matches = await engine.findByCaption(op.sha256, op.size);
1218
+ const matches = await engine.findByCaption(uploadCaption(op.sha256, op.operationId), op.size);
1215
1219
  if (matches === null) {
1216
1220
  throw new ConflictError(
1217
1221
  "This upload's outcome is unknown and the storage backend cannot search for it."
@@ -1316,8 +1320,9 @@ var FileService = class {
1316
1320
  mimeType,
1317
1321
  path: input.spooled.path,
1318
1322
  size: input.spooled.size,
1319
- sha256: input.spooled.sha256
1320
- } : { name, mimeType, data: input.data },
1323
+ sha256: input.spooled.sha256,
1324
+ caption: hooks.caption
1325
+ } : { name, mimeType, data: input.data, caption: hooks.caption },
1321
1326
  control
1322
1327
  );
1323
1328
  await hooks.onStored?.(stored);
@@ -2846,7 +2851,7 @@ var TelegramStorageProvider = class {
2846
2851
  file,
2847
2852
  forceDocument: true,
2848
2853
  workers: 1,
2849
- caption: input.sha256,
2854
+ caption: input.caption,
2850
2855
  // Surface transport-level progress to the caller. GramJS reports a
2851
2856
  // 0..1 fraction. `isCanceled` lets us abort an in-flight upload.
2852
2857
  progressCallback: Object.assign(
@@ -3005,18 +3010,18 @@ var TelegramStorageProvider = class {
3005
3010
  return objects;
3006
3011
  }
3007
3012
  /**
3008
- * Finds stored documents whose caption equals the content hash and whose size
3013
+ * Finds stored documents whose caption equals the given caption and whose size
3009
3014
  * matches. Used to recover an upload whose outcome was unknown.
3010
3015
  */
3011
- async findByCaption(sha256, size) {
3016
+ async findByCaption(caption, size) {
3012
3017
  const matches = [];
3013
3018
  try {
3014
3019
  for await (const message of this.client.iterMessages(this.peer, {
3015
- search: sha256,
3020
+ search: caption,
3016
3021
  limit: 20
3017
3022
  })) {
3018
3023
  if (!(message instanceof Api2.Message)) continue;
3019
- if (message.message !== sha256) continue;
3024
+ if (message.message !== caption) continue;
3020
3025
  const document = message.document;
3021
3026
  if (!(document instanceof Api2.Document)) continue;
3022
3027
  if (Number(document.size.toString()) !== size) continue;
@@ -5192,7 +5197,7 @@ function encryptionCheck(configured) {
5192
5197
  }
5193
5198
 
5194
5199
  // ../../apps/api/src/routes/storage.ts
5195
- var VERSION = "0.2.27";
5200
+ var VERSION = "0.2.28";
5196
5201
  function registerStorageRoutes(app2, container2) {
5197
5202
  app2.get("/api/health", async () => {
5198
5203
  const database = await probeDatabase(container2);