Skip to content
Open
Changes from all commits
Commits
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
33 changes: 24 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
export type QueryKeyPart = string | number | boolean | object;
export type QueryKey = QueryKeyPart[];
export type QueryKeyBuilder<Args extends any[] = []> = (
export type QueryKeyBuilder<Args extends unknown[] = unknown[]> = (
...args: Args
) => QueryKey;
export type QueryKeyRegistry = Record<string, QueryKeyBuilder<any>>;
export type StoredQueryKeyBuilder = (...args: unknown[]) => QueryKey;
export type QueryKeyRegistry = Record<string, StoredQueryKeyBuilder>;
export type QueryKeyTree = Record<string, unknown>;

export class QueryKeyManager {
private static registry: QueryKeyRegistry = {};
Expand All @@ -22,25 +24,38 @@ export class QueryKeyManager {
* settings: (userId: string) => ['user', 'settings', userId]
* });
*/
static create<KeyMap extends Record<string, QueryKeyBuilder>>(
static create<KeyMap extends QueryKeyTree>(
name: string,
keyMap: KeyMap
): KeyMap {
// Runtime duplicate check
if (this.keyNames.has(name)) {
if (process.env.NODE_ENV !== "production") {
if (process.env.NODE_ENV !== 'production') {
throw new Error(`QueryKeyManager: Key name "${name}" already exists`);
}
return keyMap;
}

this.keyNames.add(name);

// Register each key builder
for (const [key, builder] of Object.entries(keyMap)) {
const fullKey = `${name}.${key}`;
this.registry[fullKey] = builder;
}
// Register each key builder (supports nested maps)
const register = (prefix: string, node: QueryKeyTree | StoredQueryKeyBuilder) => {
if (typeof node === 'function') {
this.registry[prefix] = node as StoredQueryKeyBuilder;
return;
}

for (const [key, value] of Object.entries(node as QueryKeyTree)) {
const fullKey = `${prefix}.${key}`;
if (typeof value === 'function') {
this.registry[fullKey] = value as StoredQueryKeyBuilder;
} else if (value && typeof value === 'object') {
register(fullKey, value as QueryKeyTree);
}
}
};

register(name, keyMap);

return keyMap;
}
Expand Down