From 121ada61dad098cf85a4fa3e1df477cb0d14ce9c Mon Sep 17 00:00:00 2001 From: David Bosschaert Date: Fri, 13 Jun 2025 11:33:18 +0100 Subject: [PATCH 01/10] Merge original s3sb --- src/storage/object/copy.js | 6 +-- src/storage/object/delete.js | 2 +- src/storage/object/get.js | 10 ++--- src/storage/object/list.js | 10 +++-- src/storage/object/move.js | 8 ++-- src/storage/object/put.js | 14 ++++--- src/storage/utils/list.js | 14 +++---- src/storage/version/get.js | 4 +- src/storage/version/list.js | 7 ++-- src/storage/version/put.js | 15 +++---- src/utils/daCtx.js | 2 + test/storage/object/copy.test.js | 30 +++++++------- test/storage/object/delete.test.js | 5 ++- test/storage/object/list.test.js | 12 +++--- test/storage/version/put.test.js | 66 +++++++++++++++--------------- wrangler.toml | 6 +-- 16 files changed, 110 insertions(+), 101 deletions(-) diff --git a/src/storage/object/copy.js b/src/storage/object/copy.js index cb7b453a..517766be 100644 --- a/src/storage/object/copy.js +++ b/src/storage/object/copy.js @@ -36,9 +36,9 @@ export const copyFile = async (config, env, daCtx, sourceKey, details, isRename) } const input = { - Bucket: `${daCtx.org}-content`, - Key, - CopySource: `${daCtx.org}-content/${sourceKey}`, + Bucket: daCtx.bucket, + Key: `${daCtx.org}/${Key}`, + CopySource: `${daCtx.bucket}/${daCtx.org}/${sourceKey}`, }; // We only want to keep the history if this was a rename. In case of an actual diff --git a/src/storage/object/delete.js b/src/storage/object/delete.js index b9b0fc55..c00abbf4 100644 --- a/src/storage/object/delete.js +++ b/src/storage/object/delete.js @@ -31,7 +31,7 @@ export async function deleteObject(client, daCtx, Key, env /* , isMove = false * let resp; try { - const delCommand = new DeleteObjectCommand({ Bucket: `${daCtx.org}-content`, Key }); + const delCommand = new DeleteObjectCommand({ Bucket: daCtx.bucket, Key: `${daCtx.org}/${Key}` }); const url = await getSignedUrl(client, delCommand, { expiresIn: 3600 }); resp = await fetch(url, { method: 'DELETE' }); } catch (e) { diff --git a/src/storage/object/get.js b/src/storage/object/get.js index efb21604..cf17df94 100644 --- a/src/storage/object/get.js +++ b/src/storage/object/get.js @@ -18,16 +18,16 @@ import { import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import getS3Config from '../utils/config.js'; -function buildInput({ org, key }) { - const Bucket = `${org}-content`; - return { Bucket, Key: key }; +function buildInput({ bucket, org, key }) { + const Bucket = bucket; + return { Bucket, Key: `${org}/${key}` }; } -export default async function getObject(env, { org, key }, head = false) { +export default async function getObject(env, { bucket, org, key }, head = false) { const config = getS3Config(env); const client = new S3Client(config); - const input = buildInput({ org, key }); + const input = buildInput({ bucket, org, key }); if (!head) { try { const resp = await client.send(new GetObjectCommand(input)); diff --git a/src/storage/object/list.js b/src/storage/object/list.js index 9132fef2..a6f0afde 100644 --- a/src/storage/object/list.js +++ b/src/storage/object/list.js @@ -17,10 +17,12 @@ import { import getS3Config from '../utils/config.js'; import formatList from '../utils/list.js'; -function buildInput({ org, key, maxKeys }) { +function buildInput({ + bucket, org, key, maxKeys, +}) { const input = { - Bucket: `${org}-content`, - Prefix: key ? `${key}/` : null, + Bucket: bucket, + Prefix: key ? `${org}/${key}/` : `${org}/`, Delimiter: '/', }; if (maxKeys) input.MaxKeys = maxKeys; @@ -36,7 +38,7 @@ export default async function listObjects(env, daCtx, maxKeys) { try { const resp = await client.send(command); // console.log(resp); - const body = formatList(resp, daCtx); + const body = formatList(resp); return { body: JSON.stringify(body), status: resp.$metadata.httpStatusCode, diff --git a/src/storage/object/move.js b/src/storage/object/move.js index 8cc1f3d1..5494f507 100644 --- a/src/storage/object/move.js +++ b/src/storage/object/move.js @@ -19,17 +19,17 @@ import { deleteObject } from './delete.js'; import { copyFile } from './copy.js'; import { hasPermission } from '../../utils/auth.js'; -function buildInput(org, key) { +function buildInput(bucket, org, key) { return { - Bucket: `${org}-content`, - Prefix: `${key}/`, + Bucket: bucket, + Prefix: `${org}/${key}/`, }; } export default async function moveObject(env, daCtx, details) { const config = getS3Config(env); const client = new S3Client(config); - const input = buildInput(daCtx.org, details.source); + const input = buildInput(daCtx.bucket, daCtx.org, details.source); // The input prefix has a forward slash to prevent (drafts + drafts-new, etc.). // Which means the list will only pickup children. This adds to the initial list. diff --git a/src/storage/object/put.js b/src/storage/object/put.js index 36f2611b..20cfa97c 100644 --- a/src/storage/object/put.js +++ b/src/storage/object/put.js @@ -29,11 +29,11 @@ function getObjectBody(data) { } function buildInput({ - org, key, body, type, + bucket, org, key, body, type, }) { - const Bucket = `${org}-content`; + const Bucket = bucket; return { - Bucket, Key: key, Body: body, ContentType: type, + Bucket, Key: `${org}/${key}`, Body: body, ContentType: type, }; } @@ -70,7 +70,9 @@ export default async function putObject(env, daCtx, obj) { const config = getS3Config(env); const client = new S3Client(config); - const { org, key, propsKey } = daCtx; + const { + bucket, org, key, propsKey, + } = daCtx; // Only allow creating a new bucket for orgs and repos if (key.split('/').length <= 1) { @@ -89,7 +91,7 @@ export default async function putObject(env, daCtx, obj) { const isFile = obj.data instanceof File; const { body, type } = isFile ? await getFileBody(obj.data) : getObjectBody(obj.data); const res = await putObjectWithVersion(env, daCtx, { - org, key, body, type, + bucket, org, key, body, type, }, false, obj.guid); status = res.status; metadata = res.metadata; @@ -97,7 +99,7 @@ export default async function putObject(env, daCtx, obj) { } else { const { body, type } = getObjectBody({}); const inputConfig = { - org, key: propsKey, body, type, + bucket, org, key: propsKey, body, type, }; inputs.push(buildInput(inputConfig)); } diff --git a/src/storage/utils/list.js b/src/storage/utils/list.js index 5d6e5ee9..500c266d 100644 --- a/src/storage/utils/list.js +++ b/src/storage/utils/list.js @@ -13,7 +13,7 @@ import { ListObjectsV2Command, } from '@aws-sdk/client-s3'; -export default function formatList(resp, daCtx) { +export default function formatList(resp) { function compare(a, b) { if (a.name < b.name) return -1; if (a.name > b.name) return 1; @@ -32,7 +32,7 @@ export default function formatList(resp, daCtx) { // Do not add any extension folders if (splitName.length > 1) return; - const path = `/${daCtx.org}/${prefix.Prefix.slice(0, -1)}`; + const path = `/${prefix.Prefix.slice(0, -1)}`; combined.push({ path, name }); }); } @@ -61,7 +61,7 @@ export default function formatList(resp, daCtx) { // Do not show any hidden files. if (!name) return; - const item = { path: `/${daCtx.org}/${content.Key}`, name }; + const item = { path: `/${content.Key}`, name }; if (ext !== 'props') { item.ext = ext; item.lastModified = content.LastModified.getTime(); @@ -74,10 +74,10 @@ export default function formatList(resp, daCtx) { return combined.sort(compare); } -function buildInput(org, key) { +function buildInput(bucket, org, key) { return { - Bucket: `${org}-content`, - Prefix: `${key}/`, + Bucket: bucket, + Prefix: `${org}/${key}/`, MaxKeys: 300, }; } @@ -93,7 +93,7 @@ export async function listCommand(daCtx, details, s3client) { // There's no need to use the list command if the item has an extension if (daCtx.ext) return { sourceKeys: [daCtx.key] }; - const input = buildInput(daCtx.org, daCtx.key); + const input = buildInput(daCtx.bucket, daCtx.org, daCtx.key); const { continuationToken } = details; // The input prefix has a forward slash to prevent (drafts + drafts-new, etc.). diff --git a/src/storage/version/get.js b/src/storage/version/get.js index cadd5d74..5326461a 100644 --- a/src/storage/version/get.js +++ b/src/storage/version/get.js @@ -11,6 +11,6 @@ */ import getObject from '../object/get.js'; -export async function getObjectVersion(env, { org, key }, head) { - return getObject(env, { org, key: `.da-versions/${key}` }, head); +export async function getObjectVersion(env, { bucket, org, key }, head) { + return getObject(env, { bucket, org, key: `.da-versions/${key}` }, head); } diff --git a/src/storage/version/list.js b/src/storage/version/list.js index 857a2f1d..510e2cb8 100644 --- a/src/storage/version/list.js +++ b/src/storage/version/list.js @@ -12,14 +12,15 @@ import getObject from '../object/get.js'; import listObjects from '../object/list.js'; -export async function listObjectVersions(env, { org, key }) { - const current = await getObject(env, { org, key }, true); +export async function listObjectVersions(env, { bucket, org, key }) { + const current = await getObject(env, { bucket, org, key }, true); if (current.status === 404 || !current.metadata.id) { return 404; } - const resp = await listObjects(env, { org, key: `.da-versions/${current.metadata.id}` }, 500); + const resp = await listObjects(env, { bucket, org, key: `.da-versions/${current.metadata.id}` }, 500); const promises = await Promise.all(JSON.parse(resp.body).map(async (entry) => { const entryResp = await getObject(env, { + bucket, org, key: `.da-versions/${current.metadata.id}/${entry.name}.${entry.ext}`, }, true); diff --git a/src/storage/version/put.js b/src/storage/version/put.js index 78989b71..f6227ac0 100644 --- a/src/storage/version/put.js +++ b/src/storage/version/put.js @@ -35,13 +35,13 @@ export function getContentLength(body) { } export async function putVersion(config, { - Bucket, Body, ID, Version, Ext, Metadata, ContentLength, + Bucket, Org, Body, ID, Version, Ext, Metadata, ContentLength, }, noneMatch = true) { const length = ContentLength ?? getContentLength(Body); const client = noneMatch ? ifNoneMatch(config) : createBucketIfMissing(new S3Client(config)); const input = { - Bucket, Key: `.da-versions/${ID}/${Version}.${Ext}`, Body, Metadata, ContentLength: length, + Bucket, Key: `${Org}/.da-versions/${ID}/${Version}.${Ext}`, Body, Metadata, ContentLength: length, }; const command = new PutObjectCommand(input); try { @@ -53,13 +53,13 @@ export async function putVersion(config, { } function buildInput({ - org, key, body, type, contentLength, + bucket, org, key, body, type, contentLength, }) { const length = contentLength ?? getContentLength(body); - const Bucket = `${org}-content`; + const Bucket = bucket; return { - Bucket, Key: key, Body: body, ContentType: type, ContentLength: length, + Bucket, Key: `${org}/${key}`, Body: body, ContentType: type, ContentLength: length, }; } @@ -113,6 +113,7 @@ export async function putObjectWithVersion(env, daCtx, update, body, guid) { const versionResp = await putVersion(config, { Bucket: input.Bucket, + Org: daCtx.org, Body: (body || storeBody ? current.body : ''), ContentLength: (body || storeBody ? current.contentLength : undefined), ID, @@ -151,10 +152,10 @@ export async function putObjectWithVersion(env, daCtx, update, body, guid) { export async function postObjectVersionWithLabel(label, env, daCtx) { const { body, contentLength, contentType } = await getObject(env, daCtx); - const { org, key } = daCtx; + const { bucket, org, key } = daCtx; const resp = await putObjectWithVersion(env, daCtx, { - org, key, body, contentLength, type: contentType, label, + bucket, org, key, body, contentLength, type: contentType, label, }, true); return { status: resp.status === 200 ? 201 : resp.status }; diff --git a/src/utils/daCtx.js b/src/utils/daCtx.js index bec47a5b..82298d68 100644 --- a/src/utils/daCtx.js +++ b/src/utils/daCtx.js @@ -33,11 +33,13 @@ export default async function getDaCtx(req, env) { const api = split.shift(); const fullKey = split.join('/'); const [org, ...parts] = split; + const bucket = env.DA_BUCKET; // Set base details const daCtx = { path: pathname, api, + bucket, org, users, fullKey, diff --git a/test/storage/object/copy.test.js b/test/storage/object/copy.test.js index f35df28d..fe03594f 100644 --- a/test/storage/object/copy.test.js +++ b/test/storage/object/copy.test.js @@ -95,7 +95,7 @@ describe('Object copy', () => { ]); const aclCtx = { pathLookup, actionSet: new Set(['read'])}; - const ctx = { aclCtx, key: 'source/mysrc', org: 'org', users: [{email: 'aaa@bbb.ccc'}] }; + const ctx = { aclCtx, bucket: 'root-bucket', key: 'source/mysrc', org: 'org', users: [{email: 'aaa@bbb.ccc'}] }; const details = { source: 'mysrc', @@ -125,9 +125,9 @@ describe('Object copy', () => { const resp = await copyFile({}, {}, ctx, 'source/mysrc', details, true); assert.strictEqual(resp.$metadata.httpStatusCode, 200); const input = resp.command.input; - assert.strictEqual(input.Bucket, 'org-content'); - assert.strictEqual(input.CopySource, 'org-content/source/mysrc'); - assert.strictEqual(input.Key, 'source/mydst'); + assert.strictEqual(input.Bucket, 'root-bucket'); + assert.strictEqual(input.CopySource, 'root-bucket/org/source/mysrc'); + assert.strictEqual(input.Key, 'org/source/mydst'); assert(input.MetadataDirective === undefined); }); @@ -148,6 +148,7 @@ describe('Object copy', () => { } const env = { dacollab }; const ctx = { + bucket: 'root-bucket', env, org: 'foo', key: 'mydir', @@ -167,9 +168,9 @@ describe('Object copy', () => { s3Sent.sort((a, b) => a.Key.localeCompare(b.Key)); const input = s3Sent[2]; - assert.strictEqual(input.Bucket, 'foo-content'); - assert.strictEqual(input.CopySource, 'foo-content/mydir/xyz.html'); - assert.strictEqual(input.Key, 'mydir/newdir/xyz.html'); + assert.strictEqual(input.Bucket, 'root-bucket'); + assert.strictEqual(input.CopySource, 'root-bucket/foo/mydir/xyz.html'); + assert.strictEqual(input.Key, 'foo/mydir/newdir/xyz.html'); const md = input.Metadata; assert(md.ID, "ID should be set"); @@ -198,7 +199,7 @@ describe('Object copy', () => { } } const env = { dacollab }; - const ctx = { org: 'testorg', key: 'mydir/dir1', origin: 'http://localhost:3000' }; + const ctx = { bucket: 'root-bucket', org: 'testorg', key: 'mydir/dir1', origin: 'http://localhost:3000' }; ctx.aclCtx = await getAclCtx(env, ctx.org, ctx.users, '/'); const details = { source: 'mydir/dir1', @@ -212,9 +213,9 @@ describe('Object copy', () => { s3Sent.sort((a, b) => a.Key.localeCompare(b.Key)); const input = s3Sent[2]; - assert.strictEqual(input.Bucket, 'testorg-content'); - assert.strictEqual(input.CopySource, 'testorg-content/mydir/dir1/myfile.html'); - assert.strictEqual(input.Key, 'mydir/dir2/myfile.html'); + assert.strictEqual(input.Bucket, 'root-bucket'); + assert.strictEqual(input.CopySource, 'root-bucket/testorg/mydir/dir1/myfile.html'); + assert.strictEqual(input.Key, 'testorg/mydir/dir2/myfile.html'); assert.ifError(input.Metadata); assert.deepStrictEqual(collabcalls, @@ -250,6 +251,7 @@ describe('Object copy', () => { }, }; const daCtx = { + bucket: 'root-bucket', org: 'myorg', origin: 'https://blahblah:7890', users: [{email: 'joe@bloggs.org', otherstuff: 'blah'}], @@ -262,9 +264,9 @@ describe('Object copy', () => { const resp = await copyFile({}, env, daCtx, 'mysrc/abc/def.html', details, false); assert.strictEqual(resp.constructor.name, 'CopyObjectCommand'); - assert.strictEqual(resp.input.Bucket, 'myorg-content'); - assert.strictEqual(resp.input.Key, 'mydst/abc/def.html'); - assert.strictEqual(resp.input.CopySource, 'myorg-content/mysrc/abc/def.html'); + assert.strictEqual(resp.input.Bucket, 'root-bucket'); + assert.strictEqual(resp.input.Key, 'myorg/mydst/abc/def.html'); + assert.strictEqual(resp.input.CopySource, 'root-bucket/myorg/mysrc/abc/def.html'); assert.strictEqual(resp.input.MetadataDirective, 'REPLACE'); assert.strictEqual(resp.input.Metadata.Path, 'mydst/abc/def.html'); assert.strictEqual(resp.input.Metadata.Users, '[{"email":"joe@bloggs.org"}]'); diff --git a/test/storage/object/delete.test.js b/test/storage/object/delete.test.js index c6259da0..de77e41d 100644 --- a/test/storage/object/delete.test.js +++ b/test/storage/object/delete.test.js @@ -305,6 +305,7 @@ describe('Object delete', () => { } }; const getSignedUrl = (c, dc) => { + assert.strictEqual(dc.input.Bucket, 'testbucket'); return dc.input.Key; } const mockS3Client = class {}; @@ -331,7 +332,7 @@ describe('Object delete', () => { ]); const aclCtx = { pathLookup }; const users = [{ email: 'harry@foo.org' }]; - const ctx = { aclCtx, users, key: 'notused' }; + const ctx = { bucket: 'testbucket', org: 'myorg', aclCtx, users, key: 'notused' }; const fetchURLs = []; const savedFetch = globalThis.fetch; @@ -346,7 +347,7 @@ describe('Object delete', () => { } finally { globalThis.fetch = savedFetch; } - assert.deepStrictEqual(['c'], fetchURLs); + assert.deepStrictEqual(['myorg/c'], fetchURLs); }); }); }); diff --git a/test/storage/object/list.test.js b/test/storage/object/list.test.js index 032e11d7..211714ee 100644 --- a/test/storage/object/list.test.js +++ b/test/storage/object/list.test.js @@ -32,12 +32,12 @@ describe('List Objects', () => { it('populates file metadata', async () => { s3Mock.on(ListObjectsV2Command, { - Bucket: 'adobe-content', - Prefix: 'wknd/', + Bucket: 'bkt', + Prefix: 'adobe/wknd/', Delimiter: '/', }).resolves({ $metadata: { httpStatusCode: 200 }, Contents }); - const daCtx = { org: 'adobe', key: 'wknd' }; + const daCtx = { bucket: 'bkt', org: 'adobe', key: 'wknd' }; const resp = await listObjects({}, daCtx); const data = JSON.parse(resp.body); assert.strictEqual(data.length, 3); @@ -46,13 +46,13 @@ describe('List Objects', () => { it('limits the results', async () => { s3Mock.on(ListObjectsV2Command, { - Bucket: 'adobe-content', - Prefix: 'wknd/', + Bucket: 'rt-bkt', + Prefix: 'acme/wknd/', Delimiter: '/', MaxKeys: 2, }).resolves({ $metadata: { httpStatusCode: 200 }, Contents: [Contents[0], Contents[1]]}); - const daCtx = { org: 'adobe', key: 'wknd' }; + const daCtx = { bucket: 'rt-bkt', org: 'acme', key: 'wknd' }; const resp = await listObjects({}, daCtx, 2); const data = JSON.parse(resp.body); assert.strictEqual(data.length, 2, 'Should only return 2 items'); diff --git a/test/storage/version/put.test.js b/test/storage/version/put.test.js index 50321161..bd72ef2c 100644 --- a/test/storage/version/put.test.js +++ b/test/storage/version/put.test.js @@ -181,25 +181,25 @@ describe('Version Put', () => { }); const env = {}; - const daCtx= { ext: 'html' }; - const update = { body: 'new-body', org: 'myorg', key: '/a/x.html' }; + const daCtx= { bucket: 'bkt', org: 'myorg', ext: 'html' }; + const update = { bucket: 'bkt', body: 'new-body', org: 'myorg', key: 'a/x.html' }; const resp = await putObjectWithVersion(env, daCtx, update, true); assert.equal(200, resp.status); assert.equal('x123', resp.metadata.id); assert.equal(1, s3VersionSent.length); assert.equal('prevbody', s3VersionSent[0].input.Body); - assert.equal('myorg-content', s3VersionSent[0].input.Bucket); - assert.equal('.da-versions/x123/aaa-bbb.html', s3VersionSent[0].input.Key); + assert.equal('bkt', s3VersionSent[0].input.Bucket); + assert.equal('myorg/.da-versions/x123/aaa-bbb.html', s3VersionSent[0].input.Key); assert.equal('[{"email":"anonymous"}]', s3VersionSent[0].input.Metadata.Users); - assert.equal('/a/x.html', s3VersionSent[0].input.Metadata.Path); + assert.equal('a/x.html', s3VersionSent[0].input.Metadata.Path); assert(s3VersionSent[0].input.Metadata.Timestamp > 0); assert.equal(1, s3Sent.length); assert.equal('new-body', s3Sent[0].input.Body); - assert.equal('myorg-content', s3Sent[0].input.Bucket); - assert.equal('/a/x.html', s3Sent[0].input.Key); + assert.equal('bkt', s3Sent[0].input.Bucket); + assert.equal('myorg/a/x.html', s3Sent[0].input.Key); assert.equal('x123', s3Sent[0].input.Metadata.ID); - assert.equal('/a/x.html', s3Sent[0].input.Metadata.Path); + assert.equal('a/x.html', s3Sent[0].input.Metadata.Path); assert.notEqual('aaa-bbb', s3Sent[0].input.Metadata.Version); assert(s3Sent[0].input.Metadata.Timestamp > 0); }); @@ -248,30 +248,25 @@ describe('Version Put', () => { }); const env = {}; - const daCtx= { - ext: 'html', - users: [ - {"email": "foo@acme.org", orgs: ['myorg']}, - {"email": "bar@acme.org", groups: ['g1', 'g2']} - ]}; - const update = { body: 'new-body', org: 'myorg', key: '/a/x.html' }; + const daCtx= { bucket: 'bbb', org: 'myorg', ext: 'html', users: [{"email": "foo@acme.org"}, {"email": "bar@acme.org"}] }; + const update = { bucket: 'bbb', body: 'new-body', org: 'myorg', key: 'a/x.html' }; const resp = await putObjectWithVersion(env, daCtx, update, false); assert.equal(202, resp.status); assert.equal('q123-456', resp.metadata.id); assert.equal(1, s3VersionSent.length); assert.equal('', s3VersionSent[0].input.Body); - assert.equal('myorg-content', s3VersionSent[0].input.Bucket); - assert.equal('.da-versions/q123-456/ver123.html', s3VersionSent[0].input.Key); + assert.equal('bbb', s3VersionSent[0].input.Bucket); + assert.equal('myorg/.da-versions/q123-456/ver123.html', s3VersionSent[0].input.Key); assert.equal('[{"email":"anonymous"}]', s3VersionSent[0].input.Metadata.Users); - assert.equal('/a/x.html', s3VersionSent[0].input.Metadata.Path); + assert.equal('a/x.html', s3VersionSent[0].input.Metadata.Path); assert(s3VersionSent[0].input.Metadata.Timestamp > 0); assert.equal(1, s3Sent.length); assert.equal('new-body', s3Sent[0].input.Body); - assert.equal('myorg-content', s3Sent[0].input.Bucket); - assert.equal('/a/x.html', s3Sent[0].input.Key); + assert.equal('bbb', s3Sent[0].input.Bucket); + assert.equal('myorg/a/x.html', s3Sent[0].input.Key); assert.equal('q123-456', s3Sent[0].input.Metadata.ID); - assert.equal('/a/x.html', s3Sent[0].input.Metadata.Path); + assert.equal('a/x.html', s3Sent[0].input.Metadata.Path); assert.equal('[{\"email\":\"foo@acme.org\"},{\"email\":\"bar@acme.org\"}]', s3Sent[0].input.Metadata.Users); assert.notEqual('aaa-bbb', s3Sent[0].input.Metadata.Version); assert(s3Sent[0].input.Metadata.Timestamp > 0); @@ -310,16 +305,16 @@ describe('Version Put', () => { }); const env = {}; - const daCtx= {}; - const update = { org: 'myorg', key: '/a/b/c' }; + const daCtx= { bucket: 'b-b', org: 'myorg' }; + const update = { bucket: 'b-b', org: 'myorg', key: 'a/b/c' }; const resp = await putObjectWithVersion(env, daCtx, update, true); assert.equal(201, resp.status); assert(resp.metadata.id, 'The ID should be set'); assert.equal(1, s3Sent.length); - assert.equal('myorg-content', s3Sent[0].input.Bucket); + assert.equal('b-b', s3Sent[0].input.Bucket); assert(s3Sent[0].input.Metadata.ID); - assert.equal('/a/b/c', s3Sent[0].input.Metadata.Path); + assert.equal('a/b/c', s3Sent[0].input.Metadata.Path); assert(s3Sent[0].input.Metadata.Timestamp > 0); assert(s3Sent[0].input.Metadata.Version); }); @@ -380,8 +375,9 @@ describe('Version Put', () => { }; const env = {}; const ctx = { + bucket: 'mybucket', org: 'org123', - key: '/q/r/t' + key: 'q/r/t' }; const mockGetObject = async (e, u, h) => { @@ -436,8 +432,8 @@ describe('Version Put', () => { assert.equal(201, resp.status); assert.equal(1, s3INMSent.length); assert(s3INMSent[0].input.Body instanceof ReadableStream); - assert.equal('org123-content', s3INMSent[0].input.Bucket); - assert.equal('/q/r/t', s3INMSent[0].input.Metadata.Path); + assert.equal('mybucket', s3INMSent[0].input.Bucket); + assert.equal('q/r/t', s3INMSent[0].input.Metadata.Path); assert(s3INMSent[0].input.Metadata.Timestamp > 0); assert.equal('[{"email":"anonymous"}]', s3INMSent[0].input.Metadata.Users); assert.equal('foobar', s3INMSent[0].input.Metadata.Label); @@ -445,9 +441,9 @@ describe('Version Put', () => { assert.equal(1, s3Sent.length); assert(s3Sent[0].input.Body instanceof ReadableStream); - assert.equal('org123-content', s3Sent[0].input.Bucket); - assert.equal('/q/r/t', s3Sent[0].input.Key); - assert.equal('/q/r/t', s3Sent[0].input.Metadata.Path); + assert.equal('mybucket', s3Sent[0].input.Bucket); + assert.equal('org123/q/r/t', s3Sent[0].input.Key); + assert.equal('q/r/t', s3Sent[0].input.Metadata.Path); assert(s3Sent[0].input.Metadata.ID); assert(s3Sent[0].input.Metadata.Timestamp > 0); assert(s3Sent[0].input.Metadata.Version); @@ -550,11 +546,13 @@ describe('Version Put', () => { }); const update = { + org: 'o1', body: 'foobar', - key: '/mypath', + key: 'mypath', type: 'test/plain', } const ctx = { + org: 'o1', users: [{ email: 'hi@acme.com' }] } const resp = await putObjectWithVersion({}, ctx, update, true); @@ -571,8 +569,8 @@ describe('Version Put', () => { assert.equal('foobar', input2.Body); assert.equal(6, input2.ContentLength); assert.equal('test/plain', input2.ContentType); - assert.equal('/mypath', input2.Key); - assert.equal('/mypath', input2.Metadata.Path); + assert.equal('o1/mypath', input2.Key); + assert.equal('mypath', input2.Metadata.Path); assert.equal('[{"email":"hi@acme.com"}]', input2.Metadata.Users); assert(input2.Metadata.Version && input2.Metadata.Version !== 101); }); diff --git a/wrangler.toml b/wrangler.toml index bcf3389b..c508f786 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -2,7 +2,7 @@ name = "da-admin" main = "src/index.js" compatibility_date = "2024-11-11" -vars = { DA_COLLAB = "https://collab.da.live" } +vars = { DA_COLLAB = "https://collab.da.live", DA_BUCKET = "da-content" } services = [ { binding = "dacollab", service = "da-collab" } @@ -15,7 +15,7 @@ kv_namespaces = [ ] [env.stage] -vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.live" } +vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.live", DA_BUCKET = "da-content-stg" } services = [ { binding = "dacollab", service = "da-collab-stage" } @@ -29,7 +29,7 @@ kv_namespaces = [ [env.dev] -vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711" } +vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", DA_BUCKET = "da-content-dev" } kv_namespaces = [ { binding = "DA_AUTH", id = "21693f3b20f54fcbb850ddc8947335ba" }, { binding = "DA_CONFIG", id = "feb8618620bb4ca3a866f1c71adbe8ef" }, From baf850913afd47f23e0f2c86c4b18dd2daf81935 Mon Sep 17 00:00:00 2001 From: David Bosschaert Date: Fri, 13 Jun 2025 14:49:03 +0100 Subject: [PATCH 02/10] Fixes taken from https://github.com/adobe/da-admin/commit/3e06eae576943f9f2ba7f9b3cabf414a8985e911 --- .github/workflows/deploy-main.yaml | 3 ++- src/storage/object/copy.js | 7 +++++-- src/storage/object/move.js | 2 +- src/storage/object/put.js | 20 +------------------- src/storage/utils/list.js | 2 +- src/storage/utils/version.js | 18 ------------------ src/storage/version/put.js | 4 ++-- src/utils/daCtx.js | 2 +- wrangler.toml | 22 +++++++++++++++++++--- 9 files changed, 32 insertions(+), 48 deletions(-) diff --git a/.github/workflows/deploy-main.yaml b/.github/workflows/deploy-main.yaml index 87a6fcb8..107c2ff6 100644 --- a/.github/workflows/deploy-main.yaml +++ b/.github/workflows/deploy-main.yaml @@ -13,4 +13,5 @@ jobs: - name: Deploy uses: cloudflare/wrangler-action@v3 with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + apiToken: ${{ secrets.CLOUDFLARE_AUTH }} + accountId: ${{secrets.CLOUDFLARE_ACCOUNT}} diff --git a/src/storage/object/copy.js b/src/storage/object/copy.js index 517766be..625093f5 100644 --- a/src/storage/object/copy.js +++ b/src/storage/object/copy.js @@ -78,7 +78,10 @@ export const copyFile = async (config, env, daCtx, sourceKey, details, isRename) if (!isRename) { // This is a copy so just put the source into the target to keep the history. - const original = await getObject(env, { org: daCtx.org, key: sourceKey }); + const original = await getObject( + env, + { bucket: daCtx.bucket, org: daCtx.org, key: sourceKey }, + ); return /* await */ putObjectWithVersion(env, daCtx, { org: daCtx.org, key: Key, @@ -126,7 +129,7 @@ export default async function copyObject(env, daCtx, details, isRename) { let resp = await listCommand(daCtx, details, client); sourceKeys = resp.sourceKeys; if (resp.continuationToken) { - continuationToken = `copy-${details.source}-${details.destination}-${crypto.randomUUID()}`; + continuationToken = `copy-${daCtx.org}-${details.source}-${details.destination}-${crypto.randomUUID()}`; while (resp.continuationToken) { resp = await listCommand(daCtx, { continuationToken: resp.continuationToken }, client); remainingKeys.push(...resp.sourceKeys); diff --git a/src/storage/object/move.js b/src/storage/object/move.js index 5494f507..3216b6e1 100644 --- a/src/storage/object/move.js +++ b/src/storage/object/move.js @@ -48,7 +48,7 @@ export default async function moveObject(env, daCtx, details) { const resp = await client.send(command); const { Contents = [], NextContinuationToken } = resp; - sourceKeys.push(...Contents.map(({ Key }) => Key)); + sourceKeys.push(...Contents.map(({ Key }) => Key.replace(`${daCtx.org}/`, ''))); const movedLoad = sourceKeys .filter((key) => hasPermission(daCtx, key, 'write')) diff --git a/src/storage/object/put.js b/src/storage/object/put.js index 20cfa97c..5deafa8e 100644 --- a/src/storage/object/put.js +++ b/src/storage/object/put.js @@ -37,21 +37,6 @@ function buildInput({ }; } -function createBucketIfMissing(client) { - client.middlewareStack.add( - (next) => async (args) => { - // eslint-disable-next-line no-param-reassign - args.request.headers['cf-create-bucket-if-missing'] = 'true'; - return next(args); - }, - { - step: 'build', - name: 'createIfMissingMiddleware', - tags: ['METADATA', 'CREATE-BUCKET-IF-MISSING'], - }, - ); -} - /** * Check to see if the org is in the existing list of orgs * @@ -76,10 +61,7 @@ export default async function putObject(env, daCtx, obj) { // Only allow creating a new bucket for orgs and repos if (key.split('/').length <= 1) { - // await checkOrgIndex(env, org); - - // R2 ONLY FEATURE - createBucketIfMissing(client); + await checkOrgIndex(env, org); } const inputs = []; diff --git a/src/storage/utils/list.js b/src/storage/utils/list.js index 500c266d..2bbf91d6 100644 --- a/src/storage/utils/list.js +++ b/src/storage/utils/list.js @@ -106,7 +106,7 @@ export async function listCommand(daCtx, details, s3client) { const resp = await s3client.send(command); const { Contents = [], NextContinuationToken } = resp; - sourceKeys.push(...Contents.map(({ Key }) => Key)); + sourceKeys.push(...Contents.map(({ Key }) => Key.replace(`${daCtx.org}/`, ''))); return { sourceKeys, continuationToken: NextContinuationToken }; } diff --git a/src/storage/utils/version.js b/src/storage/utils/version.js index 72ae7cc5..bc3568d7 100644 --- a/src/storage/utils/version.js +++ b/src/storage/utils/version.js @@ -13,25 +13,8 @@ import { S3Client, } from '@aws-sdk/client-s3'; -export function createBucketIfMissing(client) { - client.middlewareStack.add( - (next) => async (args) => { - // eslint-disable-next-line no-param-reassign - args.request.headers['cf-create-bucket-if-missing'] = 'true'; - return next(args); - }, - { - step: 'build', - name: 'createIfMissingMiddleware', - tags: ['METADATA', 'CREATE-BUCKET-IF-MISSING'], - }, - ); - return client; -} - export function ifNoneMatch(config) { const client = new S3Client(config); - createBucketIfMissing(client); client.middlewareStack.add( (next) => async (args) => { // eslint-disable-next-line no-param-reassign @@ -49,7 +32,6 @@ export function ifNoneMatch(config) { export function ifMatch(config, match) { const client = new S3Client(config); - createBucketIfMissing(client); client.middlewareStack.add( (next) => async (args) => { // eslint-disable-next-line no-param-reassign diff --git a/src/storage/version/put.js b/src/storage/version/put.js index f6227ac0..abe76217 100644 --- a/src/storage/version/put.js +++ b/src/storage/version/put.js @@ -16,7 +16,7 @@ import { import getS3Config from '../utils/config.js'; import { - createBucketIfMissing, getUsersForMetadata, ifMatch, ifNoneMatch, + getUsersForMetadata, ifMatch, ifNoneMatch, } from '../utils/version.js'; import getObject from '../object/get.js'; @@ -39,7 +39,7 @@ export async function putVersion(config, { }, noneMatch = true) { const length = ContentLength ?? getContentLength(Body); - const client = noneMatch ? ifNoneMatch(config) : createBucketIfMissing(new S3Client(config)); + const client = noneMatch ? ifNoneMatch(config) : new S3Client(config); const input = { Bucket, Key: `${Org}/.da-versions/${ID}/${Version}.${Ext}`, Body, Metadata, ContentLength: length, }; diff --git a/src/utils/daCtx.js b/src/utils/daCtx.js index 82298d68..7993e578 100644 --- a/src/utils/daCtx.js +++ b/src/utils/daCtx.js @@ -33,7 +33,7 @@ export default async function getDaCtx(req, env) { const api = split.shift(); const fullKey = split.join('/'); const [org, ...parts] = split; - const bucket = env.DA_BUCKET; + const bucket = env.DA_BUCKET_NAME; // Set base details const daCtx = { diff --git a/wrangler.toml b/wrangler.toml index c508f786..dfbfe000 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -2,7 +2,7 @@ name = "da-admin" main = "src/index.js" compatibility_date = "2024-11-11" -vars = { DA_COLLAB = "https://collab.da.live", DA_BUCKET = "da-content" } +vars = { DA_COLLAB = "https://collab.da.live", DA_BUCKET_NAME = "da-content" } services = [ { binding = "dacollab", service = "da-collab" } @@ -14,8 +14,12 @@ kv_namespaces = [ { binding = "DA_JOBS", id = "0ba6184767b2470ea05a1d082f974134" } ] +r2_buckets = [ + { binding = "DA_CONTENT", bucket_name = "da-content" } +] + [env.stage] -vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.live", DA_BUCKET = "da-content-stg" } +vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.live", DA_BUCKET_NAME = "da-content-stage" } services = [ { binding = "dacollab", service = "da-collab-stage" } @@ -27,11 +31,23 @@ kv_namespaces = [ { binding = "DA_JOBS", id = "0ba6184767b2470ea05a1d082f974134" } ] +r2_buckets = [ + { binding = "DA_CONTENT", bucket_name = "da-content-stage" } +] [env.dev] -vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", DA_BUCKET = "da-content-dev" } +vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", DA_BUCKET_NAME = "da-content-dev" } + +services = [ + { binding = "dacollab", service = "da-collab-local" } +] + kv_namespaces = [ { binding = "DA_AUTH", id = "21693f3b20f54fcbb850ddc8947335ba" }, { binding = "DA_CONFIG", id = "feb8618620bb4ca3a866f1c71adbe8ef" }, { binding = "DA_JOBS", id = "0ba6184767b2470ea05a1d082f974134" } ] + +r2_buckets = [ + { binding = "DA_CONTENT", bucket_name = "da-content-dev" } +] From b18b8c3316f699da95451e161e72520f7656267d Mon Sep 17 00:00:00 2001 From: David Bosschaert Date: Fri, 13 Jun 2025 15:11:30 +0100 Subject: [PATCH 03/10] Fixes taken from https://github.com/adobe/da-admin/commit/842bccbe0735e29395475daba0084fbd5c5f0358 --- package-lock.json | 1478 +++++++++++++++++++++++++++---------- package.json | 2 +- src/routes/source.js | 2 +- src/storage/object/put.js | 19 - src/utils/auth.js | 7 +- wrangler.toml | 22 +- 6 files changed, 1105 insertions(+), 425 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb15b3e6..a55a96fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "eslint": "8.56.0", "esmock": "^2.6.4", "mocha": "^10.2.0", - "wrangler": "^3.107.3" + "wrangler": "^4.10.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -4384,27 +4384,40 @@ "dev": true }, "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", - "integrity": "sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.0.tgz", + "integrity": "sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==", "dev": true, - "license": "MIT OR Apache-2.0", "dependencies": { "mime": "^3.0.0" }, "engines": { - "node": ">=16.13" + "node": ">=18.0.0" + } + }, + "node_modules/@cloudflare/unenv-preset": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.3.1.tgz", + "integrity": "sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg==", + "dev": true, + "peerDependencies": { + "unenv": "2.0.0-rc.15", + "workerd": "^1.20250320.0" + }, + "peerDependenciesMeta": { + "workerd": { + "optional": true + } } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20250129.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250129.0.tgz", - "integrity": "sha512-M+xETVnl+xy2dfDDWmp0XXr2rttl70a6bljQygl0EmYmNswFTcYbQWCaBuNBo9kabU59rLKr4a/b3QZ07NoL/g==", + "version": "1.20250409.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20250409.0.tgz", + "integrity": "sha512-smA9yq77xsdQ1NMLhFz3JZxMHGd01lg0bE+X3dTFmIUs+hHskJ+HJ/IkMFInkCCeEFlUkoL4yO7ilaU/fin/xA==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -4414,14 +4427,13 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20250129.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250129.0.tgz", - "integrity": "sha512-c4PQUyIMp+bCMxZkAMBzXgTHjRZxeYCujDbb3staestqgRbenzcfauXsMd6np35ng+EE1uBgHNPV4+7fC0ZBfg==", + "version": "1.20250409.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20250409.0.tgz", + "integrity": "sha512-oLVcf+Y5Qun8JHcy1VcR/YnbA5U2ne0czh3XNhDqdHZFK8+vKeC7MnVPX+kEqQA3+uLcMM1/FsIDU1U4Na0h1g==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -4431,14 +4443,13 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20250129.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250129.0.tgz", - "integrity": "sha512-xJx8LwWFxsm5U3DETJwRuOmT5RWBqm4FmA4itYXvcEICca9pWJDB641kT4PnpypwDNmYOebhU7A+JUrCRucG0w==", + "version": "1.20250409.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20250409.0.tgz", + "integrity": "sha512-D31B4kdC3a0RD5yfpdIa89//kGHbYsYihZmejm1k4S4NHOho3MUDHAEh4aHtafQNXbZdydGHlSyiVYjTdQ9ILQ==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4448,14 +4459,13 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20250129.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250129.0.tgz", - "integrity": "sha512-dR//npbaX5p323huBVNIy5gaWubQx6CC3aiXeK0yX4aD5ar8AjxQFb2U/Sgjeo65Rkt53hJWqC7IwRpK/eOxrA==", + "version": "1.20250409.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20250409.0.tgz", + "integrity": "sha512-Sr59P0TREayil5OQ7kcbjuIn6L6OTSRLI91LKu0D8vi1hss2q9FUwBcwxg0+Yd/x+ty/x7IISiAK5QBkAMeITQ==", "cpu": [ "arm64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -4465,14 +4475,13 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20250129.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250129.0.tgz", - "integrity": "sha512-OeO+1nPj/ocAE3adFar/tRFGRkbCrBnrOYXq0FUBSpyNHpDdA9/U3PAw5CN4zvjfTnqXZfTxTFeqoruqzRzbtg==", + "version": "1.20250409.0", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20250409.0.tgz", + "integrity": "sha512-dK9I8zBX5rR7MtaaP2AhICQTEw3PVzHcsltN8o46w7JsbYlMvFOj27FfYH5dhs3IahgmIfw2e572QXW2o/dbpg==", "cpu": [ "x64" ], "dev": true, - "license": "Apache-2.0", "optional": true, "os": [ "win32" @@ -4486,7 +4495,6 @@ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -4499,12 +4507,21 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@emnapi/runtime": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.0.tgz", + "integrity": "sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/is-prop-valid": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", @@ -4526,32 +4543,74 @@ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", "dev": true }, - "node_modules/@esbuild-plugins/node-globals-polyfill": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", - "integrity": "sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "cpu": [ + "ppc64" + ], "dev": true, - "peerDependencies": { - "esbuild": "*" + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@esbuild-plugins/node-modules-polyfill": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.2.2.tgz", - "integrity": "sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==", + "node_modules/@esbuild/android-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "escape-string-regexp": "^4.0.0", - "rollup-plugin-node-polyfills": "^0.2.1" - }, - "peerDependencies": { - "esbuild": "*" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", - "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", "cpu": [ "arm64" ], @@ -4561,158 +4620,838 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/linux-arm": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@exodus/schemasafe": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", + "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", + "dev": true + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "dev": true + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" }, - "engines": { - "node": "*" + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@exodus/schemasafe": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz", - "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==", - "dev": true - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.10.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], "dev": true, + "optional": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "*" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.22" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -7478,14 +8217,10 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, "engines": { "node": ">=0.4.0" } @@ -7700,7 +8435,6 @@ "resolved": "https://registry.npmjs.org/as-table/-/as-table-1.0.55.tgz", "integrity": "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==", "dev": true, - "license": "MIT", "dependencies": { "printable-characters": "^1.0.42" } @@ -7984,6 +8718,20 @@ "node": ">=6" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8002,6 +8750,17 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -8014,13 +8773,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true, - "license": "MIT" - }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", @@ -8038,7 +8790,6 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8098,8 +8849,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", "integrity": "sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/debug": { "version": "4.3.4", @@ -8178,8 +8928,17 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, - "license": "MIT" + "optional": true, + "engines": { + "node": ">=8" + } }, "node_modules/diff": { "version": "5.0.0", @@ -8329,40 +9088,43 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.17.19", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", - "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.19", - "@esbuild/android-arm64": "0.17.19", - "@esbuild/android-x64": "0.17.19", - "@esbuild/darwin-arm64": "0.17.19", - "@esbuild/darwin-x64": "0.17.19", - "@esbuild/freebsd-arm64": "0.17.19", - "@esbuild/freebsd-x64": "0.17.19", - "@esbuild/linux-arm": "0.17.19", - "@esbuild/linux-arm64": "0.17.19", - "@esbuild/linux-ia32": "0.17.19", - "@esbuild/linux-loong64": "0.17.19", - "@esbuild/linux-mips64el": "0.17.19", - "@esbuild/linux-ppc64": "0.17.19", - "@esbuild/linux-riscv64": "0.17.19", - "@esbuild/linux-s390x": "0.17.19", - "@esbuild/linux-x64": "0.17.19", - "@esbuild/netbsd-x64": "0.17.19", - "@esbuild/openbsd-x64": "0.17.19", - "@esbuild/sunos-x64": "0.17.19", - "@esbuild/win32-arm64": "0.17.19", - "@esbuild/win32-ia32": "0.17.19", - "@esbuild/win32-x64": "0.17.19" + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" } }, "node_modules/escalade": { @@ -8741,12 +9503,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -8767,7 +9523,6 @@ "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-2.2.1.tgz", "integrity": "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" }, @@ -8775,6 +9530,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/exsolve": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.4.tgz", + "integrity": "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -9022,7 +9783,6 @@ "resolved": "https://registry.npmjs.org/get-source/-/get-source-2.0.12.tgz", "integrity": "sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==", "dev": true, - "license": "Unlicense", "dependencies": { "data-uri-to-buffer": "^2.0.0", "source-map": "^0.6.1" @@ -9080,8 +9840,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" + "dev": true }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.11", @@ -9356,6 +10115,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true, + "optional": true + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -9840,33 +10606,12 @@ "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -9905,7 +10650,6 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", "dev": true, - "license": "MIT", "bin": { "mime": "cli.js" }, @@ -9914,29 +10658,28 @@ } }, "node_modules/miniflare": { - "version": "3.20250129.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20250129.0.tgz", - "integrity": "sha512-qYlGEjMl/2kJdgNaztj4hpA64d6Dl79Lx/NL61p/v5XZRiWanBOTgkQqdPxCKZOj6KQnioqhC7lfd6jDXKSs2A==", + "version": "4.20250409.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20250409.0.tgz", + "integrity": "sha512-Hu02dYZvFR+MyrI57O6rSrOUTofcO9EIvcodgq2SAHzAeWSJw2E0oq9lylOrcckFwPMcwxUAb/cQN1LIoCyySw==", "dev": true, - "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", - "acorn": "^8.8.0", - "acorn-walk": "^8.2.0", - "exit-hook": "^2.2.1", - "glob-to-regexp": "^0.4.1", - "stoppable": "^1.1.0", - "undici": "^5.28.4", - "workerd": "1.20250129.0", - "ws": "^8.18.0", - "youch": "^3.2.2", - "zod": "^3.22.3" + "acorn": "8.14.0", + "acorn-walk": "8.3.2", + "exit-hook": "2.2.1", + "glob-to-regexp": "0.4.1", + "stoppable": "1.1.0", + "undici": "^5.28.5", + "workerd": "1.20250409.0", + "ws": "8.18.0", + "youch": "3.3.4", + "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" }, "engines": { - "node": ">=16.13" + "node": ">=18.0.0" } }, "node_modules/miniflare/node_modules/ws": { @@ -9944,7 +10687,6 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "dev": true, - "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -9982,26 +10724,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mlly": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", - "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.14.0", - "pathe": "^2.0.1", - "pkg-types": "^1.3.0", - "ufo": "^1.5.4" - } - }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", - "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", - "dev": true, - "license": "MIT" - }, "node_modules/mobx": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/mobx/-/mobx-6.11.0.tgz", @@ -10209,7 +10931,6 @@ "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", "dev": true, - "license": "MIT", "bin": { "mustache": "bin/mustache" } @@ -10493,11 +11214,10 @@ } }, "node_modules/ohash": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.4.tgz", - "integrity": "sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==", - "dev": true, - "license": "MIT" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true }, "node_modules/once": { "version": "1.4.0", @@ -10624,11 +11344,10 @@ "license": "MIT" }, "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, - "license": "MIT" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true }, "node_modules/perfect-scrollbar": { "version": "1.5.5", @@ -10654,25 +11373,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", - "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", - "dev": true, - "license": "MIT" - }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -10741,8 +11441,7 @@ "version": "1.0.42", "resolved": "https://registry.npmjs.org/printable-characters/-/printable-characters-1.0.42.tgz", "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", - "dev": true, - "license": "Unlicense" + "dev": true }, "node_modules/prismjs": { "version": "1.29.0", @@ -11022,36 +11721,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup-plugin-inject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", - "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1", - "magic-string": "^0.25.3", - "rollup-pluginutils": "^2.8.1" - } - }, - "node_modules/rollup-plugin-node-polyfills": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", - "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", - "dev": true, - "dependencies": { - "rollup-plugin-inject": "^3.0.0" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11140,13 +11809,10 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -11200,6 +11866,46 @@ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", "dev": true }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -11299,6 +12005,16 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/simple-websocket": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/simple-websocket/-/simple-websocket-9.1.0.tgz", @@ -11392,19 +12108,11 @@ "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead", - "dev": true - }, "node_modules/stacktracey": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/stacktracey/-/stacktracey-2.1.8.tgz", "integrity": "sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==", "dev": true, - "license": "Unlicense", "dependencies": { "as-table": "^1.0.36", "get-source": "^2.0.12" @@ -11421,7 +12129,6 @@ "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4", "npm": ">=6" @@ -11798,11 +12505,10 @@ } }, "node_modules/ufo": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", - "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", - "dev": true, - "license": "MIT" + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true }, "node_modules/uglify-js": { "version": "3.17.4", @@ -11833,11 +12539,10 @@ } }, "node_modules/undici": { - "version": "5.28.5", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz", - "integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==", + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", "dev": true, - "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -11846,16 +12551,15 @@ } }, "node_modules/unenv": { - "version": "2.0.0-rc.1", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.1.tgz", - "integrity": "sha512-PU5fb40H8X149s117aB4ytbORcCvlASdtF97tfls4BPIyj4PeVxvpSuy1jAptqYHqB0vb2w2sHvzM0XWcp2OKg==", + "version": "2.0.0-rc.15", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.15.tgz", + "integrity": "sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==", "dev": true, - "license": "MIT", "dependencies": { "defu": "^6.1.4", - "mlly": "^1.7.4", - "ohash": "^1.1.4", - "pathe": "^1.1.2", + "exsolve": "^1.0.4", + "ohash": "^2.0.11", + "pathe": "^2.0.3", "ufo": "^1.5.4" } }, @@ -11980,12 +12684,11 @@ "dev": true }, "node_modules/workerd": { - "version": "1.20250129.0", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250129.0.tgz", - "integrity": "sha512-Rprz8rxKTF4l6q/nYYI07lBetJnR19mGipx+u/a27GZOPKMG5SLIzA2NciZlJaB2Qd5YY+4p/eHOeKqo5keVWA==", + "version": "1.20250409.0", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20250409.0.tgz", + "integrity": "sha512-hqjX9swiHvrkOI3jlH9lrZsZRRv9lddUwcMe8Ua76jnyQz+brybWznNjHu8U5oswwcrFwvky1A4CcLjcLY31gQ==", "dev": true, "hasInstallScript": true, - "license": "Apache-2.0", "bin": { "workerd": "bin/workerd" }, @@ -11993,11 +12696,11 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20250129.0", - "@cloudflare/workerd-darwin-arm64": "1.20250129.0", - "@cloudflare/workerd-linux-64": "1.20250129.0", - "@cloudflare/workerd-linux-arm64": "1.20250129.0", - "@cloudflare/workerd-windows-64": "1.20250129.0" + "@cloudflare/workerd-darwin-64": "1.20250409.0", + "@cloudflare/workerd-darwin-arm64": "1.20250409.0", + "@cloudflare/workerd-linux-64": "1.20250409.0", + "@cloudflare/workerd-linux-arm64": "1.20250409.0", + "@cloudflare/workerd-windows-64": "1.20250409.0" } }, "node_modules/workerpool": { @@ -12007,34 +12710,33 @@ "dev": true }, "node_modules/wrangler": { - "version": "3.107.3", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-3.107.3.tgz", - "integrity": "sha512-N9ZMDHZ+DI5/B0yclr3bG57U/Zw7wSzGdpO2l7j6+3q8yUf+4Fk0Rvneo2t8rjLewKlvqgt9D9siFuo8MXJ55Q==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.10.0.tgz", + "integrity": "sha512-fTE4hZ79msEUt8+HEjl/8Q72haCyzPLu4PgrU3L81ysmjrMEdiYfUPqnvCkBUVtJvrDNdctTEimkufT1Y0ipNg==", "dev": true, - "license": "MIT OR Apache-2.0", "dependencies": { - "@cloudflare/kv-asset-handler": "0.3.4", - "@esbuild-plugins/node-globals-polyfill": "0.2.3", - "@esbuild-plugins/node-modules-polyfill": "0.2.2", + "@cloudflare/kv-asset-handler": "0.4.0", + "@cloudflare/unenv-preset": "2.3.1", "blake3-wasm": "2.1.5", - "esbuild": "0.17.19", - "miniflare": "3.20250129.0", + "esbuild": "0.24.2", + "miniflare": "4.20250409.0", "path-to-regexp": "6.3.0", - "unenv": "2.0.0-rc.1", - "workerd": "1.20250129.0" + "unenv": "2.0.0-rc.15", + "workerd": "1.20250409.0" }, "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=16.17.0" + "node": ">=18.0.0" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.2", + "sharp": "^0.33.5" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20250129.0" + "@cloudflare/workers-types": "^4.20250409.0" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -12095,12 +12797,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", @@ -12175,7 +12871,6 @@ "resolved": "https://registry.npmjs.org/youch/-/youch-3.3.4.tgz", "integrity": "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==", "dev": true, - "license": "MIT", "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", @@ -12183,11 +12878,10 @@ } }, "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.3.tgz", + "integrity": "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==", "dev": true, - "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index b95eec41..2e7b06db 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "eslint": "8.56.0", "esmock": "^2.6.4", "mocha": "^10.2.0", - "wrangler": "^3.107.3" + "wrangler": "^4.10.0" }, "lint-staged": { "*.js": "eslint", diff --git a/src/routes/source.js b/src/routes/source.js index c2ab5b8c..5d673eef 100644 --- a/src/routes/source.js +++ b/src/routes/source.js @@ -21,7 +21,7 @@ import { hasPermission } from '../utils/auth.js'; export async function deleteSource({ req, env, daCtx }) { if (!hasPermission(daCtx, daCtx.key, 'write')) return { status: 403 }; const details = await deleteHelper(req); - return /* await */ deleteObjects(env, daCtx, details); + return deleteObjects(env, daCtx, details); } export async function postSource({ req, env, daCtx }) { diff --git a/src/storage/object/put.js b/src/storage/object/put.js index 5deafa8e..0278746c 100644 --- a/src/storage/object/put.js +++ b/src/storage/object/put.js @@ -37,20 +37,6 @@ function buildInput({ }; } -/** - * Check to see if the org is in the existing list of orgs - * - * @param {Object} env the cloud provider environment - * @param {*} org the org associated with the bucket - * @returns null - */ -async function checkOrgIndex(env, org) { - const orgs = await env.DA_AUTH.get('orgs', { type: 'json' }); - if (orgs.some((existingOrg) => existingOrg.name === org)) return; - orgs.push({ name: org, created: new Date().toISOString() }); - await env.DA_AUTH.put('orgs', JSON.stringify(orgs)); -} - export default async function putObject(env, daCtx, obj) { const config = getS3Config(env); const client = new S3Client(config); @@ -59,11 +45,6 @@ export default async function putObject(env, daCtx, obj) { bucket, org, key, propsKey, } = daCtx; - // Only allow creating a new bucket for orgs and repos - if (key.split('/').length <= 1) { - await checkOrgIndex(env, org); - } - const inputs = []; let metadata = {}; diff --git a/src/utils/auth.js b/src/utils/auth.js index eb6be927..2456fd82 100644 --- a/src/utils/auth.js +++ b/src/utils/auth.js @@ -16,8 +16,13 @@ export async function logout({ daCtx, env }) { return { status: 200 }; } -export async function setUser(userId, expiration, headers, env) { +export async function setUser(userId, expiration, reqHeaders, env) { + const headers = new Headers(reqHeaders); + // Local Cloudflare Struggles with this property and IMS + headers.delete('cf-connecting-ip'); + let resp = await fetch(`${env.IMS_ORIGIN}/ims/profile/v1`, { headers }); + if (!resp.ok) { // Something went wrong - either with the connection or the token isn't valid // assume we are anon for now (but don't cache so we can try again next time) diff --git a/wrangler.toml b/wrangler.toml index dfbfe000..5c603f65 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -2,16 +2,16 @@ name = "da-admin" main = "src/index.js" compatibility_date = "2024-11-11" -vars = { DA_COLLAB = "https://collab.da.live", DA_BUCKET_NAME = "da-content" } +vars = { DA_COLLAB = "https://collab.da.page", DA_BUCKET_NAME = "da-content" } services = [ { binding = "dacollab", service = "da-collab" } ] kv_namespaces = [ - { binding = "DA_AUTH", id = "d6217b7c63ef40889583ba5c080c3908" }, - { binding = "DA_CONFIG", id = "feb8618620bb4ca3a866f1c71adbe8ef" }, - { binding = "DA_JOBS", id = "0ba6184767b2470ea05a1d082f974134" } + { binding = "DA_AUTH", id = "f8978fd2270f4c4fbcc8c9f04248a034" }, + { binding = "DA_CONFIG", id = "a20824737cd8499bae0f0d887ac6db21" }, + { binding = "DA_JOBS", id = "7056c4ab4e0c4604b6304607404eba1a" } ] r2_buckets = [ @@ -19,16 +19,16 @@ r2_buckets = [ ] [env.stage] -vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.live", DA_BUCKET_NAME = "da-content-stage" } +vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.page", DA_BUCKET_NAME = "da-content-stage" } services = [ { binding = "dacollab", service = "da-collab-stage" } ] kv_namespaces = [ - { binding = "DA_AUTH", id = "21693f3b20f54fcbb850ddc8947335ba" }, - { binding = "DA_CONFIG", id = "feb8618620bb4ca3a866f1c71adbe8ef" }, - { binding = "DA_JOBS", id = "0ba6184767b2470ea05a1d082f974134" } + { binding = "DA_AUTH", id = "f5cc4d0150ac48d5b56948b5d147c77e" }, + { binding = "DA_CONFIG", id = "3f6f6db5c27348fabee7c2a8ed39be17" }, + { binding = "DA_JOBS", id = "66265e68cb2b422d8dc7a34b9fe2b0c9" } ] r2_buckets = [ @@ -43,9 +43,9 @@ services = [ ] kv_namespaces = [ - { binding = "DA_AUTH", id = "21693f3b20f54fcbb850ddc8947335ba" }, - { binding = "DA_CONFIG", id = "feb8618620bb4ca3a866f1c71adbe8ef" }, - { binding = "DA_JOBS", id = "0ba6184767b2470ea05a1d082f974134" } + { binding = "DA_AUTH", id = "f5cc4d0150ac48d5b56948b5d147c77e" }, + { binding = "DA_CONFIG", id = "3f6f6db5c27348fabee7c2a8ed39be17" }, + { binding = "DA_JOBS", id = "66265e68cb2b422d8dc7a34b9fe2b0c9" } ] r2_buckets = [ From 5fe344543f235cf3662191a3daeb414434154dd6 Mon Sep 17 00:00:00 2001 From: David Bosschaert Date: Mon, 23 Jun 2025 15:07:17 +0100 Subject: [PATCH 04/10] Additional unit tests --- test/storage/object/copy.test.js | 16 ++++++++++------ test/storage/object/move.test.js | 8 ++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/test/storage/object/copy.test.js b/test/storage/object/copy.test.js index fe03594f..bea82069 100644 --- a/test/storage/object/copy.test.js +++ b/test/storage/object/copy.test.js @@ -185,7 +185,7 @@ describe('Object copy', () => { }); it('Copies a file for rename', async () => { - s3Mock.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'mydir/dir1/myfile.html' }] }); + s3Mock.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'testorg/mydir/dir1/myfile.html' }] }); const s3Sent = []; s3Mock.on(CopyObjectCommand).callsFake((input => { @@ -312,10 +312,14 @@ describe('Object copy', () => { middlewareStack = { add: () => {} }; }; const mockGetObject = async (e, u, h) => { - return { - body: 'original body', - contentLength: 42, - contentType: 'text/html', + if (u.bucket === 'mybucket' + && u.org === 'xorg' + && u.key === 'xsrc/abc/def.html') { + return { + body: 'original body', + contentLength: 42, + contentType: 'text/html', + } } }; const puwv = [] @@ -344,7 +348,7 @@ describe('Object copy', () => { fetch: (x) => { collabCalled.push(x); }, }, }; - const daCtx = { org: 'xorg' }; + const daCtx = { bucket: 'mybucket', org: 'xorg' }; daCtx.aclCtx = await getAclCtx(env, daCtx.org, daCtx.users, '/'); const details = { source: 'xsrc', diff --git a/test/storage/object/move.test.js b/test/storage/object/move.test.js index 2da9de8d..d7cad825 100644 --- a/test/storage/object/move.test.js +++ b/test/storage/object/move.test.js @@ -17,9 +17,9 @@ describe('Move', () => { const mockS3Client = class { send(c) { return { Contents: [ - { Key: 'somewhere/x.html' }, - { Key: 'somewhere/y.png' }, - { Key: 'somewhere/z.html' }, + { Key: 'myorg/somewhere/x.html' }, + { Key: 'myorg/somewhere/y.png' }, + { Key: 'myorg/somewhere/z.html' }, ]}; } }; @@ -59,7 +59,7 @@ describe('Move', () => { ]); const aclCtx = { pathLookup }; const users = [ { email: 'blah@foo.org' }]; - const ctx = { aclCtx, users, key: 'q.html' }; + const ctx = { org: 'myorg', aclCtx, users, key: 'q.html' }; const details = { source: 'somewhere', destination: 'nonpermdest' }; const resp = await moveObject({}, ctx, details); From d76b7fd69ccaf960fcb12defbeca60d2f7f56fb1 Mon Sep 17 00:00:00 2001 From: David Bosschaert Date: Tue, 24 Jun 2025 17:09:34 +0100 Subject: [PATCH 05/10] Remove unnecessary change --- src/routes/source.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/source.js b/src/routes/source.js index 5d673eef..c2ab5b8c 100644 --- a/src/routes/source.js +++ b/src/routes/source.js @@ -21,7 +21,7 @@ import { hasPermission } from '../utils/auth.js'; export async function deleteSource({ req, env, daCtx }) { if (!hasPermission(daCtx, daCtx.key, 'write')) return { status: 403 }; const details = await deleteHelper(req); - return deleteObjects(env, daCtx, details); + return /* await */ deleteObjects(env, daCtx, details); } export async function postSource({ req, env, daCtx }) { From 2318f6623f0415f465fdfe9fae110b9b1cb51bc0 Mon Sep 17 00:00:00 2001 From: Chris Millar Date: Tue, 8 Jul 2025 12:32:54 +0200 Subject: [PATCH 06/10] Respect vars set via UI --- wrangler.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/wrangler.toml b/wrangler.toml index 5c603f65..93b59b21 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,6 +1,7 @@ name = "da-admin" main = "src/index.js" compatibility_date = "2024-11-11" +keep_vars = true vars = { DA_COLLAB = "https://collab.da.page", DA_BUCKET_NAME = "da-content" } From 64b8fd7dee3608cebdaf618c778c8a1a1ae2b101 Mon Sep 17 00:00:00 2001 From: Chris Millar Date: Wed, 9 Jul 2025 10:26:47 +0200 Subject: [PATCH 07/10] Change bucket name --- wrangler.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wrangler.toml b/wrangler.toml index 93b59b21..75e5a3fa 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -3,7 +3,7 @@ main = "src/index.js" compatibility_date = "2024-11-11" keep_vars = true -vars = { DA_COLLAB = "https://collab.da.page", DA_BUCKET_NAME = "da-content" } +vars = { DA_COLLAB = "https://collab.da.page", AEM_BUCKET_NAME = "da-content" } services = [ { binding = "dacollab", service = "da-collab" } @@ -16,11 +16,11 @@ kv_namespaces = [ ] r2_buckets = [ - { binding = "DA_CONTENT", bucket_name = "da-content" } + { binding = "AEM_CONTENT", bucket_name = "aem-content" } ] [env.stage] -vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.page", DA_BUCKET_NAME = "da-content-stage" } +vars = { ENVIRONMENT = "stage", DA_COLLAB = "https://collab.da.page", AEM_BUCKET_NAME = "aem-content-stage" } services = [ { binding = "dacollab", service = "da-collab-stage" } @@ -33,11 +33,11 @@ kv_namespaces = [ ] r2_buckets = [ - { binding = "DA_CONTENT", bucket_name = "da-content-stage" } + { binding = "AEM_CONTENT", bucket_name = "aem-content-stage" } ] [env.dev] -vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", DA_BUCKET_NAME = "da-content-dev" } +vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", AEM_BUCKET_NAME = "da-content-dev" } services = [ { binding = "dacollab", service = "da-collab-local" } @@ -50,5 +50,5 @@ kv_namespaces = [ ] r2_buckets = [ - { binding = "DA_CONTENT", bucket_name = "da-content-dev" } + { binding = "AEM_CONTENT", bucket_name = "aem-content-dev" } ] From abf3af3c19c5a847429529e7de496e27d3f65dc1 Mon Sep 17 00:00:00 2001 From: Chris Millar Date: Wed, 9 Jul 2025 10:42:17 +0200 Subject: [PATCH 08/10] Update AEM_BUCKET_NAME --- src/utils/daCtx.js | 2 +- wrangler.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/daCtx.js b/src/utils/daCtx.js index 7993e578..bab8d229 100644 --- a/src/utils/daCtx.js +++ b/src/utils/daCtx.js @@ -33,7 +33,7 @@ export default async function getDaCtx(req, env) { const api = split.shift(); const fullKey = split.join('/'); const [org, ...parts] = split; - const bucket = env.DA_BUCKET_NAME; + const bucket = env.AEM_BUCKET_NAME; // Set base details const daCtx = { diff --git a/wrangler.toml b/wrangler.toml index 75e5a3fa..88b30f7e 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -3,7 +3,7 @@ main = "src/index.js" compatibility_date = "2024-11-11" keep_vars = true -vars = { DA_COLLAB = "https://collab.da.page", AEM_BUCKET_NAME = "da-content" } +vars = { DA_COLLAB = "https://collab.da.page", AEM_BUCKET_NAME = "aem-content" } services = [ { binding = "dacollab", service = "da-collab" } @@ -37,7 +37,7 @@ r2_buckets = [ ] [env.dev] -vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", AEM_BUCKET_NAME = "da-content-dev" } +vars = { ENVIRONMENT = "dev", DA_COLLAB = "http://localhost:4711", AEM_BUCKET_NAME = "aem-content-dev" } services = [ { binding = "dacollab", service = "da-collab-local" } From 89c215efd79aafb91c9855e2683f732a961e2ba9 Mon Sep 17 00:00:00 2001 From: kptdobe Date: Tue, 19 Aug 2025 11:06:18 +0200 Subject: [PATCH 09/10] chore: missing bucket in get test --- test/storage/object/get.test.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test/storage/object/get.test.js b/test/storage/object/get.test.js index 4f41c17c..381f531c 100644 --- a/test/storage/object/get.test.js +++ b/test/storage/object/get.test.js @@ -14,7 +14,6 @@ import assert from 'node:assert'; import { S3Client, GetObjectCommand, - HeadObjectCommand, } from '@aws-sdk/client-s3'; import { mockClient } from 'aws-sdk-client-mock'; import esmock from 'esmock'; @@ -25,6 +24,9 @@ import getObject from '../../../src/storage/object/get.js'; const ORG = 'adobe'; const KEY = 'wknd/index.html'; +const BUCKET = `root-bucket`; + +const S3_KEY = `${ORG}/${KEY}`; describe('Get Object', () => { beforeEach(() => { @@ -39,8 +41,8 @@ describe('Get Object', () => { const ETag = 'etag123'; s3Mock .on(GetObjectCommand, { - Bucket: `${ORG}-content`, - Key: KEY, + Bucket: BUCKET, + Key: S3_KEY, }) .resolves({ Body, @@ -50,7 +52,7 @@ describe('Get Object', () => { ETag, $metadata: { httpStatusCode: 200 }, }); - const resp = await getObject({}, { org: ORG, key: KEY }, false); + const resp = await getObject({}, { bucket: BUCKET, org: ORG, key: KEY }, false); assert.strictEqual(resp.status, 200); assert.strictEqual(resp.contentType, ContentType); assert.strictEqual(resp.contentLength, ContentLength); @@ -94,7 +96,7 @@ describe('Get Object', () => { }; }; - const resp = await getObjectWithMocks({}, { org: ORG, key: KEY }, true); + const resp = await getObjectWithMocks({}, { bucket: BUCKET, org: ORG, key: KEY }, true); assert.strictEqual(resp.status, 200); assert.strictEqual(resp.contentType, 'text/html'); assert.strictEqual(resp.contentLength, '123'); @@ -111,12 +113,12 @@ describe('Get Object', () => { const error = new Error('Not found'); error.$metadata = { httpStatusCode: 404 }; s3Mock.on(GetObjectCommand, { - Bucket: `${ORG}-content`, - Key: KEY, + Bucket: BUCKET, + Key: S3_KEY, }).rejects(error); // Import getObject directly for head=false (no esmock needed) const getObject = (await import('../../../src/storage/object/get.js')).default; - const resp = await getObject({}, { org: ORG, key: KEY }, false); + const resp = await getObject({}, { bucket: BUCKET, org: ORG, key: KEY }, false); assert.strictEqual(resp.status, 404); assert.strictEqual(resp.body, ''); assert.strictEqual(resp.contentLength, 0); From 276739ba25340a84abccf22a933b4ddf401898f8 Mon Sep 17 00:00:00 2001 From: Chris Millar Date: Tue, 26 Aug 2025 12:29:11 -0600 Subject: [PATCH 10/10] More test fixes --- src/storage/utils/list.js | 5 ++++- test/storage/object/copy.test.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/storage/utils/list.js b/src/storage/utils/list.js index 4020bc73..7e9acc26 100644 --- a/src/storage/utils/list.js +++ b/src/storage/utils/list.js @@ -106,7 +106,10 @@ export async function listCommand(daCtx, details, s3client) { const resp = await s3client.send(command); const { Contents = [], NextContinuationToken } = resp; - sourceKeys.push(...Contents.map(({ Key }) => Key.replace(`${daCtx.org}/`, ''))); + + console.log(Contents); + + sourceKeys.push(...Contents.map(({ Key }) => Key)); return { sourceKeys, continuationToken: NextContinuationToken }; } diff --git a/test/storage/object/copy.test.js b/test/storage/object/copy.test.js index bea82069..6a455b8b 100644 --- a/test/storage/object/copy.test.js +++ b/test/storage/object/copy.test.js @@ -185,7 +185,7 @@ describe('Object copy', () => { }); it('Copies a file for rename', async () => { - s3Mock.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'testorg/mydir/dir1/myfile.html' }] }); + s3Mock.on(ListObjectsV2Command).resolves({ Contents: [{ Key: 'mydir/dir1/myfile.html' }] }); const s3Sent = []; s3Mock.on(CopyObjectCommand).callsFake((input => {