@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.
@@ -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 };