zerobucket 0.8.0 → 0.8.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/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as StorageBackend, O as OperationEvent, a as ObjectStorageLike, P as PreparedRow, C as CallOptions, b as StoredRecord, c as StoredRecordMetadata, d as StreamOptions, e as StorageInfo, I as ImageListOptions, f as ImageListEntry, M as MysqlPoolLike, g as ContentValidator, V as ValidatedContent } from './client-XQ22b1l3.cjs';
2
- export { B as BatchDeleteResult, h as BatchGetResult, i as BatchPutResult, j as BeforeGetHook, k as BeforePutHook, l as Connection, D as DEFAULT_MAX_BYTES, G as GetOptions, m as Image, n as ImageInput, o as ImageMetadata, p as MysqlPoolConnectionLike, q as MysqlQueryable, r as ObjectStorage, s as ObjectStorageOptions, t as OptimizationResult, u as OptimizeOptions, v as PutManyOptions, w as PutOptions, Q as Queryable, x as SqliteDatabaseLike, y as StreamOptions, W as WritableLike, Z as ZeroBucket, z as ZeroBucketOptions, A as optimizeImage, E as readInput } from './client-XQ22b1l3.cjs';
1
+ import { S as StorageBackend, O as OperationEvent, a as ObjectStorageLike, P as PreparedRow, C as CallOptions, b as StoredRecord, c as StoredRecordMetadata, d as StreamOptions, e as StorageInfo, I as ImageListOptions, f as ImageListEntry, M as MigrateToDedupOptions, g as MigrateToDedupResult, h as MysqlPoolLike, i as ContentValidator, V as ValidatedContent } from './client-l4jPIFJI.cjs';
2
+ export { B as BatchDeleteResult, j as BatchGetResult, k as BatchPutResult, l as BeforeGetHook, m as BeforePutHook, n as Connection, D as DEFAULT_MAX_BYTES, G as GetOptions, o as Image, p as ImageInput, q as ImageMetadata, r as MysqlPoolConnectionLike, s as MysqlQueryable, t as ObjectStorage, u as ObjectStorageOptions, v as OptimizationResult, w as OptimizeOptions, x as PutManyOptions, y as PutOptions, Q as Queryable, z as SqliteDatabaseLike, A as StreamOptions, W as WritableLike, Z as ZeroBucket, E as ZeroBucketOptions, F as optimizeImage, H as readInput } from './client-l4jPIFJI.cjs';
3
3
  import { Pool } from 'pg';
4
4
 
5
5
  /**
@@ -158,18 +158,13 @@ declare class PostgresBackend implements StorageBackend {
158
158
  * dedup instance's tables, preserving every id (external references keep working) and
159
159
  * deduplicating identical content on the way. The classic table is never modified.
160
160
  *
161
- * Differences from the Python version, all deliberate: rows are copied in small batches (bounded
162
- * memory instead of loading the whole table); re-running is safe (already-migrated ids are
163
- * skipped and reported, not an error); and classic rows already tiered to object storage are
164
- * refused up front with a clear message (their bytes are not in the database to copy).
161
+ * Rows are copied in small batches (bounded memory instead of loading the whole table);
162
+ * re-running is safe (already-migrated ids are skipped and reported, not an error). Classic rows
163
+ * already tiered to object storage are refused up front with a clear message (their bytes are
164
+ * not in the database to copy) unless `skipTiered: true`, which skips and counts them instead.
165
165
  * Still all-or-nothing: one transaction.
166
166
  */
167
- migrateClassicToDedup(): Promise<{
168
- imagesMigrated: number;
169
- distinctBlobsCreated: number;
170
- duplicateReferencesFound: number;
171
- alreadyMigrated: number;
172
- }>;
167
+ migrateClassicToDedup(opts?: MigrateToDedupOptions): Promise<MigrateToDedupResult>;
173
168
  private hydrate;
174
169
  /**
175
170
  * Remove tiered objects AFTER their rows are gone. Ordering is deliberate:
@@ -434,4 +429,4 @@ declare class PDFValidator implements ContentValidator {
434
429
  }): ValidatedContent;
435
430
  }
436
431
 
437
- export { AccessDeniedError, CallOptions, ContentValidationError, ContentValidator, CorruptedImageError, DEFAULT_MAX_PIXELS, DEFAULT_STREAM_CHUNK_SIZE, ImageNotFoundError, ImageTooLargeError, ImageValidationError, MySQLBackend, type MySQLBackendOptions, MysqlPoolLike, ObjectStorageLike, OperationEvent, PDFValidator, PostgresBackend, type PostgresBackendOptions, PreparedRow, SQLiteBackend, type SQLiteBackendOptions, SUPPORTED_FORMATS, StorageBackend, StorageError, StoredRecord, StoredRecordMetadata, UnsupportedFormatError, ValidatedContent, type ValidatedImage, ZeroBucketError, validateImage };
432
+ export { AccessDeniedError, CallOptions, ContentValidationError, ContentValidator, CorruptedImageError, DEFAULT_MAX_PIXELS, DEFAULT_STREAM_CHUNK_SIZE, ImageNotFoundError, ImageTooLargeError, ImageValidationError, MigrateToDedupOptions, MigrateToDedupResult, MySQLBackend, type MySQLBackendOptions, MysqlPoolLike, ObjectStorageLike, OperationEvent, PDFValidator, PostgresBackend, type PostgresBackendOptions, PreparedRow, SQLiteBackend, type SQLiteBackendOptions, SUPPORTED_FORMATS, StorageBackend, StorageError, StoredRecord, StoredRecordMetadata, UnsupportedFormatError, ValidatedContent, type ValidatedImage, ZeroBucketError, validateImage };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { S as StorageBackend, O as OperationEvent, a as ObjectStorageLike, P as PreparedRow, C as CallOptions, b as StoredRecord, c as StoredRecordMetadata, d as StreamOptions, e as StorageInfo, I as ImageListOptions, f as ImageListEntry, M as MysqlPoolLike, g as ContentValidator, V as ValidatedContent } from './client-XQ22b1l3.js';
2
- export { B as BatchDeleteResult, h as BatchGetResult, i as BatchPutResult, j as BeforeGetHook, k as BeforePutHook, l as Connection, D as DEFAULT_MAX_BYTES, G as GetOptions, m as Image, n as ImageInput, o as ImageMetadata, p as MysqlPoolConnectionLike, q as MysqlQueryable, r as ObjectStorage, s as ObjectStorageOptions, t as OptimizationResult, u as OptimizeOptions, v as PutManyOptions, w as PutOptions, Q as Queryable, x as SqliteDatabaseLike, y as StreamOptions, W as WritableLike, Z as ZeroBucket, z as ZeroBucketOptions, A as optimizeImage, E as readInput } from './client-XQ22b1l3.js';
1
+ import { S as StorageBackend, O as OperationEvent, a as ObjectStorageLike, P as PreparedRow, C as CallOptions, b as StoredRecord, c as StoredRecordMetadata, d as StreamOptions, e as StorageInfo, I as ImageListOptions, f as ImageListEntry, M as MigrateToDedupOptions, g as MigrateToDedupResult, h as MysqlPoolLike, i as ContentValidator, V as ValidatedContent } from './client-l4jPIFJI.js';
2
+ export { B as BatchDeleteResult, j as BatchGetResult, k as BatchPutResult, l as BeforeGetHook, m as BeforePutHook, n as Connection, D as DEFAULT_MAX_BYTES, G as GetOptions, o as Image, p as ImageInput, q as ImageMetadata, r as MysqlPoolConnectionLike, s as MysqlQueryable, t as ObjectStorage, u as ObjectStorageOptions, v as OptimizationResult, w as OptimizeOptions, x as PutManyOptions, y as PutOptions, Q as Queryable, z as SqliteDatabaseLike, A as StreamOptions, W as WritableLike, Z as ZeroBucket, E as ZeroBucketOptions, F as optimizeImage, H as readInput } from './client-l4jPIFJI.js';
3
3
  import { Pool } from 'pg';
4
4
 
5
5
  /**
@@ -158,18 +158,13 @@ declare class PostgresBackend implements StorageBackend {
158
158
  * dedup instance's tables, preserving every id (external references keep working) and
159
159
  * deduplicating identical content on the way. The classic table is never modified.
160
160
  *
161
- * Differences from the Python version, all deliberate: rows are copied in small batches (bounded
162
- * memory instead of loading the whole table); re-running is safe (already-migrated ids are
163
- * skipped and reported, not an error); and classic rows already tiered to object storage are
164
- * refused up front with a clear message (their bytes are not in the database to copy).
161
+ * Rows are copied in small batches (bounded memory instead of loading the whole table);
162
+ * re-running is safe (already-migrated ids are skipped and reported, not an error). Classic rows
163
+ * already tiered to object storage are refused up front with a clear message (their bytes are
164
+ * not in the database to copy) unless `skipTiered: true`, which skips and counts them instead.
165
165
  * Still all-or-nothing: one transaction.
166
166
  */
167
- migrateClassicToDedup(): Promise<{
168
- imagesMigrated: number;
169
- distinctBlobsCreated: number;
170
- duplicateReferencesFound: number;
171
- alreadyMigrated: number;
172
- }>;
167
+ migrateClassicToDedup(opts?: MigrateToDedupOptions): Promise<MigrateToDedupResult>;
173
168
  private hydrate;
174
169
  /**
175
170
  * Remove tiered objects AFTER their rows are gone. Ordering is deliberate:
@@ -434,4 +429,4 @@ declare class PDFValidator implements ContentValidator {
434
429
  }): ValidatedContent;
435
430
  }
436
431
 
437
- export { AccessDeniedError, CallOptions, ContentValidationError, ContentValidator, CorruptedImageError, DEFAULT_MAX_PIXELS, DEFAULT_STREAM_CHUNK_SIZE, ImageNotFoundError, ImageTooLargeError, ImageValidationError, MySQLBackend, type MySQLBackendOptions, MysqlPoolLike, ObjectStorageLike, OperationEvent, PDFValidator, PostgresBackend, type PostgresBackendOptions, PreparedRow, SQLiteBackend, type SQLiteBackendOptions, SUPPORTED_FORMATS, StorageBackend, StorageError, StoredRecord, StoredRecordMetadata, UnsupportedFormatError, ValidatedContent, type ValidatedImage, ZeroBucketError, validateImage };
432
+ export { AccessDeniedError, CallOptions, ContentValidationError, ContentValidator, CorruptedImageError, DEFAULT_MAX_PIXELS, DEFAULT_STREAM_CHUNK_SIZE, ImageNotFoundError, ImageTooLargeError, ImageValidationError, MigrateToDedupOptions, MigrateToDedupResult, MySQLBackend, type MySQLBackendOptions, MysqlPoolLike, ObjectStorageLike, OperationEvent, PDFValidator, PostgresBackend, type PostgresBackendOptions, PreparedRow, SQLiteBackend, type SQLiteBackendOptions, SUPPORTED_FORMATS, StorageBackend, StorageError, StoredRecord, StoredRecordMetadata, UnsupportedFormatError, ValidatedContent, type ValidatedImage, ZeroBucketError, validateImage };
package/dist/index.js CHANGED
@@ -875,13 +875,13 @@ var PostgresBackend = class {
875
875
  * dedup instance's tables, preserving every id (external references keep working) and
876
876
  * deduplicating identical content on the way. The classic table is never modified.
877
877
  *
878
- * Differences from the Python version, all deliberate: rows are copied in small batches (bounded
879
- * memory instead of loading the whole table); re-running is safe (already-migrated ids are
880
- * skipped and reported, not an error); and classic rows already tiered to object storage are
881
- * refused up front with a clear message (their bytes are not in the database to copy).
878
+ * Rows are copied in small batches (bounded memory instead of loading the whole table);
879
+ * re-running is safe (already-migrated ids are skipped and reported, not an error). Classic rows
880
+ * already tiered to object storage are refused up front with a clear message (their bytes are
881
+ * not in the database to copy) unless `skipTiered: true`, which skips and counts them instead.
882
882
  * Still all-or-nothing: one transaction.
883
883
  */
884
- async migrateClassicToDedup() {
884
+ async migrateClassicToDedup(opts = {}) {
885
885
  if (!this.dedup) {
886
886
  throw new StorageError(
887
887
  "migrateClassicToDedup() must be called on an instance created with dedup: true."
@@ -900,6 +900,7 @@ var PostgresBackend = class {
900
900
  "No classic zerobucket_images table found in this database -- nothing to migrate."
901
901
  );
902
902
  }
903
+ let tieredSkipped = 0;
903
904
  const hasTierCol = (await client.query(
904
905
  "SELECT 1 FROM information_schema.columns WHERE table_name = 'zerobucket_images' AND column_name = 'storage_backend'"
905
906
  )).rowCount;
@@ -907,12 +908,14 @@ var PostgresBackend = class {
907
908
  const tiered = (await client.query(
908
909
  "SELECT count(*)::int AS n FROM zerobucket_images WHERE storage_backend <> 'postgres'"
909
910
  )).rows[0].n;
910
- if (tiered > 0) {
911
+ if (tiered > 0 && !opts.skipTiered) {
911
912
  throw new StorageError(
912
- `${tiered} classic image(s) are tiered to object storage, so their bytes are not in the database to migrate. Dedup mode does not support tiering. Migrate only an un-tiered table, or bring those images back first.`
913
+ `${tiered} classic image(s) are tiered to object storage, so their bytes are not in the database to migrate. Dedup mode does not support tiering. Migrate only an un-tiered table, bring those images back first, or pass skipTiered: true (CLI: --skip-tiered) to skip them and migrate the rest.`
913
914
  );
914
915
  }
916
+ tieredSkipped = tiered;
915
917
  }
918
+ const onlyInDb = hasTierCol && tieredSkipped > 0;
916
919
  const seen = /* @__PURE__ */ new Set();
917
920
  let migrated = 0;
918
921
  let already = 0;
@@ -921,11 +924,11 @@ var PostgresBackend = class {
921
924
  for (; ; ) {
922
925
  const page = cursor ? await client.query(
923
926
  `SELECT id, data, mime_type, original_filename, size_bytes, width, height, checksum_sha256, created_at::text AS created_at_txt
924
- FROM zerobucket_images WHERE (created_at, id) > ($1::timestamptz, $2::uuid) ORDER BY created_at, id LIMIT ${BATCH}`,
927
+ FROM zerobucket_images WHERE (created_at, id) > ($1::timestamptz, $2::uuid)${onlyInDb ? " AND storage_backend = 'postgres'" : ""} ORDER BY created_at, id LIMIT ${BATCH}`,
925
928
  [cursor.createdAt, cursor.id]
926
929
  ) : await client.query(
927
930
  `SELECT id, data, mime_type, original_filename, size_bytes, width, height, checksum_sha256, created_at::text AS created_at_txt
928
- FROM zerobucket_images ORDER BY created_at, id LIMIT ${BATCH}`
931
+ FROM zerobucket_images${onlyInDb ? " WHERE storage_backend = 'postgres'" : ""} ORDER BY created_at, id LIMIT ${BATCH}`
929
932
  );
930
933
  if (page.rows.length === 0) break;
931
934
  const last = page.rows[page.rows.length - 1];
@@ -975,7 +978,8 @@ var PostgresBackend = class {
975
978
  imagesMigrated: migrated,
976
979
  distinctBlobsCreated: seen.size,
977
980
  duplicateReferencesFound: migrated - seen.size,
978
- alreadyMigrated: already
981
+ alreadyMigrated: already,
982
+ tieredSkipped
979
983
  };
980
984
  } catch (exc) {
981
985
  try {
@@ -3634,13 +3638,13 @@ var ZeroBucket = class _ZeroBucket {
3634
3638
  * One-time, non-destructive copy of classic-mode images into a dedup instance's tables, keeping every
3635
3639
  * id. Call it on an instance created with `dedup: true`. Safe to re-run. See PostgresBackend for details.
3636
3640
  */
3637
- async migrateClassicToDedup() {
3641
+ async migrateClassicToDedup(opts) {
3638
3642
  if (!this.backend.migrateClassicToDedup) {
3639
3643
  throw new StorageError(
3640
3644
  "This backend does not support migrateClassicToDedup()."
3641
3645
  );
3642
3646
  }
3643
- return this.backend.migrateClassicToDedup();
3647
+ return this.backend.migrateClassicToDedup(opts);
3644
3648
  }
3645
3649
  /** Release the pool (if ZeroBucket created it). */
3646
3650
  close() {