letopis 0.13.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 +98 -0
- package/README.md +362 -199
- package/dist/chain.d.ts +44 -16
- package/dist/chain.js +197 -26
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/schema.js +96 -4
- package/dist/sql.d.ts +23 -3
- package/dist/sql.js +71 -24
- package/dist/types.d.ts +40 -4
- package/dist/uuid.d.ts +6 -0
- package/dist/uuid.js +32 -0
- package/dist/write.d.ts +12 -5
- package/dist/write.js +213 -95
- package/package.json +1 -1
- package/sql/ddl.sql +53 -11
- package/sql/seed.booking.sql +21 -16
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,104 @@
|
|
|
2
2
|
|
|
3
3
|
Формат: [Keep a Changelog](https://keepachangelog.com/), версии — semver.
|
|
4
4
|
|
|
5
|
+
## [0.16.0] — 2026-07-12
|
|
6
|
+
|
|
7
|
+
### Changed — BREAKING: глаголы записи create/update, слот unset, id считает Schema
|
|
8
|
+
|
|
9
|
+
- **`set()` разбит на `create()` / `update()`** — мина «`Класс()` → INSERT,
|
|
10
|
+
`Класс({})` → UPDATE всех» мертва, намерение всегда явное:
|
|
11
|
+
- **`create(data?)`** — INSERT; известный id (шаг `Класс(id)`, `data.id` или
|
|
12
|
+
вычисленный v5) уже существует → новая версия (идемпотентный create,
|
|
13
|
+
REST-PUT семантика). Фильтр-объект перед create — ошибка ПОСТРОЕНИЯ
|
|
14
|
+
(`create() takes no filter`); create на pivot-шаге — ошибка.
|
|
15
|
+
- **`update(data?)`** — новая версия КАЖДОГО найденного путём;
|
|
16
|
+
`Класс()` ≡ `Класс({})` — «все в границах контекста»; не найдено → `[]`,
|
|
17
|
+
update НИКОГДА не создаёт.
|
|
18
|
+
- `set()` бросает подсказку `set() split into create()/update() (0.16.0)`.
|
|
19
|
+
- **Слот-снятие переименовано: `.Класс.delete()` → `.Класс.unset()`** — развели
|
|
20
|
+
«удалить сущность» (`delete()`) и «снять конец связи» (`unset()`); старое имя
|
|
21
|
+
бросает подсказку. Слот теперь требует глагол записи ПЕРЕД собой:
|
|
22
|
+
`…create(…).Класс.set(x)` / `…update(…).Класс.unset()`; слот без операции —
|
|
23
|
+
ошибка `link slot needs a write` (раньше слот молча создавал `set({})`).
|
|
24
|
+
- **Генерация id по Schema** — `attributes.id`:
|
|
25
|
+
- `"uuid"` / `{type:'uuid'}` → **v4** (random, как раньше — дефолт);
|
|
26
|
+
- `{type:'uuid', generate: 7}` → **v7** (unix-время в старших битах — вставки
|
|
27
|
+
ложатся в хвост btree-индекса);
|
|
28
|
+
- `{type:'uuid', generate: 5, from:[…]}` → **v5, детерминированный**:
|
|
29
|
+
`uuidv5("pgSchema:partition:класс:значения from")`; `from` — имена
|
|
30
|
+
ОБЯЗАТЕЛЬНЫХ концов `Schema.links` (класс или полное имя союза
|
|
31
|
+
`'Service|Complex'`; значение — id конца) и/или скалярных полей `data`.
|
|
32
|
+
Явный id у v5-класса запрещён (`computes id`). Свойства: **create
|
|
33
|
+
идемпотентен** (та же комбинация → та же сущность, дубль невозможен даже в
|
|
34
|
+
гонке — двойная бронь мертва на уровне схемы) и **id известен ДО создания**
|
|
35
|
+
(формула открыта; namespace letopis `c7a2f9d4-3b61-4e8a-9f05-8d2c1e6b7a90`).
|
|
36
|
+
- Батч: multi-VALUES-склейка для v5-классов отключена (id нужны концы) —
|
|
37
|
+
такие планы исполняются поштучно, семантика та же.
|
|
38
|
+
- **Наследование attributes по иерархии Schema**: при загрузке реестра attributes
|
|
39
|
+
класса собираются по цепочке `ancestor` — потомок ПОВЕРХ предка, переопределение
|
|
40
|
+
поля = замена правила целиком (не слияние). Правило `id` (генерация) наследуется
|
|
41
|
+
так же; `links` НЕ наследуются (концы объявляются каждым классом). Валидатор и
|
|
42
|
+
fieldTypes компилируются из слитых attributes.
|
|
43
|
+
- **Демо-схема booking целиком на generate** — с наследованием: `Entity` и `link`
|
|
44
|
+
объявляют дефолт `{generate: 7}`, v7-классы (Org/Staff/Folder/Customer/Schedule/
|
|
45
|
+
Booking/item) наследуют его без собственного правила; v5-классы переопределяют:
|
|
46
|
+
`busy ← v5(Slot, Staff)`; `skill ← v5(Staff, Service|Complex)`;
|
|
47
|
+
`shift ← v5(Schedule, Staff)`; `compo ← v5(Complex, Service)`;
|
|
48
|
+
`Slot ← v5(Schedule, data.start)`; `Service`/`Complex` ← `v5(Org, data.name)`
|
|
49
|
+
(имя уникально в организации). Полигоны `v1.salondemo`/`v1.article` обновлены
|
|
50
|
+
на месте (UPDATE Schema; данные нетронуты).
|
|
51
|
+
- Тесты мигрированы (все `set`→`create`/`update`, слот `.delete`→`.unset`,
|
|
52
|
+
фикс-id v5-классов → вычисляемые); новый **`test/idgen.test.ts`** — генерация
|
|
53
|
+
id на боевых классах Schema (v4/v7/v5 из поля и концов, гонка без локов,
|
|
54
|
+
наследование attributes/id-правила, схема-гарды). SALON.md и демо-полигон
|
|
55
|
+
перегнаны на 0.16.0. Итого **165 тестов**.
|
|
56
|
+
|
|
57
|
+
## [0.15.0] — 2026-07-12
|
|
58
|
+
|
|
59
|
+
### Changed — BREAKING: единый закон пути, слоты связей, pivot, entity()
|
|
60
|
+
- **Один закон навигации для чтения И записи**: цепочка всегда подчиняется переходам
|
|
61
|
+
`Schema.links`; недопустимый переход — ошибка СИНХРОННО при построении (не в терминале).
|
|
62
|
+
Мультиродительский «контекст-сбор» через невалидные HUB→HUB прыжки удалён.
|
|
63
|
+
- **Слоты связей** вместо `.link()`: конец связки задаётся `.Класс.set(target)` ПОСЛЕ
|
|
64
|
+
`.set(данные)` — свойство-класс БЕЗ вызова. Владелец создаваемой связки — из валидного
|
|
65
|
+
пути, прочие концы — слотами. `target` = id | Row | **вложенная цепочка** (исполняется в
|
|
66
|
+
той же транзакции, обязана дать ровно одну сущность класса конца — «создать И привязать»).
|
|
67
|
+
`.Класс.delete()` снимает optional-конец; союз-конец `[A|B]` замещается слотом целиком.
|
|
68
|
+
**`.link()` УДАЛЁН** (бросает подсказку).
|
|
69
|
+
- **pivot**: повтор LINK-класса в пути — возврат к тому же узлу (ветвление к другому концу
|
|
70
|
+
+ дофильтровка AND). `db.Запись(з).позиция().Услуга(у).позиция().Сотрудник(вася)` —
|
|
71
|
+
«позиции записи з с услугой у у мастера вася» одной цепочкой.
|
|
72
|
+
- **`entity(x)`** (Chain и db): вставить узел-переменную/паттерн (`db.позиция()`) или Row в
|
|
73
|
+
путь; та же переменная повторно — явный pivot; `db.entity(row).…` — старт с готовой строки.
|
|
74
|
+
- Тесты мигрированы на слоты; **`test/salon.test.ts`** — тест-план «работа салона»
|
|
75
|
+
(21 акт), покрывающий ВСЕ 145 публичных точек API + матрица покрытия. Итого 153 теста.
|
|
76
|
+
|
|
77
|
+
## [0.14.0] — 2026-07-12
|
|
78
|
+
|
|
79
|
+
### Changed — Schema.links v2: концы связей объектами
|
|
80
|
+
- **Конец связи — объект**: `{"class":"Org","cardinality":1}` /
|
|
81
|
+
`{"classes":["Service","Complex"],"cardinality":1}` (союз ролей) /
|
|
82
|
+
`{"class":"Staff","optional":true,…}`. `'Entity'`-полиморф в новых схемах не
|
|
83
|
+
используется — классы концов называются явно. **Колонка `Schema.links` — `jsonb`**
|
|
84
|
+
(настоящий массив объектов; в новых схемах). Старые схемы с `text[]` читаются тем же
|
|
85
|
+
кодом по прежним правилам (legacy-строки `'Org'`, `'Entity'`-полиморф).
|
|
86
|
+
- **Валидация строгая на двух уровнях** (либа `write.ts` + БД-триггер
|
|
87
|
+
`entity_check`): жадный матчинг ключей `Entity.links` по порядку объявления
|
|
88
|
+
концов; обязательный конец без ключа → `requires end "Service|Complex"`;
|
|
89
|
+
связь вне концов → `has stray link(s)` (раньше лишние молчали). Голый SQL
|
|
90
|
+
мимо либы ловится триггером так же.
|
|
91
|
+
- **Демо-домен уточнён**: `позиция = [Запись, {Услуга|Комплекс}, Сотрудник?]` —
|
|
92
|
+
три конца, владелец строго Запись; состав комплекса — новый LINK-класс
|
|
93
|
+
**`compo`/«состав» = [Комплекс, Услуга]** (раньше ездил на позиции);
|
|
94
|
+
`навык = [Сотрудник, {Услуга|Комплекс}]`; `занятость = [Сотрудник, Окно, Запись?]`
|
|
95
|
+
(третий конец легализован — раньше жил контрабандой); `Запись = [Клиент?]`
|
|
96
|
+
(ручная бронь без клиента). `cardinality` — зарезервировано, пока не проверяется.
|
|
97
|
+
- Полигон `v1.article` мигрирован НА МЕСТЕ (ALTER links → jsonb + apply поверх):
|
|
98
|
+
данные Entity нетронуты (1 112 952), схема идентична booking.
|
|
99
|
+
- `lib/scripts/gen-seed.mjs` — сид Schema теперь реально генерится из
|
|
100
|
+
`schema.booking.v2.json` (комментарий «файл сгенерирован» стал правдой);
|
|
101
|
+
`schema-sync` сравнивает концы канонически (объект ⇔ JSON-текст в text[]).
|
|
102
|
+
|
|
5
103
|
## [0.13.0] — 2026-07-11
|
|
6
104
|
|
|
7
105
|
### Added — `up()`: одна точка входа
|