@yongdall/connection 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/hooks.yongdall.mjs +117 -0
- package/hooks.yongdall.mjs.map +1 -0
- package/index.mjs +249 -0
- package/index.mjs.map +1 -0
- package/package.json +22 -0
- package/types.d.mts +186 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Connection } from "@yongdall/model";
|
|
2
|
+
|
|
3
|
+
//#region packages/connection/hooks.yongdall.mjs
|
|
4
|
+
/** @import {Hooks, Providers, ProvidersConverted, Connections} from './types.mjs' */
|
|
5
|
+
/** @type {Hooks.providerDefines} */
|
|
6
|
+
const providerDefines = {
|
|
7
|
+
fs: {
|
|
8
|
+
convert: (fs) => fs,
|
|
9
|
+
connect: (fs) => ({
|
|
10
|
+
read: (path) => fs.then((s) => s.read(path)),
|
|
11
|
+
write: (path, data, size) => fs.then((s) => s.write(path, data, size)),
|
|
12
|
+
urlRead: (path, expires) => fs.then((s) => s.urlRead(path, expires)),
|
|
13
|
+
urlWrite: (path, expires) => fs.then((s) => s.urlWrite(path, expires))
|
|
14
|
+
})
|
|
15
|
+
},
|
|
16
|
+
mq: {
|
|
17
|
+
convert: (service) => ({
|
|
18
|
+
channels: /* @__PURE__ */ new Map(),
|
|
19
|
+
service,
|
|
20
|
+
abort() {}
|
|
21
|
+
}),
|
|
22
|
+
connect: (param) => ({
|
|
23
|
+
async subscribe(channelName, listener) {
|
|
24
|
+
const { channels, service } = await param;
|
|
25
|
+
let channel = channels.get(channelName);
|
|
26
|
+
if (!channel) {
|
|
27
|
+
/** @type {Set<(val: any) => any>} */
|
|
28
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
29
|
+
channel = {
|
|
30
|
+
listeners,
|
|
31
|
+
promise: Promise.resolve(null),
|
|
32
|
+
run(value) {
|
|
33
|
+
try {
|
|
34
|
+
for (const f of [...listeners]) f(value);
|
|
35
|
+
} catch {}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
channels.set(channelName, channel);
|
|
39
|
+
}
|
|
40
|
+
const listeners = channel.listeners;
|
|
41
|
+
if (!listeners.size) channel.promise = channel.promise.then((v) => v || service.subscribe(channelName, channel.run));
|
|
42
|
+
listeners.add(listener);
|
|
43
|
+
let done = false;
|
|
44
|
+
return () => {
|
|
45
|
+
if (done) return;
|
|
46
|
+
done = true;
|
|
47
|
+
listeners.delete(listener);
|
|
48
|
+
if (!listeners.size) {
|
|
49
|
+
const promise = channel.promise;
|
|
50
|
+
channel.promise = promise.then((v) => v?.()).then(() => null);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
async publish(channel, message) {
|
|
55
|
+
const { channels, service } = await param;
|
|
56
|
+
await service.publish(channel, message);
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
},
|
|
60
|
+
tq: {
|
|
61
|
+
convert: (service) => ({
|
|
62
|
+
channels: /* @__PURE__ */ new Map(),
|
|
63
|
+
service,
|
|
64
|
+
abort() {
|
|
65
|
+
service.disconnect();
|
|
66
|
+
}
|
|
67
|
+
}),
|
|
68
|
+
connect: (param) => ({
|
|
69
|
+
async publish(queue, message) {
|
|
70
|
+
const { channels, service } = await param;
|
|
71
|
+
await service.publish(queue, message);
|
|
72
|
+
},
|
|
73
|
+
async get(queue) {
|
|
74
|
+
const { channels, service } = await param;
|
|
75
|
+
const promise = (channels.get(queue) || Promise.resolve()).then(() => service).then((v) => v.get(queue));
|
|
76
|
+
channels.set(queue, promise.catch(() => {}));
|
|
77
|
+
return promise;
|
|
78
|
+
},
|
|
79
|
+
abort() {}
|
|
80
|
+
})
|
|
81
|
+
},
|
|
82
|
+
rdb: {
|
|
83
|
+
convert: (conn) => conn,
|
|
84
|
+
connect: (conn) => new Connection(conn)
|
|
85
|
+
},
|
|
86
|
+
cache: {
|
|
87
|
+
default: {
|
|
88
|
+
set: async (key, field, value) => {},
|
|
89
|
+
get: async (key, field) => {},
|
|
90
|
+
exists: async (key, field) => false,
|
|
91
|
+
del: async (key, field) => {},
|
|
92
|
+
clear: async (key) => {},
|
|
93
|
+
abort() {}
|
|
94
|
+
},
|
|
95
|
+
convert: ({ disconnect, ...cache }) => ({
|
|
96
|
+
...cache,
|
|
97
|
+
abort: disconnect
|
|
98
|
+
}),
|
|
99
|
+
connect: (cache) => ({
|
|
100
|
+
set: (key, field, value) => cache.then((c) => c.set(key, field, value)),
|
|
101
|
+
get: (key, field) => cache.then((c) => c.get(key, field)),
|
|
102
|
+
exists: (key, field) => cache.then((c) => c.exists(key, field)),
|
|
103
|
+
del: (key, field) => cache.then((c) => c.del(key, field)),
|
|
104
|
+
clear: (key) => cache.then((c) => c.clear(key)),
|
|
105
|
+
memoize: (key, field, exec) => cache.then((c) => c.get(key, field).then(async (v) => {
|
|
106
|
+
if (v !== void 0) return v;
|
|
107
|
+
const val = await exec();
|
|
108
|
+
await c.set(key, field, val);
|
|
109
|
+
return val;
|
|
110
|
+
}))
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
export { providerDefines };
|
|
117
|
+
//# sourceMappingURL=hooks.yongdall.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.yongdall.mjs","names":[],"sources":["../../packages/connection/hooks.yongdall.mjs"],"sourcesContent":["import { Connection } from '@yongdall/model';\n/** @import {Hooks, Providers, ProvidersConverted, Connections} from './types.mjs' */\n\n\n/** @type {Hooks.providerDefines} */\nexport const providerDefines = {\n\tfs: {\n\t\tconvert: (/** @type {Providers['fs']} */ fs) => fs,\n\t\tconnect: (/** @type {Promise<ProvidersConverted['fs']>} */ fs) => /** @type {Connections['fs']} */({\n\t\t\tread: path => fs.then(s => s.read(path)),\n\t\t\twrite: (path, data, size) => fs.then(s => s.write(path, data, size)),\n\t\t\turlRead: (path, expires) => fs.then(s => s.urlRead(path, expires)),\n\t\t\turlWrite: (path, expires) => fs.then(s => s.urlWrite(path, expires)),\n\t\t}),\n\t},\n\tmq: {\n\t\tconvert: (/** @type {Providers['mq']} */ service) => /** @type {ProvidersConverted['mq']} */({\n\t\t\tchannels: new Map(),\n\t\t\tservice,\n\t\t\tabort() {\n\t\t\t\t// TODO: \n\t\t\t},\n\t\t}),\n\t\tconnect: (/** @type {Promise<ProvidersConverted['mq']>} */param) => ({\n\t\t\t/**\n\t\t\t * \n\t\t\t * @param {string} channelName \n\t\t\t * @param {(val: any) => any} listener \n\t\t\t */\n\t\t\tasync subscribe(channelName, listener) {\n\t\t\t\tconst { channels, service } = await param;\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\n\t\t\t\tlet done = false;\n\t\t\t\treturn () => {\n\t\t\t\t\tif (done) { return; }\n\t\t\t\t\tdone = true;\n\t\t\t\t\tlisteners.delete(listener);\n\t\t\t\t\tif (!listeners.size) {\n\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\t\t\t},\n\t\t\t/**\n\t\t\t * \n\t\t\t * @param {string} channel \n\t\t\t * @param {any} message \n\t\t\t */\n\t\t\tasync publish(channel, message) {\n\t\t\t\tconst { channels, service } = await param;\n\t\t\t\tawait service.publish(channel, message);\n\t\t\t},\n\t\t}),\n\t},\n\ttq: {\n\t\tconvert: (/** @type {Providers['tq']} */ service) => /** @type {ProvidersConverted['tq']} */({\n\t\t\tchannels: new Map(),\n\t\t\tservice,\n\t\t\tabort() { service.disconnect(); },\n\t\t}),\n\t\tconnect: (/** @type {Promise<ProvidersConverted['tq']>} */param) => ({\n\t\t\t/**\n\t\t\t * \n\t\t\t * @param {string} queue \n\t\t\t * @param {any} message \n\t\t\t */\n\t\t\tasync publish(queue, message) {\n\t\t\t\tconst { channels, service } = await param;\n\t\t\t\tawait service.publish(queue, message);\n\t\t\t},\n\t\t\t/**\n\t\t\t * @template T\n\t\t\t * @param {string} queue \n\t\t\t * @returns {Promise<T | void>}\n\t\t\t */\n\t\t\tasync get(queue) {\n\t\t\t\tconst { channels, service } = await param;\n\t\t\t\tconst taskQueueChannel = channels.get(queue) || Promise.resolve();\n\n\t\t\t\tconst promise = taskQueueChannel\n\t\t\t\t\t.then(() => service)\n\t\t\t\t\t.then(v => v.get(queue));\n\n\t\t\t\tchannels.set(queue, promise.catch(() => { }));\n\t\t\t\treturn promise;\n\t\t\t},\n\t\t\tabort() { },\n\t\t}),\n\t},\n\trdb: {\n\t\tconvert: (/** @type {Providers['rdb']} */ conn) => conn,\n\t\tconnect: (/** @type {Promise<ProvidersConverted['rdb']>} */ conn) => new Connection(conn),\n\t},\n\tcache: {\n\t\tdefault: /** @type {ProvidersConverted['cache']} */({\n\t\t\tset: async (key, field, value) => { },\n\t\t\tget: async (key, field) => { },\n\t\t\texists: async (key, field) => false,\n\t\t\tdel: async (key, field) => { },\n\t\t\tclear: async (key) => { },\n\t\t\tabort() { },\n\t\t}),\n\t\tconvert: (/** @type {Providers['cache']} */ { disconnect, ...cache }) => ({\n\t\t\t...cache,\n\t\t\tabort: disconnect,\n\t\t}),\n\t\tconnect: (/** @type {Promise<ProvidersConverted['cache']>} */ cache) => /** @type {Connections['cache']} */({\n\t\t\tset: (key, field, value) => cache.then(c => c.set(key, field, value)),\n\t\t\tget: (key, field) => cache.then(c => c.get(key, field)),\n\t\t\texists: (key, field) => cache.then(c => c.exists(key, field)),\n\t\t\tdel: (key, field) => cache.then(c => c.del(key, field)),\n\t\t\tclear: (key) => cache.then(c => c.clear(key)),\n\t\t\tmemoize: (key, field, exec) => cache.then(c => c.get(key, field).then(async v => {\n\t\t\t\tif (v !== undefined) { return v; }\n\t\t\t\tconst val = await exec();\n\t\t\t\tawait c.set(key, field, val);\n\t\t\t\treturn val;\n\t\t\t}))\n\t\t}),\n\t},\n};\n"],"mappings":"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"}
|
package/index.mjs
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { Query } from "@yongdall/model";
|
|
2
|
+
import { addFinally, createStore, has } from "@yongdall/context";
|
|
3
|
+
import { getModel, hooks, useTenant } from "@yongdall/core";
|
|
4
|
+
|
|
5
|
+
//#region packages/connection/main.mjs
|
|
6
|
+
/** @import { Tenant } from '@yongdall/types' */
|
|
7
|
+
/** @import {Connections, Hooks, Providers, ProvidersConverted} from './types.mjs' */
|
|
8
|
+
/**
|
|
9
|
+
* @returns {[
|
|
10
|
+
* Hooks['providers'],
|
|
11
|
+
* Hooks['providerDefines'],
|
|
12
|
+
* ]}
|
|
13
|
+
*/
|
|
14
|
+
function getProviders() {
|
|
15
|
+
/** @type {[string, Hooks['providers'][keyof Hooks['providers']]][]} */
|
|
16
|
+
const list = [...hooks.get("providers").values()].flatMap((v) => v ? Object.entries(v) : []);
|
|
17
|
+
const allProviders = Object.assign(Object.create(null), Object.fromEntries(Object.entries(Object.groupBy(list, (v) => v[0])).map(([t, v]) => [t, v ? Object.assign(Object.create(null), ...v.map((v) => v[1])) : Object.create(null)])));
|
|
18
|
+
/** @type {[string, Hooks['providerDefines'][keyof Hooks['providerDefines']]][]} */
|
|
19
|
+
const list0 = [...hooks.get("providerDefines").values()].flatMap((v) => v ? Object.entries(v) : []);
|
|
20
|
+
return [allProviders, Object.assign(Object.create(null), Object.fromEntries(list0))];
|
|
21
|
+
}
|
|
22
|
+
let [allProviders, allDefines] = getProviders();
|
|
23
|
+
hooks.listen(() => {
|
|
24
|
+
[allProviders, allDefines] = getProviders();
|
|
25
|
+
}, -1e6);
|
|
26
|
+
/**
|
|
27
|
+
* @type {Record<string, { [K in keyof ProvidersConverted]: Record<string, Promise<ProvidersConverted[K]>>}>}
|
|
28
|
+
*/
|
|
29
|
+
let allConnections = Object.create(null);
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @template {string} K
|
|
33
|
+
* @param {K} type
|
|
34
|
+
* @param {string} name
|
|
35
|
+
* @param {Tenant?} [tenant]
|
|
36
|
+
*/
|
|
37
|
+
async function clear(type, name, tenant) {
|
|
38
|
+
const tenantId = (tenant || await useTenant()).id;
|
|
39
|
+
const tenantConnections = allConnections[tenantId];
|
|
40
|
+
if (!tenantConnections) return;
|
|
41
|
+
const connections = tenantConnections[type];
|
|
42
|
+
if (!connections) return;
|
|
43
|
+
const db = connections[name];
|
|
44
|
+
delete connections[name];
|
|
45
|
+
return (await db)?.abort?.();
|
|
46
|
+
}
|
|
47
|
+
async function stop() {
|
|
48
|
+
const oldConnections = allConnections;
|
|
49
|
+
allConnections = Object.create(null);
|
|
50
|
+
for (const tenantConnections of Object.values(oldConnections)) for (const connections of Object.values(tenantConnections)) for (const db of Object.values(connections)) (await db)?.abort?.();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @template {string} T
|
|
55
|
+
* @param {T} type
|
|
56
|
+
* @param {string} name
|
|
57
|
+
* @param {Tenant} tenant
|
|
58
|
+
* @returns {Promise<string | null | void>}
|
|
59
|
+
*/
|
|
60
|
+
async function getUri(type, name, tenant) {
|
|
61
|
+
if (!name) {
|
|
62
|
+
const provider = tenant.providers[type];
|
|
63
|
+
return typeof provider === "string" && provider || null;
|
|
64
|
+
}
|
|
65
|
+
const model = await getModel("database");
|
|
66
|
+
if (!model) return;
|
|
67
|
+
let sql = new Query(model, true).where("type", type).where("name", name);
|
|
68
|
+
return (await connect("rdb", "", tenant).first(sql.select("uri")))?.uri;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* @template {string & keyof Providers} K
|
|
72
|
+
* @param {K} type
|
|
73
|
+
* @param {string} name
|
|
74
|
+
* @param {Tenant} tenant
|
|
75
|
+
*/
|
|
76
|
+
async function link(type, name, tenant) {
|
|
77
|
+
const providers = allProviders[type];
|
|
78
|
+
if (!providers) throw new Error(`不支持 ${type} 类型`);
|
|
79
|
+
const uri = await getUri(type, name, tenant);
|
|
80
|
+
if (!uri || typeof uri !== "string") {
|
|
81
|
+
/** @type {ProvidersConverted[K] | Providers[K]} */
|
|
82
|
+
const conn = allDefines[type]?.default;
|
|
83
|
+
if (!conn) throw new Error(`找不到 URI (${type}, ${name})`);
|
|
84
|
+
return conn;
|
|
85
|
+
}
|
|
86
|
+
const protocol = uri.split(":", 1)[0].split("+", 1)[0].toLowerCase();
|
|
87
|
+
const provider = providers[protocol];
|
|
88
|
+
if (typeof provider !== "function") throw new Error(`不支持 ${protocol} 协议`);
|
|
89
|
+
const promise = await provider(uri);
|
|
90
|
+
/** @type {ProvidersConverted[K] | Providers[K]} */
|
|
91
|
+
const conn = allDefines[type]?.convert?.(promise) || promise;
|
|
92
|
+
if (!conn) throw new Error();
|
|
93
|
+
return conn;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @template {string & keyof Providers} K
|
|
98
|
+
* @param {K} type
|
|
99
|
+
* @param {string} [dbId]
|
|
100
|
+
* @param {Tenant?} [tenant]
|
|
101
|
+
*/
|
|
102
|
+
async function findConnection(type, dbId, tenant) {
|
|
103
|
+
const currentTenant = tenant || await useTenant();
|
|
104
|
+
const tenantId = currentTenant.id;
|
|
105
|
+
let tenantConnections = allConnections[tenantId];
|
|
106
|
+
if (!tenantConnections) {
|
|
107
|
+
tenantConnections = Object.create(null);
|
|
108
|
+
allConnections[type] = tenantConnections;
|
|
109
|
+
}
|
|
110
|
+
/** @type {Record<string, Promise<ProvidersConverted[K]>>} */
|
|
111
|
+
let connections = tenantConnections[type];
|
|
112
|
+
if (!connections) {
|
|
113
|
+
connections = Object.create(null);
|
|
114
|
+
tenantConnections[type] = connections;
|
|
115
|
+
}
|
|
116
|
+
const dbName = String(dbId || "");
|
|
117
|
+
const connection = connections[dbName];
|
|
118
|
+
if (connection) return connection;
|
|
119
|
+
const conn = link(type, dbName, currentTenant);
|
|
120
|
+
connections[dbName] = conn;
|
|
121
|
+
return conn;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
*
|
|
125
|
+
* @template {string} K
|
|
126
|
+
* @param {K} type
|
|
127
|
+
* @param {string} [dbId]
|
|
128
|
+
* @param {Tenant?} [tenant]
|
|
129
|
+
* @returns {Connections[K]}
|
|
130
|
+
*/
|
|
131
|
+
function connect(type, dbId, tenant) {
|
|
132
|
+
const res = allDefines[type]?.connect?.(findConnection(type, dbId, tenant));
|
|
133
|
+
if (!res) throw new Error();
|
|
134
|
+
return res;
|
|
135
|
+
}
|
|
136
|
+
const [dbGetter, dbSetter] = createStore(null);
|
|
137
|
+
/**
|
|
138
|
+
* @template {string & keyof ProvidersConverted} T
|
|
139
|
+
* @param {T} type
|
|
140
|
+
* @param {string?} [dbId]
|
|
141
|
+
* @returns {Connections[T]}
|
|
142
|
+
*/
|
|
143
|
+
function useConnection(type, dbId) {
|
|
144
|
+
has(true);
|
|
145
|
+
let dbs = dbGetter();
|
|
146
|
+
if (!dbs) {
|
|
147
|
+
dbs = {};
|
|
148
|
+
dbSetter(dbs);
|
|
149
|
+
}
|
|
150
|
+
let typed = dbs[type];
|
|
151
|
+
if (!typed) {
|
|
152
|
+
typed = {};
|
|
153
|
+
dbs[type] = typed;
|
|
154
|
+
}
|
|
155
|
+
const dbName = String(dbId || "");
|
|
156
|
+
if (Object.hasOwn(typed, dbName)) return typed[dbName];
|
|
157
|
+
const db = connect(type, dbName);
|
|
158
|
+
typed[dbName] = db;
|
|
159
|
+
addFinally(() => {
|
|
160
|
+
db.abort?.();
|
|
161
|
+
});
|
|
162
|
+
return db;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region packages/connection/rdb.mjs
|
|
167
|
+
/**
|
|
168
|
+
* @param {string?} [dbId]
|
|
169
|
+
*/
|
|
170
|
+
function useDatabase(dbId) {
|
|
171
|
+
return useConnection("rdb", dbId);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
* @param {...string | null | (string | null)[]} names
|
|
176
|
+
*/
|
|
177
|
+
function transaction(...names) {
|
|
178
|
+
const allNames = new Set(names.flat().filter((v) => v && typeof v === "string" || v === null));
|
|
179
|
+
if (!allNames.size) allNames.add(null);
|
|
180
|
+
/**
|
|
181
|
+
* @template {any[]} P
|
|
182
|
+
* @template {any} R
|
|
183
|
+
* @template {any} T
|
|
184
|
+
* @param {(this:T, ...p: P) => Promise<R>} f
|
|
185
|
+
* @param {ClassMethodDecoratorContext} ctx
|
|
186
|
+
* @returns {(this:T, ...p: P) => Promise<R>}
|
|
187
|
+
*/
|
|
188
|
+
return function decorator(f, ctx) {
|
|
189
|
+
if (typeof f !== "function") throw new Error("事务修饰器只能加在方法上");
|
|
190
|
+
if (ctx.kind !== "method") throw new Error("事务修饰器只能加在方法上");
|
|
191
|
+
let fn = f;
|
|
192
|
+
for (const name of allNames) fn = async function(...p) {
|
|
193
|
+
return useDatabase(name).transaction((signal) => {
|
|
194
|
+
return f.apply(this, p);
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
return fn;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//#endregion
|
|
202
|
+
//#region packages/connection/mq.mjs
|
|
203
|
+
/** @import { Tenant } from '@yongdall/types' */
|
|
204
|
+
/**
|
|
205
|
+
*
|
|
206
|
+
* @param {string} channel
|
|
207
|
+
* @param {any} message
|
|
208
|
+
* @param {string} [service]
|
|
209
|
+
* @param {Tenant?} [tenant]
|
|
210
|
+
*/
|
|
211
|
+
async function publishMessage(channel, message, service, tenant) {
|
|
212
|
+
return connect("mq", service, tenant).publish(channel, message);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
*
|
|
216
|
+
* @param {string} channel
|
|
217
|
+
* @param {(val: any) => any} listener
|
|
218
|
+
* @param {string} [service]
|
|
219
|
+
*/
|
|
220
|
+
function subscribeMessage(channel, listener, service) {
|
|
221
|
+
return connect("mq", service).subscribe(channel, listener);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
//#region packages/connection/tq.mjs
|
|
226
|
+
/** @import { Tenant } from '@yongdall/types' */
|
|
227
|
+
/**
|
|
228
|
+
*
|
|
229
|
+
* @param {string} queue
|
|
230
|
+
* @param {any} message
|
|
231
|
+
* @param {string} [service]
|
|
232
|
+
* @param {Tenant?} [tenant]
|
|
233
|
+
*/
|
|
234
|
+
async function publishTask(queue, message, service, tenant) {
|
|
235
|
+
return connect("tq", service, tenant).publish(queue, message);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* @template T
|
|
239
|
+
* @param {string} queue
|
|
240
|
+
* @param {string} [service]
|
|
241
|
+
* @returns {Promise<T | void>}
|
|
242
|
+
*/
|
|
243
|
+
function waitTask(queue, service) {
|
|
244
|
+
return connect("tq", service).get(queue);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
//#endregion
|
|
248
|
+
export { clear, connect, publishMessage, publishTask, stop, subscribeMessage, transaction, useConnection, useDatabase, waitTask };
|
|
249
|
+
//# sourceMappingURL=index.mjs.map
|
package/index.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../packages/connection/main.mjs","../../packages/connection/rdb.mjs","../../packages/connection/mq.mjs","../../packages/connection/tq.mjs"],"sourcesContent":["import { addFinally, createStore, has } from '@yongdall/context';\nimport { getModel, useTenant, hooks } from '@yongdall/core';\nimport { Query } from '@yongdall/model';\n/** @import { Tenant } from '@yongdall/types' */\n\n/** @import {Connections, Hooks, Providers, ProvidersConverted} from './types.mjs' */\n\n\n\n\n/**\n * @returns {[\n * Hooks['providers'],\n * Hooks['providerDefines'],\n * ]}\n */\nfunction getProviders() {\n\n\t/** @type {[string, Hooks['providers'][keyof Hooks['providers']]][]} */\n\tconst list = [...hooks.get('providers').values()].flatMap(v => v ? Object.entries(v) : []);\n\tconst allProviders = Object.assign(Object.create(null), Object.fromEntries(\n\t\tObject.entries(Object.groupBy(list, 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\t/** @type {[string, Hooks['providerDefines'][keyof Hooks['providerDefines']]][]} */\n\tconst list0 = [...hooks.get('providerDefines').values()].flatMap(v => v ? Object.entries(v) : []);\n\tconst allDefines = Object.assign(Object.create(null), Object.fromEntries(list0));\n\n\n\treturn [allProviders, allDefines];\n}\nlet [allProviders, allDefines] = getProviders();\nhooks.listen(() => {\n\t[allProviders, allDefines] = getProviders();\n}, -1000000);\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 */\nexport async function clear(type, name, tenant) {\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\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<string | null | void>}\n */\nasync function getUri(type, name, tenant) {\n\tif (!name) {\n\t\tconst provider = tenant.providers[type];\n\t\treturn typeof provider === 'string' && provider || null;\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\tconst a = await connect('rdb', '', tenant).first(sql.select('uri'));\n\treturn a?.uri;\n}\n\n/**\n * @template {string & keyof Providers} K\n * @param {K} type \n * @param {string} name \n * @param {Tenant} tenant\n */\nasync function link(type, name, tenant) {\n\tconst providers = allProviders[type];\n\tif (!providers) { throw new Error(`不支持 ${type} 类型`); }\n\tconst uri = await getUri(type, name, tenant);\n\tif (!uri || typeof uri !== 'string') {\n\t\t/** @type {ProvidersConverted[K] | Providers[K]} */\n\t\tconst conn = allDefines[type]?.default\n\t\tif (!conn) {\n\t\t\tthrow new Error(`找不到 URI (${type}, ${name})`);\n\t\t}\n\t\treturn conn;\n\t}\n\n\n\tconst protocol = uri.split(':', 1)[0].split('+', 1)[0].toLowerCase();\n\tconst provider = providers[protocol];\n\tif (typeof provider !== 'function') {\n\t\tthrow new Error(`不支持 ${protocol} 协议`);\n\t}\n\tconst promise = await provider(uri);\n\t/** @type {ProvidersConverted[K] | Providers[K]} */\n\tconst conn = allDefines[type]?.convert?.(promise) || promise;\n\tif (!conn) { throw new Error(); }\n\treturn conn;\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[type] = tenantConnections;\n\t}\n\t// TODO: 实现多组合支持\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 conn = link(type, dbName, currentTenant);\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","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 { Tenant } from '@yongdall/types' */\n\n/**\n * \n * @param {string} channel \n * @param {any} message \n * @param {string} [service] \n * @param {Tenant?} [tenant]\n */\nexport async function publishMessage(channel, message, service, tenant) {\n\treturn connect('mq', service, tenant).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 { Tenant } from '@yongdall/types' */\n\n/**\n * \n * @param {string} queue \n * @param {any} message \n * @param {string} [service] \n * @param {Tenant?} [tenant]\n */\nexport async function publishTask(queue, message, service, tenant) {\n\treturn connect('tq', service, tenant).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"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yongdall/connection",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"main": "./index.mjs",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.mjs"
|
|
7
|
+
},
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"description": "",
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@yongdall/common": "^0.1.0",
|
|
15
|
+
"@yongdall/context": "^0.1.0",
|
|
16
|
+
"@yongdall/core": "^0.1.0",
|
|
17
|
+
"@yongdall/model": "^0.1.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@yongdall/types": "^0.1.0"
|
|
21
|
+
}
|
|
22
|
+
}
|
package/types.d.mts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { Hook } from "@yongdall/common";
|
|
2
|
+
import { Connection, IConnection, MaybePromise } from "@yongdall/model";
|
|
3
|
+
import { Readable } from "node:stream";
|
|
4
|
+
import { Tenant } from "@yongdall/types";
|
|
5
|
+
import * as imodel0 from "imodel";
|
|
6
|
+
|
|
7
|
+
//#region packages/connection/main.d.mts
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @template {string} K
|
|
11
|
+
* @param {K} type
|
|
12
|
+
* @param {string} name
|
|
13
|
+
* @param {Tenant?} [tenant]
|
|
14
|
+
*/
|
|
15
|
+
declare function clear<K extends string>(type: K, name: string, tenant?: Tenant | null): Promise<void>;
|
|
16
|
+
declare function stop(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @template {string} K
|
|
20
|
+
* @param {K} type
|
|
21
|
+
* @param {string} [dbId]
|
|
22
|
+
* @param {Tenant?} [tenant]
|
|
23
|
+
* @returns {Connections[K]}
|
|
24
|
+
*/
|
|
25
|
+
declare function connect<K extends string>(type: K, dbId?: string, tenant?: Tenant | null): Connections[K];
|
|
26
|
+
/**
|
|
27
|
+
* @template {string & keyof ProvidersConverted} T
|
|
28
|
+
* @param {T} type
|
|
29
|
+
* @param {string?} [dbId]
|
|
30
|
+
* @returns {Connections[T]}
|
|
31
|
+
*/
|
|
32
|
+
declare function useConnection<T extends string & keyof ProvidersConverted>(type: T, dbId?: string | null): Connections[T];
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region packages/connection/rdb.d.mts
|
|
35
|
+
/**
|
|
36
|
+
* @param {string?} [dbId]
|
|
37
|
+
*/
|
|
38
|
+
declare function useDatabase(dbId?: string | null): imodel0.Connection<any>;
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param {...string | null | (string | null)[]} names
|
|
42
|
+
*/
|
|
43
|
+
declare function transaction(...names: (string | null | (string | null)[])[]): (f: (this: T, ...p: P) => Promise<R>, ctx: ClassMethodDecoratorContext) => (this: T, ...p: P) => Promise<R>;
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region packages/connection/mq.d.mts
|
|
46
|
+
/** @import { Tenant } from '@yongdall/types' */
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @param {string} channel
|
|
50
|
+
* @param {any} message
|
|
51
|
+
* @param {string} [service]
|
|
52
|
+
* @param {Tenant?} [tenant]
|
|
53
|
+
*/
|
|
54
|
+
declare function publishMessage(channel: string, message: any, service?: string, tenant?: Tenant | null): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
*
|
|
57
|
+
* @param {string} channel
|
|
58
|
+
* @param {(val: any) => any} listener
|
|
59
|
+
* @param {string} [service]
|
|
60
|
+
*/
|
|
61
|
+
declare function subscribeMessage(channel: string, listener: (val: any) => any, service?: string): () => void;
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region packages/connection/tq.d.mts
|
|
64
|
+
/** @import { Tenant } from '@yongdall/types' */
|
|
65
|
+
/**
|
|
66
|
+
*
|
|
67
|
+
* @param {string} queue
|
|
68
|
+
* @param {any} message
|
|
69
|
+
* @param {string} [service]
|
|
70
|
+
* @param {Tenant?} [tenant]
|
|
71
|
+
*/
|
|
72
|
+
declare function publishTask(queue: string, message: any, service?: string, tenant?: Tenant | null): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* @template T
|
|
75
|
+
* @param {string} queue
|
|
76
|
+
* @param {string} [service]
|
|
77
|
+
* @returns {Promise<T | void>}
|
|
78
|
+
*/
|
|
79
|
+
declare function waitTask<T>(queue: string, service?: string): Promise<T | void>;
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region packages/connection/types.d.mts
|
|
82
|
+
type Provider<T> = (uri: string) => T | PromiseLike<T>;
|
|
83
|
+
interface MessageQueue {
|
|
84
|
+
publish(channel: string, data: any): void;
|
|
85
|
+
subscribe(channel: string, subscriber: (data: any) => void): PromiseLike<() => void> | (() => void);
|
|
86
|
+
}
|
|
87
|
+
interface TaskQueue {
|
|
88
|
+
publish(queue: string, data: any): void;
|
|
89
|
+
get<T>(queue: string): PromiseLike<T | void> | T | void;
|
|
90
|
+
disconnect(): void;
|
|
91
|
+
}
|
|
92
|
+
interface Cache {
|
|
93
|
+
set(key: string, field: string, value: any): PromiseLike<void> | void;
|
|
94
|
+
get<T>(key: string, field: string): PromiseLike<T | void> | T | void;
|
|
95
|
+
exists(key: string, field: string): PromiseLike<boolean> | boolean;
|
|
96
|
+
del(key: string, field: string): PromiseLike<void> | void;
|
|
97
|
+
clear(key: string): PromiseLike<void> | void;
|
|
98
|
+
disconnect(): void;
|
|
99
|
+
}
|
|
100
|
+
interface FileStore {
|
|
101
|
+
read(path: string): Promise<ReadableStream>;
|
|
102
|
+
write(path: string, data: ReadableStream | Blob | ArrayBufferView | ArrayBuffer | string | Buffer | Readable, size?: number): Promise<void>;
|
|
103
|
+
urlRead(path: string, expires?: number): Promise<string>;
|
|
104
|
+
urlWrite(path: string, expires?: number): Promise<string>;
|
|
105
|
+
abort?(): void;
|
|
106
|
+
}
|
|
107
|
+
interface Providers {
|
|
108
|
+
rdb: IConnection<any>;
|
|
109
|
+
tq: TaskQueue;
|
|
110
|
+
mq: MessageQueue;
|
|
111
|
+
fs: FileStore;
|
|
112
|
+
cache: Cache;
|
|
113
|
+
[k: string]: unknown;
|
|
114
|
+
}
|
|
115
|
+
interface ProvidersConverted {
|
|
116
|
+
rdb: IConnection<any> & {
|
|
117
|
+
abort?(): void;
|
|
118
|
+
};
|
|
119
|
+
tq: {
|
|
120
|
+
channels: Map<string, Promise<void>>;
|
|
121
|
+
service: TaskQueue;
|
|
122
|
+
abort?(): void;
|
|
123
|
+
};
|
|
124
|
+
mq: {
|
|
125
|
+
channels: Map<string, {
|
|
126
|
+
listeners: Set<(val: any) => any>;
|
|
127
|
+
promise: Promise<(() => void) | null>;
|
|
128
|
+
run: (value: any) => void;
|
|
129
|
+
}>;
|
|
130
|
+
service: MessageQueue;
|
|
131
|
+
abort?(): void;
|
|
132
|
+
};
|
|
133
|
+
fs: FileStore & {
|
|
134
|
+
abort?(): void;
|
|
135
|
+
};
|
|
136
|
+
cache: Omit<Cache, 'disconnect'> & {
|
|
137
|
+
abort(): void;
|
|
138
|
+
};
|
|
139
|
+
[k: string]: {
|
|
140
|
+
abort?(): void;
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
interface Connections {
|
|
144
|
+
rdb: Connection<any>;
|
|
145
|
+
tq: {
|
|
146
|
+
publish(queue: string, data: any): Promise<void>;
|
|
147
|
+
get<T>(queue: string): Promise<T | void>;
|
|
148
|
+
abort?(): void;
|
|
149
|
+
};
|
|
150
|
+
mq: {
|
|
151
|
+
publish(channel: string, data: any): Promise<void>;
|
|
152
|
+
subscribe(channel: string, subscriber: (data: any) => void): () => void;
|
|
153
|
+
abort?(): void;
|
|
154
|
+
};
|
|
155
|
+
fs: FileStore & {
|
|
156
|
+
abort?(): void;
|
|
157
|
+
};
|
|
158
|
+
cache: {
|
|
159
|
+
set(key: string, field: string, value: any): PromiseLike<void>;
|
|
160
|
+
get<T>(key: string, field: string): PromiseLike<T | void>;
|
|
161
|
+
exists(key: string, field: string): PromiseLike<boolean>;
|
|
162
|
+
del(key: string, field: string): PromiseLike<void>;
|
|
163
|
+
clear(key: string): PromiseLike<void>;
|
|
164
|
+
memoize<T>(key: string, field: string, exec: () => PromiseLike<T> | T): PromiseLike<T>;
|
|
165
|
+
abort?(): void;
|
|
166
|
+
};
|
|
167
|
+
[k: string]: {
|
|
168
|
+
abort?(): void;
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** 应用配置 */
|
|
172
|
+
interface Hooks {
|
|
173
|
+
providers: { [K in keyof Providers]: Record<string, Provider<Providers[K]>> };
|
|
174
|
+
providerDefines: { [K in keyof ProvidersConverted]: {
|
|
175
|
+
label: string;
|
|
176
|
+
convert: (vla: Providers[K]) => MaybePromise<ProvidersConverted[K]>;
|
|
177
|
+
connect: (vla: Promise<ProvidersConverted[K]>) => Connections[K];
|
|
178
|
+
default: ProvidersConverted[K];
|
|
179
|
+
} };
|
|
180
|
+
}
|
|
181
|
+
declare namespace Hooks {
|
|
182
|
+
type providers = Hook.Define<Hooks['providers']>;
|
|
183
|
+
type providerDefines = Hook.Define<Hooks['providerDefines']>;
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
186
|
+
export { Cache, Connections, FileStore, Hooks, MessageQueue, Provider, Providers, ProvidersConverted, TaskQueue, clear, connect, publishMessage, publishTask, stop, subscribeMessage, transaction, useConnection, useDatabase, waitTask };
|