@voltro/plugin-storage 0.70.0 → 0.71.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.
- package/CHANGELOG.md +1341 -111
- package/dist/index.d.ts +76 -2
- package/dist/index.js +870 -678
- package/dist/types.d.ts +16 -2
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -3,12 +3,14 @@ import { ColumnType } from '@voltro/database';
|
|
|
3
3
|
import { Context } from 'effect';
|
|
4
4
|
import { DataStore } from '@voltro/database';
|
|
5
5
|
import { Effect } from 'effect';
|
|
6
|
+
import { FieldDefinitions } from '@voltro/database';
|
|
6
7
|
import { Layer } from 'effect';
|
|
7
8
|
import { mixin } from '@voltro/database';
|
|
8
9
|
import { Readable } from 'node:stream';
|
|
9
10
|
import { Schema } from 'effect';
|
|
10
11
|
import { Stream } from 'effect';
|
|
11
12
|
import { Subject } from '@voltro/protocol';
|
|
13
|
+
import { Table } from '@voltro/database';
|
|
12
14
|
import { TableLike } from '@voltro/database';
|
|
13
15
|
import { VoltroPlugin } from '@voltro/protocol';
|
|
14
16
|
|
|
@@ -420,7 +422,20 @@ export declare const putObjectStream: (provider: StorageProvider, key: string, s
|
|
|
420
422
|
export declare const refMatchesListQuery: (ref: StorageRef, q: ResolvedListQuery) => boolean;
|
|
421
423
|
|
|
422
424
|
/** Where blob METADATA rows live (the bytes are in the provider). */
|
|
425
|
+
export declare interface RefStatistics {
|
|
426
|
+
readonly byTenant: Record<string, {
|
|
427
|
+
count: number;
|
|
428
|
+
bytes: number;
|
|
429
|
+
}>;
|
|
430
|
+
readonly visibility: {
|
|
431
|
+
public: number;
|
|
432
|
+
private: number;
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
423
436
|
export declare interface RefStore {
|
|
437
|
+
/** Aggregate the complete reference index without a recent-object limit. */
|
|
438
|
+
readonly statistics: () => Effect.Effect<RefStatistics, StorageError>;
|
|
424
439
|
readonly insert: (ref: StorageRef) => Effect.Effect<void, StorageError>;
|
|
425
440
|
readonly getById: (id: string) => Effect.Effect<StorageRef | null, StorageError>;
|
|
426
441
|
/** Remove one ref row. Returns whether a row was ACTUALLY removed — the
|
|
@@ -479,6 +494,7 @@ export declare interface Rendition {
|
|
|
479
494
|
/** A `ListRefsInput` after the service normalizes its defaults / clamps — what
|
|
480
495
|
* a `RefStore.listRefs` impl receives. `limit` is already the `+1` probe. */
|
|
481
496
|
export declare interface ResolvedListQuery {
|
|
497
|
+
readonly search?: string;
|
|
482
498
|
readonly tenantId: string | null | undefined;
|
|
483
499
|
readonly folder: string | undefined;
|
|
484
500
|
readonly tags: ReadonlyArray<string>;
|
|
@@ -606,6 +622,39 @@ export declare type StorageGuard = (ctx: {
|
|
|
606
622
|
readonly ref: StorageRef;
|
|
607
623
|
}) => boolean | Promise<boolean> | Effect.Effect<boolean>;
|
|
608
624
|
|
|
625
|
+
/**
|
|
626
|
+
* The instance name an upload ticket must carry, for THIS installation.
|
|
627
|
+
*
|
|
628
|
+
* `signUploadTicket` takes `instance: string`, and the upload route compares it
|
|
629
|
+
* against the plugin's own instance — so a wrong value is not a type error, it
|
|
630
|
+
* is a bare `401` on every upload. The value has always been derivable
|
|
631
|
+
* (`storagePlugin(options).name` is this same expression), but nothing said so
|
|
632
|
+
* and `BASE_NAME` is not exported, so a caller minting a ticket outside the
|
|
633
|
+
* plugin had to guess it. Guessing is exactly what a `string` parameter invites.
|
|
634
|
+
*
|
|
635
|
+
* const ticket = signUploadTicket(
|
|
636
|
+
* { instance: storageInstanceName(), key, contentType },
|
|
637
|
+
* 300,
|
|
638
|
+
* )
|
|
639
|
+
*
|
|
640
|
+
* Pass the SAME options the installation was built with — `alias` and `name`
|
|
641
|
+
* both move the instance, and a ticket minted for the default name does not
|
|
642
|
+
* open a door installed under an alias.
|
|
643
|
+
*/
|
|
644
|
+
export declare const storageInstanceName: (options?: StoragePluginOptions) => string;
|
|
645
|
+
|
|
646
|
+
declare interface StorageObjectIdentity {
|
|
647
|
+
readonly tenantId: string | null;
|
|
648
|
+
readonly bucket: string;
|
|
649
|
+
readonly operationId: string;
|
|
650
|
+
/** Hash of all immutable put inputs, including content and access metadata. */
|
|
651
|
+
readonly fingerprint: string;
|
|
652
|
+
/** SHA-256 of the actual normalized provider bytes, separate from metadata. */
|
|
653
|
+
readonly checksum: string;
|
|
654
|
+
/** Already tenant-scoped logical provider key. */
|
|
655
|
+
readonly logicalKey: string;
|
|
656
|
+
}
|
|
657
|
+
|
|
609
658
|
export declare const storagePlugin: (options?: StoragePluginOptions) => VoltroPlugin;
|
|
610
659
|
|
|
611
660
|
export declare interface StoragePluginOptions {
|
|
@@ -815,6 +864,13 @@ export declare interface StorageProvider {
|
|
|
815
864
|
|
|
816
865
|
export declare type StorageProviderName = 's3' | 'minio' | 'azure' | 'filesystem' | 'memory' | 'database';
|
|
817
866
|
|
|
867
|
+
export declare const storagePutIntentsTable: Table<"_voltro_storage_put_intents", FieldDefinitions<{
|
|
868
|
+
readonly id: ColumnBuilder<string, "text", boolean>;
|
|
869
|
+
readonly refId: ColumnBuilder<string, "text", boolean>;
|
|
870
|
+
readonly identity: ColumnBuilder<StorageObjectIdentity, "json", boolean>;
|
|
871
|
+
readonly ref: ColumnBuilder<StorageRef, "json", boolean>;
|
|
872
|
+
}>, false, never>;
|
|
873
|
+
|
|
818
874
|
/** Per-tenant upload budget (see `StorageServiceOptions.quota`). */
|
|
819
875
|
export declare interface StorageQuota {
|
|
820
876
|
readonly maxBytes?: number;
|
|
@@ -938,6 +994,8 @@ export declare interface StorageServiceOptions {
|
|
|
938
994
|
* the app: a browser `<img>` and server-to-server AI-gateway fetches both
|
|
939
995
|
* need an absolute, reachable URL. Omit for same-origin (relative URL). */
|
|
940
996
|
readonly publicBaseUrl?: string;
|
|
997
|
+
/** Instance-specific HTTP mount supplied by the storage plugin. */
|
|
998
|
+
readonly httpPath?: string;
|
|
941
999
|
/** Normalize raster images on upload: apply EXIF orientation, then strip ALL
|
|
942
1000
|
* metadata (GPS/camera) and re-encode. Off by default (it re-encodes, which
|
|
943
1001
|
* changes the bytes + content-address). Width/height/placeholder are always
|
|
@@ -965,6 +1023,15 @@ export declare interface StorageServiceShape {
|
|
|
965
1023
|
readonly bytes: Uint8Array;
|
|
966
1024
|
readonly ref: StorageRef;
|
|
967
1025
|
}, StorageError>;
|
|
1026
|
+
/** Trusted server-side streamed read with the same tenant guard as get.
|
|
1027
|
+
* Provider acquisition is lazy; callers must authorize private-object access.
|
|
1028
|
+
* Providers without getStream fall back to a buffered provider read. */
|
|
1029
|
+
readonly getStream: (id: string, opts?: {
|
|
1030
|
+
readonly tenantId?: string | null;
|
|
1031
|
+
}) => Effect.Effect<{
|
|
1032
|
+
readonly stream: ByteStream;
|
|
1033
|
+
readonly ref: StorageRef;
|
|
1034
|
+
}, StorageError>;
|
|
968
1035
|
/** Direct/presigned URL for an object. For PUBLIC objects this is the
|
|
969
1036
|
* CDN/bucket URL (no app round-trip).
|
|
970
1037
|
*
|
|
@@ -1054,8 +1121,12 @@ export declare interface StorageServiceShape {
|
|
|
1054
1121
|
* migration / "adopt this remote image"). The content-type comes from the
|
|
1055
1122
|
* response unless overridden. NOTE: this fetches an arbitrary URL from the
|
|
1056
1123
|
* server — pass only trusted URLs (SSRF); front it with an allow-list if the
|
|
1057
|
-
* URL is user-supplied.
|
|
1124
|
+
* URL is user-supplied. Reads are bounded by `limits.maxBytes` (64 MiB when
|
|
1125
|
+
* absent) before the scanning/checksum/put pipeline. This is bounded
|
|
1126
|
+
* buffering, not a zero-copy provider stream. Effect interruption cancels
|
|
1127
|
+
* the HTTP read; an optional caller signal interrupts the entire ingest. */
|
|
1058
1128
|
readonly ingestUrl: (url: string, opts?: {
|
|
1129
|
+
readonly abortSignal?: AbortSignal;
|
|
1059
1130
|
readonly contentType?: string;
|
|
1060
1131
|
readonly tenantId?: string | null;
|
|
1061
1132
|
readonly ownerId?: string | null;
|
|
@@ -1247,7 +1318,8 @@ export declare interface TransformParams {
|
|
|
1247
1318
|
}
|
|
1248
1319
|
|
|
1249
1320
|
export declare interface UploadLimits {
|
|
1250
|
-
/** Reject uploads larger than this many bytes.
|
|
1321
|
+
/** Reject uploads larger than this many bytes. URL ingestion enforces this
|
|
1322
|
+
* while reading the response; absent a limit, ingestion caps at 64 MiB. */
|
|
1251
1323
|
readonly maxBytes?: number;
|
|
1252
1324
|
/** Allowed content types — exact (`application/pdf`) or wildcard
|
|
1253
1325
|
* (`image/*`). Omit to allow any. */
|
|
@@ -1260,6 +1332,8 @@ export declare interface UploadLimits {
|
|
|
1260
1332
|
/** What an upload ticket authorizes: a single through-app upload bound to an
|
|
1261
1333
|
* owner/tenant/content-type/visibility, until `exp`. */
|
|
1262
1334
|
export declare interface UploadTicketPayload {
|
|
1335
|
+
/** Exact storage plugin instance authorized to accept the bytes. */
|
|
1336
|
+
readonly instance: string;
|
|
1263
1337
|
/** ownerId (subject id) the stored object is attributed to. */
|
|
1264
1338
|
readonly sub: string | null;
|
|
1265
1339
|
/** tenantId that scopes the key prefix + ref row. */
|