keyv-registry 0.1.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.
Files changed (47) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +202 -0
  3. package/dist/cjs/index.d.cts +37 -0
  4. package/dist/cjs/index.d.ts +37 -0
  5. package/dist/cjs/index.js +82 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/cjs/loadAdapter.d.cts +9 -0
  8. package/dist/cjs/loadAdapter.d.ts +9 -0
  9. package/dist/cjs/loadAdapter.js +74 -0
  10. package/dist/cjs/loadAdapter.js.map +1 -0
  11. package/dist/cjs/package.json +1 -0
  12. package/dist/cjs/registry.d.cts +13 -0
  13. package/dist/cjs/registry.d.ts +13 -0
  14. package/dist/cjs/registry.js +119 -0
  15. package/dist/cjs/registry.js.map +1 -0
  16. package/dist/cjs/types.d.cts +33 -0
  17. package/dist/cjs/types.d.ts +33 -0
  18. package/dist/cjs/types.js +5 -0
  19. package/dist/cjs/types.js.map +1 -0
  20. package/dist/cjs/utils.d.cts +8 -0
  21. package/dist/cjs/utils.d.ts +8 -0
  22. package/dist/cjs/utils.js +152 -0
  23. package/dist/cjs/utils.js.map +1 -0
  24. package/dist/cjs/worker.d.cts +5 -0
  25. package/dist/cjs/worker.d.ts +5 -0
  26. package/dist/cjs/worker.js +138 -0
  27. package/dist/cjs/worker.js.map +1 -0
  28. package/dist/esm/index.d.ts +37 -0
  29. package/dist/esm/index.js +50 -0
  30. package/dist/esm/index.js.map +1 -0
  31. package/dist/esm/loadAdapter.d.ts +9 -0
  32. package/dist/esm/loadAdapter.js +52 -0
  33. package/dist/esm/loadAdapter.js.map +1 -0
  34. package/dist/esm/package.json +1 -0
  35. package/dist/esm/registry.d.ts +13 -0
  36. package/dist/esm/registry.js +73 -0
  37. package/dist/esm/registry.js.map +1 -0
  38. package/dist/esm/types.d.ts +33 -0
  39. package/dist/esm/types.js +3 -0
  40. package/dist/esm/types.js.map +1 -0
  41. package/dist/esm/utils.d.ts +8 -0
  42. package/dist/esm/utils.js +33 -0
  43. package/dist/esm/utils.js.map +1 -0
  44. package/dist/esm/worker.d.ts +5 -0
  45. package/dist/esm/worker.js +75 -0
  46. package/dist/esm/worker.js.map +1 -0
  47. package/package.json +62 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Kevin Malakoff
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,202 @@
1
+ # keyv-registry
2
+
3
+ Protocol-based Keyv adapter registry with dynamic module installation.
4
+
5
+ Create Keyv stores from URI strings with automatic adapter resolution and on-demand installation.
6
+
7
+ ## Features
8
+
9
+ - **URI-based configuration**: Use familiar connection strings like `redis://localhost:6379`
10
+ - **Dynamic installation**: Adapters are installed on-demand, no hard dependencies
11
+ - **Extensible registry**: Register custom protocols or override defaults
12
+ - **Dual-boot API**: Supports both Promise and callback patterns
13
+ - **URI parameter mapping**: Query params automatically converted to adapter options
14
+ - **Store passthrough**: Use pre-instantiated adapters when needed
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install keyv-registry
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### Promise API
25
+
26
+ ```typescript
27
+ import createStore from 'keyv-registry';
28
+
29
+ // Redis
30
+ const redis = await createStore('redis://localhost:6379');
31
+
32
+ // PostgreSQL
33
+ const postgres = await createStore('postgresql://user:pass@localhost/db');
34
+
35
+ // File-based storage
36
+ const file = await createStore('file://~/.cache/myapp/data.json');
37
+
38
+ // In-memory (built-in, no package needed)
39
+ const memory = await createStore('memory://');
40
+
41
+ // SQLite
42
+ const sqlite = await createStore('sqlite:///path/to/db.sqlite');
43
+
44
+ // With options
45
+ const store = await createStore('redis://localhost:6379', {
46
+ namespace: 'myapp',
47
+ ttl: 60000
48
+ });
49
+ ```
50
+
51
+ ### Callback API
52
+
53
+ ```typescript
54
+ import createStore from 'keyv-registry';
55
+
56
+ createStore('redis://localhost:6379', (err, store) => {
57
+ if (err) throw err;
58
+ // use store
59
+ });
60
+
61
+ // With options
62
+ createStore('redis://localhost:6379', { namespace: 'myapp' }, (err, store) => {
63
+ if (err) throw err;
64
+ // use store
65
+ });
66
+ ```
67
+
68
+ ### URI Query Parameters
69
+
70
+ Query parameters are automatically converted to adapter options:
71
+
72
+ ```typescript
73
+ // Equivalent to { keyPrefix: 'myapp', ttl: 3600 }
74
+ const store = await createStore('redis://localhost:6379?keyPrefix=myapp&ttl=3600');
75
+
76
+ // Boolean and number conversion is automatic
77
+ const file = await createStore('file://~/data.json?writeDelay=100&pretty=true');
78
+ ```
79
+
80
+ ### Custom Adapters
81
+
82
+ Register custom protocols or override defaults:
83
+
84
+ ```typescript
85
+ import createStore, { registerAdapter } from 'keyv-registry';
86
+
87
+ // Register a new protocol
88
+ registerAdapter('cloudflare:', { package: 'keyv-cloudflare' });
89
+ const cf = await createStore('cloudflare://my-namespace');
90
+
91
+ // Override default with custom package
92
+ registerAdapter('file:', {
93
+ package: '@my-org/keyv-file-encrypted',
94
+ optionsMapper: (url) => ({
95
+ filename: url.pathname,
96
+ encryption: true
97
+ })
98
+ });
99
+ ```
100
+
101
+ ### Pre-instantiated Adapter Passthrough
102
+
103
+ For advanced configuration, pass a pre-instantiated adapter:
104
+
105
+ ```typescript
106
+ import createStore from 'keyv-registry';
107
+ import KeyvRedis from '@keyv/redis';
108
+
109
+ const customRedis = new KeyvRedis('redis://localhost:6379', {
110
+ useUnlink: true,
111
+ cluster: true
112
+ });
113
+
114
+ // URI is ignored when store option is provided
115
+ const store = await createStore('redis://ignored', { store: customRedis });
116
+ ```
117
+
118
+ ## Supported Protocols
119
+
120
+ ### Official @keyv Adapters
121
+
122
+ | Protocol | Package | Notes |
123
+ |----------|---------|-------|
124
+ | `redis://`, `rediss://` | `@keyv/redis` | Redis, supports TLS |
125
+ | `postgresql://`, `postgres://` | `@keyv/postgres` | PostgreSQL |
126
+ | `mysql://` | `@keyv/mysql` | MySQL/MariaDB |
127
+ | `sqlite://` | `@keyv/sqlite` | SQLite |
128
+ | `mongodb://`, `mongodb+srv://` | `@keyv/mongo` | MongoDB |
129
+ | `memcache://` | `@keyv/memcache` | Memcached |
130
+ | `etcd://` | `@keyv/etcd` | etcd |
131
+
132
+ ### Third-party Adapters
133
+
134
+ | Protocol | Package | Notes |
135
+ |----------|---------|-------|
136
+ | `file://` | `keyv-file` | File-based JSON storage |
137
+ | `duckdb://` | `keyv-duckdb` | DuckDB (planned) |
138
+
139
+ ### Built-in
140
+
141
+ | Protocol | Notes |
142
+ |----------|-------|
143
+ | `memory://` | In-memory Map, no package needed |
144
+
145
+ ## API
146
+
147
+ ### `createStore(uri, [options], [callback])`
148
+
149
+ Create a Keyv store from a URI string.
150
+
151
+ **Parameters:**
152
+ - `uri` (string): Connection URI with protocol
153
+ - `options` (object, optional): Keyv options
154
+ - `store`: Pre-instantiated adapter (bypasses URI loading)
155
+ - `namespace`: Keyv namespace
156
+ - `ttl`: Default TTL in milliseconds
157
+ - Additional options passed to Keyv
158
+ - `callback` (function, optional): Node-style callback `(err, store) => void`
159
+
160
+ **Returns:** `Promise<Keyv>` if no callback, `undefined` if callback provided
161
+
162
+ ### `registerAdapter(protocol, config)`
163
+
164
+ Register or override a protocol adapter.
165
+
166
+ **Parameters:**
167
+ - `protocol` (string): Protocol with or without trailing colon (e.g., `'redis:'` or `'redis'`)
168
+ - `config` (object): Adapter configuration
169
+ - `package`: npm package name, or `null` for built-in
170
+ - `exportName`: Named export (default: `'default'`)
171
+ - `optionsMapper`: Function `(url: URL) => object` to map URL to options
172
+
173
+ ### `getRegistry()`
174
+
175
+ Get a read-only copy of the current protocol registry.
176
+
177
+ **Returns:** `Record<string, AdapterConfig>`
178
+
179
+ ### `clearAdapterCache()`
180
+
181
+ Clear the loaded adapter cache. Useful for testing.
182
+
183
+ ## File Path Shortcuts
184
+
185
+ The `file://` protocol supports path shortcuts:
186
+
187
+ ```typescript
188
+ // Home directory
189
+ await createStore('file://~/.cache/myapp/data.json');
190
+
191
+ // Current working directory
192
+ await createStore('file://./data/cache.json');
193
+
194
+ // Absolute path
195
+ await createStore('file:///var/cache/myapp/data.json');
196
+ ```
197
+
198
+ Directories are created automatically if they don't exist.
199
+
200
+ ## License
201
+
202
+ MIT
@@ -0,0 +1,37 @@
1
+ import type Keyv from 'keyv';
2
+ import type { CreateStoreCallback, CreateStoreOptions } from './types.js';
3
+ export { clearAdapterCache } from './loadAdapter.js';
4
+ export { getRegistry, registerAdapter } from './registry.js';
5
+ export type { AdapterConfig, CreateStoreCallback, CreateStoreOptions } from './types.js';
6
+ /**
7
+ * Create a Keyv store from a URI string
8
+ *
9
+ * Supports dual-boot API (callback or Promise):
10
+ *
11
+ * @example
12
+ * // Promise API
13
+ * const store = await createStore('redis://localhost:6379');
14
+ * const file = await createStore('file://~/.cache/app/data.json');
15
+ * const memory = await createStore('memory://');
16
+ *
17
+ * @example
18
+ * // Callback API
19
+ * createStore('redis://localhost:6379', (err, store) => {
20
+ * if (err) throw err;
21
+ * // use store
22
+ * });
23
+ *
24
+ * @example
25
+ * // With options
26
+ * const store = await createStore('redis://localhost:6379', {
27
+ * namespace: 'myapp',
28
+ * ttl: 60000
29
+ * });
30
+ *
31
+ * @example
32
+ * // Pre-instantiated adapter passthrough
33
+ * import KeyvRedis from '@keyv/redis';
34
+ * const redis = new KeyvRedis('redis://localhost:6379');
35
+ * const store = await createStore('redis://ignored', { store: redis });
36
+ */
37
+ export default function createStore<T>(uri: string, options?: CreateStoreOptions | CreateStoreCallback<T>, callback?: CreateStoreCallback<T>): undefined | Promise<Keyv<T>>;
@@ -0,0 +1,37 @@
1
+ import type Keyv from 'keyv';
2
+ import type { CreateStoreCallback, CreateStoreOptions } from './types.js';
3
+ export { clearAdapterCache } from './loadAdapter.js';
4
+ export { getRegistry, registerAdapter } from './registry.js';
5
+ export type { AdapterConfig, CreateStoreCallback, CreateStoreOptions } from './types.js';
6
+ /**
7
+ * Create a Keyv store from a URI string
8
+ *
9
+ * Supports dual-boot API (callback or Promise):
10
+ *
11
+ * @example
12
+ * // Promise API
13
+ * const store = await createStore('redis://localhost:6379');
14
+ * const file = await createStore('file://~/.cache/app/data.json');
15
+ * const memory = await createStore('memory://');
16
+ *
17
+ * @example
18
+ * // Callback API
19
+ * createStore('redis://localhost:6379', (err, store) => {
20
+ * if (err) throw err;
21
+ * // use store
22
+ * });
23
+ *
24
+ * @example
25
+ * // With options
26
+ * const store = await createStore('redis://localhost:6379', {
27
+ * namespace: 'myapp',
28
+ * ttl: 60000
29
+ * });
30
+ *
31
+ * @example
32
+ * // Pre-instantiated adapter passthrough
33
+ * import KeyvRedis from '@keyv/redis';
34
+ * const redis = new KeyvRedis('redis://localhost:6379');
35
+ * const store = await createStore('redis://ignored', { store: redis });
36
+ */
37
+ export default function createStore<T>(uri: string, options?: CreateStoreOptions | CreateStoreCallback<T>, callback?: CreateStoreCallback<T>): undefined | Promise<Keyv<T>>;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get clearAdapterCache () {
13
+ return _loadAdapterts.clearAdapterCache;
14
+ },
15
+ get /**
16
+ * Create a Keyv store from a URI string
17
+ *
18
+ * Supports dual-boot API (callback or Promise):
19
+ *
20
+ * @example
21
+ * // Promise API
22
+ * const store = await createStore('redis://localhost:6379');
23
+ * const file = await createStore('file://~/.cache/app/data.json');
24
+ * const memory = await createStore('memory://');
25
+ *
26
+ * @example
27
+ * // Callback API
28
+ * createStore('redis://localhost:6379', (err, store) => {
29
+ * if (err) throw err;
30
+ * // use store
31
+ * });
32
+ *
33
+ * @example
34
+ * // With options
35
+ * const store = await createStore('redis://localhost:6379', {
36
+ * namespace: 'myapp',
37
+ * ttl: 60000
38
+ * });
39
+ *
40
+ * @example
41
+ * // Pre-instantiated adapter passthrough
42
+ * import KeyvRedis from '@keyv/redis';
43
+ * const redis = new KeyvRedis('redis://localhost:6379');
44
+ * const store = await createStore('redis://ignored', { store: redis });
45
+ */ default () {
46
+ return createStore;
47
+ },
48
+ get getRegistry () {
49
+ return _registryts.getRegistry;
50
+ },
51
+ get registerAdapter () {
52
+ return _registryts.registerAdapter;
53
+ }
54
+ });
55
+ var _workerts = /*#__PURE__*/ _interop_require_default(require("./worker.js"));
56
+ var _loadAdapterts = require("./loadAdapter.js");
57
+ var _registryts = require("./registry.js");
58
+ function _interop_require_default(obj) {
59
+ return obj && obj.__esModule ? obj : {
60
+ default: obj
61
+ };
62
+ }
63
+ function createStore(uri, options, callback) {
64
+ // Normalize arguments
65
+ if (typeof options === 'function') {
66
+ callback = options;
67
+ options = {};
68
+ }
69
+ options = options || {};
70
+ // Callback mode
71
+ if (typeof callback === 'function') {
72
+ (0, _workerts.default)(uri, options, callback);
73
+ return undefined;
74
+ }
75
+ // Promise mode
76
+ return new Promise(function(resolve, reject) {
77
+ (0, _workerts.default)(uri, options, function(err, store) {
78
+ return err ? reject(err) : resolve(store);
79
+ });
80
+ });
81
+ }
82
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/keyv/keyv-registry/src/index.ts"],"sourcesContent":["import type Keyv from 'keyv';\nimport type { CreateStoreCallback, CreateStoreOptions } from './types.ts';\nimport worker from './worker.ts';\n\nexport { clearAdapterCache } from './loadAdapter.ts';\nexport { getRegistry, registerAdapter } from './registry.ts';\nexport type { AdapterConfig, CreateStoreCallback, CreateStoreOptions } from './types.ts';\n\n/**\n * Create a Keyv store from a URI string\n *\n * Supports dual-boot API (callback or Promise):\n *\n * @example\n * // Promise API\n * const store = await createStore('redis://localhost:6379');\n * const file = await createStore('file://~/.cache/app/data.json');\n * const memory = await createStore('memory://');\n *\n * @example\n * // Callback API\n * createStore('redis://localhost:6379', (err, store) => {\n * if (err) throw err;\n * // use store\n * });\n *\n * @example\n * // With options\n * const store = await createStore('redis://localhost:6379', {\n * namespace: 'myapp',\n * ttl: 60000\n * });\n *\n * @example\n * // Pre-instantiated adapter passthrough\n * import KeyvRedis from '@keyv/redis';\n * const redis = new KeyvRedis('redis://localhost:6379');\n * const store = await createStore('redis://ignored', { store: redis });\n */\nexport default function createStore<T>(uri: string, options?: CreateStoreOptions | CreateStoreCallback<T>, callback?: CreateStoreCallback<T>): undefined | Promise<Keyv<T>> {\n // Normalize arguments\n if (typeof options === 'function') {\n callback = options;\n options = {};\n }\n options = options || {};\n\n // Callback mode\n if (typeof callback === 'function') {\n worker(uri, options, callback);\n return undefined;\n }\n\n // Promise mode\n return new Promise((resolve, reject) => {\n worker(uri, options as CreateStoreOptions, (err, store) => (err ? reject(err) : resolve(store as Keyv<T>)));\n });\n}\n"],"names":["clearAdapterCache","createStore","getRegistry","registerAdapter","uri","options","callback","worker","undefined","Promise","resolve","reject","err","store"],"mappings":";;;;;;;;;;;QAISA;eAAAA,gCAAiB;;QAI1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BC,GACD;eAAwBC;;QAlCfC;eAAAA,uBAAW;;QAAEC;eAAAA,2BAAe;;;+DAHlB;6BAEe;0BACW;;;;;;AAkC9B,SAASF,YAAeG,GAAW,EAAEC,OAAqD,EAAEC,QAAiC;IAC1I,sBAAsB;IACtB,IAAI,OAAOD,YAAY,YAAY;QACjCC,WAAWD;QACXA,UAAU,CAAC;IACb;IACAA,UAAUA,WAAW,CAAC;IAEtB,gBAAgB;IAChB,IAAI,OAAOC,aAAa,YAAY;QAClCC,IAAAA,iBAAM,EAACH,KAAKC,SAASC;QACrB,OAAOE;IACT;IAEA,eAAe;IACf,OAAO,IAAIC,QAAQ,SAACC,SAASC;QAC3BJ,IAAAA,iBAAM,EAACH,KAAKC,SAA+B,SAACO,KAAKC;mBAAWD,MAAMD,OAAOC,OAAOF,QAAQG;;IAC1F;AACF"}
@@ -0,0 +1,9 @@
1
+ import type { LoadAdapterCallback } from './types.js';
2
+ /**
3
+ * Load an adapter, installing it dynamically if needed
4
+ */
5
+ export default function loadAdapter(packageName: string, exportName: string | undefined, callback: LoadAdapterCallback): void;
6
+ /**
7
+ * Clear the adapter cache (useful for testing)
8
+ */
9
+ export declare function clearAdapterCache(): void;
@@ -0,0 +1,9 @@
1
+ import type { LoadAdapterCallback } from './types.js';
2
+ /**
3
+ * Load an adapter, installing it dynamically if needed
4
+ */
5
+ export default function loadAdapter(packageName: string, exportName: string | undefined, callback: LoadAdapterCallback): void;
6
+ /**
7
+ * Clear the adapter cache (useful for testing)
8
+ */
9
+ export declare function clearAdapterCache(): void;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get clearAdapterCache () {
13
+ return clearAdapterCache;
14
+ },
15
+ get /**
16
+ * Load an adapter, installing it dynamically if needed
17
+ */ default () {
18
+ return loadAdapter;
19
+ }
20
+ });
21
+ var _nodemodule = /*#__PURE__*/ _interop_require_default(require("node:module"));
22
+ var _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
23
+ var _nodeurl = /*#__PURE__*/ _interop_require_default(require("node:url"));
24
+ var _installmodulelinked = /*#__PURE__*/ _interop_require_default(require("install-module-linked"));
25
+ function _interop_require_default(obj) {
26
+ return obj && obj.__esModule ? obj : {
27
+ default: obj
28
+ };
29
+ }
30
+ // Create require function for ESM compatibility
31
+ var _require = typeof require === 'undefined' ? _nodemodule.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
32
+ // Determine node_modules path
33
+ var _dirname = _nodepath.default.dirname(typeof __dirname !== 'undefined' ? __dirname : _nodeurl.default.fileURLToPath(require("url").pathToFileURL(__filename).toString()));
34
+ var nodeModulesPath = _nodepath.default.join(_dirname, '..', '..', 'node_modules');
35
+ // Cache loaded adapters
36
+ var adapterCache = new Map();
37
+ function loadAdapter(packageName, exportName, callback) {
38
+ var cacheKey = "".concat(packageName, ":").concat(exportName !== null && exportName !== void 0 ? exportName : 'default');
39
+ // Return cached adapter if available
40
+ if (adapterCache.has(cacheKey)) {
41
+ callback(null, adapterCache.get(cacheKey));
42
+ return;
43
+ }
44
+ // Try to require first (may already be installed)
45
+ try {
46
+ var mod = _require(packageName);
47
+ var _mod_default;
48
+ var Adapter = exportName ? mod[exportName] : (_mod_default = mod.default) !== null && _mod_default !== void 0 ? _mod_default : mod;
49
+ adapterCache.set(cacheKey, Adapter);
50
+ callback(null, Adapter);
51
+ return;
52
+ } catch (e) {
53
+ // Not installed - dynamically install then load
54
+ (0, _installmodulelinked.default)(packageName, nodeModulesPath, {}, function(err) {
55
+ if (err) {
56
+ callback(err);
57
+ return;
58
+ }
59
+ try {
60
+ var mod = _require(packageName);
61
+ var _mod_default;
62
+ var Adapter = exportName ? mod[exportName] : (_mod_default = mod.default) !== null && _mod_default !== void 0 ? _mod_default : mod;
63
+ adapterCache.set(cacheKey, Adapter);
64
+ callback(null, Adapter);
65
+ } catch (loadErr) {
66
+ callback(loadErr);
67
+ }
68
+ });
69
+ }
70
+ }
71
+ function clearAdapterCache() {
72
+ adapterCache.clear();
73
+ }
74
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/keyv/keyv-registry/src/loadAdapter.ts"],"sourcesContent":["import Module from 'node:module';\nimport path from 'node:path';\nimport url from 'node:url';\nimport installModule from 'install-module-linked';\nimport type { LoadAdapterCallback } from './types.ts';\n\n// Create require function for ESM compatibility\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\n\n// Determine node_modules path\nconst _dirname = path.dirname(typeof __dirname !== 'undefined' ? __dirname : url.fileURLToPath(import.meta.url));\nconst nodeModulesPath = path.join(_dirname, '..', '..', 'node_modules');\n\n// Cache loaded adapters\nconst adapterCache = new Map<string, unknown>();\n\n/**\n * Load an adapter, installing it dynamically if needed\n */\nexport default function loadAdapter(packageName: string, exportName: string | undefined, callback: LoadAdapterCallback): void {\n const cacheKey = `${packageName}:${exportName ?? 'default'}`;\n\n // Return cached adapter if available\n if (adapterCache.has(cacheKey)) {\n callback(null, adapterCache.get(cacheKey));\n return;\n }\n\n // Try to require first (may already be installed)\n try {\n const mod = _require(packageName);\n const Adapter = exportName ? mod[exportName] : (mod.default ?? mod);\n adapterCache.set(cacheKey, Adapter);\n callback(null, Adapter);\n return;\n } catch {\n // Not installed - dynamically install then load\n installModule(packageName, nodeModulesPath, {}, (err: Error | null) => {\n if (err) {\n callback(err);\n return;\n }\n try {\n const mod = _require(packageName);\n const Adapter = exportName ? mod[exportName] : (mod.default ?? mod);\n adapterCache.set(cacheKey, Adapter);\n callback(null, Adapter);\n } catch (loadErr) {\n callback(loadErr as Error);\n }\n });\n }\n}\n\n/**\n * Clear the adapter cache (useful for testing)\n */\nexport function clearAdapterCache(): void {\n adapterCache.clear();\n}\n"],"names":["clearAdapterCache","loadAdapter","_require","require","Module","createRequire","_dirname","path","dirname","__dirname","url","fileURLToPath","nodeModulesPath","join","adapterCache","Map","packageName","exportName","callback","cacheKey","has","get","mod","Adapter","default","set","installModule","err","loadErr","clear"],"mappings":";;;;;;;;;;;QAyDgBA;eAAAA;;QAzChB;;CAEC,GACD;eAAwBC;;;iEAnBL;+DACF;8DACD;0EACU;;;;;;AAG1B,gDAAgD;AAChD,IAAMC,WAAW,OAAOC,YAAY,cAAcC,mBAAM,CAACC,aAAa,CAAC,uDAAmBF;AAE1F,8BAA8B;AAC9B,IAAMG,WAAWC,iBAAI,CAACC,OAAO,CAAC,OAAOC,cAAc,cAAcA,YAAYC,gBAAG,CAACC,aAAa,CAAC;AAC/F,IAAMC,kBAAkBL,iBAAI,CAACM,IAAI,CAACP,UAAU,MAAM,MAAM;AAExD,wBAAwB;AACxB,IAAMQ,eAAe,IAAIC;AAKV,SAASd,YAAYe,WAAmB,EAAEC,UAA8B,EAAEC,QAA6B;IACpH,IAAMC,WAAW,AAAC,GAAiBF,OAAfD,aAAY,KAA2B,OAAxBC,uBAAAA,wBAAAA,aAAc;IAEjD,qCAAqC;IACrC,IAAIH,aAAaM,GAAG,CAACD,WAAW;QAC9BD,SAAS,MAAMJ,aAAaO,GAAG,CAACF;QAChC;IACF;IAEA,kDAAkD;IAClD,IAAI;QACF,IAAMG,MAAMpB,SAASc;YAC2BM;QAAhD,IAAMC,UAAUN,aAAaK,GAAG,CAACL,WAAW,GAAIK,CAAAA,eAAAA,IAAIE,OAAO,cAAXF,0BAAAA,eAAeA;QAC/DR,aAAaW,GAAG,CAACN,UAAUI;QAC3BL,SAAS,MAAMK;QACf;IACF,EAAE,UAAM;QACN,gDAAgD;QAChDG,IAAAA,4BAAa,EAACV,aAAaJ,iBAAiB,CAAC,GAAG,SAACe;YAC/C,IAAIA,KAAK;gBACPT,SAASS;gBACT;YACF;YACA,IAAI;gBACF,IAAML,MAAMpB,SAASc;oBAC2BM;gBAAhD,IAAMC,UAAUN,aAAaK,GAAG,CAACL,WAAW,GAAIK,CAAAA,eAAAA,IAAIE,OAAO,cAAXF,0BAAAA,eAAeA;gBAC/DR,aAAaW,GAAG,CAACN,UAAUI;gBAC3BL,SAAS,MAAMK;YACjB,EAAE,OAAOK,SAAS;gBAChBV,SAASU;YACX;QACF;IACF;AACF;AAKO,SAAS5B;IACdc,aAAae,KAAK;AACpB"}
@@ -0,0 +1 @@
1
+ { "type": "commonjs" }
@@ -0,0 +1,13 @@
1
+ import type { AdapterConfig } from './types.js';
2
+ /**
3
+ * Register or override a protocol adapter
4
+ */
5
+ export declare function registerAdapter(protocol: string, config: AdapterConfig): void;
6
+ /**
7
+ * Get the current registry (read-only copy)
8
+ */
9
+ export declare function getRegistry(): Readonly<Record<string, AdapterConfig>>;
10
+ /**
11
+ * Get adapter config for a protocol
12
+ */
13
+ export declare function getAdapterConfig(protocol: string): AdapterConfig | undefined;
@@ -0,0 +1,13 @@
1
+ import type { AdapterConfig } from './types.js';
2
+ /**
3
+ * Register or override a protocol adapter
4
+ */
5
+ export declare function registerAdapter(protocol: string, config: AdapterConfig): void;
6
+ /**
7
+ * Get the current registry (read-only copy)
8
+ */
9
+ export declare function getRegistry(): Readonly<Record<string, AdapterConfig>>;
10
+ /**
11
+ * Get adapter config for a protocol
12
+ */
13
+ export declare function getAdapterConfig(protocol: string): AdapterConfig | undefined;
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get getAdapterConfig () {
13
+ return getAdapterConfig;
14
+ },
15
+ get getRegistry () {
16
+ return getRegistry;
17
+ },
18
+ get registerAdapter () {
19
+ return registerAdapter;
20
+ }
21
+ });
22
+ var _utilsts = require("./utils.js");
23
+ function _define_property(obj, key, value) {
24
+ if (key in obj) {
25
+ Object.defineProperty(obj, key, {
26
+ value: value,
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true
30
+ });
31
+ } else {
32
+ obj[key] = value;
33
+ }
34
+ return obj;
35
+ }
36
+ function _object_spread(target) {
37
+ for(var i = 1; i < arguments.length; i++){
38
+ var source = arguments[i] != null ? arguments[i] : {};
39
+ var ownKeys = Object.keys(source);
40
+ if (typeof Object.getOwnPropertySymbols === "function") {
41
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
42
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
43
+ }));
44
+ }
45
+ ownKeys.forEach(function(key) {
46
+ _define_property(target, key, source[key]);
47
+ });
48
+ }
49
+ return target;
50
+ }
51
+ /**
52
+ * Protocol registry mapping URI protocols to adapter configurations
53
+ */ var PROTOCOL_REGISTRY = {
54
+ // Official @keyv adapters
55
+ 'redis:': {
56
+ package: '@keyv/redis'
57
+ },
58
+ 'rediss:': {
59
+ package: '@keyv/redis'
60
+ },
61
+ 'postgresql:': {
62
+ package: '@keyv/postgres'
63
+ },
64
+ 'postgres:': {
65
+ package: '@keyv/postgres'
66
+ },
67
+ 'mysql:': {
68
+ package: '@keyv/mysql'
69
+ },
70
+ 'sqlite:': {
71
+ package: '@keyv/sqlite'
72
+ },
73
+ 'mongodb:': {
74
+ package: '@keyv/mongo'
75
+ },
76
+ 'mongodb+srv:': {
77
+ package: '@keyv/mongo'
78
+ },
79
+ 'memcache:': {
80
+ package: '@keyv/memcache'
81
+ },
82
+ 'etcd:': {
83
+ package: '@keyv/etcd'
84
+ },
85
+ // Third-party adapters
86
+ 'file:': {
87
+ package: 'keyv-file',
88
+ exportName: 'KeyvFile',
89
+ optionsMapper: function(url) {
90
+ return {
91
+ filename: (0, _utilsts.resolveFilePath)(url)
92
+ };
93
+ }
94
+ },
95
+ // Built-in (no package needed)
96
+ 'memory:': {
97
+ package: null
98
+ },
99
+ // Future/custom adapters
100
+ 'duckdb:': {
101
+ package: 'keyv-duckdb',
102
+ optionsMapper: function(url) {
103
+ return {
104
+ filename: (0, _utilsts.resolveFilePath)(url)
105
+ };
106
+ }
107
+ }
108
+ };
109
+ function registerAdapter(protocol, config) {
110
+ var normalizedProtocol = protocol.endsWith(':') ? protocol : "".concat(protocol, ":");
111
+ PROTOCOL_REGISTRY[normalizedProtocol] = config;
112
+ }
113
+ function getRegistry() {
114
+ return _object_spread({}, PROTOCOL_REGISTRY);
115
+ }
116
+ function getAdapterConfig(protocol) {
117
+ return PROTOCOL_REGISTRY[protocol];
118
+ }
119
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/keyv/keyv-registry/src/registry.ts"],"sourcesContent":["import type { AdapterConfig } from './types.ts';\nimport { resolveFilePath } from './utils.ts';\n\n/**\n * Protocol registry mapping URI protocols to adapter configurations\n */\nconst PROTOCOL_REGISTRY: Record<string, AdapterConfig> = {\n // Official @keyv adapters\n 'redis:': { package: '@keyv/redis' },\n 'rediss:': { package: '@keyv/redis' },\n 'postgresql:': { package: '@keyv/postgres' },\n 'postgres:': { package: '@keyv/postgres' },\n 'mysql:': { package: '@keyv/mysql' },\n 'sqlite:': { package: '@keyv/sqlite' },\n 'mongodb:': { package: '@keyv/mongo' },\n 'mongodb+srv:': { package: '@keyv/mongo' },\n 'memcache:': { package: '@keyv/memcache' },\n 'etcd:': { package: '@keyv/etcd' },\n\n // Third-party adapters\n 'file:': {\n package: 'keyv-file',\n exportName: 'KeyvFile',\n optionsMapper: (url: URL) => ({ filename: resolveFilePath(url) }),\n },\n\n // Built-in (no package needed)\n 'memory:': { package: null },\n\n // Future/custom adapters\n 'duckdb:': {\n package: 'keyv-duckdb',\n optionsMapper: (url: URL) => ({ filename: resolveFilePath(url) }),\n },\n};\n\n/**\n * Register or override a protocol adapter\n */\nexport function registerAdapter(protocol: string, config: AdapterConfig): void {\n const normalizedProtocol = protocol.endsWith(':') ? protocol : `${protocol}:`;\n PROTOCOL_REGISTRY[normalizedProtocol] = config;\n}\n\n/**\n * Get the current registry (read-only copy)\n */\nexport function getRegistry(): Readonly<Record<string, AdapterConfig>> {\n return { ...PROTOCOL_REGISTRY };\n}\n\n/**\n * Get adapter config for a protocol\n */\nexport function getAdapterConfig(protocol: string): AdapterConfig | undefined {\n return PROTOCOL_REGISTRY[protocol];\n}\n"],"names":["getAdapterConfig","getRegistry","registerAdapter","PROTOCOL_REGISTRY","package","exportName","optionsMapper","url","filename","resolveFilePath","protocol","config","normalizedProtocol","endsWith"],"mappings":";;;;;;;;;;;QAsDgBA;eAAAA;;QAPAC;eAAAA;;QARAC;eAAAA;;;uBAtCgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEhC;;CAEC,GACD,IAAMC,oBAAmD;IACvD,0BAA0B;IAC1B,UAAU;QAAEC,SAAS;IAAc;IACnC,WAAW;QAAEA,SAAS;IAAc;IACpC,eAAe;QAAEA,SAAS;IAAiB;IAC3C,aAAa;QAAEA,SAAS;IAAiB;IACzC,UAAU;QAAEA,SAAS;IAAc;IACnC,WAAW;QAAEA,SAAS;IAAe;IACrC,YAAY;QAAEA,SAAS;IAAc;IACrC,gBAAgB;QAAEA,SAAS;IAAc;IACzC,aAAa;QAAEA,SAAS;IAAiB;IACzC,SAAS;QAAEA,SAAS;IAAa;IAEjC,uBAAuB;IACvB,SAAS;QACPA,SAAS;QACTC,YAAY;QACZC,eAAe,SAACC;mBAAc;gBAAEC,UAAUC,IAAAA,wBAAe,EAACF;YAAK;;IACjE;IAEA,+BAA+B;IAC/B,WAAW;QAAEH,SAAS;IAAK;IAE3B,yBAAyB;IACzB,WAAW;QACTA,SAAS;QACTE,eAAe,SAACC;mBAAc;gBAAEC,UAAUC,IAAAA,wBAAe,EAACF;YAAK;;IACjE;AACF;AAKO,SAASL,gBAAgBQ,QAAgB,EAAEC,MAAqB;IACrE,IAAMC,qBAAqBF,SAASG,QAAQ,CAAC,OAAOH,WAAW,AAAC,GAAW,OAATA,UAAS;IAC3EP,iBAAiB,CAACS,mBAAmB,GAAGD;AAC1C;AAKO,SAASV;IACd,OAAO,mBAAKE;AACd;AAKO,SAASH,iBAAiBU,QAAgB;IAC/C,OAAOP,iBAAiB,CAACO,SAAS;AACpC"}