Skip to content

Commit

Permalink
feat: support maxDepth for getKeys (#547)
Browse files Browse the repository at this point in the history
  • Loading branch information
43081j authored Dec 28, 2024
1 parent 7e912b0 commit 990e776
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/drivers/netlify-blobs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createError, createRequiredError, defineDriver } from "./utils";
import { type GetKeysOptions } from "../types";
import { getStore, getDeployStore } from "@netlify/blobs";
import type {
Store,
Expand Down Expand Up @@ -98,7 +99,7 @@ export default defineDriver((options: NetlifyStoreOptions) => {
},
async getKeys(
base?: string,
tops?: Omit<ListOptions, "prefix" | "paginate">
tops?: GetKeysOptions & Omit<ListOptions, "prefix" | "paginate">
) {
return (await getClient().list({ ...tops, prefix: base })).blobs.map(
(item) => item.key
Expand Down
19 changes: 13 additions & 6 deletions src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import type {
} from "./types";
import memory from "./drivers/memory";
import { asyncCall, deserializeRaw, serializeRaw, stringify } from "./_utils";
import { normalizeKey, normalizeBaseKey, joinKeys } from "./utils";
import {
normalizeKey,
normalizeBaseKey,
joinKeys,
filterKeyByDepth,
filterKeyByBase,
} from "./utils";

interface StorageCTX {
mounts: Record<string, Driver>;
Expand Down Expand Up @@ -362,11 +368,12 @@ export function createStorage<T extends StorageValue>(
...maskedMounts.filter((p) => !p.startsWith(mount.mountpoint)),
];
}
return base
? allKeys.filter(
(key) => key.startsWith(base!) && key[key.length - 1] !== "$"
)
: allKeys.filter((key) => key[key.length - 1] !== "$");
return allKeys.filter(
(key) =>
(opts.maxDepth === undefined ||
filterKeyByDepth(key, opts.maxDepth)) &&
filterKeyByBase(key, base)
);
},
// Utils
async clear(base, opts = {}) {
Expand Down
8 changes: 6 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export interface StorageMeta {
// TODO: type ttl
export type TransactionOptions = Record<string, any>;

export type GetKeysOptions = TransactionOptions & {
maxDepth?: number;
};

export interface Driver<OptionsT = any, InstanceT = any> {
name?: string;
options?: OptionsT;
Expand Down Expand Up @@ -55,7 +59,7 @@ export interface Driver<OptionsT = any, InstanceT = any> {
key: string,
opts: TransactionOptions
) => MaybePromise<StorageMeta | null>;
getKeys: (base: string, opts: TransactionOptions) => MaybePromise<string[]>;
getKeys: (base: string, opts: GetKeysOptions) => MaybePromise<string[]>;
clear?: (base: string, opts: TransactionOptions) => MaybePromise<void>;
dispose?: () => MaybePromise<void>;
watch?: (callback: WatchCallback) => MaybePromise<Unwatch>;
Expand Down Expand Up @@ -163,7 +167,7 @@ export interface Storage<T extends StorageValue = StorageValue> {
) => Promise<void>;
removeMeta: (key: string, opts?: TransactionOptions) => Promise<void>;
// Keys
getKeys: (base?: string, opts?: TransactionOptions) => Promise<string[]>;
getKeys: (base?: string, opts?: GetKeysOptions) => Promise<string[]>;
// Utils
clear: (base?: string, opts?: TransactionOptions) => Promise<void>;
dispose: () => Promise<void>;
Expand Down
30 changes: 30 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,33 @@ export function normalizeBaseKey(base?: string) {
base = normalizeKey(base);
return base ? base + ":" : "";
}

export function filterKeyByDepth(
key: string,
depth: number | undefined
): boolean {
if (depth === undefined) {
return true;
}

let substrCount = 0;
let index = key.indexOf(":");

while (index > -1) {
substrCount++;
index = key.indexOf(":", index + 1);
}

return substrCount <= depth;
}

export function filterKeyByBase(
key: string,
base: string | undefined
): boolean {
if (base) {
return key.startsWith(base) && key[key.length - 1] !== "$";
}

return key[key.length - 1] !== "$";
}
23 changes: 23 additions & 0 deletions test/drivers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,29 @@ export function testDriver(opts: TestOptions) {
);
});

it("getKeys with depth", async () => {
await ctx.storage.setItem("depth0_0", "test_data");
await ctx.storage.setItem("depth0:depth1:depth2_0", "test_data");
await ctx.storage.setItem("depth0:depth1:depth2_1", "test_data");
await ctx.storage.setItem("depth0:depth1_0", "test_data");
await ctx.storage.setItem("depth0:depth1_1", "test_data");
expect(await ctx.storage.getKeys(undefined, { maxDepth: 0 })).toMatchObject(
["depth0_0"]
);
expect(
(await ctx.storage.getKeys(undefined, { maxDepth: 1 })).sort()
).toMatchObject(["depth0:depth1_0", "depth0:depth1_1", "depth0_0"]);
expect(
(await ctx.storage.getKeys(undefined, { maxDepth: 2 })).sort()
).toMatchObject([
"depth0:depth1:depth2_0",
"depth0:depth1:depth2_1",
"depth0:depth1_0",
"depth0:depth1_1",
"depth0_0",
]);
});

it("serialize (object)", async () => {
await ctx.storage.setItem("/data/test.json", { json: "works" });
expect(await ctx.storage.getItem("/data/test.json")).toMatchObject({
Expand Down

0 comments on commit 990e776

Please sign in to comment.