letopis 0.5.0 → 0.16.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/CHANGELOG.md +269 -0
- package/README.md +2472 -240
- package/dist/acl.d.ts +48 -0
- package/dist/acl.js +208 -0
- package/dist/auth.d.ts +116 -0
- package/dist/auth.js +263 -0
- package/dist/chain.d.ts +81 -28
- package/dist/chain.js +312 -72
- package/dist/index.d.ts +10 -3
- package/dist/index.js +26 -3
- package/dist/schema.js +107 -4
- package/dist/sessions.d.ts +32 -0
- package/dist/sessions.js +48 -0
- package/dist/sql.d.ts +43 -1
- package/dist/sql.js +238 -79
- package/dist/tx.d.ts +1 -1
- package/dist/tx.js +16 -1
- package/dist/types.d.ts +81 -2
- package/dist/up.d.ts +48 -0
- package/dist/up.js +209 -0
- package/dist/uuid.d.ts +6 -0
- package/dist/uuid.js +32 -0
- package/dist/write.d.ts +29 -16
- package/dist/write.js +427 -98
- package/docker/Dockerfile +17 -0
- package/docker/start.sh +4 -0
- package/package.json +16 -2
- package/sql/ddl.sql +404 -0
- package/sql/seed.auth.sql +46 -0
- package/sql/seed.booking.sql +69 -0
package/dist/chain.d.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dot-цепочки: db.Сотрудник({name:'Вася'}).навык().Услуга().
|
|
2
|
+
* Dot-цепочки: db.Сотрудник({name:'Вася'}).навык().Услуга().run()
|
|
3
3
|
* db и цепочка — Proxy над реестром классов (id и alias работают одинаково).
|
|
4
4
|
*
|
|
5
5
|
* Выборка настраивается модификаторами: .limit(n) .offset(n) .sort(field, dir?)
|
|
6
6
|
* Колонки — модификаторами: .tags(…) .account(…) .owner(…); ключ путей — .alias(…).
|
|
7
|
-
* Запись: .
|
|
7
|
+
* Запись: .create(data) / .update(data) / .delete({confirm}) / .anonymize(fields) — ЗВЕНЬЯ
|
|
8
|
+
* (возвращают цепочку, продолжение — от результата); исполняет ТЕРМИНАЛ, весь план
|
|
9
|
+
* одной транзакцией.
|
|
8
10
|
*/
|
|
9
11
|
import type { Row, Path, Filter } from './types.js';
|
|
10
12
|
import { type Ctx } from './sql.js';
|
|
11
|
-
import { type
|
|
13
|
+
import { type BatchPlan } from './write.js';
|
|
12
14
|
import { type Tables } from './tables.js';
|
|
15
|
+
import { type AuthApi } from './auth.js';
|
|
16
|
+
import { type AclApi } from './acl.js';
|
|
13
17
|
import type { Registry } from './schema.js';
|
|
14
18
|
export interface ChainCore {
|
|
15
|
-
/** Пути: [{шаг1: Row, шаг2: Row, …}, …] — все узлы каждого
|
|
16
|
-
|
|
19
|
+
/** Пути: [{шаг1: Row, шаг2: Row, …}, …] — все узлы каждого варианта (бывший execute). */
|
|
20
|
+
run(): Promise<Path[]>;
|
|
17
21
|
/** Уникальные сущности последнего шага. */
|
|
18
22
|
rows(): Promise<Row[]>;
|
|
19
23
|
first(): Promise<Row | null>;
|
|
@@ -39,53 +43,88 @@ export interface ChainCore {
|
|
|
39
43
|
min(field: string): Promise<unknown>;
|
|
40
44
|
max(field: string): Promise<unknown>;
|
|
41
45
|
countBy(field: string): Promise<Record<string, number>>;
|
|
42
|
-
/**
|
|
43
|
-
|
|
46
|
+
/**
|
|
47
|
+
* GDPR-звено: новая версия с затёртыми string-полями ('[erased]') + тег 'anonymized'.
|
|
48
|
+
* История остаётся. Возвращает цепочку — исполняет терминал; продолжение — от затёртых версий.
|
|
49
|
+
*/
|
|
50
|
+
anonymize(fields: string[]): Chain;
|
|
44
51
|
/** Переименовать ключ ТЕКУЩЕГО шага в выводе путей. */
|
|
45
52
|
alias(name: string): Chain;
|
|
46
|
-
/** Колонка tags: строка | string[] (все) | has/hasAny/hasAll. В
|
|
53
|
+
/** Колонка tags: строка | string[] (все) | has/hasAny/hasAll. В записи — значение тегов. */
|
|
47
54
|
tags(v: string | string[] | object): Chain;
|
|
48
|
-
/** Колонка account (uuid или Row/Account). В
|
|
55
|
+
/** Колонка account (uuid или Row/Account). В create() — значение. */
|
|
49
56
|
account(v: string | {
|
|
50
57
|
id: string;
|
|
51
58
|
}): Chain;
|
|
52
|
-
/** Колонка owner (uuid или Row/Account). В
|
|
59
|
+
/** Колонка owner (uuid или Row/Account). В create() — значение. */
|
|
53
60
|
owner(v: string | {
|
|
54
61
|
id: string;
|
|
55
62
|
}): Chain;
|
|
56
63
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
* Вставить узел в путь: x — ленивая цепочка-паттерн (стык проверяется правилами
|
|
65
|
+
* переходов) либо Row (шаг его класса по id). ТА ЖЕ переменная-цепочка повторно
|
|
66
|
+
* в одном пути — возврат к её узлу (ветвление); разные переменные — разные узлы.
|
|
67
|
+
*/
|
|
68
|
+
entity(x: Chain | Row): Chain;
|
|
69
|
+
/**
|
|
70
|
+
* Создать сущность (ЗВЕНО — вернёт цепочку, исполняет терминал):
|
|
71
|
+
* await db.Организация(org).Сотрудник().create({ name: 'Вася' }).rows()
|
|
72
|
+
* Связи — контекст-шагами до create() + слотами .Класс.set(…) после. id — по Schema
|
|
73
|
+
* (attributes.id: v4 | v7 | v5-вычисляемый); известный id (Класс(id) / data.id / v5)
|
|
74
|
+
* уже существует → новая версия (идемпотентно). Фильтр-объект — ошибка: это update().
|
|
63
75
|
*/
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
|
|
76
|
+
create(data?: Record<string, unknown>): Chain;
|
|
77
|
+
/**
|
|
78
|
+
* Новая версия КАЖДОГО найденного путём (deep-merge листьев data):
|
|
79
|
+
* await db.Запись(з).позиция({ qty: 1 }).update({ qty: 2 }).rows()
|
|
80
|
+
* Класс() ≡ Класс({}) — все в границах контекста. Не найдено → [] (НИКОГДА не создаёт).
|
|
81
|
+
* Продолжение цепочки — от записанных строк (fan-out при множестве).
|
|
82
|
+
*/
|
|
83
|
+
update(data?: Record<string, unknown>): Chain;
|
|
84
|
+
/**
|
|
85
|
+
* Удаление-звено. { confirm: true } — серверный tombstone + каскад (продолжение — от
|
|
86
|
+
* затомбстоуненных, $deleted: true); БЕЗ confirm — превью: терминал вернёт кандидатов
|
|
87
|
+
* (цели + каскад), БД не тронута.
|
|
88
|
+
*/
|
|
89
|
+
delete(opts?: {
|
|
90
|
+
confirm?: boolean;
|
|
91
|
+
}): Chain;
|
|
67
92
|
}
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
-
|
|
93
|
+
/**
|
|
94
|
+
* Свойство-класс на цепочке:
|
|
95
|
+
* ВЫЗОВ `Класс(фильтр?)` — шаг-навигация; повтор LINK-класса в пути = возврат
|
|
96
|
+
* к его узлу (pivot: ветвление к другому концу, дофильтровка AND);
|
|
97
|
+
* СЛОТ `Класс` без скобок — конец links записываемой версии:
|
|
98
|
+
* .set(target) — установить конец (id | Row | вложенная цепочка: та же транзакция,
|
|
99
|
+
* ровно одна сущность класса конца); союз-конец замещается целиком;
|
|
100
|
+
* .unset() — снять optional-конец.
|
|
101
|
+
* Слот валиден только для конца из Schema.links владельца и ТОЛЬКО после операции
|
|
102
|
+
* записи: …create(…).Класс.set(x) / …update(…).Класс.unset() — та же версия строки.
|
|
103
|
+
*/
|
|
104
|
+
export type StepProp = ((filter?: Filter) => Chain) & {
|
|
105
|
+
set(target: string | {
|
|
71
106
|
id: string;
|
|
72
|
-
})
|
|
107
|
+
} | Chain): Chain;
|
|
108
|
+
unset(): Chain;
|
|
73
109
|
};
|
|
74
110
|
export type Chain = ChainCore & {
|
|
75
|
-
[className: string]:
|
|
111
|
+
[className: string]: StepProp;
|
|
76
112
|
};
|
|
77
113
|
export interface DbCore {
|
|
78
114
|
/** Открыть транзакцию: tr — тот же API + commit/rollback/lock. */
|
|
79
115
|
begin(): Promise<EntityTx>;
|
|
80
116
|
commit(tr: EntityTx): Promise<void>;
|
|
81
117
|
rollback(tr: EntityTx): Promise<void>;
|
|
82
|
-
/** Именованный батч: те же цепочки,
|
|
118
|
+
/** Именованный батч: те же цепочки, планы записи копятся до run(). */
|
|
83
119
|
batch(name: string): Batch;
|
|
84
120
|
/**
|
|
85
121
|
* Realtime: события каждой вставленной версии (insert/update/delete-tombstone).
|
|
86
122
|
* watch(cb) — все классы; watch('Запись', cb) — один. Возврат — stop-функция.
|
|
123
|
+
* LISTEN-соединение переживает обрывы (re-listen автоматом), но NOTIFY за время
|
|
124
|
+
* разрыва потеряны — opts.onReconnect зовётся после восстановления: дочитайте пропущенное.
|
|
87
125
|
*/
|
|
88
|
-
watch(
|
|
126
|
+
watch(cb: (e: WatchEvent) => void, opts?: WatchOpts): Promise<() => void>;
|
|
127
|
+
watch(cls: string, cb: (e: WatchEvent) => void, opts?: WatchOpts): Promise<() => void>;
|
|
89
128
|
close(): Promise<void>;
|
|
90
129
|
registry: Registry;
|
|
91
130
|
/** Голый postgres-клиент (тесты, EXPLAIN). */
|
|
@@ -95,6 +134,12 @@ export interface DbCore {
|
|
|
95
134
|
credentials: Tables['credentials'];
|
|
96
135
|
resources: Tables['resources'];
|
|
97
136
|
rules: Tables['rules'];
|
|
137
|
+
/** Вход по кредам (пароль/api-key/key-secret/внешние identity) + сессии в Redis. */
|
|
138
|
+
auth: AuthApi;
|
|
139
|
+
/** ACL по Resource/Rule: check(эндпоинт) / checkData(класс, READ|WRITE|DELETE) / reload. */
|
|
140
|
+
acl: AclApi;
|
|
141
|
+
/** Начать путь с готового узла/паттерна: db.entity(pos).… (pos — ленивая цепочка или Row). */
|
|
142
|
+
entity(x: Chain | Row): Chain;
|
|
98
143
|
}
|
|
99
144
|
export type EntityDb = DbCore & {
|
|
100
145
|
[className: string]: (filter?: Filter) => Chain;
|
|
@@ -112,15 +157,23 @@ export interface WatchEvent {
|
|
|
112
157
|
updated: string;
|
|
113
158
|
deleted: boolean;
|
|
114
159
|
}
|
|
160
|
+
/** Опции watch(): реакция на восстановление LISTEN-соединения. */
|
|
161
|
+
export interface WatchOpts {
|
|
162
|
+
/** Зовётся после каждого re-listen (не на первом подключении): NOTIFY за разрыв потеряны. */
|
|
163
|
+
onReconnect?: () => void;
|
|
164
|
+
}
|
|
115
165
|
export type Batch = {
|
|
116
|
-
execute
|
|
166
|
+
/** Исполнить всю очередь планов одной транзакцией (бывший execute). */
|
|
167
|
+
run(): Promise<Row[][]>;
|
|
117
168
|
discard(): void;
|
|
118
169
|
size(): number;
|
|
119
170
|
} & {
|
|
120
171
|
[className: string]: (filter?: Filter) => Chain;
|
|
121
172
|
};
|
|
122
173
|
interface RootState {
|
|
123
|
-
batches: Map<string,
|
|
174
|
+
batches: Map<string, BatchPlan[]>;
|
|
124
175
|
}
|
|
176
|
+
/** Внутренний канал: план чужой ленивой цепочки (слот-значения, entity()). */
|
|
177
|
+
export declare const PLAN: unique symbol;
|
|
125
178
|
export declare function makeDb(ctx: Ctx, root?: RootState): EntityDb;
|
|
126
179
|
export {};
|