@yongdall/connection 0.3.0 → 0.4.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/index.d.mts CHANGED
@@ -11,8 +11,9 @@ import * as imodel0 from "imodel";
11
11
  * @param {K} type
12
12
  * @param {string} name
13
13
  * @param {Tenant?} [tenant]
14
+ * @param {boolean} [isAlias]
14
15
  */
15
- declare function clear<K extends string>(type: K, name: string, tenant?: Tenant | null): Promise<void>;
16
+ declare function clear<K extends string>(type: K, name: string, tenant?: Tenant | null, isAlias?: boolean): Promise<void>;
16
17
  declare function stop(): Promise<void>;
17
18
  /**
18
19
  *
package/index.mjs CHANGED
@@ -33,8 +33,9 @@ let allConnections = Object.create(null);
33
33
  * @param {K} type
34
34
  * @param {string} name
35
35
  * @param {Tenant?} [tenant]
36
+ * @param {boolean} [isAlias]
36
37
  */
37
- async function clear(type, name, tenant) {
38
+ async function clear(type, name, tenant, isAlias) {
38
39
  const tenantId = (tenant || await useTenant()).id;
39
40
  const tenantConnections = allConnections[tenantId];
40
41
  if (!tenantConnections) return;
@@ -42,6 +43,7 @@ async function clear(type, name, tenant) {
42
43
  if (!connections) return;
43
44
  const db = connections[name];
44
45
  delete connections[name];
46
+ if (isAlias) return;
45
47
  return (await db)?.abort?.();
46
48
  }
47
49
  async function stop() {
@@ -55,42 +57,23 @@ async function stop() {
55
57
  * @param {T} type
56
58
  * @param {string} name
57
59
  * @param {Tenant} tenant
58
- * @returns {Promise<string | null | void>}
60
+ * @returns {Promise<[uri: string, alias?: string]>}
59
61
  */
60
62
  async function getUri(type, name, tenant) {
61
63
  if (!name) {
62
64
  const provider = tenant.providers[type];
63
- return typeof provider === "string" && provider || null;
65
+ return [typeof provider === "string" && provider || ""];
64
66
  }
65
67
  const model = await getModel("database");
66
- if (!model) return;
68
+ if (!model) return [""];
67
69
  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;
70
+ sql = sql.select("uri");
71
+ const aliasField = model.fields.alias;
72
+ if (aliasField && aliasField.type === "string") sql = sql.select("alias");
73
+ const a = await connect("rdb", "", tenant).first(sql);
74
+ if (!a) return [""];
75
+ const { uri, alias } = a;
76
+ return [uri || "", alias];
94
77
  }
95
78
  /**
96
79
  *
@@ -105,7 +88,7 @@ async function findConnection(type, dbId, tenant) {
105
88
  let tenantConnections = allConnections[tenantId];
106
89
  if (!tenantConnections) {
107
90
  tenantConnections = Object.create(null);
108
- allConnections[type] = tenantConnections;
91
+ allConnections[tenantId] = tenantConnections;
109
92
  }
110
93
  /** @type {Record<string, Promise<ProvidersConverted[K]>>} */
111
94
  let connections = tenantConnections[type];
@@ -116,7 +99,37 @@ async function findConnection(type, dbId, tenant) {
116
99
  const dbName = String(dbId || "");
117
100
  const connection = connections[dbName];
118
101
  if (connection) return connection;
119
- const conn = link(type, dbName, currentTenant);
102
+ const providers = allProviders[type];
103
+ if (!providers) throw new Error(`不支持 ${type} 类型`);
104
+ /**
105
+ *
106
+ * @param {string} uri
107
+ * @returns
108
+ */
109
+ async function build(uri) {
110
+ if (!uri) {
111
+ /** @type {ProvidersConverted[K] | Providers[K]} */
112
+ const conn = allDefines[type]?.default;
113
+ if (conn) return conn;
114
+ throw new Error(`找不到 URI (${type}, ${dbName})`);
115
+ }
116
+ const protocol = uri.split(":", 1)[0].split("+", 1)[0].toLowerCase();
117
+ const provider = providers[protocol];
118
+ if (typeof provider !== "function") throw new Error(`不支持 ${protocol} 协议`);
119
+ const promise = await provider(uri);
120
+ /** @type {ProvidersConverted[K] | Providers[K]} */
121
+ const conn = allDefines[type]?.convert?.(promise) || promise;
122
+ if (!conn) throw new Error();
123
+ return conn;
124
+ }
125
+ const conn = getUri(type, dbName, currentTenant).then(([uri, alias]) => {
126
+ if (!alias) return build(uri);
127
+ const connection = connections[alias];
128
+ if (connection) return connection;
129
+ const conn = getUri(type, alias, currentTenant).then(([uri, alias]) => alias ? Promise.reject(/* @__PURE__ */ new Error()) : build(uri));
130
+ connections[alias] = conn;
131
+ return conn;
132
+ });
120
133
  connections[dbName] = conn;
121
134
  return conn;
122
135
  }
package/index.mjs.map CHANGED
@@ -1 +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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"}
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 * @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","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 CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "@yongdall/connection",
3
+ "version": "0.4.0",
3
4
  "type": "module",
4
5
  "main": "./index.mjs",
5
6
  "exports": {
6
7
  ".": "./index.mjs"
7
8
  },
8
- "version": "0.3.0",
9
9
  "description": "",
10
10
  "keywords": [],
11
11
  "author": "",
12
12
  "license": "ISC",
13
13
  "dependencies": {
14
- "@yongdall/common": "^0.3.0",
15
- "@yongdall/context": "^0.3.0",
16
- "@yongdall/core": "^0.3.0",
17
- "@yongdall/model": "^0.3.0"
14
+ "@yongdall/common": "^0.4.0",
15
+ "@yongdall/context": "^0.4.0",
16
+ "@yongdall/core": "^0.4.0",
17
+ "@yongdall/model": "^0.4.0"
18
18
  },
19
19
  "devDependencies": {
20
- "@yongdall/types": "^0.3.0"
20
+ "@yongdall/types": "^0.4.0"
21
21
  }
22
22
  }