@yongdall/connection 0.5.0 → 0.5.2
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/index.d.mts +17 -11
- package/index.mjs +9 -9
- package/index.mjs.map +1 -1
- package/{main-C8igejll.mjs → main-B_-mso2s.mjs} +29 -28
- package/main-B_-mso2s.mjs.map +1 -0
- package/package.json +4 -4
- package/yongdall/enumeration.mjs +1 -1
- package/yongdall/providerDefine.mjs +8 -5
- package/yongdall/providerDefine.mjs.map +1 -1
- package/main-C8igejll.mjs.map +0 -1
package/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Connection, IConnection, MaybePromise } from "@yongdall/model";
|
|
2
2
|
import { Readable } from "node:stream";
|
|
3
3
|
import * as imodel0 from "imodel";
|
|
4
|
-
import {
|
|
4
|
+
import { Realm } from "@yongdall/types";
|
|
5
5
|
import "@yongdall/common";
|
|
6
6
|
|
|
7
7
|
//#region packages/connection/rdb.d.mts
|
|
@@ -16,15 +16,15 @@ declare function useDatabase(dbId?: string | null): imodel0.Connection<any>;
|
|
|
16
16
|
declare function transaction(...names: (string | null | (string | null)[])[]): (f: (this: T, ...p: P) => Promise<R>, ctx: ClassMethodDecoratorContext) => (this: T, ...p: P) => Promise<R>;
|
|
17
17
|
//#endregion
|
|
18
18
|
//#region packages/connection/mq.d.mts
|
|
19
|
-
/** @import {
|
|
19
|
+
/** @import { Realm } from '@yongdall/types' */
|
|
20
20
|
/**
|
|
21
21
|
*
|
|
22
22
|
* @param {string} channel
|
|
23
23
|
* @param {any} message
|
|
24
24
|
* @param {string} [service]
|
|
25
|
-
* @param {
|
|
25
|
+
* @param {Realm?} [realm]
|
|
26
26
|
*/
|
|
27
|
-
declare function publishMessage(channel: string, message: any, service?: string,
|
|
27
|
+
declare function publishMessage(channel: string, message: any, service?: string, realm?: Realm | null): Promise<void>;
|
|
28
28
|
/**
|
|
29
29
|
*
|
|
30
30
|
* @param {string} channel
|
|
@@ -34,15 +34,15 @@ declare function publishMessage(channel: string, message: any, service?: string,
|
|
|
34
34
|
declare function subscribeMessage(channel: string, listener: (val: any) => any, service?: string): () => void;
|
|
35
35
|
//#endregion
|
|
36
36
|
//#region packages/connection/tq.d.mts
|
|
37
|
-
/** @import {
|
|
37
|
+
/** @import { Realm } from '@yongdall/types' */
|
|
38
38
|
/**
|
|
39
39
|
*
|
|
40
40
|
* @param {string} queue
|
|
41
41
|
* @param {any} message
|
|
42
42
|
* @param {string} [service]
|
|
43
|
-
* @param {
|
|
43
|
+
* @param {Realm?} [realm]
|
|
44
44
|
*/
|
|
45
|
-
declare function publishTask(queue: string, message: any, service?: string,
|
|
45
|
+
declare function publishTask(queue: string, message: any, service?: string, realm?: Realm | null): Promise<void>;
|
|
46
46
|
/**
|
|
47
47
|
* @template T
|
|
48
48
|
* @param {string} queue
|
|
@@ -67,6 +67,7 @@ declare function useCache(dbId?: string | null): {
|
|
|
67
67
|
delExpirable(key: string, field: string): PromiseLike<void>;
|
|
68
68
|
memoize<T>(key: string, field: string, exec: () => PromiseLike<T> | T): PromiseLike<T>;
|
|
69
69
|
abort?(): void;
|
|
70
|
+
[Symbol.dispose](): void;
|
|
70
71
|
};
|
|
71
72
|
//#endregion
|
|
72
73
|
//#region packages/connection/main.d.mts
|
|
@@ -75,20 +76,20 @@ declare function useCache(dbId?: string | null): {
|
|
|
75
76
|
* @template {string} K
|
|
76
77
|
* @param {K} type
|
|
77
78
|
* @param {string} name
|
|
78
|
-
* @param {
|
|
79
|
+
* @param {Realm?} [realm]
|
|
79
80
|
* @param {boolean} [isAlias]
|
|
80
81
|
*/
|
|
81
|
-
declare function clear<K extends string>(type: K, name: string,
|
|
82
|
+
declare function clear<K extends string>(type: K, name: string, realm?: Realm | null, isAlias?: boolean): Promise<void>;
|
|
82
83
|
declare function stop(): Promise<void>;
|
|
83
84
|
/**
|
|
84
85
|
*
|
|
85
86
|
* @template {string} K
|
|
86
87
|
* @param {K} type
|
|
87
88
|
* @param {string} [dbId]
|
|
88
|
-
* @param {
|
|
89
|
+
* @param {Realm?} [realm]
|
|
89
90
|
* @returns {Connections[K]}
|
|
90
91
|
*/
|
|
91
|
-
declare function connect<K extends string>(type: K, dbId?: string,
|
|
92
|
+
declare function connect<K extends string>(type: K, dbId?: string, realm?: Realm | null): Connections[K];
|
|
92
93
|
/**
|
|
93
94
|
* @template {string & keyof ProvidersConverted} T
|
|
94
95
|
* @param {T} type
|
|
@@ -169,14 +170,17 @@ interface Connections {
|
|
|
169
170
|
publish(queue: string, data: any): Promise<void>;
|
|
170
171
|
get<T>(queue: string): Promise<T | void>;
|
|
171
172
|
abort?(): void;
|
|
173
|
+
[Symbol.dispose](): void;
|
|
172
174
|
};
|
|
173
175
|
mq: {
|
|
174
176
|
publish(channel: string, data: any): Promise<void>;
|
|
175
177
|
subscribe(channel: string, subscriber: (data: any) => void): () => void;
|
|
176
178
|
abort?(): void;
|
|
179
|
+
[Symbol.dispose](): void;
|
|
177
180
|
};
|
|
178
181
|
fs: FileStore & {
|
|
179
182
|
abort?(): void;
|
|
183
|
+
[Symbol.dispose](): void;
|
|
180
184
|
};
|
|
181
185
|
cache: {
|
|
182
186
|
set(key: string, field: string, value: any): PromiseLike<void>;
|
|
@@ -190,9 +194,11 @@ interface Connections {
|
|
|
190
194
|
delExpirable(key: string, field: string): PromiseLike<void>;
|
|
191
195
|
memoize<T>(key: string, field: string, exec: () => PromiseLike<T> | T): PromiseLike<T>;
|
|
192
196
|
abort?(): void;
|
|
197
|
+
[Symbol.dispose](): void;
|
|
193
198
|
};
|
|
194
199
|
[k: string]: {
|
|
195
200
|
abort?(): void;
|
|
201
|
+
[Symbol.dispose](): void;
|
|
196
202
|
};
|
|
197
203
|
}
|
|
198
204
|
type ProviderProfile = { [K in keyof Providers]: Record<string, Provider<Providers[K]>> };
|
package/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as useConnection, i as stop, n as connect, t as clear } from "./main-
|
|
1
|
+
import { a as useConnection, i as stop, n as connect, t as clear } from "./main-B_-mso2s.mjs";
|
|
2
2
|
|
|
3
3
|
//#region packages/connection/rdb.mjs
|
|
4
4
|
/**
|
|
@@ -37,16 +37,16 @@ function transaction(...names) {
|
|
|
37
37
|
|
|
38
38
|
//#endregion
|
|
39
39
|
//#region packages/connection/mq.mjs
|
|
40
|
-
/** @import {
|
|
40
|
+
/** @import { Realm } from '@yongdall/types' */
|
|
41
41
|
/**
|
|
42
42
|
*
|
|
43
43
|
* @param {string} channel
|
|
44
44
|
* @param {any} message
|
|
45
45
|
* @param {string} [service]
|
|
46
|
-
* @param {
|
|
46
|
+
* @param {Realm?} [realm]
|
|
47
47
|
*/
|
|
48
|
-
async function publishMessage(channel, message, service,
|
|
49
|
-
return connect("mq", service,
|
|
48
|
+
async function publishMessage(channel, message, service, realm) {
|
|
49
|
+
return connect("mq", service, realm).publish(channel, message);
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
*
|
|
@@ -60,16 +60,16 @@ function subscribeMessage(channel, listener, service) {
|
|
|
60
60
|
|
|
61
61
|
//#endregion
|
|
62
62
|
//#region packages/connection/tq.mjs
|
|
63
|
-
/** @import {
|
|
63
|
+
/** @import { Realm } from '@yongdall/types' */
|
|
64
64
|
/**
|
|
65
65
|
*
|
|
66
66
|
* @param {string} queue
|
|
67
67
|
* @param {any} message
|
|
68
68
|
* @param {string} [service]
|
|
69
|
-
* @param {
|
|
69
|
+
* @param {Realm?} [realm]
|
|
70
70
|
*/
|
|
71
|
-
async function publishTask(queue, message, service,
|
|
72
|
-
return connect("tq", service,
|
|
71
|
+
async function publishTask(queue, message, service, realm) {
|
|
72
|
+
return connect("tq", service, realm).publish(queue, message);
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
75
|
* @template T
|
package/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../packages/connection/rdb.mjs","../../packages/connection/mq.mjs","../../packages/connection/tq.mjs","../../packages/connection/cache.mjs"],"sourcesContent":["import { useConnection } from './main.mjs';\n\n\n\n/**\n * @param {string?} [dbId]\n */\nexport function useDatabase(dbId) {\n\treturn useConnection('rdb', dbId);\n}\n\n/**\n * \n * @param {...string | null | (string | null)[]} names \n */\nexport function transaction(...names) {\n\tconst allNames = new Set(names.flat().filter(v => v && typeof v === 'string' || v === null));\n\tif (!allNames.size) {\n\t\tallNames.add(null);\n\t}\n\t/**\n\t * @template {any[]} P\n\t * @template {any} R\n\t * @template {any} T\n\t * @param {(this:T, ...p: P) => Promise<R>} f\n\t * @param {ClassMethodDecoratorContext} ctx\n\t * @returns {(this:T, ...p: P) => Promise<R>}\n\t */\n\treturn function decorator(f, ctx) {\n\t\t// TODO: 修饰器\n\t\tif (typeof f !== 'function') {\n\t\t\tthrow new Error('事务修饰器只能加在方法上');\n\t\t}\n\t\tif (ctx.kind !== 'method') {\n\t\t\tthrow new Error('事务修饰器只能加在方法上');\n\t\t}\n\t\tlet fn = f;\n\t\tfor (const name of allNames) {\n\t\t\tfn = async function(...p) {\n\t\t\t\treturn useDatabase(name).transaction(signal => {\n\t\t\t\t\treturn f.apply(this, p);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn fn;\n\t}\n}\n","import { connect } from './main.mjs';\n/** @import {
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../packages/connection/rdb.mjs","../../packages/connection/mq.mjs","../../packages/connection/tq.mjs","../../packages/connection/cache.mjs"],"sourcesContent":["import { useConnection } from './main.mjs';\n\n\n\n/**\n * @param {string?} [dbId]\n */\nexport function useDatabase(dbId) {\n\treturn useConnection('rdb', dbId);\n}\n\n/**\n * \n * @param {...string | null | (string | null)[]} names \n */\nexport function transaction(...names) {\n\tconst allNames = new Set(names.flat().filter(v => v && typeof v === 'string' || v === null));\n\tif (!allNames.size) {\n\t\tallNames.add(null);\n\t}\n\t/**\n\t * @template {any[]} P\n\t * @template {any} R\n\t * @template {any} T\n\t * @param {(this:T, ...p: P) => Promise<R>} f\n\t * @param {ClassMethodDecoratorContext} ctx\n\t * @returns {(this:T, ...p: P) => Promise<R>}\n\t */\n\treturn function decorator(f, ctx) {\n\t\t// TODO: 修饰器\n\t\tif (typeof f !== 'function') {\n\t\t\tthrow new Error('事务修饰器只能加在方法上');\n\t\t}\n\t\tif (ctx.kind !== 'method') {\n\t\t\tthrow new Error('事务修饰器只能加在方法上');\n\t\t}\n\t\tlet fn = f;\n\t\tfor (const name of allNames) {\n\t\t\tfn = async function(...p) {\n\t\t\t\treturn useDatabase(name).transaction(signal => {\n\t\t\t\t\treturn f.apply(this, p);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn fn;\n\t}\n}\n","import { connect } from './main.mjs';\n/** @import { Realm } from '@yongdall/types' */\n\n/**\n * \n * @param {string} channel \n * @param {any} message \n * @param {string} [service] \n * @param {Realm?} [realm]\n */\nexport async function publishMessage(channel, message, service, realm) {\n\treturn connect('mq', service, realm).publish(channel, message);\n}\n\n\n\n/**\n * \n * @param {string} channel \n * @param {(val: any) => any} listener\n * @param {string} [service] \n */\nexport function subscribeMessage(channel, listener, service) {\n\treturn connect('mq', service).subscribe(channel, listener);\n}\n","import { connect } from './main.mjs';\n/** @import { Realm } from '@yongdall/types' */\n\n/**\n * \n * @param {string} queue \n * @param {any} message \n * @param {string} [service] \n * @param {Realm?} [realm]\n */\nexport async function publishTask(queue, message, service, realm) {\n\treturn connect('tq', service, realm).publish(queue, message);\n}\n\n/**\n * @template T\n * @param {string} queue \n * @param {string} [service] \n * @returns {Promise<T | void>}\n */\nexport function waitTask(queue, service) {\n\treturn connect('tq', service).get(queue);\n}\n","import { useConnection } from './main.mjs';\n\n\n\n/**\n * @param {string?} [dbId]\n */\nexport function useCache(dbId) {\n\treturn useConnection('cache', dbId);\n}\n"],"mappings":";;;;;;AAOA,SAAgB,YAAY,MAAM;AACjC,QAAO,cAAc,OAAO,KAAK;;;;;;AAOlC,SAAgB,YAAY,GAAG,OAAO;CACrC,MAAM,WAAW,IAAI,IAAI,MAAM,MAAM,CAAC,QAAO,MAAK,KAAK,OAAO,MAAM,YAAY,MAAM,KAAK,CAAC;AAC5F,KAAI,CAAC,SAAS,KACb,UAAS,IAAI,KAAK;;;;;;;;;AAUnB,QAAO,SAAS,UAAU,GAAG,KAAK;AAEjC,MAAI,OAAO,MAAM,WAChB,OAAM,IAAI,MAAM,eAAe;AAEhC,MAAI,IAAI,SAAS,SAChB,OAAM,IAAI,MAAM,eAAe;EAEhC,IAAI,KAAK;AACT,OAAK,MAAM,QAAQ,SAClB,MAAK,eAAe,GAAG,GAAG;AACzB,UAAO,YAAY,KAAK,CAAC,aAAY,WAAU;AAC9C,WAAO,EAAE,MAAM,MAAM,EAAE;KACtB;;AAGJ,SAAO;;;;;;;;;;;;;;AClCT,eAAsB,eAAe,SAAS,SAAS,SAAS,OAAO;AACtE,QAAO,QAAQ,MAAM,SAAS,MAAM,CAAC,QAAQ,SAAS,QAAQ;;;;;;;;AAW/D,SAAgB,iBAAiB,SAAS,UAAU,SAAS;AAC5D,QAAO,QAAQ,MAAM,QAAQ,CAAC,UAAU,SAAS,SAAS;;;;;;;;;;;;;ACb3D,eAAsB,YAAY,OAAO,SAAS,SAAS,OAAO;AACjE,QAAO,QAAQ,MAAM,SAAS,MAAM,CAAC,QAAQ,OAAO,QAAQ;;;;;;;;AAS7D,SAAgB,SAAS,OAAO,SAAS;AACxC,QAAO,QAAQ,MAAM,QAAQ,CAAC,IAAI,MAAM;;;;;;;;ACdzC,SAAgB,SAAS,MAAM;AAC9B,QAAO,cAAc,SAAS,KAAK"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LazyPromise } from "@yongdall/common";
|
|
2
2
|
import { addFinally, createStore, has } from "@yongdall/context";
|
|
3
|
-
import { getModel,
|
|
3
|
+
import { getModel, useRealm } from "@yongdall/core";
|
|
4
4
|
import { Query } from "@yongdall/model";
|
|
5
5
|
import { loadPluginProfiles } from "@yongdall/plugins";
|
|
6
6
|
|
|
@@ -29,14 +29,14 @@ let allConnections = Object.create(null);
|
|
|
29
29
|
* @template {string} K
|
|
30
30
|
* @param {K} type
|
|
31
31
|
* @param {string} name
|
|
32
|
-
* @param {
|
|
32
|
+
* @param {Realm?} [realm]
|
|
33
33
|
* @param {boolean} [isAlias]
|
|
34
34
|
*/
|
|
35
|
-
async function clear(type, name,
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
if (!
|
|
39
|
-
const connections =
|
|
35
|
+
async function clear(type, name, realm, isAlias) {
|
|
36
|
+
const realmId = (realm || await useRealm()).id;
|
|
37
|
+
const realmConnections = allConnections[realmId];
|
|
38
|
+
if (!realmConnections) return;
|
|
39
|
+
const connections = realmConnections[type];
|
|
40
40
|
if (!connections) return;
|
|
41
41
|
const db = connections[name];
|
|
42
42
|
delete connections[name];
|
|
@@ -46,19 +46,19 @@ async function clear(type, name, tenant, isAlias) {
|
|
|
46
46
|
async function stop() {
|
|
47
47
|
const oldConnections = allConnections;
|
|
48
48
|
allConnections = Object.create(null);
|
|
49
|
-
for (const
|
|
49
|
+
for (const realmConnections of Object.values(oldConnections)) for (const connections of Object.values(realmConnections)) for (const db of Object.values(connections)) (await db)?.abort?.();
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
52
|
*
|
|
53
53
|
* @template {string} T
|
|
54
54
|
* @param {T} type
|
|
55
55
|
* @param {string} name
|
|
56
|
-
* @param {
|
|
56
|
+
* @param {Realm} realm
|
|
57
57
|
* @returns {Promise<[uri: string, alias?: string]>}
|
|
58
58
|
*/
|
|
59
|
-
async function getUri(type, name,
|
|
59
|
+
async function getUri(type, name, realm) {
|
|
60
60
|
if (!name) {
|
|
61
|
-
const provider =
|
|
61
|
+
const provider = realm.providers[type];
|
|
62
62
|
return [typeof provider === "string" && provider || ""];
|
|
63
63
|
}
|
|
64
64
|
const model = await getModel("database");
|
|
@@ -67,7 +67,8 @@ async function getUri(type, name, tenant) {
|
|
|
67
67
|
sql = sql.select("uri");
|
|
68
68
|
const aliasField = model.fields.alias;
|
|
69
69
|
if (aliasField && aliasField.type === "string") sql = sql.select("alias");
|
|
70
|
-
|
|
70
|
+
using conn = connect("rdb", "", realm);
|
|
71
|
+
const a = await conn.first(sql);
|
|
71
72
|
if (!a) return [""];
|
|
72
73
|
const { uri, alias } = a;
|
|
73
74
|
return [uri || "", alias];
|
|
@@ -77,21 +78,21 @@ async function getUri(type, name, tenant) {
|
|
|
77
78
|
* @template {string & keyof Providers} K
|
|
78
79
|
* @param {K} type
|
|
79
80
|
* @param {string} [dbId]
|
|
80
|
-
* @param {
|
|
81
|
+
* @param {Realm?} [realm]
|
|
81
82
|
*/
|
|
82
|
-
async function findConnection(type, dbId,
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
let
|
|
86
|
-
if (!
|
|
87
|
-
|
|
88
|
-
allConnections[
|
|
83
|
+
async function findConnection(type, dbId, realm) {
|
|
84
|
+
const currentRealm = realm || await useRealm();
|
|
85
|
+
const realmId = currentRealm.id;
|
|
86
|
+
let realmConnections = allConnections[realmId];
|
|
87
|
+
if (!realmConnections) {
|
|
88
|
+
realmConnections = Object.create(null);
|
|
89
|
+
allConnections[realmId] = realmConnections;
|
|
89
90
|
}
|
|
90
91
|
/** @type {Record<string, Promise<ProvidersConverted[K]>>} */
|
|
91
|
-
let connections =
|
|
92
|
+
let connections = realmConnections[type];
|
|
92
93
|
if (!connections) {
|
|
93
94
|
connections = Object.create(null);
|
|
94
|
-
|
|
95
|
+
realmConnections[type] = connections;
|
|
95
96
|
}
|
|
96
97
|
const dbName = String(dbId || "");
|
|
97
98
|
const connection = connections[dbName];
|
|
@@ -119,11 +120,11 @@ async function findConnection(type, dbId, tenant) {
|
|
|
119
120
|
if (!conn) throw new Error();
|
|
120
121
|
return conn;
|
|
121
122
|
}
|
|
122
|
-
const conn = getUri(type, dbName,
|
|
123
|
+
const conn = getUri(type, dbName, currentRealm).then(([uri, alias]) => {
|
|
123
124
|
if (!alias) return build(uri);
|
|
124
125
|
const connection = connections[alias];
|
|
125
126
|
if (connection) return connection;
|
|
126
|
-
const conn = getUri(type, alias,
|
|
127
|
+
const conn = getUri(type, alias, currentRealm).then(([uri, alias]) => alias ? Promise.reject(/* @__PURE__ */ new Error()) : build(uri));
|
|
127
128
|
connections[alias] = conn;
|
|
128
129
|
return conn;
|
|
129
130
|
});
|
|
@@ -135,11 +136,11 @@ async function findConnection(type, dbId, tenant) {
|
|
|
135
136
|
* @template {string} K
|
|
136
137
|
* @param {K} type
|
|
137
138
|
* @param {string} [dbId]
|
|
138
|
-
* @param {
|
|
139
|
+
* @param {Realm?} [realm]
|
|
139
140
|
* @returns {Connections[K]}
|
|
140
141
|
*/
|
|
141
|
-
function connect(type, dbId,
|
|
142
|
-
const res = allDefines[type]?.connect?.(findConnection(type, dbId,
|
|
142
|
+
function connect(type, dbId, realm) {
|
|
143
|
+
const res = allDefines[type]?.connect?.(findConnection(type, dbId, realm));
|
|
143
144
|
if (!res) throw new Error();
|
|
144
145
|
return res;
|
|
145
146
|
}
|
|
@@ -174,4 +175,4 @@ function useConnection(type, dbId) {
|
|
|
174
175
|
|
|
175
176
|
//#endregion
|
|
176
177
|
export { useConnection as a, stop as i, connect as n, providerDefinePromise as r, clear as t };
|
|
177
|
-
//# sourceMappingURL=main-
|
|
178
|
+
//# sourceMappingURL=main-B_-mso2s.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-B_-mso2s.mjs","names":[],"sources":["../../packages/connection/main.mjs"],"sourcesContent":["import { LazyPromise } from '@yongdall/common';\nimport { addFinally, createStore, has } from '@yongdall/context';\nimport { getModel, useRealm } from '@yongdall/core';\nimport { Query } from '@yongdall/model';\nimport { loadPluginProfiles } from '@yongdall/plugins';\n/** @import { Realm } from '@yongdall/types' */\n\n/** @import {Connections, ProviderDefineProfile, ProviderProfile, Providers, ProvidersConverted} from './types.mjs' */\n\n\n\nconst providerPromise = LazyPromise.try(async function () {\n\t/** @type {[string, ProviderProfile[keyof ProviderProfile]][]} */\n\tconst profiles = await Array.fromAsync(loadPluginProfiles('provider', function *(/** @type {ProviderProfile}*/v) {\n\t\tyield* v ? Object.entries(v) : [];\n\t}));\n\t/** @type {ProviderProfile} */\n\tconst allProviders = Object.assign(Object.create(null), Object.fromEntries(\n\t\tObject.entries(Object.groupBy(profiles, v => v[0])).map(([t, v]) => [\n\t\t\tt, v ? Object.assign(Object.create(null), ...v.map(v => v[1])) : Object.create(null)\n\t\t]),\n\t));\n\treturn allProviders;\n});\n\nconst allProviders = await providerPromise;\n\n\n\nexport const providerDefinePromise = LazyPromise.try(async function () {\n\t/** @type {[string, ProviderDefineProfile[keyof ProviderDefineProfile]][]} */\n\t// @ts-ignore\n\tconst profiles = await Array.fromAsync(loadPluginProfiles('providerDefine', function *(/** @type {ProviderDefineProfile}*/v) {\n\t\tyield* v ? Object.entries(v) : [];\n\t}));\n\t/** @type {ProviderDefineProfile} */\n\tconst allDefines = Object.assign(Object.create(null), Object.fromEntries(profiles));\n\treturn allDefines;\n});\n\nconst allDefines = await providerDefinePromise\n\n\n/**\n * @type {Record<string, { [K in keyof ProvidersConverted]: Record<string, Promise<ProvidersConverted[K]>>}>}\n */\nlet allConnections = Object.create(null);\n/**\n * \n * @template {string} K\n * @param {K} type\n * @param {string} name \n * @param {Realm?} [realm] \n * @param {boolean} [isAlias] \n */\nexport async function clear(type, name, realm, isAlias) {\n\tconst realmId = (realm || await useRealm()).id;\n\tconst realmConnections = allConnections[realmId];\n\tif (!realmConnections) { return; }\n\tconst connections = realmConnections[type];\n\tif (!connections) { return; }\n\tconst db = connections[name];\n\tdelete connections[name];\n\tif (isAlias) { return; }\n\tconst k = await db;\n\treturn k?.abort?.();\n}\nexport async function stop() {\n\tconst oldConnections = allConnections;\n\tallConnections = Object.create(null);\n\tfor (const realmConnections of Object.values(oldConnections)) {\n\t\tfor (const connections of Object.values(realmConnections)) {\n\t\t\tfor (const db of Object.values(connections)) {\n\t\t\t\tconst k = await db;\n\t\t\t\tk?.abort?.();\n\t\t\t}\n\t\t}\n\t}\n\n}\n/**\n * \n * @template {string} T\n * @param {T} type\n * @param {string} name \n * @param {Realm} realm \n * @returns {Promise<[uri: string, alias?: string]>}\n */\nasync function getUri(type, name, realm) {\n\tif (!name) {\n\t\tconst provider = realm.providers[type];\n\t\treturn [typeof provider === 'string' && provider || ''];\n\t}\n\tconst model = await getModel('database');\n\tif (!model) { return ['']; }\n\tconst modelQuery = new Query(model, true);\n\tlet sql = modelQuery.where('type', type).where('name', name);\n\tsql = sql.select('uri');\n\tconst aliasField = model.fields.alias;\n\tif (aliasField && aliasField.type === 'string') { sql = sql.select('alias'); }\n\tusing conn = connect('rdb', '', realm);\n\tconst a = await conn.first(sql);\n\tif (!a) { return ['']; }\n\tconst { uri, alias } = a;\n\treturn [uri || '', alias];\n}\n\n\n/**\n * \n * @template {string & keyof Providers} K\n * @param {K} type\n * @param {string} [dbId] \n * @param {Realm?} [realm] \n */\nasync function findConnection(type, dbId, realm) {\n\tconst currentRealm = realm || await useRealm();\n\tconst realmId = currentRealm.id;\n\tlet realmConnections = allConnections[realmId];\n\tif (!realmConnections) {\n\t\trealmConnections = Object.create(null);\n\t\tallConnections[realmId] = realmConnections;\n\t}\n\t/** @type {Record<string, Promise<ProvidersConverted[K]>>} */\n\tlet connections = realmConnections[type];\n\tif (!connections) {\n\t\tconnections = Object.create(null);\n\t\trealmConnections[type] = connections;\n\t}\n\tconst dbName = String(dbId || '');\n\tconst connection = connections[dbName];\n\tif (connection) { return connection; }\n\tconst providers = allProviders[type];\n\tif (!providers) { throw new Error(`不支持 ${type} 类型`); }\n\t/**\n\t * \n\t * @param {string} uri \n\t * @returns \n\t */\n\tasync function build(uri) {\n\t\tif (!uri) {\n\t\t\t/** @type {ProvidersConverted[K] | Providers[K]} */\n\t\t\tconst conn = allDefines[type]?.default;\n\t\t\tif (conn) { return conn; }\n\t\t\tthrow new Error(`找不到 URI (${type}, ${dbName})`);\n\t\t}\n\t\tconst protocol = uri.split(':', 1)[0].split('+', 1)[0].toLowerCase();\n\t\tconst provider = providers[protocol];\n\t\tif (typeof provider !== 'function') {\n\t\t\tthrow new Error(`不支持 ${protocol} 协议`);\n\t\t}\n\t\tconst promise = await provider(uri);\n\t\t/** @type {ProvidersConverted[K] | Providers[K]} */\n\t\tconst conn = allDefines[type]?.convert?.(promise) || promise;\n\t\tif (!conn) { throw new Error(); }\n\t\treturn conn;\n\t}\n\tconst conn = getUri(type, dbName, currentRealm).then(([uri, alias]) => {\n\t\tif (!alias) { return build(uri); }\n\t\tconst connection = connections[alias];\n\t\tif (connection) { return connection; }\n\t\tconst conn = getUri(type, alias, currentRealm).then(([uri, alias]) => alias ? Promise.reject(new Error) : build(uri));\n\t\tconnections[alias] = conn;\n\t\treturn conn;\n\t});\n\tconnections[dbName] = conn;\n\treturn conn;\n}\n\n/**\n * \n * @template {string} K\n * @param {K} type\n * @param {string} [dbId] \n * @param {Realm?} [realm] \n * @returns {Connections[K]}\n */\nexport function connect(type, dbId, realm) {\n\tconst res = allDefines[type]?.connect?.(findConnection(type, dbId, realm));\n\tif (!res) {\n\t\tthrow new Error();\n\t}\n\treturn res;\n}\n\n\n\nconst [dbGetter, dbSetter] = createStore(/** @type {{ [K in keyof Connections]?: Record<String, Connections[K]>}?} */(null));\n\n/**\n * @template {string & keyof ProvidersConverted} T\n * @param {T} type\n * @param {string?} [dbId]\n * @returns {Connections[T]}\n */\nexport function useConnection(type, dbId) {\n\thas(true);\n\tlet dbs = dbGetter();\n\tif (!dbs) {\n\t\tdbs = {};\n\t\tdbSetter(dbs);\n\t}\n\tlet typed = dbs[type];\n\tif (!typed) {\n\t\ttyped = {};\n\t\tdbs[type] = typed;\n\t}\n\tconst dbName = String(dbId || '');\n\tif (Object.hasOwn(typed, dbName)) {\n\t\treturn typed[dbName];\n\t}\n\tconst db = connect(type, dbName);\n\ttyped[dbName] = db;\n\taddFinally(() => { db.abort?.(); });\n\treturn db;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yongdall/connection",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@yongdall/common": "^0.5.0",
|
|
15
15
|
"@yongdall/context": "^0.5.0",
|
|
16
|
-
"@yongdall/core": "^0.5.
|
|
17
|
-
"@yongdall/model": "^0.5.
|
|
16
|
+
"@yongdall/core": "^0.5.2",
|
|
17
|
+
"@yongdall/model": "^0.5.2",
|
|
18
18
|
"@yongdall/plugins": "^0.5.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@yongdall/types": "^0.5.
|
|
21
|
+
"@yongdall/types": "^0.5.2"
|
|
22
22
|
}
|
|
23
23
|
}
|
package/yongdall/enumeration.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Connection } from "@yongdall/model";
|
|
2
2
|
|
|
3
3
|
//#region packages/connection/yongdall/providerDefine.mjs
|
|
4
|
-
/** @import {ProviderDefineProfile, Providers, ProvidersConverted
|
|
4
|
+
/** @import { ProviderDefineProfile, Providers, ProvidersConverted } from '../types.mjs' */
|
|
5
5
|
/** @type {ProviderDefineProfile['fs']} */
|
|
6
6
|
const fs = {
|
|
7
7
|
label: "文件存储",
|
|
@@ -10,7 +10,8 @@ const fs = {
|
|
|
10
10
|
read: (path) => fs.then((s) => s.read(path)),
|
|
11
11
|
write: (path, data, size) => fs.then((s) => s.write(path, data, size)),
|
|
12
12
|
urlRead: (path, expires) => fs.then((s) => s.urlRead(path, expires)),
|
|
13
|
-
urlWrite: (path, expires) => fs.then((s) => s.urlWrite(path, expires))
|
|
13
|
+
urlWrite: (path, expires) => fs.then((s) => s.urlWrite(path, expires)),
|
|
14
|
+
[Symbol.dispose]() {}
|
|
14
15
|
})
|
|
15
16
|
};
|
|
16
17
|
/** @type {ProviderDefineProfile['mq']} */
|
|
@@ -64,7 +65,8 @@ const mq = {
|
|
|
64
65
|
async publish(channel, message) {
|
|
65
66
|
const { channels, service } = await param;
|
|
66
67
|
await service.publish(channel, message);
|
|
67
|
-
}
|
|
68
|
+
},
|
|
69
|
+
[Symbol.dispose]() {}
|
|
68
70
|
})
|
|
69
71
|
};
|
|
70
72
|
/** @type {ProviderDefineProfile['tq']} */
|
|
@@ -88,7 +90,7 @@ const tq = {
|
|
|
88
90
|
channels.set(queue, promise.catch(() => {}));
|
|
89
91
|
return promise;
|
|
90
92
|
},
|
|
91
|
-
|
|
93
|
+
[Symbol.dispose]() {}
|
|
92
94
|
})
|
|
93
95
|
};
|
|
94
96
|
/** @type {ProviderDefineProfile['rdb']} */
|
|
@@ -131,7 +133,8 @@ const cache = {
|
|
|
131
133
|
const val = await exec();
|
|
132
134
|
await c.set(key, field, val);
|
|
133
135
|
return val;
|
|
134
|
-
}))
|
|
136
|
+
})),
|
|
137
|
+
[Symbol.dispose]() {}
|
|
135
138
|
})
|
|
136
139
|
};
|
|
137
140
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providerDefine.mjs","names":[],"sources":["../../../packages/connection/yongdall/providerDefine.mjs"],"sourcesContent":["import { Connection } from '@yongdall/model';\n/** @import {ProviderDefineProfile, Providers, ProvidersConverted
|
|
1
|
+
{"version":3,"file":"providerDefine.mjs","names":[],"sources":["../../../packages/connection/yongdall/providerDefine.mjs"],"sourcesContent":["import { Connection } from '@yongdall/model';\n/** @import { ProviderDefineProfile, Providers, ProvidersConverted } from '../types.mjs' */\n\n\n/** @type {ProviderDefineProfile['fs']} */\nexport const fs = {\n\tlabel: '文件存储',\n\tconvert: (/** @type {Providers['fs']} */ fs) => fs,\n\tconnect: (/** @type {Promise<ProvidersConverted['fs']>} */ fs) => ({\n\t\tread: path => fs.then(s => s.read(path)),\n\t\twrite: (path, data, size) => fs.then(s => s.write(path, data, size)),\n\t\turlRead: (path, expires) => fs.then(s => s.urlRead(path, expires)),\n\t\turlWrite: (path, expires) => fs.then(s => s.urlWrite(path, expires)),\n\t\t[Symbol.dispose]() { },\n\t}),\n};\n/** @type {ProviderDefineProfile['mq']} */\nexport const mq = {\n\tlabel: '消息队列',\n\tconvert: (/** @type {Providers['mq']} */ service) => /** @type {ProvidersConverted['mq']} */({\n\t\tchannels: new Map(),\n\t\tservice,\n\t\tabort() {\n\t\t\t// TODO: \n\t\t},\n\t}),\n\tconnect: (/** @type {Promise<ProvidersConverted['mq']>} */param) => ({\n\t\t/**\n\t\t * \n\t\t * @param {string} channelName \n\t\t * @param {(val: any) => any} listener \n\t\t */\n\t\tsubscribe(channelName, listener) {\n\t\t\tlet cancelled = false;\n\t\t\tlet cancel = () => { cancelled = true; };\n\t\t\tparam.then(({ channels, service }) => {\n\t\t\t\tif (cancelled) { return; }\n\t\t\t\tlet channel = channels.get(channelName);\n\t\t\t\tif (!channel) {\n\t\t\t\t\t/** @type {Set<(val: any) => any>} */\n\t\t\t\t\tconst listeners = new Set();\n\t\t\t\t\tchannel = {\n\t\t\t\t\t\tlisteners, promise: Promise.resolve(null), run(value) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tfor (const f of [...listeners]) { f(value); }\n\t\t\t\t\t\t\t} catch {\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tchannels.set(channelName, channel);\n\t\t\t\t}\n\n\t\t\t\tconst listeners = channel.listeners;\n\n\t\t\t\tif (!listeners.size) {\n\t\t\t\t\tchannel.promise = channel.promise\n\t\t\t\t\t\t.then(v => v || service.subscribe(channelName, channel.run));\n\t\t\t\t}\n\t\t\t\tlisteners.add(listener);\n\t\t\t\tcancel = () => {\n\t\t\t\t\tif (cancelled) { return; }\n\t\t\t\t\tcancelled = true;\n\t\t\t\t\tlisteners.delete(listener);\n\t\t\t\t\tif (!listeners.size) {\n\t\t\t\t\t\tconst promise = channel.promise;\n\t\t\t\t\t\tchannel.promise = promise.then(v => v?.()).then(() => null);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t});\n\n\t\t\treturn () => { cancel(); };\n\t\t},\n\t\t/**\n\t\t * \n\t\t * @param {string} channel \n\t\t * @param {any} message \n\t\t */\n\t\tasync publish(channel, message) {\n\t\t\tconst { channels, service } = await param;\n\t\t\tawait service.publish(channel, message);\n\t\t},\n\t\t[Symbol.dispose]() { },\n\t}),\n};\n/** @type {ProviderDefineProfile['tq']} */\nexport const tq = {\n\tlabel: '任务队列',\n\tconvert: (/** @type {Providers['tq']} */ service) => /** @type {ProvidersConverted['tq']} */({\n\t\tchannels: new Map(),\n\t\tservice,\n\t\tabort() { service.disconnect(); },\n\t}),\n\tconnect: (/** @type {Promise<ProvidersConverted['tq']>} */param) => ({\n\t\t/**\n\t\t * \n\t\t * @param {string} queue \n\t\t * @param {any} message \n\t\t */\n\t\tasync publish(queue, message) {\n\t\t\tconst { channels, service } = await param;\n\t\t\tawait service.publish(queue, message);\n\t\t},\n\t\t/**\n\t\t * @template T\n\t\t * @param {string} queue \n\t\t * @returns {Promise<T | void>}\n\t\t */\n\t\tasync get(queue) {\n\t\t\tconst { channels, service } = await param;\n\t\t\tconst taskQueueChannel = channels.get(queue) || Promise.resolve();\n\n\t\t\tconst promise = taskQueueChannel\n\t\t\t\t.then(() => service)\n\t\t\t\t.then(v => v.get(queue));\n\n\t\t\tchannels.set(queue, promise.catch(() => { }));\n\t\t\treturn promise;\n\t\t},\n\t\t[Symbol.dispose]() { },\n\t}),\n};\n/** @type {ProviderDefineProfile['rdb']} */\nexport const rdb = {\n\tlabel: '关系型数据库',\n\tconvert: (/** @type {Providers['rdb']} */ conn) => conn,\n\tconnect: (/** @type {Promise<ProvidersConverted['rdb']>} */ conn) => new Connection(conn),\n};\n/** @type {ProviderDefineProfile['cache']} */\nexport const cache = {\n\tlabel: '缓存',\n\tdefault: /** @type {ProvidersConverted['cache']} */({\n\t\tset: async (key, field, value) => { },\n\t\tget: async (key, field) => { },\n\t\texists: async (key, field) => false,\n\t\tdel: async (key, field) => { },\n\t\tclear: async (key) => { },\n\t\tsetExpirable: async (key, field, value, ttl) => { },\n\t\tgetExpirable: async (key, field) => { },\n\t\texistsExpirable: async (key, field) => false,\n\t\tdelExpirable: async (key, field) => { },\n\t\tabort() { },\n\t}),\n\tconvert: (/** @type {Providers['cache']} */ { disconnect, ...cache }) => ({\n\t\t...cache,\n\t\tabort: disconnect,\n\t}),\n\tconnect: (/** @type {Promise<ProvidersConverted['cache']>} */ cache) => ({\n\t\tset: (key, field, value) => cache.then(c => c.set(key, field, value)),\n\t\tget: (key, field) => cache.then(c => c.get(key, field)),\n\t\texists: (key, field) => cache.then(c => c.exists(key, field)),\n\t\tdel: (key, field) => cache.then(c => c.del(key, field)),\n\t\tclear: (key) => cache.then(c => c.clear(key)),\n\t\tsetExpirable: (key, field, value, ttl) => cache.then(c => c.setExpirable(key, field, value, ttl)),\n\t\tgetExpirable: (key, field) => cache.then(c => c.getExpirable(key, field)),\n\t\texistsExpirable: (key, field) => cache.then(c => c.existsExpirable(key, field)),\n\t\tdelExpirable: (key, field) => cache.then(c => c.delExpirable(key, field)),\n\t\tmemoize: (key, field, exec) => cache.then(c => c.get(key, field).then(async (/** @type {*} */v) => {\n\t\t\tif (v !== undefined) { return v; }\n\t\t\tconst val = await exec();\n\t\t\tawait c.set(key, field, val);\n\t\t\treturn val;\n\t\t})),\n\t\t[Symbol.dispose]() { },\n\t}),\n};\n"],"mappings":"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"}
|
package/main-C8igejll.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"main-C8igejll.mjs","names":[],"sources":["../../packages/connection/main.mjs"],"sourcesContent":["import { LazyPromise } from '@yongdall/common';\nimport { addFinally, createStore, has } from '@yongdall/context';\nimport { getModel, useTenant, hooks } from '@yongdall/core';\nimport { Query } from '@yongdall/model';\nimport { loadPluginProfiles } from '@yongdall/plugins';\n/** @import { Tenant } from '@yongdall/types' */\n\n/** @import {Connections, ProviderDefineProfile, ProviderProfile, Providers, ProvidersConverted} from './types.mjs' */\n\n\n\nconst providerPromise = LazyPromise.try(async function () {\n\t/** @type {[string, ProviderProfile[keyof ProviderProfile]][]} */\n\tconst profiles = await Array.fromAsync(loadPluginProfiles('provider', function *(/** @type {ProviderProfile}*/v) {\n\t\tyield* v ? Object.entries(v) : [];\n\t}));\n\t/** @type {ProviderProfile} */\n\tconst allProviders = Object.assign(Object.create(null), Object.fromEntries(\n\t\tObject.entries(Object.groupBy(profiles, v => v[0])).map(([t, v]) => [\n\t\t\tt, v ? Object.assign(Object.create(null), ...v.map(v => v[1])) : Object.create(null)\n\t\t]),\n\t));\n\treturn allProviders;\n});\n\nconst allProviders = await providerPromise;\n\n\n\nexport const providerDefinePromise = LazyPromise.try(async function () {\n\t/** @type {[string, ProviderDefineProfile[keyof ProviderDefineProfile]][]} */\n\t// @ts-ignore\n\tconst profiles = await Array.fromAsync(loadPluginProfiles('providerDefine', function *(/** @type {ProviderDefineProfile}*/v) {\n\t\tyield* v ? Object.entries(v) : [];\n\t}));\n\t/** @type {ProviderDefineProfile} */\n\tconst allDefines = Object.assign(Object.create(null), Object.fromEntries(profiles));\n\treturn allDefines;\n});\n\nconst allDefines = await providerDefinePromise\n\n\n/**\n * @type {Record<string, { [K in keyof ProvidersConverted]: Record<string, Promise<ProvidersConverted[K]>>}>}\n */\nlet allConnections = Object.create(null);\n/**\n * \n * @template {string} K\n * @param {K} type\n * @param {string} name \n * @param {Tenant?} [tenant] \n * @param {boolean} [isAlias] \n */\nexport async function clear(type, name, tenant, isAlias) {\n\tconst tenantId = (tenant || await useTenant()).id;\n\tconst tenantConnections = allConnections[tenantId];\n\tif (!tenantConnections) { return; }\n\tconst connections = tenantConnections[type];\n\tif (!connections) { return; }\n\tconst db = connections[name];\n\tdelete connections[name];\n\tif (isAlias) { return; }\n\tconst k = await db;\n\treturn k?.abort?.();\n}\nexport async function stop() {\n\tconst oldConnections = allConnections;\n\tallConnections = Object.create(null);\n\tfor (const tenantConnections of Object.values(oldConnections)) {\n\t\tfor (const connections of Object.values(tenantConnections)) {\n\t\t\tfor (const db of Object.values(connections)) {\n\t\t\t\tconst k = await db;\n\t\t\t\tk?.abort?.();\n\t\t\t}\n\t\t}\n\t}\n\n}\n/**\n * \n * @template {string} T\n * @param {T} type\n * @param {string} name \n * @param {Tenant} tenant \n * @returns {Promise<[uri: string, alias?: string]>}\n */\nasync function getUri(type, name, tenant) {\n\tif (!name) {\n\t\tconst provider = tenant.providers[type];\n\t\treturn [typeof provider === 'string' && provider || ''];\n\t}\n\tconst model = await getModel('database');\n\tif (!model) { return ['']; }\n\tconst modelQuery = new Query(model, true);\n\tlet sql = modelQuery.where('type', type).where('name', name);\n\tsql = sql.select('uri');\n\tconst aliasField = model.fields.alias;\n\tif (aliasField && aliasField.type === 'string') { sql = sql.select('alias'); }\n\tconst a = await connect('rdb', '', tenant).first(sql);\n\tif (!a) { return ['']; }\n\tconst { uri, alias } = a;\n\treturn [uri || '', alias];\n}\n\n\n/**\n * \n * @template {string & keyof Providers} K\n * @param {K} type\n * @param {string} [dbId] \n * @param {Tenant?} [tenant] \n */\nasync function findConnection(type, dbId, tenant) {\n\tconst currentTenant = tenant || await useTenant();\n\tconst tenantId = currentTenant.id;\n\tlet tenantConnections = allConnections[tenantId];\n\tif (!tenantConnections) {\n\t\ttenantConnections = Object.create(null);\n\t\tallConnections[tenantId] = tenantConnections;\n\t}\n\t/** @type {Record<string, Promise<ProvidersConverted[K]>>} */\n\tlet connections = tenantConnections[type];\n\tif (!connections) {\n\t\tconnections = Object.create(null);\n\t\ttenantConnections[type] = connections;\n\t}\n\tconst dbName = String(dbId || '');\n\tconst connection = connections[dbName];\n\tif (connection) { return connection; }\n\tconst providers = allProviders[type];\n\tif (!providers) { throw new Error(`不支持 ${type} 类型`); }\n\t/**\n\t * \n\t * @param {string} uri \n\t * @returns \n\t */\n\tasync function build(uri) {\n\t\tif (!uri) {\n\t\t\t/** @type {ProvidersConverted[K] | Providers[K]} */\n\t\t\tconst conn = allDefines[type]?.default;\n\t\t\tif (conn) { return conn; }\n\t\t\tthrow new Error(`找不到 URI (${type}, ${dbName})`);\n\t\t}\n\t\tconst protocol = uri.split(':', 1)[0].split('+', 1)[0].toLowerCase();\n\t\tconst provider = providers[protocol];\n\t\tif (typeof provider !== 'function') {\n\t\t\tthrow new Error(`不支持 ${protocol} 协议`);\n\t\t}\n\t\tconst promise = await provider(uri);\n\t\t/** @type {ProvidersConverted[K] | Providers[K]} */\n\t\tconst conn = allDefines[type]?.convert?.(promise) || promise;\n\t\tif (!conn) { throw new Error(); }\n\t\treturn conn;\n\t}\n\tconst conn = getUri(type, dbName, currentTenant).then(([uri, alias]) => {\n\t\tif (!alias) { return build(uri); }\n\t\tconst connection = connections[alias];\n\t\tif (connection) { return connection; }\n\t\tconst conn = getUri(type, alias, currentTenant).then(([uri, alias]) => alias ? Promise.reject(new Error) : build(uri));\n\t\tconnections[alias] = conn;\n\t\treturn conn;\n\t});\n\tconnections[dbName] = conn;\n\treturn conn;\n}\n\n/**\n * \n * @template {string} K\n * @param {K} type\n * @param {string} [dbId] \n * @param {Tenant?} [tenant] \n * @returns {Connections[K]}\n */\nexport function connect(type, dbId, tenant) {\n\tconst res = allDefines[type]?.connect?.(findConnection(type, dbId, tenant));\n\tif (!res) {\n\t\tthrow new Error();\n\t}\n\treturn res;\n}\n\n\n\nconst [dbGetter, dbSetter] = createStore(/** @type {{ [K in keyof Connections]?: Record<String, Connections[K]>}?} */(null));\n\n/**\n * @template {string & keyof ProvidersConverted} T\n * @param {T} type\n * @param {string?} [dbId]\n * @returns {Connections[T]}\n */\nexport function useConnection(type, dbId) {\n\thas(true);\n\tlet dbs = dbGetter();\n\tif (!dbs) {\n\t\tdbs = {};\n\t\tdbSetter(dbs);\n\t}\n\tlet typed = dbs[type];\n\tif (!typed) {\n\t\ttyped = {};\n\t\tdbs[type] = typed;\n\t}\n\tconst dbName = String(dbId || '');\n\tif (Object.hasOwn(typed, dbName)) {\n\t\treturn typed[dbName];\n\t}\n\tconst db = connect(type, dbName);\n\ttyped[dbName] = db;\n\taddFinally(() => { db.abort?.(); });\n\treturn db;\n}\n"],"mappings":"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"}
|