@zhin.js/database 1.1.7 → 1.2.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/README.md +16 -10
- package/lib/base/database.js +7 -0
- package/lib/base/statement-rows.d.ts +5 -0
- package/lib/base/statement-rows.js +16 -0
- package/lib/base/transaction.d.ts +3 -1
- package/lib/base/transaction.js +6 -0
- package/lib/console-credential.d.ts +181 -0
- package/lib/console-credential.js +633 -0
- package/lib/dialects/mongodb.js +7 -2
- package/lib/dialects/mysql.d.ts +34 -0
- package/lib/dialects/mysql.js +135 -13
- package/lib/dialects/pg.d.ts +19 -0
- package/lib/dialects/pg.js +81 -14
- package/lib/dialects/sqlite.d.ts +86 -2
- package/lib/dialects/sqlite.js +453 -20
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/probe.d.ts +30 -0
- package/lib/probe.js +98 -0
- package/lib/reserved-tables.d.ts +27 -0
- package/lib/reserved-tables.js +78 -0
- package/lib/types.d.ts +21 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Universal database abstraction layer for Zhin.js framework with support for mult
|
|
|
8
8
|
npm install @zhin.js/database
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Install the database driver you need(SQLite 使用 Node 内置 `node:sqlite`,无需安装,需 Node.js 22.
|
|
11
|
+
Install the database driver you need(SQLite 使用 Node 内置 `node:sqlite`,无需安装,需 Node.js >=22.19.0,推荐 24+):
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
# For MySQL
|
|
@@ -83,7 +83,7 @@ const user = await userModel.create({
|
|
|
83
83
|
## Supported Databases
|
|
84
84
|
|
|
85
85
|
### ✅ Relational Databases (已完整实现)
|
|
86
|
-
- **SQLite** - 内置支持,使用 Node 自带 `node:sqlite`(无需安装驱动,需 Node.js 22.
|
|
86
|
+
- **SQLite** - 内置支持,使用 Node 自带 `node:sqlite`(无需安装驱动,需 Node.js >=22.19.0,推荐 24+)
|
|
87
87
|
- 轻量级、零配置
|
|
88
88
|
- 适合中小型应用
|
|
89
89
|
- 支持 WAL 模式
|
|
@@ -262,27 +262,33 @@ await db.start();
|
|
|
262
262
|
|
|
263
263
|
## Model API
|
|
264
264
|
|
|
265
|
+
以下为关系型模型(`RelatedModel`,SQLite / MySQL / PostgreSQL)的便捷方法;更复杂的查询见下方链式查询 API。
|
|
266
|
+
|
|
265
267
|
```typescript
|
|
266
268
|
const model = db.model('users');
|
|
267
269
|
|
|
268
270
|
// Create
|
|
269
271
|
const user = await model.create({ name: 'John', email: 'john@example.com' });
|
|
272
|
+
const created = await model.createMany([{ name: 'A' }, { name: 'B' }]);
|
|
270
273
|
|
|
271
274
|
// Read
|
|
272
|
-
const users = await model.
|
|
273
|
-
const
|
|
275
|
+
const users = await model.findAll({ name: 'John' });
|
|
276
|
+
const one = await model.findOne({ email: 'john@example.com' });
|
|
277
|
+
const byId = await model.findById(1);
|
|
274
278
|
|
|
275
|
-
// Update
|
|
276
|
-
await model.
|
|
279
|
+
// Update —— 条件在前、数据在后;返回受影响行数
|
|
280
|
+
await model.updateWhere({ name: 'John' }, { name: 'Jane' });
|
|
281
|
+
await model.updateById(1, { name: 'Jane' });
|
|
277
282
|
|
|
278
|
-
// Delete
|
|
279
|
-
await model.
|
|
283
|
+
// Delete —— 启用软删除的模型会改为标记 deletedAt
|
|
284
|
+
await model.deleteWhere({ name: 'Jane' });
|
|
285
|
+
await model.deleteById(1);
|
|
280
286
|
|
|
281
287
|
// Count
|
|
282
288
|
const count = await model.count({ email: { $like: '%@example.com' } });
|
|
283
289
|
|
|
284
|
-
// Pagination
|
|
285
|
-
const
|
|
290
|
+
// Pagination —— 用链式查询
|
|
291
|
+
const page = await model.select().where({}).limit(10).offset(0);
|
|
286
292
|
```
|
|
287
293
|
|
|
288
294
|
## 链式查询 API (Fluent Query Builder)
|
package/lib/base/database.js
CHANGED
|
@@ -236,6 +236,13 @@ export class Database {
|
|
|
236
236
|
},
|
|
237
237
|
commit: () => trx.commit(),
|
|
238
238
|
rollback: () => trx.rollback(),
|
|
239
|
+
...(trx.queryStatement ? {
|
|
240
|
+
queryStatement: (sql, options) => {
|
|
241
|
+
if (!frame.active)
|
|
242
|
+
return Promise.reject(new Error('Database transaction is already closed'));
|
|
243
|
+
return trx.queryStatement(sql, options);
|
|
244
|
+
},
|
|
245
|
+
} : {}),
|
|
239
246
|
};
|
|
240
247
|
const trxContext = new TransactionContextImpl(this, guarded);
|
|
241
248
|
try {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Row-cap helpers of `Transaction.queryStatement` (internal, not part of the public entry). */
|
|
2
|
+
/** Marks a row array as cut at `maxRows` (non-enumerable, so JSON and equality ignore it). */
|
|
3
|
+
export declare function markTruncated<T extends unknown[]>(rows: T, truncated: boolean): T;
|
|
4
|
+
/** Applies {@link StatementQueryOptions.maxRows} to a fully read result. */
|
|
5
|
+
export declare function capRows<T>(result: T, maxRows: number | undefined): T;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Row-cap helpers of `Transaction.queryStatement` (internal, not part of the public entry). */
|
|
2
|
+
/** Marks a row array as cut at `maxRows` (non-enumerable, so JSON and equality ignore it). */
|
|
3
|
+
export function markTruncated(rows, truncated) {
|
|
4
|
+
if (Array.isArray(rows) && !Object.isFrozen(rows))
|
|
5
|
+
Object.defineProperty(rows, 'truncated', { value: truncated, enumerable: false, configurable: true });
|
|
6
|
+
return rows;
|
|
7
|
+
}
|
|
8
|
+
/** Applies {@link StatementQueryOptions.maxRows} to a fully read result. */
|
|
9
|
+
export function capRows(result, maxRows) {
|
|
10
|
+
if (maxRows === undefined || !Array.isArray(result))
|
|
11
|
+
return result;
|
|
12
|
+
const extra = result.length > maxRows;
|
|
13
|
+
if (extra)
|
|
14
|
+
result.splice(maxRows);
|
|
15
|
+
return markTruncated(result, extra);
|
|
16
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transaction, TransactionContext, TransactionSelection, TransactionUpdation, TransactionDeletion } from '../types.js';
|
|
1
|
+
import { Transaction, TransactionContext, TransactionSelection, TransactionUpdation, TransactionDeletion, StatementQueryOptions } from '../types.js';
|
|
2
2
|
import type { Database } from './database.js';
|
|
3
3
|
/**
|
|
4
4
|
* 增强的事务上下文实现
|
|
@@ -20,6 +20,8 @@ export declare class TransactionContextImpl<S extends Record<string, object>> im
|
|
|
20
20
|
* 执行原生 SQL
|
|
21
21
|
*/
|
|
22
22
|
query<T = any>(sql: string, params?: any[]): Promise<T>;
|
|
23
|
+
/** One statement through the single-statement protocol of the dialect (see {@link Transaction.queryStatement}). */
|
|
24
|
+
queryStatement<T = any>(sql: string, options?: StatementQueryOptions): Promise<T>;
|
|
23
25
|
/**
|
|
24
26
|
* 插入单条数据
|
|
25
27
|
*/
|
package/lib/base/transaction.js
CHANGED
|
@@ -138,6 +138,12 @@ export class TransactionContextImpl {
|
|
|
138
138
|
async query(sql, params) {
|
|
139
139
|
return this.trx.query(sql, params);
|
|
140
140
|
}
|
|
141
|
+
/** One statement through the single-statement protocol of the dialect (see {@link Transaction.queryStatement}). */
|
|
142
|
+
async queryStatement(sql, options) {
|
|
143
|
+
if (!this.trx.queryStatement)
|
|
144
|
+
throw new Error('This database does not support single-statement queries');
|
|
145
|
+
return this.trx.queryStatement(sql, options);
|
|
146
|
+
}
|
|
141
147
|
/**
|
|
142
148
|
* 插入单条数据
|
|
143
149
|
*/
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
export type ConsoleCredentialDialect = 'pg' | 'mysql';
|
|
2
|
+
/** Runs one statement on a connection (parameters bound by the driver). */
|
|
3
|
+
export type ConsoleSqlRunner = (sql: string, params?: unknown[]) => Promise<unknown>;
|
|
4
|
+
/** Connections the restricted account may hold at once (the Console pool uses at most 2). */
|
|
5
|
+
export declare const CONSOLE_ROLE_CONNECTION_LIMIT = 4;
|
|
6
|
+
/** Role-level `statement_timeout` backstop (the Console sets a shorter one per transaction). */
|
|
7
|
+
export declare const CONSOLE_ROLE_STATEMENT_TIMEOUT = "60s";
|
|
8
|
+
/** Privileges of the PostgreSQL account on tables / sequences of `public`. */
|
|
9
|
+
export declare const PG_CONSOLE_TABLE_PRIVILEGES = "SELECT, INSERT, UPDATE, DELETE, TRUNCATE";
|
|
10
|
+
export declare const PG_CONSOLE_SEQUENCE_PRIVILEGES = "USAGE, SELECT, UPDATE";
|
|
11
|
+
/** Privileges of the MySQL account on `<database>.*` (nothing global). */
|
|
12
|
+
export declare const MYSQL_CONSOLE_PRIVILEGES: readonly ["SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "ALTER", "DROP", "INDEX", "REFERENCES", "CREATE VIEW", "SHOW VIEW", "CREATE TEMPORARY TABLES"];
|
|
13
|
+
/** Schema privileges the MySQL account must never hold. */
|
|
14
|
+
export declare const MYSQL_FORBIDDEN_PRIVILEGES: ReadonlySet<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Role-level settings of the PostgreSQL account (`pg_db_role_setting`), exactly: the probe refuses
|
|
17
|
+
* an account whose settings differ — the account itself may `ALTER ROLE current_user SET …`
|
|
18
|
+
* (e.g. `search_path = pg_temp, public`), which would change how the main account's objects resolve
|
|
19
|
+
* in its sessions.
|
|
20
|
+
*/
|
|
21
|
+
export declare const PG_CONSOLE_ROLE_SETTINGS: readonly string[];
|
|
22
|
+
/** SCRAM-SHA-256 iteration count of the verifier sent instead of the password (PostgreSQL default). */
|
|
23
|
+
export declare const PG_SCRAM_ITERATIONS = 4096;
|
|
24
|
+
/**
|
|
25
|
+
* A PostgreSQL SCRAM-SHA-256 verifier (`SCRAM-SHA-256$<iter>:<salt>$<StoredKey>:<ServerKey>`, RFC
|
|
26
|
+
* 7677 / `pg_authid.rolpassword` format) computed on the client, so `CREATE` / `ALTER ROLE` never
|
|
27
|
+
* carries the password itself — not to the server log, not into `--print-sql` output. The password
|
|
28
|
+
* is base64url ASCII, so SASLprep leaves it unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export declare function pgScramVerifier(password: string, salt?: Buffer, iterations?: number): string;
|
|
31
|
+
/** Replaces every spelling of `secret` (raw, quoted, URL-encoded) in `text` with `[redacted]`. */
|
|
32
|
+
export declare function scrubSecret(text: string, secrets: readonly (string | undefined)[]): string;
|
|
33
|
+
/** An error with `secrets` scrubbed from its message (driver codes kept; the original is dropped). */
|
|
34
|
+
export declare function scrubbedError(error: unknown, secrets: readonly (string | undefined)[]): Error;
|
|
35
|
+
/** `zhin_console_<first 8 hex of SHA-256(projectKey)>`: one account per project. */
|
|
36
|
+
export declare function consoleRoleName(projectKey: string): string;
|
|
37
|
+
/** 32 random bytes, base64url (no quotes or backslashes: safe inside a SQL literal). */
|
|
38
|
+
export declare function generateConsolePassword(): string;
|
|
39
|
+
export declare function quotePgIdentifier(name: string): string;
|
|
40
|
+
export interface ConsoleRoleStatementOptions {
|
|
41
|
+
readonly dialect: ConsoleCredentialDialect;
|
|
42
|
+
readonly role: string;
|
|
43
|
+
/** The account's password; `--print-sql` passes a placeholder the DBA replaces. */
|
|
44
|
+
readonly password: string;
|
|
45
|
+
/** The project database. */
|
|
46
|
+
readonly database: string;
|
|
47
|
+
/** The main account (PostgreSQL: default privileges are declared for the tables it creates). */
|
|
48
|
+
readonly mainUser: string;
|
|
49
|
+
/** MySQL: host part of the new account (the host part of the main account's `CURRENT_USER()`). */
|
|
50
|
+
readonly host?: string;
|
|
51
|
+
/** PostgreSQL: the role exists already (ALTER instead of CREATE). */
|
|
52
|
+
readonly exists?: boolean;
|
|
53
|
+
/** PostgreSQL: the main account is a superuser (may set SUPERUSER / REPLICATION / BYPASSRLS attributes on ALTER). */
|
|
54
|
+
readonly mainIsSuperuser?: boolean;
|
|
55
|
+
/** PostgreSQL: the main account has CREATEDB (PG 16 lets only such an account name CREATEDB on ALTER). */
|
|
56
|
+
readonly mainCanCreateDb?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* PostgreSQL: tables (and views) of `public` to grant on. Undefined grants `ON ALL TABLES IN
|
|
59
|
+
* SCHEMA public`; gateway-owned names (`console_*`) are always left out.
|
|
60
|
+
*/
|
|
61
|
+
readonly tables?: readonly string[];
|
|
62
|
+
/** PostgreSQL ≤ 14: `PUBLIC` may create in `public`; revoke that (and grant CREATE to the main account first). */
|
|
63
|
+
readonly revokePublicCreate?: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** The statements that create (or rotate) the restricted account, in order. */
|
|
66
|
+
export declare function consoleRoleStatements(options: ConsoleRoleStatementOptions): string[];
|
|
67
|
+
/** `user@host` of MySQL `CURRENT_USER()` (the user part may itself contain `@`). */
|
|
68
|
+
export declare function splitMysqlAccount(account: string): {
|
|
69
|
+
user: string;
|
|
70
|
+
host: string;
|
|
71
|
+
};
|
|
72
|
+
export interface ProvisionConsoleRoleOptions {
|
|
73
|
+
readonly dialect: ConsoleCredentialDialect;
|
|
74
|
+
/** Role name; default {@link consoleRoleName}(projectKey). */
|
|
75
|
+
readonly role?: string;
|
|
76
|
+
/** Stable project identity for the default role name (the CLI passes the project root). */
|
|
77
|
+
readonly projectKey: string;
|
|
78
|
+
/** Default {@link generateConsolePassword}. */
|
|
79
|
+
readonly password?: string;
|
|
80
|
+
}
|
|
81
|
+
export interface ConsoleRolePlan {
|
|
82
|
+
readonly dialect: ConsoleCredentialDialect;
|
|
83
|
+
readonly user: string;
|
|
84
|
+
readonly password: string;
|
|
85
|
+
/** MySQL host part of the account. */
|
|
86
|
+
readonly host?: string;
|
|
87
|
+
readonly database: string;
|
|
88
|
+
readonly mainUser: string;
|
|
89
|
+
readonly statements: readonly string[];
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Reads what the statements need from the main account's connection (its name, the database,
|
|
93
|
+
* existing tables, whether the role exists) and returns the plan without running it
|
|
94
|
+
* (`--print-sql`).
|
|
95
|
+
*/
|
|
96
|
+
export declare function planConsoleRole(run: ConsoleSqlRunner, options: ProvisionConsoleRoleOptions): Promise<ConsoleRolePlan>;
|
|
97
|
+
/**
|
|
98
|
+
* Creates (or rotates the password of) the restricted account with the main account's
|
|
99
|
+
* connection. Needs CREATEROLE (PostgreSQL) or CREATE USER + GRANT OPTION (MySQL); without them
|
|
100
|
+
* the first statement fails and the caller offers `--print-sql`.
|
|
101
|
+
*/
|
|
102
|
+
export declare function provisionConsoleRole(run: ConsoleSqlRunner, options: ProvisionConsoleRoleOptions): Promise<ConsoleRolePlan>;
|
|
103
|
+
/**
|
|
104
|
+
* Version check of `CREATE USER IF NOT EXISTS` / `ALTER USER … IDENTIFIED BY` (MySQL 5.7.6,
|
|
105
|
+
* MariaDB 10.1.3); `undefined` when supported.
|
|
106
|
+
*/
|
|
107
|
+
export declare function mysqlVersionProblem(version: string): string | undefined;
|
|
108
|
+
/** Role grants and PROXY grants in `SHOW GRANTS` output (`GRANT \`r\`@\`%\` TO …`, `GRANT PROXY ON …`). */
|
|
109
|
+
export declare function mysqlRoleAndProxyGrants(lines: readonly string[]): {
|
|
110
|
+
readonly roles: readonly string[];
|
|
111
|
+
readonly proxies: readonly string[];
|
|
112
|
+
};
|
|
113
|
+
export interface ConsoleCredentialProbe {
|
|
114
|
+
readonly ok: boolean;
|
|
115
|
+
/** Why the account is not acceptable (empty when ok). */
|
|
116
|
+
readonly problems: readonly string[];
|
|
117
|
+
/** The account the connection logged in as. */
|
|
118
|
+
readonly user?: string;
|
|
119
|
+
/**
|
|
120
|
+
* For the log only (never shown to Console users): object names behind a problem, e.g. the
|
|
121
|
+
* SECURITY DEFINER functions the account may execute.
|
|
122
|
+
*/
|
|
123
|
+
readonly details?: readonly string[];
|
|
124
|
+
}
|
|
125
|
+
/** How many SECURITY DEFINER functions a probe names in its log details. */
|
|
126
|
+
export declare const PG_DEFINER_FUNCTIONS_LOGGED = 5;
|
|
127
|
+
/**
|
|
128
|
+
* The account may EXECUTE a SECURITY DEFINER function owned by another role outside `pg_catalog` /
|
|
129
|
+
* `information_schema` (extension functions in other schemas included): it would run with that
|
|
130
|
+
* owner's rights. PUBLIC has EXECUTE on functions by default, so provisioning cannot fix this
|
|
131
|
+
* without changing everyone's access — the owner revokes it (or grants it explicitly) instead.
|
|
132
|
+
*/
|
|
133
|
+
export declare const PG_DEFINER_FUNCTION_PROBLEM: string;
|
|
134
|
+
/**
|
|
135
|
+
* Functions that read or write server files or reach other servers (`pg_ls_*`, `pg_read_file`,
|
|
136
|
+
* `pg_read_binary_file`, `pg_stat_file`, server-side `lo_import` / `lo_export`, adminpack
|
|
137
|
+
* `pg_file_*`, `dblink*`): none of them may be executable by the console account (they are
|
|
138
|
+
* revoked from PUBLIC by default; an explicit grant or an extension that grants them is refused).
|
|
139
|
+
*/
|
|
140
|
+
export declare const PG_FILE_FUNCTIONS_QUERY = "SELECT DISTINCT p.proname AS name FROM pg_proc p\n WHERE (p.proname LIKE 'pg\\_ls\\_%' OR p.proname IN ('pg_read_file', 'pg_read_binary_file', 'pg_stat_file', 'lo_import', 'lo_export')\n OR p.proname LIKE 'pg\\_file\\_%' OR p.proname LIKE 'dblink%')\n AND has_function_privilege(current_user, p.oid, 'EXECUTE')\n ORDER BY 1";
|
|
141
|
+
/** The query behind {@link PG_DEFINER_FUNCTION_PROBLEM} (at most PG_DEFINER_FUNCTIONS_LOGGED + 1 rows). */
|
|
142
|
+
export declare const PG_DEFINER_FUNCTIONS_QUERY = "SELECT n.nspname AS schema, p.proname AS name FROM pg_proc p\n JOIN pg_namespace n ON n.oid = p.pronamespace\n WHERE p.prosecdef AND p.proowner <> (SELECT oid FROM pg_roles WHERE rolname = current_user)\n AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND n.nspname NOT LIKE 'pg\\_temp\\_%' AND n.nspname NOT LIKE 'pg\\_toast\\_temp\\_%'\n AND has_function_privilege(current_user, p.oid, 'EXECUTE')\n ORDER BY 1, 2 LIMIT 6";
|
|
143
|
+
export interface ProbeConsoleCredentialOptions {
|
|
144
|
+
readonly dialect: ConsoleCredentialDialect;
|
|
145
|
+
/** `database.console.user`. */
|
|
146
|
+
readonly expectedUser: string;
|
|
147
|
+
/** The main account (`database.user`; PostgreSQL also the main connection's `current_user`). */
|
|
148
|
+
readonly mainUser?: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Checks, on the restricted connection itself, that it is the configured account and holds no
|
|
152
|
+
* more than {@link consoleRoleStatements} grants. Raw Console SQL stays off unless `ok`.
|
|
153
|
+
*/
|
|
154
|
+
export declare function probeConsoleCredential(run: ConsoleSqlRunner, options: ProbeConsoleCredentialOptions): Promise<ConsoleCredentialProbe>;
|
|
155
|
+
export interface RefreshConsoleGrantsOptions {
|
|
156
|
+
readonly role: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* PostgreSQL, main account: grants the account the table / sequence privileges on what exists in
|
|
160
|
+
* `public` now (tables created before the default privileges, or by another role the main
|
|
161
|
+
* account can grant for), and revokes everything on gateway-owned (`console_*`) tables that are
|
|
162
|
+
* still in the project database. Idempotent; run at instance start.
|
|
163
|
+
*/
|
|
164
|
+
export declare function refreshConsoleGrants(run: ConsoleSqlRunner, options: RefreshConsoleGrantsOptions): Promise<{
|
|
165
|
+
readonly granted: readonly string[];
|
|
166
|
+
readonly revoked: readonly string[];
|
|
167
|
+
}>;
|
|
168
|
+
export interface ConsoleCredential {
|
|
169
|
+
readonly user: string;
|
|
170
|
+
readonly password: string;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Connection options of the restricted Console account, built from the main connection's options
|
|
174
|
+
* (ADR 0059 §4): the main account's credentials never reach it — neither as fields nor inside a
|
|
175
|
+
* PostgreSQL `connectionString` (whose `user` / `password`, also as query parameters, would win over
|
|
176
|
+
* explicit fields, empty ones included) nor a MySQL `uri` (whose query parameters fill every falsy
|
|
177
|
+
* field: `?multipleStatements=true` would beat `false`, `?flags=LOCAL_FILES` would re-enable LOCAL
|
|
178
|
+
* INFILE). Pool of at most two connections, session reset on release; MySQL without
|
|
179
|
+
* `LOCAL_FILES` and multiple statements.
|
|
180
|
+
*/
|
|
181
|
+
export declare function consoleConnectionOptions(dialect: ConsoleCredentialDialect, main: Readonly<Record<string, unknown>>, credential: ConsoleCredential): Record<string, unknown>;
|