@segmentstream-cloud/ontology 0.25.1 → 0.26.1

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.
@@ -82,6 +82,25 @@ export declare function blobRuntime(ontology: Ontology, sql: SqlClient.SqlClient
82
82
  state: string;
83
83
  expiresAt: string;
84
84
  }, import("../errors.js").PermissionDenied | Conflict | NotFound | import("effect/unstable/sql/SqlError").SqlError, never>;
85
- download: (entityName: string, recordId: string, propertyName: string, input: typeof DownloadRequest.Type, principal: Principal) => Effect.Effect<import("./provider.js").TransferGrant, import("../errors.js").PermissionDenied | NotFound | import("effect/unstable/sql/SqlError").SqlError | import("./provider.js").BlobStorageError, never>;
85
+ download: (entityName: string, recordId: string, propertyName: string, input: {
86
+ readonly inline?: boolean | undefined;
87
+ readonly revisionId?: string | undefined;
88
+ }, principal: Principal) => Effect.Effect<import("./provider.js").TransferGrant, import("../errors.js").PermissionDenied | NotFound | import("effect/unstable/sql/SqlError").SqlError | import("./provider.js").BlobStorageError, never>;
89
+ downloadFile: (entityName: string, recordId: string, propertyName: string, input: {
90
+ readonly inline?: boolean | undefined;
91
+ readonly revisionId?: string | undefined;
92
+ }, principal: Principal) => Effect.Effect<{
93
+ file: {
94
+ id: string;
95
+ entity: string;
96
+ property: string;
97
+ revision_id: string;
98
+ filename: string;
99
+ content_type: string;
100
+ size: number;
101
+ sha256: string;
102
+ };
103
+ download: import("./provider.js").TransferGrant;
104
+ }, import("../errors.js").PermissionDenied | NotFound | import("effect/unstable/sql/SqlError").SqlError | import("./provider.js").BlobStorageError, never>;
86
105
  };
87
106
  export type BlobRuntime = ReturnType<typeof blobRuntime>;
@@ -299,7 +299,7 @@ export function blobRuntime(ontology, sql, provider) {
299
299
  WHERE id = $1::uuid`, [id]);
300
300
  return view(yield* load(id, principal));
301
301
  }));
302
- const download = (entityName, recordId, propertyName, input, principal) => Effect.gen(function* () {
302
+ const prepareDownload = (entityName, recordId, propertyName, input, principal) => Effect.gen(function* () {
303
303
  const entity = ontology.manifest.entities.find((item) => item.name === entityName);
304
304
  const property = entity?.properties.find((item) => item.name === propertyName && item.type === "blob");
305
305
  if (!entity || !property) {
@@ -319,9 +319,10 @@ export function blobRuntime(ontology, sql, provider) {
319
319
  });
320
320
  revisionId = record[propertyName]?.id;
321
321
  }
322
- const [blob] = yield* sql.unsafe(`SELECT b.key, b.filename, b.content_type FROM "_blobs" b JOIN "_blob_references" r ON r.blob_id = b.id
323
- WHERE b.id = $1::uuid AND b.state = 'retained' AND r.entity_id = $2
324
- AND r.property_id = $3 AND r.record_id = $4::uuid FOR SHARE OF b`, [revisionId ?? null, entity.id, property.name, recordId]);
322
+ const [blob] = yield* sql.unsafe(`SELECT b.id::text, b.key, b.filename, b.content_type, b.size::text
323
+ FROM "_blobs" b JOIN "_blob_references" r ON r.blob_id = b.id
324
+ WHERE b.id = $1::uuid AND b.state = 'retained' AND b.branch_id = $5 AND r.entity_id = $2
325
+ AND r.property_id = $3 AND r.record_id = $4::uuid FOR SHARE OF b`, [revisionId ?? null, entity.id, property.name, recordId, binding.branchId]);
325
326
  if (!blob) {
326
327
  return yield* new NotFound({
327
328
  entity: entityName,
@@ -331,13 +332,42 @@ export function blobRuntime(ontology, sql, provider) {
331
332
  }
332
333
  return blob;
333
334
  }));
335
+ return blob;
336
+ });
337
+ const download = (...args) => Effect.gen(function* () {
338
+ const blob = yield* prepareDownload(...args);
334
339
  return yield* provider.download({
335
340
  key: blob.key,
336
341
  filename: blob.filename,
337
342
  contentType: blob.content_type,
338
- inline: input.inline === true &&
343
+ inline: args[3].inline === true &&
339
344
  ["image/jpeg", "image/png"].includes(blob.content_type.toLowerCase()),
340
345
  });
341
346
  });
342
- return { begin, status, part, complete, cancel, download };
347
+ const downloadFile = (...args) => Effect.gen(function* () {
348
+ const blob = yield* prepareDownload(...args);
349
+ const sha256 = yield* provider.sha256(blob.key, Number(blob.size));
350
+ // Recheck live access after hashing; no provider I/O holds a database transaction.
351
+ yield* prepareDownload(args[0], args[1], args[2], { revisionId: blob.id }, args[4]);
352
+ const grant = yield* provider.download({
353
+ key: blob.key,
354
+ filename: blob.filename,
355
+ contentType: blob.content_type,
356
+ inline: false,
357
+ });
358
+ return {
359
+ file: {
360
+ id: args[1],
361
+ entity: args[0],
362
+ property: args[2],
363
+ revision_id: blob.id,
364
+ filename: blob.filename,
365
+ content_type: blob.content_type,
366
+ size: Number(blob.size),
367
+ sha256,
368
+ },
369
+ download: grant,
370
+ };
371
+ });
372
+ return { begin, status, part, complete, cancel, download, downloadFile };
343
373
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@segmentstream-cloud/ontology",
3
- "version": "0.25.1",
3
+ "version": "0.26.1",
4
4
  "description": "Define a SegmentStream workspace app's ontology: entities, relationships, roles and actions, written with Effect.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "SegmentStream",
@@ -45,7 +45,9 @@
45
45
  "lint": "eslint src tests --config ../../eslint.config.mjs",
46
46
  "test": "vitest run",
47
47
  "test:postgres": "vitest run --config vitest.postgres.config.ts",
48
- "prepack": "npm run build"
48
+ "prepack": "npm run build",
49
+ "benchmark:batch": "tsx tests/batch/benchmark.ts",
50
+ "benchmark:batch:profile": "tsx tests/batch/profile.ts"
49
51
  },
50
52
  "dependencies": {
51
53
  "@aws-sdk/client-s3": "^3.1148.0",