@flaghoist/adapter-cloudflare-kv 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +1 -1
- package/package.json +17 -2
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @flaghoist/adapter-cloudflare-kv
|
|
2
|
+
|
|
3
|
+
Store Flaghoist flags in Cloudflare Workers KV. This is the default storage for a Flaghoist deploy,
|
|
4
|
+
and the one the CLI picks unless you tell it otherwise.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install @flaghoist/adapter-cloudflare-kv
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { cloudflareKV } from '@flaghoist/adapter-cloudflare-kv'
|
|
12
|
+
import { createFlagServer } from '@flaghoist/server'
|
|
13
|
+
|
|
14
|
+
export default createFlagServer((env) => ({
|
|
15
|
+
storage: cloudflareKV(env.FLAGS),
|
|
16
|
+
auth: {/* ... */},
|
|
17
|
+
}))
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`FLAGS` is a KV namespace binding in your `wrangler.toml`. If you are using the CLI, `flaghoist
|
|
21
|
+
deploy` creates the namespace and fills in its id for you. By hand it is:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx wrangler kv namespace create FLAGS
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Sharing a namespace
|
|
28
|
+
|
|
29
|
+
By default Flaghoist writes each flag under its own key, so a flag called `checkout` is stored as
|
|
30
|
+
`checkout`. That keeps the namespace readable when you browse it in the Cloudflare dashboard.
|
|
31
|
+
|
|
32
|
+
If the namespace holds anything besides Flaghoist's flags, give it a prefix:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
cloudflareKV(env.FLAGS, { prefix: 'flag:' })
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Without one, `list()` reads every key in the namespace. Values that are not flags are skipped rather
|
|
39
|
+
than showing up as broken rows, so nothing breaks, but you pay a read for each one.
|
|
40
|
+
|
|
41
|
+
Changing the prefix on a running deployment hides the flags written under the old one. They are
|
|
42
|
+
still in KV, the adapter is just no longer looking there.
|
|
43
|
+
|
|
44
|
+
Worth knowing: KV is eventually consistent. A flag you just changed can take a few seconds to reach
|
|
45
|
+
every edge location, which is fine for flags and would not be fine for a bank balance.
|
|
46
|
+
|
|
47
|
+
Storage is an interface, so moving to Redis or Postgres later is a one line change in your server
|
|
48
|
+
config.
|
|
49
|
+
|
|
50
|
+
## Status
|
|
51
|
+
|
|
52
|
+
Pre-alpha, built and maintained by one person. The API can still change without notice, and
|
|
53
|
+
production use is not recommended yet. If you try it and something breaks, an issue is genuinely
|
|
54
|
+
useful.
|
|
55
|
+
|
|
56
|
+
Apache-2.0. Part of [Flaghoist](https://github.com/flaghoist/flaghoist).
|
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,7 @@ function safeParse(raw) {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
function cloudflareKV(kv, options = {}) {
|
|
36
|
-
const prefix = options.prefix ?? "
|
|
36
|
+
const prefix = options.prefix ?? "";
|
|
37
37
|
return {
|
|
38
38
|
async get(key) {
|
|
39
39
|
return safeParse(await kv.get(prefix + key, { type: "text" }));
|
package/dist/index.d.cts
CHANGED
|
@@ -24,11 +24,21 @@ interface KVNamespaceLike {
|
|
|
24
24
|
}>;
|
|
25
25
|
}
|
|
26
26
|
interface CloudflareKVOptions {
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Namespace every key Flaghoist writes, and ignore anything without it when listing.
|
|
29
|
+
*
|
|
30
|
+
* Empty by default, so a flag called `checkout` is stored under `checkout` and the namespace
|
|
31
|
+
* reads the way you expect when browsing it in the Cloudflare dashboard. Set this when the
|
|
32
|
+
* namespace holds anything besides Flaghoist's flags: without it `list()` reads every key in the
|
|
33
|
+
* namespace. Values that are not flags are skipped rather than surfacing as broken rows, but you
|
|
34
|
+
* still pay a read for each one.
|
|
35
|
+
*
|
|
36
|
+
* @example cloudflareKV(env.FLAGS, { prefix: 'flag:' })
|
|
37
|
+
*/
|
|
28
38
|
prefix?: string;
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
|
-
* A StorageAdapter backed by Cloudflare Workers KV
|
|
41
|
+
* A StorageAdapter backed by Cloudflare Workers KV, the default Flaghoist storage backend.
|
|
32
42
|
* Flags are stored as JSON under a configurable key prefix, and every read is re-validated
|
|
33
43
|
* through `parseFlag`, so tampered or corrupted data degrades to "flag ignored" rather than a
|
|
34
44
|
* crash or a malformed evaluation.
|
package/dist/index.d.ts
CHANGED
|
@@ -24,11 +24,21 @@ interface KVNamespaceLike {
|
|
|
24
24
|
}>;
|
|
25
25
|
}
|
|
26
26
|
interface CloudflareKVOptions {
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Namespace every key Flaghoist writes, and ignore anything without it when listing.
|
|
29
|
+
*
|
|
30
|
+
* Empty by default, so a flag called `checkout` is stored under `checkout` and the namespace
|
|
31
|
+
* reads the way you expect when browsing it in the Cloudflare dashboard. Set this when the
|
|
32
|
+
* namespace holds anything besides Flaghoist's flags: without it `list()` reads every key in the
|
|
33
|
+
* namespace. Values that are not flags are skipped rather than surfacing as broken rows, but you
|
|
34
|
+
* still pay a read for each one.
|
|
35
|
+
*
|
|
36
|
+
* @example cloudflareKV(env.FLAGS, { prefix: 'flag:' })
|
|
37
|
+
*/
|
|
28
38
|
prefix?: string;
|
|
29
39
|
}
|
|
30
40
|
/**
|
|
31
|
-
* A StorageAdapter backed by Cloudflare Workers KV
|
|
41
|
+
* A StorageAdapter backed by Cloudflare Workers KV, the default Flaghoist storage backend.
|
|
32
42
|
* Flags are stored as JSON under a configurable key prefix, and every read is re-validated
|
|
33
43
|
* through `parseFlag`, so tampered or corrupted data degrades to "flag ignored" rather than a
|
|
34
44
|
* crash or a malformed evaluation.
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ function safeParse(raw) {
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
function cloudflareKV(kv, options = {}) {
|
|
12
|
-
const prefix = options.prefix ?? "
|
|
12
|
+
const prefix = options.prefix ?? "";
|
|
13
13
|
return {
|
|
14
14
|
async get(key) {
|
|
15
15
|
return safeParse(await kv.get(prefix + key, { type: "text" }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flaghoist/adapter-cloudflare-kv",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Cloudflare Workers KV StorageAdapter for Flaghoist — the default storage backend.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"node": ">=20"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@flaghoist/core": "0.1.
|
|
30
|
+
"@flaghoist/core": "0.1.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@flaghoist/adapter-conformance": "0.0.0"
|
|
@@ -35,6 +35,21 @@
|
|
|
35
35
|
"publishConfig": {
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"feature-flags",
|
|
40
|
+
"storage",
|
|
41
|
+
"cloudflare",
|
|
42
|
+
"workers-kv"
|
|
43
|
+
],
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/flaghoist/flaghoist.git",
|
|
47
|
+
"directory": "packages/adapters/cloudflare-kv"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/flaghoist/flaghoist#readme",
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/flaghoist/flaghoist/issues"
|
|
52
|
+
},
|
|
38
53
|
"scripts": {
|
|
39
54
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
40
55
|
"test": "vitest run --passWithNoTests",
|