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.
- package/LICENSE +22 -0
- package/README.md +202 -0
- package/dist/cjs/index.d.cts +37 -0
- package/dist/cjs/index.d.ts +37 -0
- package/dist/cjs/index.js +82 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/loadAdapter.d.cts +9 -0
- package/dist/cjs/loadAdapter.d.ts +9 -0
- package/dist/cjs/loadAdapter.js +74 -0
- package/dist/cjs/loadAdapter.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/registry.d.cts +13 -0
- package/dist/cjs/registry.d.ts +13 -0
- package/dist/cjs/registry.js +119 -0
- package/dist/cjs/registry.js.map +1 -0
- package/dist/cjs/types.d.cts +33 -0
- package/dist/cjs/types.d.ts +33 -0
- package/dist/cjs/types.js +5 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.d.cts +8 -0
- package/dist/cjs/utils.d.ts +8 -0
- package/dist/cjs/utils.js +152 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/cjs/worker.d.cts +5 -0
- package/dist/cjs/worker.d.ts +5 -0
- package/dist/cjs/worker.js +138 -0
- package/dist/cjs/worker.js.map +1 -0
- package/dist/esm/index.d.ts +37 -0
- package/dist/esm/index.js +50 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/loadAdapter.d.ts +9 -0
- package/dist/esm/loadAdapter.js +52 -0
- package/dist/esm/loadAdapter.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/registry.d.ts +13 -0
- package/dist/esm/registry.js +73 -0
- package/dist/esm/registry.js.map +1 -0
- package/dist/esm/types.d.ts +33 -0
- package/dist/esm/types.js +3 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.d.ts +8 -0
- package/dist/esm/utils.js +33 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/worker.d.ts +5 -0
- package/dist/esm/worker.js +75 -0
- package/dist/esm/worker.js.map +1 -0
- 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"}
|