@carddb/browser 0.1.4 → 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 +15 -1
- package/dist/browser/index.js +699 -88
- package/dist/browser/index.js.map +1 -1
- package/dist/index.cjs +19 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var client = require('@carddb/client');
|
|
4
|
+
var core = require('@carddb/core');
|
|
5
|
+
|
|
6
|
+
// src/index.ts
|
|
4
7
|
|
|
5
8
|
// src/cache.ts
|
|
6
9
|
var BrowserCache = class {
|
|
@@ -115,8 +118,24 @@ var BrowserCache = class {
|
|
|
115
118
|
}
|
|
116
119
|
}
|
|
117
120
|
};
|
|
121
|
+
var CardDBClient = class extends client.CardDBClient {
|
|
122
|
+
constructor(config = {}) {
|
|
123
|
+
if ("apiKey" in config && config.apiKey !== void 0) {
|
|
124
|
+
throw new core.RestrictedError(
|
|
125
|
+
"apiKey is not accepted in browsers; use publishableKey or accessToken"
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if ("secretKey" in config && config.secretKey !== void 0) {
|
|
129
|
+
throw new core.RestrictedError(
|
|
130
|
+
"secretKey is server-only; use publishableKey or accessToken in browsers"
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
super(config);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
118
136
|
|
|
119
137
|
exports.BrowserCache = BrowserCache;
|
|
138
|
+
exports.CardDBClient = CardDBClient;
|
|
120
139
|
Object.keys(client).forEach(function (k) {
|
|
121
140
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
122
141
|
enumerable: true,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Browser-based cache implementations using localStorage/sessionStorage\n */\n\nimport type { Cache } from '@carddb/core'\n\ninterface CacheEntry<T> {\n value: T\n expiresAt: number | null\n}\n\ntype StorageType = 'localStorage' | 'sessionStorage'\n\n/**\n * Browser cache using localStorage or sessionStorage.\n *\n * Uses localStorage by default for persistent caching across sessions.\n * Use sessionStorage for per-session caching that clears when the tab is closed.\n *\n * @example localStorage (default, persistent)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache(),\n * cacheTtl: 300 // 5 minutes\n * })\n *\n * @example sessionStorage (per-session)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache({ storage: 'sessionStorage' }),\n * cacheTtl: 300\n * })\n *\n * @example Custom prefix\n * const cache = new BrowserCache({ prefix: 'myapp:carddb:' })\n */\nexport class BrowserCache implements Cache {\n private storage: Storage\n private prefix: string\n\n constructor(options: { storage?: StorageType; prefix?: string } = {}) {\n const storageType = options.storage ?? 'localStorage'\n this.storage =\n storageType === 'sessionStorage' ? globalThis.sessionStorage : globalThis.localStorage\n this.prefix = options.prefix ?? 'carddb:'\n }\n\n /**\n * Get a value from the cache\n */\n get<T>(key: string): T | null {\n try {\n const raw = this.storage.getItem(this.prefix + key)\n if (!raw) return null\n\n const entry = JSON.parse(raw) as CacheEntry<T>\n\n // Check if expired\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.storage.removeItem(this.prefix + key)\n return null\n }\n\n return entry.value\n } catch {\n // If parsing fails, remove the invalid entry\n this.storage.removeItem(this.prefix + key)\n return null\n }\n }\n\n /**\n * Set a value in the cache\n *\n * @param key - The cache key\n * @param value - The value to cache (must be JSON-serializable)\n * @param ttl - Time to live in seconds (optional, undefined = no expiry)\n */\n set<T>(key: string, value: T, ttl?: number): void {\n try {\n const entry: CacheEntry<T> = {\n value,\n expiresAt: ttl !== undefined ? Date.now() + ttl * 1000 : null,\n }\n this.storage.setItem(this.prefix + key, JSON.stringify(entry))\n } catch (e) {\n // Storage might be full or disabled - silently fail\n // In the future, we could implement LRU eviction here\n console.warn('[CardDB] Failed to write to cache:', e)\n }\n }\n\n /**\n * Delete a value from the cache\n */\n delete(key: string): void {\n this.storage.removeItem(this.prefix + key)\n }\n\n /**\n * Clear all CardDB cached values (only keys with our prefix)\n */\n clear(): void {\n const keysToRemove: string[] = []\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n keysToRemove.push(key)\n }\n }\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n\n /**\n * Check if a key exists and is not expired\n */\n has(key: string): boolean {\n return this.get(key) !== null\n }\n\n /**\n * Get approximate number of cached entries (only counts our prefixed keys)\n */\n get size(): number {\n let count = 0\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n count++\n }\n }\n return count\n }\n\n /**\n * Clean up expired entries\n * Call this periodically if you want to reclaim storage space from expired entries\n */\n cleanup(): void {\n const now = Date.now()\n const keysToRemove: string[] = []\n\n for (let i = 0; i < this.storage.length; i++) {\n const fullKey = this.storage.key(i)\n if (fullKey && fullKey.startsWith(this.prefix)) {\n try {\n const raw = this.storage.getItem(fullKey)\n if (raw) {\n const entry = JSON.parse(raw) as CacheEntry<unknown>\n if (entry.expiresAt !== null && now > entry.expiresAt) {\n keysToRemove.push(fullKey)\n }\n }\n } catch {\n // Invalid entry, remove it\n keysToRemove.push(fullKey)\n }\n }\n }\n\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/cache.ts","../src/index.ts"],"names":["SharedCardDBClient","RestrictedError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Browser-based cache implementations using localStorage/sessionStorage\n */\n\nimport type { Cache } from '@carddb/core'\n\ninterface CacheEntry<T> {\n value: T\n expiresAt: number | null\n}\n\ntype StorageType = 'localStorage' | 'sessionStorage'\n\n/**\n * Browser cache using localStorage or sessionStorage.\n *\n * Uses localStorage by default for persistent caching across sessions.\n * Use sessionStorage for per-session caching that clears when the tab is closed.\n *\n * @example localStorage (default, persistent)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache(),\n * cacheTtl: 300 // 5 minutes\n * })\n *\n * @example sessionStorage (per-session)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache({ storage: 'sessionStorage' }),\n * cacheTtl: 300\n * })\n *\n * @example Custom prefix\n * const cache = new BrowserCache({ prefix: 'myapp:carddb:' })\n */\nexport class BrowserCache implements Cache {\n private storage: Storage\n private prefix: string\n\n constructor(options: { storage?: StorageType; prefix?: string } = {}) {\n const storageType = options.storage ?? 'localStorage'\n this.storage =\n storageType === 'sessionStorage' ? globalThis.sessionStorage : globalThis.localStorage\n this.prefix = options.prefix ?? 'carddb:'\n }\n\n /**\n * Get a value from the cache\n */\n get<T>(key: string): T | null {\n try {\n const raw = this.storage.getItem(this.prefix + key)\n if (!raw) return null\n\n const entry = JSON.parse(raw) as CacheEntry<T>\n\n // Check if expired\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.storage.removeItem(this.prefix + key)\n return null\n }\n\n return entry.value\n } catch {\n // If parsing fails, remove the invalid entry\n this.storage.removeItem(this.prefix + key)\n return null\n }\n }\n\n /**\n * Set a value in the cache\n *\n * @param key - The cache key\n * @param value - The value to cache (must be JSON-serializable)\n * @param ttl - Time to live in seconds (optional, undefined = no expiry)\n */\n set<T>(key: string, value: T, ttl?: number): void {\n try {\n const entry: CacheEntry<T> = {\n value,\n expiresAt: ttl !== undefined ? Date.now() + ttl * 1000 : null,\n }\n this.storage.setItem(this.prefix + key, JSON.stringify(entry))\n } catch (e) {\n // Storage might be full or disabled - silently fail\n // In the future, we could implement LRU eviction here\n console.warn('[CardDB] Failed to write to cache:', e)\n }\n }\n\n /**\n * Delete a value from the cache\n */\n delete(key: string): void {\n this.storage.removeItem(this.prefix + key)\n }\n\n /**\n * Clear all CardDB cached values (only keys with our prefix)\n */\n clear(): void {\n const keysToRemove: string[] = []\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n keysToRemove.push(key)\n }\n }\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n\n /**\n * Check if a key exists and is not expired\n */\n has(key: string): boolean {\n return this.get(key) !== null\n }\n\n /**\n * Get approximate number of cached entries (only counts our prefixed keys)\n */\n get size(): number {\n let count = 0\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n count++\n }\n }\n return count\n }\n\n /**\n * Clean up expired entries\n * Call this periodically if you want to reclaim storage space from expired entries\n */\n cleanup(): void {\n const now = Date.now()\n const keysToRemove: string[] = []\n\n for (let i = 0; i < this.storage.length; i++) {\n const fullKey = this.storage.key(i)\n if (fullKey && fullKey.startsWith(this.prefix)) {\n try {\n const raw = this.storage.getItem(fullKey)\n if (raw) {\n const entry = JSON.parse(raw) as CacheEntry<unknown>\n if (entry.expiresAt !== null && now > entry.expiresAt) {\n keysToRemove.push(fullKey)\n }\n }\n } catch {\n // Invalid entry, remove it\n keysToRemove.push(fullKey)\n }\n }\n }\n\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n}\n","/**\n * @carddb/browser - CardDB client for browsers\n *\n * @example\n * import { CardDBClient, BrowserCache, gte, ilike } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * publishableKey: 'carddb_pk_xxx...',\n * cache: new BrowserCache(), // localStorage-based\n * defaultPublisher: 'pokemon',\n * defaultGame: 'tcg'\n * })\n *\n * // Search for cards with filtering\n * const cards = await client.records.search({\n * datasetKey: 'cards',\n * filter: f => f\n * .where('hp', gte(100))\n * .where('name', ilike('%pikachu%'))\n * })\n *\n * // Iterate through all results (auto-paginates)\n * for await (const card of cards) {\n * console.log(card.data.name)\n * }\n *\n * @example Session-based caching\n * const client = new CardDBClient({\n * cache: new BrowserCache({ storage: 'sessionStorage' })\n * })\n */\n\nimport { CardDBClient as SharedCardDBClient } from '@carddb/client'\nimport { RestrictedError } from '@carddb/core'\nimport type { CardDBConfig } from '@carddb/core'\n\nexport type BrowserCardDBConfig = Omit<CardDBConfig, 'apiKey' | 'secretKey'> & {\n /** Legacy apiKey is ambiguous in browsers; use publishableKey or accessToken. */\n apiKey?: never\n /** Secret keys are server-only and are rejected by the browser client. */\n secretKey?: never\n}\n\nexport class CardDBClient extends SharedCardDBClient {\n constructor(config: BrowserCardDBConfig = {}) {\n if ('apiKey' in config && config.apiKey !== undefined) {\n throw new RestrictedError(\n 'apiKey is not accepted in browsers; use publishableKey or accessToken'\n )\n }\n\n if ('secretKey' in config && config.secretKey !== undefined) {\n throw new RestrictedError(\n 'secretKey is server-only; use publishableKey or accessToken in browsers'\n )\n }\n\n super(config)\n }\n}\n\n// Browser-specific cache implementation\nexport { BrowserCache } from './cache.js'\n\n// Re-export everything from @carddb/client\nexport * from '@carddb/client'\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CardDBClient as CardDBClient$1 } from '@carddb/client';
|
|
2
2
|
export * from '@carddb/client';
|
|
3
|
+
import { Cache, CardDBConfig } from '@carddb/core';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Browser-based cache implementations using localStorage/sessionStorage
|
|
@@ -73,4 +74,46 @@ declare class BrowserCache implements Cache {
|
|
|
73
74
|
cleanup(): void;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
/**
|
|
78
|
+
* @carddb/browser - CardDB client for browsers
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* import { CardDBClient, BrowserCache, gte, ilike } from '@carddb/browser'
|
|
82
|
+
*
|
|
83
|
+
* const client = new CardDBClient({
|
|
84
|
+
* publishableKey: 'carddb_pk_xxx...',
|
|
85
|
+
* cache: new BrowserCache(), // localStorage-based
|
|
86
|
+
* defaultPublisher: 'pokemon',
|
|
87
|
+
* defaultGame: 'tcg'
|
|
88
|
+
* })
|
|
89
|
+
*
|
|
90
|
+
* // Search for cards with filtering
|
|
91
|
+
* const cards = await client.records.search({
|
|
92
|
+
* datasetKey: 'cards',
|
|
93
|
+
* filter: f => f
|
|
94
|
+
* .where('hp', gte(100))
|
|
95
|
+
* .where('name', ilike('%pikachu%'))
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* // Iterate through all results (auto-paginates)
|
|
99
|
+
* for await (const card of cards) {
|
|
100
|
+
* console.log(card.data.name)
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* @example Session-based caching
|
|
104
|
+
* const client = new CardDBClient({
|
|
105
|
+
* cache: new BrowserCache({ storage: 'sessionStorage' })
|
|
106
|
+
* })
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
type BrowserCardDBConfig = Omit<CardDBConfig, 'apiKey' | 'secretKey'> & {
|
|
110
|
+
/** Legacy apiKey is ambiguous in browsers; use publishableKey or accessToken. */
|
|
111
|
+
apiKey?: never;
|
|
112
|
+
/** Secret keys are server-only and are rejected by the browser client. */
|
|
113
|
+
secretKey?: never;
|
|
114
|
+
};
|
|
115
|
+
declare class CardDBClient extends CardDBClient$1 {
|
|
116
|
+
constructor(config?: BrowserCardDBConfig);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { BrowserCache, type BrowserCardDBConfig, CardDBClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CardDBClient as CardDBClient$1 } from '@carddb/client';
|
|
2
2
|
export * from '@carddb/client';
|
|
3
|
+
import { Cache, CardDBConfig } from '@carddb/core';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Browser-based cache implementations using localStorage/sessionStorage
|
|
@@ -73,4 +74,46 @@ declare class BrowserCache implements Cache {
|
|
|
73
74
|
cleanup(): void;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
|
|
77
|
+
/**
|
|
78
|
+
* @carddb/browser - CardDB client for browsers
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* import { CardDBClient, BrowserCache, gte, ilike } from '@carddb/browser'
|
|
82
|
+
*
|
|
83
|
+
* const client = new CardDBClient({
|
|
84
|
+
* publishableKey: 'carddb_pk_xxx...',
|
|
85
|
+
* cache: new BrowserCache(), // localStorage-based
|
|
86
|
+
* defaultPublisher: 'pokemon',
|
|
87
|
+
* defaultGame: 'tcg'
|
|
88
|
+
* })
|
|
89
|
+
*
|
|
90
|
+
* // Search for cards with filtering
|
|
91
|
+
* const cards = await client.records.search({
|
|
92
|
+
* datasetKey: 'cards',
|
|
93
|
+
* filter: f => f
|
|
94
|
+
* .where('hp', gte(100))
|
|
95
|
+
* .where('name', ilike('%pikachu%'))
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* // Iterate through all results (auto-paginates)
|
|
99
|
+
* for await (const card of cards) {
|
|
100
|
+
* console.log(card.data.name)
|
|
101
|
+
* }
|
|
102
|
+
*
|
|
103
|
+
* @example Session-based caching
|
|
104
|
+
* const client = new CardDBClient({
|
|
105
|
+
* cache: new BrowserCache({ storage: 'sessionStorage' })
|
|
106
|
+
* })
|
|
107
|
+
*/
|
|
108
|
+
|
|
109
|
+
type BrowserCardDBConfig = Omit<CardDBConfig, 'apiKey' | 'secretKey'> & {
|
|
110
|
+
/** Legacy apiKey is ambiguous in browsers; use publishableKey or accessToken. */
|
|
111
|
+
apiKey?: never;
|
|
112
|
+
/** Secret keys are server-only and are rejected by the browser client. */
|
|
113
|
+
secretKey?: never;
|
|
114
|
+
};
|
|
115
|
+
declare class CardDBClient extends CardDBClient$1 {
|
|
116
|
+
constructor(config?: BrowserCardDBConfig);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { BrowserCache, type BrowserCardDBConfig, CardDBClient };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { CardDBClient as CardDBClient$1 } from '@carddb/client';
|
|
1
2
|
export * from '@carddb/client';
|
|
3
|
+
import { RestrictedError } from '@carddb/core';
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
2
6
|
|
|
3
7
|
// src/cache.ts
|
|
4
8
|
var BrowserCache = class {
|
|
@@ -113,7 +117,22 @@ var BrowserCache = class {
|
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
119
|
};
|
|
120
|
+
var CardDBClient = class extends CardDBClient$1 {
|
|
121
|
+
constructor(config = {}) {
|
|
122
|
+
if ("apiKey" in config && config.apiKey !== void 0) {
|
|
123
|
+
throw new RestrictedError(
|
|
124
|
+
"apiKey is not accepted in browsers; use publishableKey or accessToken"
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
if ("secretKey" in config && config.secretKey !== void 0) {
|
|
128
|
+
throw new RestrictedError(
|
|
129
|
+
"secretKey is server-only; use publishableKey or accessToken in browsers"
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
super(config);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
116
135
|
|
|
117
|
-
export { BrowserCache };
|
|
136
|
+
export { BrowserCache, CardDBClient };
|
|
118
137
|
//# sourceMappingURL=index.js.map
|
|
119
138
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Browser-based cache implementations using localStorage/sessionStorage\n */\n\nimport type { Cache } from '@carddb/core'\n\ninterface CacheEntry<T> {\n value: T\n expiresAt: number | null\n}\n\ntype StorageType = 'localStorage' | 'sessionStorage'\n\n/**\n * Browser cache using localStorage or sessionStorage.\n *\n * Uses localStorage by default for persistent caching across sessions.\n * Use sessionStorage for per-session caching that clears when the tab is closed.\n *\n * @example localStorage (default, persistent)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache(),\n * cacheTtl: 300 // 5 minutes\n * })\n *\n * @example sessionStorage (per-session)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache({ storage: 'sessionStorage' }),\n * cacheTtl: 300\n * })\n *\n * @example Custom prefix\n * const cache = new BrowserCache({ prefix: 'myapp:carddb:' })\n */\nexport class BrowserCache implements Cache {\n private storage: Storage\n private prefix: string\n\n constructor(options: { storage?: StorageType; prefix?: string } = {}) {\n const storageType = options.storage ?? 'localStorage'\n this.storage =\n storageType === 'sessionStorage' ? globalThis.sessionStorage : globalThis.localStorage\n this.prefix = options.prefix ?? 'carddb:'\n }\n\n /**\n * Get a value from the cache\n */\n get<T>(key: string): T | null {\n try {\n const raw = this.storage.getItem(this.prefix + key)\n if (!raw) return null\n\n const entry = JSON.parse(raw) as CacheEntry<T>\n\n // Check if expired\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.storage.removeItem(this.prefix + key)\n return null\n }\n\n return entry.value\n } catch {\n // If parsing fails, remove the invalid entry\n this.storage.removeItem(this.prefix + key)\n return null\n }\n }\n\n /**\n * Set a value in the cache\n *\n * @param key - The cache key\n * @param value - The value to cache (must be JSON-serializable)\n * @param ttl - Time to live in seconds (optional, undefined = no expiry)\n */\n set<T>(key: string, value: T, ttl?: number): void {\n try {\n const entry: CacheEntry<T> = {\n value,\n expiresAt: ttl !== undefined ? Date.now() + ttl * 1000 : null,\n }\n this.storage.setItem(this.prefix + key, JSON.stringify(entry))\n } catch (e) {\n // Storage might be full or disabled - silently fail\n // In the future, we could implement LRU eviction here\n console.warn('[CardDB] Failed to write to cache:', e)\n }\n }\n\n /**\n * Delete a value from the cache\n */\n delete(key: string): void {\n this.storage.removeItem(this.prefix + key)\n }\n\n /**\n * Clear all CardDB cached values (only keys with our prefix)\n */\n clear(): void {\n const keysToRemove: string[] = []\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n keysToRemove.push(key)\n }\n }\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n\n /**\n * Check if a key exists and is not expired\n */\n has(key: string): boolean {\n return this.get(key) !== null\n }\n\n /**\n * Get approximate number of cached entries (only counts our prefixed keys)\n */\n get size(): number {\n let count = 0\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n count++\n }\n }\n return count\n }\n\n /**\n * Clean up expired entries\n * Call this periodically if you want to reclaim storage space from expired entries\n */\n cleanup(): void {\n const now = Date.now()\n const keysToRemove: string[] = []\n\n for (let i = 0; i < this.storage.length; i++) {\n const fullKey = this.storage.key(i)\n if (fullKey && fullKey.startsWith(this.prefix)) {\n try {\n const raw = this.storage.getItem(fullKey)\n if (raw) {\n const entry = JSON.parse(raw) as CacheEntry<unknown>\n if (entry.expiresAt !== null && now > entry.expiresAt) {\n keysToRemove.push(fullKey)\n }\n }\n } catch {\n // Invalid entry, remove it\n keysToRemove.push(fullKey)\n }\n }\n }\n\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/cache.ts","../src/index.ts"],"names":["SharedCardDBClient"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Browser-based cache implementations using localStorage/sessionStorage\n */\n\nimport type { Cache } from '@carddb/core'\n\ninterface CacheEntry<T> {\n value: T\n expiresAt: number | null\n}\n\ntype StorageType = 'localStorage' | 'sessionStorage'\n\n/**\n * Browser cache using localStorage or sessionStorage.\n *\n * Uses localStorage by default for persistent caching across sessions.\n * Use sessionStorage for per-session caching that clears when the tab is closed.\n *\n * @example localStorage (default, persistent)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache(),\n * cacheTtl: 300 // 5 minutes\n * })\n *\n * @example sessionStorage (per-session)\n * import { CardDBClient, BrowserCache } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * cache: new BrowserCache({ storage: 'sessionStorage' }),\n * cacheTtl: 300\n * })\n *\n * @example Custom prefix\n * const cache = new BrowserCache({ prefix: 'myapp:carddb:' })\n */\nexport class BrowserCache implements Cache {\n private storage: Storage\n private prefix: string\n\n constructor(options: { storage?: StorageType; prefix?: string } = {}) {\n const storageType = options.storage ?? 'localStorage'\n this.storage =\n storageType === 'sessionStorage' ? globalThis.sessionStorage : globalThis.localStorage\n this.prefix = options.prefix ?? 'carddb:'\n }\n\n /**\n * Get a value from the cache\n */\n get<T>(key: string): T | null {\n try {\n const raw = this.storage.getItem(this.prefix + key)\n if (!raw) return null\n\n const entry = JSON.parse(raw) as CacheEntry<T>\n\n // Check if expired\n if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {\n this.storage.removeItem(this.prefix + key)\n return null\n }\n\n return entry.value\n } catch {\n // If parsing fails, remove the invalid entry\n this.storage.removeItem(this.prefix + key)\n return null\n }\n }\n\n /**\n * Set a value in the cache\n *\n * @param key - The cache key\n * @param value - The value to cache (must be JSON-serializable)\n * @param ttl - Time to live in seconds (optional, undefined = no expiry)\n */\n set<T>(key: string, value: T, ttl?: number): void {\n try {\n const entry: CacheEntry<T> = {\n value,\n expiresAt: ttl !== undefined ? Date.now() + ttl * 1000 : null,\n }\n this.storage.setItem(this.prefix + key, JSON.stringify(entry))\n } catch (e) {\n // Storage might be full or disabled - silently fail\n // In the future, we could implement LRU eviction here\n console.warn('[CardDB] Failed to write to cache:', e)\n }\n }\n\n /**\n * Delete a value from the cache\n */\n delete(key: string): void {\n this.storage.removeItem(this.prefix + key)\n }\n\n /**\n * Clear all CardDB cached values (only keys with our prefix)\n */\n clear(): void {\n const keysToRemove: string[] = []\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n keysToRemove.push(key)\n }\n }\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n\n /**\n * Check if a key exists and is not expired\n */\n has(key: string): boolean {\n return this.get(key) !== null\n }\n\n /**\n * Get approximate number of cached entries (only counts our prefixed keys)\n */\n get size(): number {\n let count = 0\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i)\n if (key && key.startsWith(this.prefix)) {\n count++\n }\n }\n return count\n }\n\n /**\n * Clean up expired entries\n * Call this periodically if you want to reclaim storage space from expired entries\n */\n cleanup(): void {\n const now = Date.now()\n const keysToRemove: string[] = []\n\n for (let i = 0; i < this.storage.length; i++) {\n const fullKey = this.storage.key(i)\n if (fullKey && fullKey.startsWith(this.prefix)) {\n try {\n const raw = this.storage.getItem(fullKey)\n if (raw) {\n const entry = JSON.parse(raw) as CacheEntry<unknown>\n if (entry.expiresAt !== null && now > entry.expiresAt) {\n keysToRemove.push(fullKey)\n }\n }\n } catch {\n // Invalid entry, remove it\n keysToRemove.push(fullKey)\n }\n }\n }\n\n for (const key of keysToRemove) {\n this.storage.removeItem(key)\n }\n }\n}\n","/**\n * @carddb/browser - CardDB client for browsers\n *\n * @example\n * import { CardDBClient, BrowserCache, gte, ilike } from '@carddb/browser'\n *\n * const client = new CardDBClient({\n * publishableKey: 'carddb_pk_xxx...',\n * cache: new BrowserCache(), // localStorage-based\n * defaultPublisher: 'pokemon',\n * defaultGame: 'tcg'\n * })\n *\n * // Search for cards with filtering\n * const cards = await client.records.search({\n * datasetKey: 'cards',\n * filter: f => f\n * .where('hp', gte(100))\n * .where('name', ilike('%pikachu%'))\n * })\n *\n * // Iterate through all results (auto-paginates)\n * for await (const card of cards) {\n * console.log(card.data.name)\n * }\n *\n * @example Session-based caching\n * const client = new CardDBClient({\n * cache: new BrowserCache({ storage: 'sessionStorage' })\n * })\n */\n\nimport { CardDBClient as SharedCardDBClient } from '@carddb/client'\nimport { RestrictedError } from '@carddb/core'\nimport type { CardDBConfig } from '@carddb/core'\n\nexport type BrowserCardDBConfig = Omit<CardDBConfig, 'apiKey' | 'secretKey'> & {\n /** Legacy apiKey is ambiguous in browsers; use publishableKey or accessToken. */\n apiKey?: never\n /** Secret keys are server-only and are rejected by the browser client. */\n secretKey?: never\n}\n\nexport class CardDBClient extends SharedCardDBClient {\n constructor(config: BrowserCardDBConfig = {}) {\n if ('apiKey' in config && config.apiKey !== undefined) {\n throw new RestrictedError(\n 'apiKey is not accepted in browsers; use publishableKey or accessToken'\n )\n }\n\n if ('secretKey' in config && config.secretKey !== undefined) {\n throw new RestrictedError(\n 'secretKey is server-only; use publishableKey or accessToken in browsers'\n )\n }\n\n super(config)\n }\n}\n\n// Browser-specific cache implementation\nexport { BrowserCache } from './cache.js'\n\n// Re-export everything from @carddb/client\nexport * from '@carddb/client'\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carddb/browser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CardDB client for browsers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"url": "https://github.com/carddb/carddb-js/issues"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@carddb/client": "0.
|
|
53
|
-
"@carddb/core": "0.
|
|
52
|
+
"@carddb/client": "0.2.0",
|
|
53
|
+
"@carddb/core": "0.2.0"
|
|
54
54
|
},
|
|
55
55
|
"sideEffects": false
|
|
56
56
|
}
|