lazypock 0.16.1 → 0.17.0

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.cjs CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  getFileUrl: () => getFileUrl,
40
40
  getScaleUrl: () => getScaleUrl,
41
41
  getThumbUrl: () => getThumbUrl,
42
+ getVariantUrl: () => getVariantUrl,
42
43
  schemaFieldType: () => schemaFieldType,
43
44
  wsUrlFromBaseUrl: () => wsUrlFromBaseUrl
44
45
  });
@@ -1229,7 +1230,7 @@ var CollectionService = class _CollectionService {
1229
1230
  requestKey,
1230
1231
  autoCancel,
1231
1232
  cancelKey,
1232
- fetch,
1233
+ fetch: fetch2,
1233
1234
  headers,
1234
1235
  signal,
1235
1236
  singleFlight,
@@ -1273,7 +1274,7 @@ var CollectionService = class _CollectionService {
1273
1274
  requestKey,
1274
1275
  autoCancel,
1275
1276
  cancelKey,
1276
- fetch,
1277
+ fetch: fetch2,
1277
1278
  headers,
1278
1279
  signal,
1279
1280
  singleFlight,
@@ -1999,9 +2000,28 @@ function getThumbUrl(baseUrl, fileId, size) {
1999
2000
  function getScaleUrl(baseUrl, fileId, size) {
2000
2001
  return baseUrl.replace(/\/+$/, "") + "/files/" + encodeURIComponent(fileId) + "/scale/" + encodeURIComponent(size);
2001
2002
  }
2003
+ function getVariantUrl(baseUrl, fileId, preset) {
2004
+ return getScaleUrl(baseUrl, fileId, preset);
2005
+ }
2006
+ function parseUploadTarget(rawUrl, allowedHosts) {
2007
+ let parsed;
2008
+ try {
2009
+ parsed = new URL(rawUrl);
2010
+ } catch {
2011
+ throw new Error("Direct upload: the server returned an invalid upload URL");
2012
+ }
2013
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
2014
+ throw new Error(`Direct upload: unsupported protocol ${parsed.protocol}`);
2015
+ }
2016
+ if (allowedHosts && allowedHosts.length > 0 && !allowedHosts.includes(parsed.host)) {
2017
+ throw new Error(`Direct upload: host ${parsed.host} is not in the allowlist`);
2018
+ }
2019
+ return parsed;
2020
+ }
2002
2021
  var FilesService = class {
2003
- constructor(http) {
2022
+ constructor(http, allowedUploadHosts) {
2004
2023
  this.http = http;
2024
+ this.allowedUploadHosts = allowedUploadHosts;
2005
2025
  }
2006
2026
  /**
2007
2027
  * Upload a file or blob.
@@ -2022,6 +2042,8 @@ var FilesService = class {
2022
2042
  formData.append("collection_name", meta.collectionName);
2023
2043
  if (meta?.recordId) formData.append("record_id", meta.recordId);
2024
2044
  if (meta?.fieldName) formData.append("field_name", meta.fieldName);
2045
+ if (meta?.origin) formData.append("origin", meta.origin);
2046
+ if (meta?.variants?.length) formData.append("variants", meta.variants.join(","));
2025
2047
  const data = await this.http.request(
2026
2048
  "POST",
2027
2049
  "/files",
@@ -2030,6 +2052,62 @@ var FilesService = class {
2030
2052
  );
2031
2053
  return data;
2032
2054
  }
2055
+ /**
2056
+ * Direct upload (Mode B): the browser PUTs straight to S3/R2.
2057
+ *
2058
+ * Presigns, uploads, then asks the server to verify the object. Falls back to
2059
+ * `upload()` when the server has no direct-upload support configured.
2060
+ */
2061
+ async uploadDirect(file, opts) {
2062
+ const filename = opts?.filename || (file instanceof File ? file.name : "file");
2063
+ const mime = file.type || "application/octet-stream";
2064
+ const presigned = await this.presign({
2065
+ filename,
2066
+ size: file.size,
2067
+ mime,
2068
+ collectionName: opts?.collectionName,
2069
+ fieldName: opts?.fieldName,
2070
+ recordId: opts?.recordId
2071
+ });
2072
+ if (!presigned) return this.upload(file, filename, { signal: opts?.signal }, { collectionName: opts?.collectionName, fieldName: opts?.fieldName, recordId: opts?.recordId });
2073
+ const target = parseUploadTarget(presigned.url, this.allowedUploadHosts);
2074
+ const put = await fetch(target.href, {
2075
+ method: presigned.method || "PUT",
2076
+ headers: presigned.headers,
2077
+ body: file,
2078
+ signal: opts?.signal
2079
+ });
2080
+ if (!put.ok) throw new Error(`Direct upload failed: HTTP ${put.status}`);
2081
+ return this.complete(presigned.id, { variant: opts?.variant, signal: opts?.signal });
2082
+ }
2083
+ /** Step 1 of a direct upload: reserve an object and get a presigned PUT. */
2084
+ async presign(params) {
2085
+ const data = await this.http.request(
2086
+ "POST",
2087
+ "/files/presign",
2088
+ {
2089
+ filename: params.filename,
2090
+ size: params.size,
2091
+ mime: params.mime,
2092
+ collection_name: params.collectionName,
2093
+ field_name: params.fieldName,
2094
+ record_id: params.recordId
2095
+ }
2096
+ );
2097
+ if (!data || typeof data.url !== "string") return null;
2098
+ return data;
2099
+ }
2100
+ /** Step 2 of a direct upload: ask the server to verify the object. */
2101
+ async complete(fileId, opts) {
2102
+ const query = opts?.variant ? `?variants=${encodeURIComponent(opts.variant)}` : "";
2103
+ const data = await this.http.request(
2104
+ "POST",
2105
+ `/files/${encodeURIComponent(fileId)}/complete${query}`,
2106
+ {},
2107
+ { signal: opts?.signal }
2108
+ );
2109
+ return data;
2110
+ }
2033
2111
  /**
2034
2112
  * List uploaded files (newest first), with optional filters.
2035
2113
  *
@@ -2842,6 +2920,7 @@ function createClient(options) {
2842
2920
  getFileUrl,
2843
2921
  getScaleUrl,
2844
2922
  getThumbUrl,
2923
+ getVariantUrl,
2845
2924
  schemaFieldType,
2846
2925
  wsUrlFromBaseUrl
2847
2926
  });