letopis 1.3.0 → 1.4.1
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/AGENT-CHEATSHEET.en.md +14 -6
- package/AGENT-CHEATSHEET.md +18 -10
- package/CHANGELOG.md +247 -0
- package/README.en.md +146 -58
- package/README.md +129 -51
- package/dist/acl.d.ts +11 -5
- package/dist/admin.d.ts +30 -14
- package/dist/admin.js +42 -16
- package/dist/auth.d.ts +61 -17
- package/dist/auth.js +16 -2
- package/dist/cache.d.ts +5 -1
- package/dist/chain.d.ts +91 -15
- package/dist/chain.js +47 -4
- package/dist/cli.js +6 -0
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +5 -5
- package/dist/import.js +7 -0
- package/dist/index.d.ts +74 -45
- package/dist/index.js +18 -4
- package/dist/load.d.ts +10 -3
- package/dist/load.js +19 -4
- package/dist/mcp.d.ts +20 -11
- package/dist/mcp.js +4 -4
- package/dist/model.d.ts +4 -1
- package/dist/ops.d.ts +58 -18
- package/dist/ops.js +58 -18
- package/dist/project.d.ts +44 -12
- package/dist/project.js +90 -8
- package/dist/registry.d.ts +4 -1
- package/dist/registry.js +4 -1
- package/dist/sql.d.ts +4 -1
- package/dist/sql.js +12 -4
- package/dist/sync.js +11 -5
- package/dist/tx.js +10 -1
- package/dist/types.d.ts +14 -7
- package/dist/types.js +13 -6
- package/dist/up.d.ts +65 -25
- package/dist/up.js +152 -40
- package/dist/validate.d.ts +9 -2
- package/dist/validate.js +19 -3
- package/dist/watch.d.ts +17 -5
- package/dist/watch.js +40 -8
- package/dist/write.d.ts +3 -2
- package/dist/write.js +29 -10
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/sql/10-core.sql +6 -1
- package/sql/50-acl.sql +5 -1
- package/sql/60-write.sql +77 -22
- package/sql/80-auth.sql +39 -2
- package/sql/88-derived.sql +82 -1
- package/sql/90-time.sql +75 -38
- package/sql/95-seed.system.sql +6 -3
- package/sql/99-revision.sql +3 -2
- package/sql/README.md +2 -0
- package/sql/migrate/0007-secret-account-fk.sql +12 -0
package/dist/sync.js
CHANGED
|
@@ -12,13 +12,19 @@ export async function syncModels(db, models, opts = {}) {
|
|
|
12
12
|
const res = { applied: Boolean(opts.apply), created: [], updated: [], unchanged: [], skipped: [], lost: models.flatMap((m) => m.lostRules()) };
|
|
13
13
|
const S = `"${db.schema.replace(/"/g, '""')}"`;
|
|
14
14
|
// предок раньше потомка; класс-источник агрегата раньше цели: агрегат над классом, которого ещё нет, база отклоняет.
|
|
15
|
-
//
|
|
15
|
+
// Круг (агрегат над собственным потомком, цикл агрегатов) так не упорядочить — отказ до записи с самим кругом (хвост
|
|
16
|
+
// ревью доработок после 1.2.0: раньше обход молча ставил потомка раньше предка)
|
|
16
17
|
const ordered = [];
|
|
17
|
-
const
|
|
18
|
+
const path = [];
|
|
18
19
|
const visit = (m) => {
|
|
19
|
-
if (ordered.includes(m)
|
|
20
|
+
if (ordered.includes(m))
|
|
20
21
|
return;
|
|
21
|
-
|
|
22
|
+
const at = path.indexOf(m);
|
|
23
|
+
if (at >= 0) {
|
|
24
|
+
throw new LetopisError('invalid_class', `syncModels: модели зависят друг от друга по кругу: ${[...path.slice(at), m].map((x) => x.name).join(' → ')} — `
|
|
25
|
+
+ 'родителя и источник агрегата база ждёт раньше класса');
|
|
26
|
+
}
|
|
27
|
+
path.push(m);
|
|
22
28
|
if (m.parent && models.includes(m.parent))
|
|
23
29
|
visit(m.parent);
|
|
24
30
|
for (const a of Object.values(m.describe().aggregate ?? {})) {
|
|
@@ -26,7 +32,7 @@ export async function syncModels(db, models, opts = {}) {
|
|
|
26
32
|
if (src)
|
|
27
33
|
visit(src);
|
|
28
34
|
}
|
|
29
|
-
|
|
35
|
+
path.pop();
|
|
30
36
|
ordered.push(m);
|
|
31
37
|
};
|
|
32
38
|
models.forEach(visit);
|
package/dist/tx.js
CHANGED
|
@@ -282,7 +282,16 @@ export class ExplicitTx {
|
|
|
282
282
|
let changed = null;
|
|
283
283
|
try {
|
|
284
284
|
// чтение letopis.changed и COMMIT — одним конвейером (как в runTx); обрыв — исход неизвестен
|
|
285
|
-
const
|
|
285
|
+
const read = this.conn.unsafe(`select current_setting('letopis.changed', true) as changed`);
|
|
286
|
+
const commit = this.conn.unsafe('commit');
|
|
287
|
+
const [rows, res] = (await Promise.all([read, commit]).catch(async (e) => {
|
|
288
|
+
// транзакцию уже прервала ошибка, которую код внутри db.begin() поймал и проглотил: чтение получает 25P02,
|
|
289
|
+
// а COMMIT того же конвейера отвечает ROLLBACK — это tx_rolled_back, а не сырая ошибка PostgreSQL
|
|
290
|
+
const tail = e.code === '25P02' ? await commit.catch(() => null) : null;
|
|
291
|
+
if (tail?.command === 'ROLLBACK')
|
|
292
|
+
return [[], tail];
|
|
293
|
+
throw e;
|
|
294
|
+
}));
|
|
286
295
|
changed = rows[0]?.changed ?? null;
|
|
287
296
|
if (res.command === 'ROLLBACK') {
|
|
288
297
|
this.failure = new LetopisError('tx_rolled_back', 'commit: PostgreSQL откатил транзакцию (в ней была ошибка)');
|
package/dist/types.d.ts
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Общие типы letopis 1.0. Файл наполняется по этапам плана (reports/PLAN-LETOPIS-1.0.md).
|
|
3
3
|
*/
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Ревизия схемы, которую знает эта версия пакета, — номер версии SQL-части letopis (таблиц и функций в схеме установки).
|
|
6
|
+
* После `up()` у схемы та же ревизия (`r.revision`); схему отставшей ревизии `up()` обновляет только с `upgrade: true`,
|
|
7
|
+
* а `connect()` о ней предупреждает.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DDL_REVISION = 7;
|
|
6
10
|
/**
|
|
7
11
|
* Классы, строки которых меняют права и схему: их запись повышает счётчик прав (загрузчик), а сигнал
|
|
8
12
|
* сбрасывает весь кэш результатов и пропуска прав. Тот же список — в триггерах базы (60-write.sql).
|
|
9
13
|
*/
|
|
10
14
|
export declare const ACL_CLASS_NAMES: readonly string[];
|
|
11
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Имена методов цепочки: модификаторы, терминалы, глаголы записи и слоты концов, а также `then` и снятые методы прежних
|
|
17
|
+
* версий. После шага цепочки эти имена библиотека не ищет среди классов; все они входят в `RESERVED_CLASS_NAMES`.
|
|
18
|
+
*/
|
|
12
19
|
export declare const CHAIN_METHODS: readonly ["then", "entity", "paths", "rows", "first", "ids", "count", "limit", "offset", "sort", "asOf", "withDeleted", "deep", "exact", "sum", "avg", "min", "max", "countBy", "after", "versions", "create", "update", "upsert", "set", "unset", "add", "remove", "delete", "anonymize", "reclass", "restore", "purge", "alias", "tags", "owner", "forUpdate", "cache", "rekey", "run", "execute", "account", "diff", "blame"];
|
|
13
20
|
/** Свойства корня db (и транзакции db.begin()). */
|
|
14
21
|
export declare const DB_METHODS: readonly ["as", "begin", "commit", "rollback", "lock", "batch", "watch", "close", "registry", "sql", "load", "verify", "maintain", "reset", "describe", "auth", "acl", "idOf", "refresh", "transaction", "flushSignals", "schema", "token", "tenant", "reloadSchema", "accounts", "credentials", "resources", "rules", "compact", "trimHistory", "rekeyClass", "cache", "projector", "rebuildAggregates"];
|
|
15
22
|
/** Свойства батча db.batch(name). */
|
|
16
23
|
export declare const BATCH_METHODS: readonly ["discard", "size"];
|
|
17
24
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
25
|
+
* Имена методов цепочки, корня `db` и батча. Там, где имя занято методом, библиотека не ищет его среди классов, и шаг с
|
|
26
|
+
* таким именем до класса не дойдёт; класс-связь (`link`) с таким именем база не создаст (`invalid_class`). Не давайте
|
|
27
|
+
* классам эти имена.
|
|
21
28
|
*/
|
|
22
29
|
export declare const RESERVED_CLASS_NAMES: readonly string[];
|
|
23
30
|
/** Строка ответа: текущая версия (или версия журнала для asOf, versions, withDeleted). */
|
|
@@ -78,7 +85,7 @@ export type Filter = string | string[] | Op | {
|
|
|
78
85
|
} | {
|
|
79
86
|
[field: string]: FieldFilter | undefined;
|
|
80
87
|
};
|
|
81
|
-
/** Курсор
|
|
88
|
+
/** Курсор постраничного вывода для `after()`: значение поля сортировки и id последней строки страницы. */
|
|
82
89
|
export interface Cursor {
|
|
83
90
|
v: string | number | boolean | null;
|
|
84
91
|
id: string;
|
package/dist/types.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Общие типы letopis 1.0. Файл наполняется по этапам плана (reports/PLAN-LETOPIS-1.0.md).
|
|
3
3
|
*/
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Ревизия схемы, которую знает эта версия пакета, — номер версии SQL-части letopis (таблиц и функций в схеме установки).
|
|
6
|
+
* После `up()` у схемы та же ревизия (`r.revision`); схему отставшей ревизии `up()` обновляет только с `upgrade: true`,
|
|
7
|
+
* а `connect()` о ней предупреждает.
|
|
8
|
+
*/
|
|
9
|
+
export const DDL_REVISION = 7;
|
|
6
10
|
/**
|
|
7
11
|
* Классы, строки которых меняют права и схему: их запись повышает счётчик прав (загрузчик), а сигнал
|
|
8
12
|
* сбрасывает весь кэш результатов и пропуска прав. Тот же список — в триггерах базы (60-write.sql).
|
|
@@ -11,7 +15,10 @@ export const ACL_CLASS_NAMES = ['rule', 'Resource', 'member', 'Account', 'Class'
|
|
|
11
15
|
// ---------------------------------------------------------------------------
|
|
12
16
|
// Методы цепочки — единственный источник зарезервированных имён (план, §2.14, этап 3, п. 10)
|
|
13
17
|
// ---------------------------------------------------------------------------
|
|
14
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Имена методов цепочки: модификаторы, терминалы, глаголы записи и слоты концов, а также `then` и снятые методы прежних
|
|
20
|
+
* версий. После шага цепочки эти имена библиотека не ищет среди классов; все они входят в `RESERVED_CLASS_NAMES`.
|
|
21
|
+
*/
|
|
15
22
|
export const CHAIN_METHODS = [
|
|
16
23
|
'then', 'entity', 'paths', 'rows', 'first', 'ids', 'count', 'limit', 'offset', 'sort', 'asOf', 'withDeleted',
|
|
17
24
|
'deep', 'exact', 'sum', 'avg', 'min', 'max', 'countBy', 'after', 'versions', 'create', 'update', 'upsert', 'set',
|
|
@@ -28,9 +35,9 @@ export const DB_METHODS = [
|
|
|
28
35
|
/** Свойства батча db.batch(name). */
|
|
29
36
|
export const BATCH_METHODS = ['discard', 'size'];
|
|
30
37
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
38
|
+
* Имена методов цепочки, корня `db` и батча. Там, где имя занято методом, библиотека не ищет его среди классов, и шаг с
|
|
39
|
+
* таким именем до класса не дойдёт; класс-связь (`link`) с таким именем база не создаст (`invalid_class`). Не давайте
|
|
40
|
+
* классам эти имена.
|
|
34
41
|
*/
|
|
35
42
|
export const RESERVED_CLASS_NAMES = [...new Set([...CHAIN_METHODS, ...DB_METHODS, ...BATCH_METHODS])];
|
|
36
43
|
/** Метка операторов фильтра (символ не пересекается с данными). */
|
package/dist/up.d.ts
CHANGED
|
@@ -8,28 +8,36 @@ export interface InstallOptions {
|
|
|
8
8
|
schema: string;
|
|
9
9
|
owner?: string;
|
|
10
10
|
app?: string;
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Разрешить `db.reset()` и `maintain({ now })` — для тестовых установок и стендов; по умолчанию запрещено. Значение
|
|
13
|
+
* задаётся при установке и хранится в схеме: каждый `up()` записывает его заново (план, §2.2).
|
|
14
|
+
*/
|
|
12
15
|
allowReset?: boolean;
|
|
13
16
|
/**
|
|
14
|
-
*
|
|
15
|
-
* `{ all: '1 day', daily: '1 week', weekly: '1 month', monthly: '1 year', yearly: 'forever' }
|
|
16
|
-
*
|
|
17
|
+
* Политика хранения истории для классов без своей, например
|
|
18
|
+
* `{ all: '1 day', daily: '1 week', weekly: '1 month', monthly: '1 year', yearly: 'forever' }`; не задана — история
|
|
19
|
+
* хранится вся. Значение задаётся при установке и хранится в схеме: каждый `up()` записывает его заново (план, §2.11).
|
|
17
20
|
*/
|
|
18
21
|
history?: HistoryPolicy;
|
|
19
22
|
/** Номер последнего накатываемого файла — для пошаговых тестов. */
|
|
20
23
|
upTo?: number;
|
|
21
24
|
/** Сиды после ядра: имена lib/sql/seed.<имя>.sql (например 'booking') или пути к своим файлам .sql. */
|
|
22
25
|
seeds?: string[];
|
|
23
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Обновление (upgrade): ревизия схемы до наката — миграции lib/sql/migrate/ с номером выше неё. Если под блокировкой
|
|
28
|
+
* схемы видна более новая ревизия (её уже обновил одновременный up()), миграции считаются от неё.
|
|
29
|
+
*/
|
|
24
30
|
migrateFrom?: number;
|
|
31
|
+
/** Удалить схему и поставить заново (up({ fresh })) — под той же блокировкой схемы, что и накат. ДАННЫЕ ТЕРЯЮТСЯ. */
|
|
32
|
+
fresh?: boolean;
|
|
25
33
|
/** Каталог миграций (по умолчанию lib/sql/migrate). */
|
|
26
34
|
migrationsDir?: string;
|
|
27
35
|
/** Свой ключ сервиса: зарегистрировать, если такого ещё нет (вместо выпуска случайного). */
|
|
28
36
|
serviceKey?: string;
|
|
29
37
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* схеме:
|
|
38
|
+
* Что видно в сигналах базы (`NOTIFY`): `'class'` (у новой схемы по умолчанию) — имя класса; `'tenant'` — имя класса и
|
|
39
|
+
* псевдоним арендатора (токен); `'opaque'` — только псевдонимы класса и арендатора; `'none'` — сигналов нет.
|
|
40
|
+
* Режим хранится в схеме: `up()` без опции его не меняет, `reset({ all })` сохраняет (план 1.1, §2.2).
|
|
33
41
|
*/
|
|
34
42
|
signals?: SignalMode;
|
|
35
43
|
}
|
|
@@ -47,7 +55,11 @@ export interface InstallResult {
|
|
|
47
55
|
schema: string;
|
|
48
56
|
owner: string;
|
|
49
57
|
app: string;
|
|
50
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Ключ API сервисного аккаунта, выпущенный или зарегистрированный этим накатом, иначе `null`. Без опции `serviceKey`
|
|
60
|
+
* новый ключ выпускается на любом накате, где в схеме не осталось ни одного неотозванного ключа API, — не только при
|
|
61
|
+
* первой установке; свой `serviceKey` регистрируется и возвращается, если неотозванного ключа с таким значением ещё нет.
|
|
62
|
+
*/
|
|
51
63
|
serviceKey: string | null;
|
|
52
64
|
/** Применённые миграции. */
|
|
53
65
|
migrations: string[];
|
|
@@ -57,8 +69,27 @@ export interface InstallResult {
|
|
|
57
69
|
export declare const quoteIdent: (name: string) => string;
|
|
58
70
|
/** Файлы ядра по номеру: `10-core.sql` … `99-revision.sql`; сиды демо-домена сюда не входят. */
|
|
59
71
|
export declare function engineFiles(upTo?: number): Promise<string[]>;
|
|
72
|
+
/** Штамп движка: версия пакета и хэш файлов ядра (`99-revision.sql` пишет его в комментарий схемы). */
|
|
73
|
+
export interface EngineStamp {
|
|
74
|
+
version: string;
|
|
75
|
+
sql: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Штамп движка этого пакета. Хэш — по исходному тексту файлов ядра до подстановок (переводы строк — LF): одна и та же
|
|
79
|
+
* сборка даёт один штамп при любых опциях установки, а версия пакета без правок SQL штамп не меняет.
|
|
80
|
+
*/
|
|
81
|
+
export declare function engineStamp(): Promise<EngineStamp>;
|
|
82
|
+
/** Сравнение версий semver (метаданные сборки не учитываются): меньше нуля, ноль, больше нуля. */
|
|
83
|
+
export declare function compareVersions(a: string, b: string): number;
|
|
84
|
+
/**
|
|
85
|
+
* Штамп схемы (комментарий схемы) против файлов ядра пакета — текст предупреждения или null. Ревизия та же, а
|
|
86
|
+
* функции поставила другая версия движка: после обновления пакета не накатили up() (так было при 1.1 → 1.2).
|
|
87
|
+
*/
|
|
88
|
+
export declare function stampDrift(schema: string, comment: string): Promise<string | null>;
|
|
60
89
|
export declare function substitute(text: string, vars: Record<string, string>): string;
|
|
61
|
-
export declare function install(sql: postgres.Sql, opts: InstallOptions): Promise<InstallResult
|
|
90
|
+
export declare function install(sql: postgres.Sql, opts: InstallOptions): Promise<InstallResult & {
|
|
91
|
+
found: number | null;
|
|
92
|
+
}>;
|
|
62
93
|
/** Миграции с номером выше ревизии from и не выше DDL_REVISION: `0004-описание.sql`, по номеру. */
|
|
63
94
|
export declare function migrationFiles(dir: string, from: number): Promise<string[]>;
|
|
64
95
|
export interface UpOptions extends Omit<InstallOptions, 'schema' | 'upTo' | 'migrateFrom'> {
|
|
@@ -77,11 +108,16 @@ export interface UpOptions extends Omit<InstallOptions, 'schema' | 'upTo' | 'mig
|
|
|
77
108
|
/** Сколько ждать базу, мс (по умолчанию 60 000). */
|
|
78
109
|
waitTimeoutMs?: number;
|
|
79
110
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
111
|
+
* Запустить PGlite — PostgreSQL прямо в процессе Node — для разработки без своего сервера (решение 6 точки А);
|
|
112
|
+
* подключение к нему — `connect({ dsn: r.pglite.dsn, schema: r.schema, listen: false, max: 1, allowBypassRls: true })`.
|
|
113
|
+
* Соединение у PGlite одно, поэтому одновременные транзакции и гонки на нём не проверить: для таких тестов и в CI нужен
|
|
114
|
+
* настоящий PostgreSQL.
|
|
82
115
|
*/
|
|
83
116
|
pglite?: boolean | PgliteOptions;
|
|
84
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* Арендатор и его первый пользователь: после установки `up()` заводит их сам, как `createTenant()` с этими опциями, и
|
|
119
|
+
* кладёт итог в `r.tenant` — свой сид для этого не нужен.
|
|
120
|
+
*/
|
|
85
121
|
tenant?: TenantOptions;
|
|
86
122
|
}
|
|
87
123
|
export interface UpResult extends InstallResult {
|
|
@@ -117,14 +153,18 @@ export declare function ensureDatabase(dsn: string, log?: (m: string) => void):
|
|
|
117
153
|
*/
|
|
118
154
|
export declare function checkServer(versionNum: number, encoding: string): string[];
|
|
119
155
|
/** Ревизия движка схемы по комментарию 'letopis ddl_revision=N'; схемы нет — null. */
|
|
120
|
-
export declare function schemaRevision(sql: postgres.Sql, schema: string): Promise<number | null>;
|
|
156
|
+
export declare function schemaRevision(sql: Pick<postgres.Sql, 'unsafe'>, schema: string): Promise<number | null>;
|
|
121
157
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
158
|
+
* Ставит или обновляет установку letopis в схеме. Если схема уже есть и её ревизия та же, что у пакета, `up()` выполняет
|
|
159
|
+
* повторный накат: заново ставит функции, не трогая данные, — поэтому его можно вызывать при каждом запуске приложения.
|
|
160
|
+
* Схему отставшей ревизии `up()` обновляет только с `upgrade: true`, а на схеме новее пакета отказывает.
|
|
124
161
|
*/
|
|
125
162
|
export declare function up(opts: UpOptions): Promise<UpResult>;
|
|
126
163
|
export interface TenantOptions {
|
|
127
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* Имя арендатора — его аккаунта в System. Из имени вычисляется id арендатора, поэтому одно имя — всегда один и тот же
|
|
166
|
+
* арендатор (так же его находит `letopis import --tenant`).
|
|
167
|
+
*/
|
|
128
168
|
name: string;
|
|
129
169
|
/** Правило арендатора «аутентифицированным можно всё» (READ, WRITE, DELETE; по умолчанию да). */
|
|
130
170
|
grantAll?: boolean;
|
|
@@ -133,6 +173,10 @@ export interface TenantOptions {
|
|
|
133
173
|
name: string;
|
|
134
174
|
login: string;
|
|
135
175
|
password: string;
|
|
176
|
+
/**
|
|
177
|
+
* Вид пароля (по умолчанию PASSWORD) — как у auth.setPassword: `^[A-Z][A-Z0-9_]{1,31}$`, не служебный вид (SESSION,
|
|
178
|
+
* APIKEY, KEYSECRET, OTP, TOTP, KEY, PROJECTOR, LOCK); иначе invalid_data.
|
|
179
|
+
*/
|
|
136
180
|
kind?: string;
|
|
137
181
|
ttl?: string;
|
|
138
182
|
/** Роли членства (по умолчанию ['owner']); роли уже существующего членства повтор не меняет. */
|
|
@@ -150,14 +194,10 @@ export interface TenantResult {
|
|
|
150
194
|
created: boolean;
|
|
151
195
|
}
|
|
152
196
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* сессия выдаётся заново. Удалённые арендатор, аккаунт пользователя или членство (строки нет, а
|
|
158
|
-
* журнал id есть) — отказ invalid_data, транзакция откатывается целиком: повтор не воскрешает то,
|
|
159
|
-
* что удалил администратор (up({ tenant }) идёт при каждом запуске), а sys_create пишет только
|
|
160
|
-
* версию 1 — её занимает история; вернуть строку — restore() цепочкой.
|
|
197
|
+
* Заводит арендатора и, по желанию, его первого пользователя (аккаунт, членство, пароль, сессию) одной транзакцией от
|
|
198
|
+
* роли-владельца схемы — поэтому нужен администраторский пул. Повтор с тем же именем и логином ничего не дублирует и не
|
|
199
|
+
* меняет, только выдаёт пользователю новую сессию; одновременные вызовы заводят арендатора один раз. Если арендатор,
|
|
200
|
+
* пользователь или членство были удалены, повтор их не воскрешает — отказ `invalid_data`.
|
|
161
201
|
*/
|
|
162
202
|
export declare function createTenant(sql: postgres.Sql, schema: string, opts: TenantOptions, owner?: string): Promise<TenantResult>;
|
|
163
203
|
export {};
|