diff --git a/src/server.test.ts b/src/server.test.ts index ca64c93..0e7264a 100644 --- a/src/server.test.ts +++ b/src/server.test.ts @@ -5,7 +5,7 @@ import semver from 'semver' import tmp from 'tmp-promise' import { test, expect, beforeAll, afterEach } from 'vitest' -import { getStore } from './main.js' +import { getDeployStore, getStore } from './main.js' import { BlobsServer } from './server.js' beforeAll(async () => { @@ -286,3 +286,28 @@ test('Lists entries', async () => { expect(parachutesSongs2.directories).toEqual([]) }) + +test('Works with a deploy-scoped store', async () => { + const deployID = '655f77a1b48f470008e5879a' + const directory = await tmp.dir() + const server = new BlobsServer({ + directory: directory.path, + token, + }) + const { port } = await server.start() + + const store = getDeployStore({ + deployID, + edgeURL: `http://localhost:${port}`, + token, + siteID, + }) + const key = 'my-key' + + await store.set(key, 'value 1 for store 1') + + expect(await store.get(key)).toBe('value 1 for store 1') + + await server.stop() + await fs.rm(directory.path, { force: true, recursive: true }) +}) diff --git a/src/server.ts b/src/server.ts index bc366fe..9479ba5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -3,6 +3,7 @@ import { createReadStream, createWriteStream, promises as fs } from 'node:fs' import http from 'node:http' import { tmpdir } from 'node:os' import { dirname, join, relative, resolve, sep } from 'node:path' +import { platform } from 'node:process' import { ListResponse } from './backend/list.ts' import { decodeMetadata, encodeMetadata, METADATA_HEADER_INTERNAL } from './metadata.ts' @@ -301,12 +302,15 @@ export class BlobsServer { return {} } - const [, siteID, storeName, ...key] = url.pathname.split('/') + const [, siteID, rawStoreName, ...key] = url.pathname.split('/') - if (!siteID || !storeName) { + if (!siteID || !rawStoreName) { return {} } + // On Windows, file paths can't include the `:` character, which is used in + // deploy-scoped stores. + const storeName = platform === 'win32' ? encodeURIComponent(rawStoreName) : rawStoreName const rootPath = resolve(this.directory, 'entries', siteID, storeName) const dataPath = resolve(rootPath, ...key) const metadataPath = resolve(this.directory, 'metadata', siteID, storeName, ...key)