Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
ae7d8c9
prototype
dferber90 Jun 16, 2025
7134639
add cli command to prepare edge configs
dferber90 Jun 16, 2025
b1edc83
finalize cli
dferber90 Jun 16, 2025
29180a7
fix eslint
dferber90 Jun 16, 2025
d2f2c8d
add changeset
dferber90 Jun 16, 2025
4795cd8
enable consistentRead for build time fetching
dferber90 Jul 12, 2025
05a15a4
wip
dferber90 Jul 25, 2025
a5fe779
fix types
dferber90 Jul 25, 2025
2656808
wip
dferber90 Jul 25, 2025
3f96eb9
add controller
dferber90 Jul 28, 2025
41ae184
remove unused deps
dferber90 Jul 28, 2025
7eb3284
add types
dferber90 Jul 28, 2025
efebad5
prepare
dferber90 Jul 28, 2025
0e098ff
enhanced-fetch
dferber90 Jul 28, 2025
8be32dd
clean up
dferber90 Jul 28, 2025
04daec8
rename source
dferber90 Jul 28, 2025
48077bb
add test
dferber90 Jul 28, 2025
622790d
use dev cache
dferber90 Jul 29, 2025
a7d7685
remove shouldUseDevelopmentCache boolean
dferber90 Jul 29, 2025
406a1d7
start enhanced-fetch
dferber90 Jul 29, 2025
225c6fc
prepare more
dferber90 Jul 29, 2025
956a5ce
step
dferber90 Jul 30, 2025
ad0e048
step
dferber90 Jul 30, 2025
70f6612
ensure cached response body
dferber90 Jul 30, 2025
54233ce
fix tests
dferber90 Jul 30, 2025
1ad14c2
add more tests
dferber90 Jul 30, 2025
3daaa91
remove responseTimestamp
dferber90 Jul 30, 2025
8e09826
simplify
dferber90 Jul 30, 2025
d792d8c
fix fetch deduping tests
dferber90 Jul 30, 2025
32837c2
implement and test getAll
dferber90 Jul 31, 2025
701f167
async
dferber90 Jul 31, 2025
5180fbc
add HEAD and has()
dferber90 Jul 31, 2025
8ddba8b
more tests
dferber90 Jul 31, 2025
95552e4
refactor with ai
dferber90 Aug 1, 2025
c8d1d9c
remove digest
dferber90 Aug 1, 2025
c1d17bc
handle edge cases
dferber90 Aug 1, 2025
e796307
remove old implementation
dferber90 Aug 1, 2025
47e3a26
convert index
dferber90 Aug 1, 2025
6626f71
rm edge-config-fs
dferber90 Aug 1, 2025
922f362
fix 500 handling
dferber90 Aug 1, 2025
22f147a
wip
dferber90 Aug 1, 2025
56f6770
rename staleThreshold to maxStale
dferber90 Aug 1, 2025
5ec3243
fix controller
dferber90 Aug 1, 2025
b194a1e
rename and comment
dferber90 Aug 2, 2025
649b6cd
refactor
dferber90 Aug 2, 2025
e2ea72d
wip
dferber90 Aug 2, 2025
220bc43
implement getMultiple
dferber90 Aug 2, 2025
fe09c29
add note about missing tests
dferber90 Aug 2, 2025
654a275
more tests
dferber90 Aug 2, 2025
d037f11
add tests
dferber90 Aug 2, 2025
4e58e28
add more tests
dferber90 Aug 3, 2025
503a2fa
do not return exists from getMultiple
dferber90 Aug 3, 2025
a82af8f
add edge config cache test
dferber90 Aug 3, 2025
6a1e655
add preloading
dferber90 Aug 3, 2025
d80061a
imporve cli
dferber90 Aug 3, 2025
d650bf3
rename methods
dferber90 Aug 4, 2025
82e0e8f
deal with proxy not sending headers for 304s#
dferber90 Aug 4, 2025
87b7b14
use the real getUpdatedAt
dferber90 Aug 4, 2025
a6387d2
upgrade tests
dferber90 Aug 4, 2025
82141e3
fix embedding
dferber90 Aug 4, 2025
b20e007
increase beta
dferber90 Aug 4, 2025
4af5939
fix tests
dferber90 Aug 5, 2025
2478095
return cache status
dferber90 Aug 5, 2025
461b41c
fix preload usage
dferber90 Aug 6, 2025
f0fe3a6
after
dferber90 Aug 6, 2025
82aac1f
add comment
dferber90 Aug 7, 2025
f505f78
emit to relative folder
dferber90 Aug 20, 2025
1ae7a7f
wip
dferber90 Sep 11, 2025
22041f3
rename back to simplify diff
dferber90 Sep 26, 2025
57d7f6e
wip
dferber90 Sep 26, 2025
f301f87
wip
dferber90 Sep 26, 2025
538e231
refactor?
dferber90 Sep 27, 2025
42f0f9b
wip
dferber90 Sep 27, 2025
972365e
refactor
dferber90 Sep 29, 2025
08a945b
extract cache-manager
dferber90 Sep 29, 2025
eb5c39c
wip
dferber90 Sep 30, 2025
d6c79fe
wip
dferber90 Sep 30, 2025
eb1b0b1
wip
dferber90 Oct 1, 2025
bd37201
wip
dferber90 Oct 1, 2025
b0a2330
mget → getMany; all → getAll
dferber90 Oct 1, 2025
44166d2
wip
dferber90 Oct 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/legal-walls-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vercel/edge-config': minor
---

use consistent edge config version during builds
7 changes: 7 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"permissions": {
"allow": ["Bash(pnpm jest:*)"],
"deny": [],
"ask": []
}
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ npm-debug.log
.turbo
.DS_Store
.vscode
.claude

packages/edge-config/DEVELOPMENT.md
89 changes: 89 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Architecture

This is a pnpm monorepo containing the Vercel Storage packages:

- `@vercel/blob` - Fast object storage client
- `@vercel/kv` - Redis-compatible key-value store client
- `@vercel/edge-config` - Ultra-low latency edge data client
- `@vercel/postgres` - PostgreSQL database client
- `@vercel/postgres-kysely` - Kysely ORM wrapper for @vercel/postgres

The packages are designed to work in multiple JavaScript environments:

- Node.js (serverless and server environments)
- Edge runtime (Vercel Edge Functions)
- Browser environments

Each package includes environment-specific implementations and comprehensive test coverage across all supported runtimes.

## Common Commands

### Development & Testing

- `pnpm build` - Build all packages using Turbo
- `pnpm test` - Run all tests across packages
- `pnpm lint` - Lint all packages with ESLint (max warnings: 0)
- `pnpm type-check` - TypeScript type checking across packages
- `pnpm prettier-check` - Check code formatting
- `pnpm prettier-fix` - Fix code formatting

### Package-specific Commands

Run commands in specific packages using `-F` flag:

- `pnpm -F @vercel/blob test` - Test blob package only
- `pnpm -F @vercel/blob build` - Build blob package only

### Testing Strategy

Each package includes multi-environment testing:

- `test:node` - Node.js environment tests
- `test:edge` - Edge runtime environment tests
- `test:browser` - Browser environment tests (for applicable packages)
- `test:common` - Tests that run in multiple environments

### Integration Testing

- `pnpm run-integration` - Start the Next.js integration test suite
- `pnpm integration-test` - Run Playwright integration tests

## Key Files & Structure

### Package Structure

Each package follows consistent structure:

- `src/` - Source TypeScript files
- `dist/` - Built output (CJS + ESM)
- `tsconfig.json` - TypeScript configuration extending workspace config
- `tsup.config.js` - Build configuration
- Individual test files with environment suffixes (`.node.test.ts`, `.edge.test.ts`, etc.)

### Workspace Configuration

- `pnpm-workspace.yaml` - Defines workspace packages
- `turbo.json` - Task orchestration and caching
- `tooling/` - Shared ESLint and TypeScript configurations
- `test/next/` - Integration test suite using Next.js + Playwright

### Environment Handling

Packages use different strategies for multi-environment support:

- Browser-specific shims (e.g., `crypto-browser.js`, `stream-browser.js`)
- Conditional exports in package.json for different environments
- Environment-specific test suites using different Jest environments

## Development Notes

- Uses TypeScript with strict configuration
- ESLint extends @vercel/style-guide with zero warnings policy
- Jest for unit testing with @edge-runtime/jest-environment for edge testing
- Playwright for integration testing
- Changesets for version management and releases
- All packages support both CommonJS and ES modules via dual build
3 changes: 0 additions & 3 deletions packages/edge-config-fs/.eslintrc.js

This file was deleted.

4 changes: 0 additions & 4 deletions packages/edge-config-fs/README.md

This file was deleted.

5 changes: 0 additions & 5 deletions packages/edge-config-fs/index.edge.cjs

This file was deleted.

3 changes: 0 additions & 3 deletions packages/edge-config-fs/index.edge.js

This file was deleted.

3 changes: 0 additions & 3 deletions packages/edge-config-fs/index.node.cjs

This file was deleted.

1 change: 0 additions & 1 deletion packages/edge-config-fs/index.node.js

This file was deleted.

29 changes: 0 additions & 29 deletions packages/edge-config-fs/package.json

This file was deleted.

1 change: 0 additions & 1 deletion packages/edge-config-fs/types.d.ts

This file was deleted.

1 change: 1 addition & 0 deletions packages/edge-config/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
stores/ecfg_*.json
1 change: 1 addition & 0 deletions packages/edge-config/.node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
21 changes: 16 additions & 5 deletions packages/edge-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vercel/edge-config",
"version": "1.4.0",
"version": "2.0.0-beta.802",
"description": "Ultra-low latency data at the edge",
"homepage": "https://vercel.com",
"repository": {
Expand All @@ -12,13 +12,23 @@
"sideEffects": false,
"type": "module",
"exports": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"./stores": {
"import": "./stores",
"require": "./stores"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"bin": {
"edge-config": "./dist/cli.js"
},
"files": [
"dist"
"dist",
"stores"
],
"scripts": {
"build": "tsup",
Expand All @@ -41,7 +51,8 @@
"testEnvironment": "node"
},
"dependencies": {
"@vercel/edge-config-fs": "workspace:*"
"@vercel/functions": "^2.2.5",
"eventsource-client": "1.2.0"
},
"devDependencies": {
"@changesets/cli": "2.28.1",
Expand Down
78 changes: 78 additions & 0 deletions packages/edge-config/src/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env node

/*
* Reads all connected Edge Configs and emits them to the stores folder
* that can be accessed at runtime by the mockable-import function.
*
* Attaches the updatedAt timestamp from the header to the emitted file, since
* the endpoint does not currently include it in the response body.
*/

import { writeFile, mkdir } from 'node:fs/promises';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { Connection, EmbeddedEdgeConfig } from './types';
import { parseConnectionString } from './utils';

// Get the directory where this CLI script is located
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// Write to the stores folder relative to the package root
// This works both in development and when installed as a dependency
const getStoresDir = (): string => {
// In development: packages/edge-config/src/cli.ts -> packages/edge-config/stores/
// When installed: node_modules/@vercel/edge-config/dist/cli.cjs -> node_modules/@vercel/edge-config/stores/
return join(__dirname, '..', 'stores');
};

async function main(): Promise<void> {
const connections = Object.values(process.env).reduce<Connection[]>(
(acc, value) => {
if (typeof value !== 'string') return acc;
const data = parseConnectionString(value);

if (data) {
acc.push(data);
}

return acc;
},
[],
);

const storesDir = getStoresDir();
// eslint-disable-next-line no-console -- This is a CLI tool
console.log(`Creating stores directory: ${storesDir}`);
await mkdir(storesDir, { recursive: true });

await Promise.all(
connections.map(async (connection) => {
const { data, updatedAt } = await fetch(connection.baseUrl, {
headers: {
authorization: `Bearer ${connection.token}`,
// consistentRead
'x-edge-config-min-updated-at': `${Number.MAX_SAFE_INTEGER}`,
},
}).then(async (res) => {
const ts = res.headers.get('x-edge-config-updated-at');

return {
data: (await res.json()) as EmbeddedEdgeConfig,
updatedAt: ts ? Number(ts) : undefined,
};
});

const outputPath = join(storesDir, `${connection.id}.json`);
await writeFile(outputPath, JSON.stringify({ ...data, updatedAt }));
// eslint-disable-next-line no-console -- This is a CLI tool
console.log(`Emitted Edge Config for ${connection.id} to: ${outputPath}`);
}),
);
}

main().catch((error) => {
// eslint-disable-next-line no-console -- This is a CLI tool
console.error('@vercel/edge-config: prepare failed', error);
process.exit(1);
});
Loading