From a7e0ae3f745cf9b8e98dfc637f5b3968c1414807 Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 19:09:49 +0200 Subject: [PATCH 01/10] feat(drivers): add type generics to support strongly typed options of getters and setters --- src/drivers/utils/index.ts | 17 ++++++---- src/storage.ts | 10 +++--- src/types.ts | 63 +++++++++++++++++++++----------------- 3 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/drivers/utils/index.ts b/src/drivers/utils/index.ts index 16e584a3a..2e1230229 100644 --- a/src/drivers/utils/index.ts +++ b/src/drivers/utils/index.ts @@ -1,13 +1,18 @@ -import type { Driver } from "../.."; +import type { Driver, TransactionOptions } from "../.."; -type DriverFactory = ( +type DriverFactory = ( opts: OptionsT -) => Driver; +) => Driver; interface ErrorOptions {} -export function defineDriver( - factory: DriverFactory -): DriverFactory { +export function defineDriver< + OptionsT = any, + InstanceT = never, + SetItemOptionsT = TransactionOptions, + GetItemOptionsT = TransactionOptions, +>( + factory: DriverFactory +): DriverFactory { return factory; } diff --git a/src/storage.ts b/src/storage.ts index eb6578471..9ea66820f 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -26,13 +26,13 @@ interface StorageCTX { watchListeners: ((event: WatchEvent, key: string) => void)[]; } -export interface CreateStorageOptions { - driver?: Driver; +export interface CreateStorageOptions { + driver?: DriverT; } -export function createStorage( - options: CreateStorageOptions = {} -): Storage { +export function createStorage( + options: CreateStorageOptions = {} +): Storage { const context: StorageCTX = { mounts: { "": options.driver || memory() }, mountpoints: [""], diff --git a/src/types.ts b/src/types.ts index d347dbd06..8a636ed29 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,7 +15,6 @@ export interface StorageMeta { [key: string]: StorageValue | Date | undefined; } -// TODO: type ttl export type TransactionOptions = Record; export type GetKeysOptions = TransactionOptions & { @@ -27,46 +26,48 @@ export interface DriverFlags { ttl?: boolean; } -export interface Driver { +export interface Driver< + OptionsT = any, + InstanceT = any, + SetItemOptionsT = TransactionOptions, + GetItemOptionsT = TransactionOptions, +> { name?: string; flags?: DriverFlags; options?: OptionsT; getInstance?: () => InstanceT; - hasItem: (key: string, opts: TransactionOptions) => MaybePromise; - getItem: ( - key: string, - opts?: TransactionOptions - ) => MaybePromise; + hasItem: (key: string, opts: GetItemOptionsT) => MaybePromise; + getItem: (key: string, opts?: GetItemOptionsT) => MaybePromise; /** @experimental */ getItems?: ( - items: { key: string; options?: TransactionOptions }[], - commonOptions?: TransactionOptions + items: { key: string; options?: GetItemOptionsT }[], + commonOptions?: GetItemOptionsT ) => MaybePromise<{ key: string; value: StorageValue }[]>; /** @experimental */ - getItemRaw?: (key: string, opts: TransactionOptions) => MaybePromise; + getItemRaw?: (key: string, opts: GetItemOptionsT) => MaybePromise; setItem?: ( key: string, value: string, - opts: TransactionOptions + opts: SetItemOptionsT ) => MaybePromise; /** @experimental */ setItems?: ( - items: { key: string; value: string; options?: TransactionOptions }[], - commonOptions?: TransactionOptions + items: { key: string; value: string; options?: SetItemOptionsT }[], + commonOptions?: SetItemOptionsT ) => MaybePromise; /** @experimental */ setItemRaw?: ( key: string, value: any, - opts: TransactionOptions + opts: SetItemOptionsT ) => MaybePromise; - removeItem?: (key: string, opts: TransactionOptions) => MaybePromise; + removeItem?: (key: string, opts: GetItemOptionsT) => MaybePromise; getMeta?: ( key: string, - opts: TransactionOptions + opts: GetItemOptionsT ) => MaybePromise; getKeys: (base: string, opts: GetKeysOptions) => MaybePromise; - clear?: (base: string, opts: TransactionOptions) => MaybePromise; + clear?: (base: string, opts: GetItemOptionsT) => MaybePromise; dispose?: () => MaybePromise; watch?: (callback: WatchCallback) => MaybePromise; } @@ -83,7 +84,13 @@ type StorageItemType = K extends keyof StorageItemMap ? StorageValue : T; -export interface Storage { +type StorageSetOptions = DriverT extends Driver + ? SetItemOptionsT : never + +type StorageGetOptions = DriverT extends Driver + ? GetItemOptionsT : never + +export interface Storage { // Item hasItem< U extends Extract, @@ -99,22 +106,22 @@ export interface Storage { K extends string & keyof StorageItemMap, >( key: K, - ops?: TransactionOptions + ops?: StorageGetOptions ): Promise | null>; getItem>( key: string, - opts?: TransactionOptions + opts?: StorageGetOptions ): Promise; /** @experimental */ getItems: ( - items: (string | { key: string; options?: TransactionOptions })[], - commonOptions?: TransactionOptions + items: (string | { key: string; options?: StorageGetOptions })[], + commonOptions?: StorageGetOptions ) => Promise<{ key: string; value: U }[]>; /** @experimental See https://github.com/unjs/unstorage/issues/142 */ getItemRaw: ( key: string, - opts?: TransactionOptions + opts?: StorageGetOptions ) => Promise | null>; setItem< @@ -123,24 +130,24 @@ export interface Storage { >( key: K, value: StorageItemType, - opts?: TransactionOptions + opts?: StorageSetOptions ): Promise; setItem( key: string, value: U, - opts?: TransactionOptions + opts?: StorageSetOptions ): Promise; /** @experimental */ setItems: ( - items: { key: string; value: U; options?: TransactionOptions }[], - commonOptions?: TransactionOptions + items: { key: string; value: U; options?: StorageSetOptions }[], + commonOptions?: StorageSetOptions ) => Promise; /** @experimental See https://github.com/unjs/unstorage/issues/142 */ setItemRaw: ( key: string, value: MaybeDefined, - opts?: TransactionOptions + opts?: StorageSetOptions ) => Promise; removeItem< From 2c0878a80573bfa7da963c62ee3b840763928f3a Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 19:55:15 +0200 Subject: [PATCH 02/10] refactor(types): unify transaction options handling in driver interfaces to support all methods --- src/drivers/utils/index.ts | 13 +++-- src/types.ts | 102 ++++++++++++++++++++----------------- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/src/drivers/utils/index.ts b/src/drivers/utils/index.ts index 2e1230229..2dded895b 100644 --- a/src/drivers/utils/index.ts +++ b/src/drivers/utils/index.ts @@ -1,18 +1,17 @@ -import type { Driver, TransactionOptions } from "../.."; +import type { Driver, TransactionOpts } from "../.."; -type DriverFactory = ( +type DriverFactory = ( opts: OptionsT -) => Driver; +) => Driver; interface ErrorOptions {} export function defineDriver< OptionsT = any, InstanceT = never, - SetItemOptionsT = TransactionOptions, - GetItemOptionsT = TransactionOptions, + TransactionOptsT extends TransactionOpts = TransactionOpts >( - factory: DriverFactory -): DriverFactory { + factory: DriverFactory +): DriverFactory { return factory; } diff --git a/src/types.ts b/src/types.ts index 8a636ed29..a536d65d5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,57 +17,62 @@ export interface StorageMeta { export type TransactionOptions = Record; -export type GetKeysOptions = TransactionOptions & { - maxDepth?: number; -}; + export interface DriverFlags { maxDepth?: boolean; ttl?: boolean; } +export type TransactionOpts = { + getOptions?: GetOptionsT; + setOptions?: SetOptionsT; + hasOptions?: HasOptionsT; + removeOptions?: RemoveOptionsT; + getKeysOptions?: GetKeysOptionsT; +} + export interface Driver< OptionsT = any, InstanceT = any, - SetItemOptionsT = TransactionOptions, - GetItemOptionsT = TransactionOptions, + optionsT extends TransactionOpts = TransactionOpts > { name?: string; flags?: DriverFlags; options?: OptionsT; getInstance?: () => InstanceT; - hasItem: (key: string, opts: GetItemOptionsT) => MaybePromise; - getItem: (key: string, opts?: GetItemOptionsT) => MaybePromise; + hasItem: (key: string, opts: optionsT["hasOptions"]) => MaybePromise; + getItem: (key: string, opts?: optionsT["getOptions"]) => MaybePromise; /** @experimental */ getItems?: ( - items: { key: string; options?: GetItemOptionsT }[], - commonOptions?: GetItemOptionsT + items: { key: string; options?: optionsT["getOptions"] }[], + commonOptions?: optionsT["getOptions"] ) => MaybePromise<{ key: string; value: StorageValue }[]>; /** @experimental */ - getItemRaw?: (key: string, opts: GetItemOptionsT) => MaybePromise; + getItemRaw?: (key: string, opts: optionsT["getOptions"]) => MaybePromise; setItem?: ( key: string, value: string, - opts: SetItemOptionsT + opts: optionsT["setOptions"] ) => MaybePromise; /** @experimental */ setItems?: ( - items: { key: string; value: string; options?: SetItemOptionsT }[], - commonOptions?: SetItemOptionsT + items: { key: string; value: string; options?: optionsT["setOptions"] }[], + commonOptions?: optionsT["setOptions"] ) => MaybePromise; /** @experimental */ setItemRaw?: ( key: string, value: any, - opts: SetItemOptionsT + opts: optionsT["setOptions"] ) => MaybePromise; - removeItem?: (key: string, opts: GetItemOptionsT) => MaybePromise; + removeItem?: (key: string, opts: optionsT["removeOptions"]) => MaybePromise; getMeta?: ( key: string, - opts: GetItemOptionsT + opts: optionsT["getOptions"] ) => MaybePromise; - getKeys: (base: string, opts: GetKeysOptions) => MaybePromise; - clear?: (base: string, opts: GetItemOptionsT) => MaybePromise; + getKeys: (base: string, opts: optionsT["getKeysOptions"]) => MaybePromise; + clear?: (base: string, opts: optionsT["removeOptions"]) => MaybePromise; dispose?: () => MaybePromise; watch?: (callback: WatchCallback) => MaybePromise; } @@ -84,11 +89,16 @@ type StorageItemType = K extends keyof StorageItemMap ? StorageValue : T; -type StorageSetOptions = DriverT extends Driver - ? SetItemOptionsT : never +type StorageMethodOptions = DriverT extends Driver + ? MethodOptionsT : never; + -type StorageGetOptions = DriverT extends Driver - ? GetItemOptionsT : never +// if options type is not set it is unknown and we default back to TransactionOptions +type SetOptionsType = unknown extends StorageMethodOptions["setOptions"] ? TransactionOptions : StorageMethodOptions["setOptions"]; +type GetOptionsType = unknown extends StorageMethodOptions["getOptions"] ? TransactionOptions : StorageMethodOptions["getOptions"]; +type RemoveOptionsType = unknown extends StorageMethodOptions["removeOptions"] ? TransactionOptions : StorageMethodOptions["removeOptions"]; +type GetKeysOptionsType = unknown extends StorageMethodOptions["getKeysOptions"] ? TransactionOptions : StorageMethodOptions["getKeysOptions"]; +type HasOptionsType = unknown extends StorageMethodOptions["hasOptions"] ? TransactionOptions : StorageMethodOptions["hasOptions"]; export interface Storage { // Item @@ -97,31 +107,31 @@ export interface Storage, >( key: K, - opts?: TransactionOptions + opts?: HasOptionsType ): Promise; - hasItem(key: string, opts?: TransactionOptions): Promise; + hasItem(key: string, opts?: HasOptionsType): Promise; getItem< U extends Extract, K extends string & keyof StorageItemMap, >( key: K, - ops?: StorageGetOptions + opts?: GetOptionsType ): Promise | null>; getItem>( key: string, - opts?: StorageGetOptions + opts?: GetOptionsType ): Promise; /** @experimental */ getItems: ( - items: (string | { key: string; options?: StorageGetOptions })[], - commonOptions?: StorageGetOptions + items: (string | { key: string; options?: GetOptionsType })[], + commonOptions?: GetOptionsType ) => Promise<{ key: string; value: U }[]>; /** @experimental See https://github.com/unjs/unstorage/issues/142 */ getItemRaw: ( key: string, - opts?: StorageGetOptions + opts?: GetOptionsType ) => Promise | null>; setItem< @@ -130,24 +140,24 @@ export interface Storage( key: K, value: StorageItemType, - opts?: StorageSetOptions + opts?: SetOptionsType ): Promise; setItem( key: string, value: U, - opts?: StorageSetOptions + opts?: SetOptionsType ): Promise; /** @experimental */ setItems: ( - items: { key: string; value: U; options?: StorageSetOptions }[], - commonOptions?: StorageSetOptions + items: { key: string; value: U; options?: SetOptionsType }[], + commonOptions?: SetOptionsType ) => Promise; /** @experimental See https://github.com/unjs/unstorage/issues/142 */ setItemRaw: ( key: string, value: MaybeDefined, - opts?: StorageSetOptions + opts?: SetOptionsType ) => Promise; removeItem< @@ -156,13 +166,13 @@ export interface Storage( key: K, opts?: - | (TransactionOptions & { removeMeta?: boolean }) + | RemoveOptionsType & { removeMeta?: boolean } | boolean /* legacy: removeMeta */ ): Promise; removeItem( key: string, opts?: - | (TransactionOptions & { removeMeta?: boolean }) + | RemoveOptionsType & { removeMeta?: boolean } | boolean /* legacy: removeMeta */ ): Promise; @@ -170,19 +180,19 @@ export interface Storage & { nativeOnly?: boolean }) | boolean /* legacy: nativeOnly */ ) => MaybePromise; setMeta: ( key: string, value: StorageMeta, - opts?: TransactionOptions + opts?: SetOptionsType ) => Promise; - removeMeta: (key: string, opts?: TransactionOptions) => Promise; + removeMeta: (key: string, opts?: RemoveOptionsType) => Promise; // Keys - getKeys: (base?: string, opts?: GetKeysOptions) => Promise; + getKeys: (base?: string, opts?: GetKeysOptionsType) => Promise; // Utils - clear: (base?: string, opts?: TransactionOptions) => Promise; + clear: (base?: string, opts?: RemoveOptionsType) => Promise; dispose: () => Promise; watch: (callback: WatchCallback) => Promise; unwatch: () => Promise; @@ -196,9 +206,9 @@ export interface Storage { base: string; driver: Driver }[]; // Aliases keys: Storage["getKeys"]; - get: Storage["getItem"]; - set: Storage["setItem"]; - has: Storage["hasItem"]; - del: Storage["removeItem"]; - remove: Storage["removeItem"]; + get: Storage["getItem"]; + set: Storage["setItem"]; + has: Storage["hasItem"]; + del: Storage["removeItem"]; + remove: Storage["removeItem"]; } From de3de62facc461f97090622d0b8161b4986b7662 Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 19:56:50 +0200 Subject: [PATCH 03/10] fix: linting --- src/drivers/utils/index.ts | 10 +++-- src/storage.ts | 7 ++-- src/types.ts | 82 ++++++++++++++++++++++++++++---------- 3 files changed, 70 insertions(+), 29 deletions(-) diff --git a/src/drivers/utils/index.ts b/src/drivers/utils/index.ts index 2dded895b..6acbf9237 100644 --- a/src/drivers/utils/index.ts +++ b/src/drivers/utils/index.ts @@ -1,14 +1,16 @@ import type { Driver, TransactionOpts } from "../.."; -type DriverFactory = ( - opts: OptionsT -) => Driver; +type DriverFactory< + OptionsT, + InstanceT, + TransactionOptsT extends TransactionOpts, +> = (opts: OptionsT) => Driver; interface ErrorOptions {} export function defineDriver< OptionsT = any, InstanceT = never, - TransactionOptsT extends TransactionOpts = TransactionOpts + TransactionOptsT extends TransactionOpts = TransactionOpts, >( factory: DriverFactory ): DriverFactory { diff --git a/src/storage.ts b/src/storage.ts index 9ea66820f..525dee4ff 100644 --- a/src/storage.ts +++ b/src/storage.ts @@ -30,9 +30,10 @@ export interface CreateStorageOptions { driver?: DriverT; } -export function createStorage( - options: CreateStorageOptions = {} -): Storage { +export function createStorage< + T extends StorageValue, + DriverT extends Driver = Driver, +>(options: CreateStorageOptions = {}): Storage { const context: StorageCTX = { mounts: { "": options.driver || memory() }, mountpoints: [""], diff --git a/src/types.ts b/src/types.ts index a536d65d5..42eb691c1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,39 +17,49 @@ export interface StorageMeta { export type TransactionOptions = Record; - - export interface DriverFlags { maxDepth?: boolean; ttl?: boolean; } -export type TransactionOpts = { +export type TransactionOpts< + GetOptionsT = TransactionOptions, + SetOptionsT = TransactionOptions, + HasOptionsT = TransactionOptions, + RemoveOptionsT = TransactionOptions, + GetKeysOptionsT = TransactionOptions, +> = { getOptions?: GetOptionsT; setOptions?: SetOptionsT; hasOptions?: HasOptionsT; removeOptions?: RemoveOptionsT; getKeysOptions?: GetKeysOptionsT; -} +}; export interface Driver< OptionsT = any, InstanceT = any, - optionsT extends TransactionOpts = TransactionOpts + optionsT extends TransactionOpts = TransactionOpts, > { name?: string; flags?: DriverFlags; options?: OptionsT; getInstance?: () => InstanceT; hasItem: (key: string, opts: optionsT["hasOptions"]) => MaybePromise; - getItem: (key: string, opts?: optionsT["getOptions"]) => MaybePromise; + getItem: ( + key: string, + opts?: optionsT["getOptions"] + ) => MaybePromise; /** @experimental */ getItems?: ( items: { key: string; options?: optionsT["getOptions"] }[], commonOptions?: optionsT["getOptions"] ) => MaybePromise<{ key: string; value: StorageValue }[]>; /** @experimental */ - getItemRaw?: (key: string, opts: optionsT["getOptions"]) => MaybePromise; + getItemRaw?: ( + key: string, + opts: optionsT["getOptions"] + ) => MaybePromise; setItem?: ( key: string, value: string, @@ -66,12 +76,18 @@ export interface Driver< value: any, opts: optionsT["setOptions"] ) => MaybePromise; - removeItem?: (key: string, opts: optionsT["removeOptions"]) => MaybePromise; + removeItem?: ( + key: string, + opts: optionsT["removeOptions"] + ) => MaybePromise; getMeta?: ( key: string, opts: optionsT["getOptions"] ) => MaybePromise; - getKeys: (base: string, opts: optionsT["getKeysOptions"]) => MaybePromise; + getKeys: ( + base: string, + opts: optionsT["getKeysOptions"] + ) => MaybePromise; clear?: (base: string, opts: optionsT["removeOptions"]) => MaybePromise; dispose?: () => MaybePromise; watch?: (callback: WatchCallback) => MaybePromise; @@ -89,18 +105,37 @@ type StorageItemType = K extends keyof StorageItemMap ? StorageValue : T; -type StorageMethodOptions = DriverT extends Driver - ? MethodOptionsT : never; - +type StorageMethodOptions = + DriverT extends Driver + ? MethodOptionsT + : never; // if options type is not set it is unknown and we default back to TransactionOptions -type SetOptionsType = unknown extends StorageMethodOptions["setOptions"] ? TransactionOptions : StorageMethodOptions["setOptions"]; -type GetOptionsType = unknown extends StorageMethodOptions["getOptions"] ? TransactionOptions : StorageMethodOptions["getOptions"]; -type RemoveOptionsType = unknown extends StorageMethodOptions["removeOptions"] ? TransactionOptions : StorageMethodOptions["removeOptions"]; -type GetKeysOptionsType = unknown extends StorageMethodOptions["getKeysOptions"] ? TransactionOptions : StorageMethodOptions["getKeysOptions"]; -type HasOptionsType = unknown extends StorageMethodOptions["hasOptions"] ? TransactionOptions : StorageMethodOptions["hasOptions"]; - -export interface Storage { +type SetOptionsType = + unknown extends StorageMethodOptions["setOptions"] + ? TransactionOptions + : StorageMethodOptions["setOptions"]; +type GetOptionsType = + unknown extends StorageMethodOptions["getOptions"] + ? TransactionOptions + : StorageMethodOptions["getOptions"]; +type RemoveOptionsType = + unknown extends StorageMethodOptions["removeOptions"] + ? TransactionOptions + : StorageMethodOptions["removeOptions"]; +type GetKeysOptionsType = + unknown extends StorageMethodOptions["getKeysOptions"] + ? TransactionOptions + : StorageMethodOptions["getKeysOptions"]; +type HasOptionsType = + unknown extends StorageMethodOptions["hasOptions"] + ? TransactionOptions + : StorageMethodOptions["hasOptions"]; + +export interface Storage< + T extends StorageValue = StorageValue, + DriverT extends Driver = Driver, +> { // Item hasItem< U extends Extract, @@ -166,13 +201,13 @@ export interface Storage( key: K, opts?: - | RemoveOptionsType & { removeMeta?: boolean } + | (RemoveOptionsType & { removeMeta?: boolean }) | boolean /* legacy: removeMeta */ ): Promise; removeItem( key: string, opts?: - | RemoveOptionsType & { removeMeta?: boolean } + | (RemoveOptionsType & { removeMeta?: boolean }) | boolean /* legacy: removeMeta */ ): Promise; @@ -190,7 +225,10 @@ export interface Storage Promise; removeMeta: (key: string, opts?: RemoveOptionsType) => Promise; // Keys - getKeys: (base?: string, opts?: GetKeysOptionsType) => Promise; + getKeys: ( + base?: string, + opts?: GetKeysOptionsType + ) => Promise; // Utils clear: (base?: string, opts?: RemoveOptionsType) => Promise; dispose: () => Promise; From 27bac63709ae1cdf76623b16496f8ec77b4f299e Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 20:06:43 +0200 Subject: [PATCH 04/10] refactor(netlify-blobs): use new typed options driver to solve type issues --- src/drivers/netlify-blobs.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/drivers/netlify-blobs.ts b/src/drivers/netlify-blobs.ts index a8eb59bdf..08423bd56 100644 --- a/src/drivers/netlify-blobs.ts +++ b/src/drivers/netlify-blobs.ts @@ -1,5 +1,4 @@ import { createError, createRequiredError, defineDriver } from "./utils"; -import type { GetKeysOptions } from ".."; import { getStore, getDeployStore } from "@netlify/blobs"; import type { Store, @@ -46,7 +45,15 @@ export interface NetlifyNamedStoreOptions deployScoped?: false; } -export default defineDriver((options: NetlifyStoreOptions) => { +export interface NetlifyGetKeysOptions extends Omit { + maxDepth?: number +} + +export default defineDriver((options: NetlifyStoreOptions) => { const { deployScoped, name, ...opts } = options; let store: Store; @@ -109,7 +116,7 @@ export default defineDriver((options: NetlifyStoreOptions) => { }, async getKeys( base?: string, - tops?: GetKeysOptions & Omit + tops?: NetlifyGetKeysOptions ) { return (await getClient().list({ ...tops, prefix: base })).blobs.map( (item) => item.key From 63ac0a70af411bb29c7df7b1df038897efef4e4e Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 20:07:14 +0200 Subject: [PATCH 05/10] fix(tests): allow any driver in testDriver --- test/drivers/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/drivers/utils.ts b/test/drivers/utils.ts index 9edd7fbc7..3977aebc2 100644 --- a/test/drivers/utils.ts +++ b/test/drivers/utils.ts @@ -11,8 +11,8 @@ export interface TestContext { driver: Driver; } -export interface TestOptions { - driver: Driver | (() => Driver); +export interface TestOptions{ + driver: Driver | (() => Driver); noKeysSupport?: boolean; additionalTests?: (ctx: TestContext) => void; } From 98ceb2f17e48d2e8001cf562cf58e88be73200ee Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 20:26:17 +0200 Subject: [PATCH 06/10] fix: make typed options partial by default when passed via `defineDriver` --- src/drivers/netlify-blobs.ts | 24 +++++++++++++----------- src/drivers/utils/index.ts | 3 ++- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/drivers/netlify-blobs.ts b/src/drivers/netlify-blobs.ts index 08423bd56..b390b890d 100644 --- a/src/drivers/netlify-blobs.ts +++ b/src/drivers/netlify-blobs.ts @@ -45,15 +45,20 @@ export interface NetlifyNamedStoreOptions deployScoped?: false; } -export interface NetlifyGetKeysOptions extends Omit { - maxDepth?: number +export interface NetlifyGetKeysOptions + extends Omit { + maxDepth?: number; } -export default defineDriver((options: NetlifyStoreOptions) => { +export default defineDriver< + NetlifyStoreOptions, + Store, + { + setOptions: SetOptions; + getOptions: GetOptions; + getKeysOptions: NetlifyGetKeysOptions; + } +>((options: NetlifyStoreOptions) => { const { deployScoped, name, ...opts } = options; let store: Store; @@ -114,10 +119,7 @@ export default defineDriver item.key ); diff --git a/src/drivers/utils/index.ts b/src/drivers/utils/index.ts index 6acbf9237..5f342cb88 100644 --- a/src/drivers/utils/index.ts +++ b/src/drivers/utils/index.ts @@ -4,7 +4,8 @@ type DriverFactory< OptionsT, InstanceT, TransactionOptsT extends TransactionOpts, -> = (opts: OptionsT) => Driver; + // Partial here, to not required typed options to be optional in type argument +> = (opts: OptionsT) => Driver>; interface ErrorOptions {} export function defineDriver< From 9c5be21184d2359d72849733695a69b98278478e Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 20:26:26 +0200 Subject: [PATCH 07/10] fix: lint --- test/drivers/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/drivers/utils.ts b/test/drivers/utils.ts index 3977aebc2..92eaaffa7 100644 --- a/test/drivers/utils.ts +++ b/test/drivers/utils.ts @@ -11,7 +11,7 @@ export interface TestContext { driver: Driver; } -export interface TestOptions{ +export interface TestOptions { driver: Driver | (() => Driver); noKeysSupport?: boolean; additionalTests?: (ctx: TestContext) => void; From c12100c7430b2b633c500e0acea898a1c15dd196 Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 21:08:50 +0200 Subject: [PATCH 08/10] refactor: replace TransactionOpts with DriverMethodOptionsMap --- src/drivers/utils/index.ts | 12 +++++------ src/types.ts | 42 +++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/drivers/utils/index.ts b/src/drivers/utils/index.ts index 5f342cb88..3bfca2971 100644 --- a/src/drivers/utils/index.ts +++ b/src/drivers/utils/index.ts @@ -1,20 +1,20 @@ -import type { Driver, TransactionOpts } from "../.."; +import type { Driver, DriverMethodOptionsMap } from "../.."; type DriverFactory< OptionsT, InstanceT, - TransactionOptsT extends TransactionOpts, + DriverMethodOptionsMapT extends DriverMethodOptionsMap, // Partial here, to not required typed options to be optional in type argument -> = (opts: OptionsT) => Driver>; +> = (opts: OptionsT) => Driver>; interface ErrorOptions {} export function defineDriver< OptionsT = any, InstanceT = never, - TransactionOptsT extends TransactionOpts = TransactionOpts, + DriverMethodOptionsMapT extends DriverMethodOptionsMap = DriverMethodOptionsMap, >( - factory: DriverFactory -): DriverFactory { + factory: DriverFactory +): DriverFactory { return factory; } diff --git a/src/types.ts b/src/types.ts index 42eb691c1..1e5a3dabb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -22,73 +22,73 @@ export interface DriverFlags { ttl?: boolean; } -export type TransactionOpts< +export type DriverMethodOptionsMap< GetOptionsT = TransactionOptions, SetOptionsT = TransactionOptions, HasOptionsT = TransactionOptions, RemoveOptionsT = TransactionOptions, GetKeysOptionsT = TransactionOptions, > = { - getOptions?: GetOptionsT; - setOptions?: SetOptionsT; - hasOptions?: HasOptionsT; - removeOptions?: RemoveOptionsT; - getKeysOptions?: GetKeysOptionsT; + getOptions?: GetOptionsT ; + setOptions?: SetOptionsT ; + hasOptions?: HasOptionsT ; + removeOptions?: RemoveOptionsT ; + getKeysOptions?: GetKeysOptionsT ; }; export interface Driver< OptionsT = any, InstanceT = any, - optionsT extends TransactionOpts = TransactionOpts, + DriverMethodOptionsMapT extends DriverMethodOptionsMap = DriverMethodOptionsMap, > { name?: string; flags?: DriverFlags; options?: OptionsT; getInstance?: () => InstanceT; - hasItem: (key: string, opts: optionsT["hasOptions"]) => MaybePromise; + hasItem: (key: string, opts: DriverMethodOptionsMapT["hasOptions"]) => MaybePromise; getItem: ( key: string, - opts?: optionsT["getOptions"] + opts?: DriverMethodOptionsMapT["getOptions"] ) => MaybePromise; /** @experimental */ getItems?: ( - items: { key: string; options?: optionsT["getOptions"] }[], - commonOptions?: optionsT["getOptions"] + items: { key: string; options?: DriverMethodOptionsMapT["getOptions"] }[], + commonOptions?: DriverMethodOptionsMapT["getOptions"] ) => MaybePromise<{ key: string; value: StorageValue }[]>; /** @experimental */ getItemRaw?: ( key: string, - opts: optionsT["getOptions"] + opts: DriverMethodOptionsMapT["getOptions"] ) => MaybePromise; setItem?: ( key: string, value: string, - opts: optionsT["setOptions"] + opts: DriverMethodOptionsMapT["setOptions"] ) => MaybePromise; /** @experimental */ setItems?: ( - items: { key: string; value: string; options?: optionsT["setOptions"] }[], - commonOptions?: optionsT["setOptions"] + items: { key: string; value: string; options?: DriverMethodOptionsMapT["setOptions"] }[], + commonOptions?: DriverMethodOptionsMapT["setOptions"] ) => MaybePromise; /** @experimental */ setItemRaw?: ( key: string, value: any, - opts: optionsT["setOptions"] + opts: DriverMethodOptionsMapT["setOptions"] ) => MaybePromise; removeItem?: ( key: string, - opts: optionsT["removeOptions"] + opts: DriverMethodOptionsMapT["removeOptions"] ) => MaybePromise; getMeta?: ( key: string, - opts: optionsT["getOptions"] + opts: DriverMethodOptionsMapT["getOptions"] ) => MaybePromise; getKeys: ( base: string, - opts: optionsT["getKeysOptions"] + opts: DriverMethodOptionsMapT["getKeysOptions"] ) => MaybePromise; - clear?: (base: string, opts: optionsT["removeOptions"]) => MaybePromise; + clear?: (base: string, opts: DriverMethodOptionsMapT["removeOptions"]) => MaybePromise; dispose?: () => MaybePromise; watch?: (callback: WatchCallback) => MaybePromise; } @@ -114,7 +114,7 @@ type StorageMethodOptions = type SetOptionsType = unknown extends StorageMethodOptions["setOptions"] ? TransactionOptions - : StorageMethodOptions["setOptions"]; + : StorageMethodOptions["setOptions"] | undefined; type GetOptionsType = unknown extends StorageMethodOptions["getOptions"] ? TransactionOptions From 939cc624c174dc26ed040e96e2d7eaed6d0c87ee Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 19:38:07 +0000 Subject: [PATCH 09/10] chore: apply automated updates --- src/drivers/utils/index.ts | 7 +++++-- src/types.ts | 29 ++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/drivers/utils/index.ts b/src/drivers/utils/index.ts index 3bfca2971..96d02508f 100644 --- a/src/drivers/utils/index.ts +++ b/src/drivers/utils/index.ts @@ -5,13 +5,16 @@ type DriverFactory< InstanceT, DriverMethodOptionsMapT extends DriverMethodOptionsMap, // Partial here, to not required typed options to be optional in type argument -> = (opts: OptionsT) => Driver>; +> = ( + opts: OptionsT +) => Driver>; interface ErrorOptions {} export function defineDriver< OptionsT = any, InstanceT = never, - DriverMethodOptionsMapT extends DriverMethodOptionsMap = DriverMethodOptionsMap, + DriverMethodOptionsMapT extends + DriverMethodOptionsMap = DriverMethodOptionsMap, >( factory: DriverFactory ): DriverFactory { diff --git a/src/types.ts b/src/types.ts index 1e5a3dabb..23d32d513 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,23 +29,27 @@ export type DriverMethodOptionsMap< RemoveOptionsT = TransactionOptions, GetKeysOptionsT = TransactionOptions, > = { - getOptions?: GetOptionsT ; - setOptions?: SetOptionsT ; - hasOptions?: HasOptionsT ; - removeOptions?: RemoveOptionsT ; - getKeysOptions?: GetKeysOptionsT ; + getOptions?: GetOptionsT; + setOptions?: SetOptionsT; + hasOptions?: HasOptionsT; + removeOptions?: RemoveOptionsT; + getKeysOptions?: GetKeysOptionsT; }; export interface Driver< OptionsT = any, InstanceT = any, - DriverMethodOptionsMapT extends DriverMethodOptionsMap = DriverMethodOptionsMap, + DriverMethodOptionsMapT extends + DriverMethodOptionsMap = DriverMethodOptionsMap, > { name?: string; flags?: DriverFlags; options?: OptionsT; getInstance?: () => InstanceT; - hasItem: (key: string, opts: DriverMethodOptionsMapT["hasOptions"]) => MaybePromise; + hasItem: ( + key: string, + opts: DriverMethodOptionsMapT["hasOptions"] + ) => MaybePromise; getItem: ( key: string, opts?: DriverMethodOptionsMapT["getOptions"] @@ -67,7 +71,11 @@ export interface Driver< ) => MaybePromise; /** @experimental */ setItems?: ( - items: { key: string; value: string; options?: DriverMethodOptionsMapT["setOptions"] }[], + items: { + key: string; + value: string; + options?: DriverMethodOptionsMapT["setOptions"]; + }[], commonOptions?: DriverMethodOptionsMapT["setOptions"] ) => MaybePromise; /** @experimental */ @@ -88,7 +96,10 @@ export interface Driver< base: string, opts: DriverMethodOptionsMapT["getKeysOptions"] ) => MaybePromise; - clear?: (base: string, opts: DriverMethodOptionsMapT["removeOptions"]) => MaybePromise; + clear?: ( + base: string, + opts: DriverMethodOptionsMapT["removeOptions"] + ) => MaybePromise; dispose?: () => MaybePromise; watch?: (callback: WatchCallback) => MaybePromise; } From 3e8310501c81b8b81fa077d217e78cab5ce24348 Mon Sep 17 00:00:00 2001 From: schplitt Date: Fri, 22 Aug 2025 21:55:19 +0200 Subject: [PATCH 10/10] fix(deno-kv): make tOptions optional in setItem and setItemRaw methods --- src/drivers/deno-kv.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/drivers/deno-kv.ts b/src/drivers/deno-kv.ts index 0b1808077..497d39d8e 100644 --- a/src/drivers/deno-kv.ts +++ b/src/drivers/deno-kv.ts @@ -12,6 +12,7 @@ export interface DenoKvOptions { */ ttl?: number; } + interface DenoKVSetOptions { /** * TTL in seconds. @@ -75,12 +76,12 @@ export default defineDriver>( const value = await kv.get(r(key)); return value.value; }, - async setItem(key, value, tOptions: DenoKVSetOptions) { + async setItem(key, value, tOptions?: DenoKVSetOptions) { const ttl = normalizeTTL(tOptions?.ttl ?? opts?.ttl); const kv = await getKv(); await kv.set(r(key), value, { expireIn: ttl }); }, - async setItemRaw(key, value, tOptions: DenoKVSetOptions) { + async setItemRaw(key, value, tOptions?: DenoKVSetOptions) { const ttl = normalizeTTL(tOptions?.ttl ?? opts?.ttl); const kv = await getKv(); await kv.set(r(key), value, { expireIn: ttl });