import { BlobsInternalError, Client, MissingBlobsEnvironmentError, REGION_AUTO, base64Decode, collectIterator, getClientOptions, getEnvironmentContext, getMetadataFromResponse, setEnvironmentContext } from "./chunk-XR3MUBBK.js"; // src/lambda_compat.ts var connectLambda = (event) => { const rawData = base64Decode(event.blobs); const data = JSON.parse(rawData); const environmentContext = { deployID: event.headers["x-nf-deploy-id"], edgeURL: data.url, siteID: event.headers["x-nf-site-id"], token: data.token }; setEnvironmentContext(environmentContext); }; // src/store.ts var DEPLOY_STORE_PREFIX = "deploy:"; var LEGACY_STORE_INTERNAL_PREFIX = "netlify-internal/legacy-namespace/"; var SITE_STORE_PREFIX = "site:"; var Store = class _Store { constructor(options) { this.client = options.client; if ("deployID" in options) { _Store.validateDeployID(options.deployID); let name = DEPLOY_STORE_PREFIX + options.deployID; if (options.name) { name += `:${options.name}`; } this.name = name; } else if (options.name.startsWith(LEGACY_STORE_INTERNAL_PREFIX)) { const storeName = options.name.slice(LEGACY_STORE_INTERNAL_PREFIX.length); _Store.validateStoreName(storeName); this.name = storeName; } else { _Store.validateStoreName(options.name); this.name = SITE_STORE_PREFIX + options.name; } } async delete(key) { const res = await this.client.makeRequest({ key, method: "delete" /* DELETE */, storeName: this.name }); if (![200, 204, 404].includes(res.status)) { throw new BlobsInternalError(res); } } async get(key, options) { const { consistency, type } = options ?? {}; const res = await this.client.makeRequest({ consistency, key, method: "get" /* GET */, storeName: this.name }); if (res.status === 404) { return null; } if (res.status !== 200) { throw new BlobsInternalError(res); } if (type === void 0 || type === "text") { return res.text(); } if (type === "arrayBuffer") { return res.arrayBuffer(); } if (type === "blob") { return res.blob(); } if (type === "json") { return res.json(); } if (type === "stream") { return res.body; } throw new BlobsInternalError(res); } async getMetadata(key, { consistency } = {}) { const res = await this.client.makeRequest({ consistency, key, method: "head" /* HEAD */, storeName: this.name }); if (res.status === 404) { return null; } if (res.status !== 200 && res.status !== 304) { throw new BlobsInternalError(res); } const etag = res?.headers.get("etag") ?? void 0; const metadata = getMetadataFromResponse(res); const result = { etag, metadata }; return result; } async getWithMetadata(key, options) { const { consistency, etag: requestETag, type } = options ?? {}; const headers = requestETag ? { "if-none-match": requestETag } : void 0; const res = await this.client.makeRequest({ consistency, headers, key, method: "get" /* GET */, storeName: this.name }); if (res.status === 404) { return null; } if (res.status !== 200 && res.status !== 304) { throw new BlobsInternalError(res); } const responseETag = res?.headers.get("etag") ?? void 0; const metadata = getMetadataFromResponse(res); const result = { etag: responseETag, metadata }; if (res.status === 304 && requestETag) { return { data: null, ...result }; } if (type === void 0 || type === "text") { return { data: await res.text(), ...result }; } if (type === "arrayBuffer") { return { data: await res.arrayBuffer(), ...result }; } if (type === "blob") { return { data: await res.blob(), ...result }; } if (type === "json") { return { data: await res.json(), ...result }; } if (type === "stream") { return { data: res.body, ...result }; } throw new Error(`Invalid 'type' property: ${type}. Expected: arrayBuffer, blob, json, stream, or text.`); } list(options = {}) { const iterator = this.getListIterator(options); if (options.paginate) { return iterator; } return collectIterator(iterator).then( (items) => items.reduce( (acc, item) => ({ blobs: [...acc.blobs, ...item.blobs], directories: [...acc.directories, ...item.directories] }), { blobs: [], directories: [] } ) ); } async set(key, data, { metadata } = {}) { _Store.validateKey(key); const res = await this.client.makeRequest({ body: data, key, metadata, method: "put" /* PUT */, storeName: this.name }); if (res.status !== 200) { throw new BlobsInternalError(res); } } async setJSON(key, data, { metadata } = {}) { _Store.validateKey(key); const payload = JSON.stringify(data); const headers = { "content-type": "application/json" }; const res = await this.client.makeRequest({ body: payload, headers, key, metadata, method: "put" /* PUT */, storeName: this.name }); if (res.status !== 200) { throw new BlobsInternalError(res); } } static formatListResultBlob(result) { if (!result.key) { return null; } return { etag: result.etag, key: result.key }; } static validateKey(key) { if (key === "") { throw new Error("Blob key must not be empty."); } if (key.startsWith("/") || key.startsWith("%2F")) { throw new Error("Blob key must not start with forward slash (/)."); } if (new TextEncoder().encode(key).length > 600) { throw new Error( "Blob key must be a sequence of Unicode characters whose UTF-8 encoding is at most 600 bytes long." ); } } static validateDeployID(deployID) { if (!/^\w{1,24}$/.test(deployID)) { throw new Error(`'${deployID}' is not a valid Netlify deploy ID.`); } } static validateStoreName(name) { if (name.includes("/") || name.includes("%2F")) { throw new Error("Store name must not contain forward slashes (/)."); } if (new TextEncoder().encode(name).length > 64) { throw new Error( "Store name must be a sequence of Unicode characters whose UTF-8 encoding is at most 64 bytes long." ); } } getListIterator(options) { const { client, name: storeName } = this; const parameters = {}; if (options?.prefix) { parameters.prefix = options.prefix; } if (options?.directories) { parameters.directories = "true"; } return { [Symbol.asyncIterator]() { let currentCursor = null; let done = false; return { async next() { if (done) { return { done: true, value: void 0 }; } const nextParameters = { ...parameters }; if (currentCursor !== null) { nextParameters.cursor = currentCursor; } const res = await client.makeRequest({ method: "get" /* GET */, parameters: nextParameters, storeName }); let blobs = []; let directories = []; if (![200, 204, 404].includes(res.status)) { throw new BlobsInternalError(res); } if (res.status === 404) { done = true; } else { const page = await res.json(); if (page.next_cursor) { currentCursor = page.next_cursor; } else { done = true; } blobs = (page.blobs ?? []).map(_Store.formatListResultBlob).filter(Boolean); directories = page.directories ?? []; } return { done: false, value: { blobs, directories } }; } }; } }; } }; // src/store_factory.ts var getDeployStore = (input = {}) => { const context = getEnvironmentContext(); const options = typeof input === "string" ? { name: input } : input; const deployID = options.deployID ?? context.deployID; if (!deployID) { throw new MissingBlobsEnvironmentError(["deployID"]); } const clientOptions = getClientOptions(options, context); if (!clientOptions.region) { if (clientOptions.edgeURL || clientOptions.uncachedEdgeURL) { if (!context.primaryRegion) { throw new Error( "When accessing a deploy store, the Netlify Blobs client needs to be configured with a region, and one was not found in the environment. To manually set the region, set the `region` property in the `getDeployStore` options. If you are using the Netlify CLI, you may have an outdated version; run `npm install -g netlify-cli@latest` to update and try again." ); } clientOptions.region = context.primaryRegion; } else { clientOptions.region = REGION_AUTO; } } const client = new Client(clientOptions); return new Store({ client, deployID, name: options.name }); }; var getStore = (input) => { if (typeof input === "string") { const clientOptions = getClientOptions({}); const client = new Client(clientOptions); return new Store({ client, name: input }); } if (typeof input?.name === "string" && typeof input?.siteID === "string" && typeof input?.token === "string") { const { name, siteID, token } = input; const clientOptions = getClientOptions(input, { siteID, token }); if (!name || !siteID || !token) { throw new MissingBlobsEnvironmentError(["name", "siteID", "token"]); } const client = new Client(clientOptions); return new Store({ client, name }); } if (typeof input?.name === "string") { const { name } = input; const clientOptions = getClientOptions(input); if (!name) { throw new MissingBlobsEnvironmentError(["name"]); } const client = new Client(clientOptions); return new Store({ client, name }); } if (typeof input?.deployID === "string") { const clientOptions = getClientOptions(input); const { deployID } = input; if (!deployID) { throw new MissingBlobsEnvironmentError(["deployID"]); } const client = new Client(clientOptions); return new Store({ client, deployID }); } throw new Error( "The `getStore` method requires the name of the store as a string or as the `name` property of an options object" ); }; // src/store_list.ts function listStores(options = {}) { const context = getEnvironmentContext(); const clientOptions = getClientOptions(options, context); const client = new Client(clientOptions); const iterator = getListIterator(client, SITE_STORE_PREFIX); if (options.paginate) { return iterator; } return collectIterator(iterator).then((results) => ({ stores: results.flatMap((page) => page.stores) })); } var formatListStoreResponse = (stores) => stores.filter((store) => !store.startsWith(DEPLOY_STORE_PREFIX)).map((store) => store.startsWith(SITE_STORE_PREFIX) ? store.slice(SITE_STORE_PREFIX.length) : store); var getListIterator = (client, prefix) => { const parameters = { prefix }; return { [Symbol.asyncIterator]() { let currentCursor = null; let done = false; return { async next() { if (done) { return { done: true, value: void 0 }; } const nextParameters = { ...parameters }; if (currentCursor !== null) { nextParameters.cursor = currentCursor; } const res = await client.makeRequest({ method: "get" /* GET */, parameters: nextParameters }); if (res.status === 404) { return { done: true, value: void 0 }; } const page = await res.json(); if (page.next_cursor) { currentCursor = page.next_cursor; } else { done = true; } return { done: false, value: { ...page, stores: formatListStoreResponse(page.stores) } }; } }; } }; }; export { connectLambda, getDeployStore, getStore, listStores, setEnvironmentContext };